type space = Tree | Free type map = space array array let (.%()) arr i = arr.(i mod Array.length arr) let iter_map ?(step_x=1) ?(step_y=1) f arr = let i = ref 0 in let j = ref 0 in while !i < Array.length arr do f arr.(!i).%(!j); i := !i + step_x; j := !j + step_y done exception Unknown_char of char let make_line str = Array.init (String.length str) (fun i -> match str.[i] with | '#' -> Tree | '.' -> Free | c -> raise (Unknown_char c)) let read_file = Bracket.infile_lines ~line:make_line ~of_seq:Array.of_seq let count_trees ?step_x ?step_y map = let count = ref 0 in iter_map ?step_x ?step_y (function Tree -> incr count | _ -> ()) map; !count let main1 input = Format.printf "%d trees\n" (count_trees ~step_y:3 (read_file input)) let main2 input = let map = read_file input in let prod = List.fold_left ( * ) 1 [count_trees map; count_trees map ~step_y:3; count_trees map ~step_y:5; count_trees map ~step_y:7; count_trees map ~step_x:2] in Format.printf "product: %d\n" prod let mains = [|main1; main2|] let main = function | [part; input] -> mains.(int_of_string part - 1) input | _ -> Usage.exit_default 3 let%expect_test _ = main1 "../../data/day3"; [%expect{| 244 trees |}] let%expect_test _ = main2 "../../data/day3"; [%expect{| product: 9406609920 |}]