Advent of Code 2020
https://adventofcode.com/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('') and can be up to 35 characters long.
90 lines
2.3 KiB
90 lines
2.3 KiB
(* Common util. Should probably put this in a module or something.. *)


let get_one_line file =


try Some (input_line file) with


End_of_file > None




let get_lines file =


let rec input lines =


match get_one_line file with


Some line > input (line :: lines)


 None > List.rev lines


in input []




let read_file file =


let channel = open_in(file) in


get_lines channel




let explode s = (* convert a string to a list of chars *)


let rec exp i l =


if i < 0 then l else exp (i  1) (s.[i] :: l) in


exp (String.length s  1) []




let (<<) f g x = f(g(x))


let (>>) f g x = g(f(x))




let rec take n l = (* take the first n elements *)


match n with


 0 > []


 n >


match l with


 [] > []


 x :: xs > x :: (take (n1) xs)




let rec drop n l = (* drop the first n elemnts *)


match n with


 0 > l


 n > drop (n1) @@ List.tl l




let c2i = String.make 1 >> int_of_string




(*  *)




type exp = Add of exp * exp  Mul of exp * exp  Num of int




let rec string_of_exp = function


 Num x > string_of_int x


 Mul (a, b) > Printf.sprintf "(%s * %s)" (string_of_exp a) (string_of_exp b)


 Add (a, b) > Printf.sprintf "(%s + %s)" (string_of_exp a) (string_of_exp b)




let print_exp = print_string << string_of_exp


let print_exps = List.iter print_exp




let rec find_matching_paren count (x::xs) =


match x with


 '(' > if count = 0 then 0 else 1 + find_matching_paren (count1) xs


 ')' > 1 + find_matching_paren (count+1) xs


 n > 1 + find_matching_paren count xs




let read_exp line =


let line' = line


> explode


> List.filter (fun x > x != ' ')


> List.rev


in




let rec go stack = function


 [] > List.hd stack


 '+' :: xs > Add (List.hd stack, (go (List.tl stack) xs))


 '*' :: xs > Mul (List.hd stack, (go (List.tl stack) xs))


 ')' :: xs >


let matching = 1 + find_matching_paren 0 xs in


let sub = take matching xs in


let rest = drop matching xs in


go ((go [] sub)::stack) rest


 '(' :: xs > List.hd stack


 num :: xs > go ((Num (c2i num)) :: stack) xs


in




go [] line'




let rec eval = function


 Num a > a


 Add (a, b) > (eval a) + (eval b)


 Mul (a, b) > (eval a) * (eval b)




let () =


let exps = read_file "day18.txt" > List.map read_exp in




let values = List.map eval exps in


let sum = List.fold_left (+) 0 values in


print_int sum;
