You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
1.7 KiB
OCaml
74 lines
1.7 KiB
OCaml
(* 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 (>>) f g x = g(f(x))
|
|
|
|
let list_max l = List.fold_left (fun acc x -> if x > acc then x else acc) (List.hd l) l
|
|
|
|
let map_tuple f (a, b) = (f a, f b)
|
|
|
|
let memo_rec f =
|
|
let h = Hashtbl.create 1000 in
|
|
let rec g x =
|
|
try Hashtbl.find h x
|
|
with Not_found ->
|
|
let y = f g x in
|
|
Hashtbl.add h x y;
|
|
y
|
|
in g
|
|
|
|
(* --- *)
|
|
|
|
let rec collect_diffs = function
|
|
| x :: y :: [] -> [y - x] (* 2 elemnts left *)
|
|
| x :: y :: z -> y - x :: collect_diffs (y :: z)
|
|
|
|
let count_steps = (* returns a tuple of counts of 1's and 3's *)
|
|
List.partition (Int.equal 1)
|
|
>> map_tuple List.length
|
|
|
|
let count_valid self = function
|
|
| x :: y :: [] -> if y - x < 4 then 1 else 0
|
|
| x :: y :: rest ->
|
|
if y - x > 3
|
|
then 0
|
|
else self (x :: rest) + self (y :: rest)
|
|
|
|
let count_valid_memo = memo_rec count_valid
|
|
|
|
let () =
|
|
let lines = read_file "day10.txt"
|
|
|> List.map int_of_string
|
|
in
|
|
|
|
let adapter_jolts = 3 + list_max lines in
|
|
|
|
let sorted = lines
|
|
|> List.cons adapter_jolts (* add our adapter *)
|
|
|> List.cons 0 (* add the outlet *)
|
|
|> List.sort (fun x y -> if x > y then 1 else if x < y then -1 else 0)
|
|
in
|
|
|
|
sorted
|
|
|> collect_diffs
|
|
|> count_steps
|
|
|> fun (x, y) -> x * y
|
|
|> Printf.printf "prod: %i\n";
|
|
|
|
sorted
|
|
|> count_valid_memo
|
|
|> Printf.printf "\nsum: %i\n"
|