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