It looks like you're new here. If you want to get involved, click one of these buttons!
Here’s another one of my useless programs. I normally write code while I’m watching TV for something else to do. On Saturday and Sunday I spent both days watching the football playoffs all day. This code tries to solve solutions for the knights tour. That’s the chess piece (knight) moving on a checker board so it makes a valid move and lands on each square without landing on a previously occupied square. There are a lot of solutions and even more paths that aren’t. So here’s a visual of the knights moves. A knight can make 8 valid moves from a square. I try a move and if it’s lands on a square already occupied, I try the next move going in a counter clockwise direction. If after the 8 tries, I’ll backup to the previous square and try the next move. The program will pause when a solution is found or you can tap the screen to pause it. The first one is at 54,482,161 tries. When the program starts, it makes 1 try per draw cycle. Opening up the print pane, you can move the slider to increase it to 1,000,000 moves per draw cycle. I show different counts as the program runs. As I said, I wrote this while watching TV, so it might not display correctly on every device. This only starts at the lower left square. If you have questions, just ask.
viewer.mode=FULLSCREEN
function setup()
sx,sy=1,1
parameter.integer("tries",0,6)
piecePos=1
pieceMove={vec2(-1,2),vec2(-2,1),vec2(-2,-1),vec2(-1,-2),
vec2(1,-2),vec2(2,-1),vec2(2,1),vec2(1,2)}
rectMode(CENTER)
tab={}
board={}
for x=1,8 do
board[x]={}
for y=1,8 do
board[x][y]=0
end
end
for z=1,64 do
table.insert(tab,piece(vec2(0,0),z))
end
size=80
tab[1].x=sx
tab[1].y=sy
board[sx][sy]=1
count=0
high=0
solutions=0
end
function draw()
background(0)
drawBoard()
for z=1,10^tries do
tab[piecePos]:next()
end
if piecePos>high then
high=piecePos
end
fontSize(20)
fill(255)
text("Rotations",WIDTH/2,HEIGHT-20)
for a,b in pairs(tab) do
text(string.format("%d",b.rot),a*12+20,HEIGHT-50)
end
text("Nbr of Tries "..count,WIDTH-150,HEIGHT-80)
text("Current Pos "..piecePos,WIDTH-150,HEIGHT-110)
text("Highest Pos "..high,WIDTH-150,HEIGHT-140)
text("Solutions "..solutions,WIDTH-150,HEIGHT-170)
text("+ 1 + 8 +",WIDTH-150,HEIGHT-200)
text("2 + + + 7",WIDTH-150,HEIGHT-220)
text("+ + O + +",WIDTH-150,HEIGHT-240)
text("3 + + + 6",WIDTH-150,HEIGHT-260)
text("+ 4 + 5 +",WIDTH-150,HEIGHT-280)
text("Tries per draw-cycle "..10^tries,WIDTH/2,HEIGHT-100)
if wait then
text("PAUSED",WIDTH/2,HEIGHT-130)
end
text("3 solutions at ",WIDTH-150,HEIGHT-310)
text("54,482,161",WIDTH-150,HEIGHT-330)
text("57,053,315",WIDTH-150,HEIGHT-350)
text("57,059,627",WIDTH-150,HEIGHT-370)
end
function touched(t)
if t.state==BEGAN then
wait=not wait
if high==64 then
high=0
end
end
end
function drawBoard()
strokeWidth(1)
fill(255)
if wait then
fill(0, 201, 255)
end
for x=1,8 do
for y=1,8 do
rect(x*size,y*size,size,size)
end
end
for z=1,piecePos do
tab[z]:draw()
end
end
piece = class()
function piece:init(pos,val)
self.x=pos.x
self.y=pos.y
self.rot=0
self.val=val
end
function piece:draw()
stroke(0)
strokeWidth(4)
for z=2,piecePos do
line(tab[z].x*size,tab[z].y*size,tab[z-1].x*size,tab[z-1].y*size)
end
fontSize(60)
fill(255,0,0)
if self.x>0 then
text(self.val,self.x*size,self.y*size)
end
end
function piece:next()
if wait then
return
end
count=count+1
while true do
self.rot=self.rot+1
if self.rot>8 then
self.rot=0
board[self.x][self.y]=0
piecePos=piecePos-1
return
else
tx=tab[piecePos].x+pieceMove[self.rot].x
ty=tab[piecePos].y+pieceMove[self.rot].y
if tx<1 or ty<1 or tx>8 or ty>8 or board[tx][ty]~=0 then
--
else
tab[piecePos+1].x=tx
tab[piecePos+1].y=ty
board[tx][ty]=piecePos+1
piecePos=piecePos+1
if piecePos==64 then
wait=true
solutions=solutions+1
end
return
end
end
end
end
Comments
Here’s an updated version. This version lets you select a starting square. Just tap any square and tap outside the board to un-pause the screen. There is also a Boolean selector in the print panel to allow the program to update the found solutions count without pausing. The slider is still there to allow you to select up to 1,000,000 iterations per draw cycle. The higher the iterations, the lower the frames per second. I show the average FPS to see what’s happening. You can still pause/unpause the screen at anytime by tapping outside the board area. If you select the upper right square, that has a lot of solutions. 230 solutions below 30,000,000 tries and it increases a lot after that.
PS. Added a single step option. Slide the Boolean switch to on and then tap outside of the board for each single step move.
@dave1707 - sorry for the delay in posting very busy at moment. Thanks for posting this, I like to see logical meticulous approaches to problems - mainly because I’m personally not very organised. These are good examples of approach to a problem.
Might have an interesting issue for you to try, when I get round to finishing my current fixations. Not sure it’s something Lua can deal with. Don’t hold your breath though.
@Bri_G I like writing programs that give a visual while solving an ongoing problem. It’s a useless program other than giving me something to write. Even after writing some programs, I like to go back and see if there’s anyway to make it faster, smaller, or add other options to make it more interesting. I enjoyed the Beermat problem you posted back in Nov 2019. That was a fun problem to solve.
there is a heuristic in knight's tour: try moves in order of fewest next options to most.
@RonJeffries I looked at a lot of the Knights Tour info on Google, and saw various ways that solutions were found. I wasn’t trying to do anything like that, just to write something that would eventually find a solution. It was really just something to code. There are so many combinations of solutions, that even the fastest computers would take a long time to find them. I find it interesting to just watch as different paths are drawn and then backed out because of dead ends. It almost like watching a mouse trying to find a piece of cheese in a maze.
yes