73 lines
2.0 KiB
OCaml
73 lines
2.0 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 rec split_on_empty_line lines =
|
|
match lines with
|
|
| head :: tail ->
|
|
if String.length head = 0 then
|
|
([], tail)
|
|
else
|
|
let rest_of_list, remaining_lines = split_on_empty_line tail in
|
|
(head :: rest_of_list, remaining_lines)
|
|
| _ -> ([], lines)
|
|
|
|
let rec split_by_empty_lines lines =
|
|
if List.length lines = 0 then
|
|
[]
|
|
else
|
|
let line, remainder = split_on_empty_line lines in
|
|
line :: split_by_empty_lines remainder
|
|
|
|
let rec sum_columns_inner arr lst =
|
|
match lst with
|
|
| head :: tail ->
|
|
String.iteri (fun i v -> if v = '#' then arr.(i) <- arr.(i) + 1) head;
|
|
sum_columns_inner arr tail
|
|
| _ -> ()
|
|
|
|
let sum_columns elem_len lst =
|
|
let arr = Array.make elem_len 0 in
|
|
sum_columns_inner arr lst;
|
|
Array.to_list arr
|
|
|
|
let parse_schematic_fold (locks, keys) schematic =
|
|
match schematic with
|
|
| head :: tail -> begin
|
|
let heights = match (List.rev tail) with
|
|
| last :: rest ->
|
|
sum_columns (String.length head) rest
|
|
| _ -> raise (Invalid_argument "Invalid schematic") in
|
|
if head.[0] = '.' then
|
|
(locks, heights :: keys)
|
|
else
|
|
(heights :: locks, keys)
|
|
end
|
|
| _ -> raise (Invalid_argument "Invalid schematic")
|
|
|
|
let rec heights_fit key lock =
|
|
match (key, lock) with
|
|
| (head1 :: tail1, head2:: tail2) ->
|
|
if head1 + head2 > 5 then
|
|
false
|
|
else
|
|
heights_fit tail1 tail2
|
|
| ([], []) -> true
|
|
| _ -> raise (Invalid_argument "Key lengths don't match")
|
|
|
|
let () =
|
|
let f = open_in "input.txt" in
|
|
let schematics = list_of_lines f |> split_by_empty_lines in
|
|
let locks, keys = List.fold_left parse_schematic_fold ([], []) schematics in
|
|
let result = locks |> List.map (fun lock ->
|
|
keys
|
|
|> List.map (fun key -> if heights_fit key lock then 1 else 0)
|
|
|> List.fold_left Int.add 0)
|
|
|> List.fold_left Int.add 0 in
|
|
printf "%d\n" result |