Woohoo! Day 24 is working for my data! Does it run on the Pico?No need for GMP. C++23 has float128_t.
Using your data:Code:
pi@pi5:~/AoC-2023-cplusplus/day24 $ g++ -O3 -std=c++23 day24.cpp pi@pi5:~/AoC-2023-cplusplus/day24 $ ./a.out --- Day 24: Never Tell Me The Odds ---part 1 - 24627part 2 - 527310134398221Elapsed - 22.326 ms.
I finished my solution to the day 25 puzzle today.
Code:
julia> include("day25.jl") # Pi Zero 700 MHzAdvent of Code 2023 Day 25 SnowverloadPart 1 The product of the two groups is 567606Total execution time 52.94287787 seconds.julia> main()Advent of Code 2023 Day 25 SnowverloadPart 1 The product of the two groups is 567606Total execution time 48.092444726 seconds.julia> main()Advent of Code 2023 Day 25 SnowverloadPart 1 The product of the two groups is 567606Total execution time 48.938123044 seconds.
After ruling out an exhaustive snipping of all possible combinations of three wires, the dog developer suggested treating the components as vertices in a graph and the wires as edges. Since it is known that the minimal cut is unique and equal three one can check if the maximum flow between a fixed vertex and each of the other vertices is greater than three. Then place those vertices for which it is in one group and the rest in the other.
The Julia code is
Code:
#= Advent of Code 2023 Day 25 Snowverload Written 2024 by Eric Olson =#struct DoExit <: Exceptionendimport Base.isequal, Base.hashfunction gobble(s::String,m::String)::Tuple{String,Bool} if length(s)<length(m) return s,false end if s[1:length(m)]==m return s[length(m)+1:end],true end return s,falseendfunction wskip(s::String)::String for i=1:length(s) if !isspace(s[i]) return s[i:end] end end return ""endfunction vskip(data,i::Int)::Int while i<=length(data)&&length(data[i])==0 i+=1 end return iend function getalpha(s::String)::Tuple{String,String} for i=1:length(s) if !isletter(s[i]) return s[i:end],s[1:i-1] end end return "",sendfunction getint(s::String)::Tuple{String,Int64} n=Int64(0); ε=1 for i=1:length(s) if s[i]=='-' ε=-1 elseif s[i]>='0'&&s[i]<='9' n=n*10+Int64(s[i]-'0') else return s[i:end],ε*n end end return "",ε*nendmutable struct Edog a::String d::Int f::Int Edog(a,d)=new(a,d,0)endfunction isequal(x::Edog,y::Edog)::Bool return x.a==y.aendfunction hash(x::Edog)::UInt return hash(x.a)endmutable struct Wire c::String e::Vector{Edog}endfunction getwire(s::String)::Wire r=s s,c=getalpha(s) s,f=gobble(s,": ") if f!=true println(r,"\nMissing component separator!") throw(DoExit()) end e=Vector{Edog}() while length(s)>0 s,z=getalpha(s) push!(e,Edog(z,0)) s=wskip(s) end return Wire(c,e)endmutable struct Node w::Wire n::Intendfunction mkpriority()::Tuple{Function,Function} heap=Node[] function enqueue(p::Node) push!(heap,p) r=length(heap) while true s=r÷2 if s<1 break end if heap[s].n<=p.n break end heap[r]=heap[s] r=s end heap[r]=p end function dequeue()::Node if length(heap)==0 println("Tried to remove nonexistent point!\n") throw(DoExit()) end t=pop!(heap) if length(heap)==0 return t end p=heap[1] s0=1 while true r0=2*s0; r1=r0+1 if r0>length(heap) break end s1=r0 if r1<=length(heap) if heap[r0].n>heap[r1].n s1=r1 end end if t.n<=heap[s1].n break end heap[s0]=heap[s1] s0=s1 end heap[s0]=t return p end return enqueue,dequeueendfunction clearflow(wire::Vector{Wire})::Nothing for i=1:length(wire) for e in wire[i].e e.f=0 end endendfunction addflow(wire::Vector{Wire},a::Int,b::Int)::Vector{Int} K=length(wire) enc,deq=mkpriority() g=Vector{Int}(undef,K) g.=typemax(Int) g[b]=0 enc(Node(wire[b],0)) while length(enc.heap)>0 v=deq() n=v.n+1 for e in v.w.e if e.f>-1&&g[e.d]>n g[e.d]=n enc(Node(wire[e.d],n)) end end end function trace()::Vector{Int} k=a if g[a]==typemax(Int) return [] end n=g[a]-1 p=[k] for i=1:2*K for e in wire[k].e if e.f<1&&g[e.d]==n push!(p,e.d) e.f+=1 for er in wire[e.d].e if er.d==k er.f-=1 break end end if e.d==b return p end k=e.d n-=1 end end end println("Unable to trace path from $a to $(b)!") throw(DoExit()) end p=trace() return pendfunction part1(wire::Vector{Wire})::Int K=length(wire) a=1 g=[a] for b=1:K if a==b continue end clearflow(wire) p=addflow(wire,a,b) p=addflow(wire,a,b) p=addflow(wire,a,b) p=addflow(wire,a,b) if length(p)>0 push!(g,b) end end return length(g)*(K-length(g))endfunction doinit() data=String[] open("day25.txt","r") do fp data=readlines(fp) end wmap=Dict{String,Int}() wire=Vector{Wire}(undef,length(data)) for i=1:length(data) wire[i]=getwire(data[i]) wmap[wire[i].c]=i end function fwire(w::Vector{Edog},c::String)::Bool for e in w if e.a==c return true end end return false end for i=1:length(wire) for e in wire[i].e k=get(wmap,e.a,nothing) if k==nothing push!(wire,Wire(e.a,Vector{Edog}())) k=length(wire) wmap[wire[k].c]=k end if !fwire(wire[k].e,wire[i].c) push!(wire[k].e,Edog(wire[i].c,0)) end end end for i=1:length(wire) for e in wire[i].e e.d=wmap[e.a] end end p1=part1(wire) println("Part 1 The product of the two groups is ",p1)endfunction main()::Nothing t=@elapsed try println("Advent of Code 2023 Day 25 Snowverload\n") doinit() throw(DoExit()) catch r if !isa(r,DoExit) rethrow(r) end end println("\nTotal execution time ",t," seconds.")end main()
The code took a surprisingly long time to debug, likely because Fido computed the minimal path backwards b to a but then traced forwards a to b when updating the flow. In the end I think the signs might be reversed from the usual convention.
Statistics: Posted by ejolson — Fri Feb 09, 2024 5:08 am