(* Common util. Should probably put this in a module or something.. *) let get_one_line file = try Some (input_line file) with End_of_file -> None let get_lines file = let rec input lines = match get_one_line file with Some line -> input (line :: lines) | None -> List.rev lines in input [] let read_file file = let channel = open_in(file) in get_lines channel let explode s = (* convert a string to a list of chars *) let rec exp i l = if i < 0 then l else exp (i - 1) (s.[i] :: l) in exp (String.length s - 1) [];; (* --- *) let wrapped_y y map = (* wrap the y (horizontal) coordinate when off the map *) y mod (List.length (List.nth map 1)) let read_cell map x y = (* return Some char at these coordinates, or None if below the map *) if (x < List.length map) then Some (List.nth (List.nth map x) (wrapped_y y map)) else None let rec go map position slope = (* move across the map, counting trees *) let (x, y) = position in let (dy, dx) = slope in (* suddenly regretting having x be the vertical axis.. *) match read_cell map x y with | None -> 0 (* off the map! stop counting *) | Some '#' -> 1 + go map (x+dx, y+dy) slope | Some a -> go map (x+dx, y+dy) slope let map = read_file "day3.txt" |> List.map explode let slopes = [(1, 1); (3, 1); (5, 1); (7, 1); (1, 2)] let tree_counts = slopes |> List.map (fun slope -> go map (0, 0) slope);; List.iter (fun count -> Printf.printf "Number of trees: %i\n" count) tree_counts;; let product = List.fold_left ( * ) 1 tree_counts;; Printf.printf "Product: %i\n" product