#!nix-shell --pure -i ocaml -p ocaml
*)
let rec read_input acc =
try
read_input
( (read_line () |> String.split_on_char ' ' |> List.map int_of_string)
:: acc )
with End_of_file -> acc
let rec is_ordered = function
| [], _ | [_], _ ->
true
| x :: y :: rest, None ->
is_ordered (y :: rest, Some (x > y))
| x :: y :: rest, Some gt ->
if (gt && x > y) || ((not gt) && x < y) then
is_ordered (y :: rest, Some gt)
else false
let rec adjacent_within_bounds = function
| [] | [_] ->
true
| x :: y :: rest ->
let diff = Int.abs (y - x) in
if diff >= 1 && diff <= 3 then adjacent_within_bounds (y :: rest)
else false
let is_valid x =
let unordered_pairs = is_ordered (x, None) in
let unbounded_adjacent = adjacent_within_bounds x in
unordered_pairs && unbounded_adjacent
let part1 input = List.filter is_valid input |> List.length
let part2 input =
let rec remove_at n = function
| [] ->
[]
| h :: t ->
if n = 0 then t else h :: remove_at (n - 1) t
in
let rec bruteforce n x =
if List.length x = n then false
else if is_valid (remove_at n x) then true
else bruteforce (n + 1) x
in
let is_valid' x = is_valid x || bruteforce 0 x in
List.filter is_valid' input |> List.length
let input = read_input []
let () = input |> part1 |> print_int
let () = print_endline ""
let () = input |> part2 |> print_int