You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
2.4 KiB
OCaml

(* 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 implode l = String.of_seq (List.to_seq l)
let range start len = (* makes a new list from start with length len *)
List.init len (fun x -> x + 1) |> List.map (fun x -> x + start)
(* --- *)
type 'a tree = Leaf of 'a | Node of 'a tree * 'a tree
let rec build_tree l = (* build a balanced tree from a list *)
match l with (* exception for [] would probably be good here.. *)
| x::[] -> Leaf x
| x::xs ->
let len = List.length l in
let mid_val = List.nth l (len/2) in
let left = range (x-1) (len/2) in
let right = range (mid_val-1) (len/2) in
Node (build_tree left, build_tree right)
let rec walk tree steps =
match tree with
| Leaf a -> a (* if we've hit a leaf, return the value *)
| Node (l, r) ->
match steps with (* if we get to the end of theh list and we haven't hit a leaf, that's a problem.. if only i knew how to do exceptions *)
| 'F' :: xs -> walk l xs
| 'L' :: xs -> walk l xs
| 'B' :: xs -> walk r xs
| 'R' :: xs -> walk r xs
let rows = build_tree (range 0 128)
let cols = build_tree (range 0 8)
let find_seat map =
let row = walk rows (explode (String.sub map 0 7)) - 1 in (* one-off b/c of their non-0-indexed lists? *)
let col = walk cols (explode (String.sub map 7 3)) - 1 in
(row, col)
let seat_id (row, col) = row * 8 + col
let rec list_max li =
match li with (* again non exhaustive, empty list fails. be better *)
| x :: [] -> x
| x :: xs -> max x (list_max xs)
let rec find_missing seats =
match seats with
| x :: y :: z -> if y = x + 1 then find_missing (y :: z) else x + 1
| x :: [] -> x
let seats = read_file "day5.txt" |> List.map find_seat
let seat_ids = List.map seat_id seats
let sorted_seats = List.sort (fun a b -> if a > b then 1 else if a < b then -1 else 0) seat_ids;;
Printf.printf "max seat id %i\n" (list_max seat_ids);;
Printf.printf "missing seat %i\n" (find_missing sorted_seats);;