changeset 29:3c7df4d9b8cb

Start on day 16 - but likely wrong ansatz
author Lewin Bormann <lbo@spheniscida.de>
date Sat, 17 Dec 2022 20:50:31 +0100
parents 72bbee9f4d9e
children bf87eee356fc
files 16/16.jl 16/test_input.txt
diffstat 2 files changed, 128 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/16/16.jl	Sat Dec 17 20:50:31 2022 +0100
@@ -0,0 +1,118 @@
+
+using ParserCombinator
+
+const PValveList = (E"s " + Repeat(p"[A-Z]{2}" + Repeat(E", ", 0, 1)) + Eos()) | (E" " + p"[A-Z]{2}" + Eos());
+const PValveSpec = E"Valve " + p"[A-Z]{2}" + E" has flow rate=" + PInt64() + P"; tunnels? leads? to valve" + PValveList;
+
+struct ValveSpec
+    name::String
+    flowrate::Int
+    tunnels::Vector{String}
+end
+
+function parse_valve_line(s::String)::ValveSpec
+    vs = parse_one(s, PValveSpec);
+    ValveSpec(String(vs[1]), vs[2]::Int, [String(s) for s in vs[3:end]])
+end
+
+struct Peer
+    valve::ValveSpec
+    dist::Int
+end
+
+struct Node
+    valve::ValveSpec
+    routes::Dict{String, Peer}
+end
+
+function build_graph(lines::IOStream)::Dict{String,Node}
+    l = [Node(parse_valve_line(s), Dict()) for s in eachline(lines)];
+    Dict(n.valve.name => n for n in l)
+end
+
+function update_connections(neigh::Node, dist::Int, mine::Dict{String, Peer})::Int
+    count = 0;
+    for (s, p) = mine
+        if s == neigh.valve.name
+            continue
+        end
+        if !(s in keys(neigh.routes)) || neigh.routes[s].dist > p.dist+dist
+            pp = Peer(p.valve, p.dist+dist);
+            neigh.routes[s] = pp;
+            count += 1;
+        end
+    end
+    count
+end
+
+function populate_graph(g::Dict{String,Node})
+    for (id, valve) in g
+        for neigh in valve.valve.tunnels
+            # Insert neighbors with distance = 1.
+            valve.routes[neigh] = Peer(g[neigh].valve, 1);
+        end
+    end
+    #print_graph(g);
+
+    count = 1;
+    # While information propagates through the graph, keep updating.
+    while count > 0
+        count = 0;
+        for (id, node) = g
+            for (id2, node2) = node.routes
+                if id == id2
+                    continue
+                end
+                count += update_connections(g[id2], node2.dist, node.routes);
+            end
+        end
+        @show count
+    end
+    print_graph(g);
+end
+
+# Sort key
+function expected_total_flow(time::Int, peer::Peer)::Int
+    (30 - time - peer.dist - 1) * peer.valve.flowrate
+end
+
+function find_best_next(g::Dict{String,Node}, current::String, time::Int, opened::Set{String})::Tuple{String,Int,Int}
+    cands = [(s, p.dist, expected_total_flow(time, p)) for (s, p) = g[current].routes];
+    sort!(cands; lt=(a, b) -> a[3] < b[3], rev=true);
+    @show cands
+    for (s, dist, tf) = cands
+        if !in(s, opened)
+            return (s, dist, tf);
+        end
+    end
+end
+
+function find_order(g::Dict{String,Node}, start::String)
+    opened = Set{String}();
+    time = 0;
+    while time < 30
+        best, dist, tf = find_best_next(g, start, time, opened);
+        println("found best: $best at $dist with tf = $tf");
+        push!(opened, best);
+        time += dist + 1;
+        println("time now: $time");
+        start = best;
+    end
+end
+
+function print_graph(g::Dict{String,Node})
+    for (id, n) = g
+        println("=== $id === ");
+        println(" flowrate: $(n.valve.flowrate)");
+        println(" neighbors:");
+        for (id2, neigh) = n.routes
+            println("   $id2 => $(neigh.dist)");
+        end
+    end
+end
+
+open("16/test_input.txt"; read=true) do fh
+    g = build_graph(fh);
+    populate_graph(g);
+    find_order(g, "AA");
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/16/test_input.txt	Sat Dec 17 20:50:31 2022 +0100
@@ -0,0 +1,10 @@
+Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
+Valve BB has flow rate=13; tunnels lead to valves CC, AA
+Valve CC has flow rate=2; tunnels lead to valves DD, BB
+Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
+Valve EE has flow rate=3; tunnels lead to valves FF, DD
+Valve FF has flow rate=0; tunnels lead to valves EE, GG
+Valve GG has flow rate=0; tunnels lead to valves FF, HH
+Valve HH has flow rate=22; tunnel leads to valve GG
+Valve II has flow rate=0; tunnels lead to valves AA, JJ
+Valve JJ has flow rate=21; tunnel leads to valve II