115 lines
3.6 KiB
Plaintext
115 lines
3.6 KiB
Plaintext
integer show = 2, -- max number to show
|
|
-- (nb mirrors are not shown)
|
|
chance = 1000 -- 1=always, 2=50%, 3=33%, etc
|
|
|
|
sequence grid
|
|
|
|
integer gh, -- = length(grid),
|
|
gw -- = length(grid[1])
|
|
|
|
integer ty1, ty2, tx1, tx2 -- target {y,x}s
|
|
|
|
procedure mirror(integer y, x, ch)
|
|
-- plant/reset ch and the symmetric copy
|
|
grid[y,x] = ch
|
|
grid[gh-y+1,gw-x+1] = ch
|
|
end procedure
|
|
|
|
enum RIGHT, UP, DOWN, LEFT
|
|
constant dyx = {{0,+1},{-1,0},{+1,0},{0,-1}},
|
|
chx = "-||-"
|
|
|
|
function search(integer y, x, d, level)
|
|
integer count = 0
|
|
if level=0 or grid[y,x]!='x' then
|
|
mirror(y,x,'x')
|
|
integer {dy,dx} = dyx[d],
|
|
{ny,nx} = {y+dy,x+dx},
|
|
{yy,xx} = {y+dy*2,x+dx*3}
|
|
if grid[ny,nx]=' ' then
|
|
integer c = chx[d]
|
|
mirror(ny,nx,c)
|
|
if c='-' then
|
|
mirror(ny,nx+dx,c)
|
|
end if
|
|
integer meet = (yy=ty1 or yy=ty2) and (xx=tx1 or xx=tx2)
|
|
if meet then
|
|
count = 1
|
|
if show and rand(chance)=chance then
|
|
show -= 1
|
|
sequence g = grid -- (make copy/avoid reset)
|
|
-- fill in(/overwrite) the last cut, if any
|
|
if ty1!=ty2 then g[ty1+1,tx1] = '|'
|
|
elsif tx1!=tx2 then g[ty1][tx1+1..tx1+2] = "--"
|
|
end if
|
|
puts(1,join(g,'\n')&"\n\n")
|
|
end if
|
|
else
|
|
if grid[yy,xx]='+' then -- (minor gain)
|
|
for d=RIGHT to LEFT do -- (kinda true!)
|
|
count += search(yy,xx,d,level+1)
|
|
end for
|
|
end if
|
|
end if
|
|
mirror(ny,nx,' ')
|
|
if c='-' then
|
|
mirror(ny,nx+dx,' ')
|
|
end if
|
|
end if
|
|
if level!=0 then
|
|
-- ((level=0)==leave outer edges 'x' for next iteration)
|
|
mirror(y,x,'+')
|
|
end if
|
|
end if
|
|
return count
|
|
end function
|
|
|
|
function odd(integer n) return remainder(n,2)=1 end function
|
|
function even(integer n) return remainder(n,2)=0 end function
|
|
|
|
procedure make_grid(integer w,h)
|
|
-- The outer edges are 'x'; the inner '+' become 'x' when visited.
|
|
-- Likewise edges are cuts but the inner ones get filled in later.
|
|
sequence tb = join(repeat("x",w+1),"--"),
|
|
hz = join('x'&repeat("+",w-1)&'x'," ")&"\n",
|
|
vt = "|"&repeat(' ',w*3-1)&"|\n"
|
|
grid = split(tb&"\n"&join(repeat(vt,h),hz)&tb,'\n')
|
|
-- set size (for mirroring) and target info:
|
|
gh = length(grid) gw = length(grid[1])
|
|
ty1 = h+even(h) ty2 = ty1+odd(h)*2
|
|
tx1 = floor(w/2)*3+1 tx2 = tx1+odd(w)*3
|
|
end procedure
|
|
|
|
function side(integer w, h)
|
|
make_grid(w,h)
|
|
-- search top to mid-point
|
|
integer count = 0, last = 0
|
|
for r=3 to h+1 by 2 do
|
|
last = search(r,1,RIGHT,0) -- left to right
|
|
count += 2*last
|
|
end for
|
|
if even(h) then
|
|
count -= last -- (un-double the centre line)
|
|
end if
|
|
return count
|
|
end function
|
|
|
|
--atom t0 = time()
|
|
-- nb sub-optimal: obviously "grid" was designed for easy display, rather than speed.
|
|
for y=1 to 9 do -- 24s
|
|
--for y=1 to 10 do -- (gave up on >10x8)
|
|
for x=1 to y do
|
|
-- for x=1 to min(y,8) do -- 4 mins 16s (with y to 10)
|
|
if even(x*y) then
|
|
integer count = side(x,y)
|
|
if x=y then
|
|
count *= 2
|
|
else
|
|
count += side(y,x)
|
|
end if
|
|
printf(1,"%d x %d: %d\n", {y, x, count})
|
|
end if
|
|
end for
|
|
end for
|
|
--?elapsed(time()-t0)
|