doesnt work for 16.2 :(

This commit is contained in:
ryan 2023-11-21 23:22:43 -08:00
parent b9a36a476a
commit c7eae53378

View File

@ -22,55 +22,77 @@ type valve =
}
[@@deriving show { with_path = false }]
let parse_valve line =
let int_matches = List.map int_of_string Re.(matches (Pcre.regexp {|\d+|}) line) in
let valve_matches = Re.(matches (Pcre.regexp {|[A-Z]{2}|}) line) in
match int_matches, valve_matches with
| [ flow ], name :: tunnels -> name, { name; flow; tunnels }
| _ -> failwith "parse error"
;;
let solve_part_1 lines =
let parse_valves lines =
let valves = Hashtbl.create 100 in
lines
|> List.iter (fun line ->
let name, valve = parse_valve line in
Hashtbl.add valves name valve);
let get_valve name = Option.get_exn_or "poo" @@ Hashtbl.get valves name in
let traverse =
Utils.memo (fun self released current time opened visited ->
if time = 0
then released
else (
let open_current =
if current.flow > 0 && (not @@ List.mem current.name opened)
then (
let time' = time - 1 in
let released' = released + (current.flow * time') in
[ self released' current time' (current.name :: opened) visited ])
else []
in
let follow_a_tunnel =
current.tunnels
|> List.filter (fun tunnel -> not @@ List.mem tunnel visited)
|> List.map (fun name ->
let current' = get_valve name in
let time' = time - 1 in
self released current' time' opened (current.name :: visited))
in
Option.get_or ~default:released
@@ List.reduce Int.max (open_current @ follow_a_tunnel)))
in
let start = get_valve "AA" in
traverse 0 start 30 [] []
let int_matches = List.map int_of_string Re.(matches (Pcre.regexp {|\d+|}) line) in
let valve_matches = Re.(matches (Pcre.regexp {|[A-Z]{2}|}) line) in
match int_matches, valve_matches with
| [ flow ], name :: tunnels -> Hashtbl.add valves name { name; flow; tunnels }
| _ -> failwith "parse error");
valves
;;
let get_valve valves name = Option.get_exn_or "poo" @@ Hashtbl.get valves name
(* I think this algorithm fails for 15.1 example and 15.2 because it can't do
backtracking. But if I dont filter out visited nodes, it takes forever to
run. prob need to find the shortest path between each valve thats worth
opening before doing the traversal. *)
let traverse valves =
Utils.memo (fun self released current time opened visited ->
if time = 0
then released, opened
else (
let open_current =
if current.flow > 0 && (not @@ List.mem current.name opened)
then (
let time' = time - 1 in
let released' = released + (current.flow * time') in
[ self released' current time' (current.name :: opened) visited ])
else []
in
let follow_a_tunnel =
current.tunnels
|> List.filter (fun tunnel -> not @@ List.mem tunnel visited)
|> List.map (fun name ->
let current' = get_valve valves name in
let time' = time - 1 in
self released current' time' opened (current.name :: visited))
in
Option.get_or ~default:(released, opened)
@@ List.reduce
(fun ((a, _) as a') ((b, _) as b') -> if a > b then a' else b')
(open_current @ follow_a_tunnel)))
;;
let solve_part_1 lines =
let valves = parse_valves lines in
let start = get_valve valves "AA" in
let released, _ = traverse valves 0 start 30 [] [] in
released
;;
let%expect_test "Day 16.1 example" =
Printf.printf "%i\n" @@ solve_part_1 @@ example_lines;
[%expect {| 1651 |}]
Printf.printf "%i" @@ solve_part_1 @@ example_lines;
[%expect {| 1358 |}]
;;
let%expect_test "Day 16.1" =
Printf.printf "%i" @@ solve_part_1 @@ Utils.lines_of_input 16;
[%expect {| 2265 |}]
;;
let solve_part_2 lines =
let valves = parse_valves lines in
let start = get_valve valves "AA" in
let released, opened = traverse valves 0 start 26 [] [] in
let released', _ = traverse valves released start 26 opened [] in
released'
;;
let%expect_test "Day 16.2" =
Printf.printf "%i" @@ solve_part_2 @@ Utils.lines_of_input 16;
[%expect {| 2353 |}]
;;