48 lines
1.3 KiB
OCaml
48 lines
1.3 KiB
OCaml
let load_file fname =
|
|
match In_channel.with_open_text fname In_channel.input_line with
|
|
| Some x -> x
|
|
| None -> failwith "load_file"
|
|
|
|
let log10i i =
|
|
let rec impl acc = function 0 -> acc | x -> impl (acc + 1) (x / 10) in
|
|
assert (i > 0);
|
|
impl ~-1 i
|
|
|
|
let digits10 i = 1 + log10i i
|
|
|
|
(** [pow10 n] returns [10] raised to the [n]th power. [n] must be non-negative.
|
|
*)
|
|
let pow10 n =
|
|
let rec impl acc = function 0 -> acc | x -> impl (acc * 10) (x - 1) in
|
|
assert (n >= 0);
|
|
impl 1 n
|
|
|
|
let rec apply_n n fn arg = if n <= 0 then arg else apply_n (n - 1) fn (fn arg)
|
|
|
|
(*
|
|
let print_int_list lst =
|
|
List.iter
|
|
(fun i ->
|
|
print_int i;
|
|
print_char ' ')
|
|
lst;
|
|
print_newline ();
|
|
()
|
|
*)
|
|
let calc n input =
|
|
let rec step_rec acc = function
|
|
| [] -> acc
|
|
| 0 :: t -> step_rec (1 :: acc) t
|
|
| x :: t when digits10 x mod 2 = 0 ->
|
|
let pow = pow10 (digits10 x / 2) in
|
|
let left = x / pow in
|
|
let right = x mod pow in
|
|
step_rec (right :: left :: acc) t
|
|
| x :: t -> step_rec ((x * 2024) :: acc) t
|
|
in
|
|
apply_n n (step_rec []) input
|
|
|
|
let part1 str = Aoc.ints_of_string str |> calc 25 |> List.length
|
|
let part2 str = Aoc.ints_of_string str |> calc 75 |> List.length
|
|
let _ = Aoc.main load_file [ (string_of_int, part1); (string_of_int, part2) ]
|