So I'm trying to get a little more proficient with Python, and decided that making a maze would be a fun thing to know how to do. I found this page that goes over a bit of how to do it.
create a CellStack (LIFO) to hold a list of cell locations
set TotalCells = number of cells in grid
choose a cell at random and call it CurrentCell
set VisitedCells = 1
while VisitedCells < TotalCells
find all neighbors of CurrentCell with all walls intact
if one or more found
choose one at random
knock down the wall between it and CurrentCell
push CurrentCell location on the CellStack
make the new cell CurrentCell
add 1 to VisitedCells
else
pop the most recent cell entry off the CellStack
make it CurrentCell
endIf
endWhile
Now, I've got the following code, although it isn't much past the obvious stuff in the pseudocode.
class Cell:
top_wall = 0
bottom_wall = 0
left_wall = 0
right_wall = 0
def knock_down(self,wall):
if wall is 'top_wall' and self.top_wall is 0:
self.top_wall = 1
if wall is 'bottom_wall' and self.bottom_wall is 0:
self.bottom_wall = 1
if wall is 'left_wall' and self.left_wall is 0:
self.left_wall = 1
if wall is 'right_wall' and self.right_wall is 0:
self.right_wall = 1
else
return 'Error: Wall Already Gone'
maze = [10][10]
CellStack = [] # LIFO stack to hold list of cell locations
TotalCells = 100 # Number of cells in grid
VisitedCells = 0 # Cells that have been visited
CurrentCell = 0 # The current cell
while VisitedCells < TotalCells:
I'm not sure that the class is the best way to do the cells, but I haven't thought of another way to do it yet. However, I've run into a bit of a problem for checking for the neighbors of a cell. The find all neighbors of CurrentCell with all walls intact is throwing me for a bit of a loop.
How can you check whether cells are neighbors?
You can give each cell a position, stored as two integers. Then, two cells are neighbors if those integers are neighbors.
def isCellNeighbor(c1, c2):
if abs(c1.x - c2.x) == 1: return True
if abs(c1.y - c2.y) == 1: return True
return False
The above considers two cells as being neighbors if at least a corner of each one touches the other. You can tweak it to suit your needs.
PS: have a look at the amazing collection of maze algorithms
Related
I am given a matrix containing only 1's and 0's, where adjacent 1's (horizontal or vertical, NOT diagonal) form rivers. I am asked to return an array of all river sizes in the matrix.
e.g.
(Note the order of the river sizes don't matter- they can be in any order) i.e. [2,1,2,2,5] is also a valid solution!
I am writing the recursive part of the code, where as we explore the matrix, if we stumble on a 1, we will run a recursion to explore its adjacent left, right,up and down for any 1's.
The code is quite lengthy, and I don't believe it is necessary for my question. My question is, as I call on the recursive function, and I update currentRiverSize +1 (initialised as 0) in the argument of the recursive function as we stumble across more 1's, can I then at the end simply append this to the array?
I have a feeling the recursion is not structured correctly!
def findAllRiverSizes(matrix):
riverSizes = []
exploreRiver(matrix,row,col,entryExplored,riverSizes,0):
def exploreRiver(matrix,row,col,entryExplored,riverSizes,currentRiverSize):
#look right:
if col<len(matrix[0])-1 and not entryExplored[row][col+1] and matrix[row][col+1] == 1:
entryExplored[row][col+1] = True
exploreRiver(matrix,row,col+1,entryExplored,riverSizes,currentRiverSize +1)
#look left
if col>0 and not entryExplored[row][col-1] and matrix[row][col-1] == 1:
entryExplored[row][col-1] = True
exploreRiver(matrix,row,col-1,entryExplored,riverSizes,currentRiverSize +1)
#look up
if row >0 and not entryExplored[row-1][col] and matrix[row-1][col] == 1:
entryExplored[row-1][col] = True
exploreRiver(matrix,row-1,col,entryExplored,riverSizes,currentRiverSize +1)
#look down
if row <len(matrix)-1 and not entryExplored[row+1][col] and matrix[row+1][col] == 1:
entryExplored[row+1][col] = True
exploreRiver(matrix,row+1,col,entryExplored,riverSizes,currentRiverSize +1)
riverSizes.append(currentRiverSize)
return riverSizes
The structure of your code doesn't seem to be doing what you describe you want it to be doing.
Some suggestions -
Instead of using the 4 different conditions try to use a single condition at the top which checks for the bounds
Are we allowed to modify the matrix? In that case we can do away without the entryExplored
We don't need to pass the riverSizes to the DFS recursion function(since we only need to append the value to riverSizes once per DFS run), so we can make the function return that value instead.
Here's a simplified code that does what you want -
def findAllRiverSizes(matrix):
def exploreRiverDFS(matrix,row,col):
# go through all neighbors of(row,col) having value 1,
# set the value to 0(or use entryExplored). In the end after
# there are no neighbors append the currentRiverSize to riverSizes
# return the size of this river
# check if current row, col is valid or there is no river in the current cell
if (row < 0 or row >= len(matrix) or col < 0 or col >= len(matrix[row])
or matrix[row][col] == 0):
return 0
matrix[row][col] = 0
return 1 + sum([exploreRiverDFS(matrix, row+1, col),
exploreRiverDFS(matrix, row-1, col),
exploreRiverDFS(matrix, row, col+1),
exploreRiverDFS(matrix, row, col-1)])
riverSizes = []
# iterate through our matrix here, if we come across a 1, call the DFS function
# to go through all its neighboring cells and set them to 0 in matrix itself
# if you are allowed to modify matrix(else you can use entryExplored matrix)
# the exploreRiverDFS function returns the size of current river it traversed through
for row in range(len(matrix)):
for col in range(len(matrix[row])):
if matrix[row][col]:
riverSizes.append(exploreRiverDFS(matrix, row, col))
return riverSizes
Write python code(2.7 version) for the following and also explain the logic because i am not understanding please explain.
Eight houses ,represented as cells , are arranged in a straight line.Each day every cell competes with its adjacent cells(neighbours). An integer value of 1 represents an active cell and a value of 0 represents an inactive cell.If the neighbours on both the sides of a cell are either active or inactive,the cell becomes inactive on the next day; otherwise the cell becomes active.The two cells on each end have a single adjacent cell ,so assume that the unoccupied space on the opposite side is an inactive cell.Even after updating the cell state , consider its previous state when updating the state of other cells. The state information of all cells should be updated simultaneously.
Write an algorithm to output the state of the cells after the given number of days.
==================================================
Input
The input to the function/method consists of two arguments:
states , a list of integers representing the current state of cells ;
days ; an integer representing the number of days.
Output
Return a list of integers representing the state of the cells after the given number of days.
Note
The elements of the list states contains 0s and 1s only.
TESTCASES 1:
INPUT:
[1,0,0,0,0,1,0,0],1
EXPECTED RETURN VALUE:
[0,1,0,0,1,0,1,0]
TESTCASE 2:
INPUT:
[1,1,1,0,1,1,1,1,],2
EXPECTED RETURN VALUE:
[0,0,0,0,0,1,1,0]
==================================================================
def cellCompete(states,days):
#write your code logic with explanation
pass
==================================================================
I tried with following code but its giving the wrong output:
def cellCompete(c,d):
for _ in range(d):
for i in range(8):
n=c[i]
if i>0 and i<7:
c[i]=0 if c[i+1]==a else 1
elif i==0:
c[i]=0 if c[i+1]==0 else 1
else:
c[i]=0 if a==0 else 1
a=n
return c;
You can take advantage of the indexing of lists where lis[-1] wraps around to access the last element.
This function adds an extra inactive cell at the end to make the checking of adjacent cells at the ends of the lists work out.
def cellCompete(c, d):
c = c[:]
for _ in range(d):
q = [0] * len(c)
c.append(0)
for index in range(len(q)):
next_state = 0 if c[index - 1] == c[index + 1] else 1
q[index] = next_state
c = q
return c
Output as both test cases.
I'm working through an 'easy' HackerRank exercise, and I'm trying to apply multiple conditions to items in a list. The 'solution' I attempted appears consistent with others discussed on the site, but does not work. I am interested in learning why it fails, because I cannot discern my error.
The purpose of the function is to count the valleys along a person's walk. The relative elevations of the walk are stored in a string (ie. 'DDUU' for down, down, up, up). The walk begins and finishes at sea level. The function accepts the number of steps 'n' and the route string. In the case above, it should return v = 1, and in fact, it does. However, when I run this on longer cases, the function's returns are incorrect.
def countingValleys(n, s):
valleys = 0
position = 0
positions = []
for step in s:
if step == 'U':
position += 1
else:
position -= 1
positions.append(position)
for position in positions:
if positions[position] < 0 and positions[position+1] == 0:
valleys += 1
return valleys
s = 'DDUUUUDDDDUUDDUU'
v = countingValleys(16, s)
In this case, len(s) = 16 and the number of valleys is 3, but the number returned is 4. I'm trying to understand the error. Examples of new code are appreciated, but I mostly want to know what is wrong within the code above and how that might be adjusted. I am hoping to better understand multiple conditions, not just fix the code.
Thanks in advance!
instead of :
for position in positions:
if positions[position] < 0 and positions[position+1] == 0:
valleys += 1
you need:
for i in range(n):
if positions[i] < 0 and positions[i+1] == 0:
valleys += 1
The following lines of code are erroneous:
for position in positions:
if positions[position] < 0 and positions[position+1] == 0:
And I suppose you wanted to have something like:
for i in range(len(positions)-1):
if positions[position] < 0 and positions[position+1] == 0:
For example: If you have the following
s = 'DDDUUU', then your positions array looks like this: [-1, -2, -3, -2, -1, 0] and you will check position[-2] two times: (position[-2] is the 2nd value of positions read from the right and is -1.)
Both times your if will evaluated to true and thus you get two values and this is surely not intended.
Is it possible to solve tower of hanoi halfway? I've done extensive research to look for codes that solves the user's configuration halfway but I've yet to find one. This is for an assignment and I require the code to take over from where the user has stopped solving and continue solving it for the user, without resetting the puzzle to square one.
I understand that there are recursion algorithms out there readily available but that is not what I'm searching for.
I'm searching for algorithms that can take over from where the user has solved until, and then continue solving from there.
Any ideas?
So far, I've come up with an algorithm that stores the optimized algorithms( which is being done by recursion) into an array, and then checks if the user's input is equal to any found in the array, and then continue solving from there. However, the problem lies when the user's configuration is not found in the optimized algorithm array.
The following are my codes so far ( I've excluded the stack.py codes):
def solveHalfway(n, start, end, middle, count):
gameInstance.stackA = [3,2]
gameInstance.stackB = []
gameInstance.stackC = [1]
loopCounter = 0 # initialise loopCounter as 0
moveCounter = 0 # initialise the move index the user is stuck at
indicator = 0 # to indicate whether the user's config equals the solution's config
while loopCounter < arrayOfStacks.size(): # while loopCounter size has not reached the end of arrayOfStacks
if loopCounter != 0 and loopCounter % 3 == 0: # if 3 stacks have been dequeued
moveCounter += 1
if gameInstance.getUserConfig() == tempStack.data: #check whether user's config is equal to the solution's config
indicator += 1
print "User is stuck at move: ", moveCounter #this will be the current move the user is at
while arrayOfStacks.size() != 0: # while not the end of arrayOfStacks
correctMovesStack.push(arrayOfStacks.dequeue()) # add the moves to correctMovesStack
if correctMovesStack.size() == 3: # if 3 stacks have been dequeued
print "Step:", moveCounter , correctMovesStack.data # display the step number plus the correct move to take
moveCounter+=1 # increase move by 1
while correctMovesStack.size() != 0: # if correct moves stack isn't empty
correctMovesStack.pop() # empty the stack
return
else:
while tempStack.size() != 0: # check if tempStack is empty
tempStack.pop() # empty tempStack so that it can be used for the next loop
tempStack.push(arrayOfStacks.dequeue()) #dequeue from arrayOfStacks for a total of 3 times and push it to tempStack
else:
tempStack.push(arrayOfStacks.dequeue()) #dequeue from arrayOfStacks for a total of 3 times and push it to tempStack
loopCounter +=1 # increase loop counter by 1
if indicator == 0:
moveWith3Towers(noOfDisks, stackA, stackC, stackB, count)
print indicator
To solve the Towers of Hanoi from an arbitrary position, you can use a recursive procedure similar to the standard solution that works from the standard start position.
It just has to be a little more general.
Write a recursive procedure moveDisks(maxSize,targetPeg) that moves all the disks with size <= maxSize to the peg targetPeg, like this:
Find the largest disk m such that m.size <= maxSize and m is not on targetPeg. If there is no such disk, then return, because all the disks with size <= maxSize are already in the right place.
Let sourcePeg be the peg where m is currently, and let otherPeg be the the peg that isn't sourcePeg or targetPeg.
Call moveDisks(m.size-1, otherPeg) recursively to get the smaller disks out of the way.
Move m from sourcePeg to targetPeg.
Call moveDisks(m.size-1, targetPeg) recursively to put the smaller disks where they belong.
In python, I would write it like this. Note that I used a different representation for the game state that works better for this algorithm and doesn't allow any illegal positions:
#
# Solve Towers of Hanoi from arbitrary position
#
# diskPostions -- the current peg for each disk (0, 1, or 2) in decreasing
# order of size. This will be modified
# largestToMove -- move this one and all smaller disks
# targetPeg -- target peg for disks to move
#
def moveDisks(diskPositions, largestToMove, targetPeg):
for badDisk in range(largestToMove, len(diskPositions)):
currentPeg = diskPositions[badDisk]
if currentPeg != targetPeg:
#found the largest disk on the wrong peg
#sum of the peg numbers is 3, so to find the other one...
otherPeg = 3 - targetPeg - currentPeg
#before we can move badDisk, we have get the smaller ones out of the way
moveDisks(diskPositions, badDisk+1, otherPeg)
print "Move ", badDisk, " from ", currentPeg, " to ", targetPeg
diskPositions[badDisk]=targetPeg
#now we can put the smaller ones in the right place
moveDisks(diskPositions, badDisk+1, targetPeg)
break;
Test:
> moveDisks([2,1,0,2], 0, 2)
Move 3 from 2 to 0
Move 1 from 1 to 2
Move 3 from 0 to 1
Move 2 from 0 to 2
Move 3 from 1 to 2
So I'm trying to write a little simulator thing with pygame, but im stuck
I'm trying to make particles that fall and settle but i want them to stack and stop when they hit a wall
This may sound confusing so here is an example:
http://www.coolmath-games.com/0-sugar-sugar/
I want to make particles that resemble the sugar in the game above:
I started by trying:
if pygame.sprite.spritecollideany(self, self.game.block_list):
self.rect.x += 0
self.rect.y += 0
but then the particles just stop and they don't roll down sloped surfaces
also I need to know how to check if a sprite collides with any other sprite in its group
So if anyone knows how I can duplicate this liquid like particle movement in pygame that would be awesome!
Thank You!
As I stated above, I tried to write the exactly same game with pygame too but left it uncompleted.
First of all, I preferred NOT to store these particles as different objects. Instead I used a dictionary to store their coordinates. I made it so because there are HUNDREDS of them and you have to check for collisions ~50 times per second for each of them. If you try to make them all different objects, it may go out of hand at some point.
After you detect a collision, in order to make them roll down sloped surface, let them move diagonally too. First check for the cell below, if that cell is not empty, check for the cells at bottom left and bottom right of the particle.
Btw, I found my function that moves the particles but it is not really readable.
def spawnSugar(spawnPoint) :
global sugarList,mapDict
mapDict[spawnPoint] = 1
sugarList.append(spawnPoint)
def moveAll() :
global mapDict,sugarList
sugarListTmp = sugarList
sugarList = []
for sugarX,sugarY in sugarListTmp :
# m stands for the vertical movement (1 for down, 0 for staying still)
# k stands for horizontal movement (-1 for left, +1 for right)
m = 1
if mapDict[( sugarX , (sugarY+1)%mapSizeY )]==0:
# checks whether the coordinate below this particle is empty
k = randint( -(mapDict[((sugarX-1)%mapSizeX , (sugarY+1)%mapSizeY)]==0) , mapDict[((sugarX+1)%mapSizeX , (sugarY+1)%mapSizeY)]==0 )
# If it is empty; randomly chooses 1 of the 3 coordinates below the particle (1 of them is just below and the other 2 are diagonally below)
elif mapDict[((sugarX-1)%mapSizeX,(sugarY+1)%mapSizeY)]==0 and mapDict[((sugarX-1)%mapSizeX,(sugarY)%mapSizeY)]==0 and mapDict[((sugarX+1)%mapSizeX,(sugarY+1)%mapSizeY)]==0 and mapDict[((sugarX+1)%mapSizeX,(sugarY)%mapSizeY)]==0:
# If the coordinate below the particle is not empty but other 2 diagonals are empty
k = -1 if randint(0,1) else 1 #chooses 1 of them randomly
else : # If at most 1 of these 2 diagonal coordinates are empty
k = (mapDict[((sugarX+1)%mapSizeX,(sugarY+1)%mapSizeY)]==0 and mapDict[((sugarX+1)%mapSizeX,(sugarY)%mapSizeY)]==0) or -(mapDict[((sugarX-1)%mapSizeX,(sugarY+1)%mapSizeY)]==0 and mapDict[((sugarX-1)%mapSizeX,(sugarY)%mapSizeY)]==0)
if not k: # If none of them are empty
m = 0
mapDict[(sugarX,sugarY)] = 0
mapDict[((sugarX+k)%mapSizeX,(sugarY+m)%mapSizeY)] = 1
sugarList.append(((sugarX+k)%mapSizeX,(sugarY+m)%mapSizeY))
# Values to assign before entering the main loop
mapDict = {}
sugarList = []
for x in range(mapSizeX):
for y in range(mapSizeY):
mapDict[(x,y)] = 0