
So Here It Is - THE SOLUTION
Yes, finally - if you haven't already seen it on the forum - the solution.
My Own Codea (Lua) Listings Detailed and Condensed
Below are a couple of listings of my own Codea project which resolved this puzzle: the first is annotated and has not been minimised to display the logic more readily together and displaying progress with key variables whilst running the code - it also displays the beermat images making resoltion of the problem slower. The second is condensed - removing annotation, progress monitoring and unnecessary displays. The data that is used in both listings is provided after them in a number of tables.
Links to two further pages Sharp MZ80K and Commodore PET show puzzle solutions in different computer Basic dialects and from just less than 40 years ago.
function setup()
-- set up variables for analysis
s = require("socket")
pA,pB,pC,pD = 0,0,0,0
mirrors = {"00","00","00","00","00","00","00","00"}
lev1,lev2,lev3,lev4 = 0,0,0,0
find = false
font("Baskerville-Bold")
fontSize(32)
count = 0
hits = 0
solutions = {}
start = os.time()
timer = 0
solTimer = {}
-- call the analysis engine
st = s:gettime()
engine()
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
sprite(disc[dAS],200,812,360,360)
sprite(disc[dBS],576,812,360,360)
sprite(disc[dCS],576,440,360,360)
sprite(disc[dDS],200,440,360,360)
text(count,384,280)
text(timer,384,240)
if find == true then
fill(250, 255, 0, 255)
text("WE HAVE "..hits.. " SOLUTIONS !!! ",384,200)
for sol = 1,#solutions do
text(solutions[sol],384,150)
text(solTimer[sol].." secs",680,150)
end
else
fill(244, 33, 59, 255)
text("SORRY NO SOLUTION!!! ",364,200)
end
end
function engine()
-- main engine for testing each construction
limit = 16
for sh = 1,6 do
-- six possible orientations of 4 mats with one fixed
shuffle(sh)
for sA = 1,limit do
disc1(pA,sA)
for sB = 1,limit do
disc2(pB,sB)
for sC = 1,limit do
disc3(pC,sC)
for sD = 1,limit do
disc4(pD,sD)
checkIt()
count = count+1
end
end
end
end
print(level)
end
en = s:gettime()
print(en-st)
finish = os.time()
timer = os.difftime(finish,start)
end
function shuffle(n)
-- reads the configuration of the mats from table
pos = (n-1)*4+1
pA = routePlan[pos]
pB = routePlan[pos+1]
pC = routePlan[pos+2]
pD = routePlan[pos+3]
-- printing out to confirm each configuration has been tested in order
orientation = "Orientation: "..pA..pB..pC..pD
print(orientation)
end
function switch(str)
-- flip the two characters of string prior to comparison
local temp = string.reverse(str)
return temp
end
function disc1(mat,edge)
-- specifies the face and edge of the first mat position
if edge <= 8 then dA = 1 fA ="F" else dA = 2 fA = "B" edge = edge-8 end
dAS = (mat-1)*2+dA
mirStr = double[dAS]
mirrors[1] = string.sub(mirStr,(edge-1)*2+5,(edge-1)*2+6)
mirrors[2] = string.sub(mirStr,(edge-1)*2+9,(edge-1)*2+10)
end
function disc2(mat,edge)
-- specifies the face and edge of the second mat position
if edge <= 8 then dB = 1 fB ="F" else dB = 2 fB = "B" edge = edge-8 end
dBS = (mat-1)*2+dB
mirStr = double[dBS]
mirrors[3] = string.sub(mirStr,(edge-1)*2+9,(edge-1)*2+10)
mirrors[4] = string.sub(mirStr,(edge-1)*2+13,(edge-1)*2+14)
end
function disc3(mat,edge)
-- specifies the face and edge of the third mat position
if edge <= 8 then dC = 1 fC ="F" else dC = 2 fC = "B" edge = edge-8 end
dCS = (mat-1)*2+dC
mirStr = double[dCS]
mirrors[5] = string.sub(mirStr,(edge-1)*2+13,(edge-1)*2+14)
mirrors[6] = string.sub(mirStr,(edge-1)*2+1,(edge-1)*2+2)
end
function disc4(mat,edge)
-- specifies the face and edge of the fourth mat position
if edge <= 8 then dD = 1 fD ="F" else dD = 2 fD = "B" edge = edge-8 end
dDS = (mat-1)*2+dD
mirStr = double[dDS]
mirrors[7] = string.sub(mirStr,(edge-1)*2+1,(edge-1)*2+2)
mirrors[8] = string.sub(mirStr,(edge-1)*2+5,(edge-1)*2+6)
end
function checkIt()
-- works out the number of matches at each level/interface
level = "Lev"
if mirrors[1] == switch(mirrors[4]) then lev1 = lev1+1 end
if mirrors[3] == switch(mirrors[6]) then lev2 = lev2+1 end
if mirrors[5] == switch(mirrors[8]) then lev3 = lev3+1 end
if mirrors[7] == switch(mirrors[2]) then lev4 = lev4+1 end
-- combines matches at each level in a string
level = level.."-"..lev1.."-"..lev2.."-"..lev3.."-"..lev4
-- the real check for four matches in each configuration
if mirrors[1] == switch(mirrors[4]) and mirrors[3] == switch(mirrors[6]) and mirrors[5] == switch(mirrors[8]) and mirrors[7] == switch(mirrors[2]) then
-- record condition and hits build configuration string and store in table
find = true
hits = hits+1
solution = mirrors[1].."("..pA..fA..")-"..mirrors[3].."("..pB..fB..")-"..mirrors[5].."("..pC..fC..")-"..mirrors[7].."("..pD..fD..")"
now = os.time()
timer = os.difftime(now,start)
table.insert(solutions,hits,solution)
table.insert(solTimer,hits,timer)
end
end
A Condensed version
This listing has all remarks and minimised to necessary code
function setup()
s = require("socket")
pA,pB,pC,pD,lev1,lev2,lev3,lev4 = 0,0,0,0,0,0,0,0
mirrors = {"00","00","00","00","00","00","00","00"}
find = false
font("Baskerville-Bold")
fontSize(32)
count, hits = 0,0
solutions = {}
solTimer = {}
st = s:gettime()
engine()
end
function draw()
background(40, 40, 50)
text(count,384,280)
if find == true then
fill(250, 255, 0, 255)
text("WE HAVE "..hits.. " SOLUTIONS !!! ",384,232)
for sol = 1,#solutions do
text(solutions[sol],384,200)
text(solTimer[sol].." secs",384,150)
end
else
fill(244, 33, 59, 255)
text("SORRY NO SOLUTION!!! ",364,200)
end
end
function engine()
limit = 16
for sh = 1,6 do
shuffle(sh)
for sA = 1,limit do
if sA <= 8 then dA = 1 fA ="F" else dA = 2 fA = "B" sA = sA-8 end
dAS = (pA-1)*2+dA
mirStr = double[dAS]
mirrors[1] = string.sub(mirStr,(sA-1)*2+5,(sA-1)*2+6)
mirrors[2] = string.sub(mirStr,(sA-1)*2+9,(sA-1)*2+10)
for sB = 1,limit do
if sB <= 8 then dB = 1 fB ="F" else dB = 2 fB = "B" sB = sB-8 end
dBS = (pB-1)*2+dB
mirStr = double[dBS]
mirrors[3] = string.sub(mirStr,(sB-1)*2+9,(sB-1)*2+10)
mirrors[4] = string.sub(mirStr,(sB-1)*2+13,(sB-1)*2+14)
for sC = 1,limit do
if sC <= 8 then dC = 1 fC ="F" else dC = 2 fC = "B" sC = sC-8 end
dCS = (pC-1)*2+dC
mirStr = double[dCS]
mirrors[5] = string.sub(mirStr,(sC-1)*2+13,(sC-1)*2+14)
mirrors[6] = string.sub(mirStr,(sC-1)*2+1,(sC-1)*2+2)
for sD = 1,limit do
if sD <= 8 then dD = 1 fD ="F" else dD = 2 fD = "B" sD = sD-8 end
dDS = (pD-1)*2+dD
mirStr = double[dDS]
mirrors[7] = string.sub(mirStr,(sD-1)*2+1,(sD-1)*2+2)
mirrors[8] = string.sub(mirStr,(sD-1)*2+5,(sD-1)*2+6)
checkIt()
count = count+1
end
end
end
end
end
en = s:gettime()
print("Completion : "..en-st)
end
function shuffle(n)
pos = (n-1)*4+1
pA = routePlan[pos]
pB = routePlan[pos+1]
pC = routePlan[pos+2]
pD = routePlan[pos+3]
orientation = "Orientation: "..pA..pB..pC..pD
-- print(orientation)
end
function switch(str)
local temp = string.reverse(str)
return temp
end
function checkIt()
level = "Lev"
if mirrors[1] == switch(mirrors[4]) then lev1 = lev1+1 end
if mirrors[3] == switch(mirrors[6]) then lev2 = lev2+1 end
if mirrors[5] == switch(mirrors[8]) then lev3 = lev3+1 end
if mirrors[7] == switch(mirrors[2]) then lev4 = lev4+1 end
level = level.."-"..lev1.."-"..lev2.."-"..lev3.."-"..lev4
if mirrors[1] == switch(mirrors[4]) and mirrors[3] == switch(mirrors[6]) and mirrors[5] == switch(mirrors[8]) and mirrors[7] == switch(mirrors[2]) then
find = true
hits = hits+1
solution = mirrors[1].."("..pA..fA..")-"..mirrors[3].."("..pB..fB..")-"..mirrors[5].."("..pC..fC..")-"..mirrors[7].."("..pD..fD..")"
now = s:gettime()
table.insert(solutions,hits,solution)
table.insert(solTimer,hits,now-st)
end
end
The Common Data Tables used
double = {
"PTTFFPRBBPLBLRRBPTTFFPRBBPLBLRRB",
"RPBLPHFPTLHPTRLRRPBLPHFPTLHPTRLR",
"BRFBRFRPBTRTLTTFBRFBRFRPBTRTLTTF",
"TFTPPBPFFLRFLBPRTFTPPBPFFLRFLBPR",
"RLFBHRPBFRTRPTBTRLFBHRPBFRTRPTBT",
"TLTBFLBPBLHRBFHPTLTBFLBPBLHRBFHP",
"PRPHTBTPBRRHLFFTPRPHTBTPBRRHLFFT",
"LTFRRTFTRLBFRHLFLTFRRTFTRLBFRHLF"
}
routePlan = {1,2,3,4,1,2,4,3,1,3,2,4,1,3,4,2,1,4,2,3,1,4,3,2}
disc = {"BeerMatPuz:BM3001F",
"BeerMatPuz:BM3001B",
"BeerMatPuz:BM3002F",
"BeerMatPuz:BM3002B",
"BeerMatPuz:BM3003F",
"BeerMatPuz:BM3003B",
"BeerMatPuz:BM3004F",
"BeerMatPuz:BM3004B"
}