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