71 lines
2.3 KiB
OCaml
71 lines
2.3 KiB
OCaml
open Printf;;
|
|
|
|
let rec list_of_lines in_file =
|
|
try
|
|
let line = input_line in_file in
|
|
line :: list_of_lines(in_file)
|
|
with End_of_file ->
|
|
close_in in_file;
|
|
[]
|
|
|
|
let mix_and_prune x y =
|
|
Int.logand (Int.logxor x y) 0xffffff
|
|
|
|
let next_in_sequence x =
|
|
let x1 = mix_and_prune x (Int.shift_left x 6) in
|
|
let x2 = mix_and_prune x1 (Int.shift_right x1 5) in
|
|
mix_and_prune x2 (Int.shift_left x2 11)
|
|
|
|
let rec skip_sequence times x =
|
|
if times = 0 then
|
|
x
|
|
else skip_sequence (times - 1) (next_in_sequence x)
|
|
|
|
let make_indexing_array () =
|
|
Array.make 130321 0
|
|
|
|
let get_sequence_index (x1, x2, x3, x4) =
|
|
(x1 + 9) + (x2 + 9) * 19 + (x3 + 9) * 361 + (x4 + 9) * 6859
|
|
|
|
let mod10_diff x1 x2 =
|
|
(x1 mod 10) - (x2 mod 10)
|
|
|
|
module IntSet = Set.Make(Int)
|
|
|
|
let rec index_monkey_inner indexing_array already_occured_set current sequence seq_length =
|
|
if seq_length > 0 then
|
|
let index = get_sequence_index sequence in
|
|
let new_set = if IntSet.find_opt index already_occured_set |> Option.is_none then begin
|
|
indexing_array.(index) <- indexing_array.(index) + (current mod 10);
|
|
IntSet.add index already_occured_set
|
|
end else
|
|
already_occured_set in
|
|
let new_value = next_in_sequence current in
|
|
let diff = mod10_diff new_value current in
|
|
let (d1, d2, d3, _) = sequence in
|
|
index_monkey_inner indexing_array new_set new_value (diff, d1, d2, d3) (seq_length - 1)
|
|
|
|
let index_monkey indexing_array seq_length seed =
|
|
let s4 = next_in_sequence seed in
|
|
let s3 = next_in_sequence s4 in
|
|
let s2 = next_in_sequence s3 in
|
|
let s1 = next_in_sequence s2 in
|
|
let d1 = mod10_diff s1 s2 in
|
|
let d2 = mod10_diff s2 s3 in
|
|
let d3 = mod10_diff s3 s4 in
|
|
let d4 = mod10_diff s1 seed in
|
|
index_monkey_inner indexing_array IntSet.empty s1 (d1, d2, d3, d4) (seq_length - 4)
|
|
|
|
let decode_index index =
|
|
(index mod 19 - 9, (index / 19) mod 19 - 9, (index / 361) mod 19 - 9, (index / 6859) mod 19 - 9)
|
|
|
|
let () =
|
|
let f = open_in "input.txt" in
|
|
let monkey_seeds = list_of_lines f |> List.map int_of_string in
|
|
let result = monkey_seeds
|
|
|> List.map (skip_sequence 2000)
|
|
|> List.fold_left Int.add 0 in
|
|
let indexing_array = make_indexing_array () in
|
|
List.iter (index_monkey indexing_array 2000) monkey_seeds;
|
|
let result2 = Array.fold_left Int.max 0 indexing_array in
|
|
printf "%d\n%d\n" result result2 |