Tag Archives: puzzle

Jumping Frogs – Using Python to Solve Puzzles

A few months ago I came across the following puzzle in a video game I was playing:

The starting position for the siz frogs puzzleThree frogs are happily hopping along a narrow board together when they meet another group of three frogs traveling in the opposite direction. These frogs can only move in the direction they are facing, and only if there is a space directly in front of them. Additionally, a frog can jump over the frog in front but only if there is clear space on the other side to land in.

How can the frogs (moving one at a time) pass each other and continue on their way?

Of course, this is a hoary old puzzle that most people come across and solve as children. It should be only a couple of minutes work with a pen and paper to confirm that it is possible to exchange both sets of frogs but I wouldn’t be much of a programmer if I used a piece of paper where hundreds of dollars of computer equipment would do just as well.

To solve a puzzle like this programatically requires three things: a representation of the current state of the problem, a way of generating every possibly legal move from a given position, and a way of figuring out when is a good time to stop.

Firstly, the representation of the board is a simple python list:

1
start = [1, 1, 1, 0, -1, -1, -1]

Frogs traveling right or left are represented by “1″ and “-1″ respectively. Empty spaces that frog can move into are represented by “0″. The advantage of this representation is that you can calculate the new position of a frog by:

1
newPos = pos + (representation * distance)

where pos is the current index in the array, distance is the size of the hop (either 1 or 2) and representation is either 1 or -1.

Next, we need a way of generating legal moves for a given position:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def legalMoves(board):
	moves = []
	for pos, piece in enumerate( board ):
		jumpmove = pos + (piece * 2)
		move = pos + (piece)
		if ( piece == 0 ):
			continue
		if (not (( jumpmove < 0 ) or ( jumpmove >= len(board)))):
			if (board[jumpmove] == 0):
				t = list(board)
				t[pos] = 0
				t[jumpmove] = piece
				moves.append(t)
		if (not ((move < 0) or ( move >= len(board)))):
			if ( board[move] == 0):
				t = list(board)
				t[pos] = 0
				t[move] = piece
				moves.append(t)
	return moves

Now we need a way of keeping track of all board positions we have seen, so once we find the target we can print the states that led to the solution:

1
2
3
4
5
6
7
8
9
10
11
def evalAll( current, target ):
	next = []
	for a in current:
		n = legalMoves(a[-1])
		for q in n:
			t = list(a)
			t.append(q)
			if ( q == target ):
				return t
			next.append(t)
	return next

This code keeps a list of lists, each sublist being it’s own list of the sequence of moves investigated so far. For each sequence of moves, the next legal moves are discovered and new sequences are added to be investigated the next time this function is called. Technically this is called a breadth-first search because at all of the current legal moves are investigated before moving on the next stage. This is a very simplistic way of doing the job, but in this case the puzzle is small enough that it works well enough.

Finally, a simple wrapper that we can use to set things up and return the final result.

1
2
3
4
5
6
7
def solve(start):
	temp=[[start]]
	end = list(start)
	end.reverse()
	while(temp[-1] != end):
		temp = evalAll(temp, end)
	return temp

So now we can do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
print solve([1, 1, 1, 0, -1, -1, -1])
 
[[1, 1, 1, 0, -1, -1, -1],
 [1, 1, 0, 1, -1, -1, -1],
 [1, 1, -1, 1, 0, -1, -1],
 [1, 1, -1, 1, -1, 0, -1],
 [1, 1, -1, 0, -1, 1, -1],
 [1, 0, -1, 1, -1, 1, -1],
 [0, 1, -1, 1, -1, 1, -1],
 [-1, 1, 0, 1, -1, 1, -1],
 [-1, 1, -1, 1, 0, 1, -1],
 [-1, 1, -1, 1, -1, 1, 0],
 [-1, 1, -1, 1, -1, 0, 1],
 [-1, 1, -1, 0, -1, 1, 1],
 [-1, 0, -1, 1, -1, 1, 1],
 [-1, -1, 0, 1, -1, 1, 1],
 [-1, -1, -1, 1, 0, 1, 1],
 [-1, -1, -1, 0, 1, 1, 1]]

Success!

You might say this is a waste of time since you figured out the problem in your head. Good for you, but try this on for size:

1
[1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1]

What I Did on my Holidays – Labour Weekend 2011

I have lived in Auckland for 14 years and never been further north than Waitangi. A trip north was long overdue.
Looking over the Hokianga Horbour towards the giant dunes
This is the view from Opononi, looking across the mouth of the Hokianga Harbour towards the giant dunes. For $25 you can catch a water taxi to the other side where you can get dropped off with a board perfect for sliding down the steep banks. It sounds painful, but the sand is very soft and you can easily control your speed if not direction.

On a whim, we went to a slightly out-of-the-way shop called Labyrinth Woodworks & Maze (that isn’t a link, it’s a time corridor back to 1996) which turned out to be quite a find. It is a small building filled with the most amazing collection of puzzles and brainteasers I have ever seen, curated by a very passionate puzzle-lover who was only too keen to demonstrate his wares.

A small Japanese Puzzle BoxI have wanted a Japanese Puzzle Box ever since I saw one in a book when I was a child. Now I have one – it takes 10 cunningly concealed steps to open. If I ever go back to Labyrinth Woodworks I will buy the deluxe 21 step box.

Down the road a little way is Waipoua Kauri Forest, home to some very large trees including Tãne Mahuta, which is very, very large indeed.
Tane Mahuta
This is a terrible photo-montage I stitched together using Hugin, it in no way conveys just how big this tree is. I kept expecting a bunch of blue-skinned Navi to show up to defend it.

Sunday night was spent in Doubtless Bay, which was also very nice but not quite as wild and interesting as the west coast. We did take the time to visit Cable Bay, a beautiful beach with pink sand. It is supposed to be packed in Summer, we found it almost deserted (which suited us just fine.)

Opening Narration Quiz

You know what is wrong with television today? Not enough opening narration, that’s what! Back in the day, you could count on the producers to slap a few words together to sum up the premise of the show you were about to see, little tone poems worming their way into the subconscious week after week.

Here is a selection of opening narrations that will surely trigger memories, or at least drive you mad attempting to recall. Post your answers in the comments, no googling!

  1. “A shadowy flight into the dangerous world of a man who does not exist.”
  2. “These men promptly escaped from a maximum security stockade to the Los Angeles underground. Today, still wanted by the government, they survive as soldiers of fortune.”
  3. “It’s a port of call, home away from home for diplomats, hustlers, entrepreneurs, and wanderers. <Redacted> and <redacted> wrapped in two million, five hundred thousand tons of spinning metal, all alone in the night. It can be a dangerous place, but it’s our last, best hope for peace.”
  4. “Fabulous secret powers were revealed to me the day I held aloft my magic sword and said <redacted>”
  5. “By the way my name is Max – I take care of them. Which isn’t easy, ’cause when they met it was murder!”
  6. “The year is 1987, and NASA launches the last of America’s deep space probes.”
  7. “Now the story of a wealthy family who lost everything, and the one son who had no choice but to keep them all together.”
  8. “This is the voice of the <redacted>. We know that you can hear us, Earth man!”
  9. “I am the most powerful weapon of destruction in the two universes”
  10. “There is nothing wrong with your television set. Do not attempt to adjust the picture.”
  11. “Theorizing that one could <redacted> within his own <redacted>, Dr. <redacted> stepped into the <redacted> — and vanished.”
  12. “This is the story of a time long ago, a time of myth and legend. When the ancient gods were petty and cruel, and they plagued mankind with suffering. Only one man dared to challenge their power”
  13. “Transuranic heavy elements may not be used where there is life! Medium atomic weights are available!”
  14. “…and he must let the world think that he is dead, until he can find a way to control the raging spirit that dwells within him…”

Bonus movie narration:

  1. “From the dawn of time we came; moving silently down through the centuries…”

Bonus Bonus Epilogue narration:

  1. “Fleeing from the <redacted> tyranny, the last <redacted>, <redacted>, leads a rag-tag fugitive fleet on a lonely quest.”