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 }]
|
||||
|
||||
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 |}]
|
||||
;;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user