Hourglass puzzle: Difference between revisions

m (→‎{{header|Raku}}: side note)
Line 121:
Series: [5, 2, 3, 4, 1, 5, 1, 4, 3, 2, 1, 4, 5, 2, 3, 4, 1]
Use hourglasses from step 5 to step 17 (inclusive) to sum 36 using [5, 7, 31]
</pre>
 
=={{header|Phix}}==
<lang Phix>procedure print_solution(sequence eggtimers, tries, integer target, pdx)
sequence soln = {tries[$]}, remain
integer n = length(eggtimers), tdx = tries[$][3], t, flipbits
string et = ""
for timer=1 to n do
if timer=n then et &= " and "
elsif timer>1 then et &= ", " end if
et &= sprintf("%d",eggtimers[timer])
end for
printf(1,"\nSolution for %d minutes with %s minute eggtimers:\n",{target,et})
while tdx do
if tdx=pdx then soln &= 0 end if
soln = append(soln,tries[tdx])
tdx = tries[tdx][3]
end while
soln = reverse(soln[1..$-1])
integer tp = 0, ro = 0
sequence premain = repeat(0,n)
for i=1 to length(soln) do
if soln[i]=0 then
puts(1,"start timer\n")
else
{remain,t,?,flipbits} = soln[i]
sequence flip = int_to_bits(flipbits,n)
string fs = "", lv = ""
for timer=1 to n do
if flip[timer] then
if length(fs) then fs &= " and " end if
fs &= sprintf("%d",eggtimers[timer])
if premain[timer] then
fs &= sprintf(" (leaving %d)",eggtimers[timer]-premain[timer])
end if
end if
if remain[timer]=0 then
if flip[timer] or premain[timer]!=0 then
ro = eggtimers[timer]
end if
else
if length(lv) then lv &= " and " end if
lv &= sprintf("%d in %d",{remain[timer],eggtimers[timer]})
end if
end for
lv = iff(length(lv)?" (leaving "&lv&")":"")
printf(1,"At t=%d, flip %s, then when %d runs out%s...\n",{tp,fs,ro,lv})
tp = t
premain = remain
end if
end for
printf(1,"At t=%d, stop timer\n",{tp})
end procedure
 
procedure solve(sequence eggtimers, integer target)
integer n = length(eggtimers), tdx = 1, t, pdx
sequence remain = repeat(0,n),
tries = {{remain,0,0,0}} -- {{remain,t,link,flip}}
while tdx<=length(tries) do
for flipbits=1 to power(2,n)-1 do
{remain,t} = tries[tdx]
sequence flip = int_to_bits(flipbits,n)
for timer=1 to n do
if flip[timer] then
remain[timer] = eggtimers[timer]-remain[timer]
end if
end for
integer mr = min(filter(remain,">",0))
remain = sq_max(sq_sub(remain,mr),0)
mr += t
tries = append(tries,{remain,mr,tdx,flipbits})
pdx = tdx
while pdx do
mr -= tries[pdx][2]
if mr>=target then
if mr>target then exit end if
print_solution(eggtimers, tries, target, pdx)
return
end if
mr += tries[pdx][2]
pdx = tries[pdx][3]
end while
end for
tdx += 1
-- totally arbitrary sanity crash:
if length(tries)>20000 then crash("no solution") end if
end while
end procedure
solve({4,7},9)
solve({4,7},15)
solve({5,7,31},36) -- (slightly better output than Julia, I think...)
solve({4,5},7) -- (logo solution stops timer at t=12, this manages t=11)
solve({7,11},15) -- (logo solution stops timer at t=22, this manages t=15)
solve({5,8},14) -- (logo solution stops timer at t=24, this manages t=19)</lang>
{{out}}
<pre>
Solution for 9 minutes with 4 and 7 minute eggtimers:
start timer
At t=0, flip 4 and 7, then when 4 runs out (leaving 3 in 7)...
At t=4, flip 4, then when 7 runs out (leaving 1 in 4)...
At t=7, flip 7, then when 4 runs out (leaving 6 in 7)...
At t=8, flip 7 (leaving 1), then when 7 runs out...
At t=9, stop timer
 
Solution for 15 minutes with 4 and 7 minute eggtimers:
start timer
At t=0, flip 4, then when 4 runs out...
At t=4, flip 4, then when 4 runs out...
At t=8, flip 7, then when 7 runs out...
At t=15, stop timer
 
Solution for 36 minutes with 5, 7 and 31 minute eggtimers:
start timer
At t=0, flip 5, then when 5 runs out...
At t=5, flip 31, then when 31 runs out...
At t=36, stop timer
 
Solution for 7 minutes with 4 and 5 minute eggtimers:
At t=0, flip 4 and 5, then when 4 runs out (leaving 1 in 5)...
start timer
At t=4, flip 4, then when 5 runs out (leaving 3 in 4)...
At t=5, flip 4 (leaving 1), then when 4 runs out...
At t=6, flip 5, then when 5 runs out...
At t=11, stop timer
 
Solution for 15 minutes with 7 and 11 minute eggtimers:
start timer
At t=0, flip 7 and 11, then when 7 runs out (leaving 4 in 11)...
At t=7, flip 7, then when 11 runs out (leaving 3 in 7)...
At t=11, flip 7 (leaving 4), then when 7 runs out...
At t=15, stop timer
 
Solution for 14 minutes with 5 and 8 minute eggtimers:
At t=0, flip 5 and 8, then when 5 runs out (leaving 3 in 8)...
start timer
At t=5, flip 5, then when 8 runs out (leaving 2 in 5)...
At t=8, flip 5 (leaving 3), then when 5 runs out...
At t=11, flip 8, then when 8 runs out...
At t=19, stop timer
</pre>
 
7,796

edits