Related
class Stack:
def __init__(self):
self.stack=[]
self.top = None
def empty(self):
return not self.stack
def push(self, item):
self.stack.append(item)
self.top = item
def pop(self):
if self.empty():
a = self.stack.pop()
return a
else:
print("Empty stack")
def printall(self):
print(self.stack)
def clear(self):
self.stack = []
self.top = None
ysj = Stack()
jy = []
list = input().split()
leng = len(list)
num = 0
for i in range(0, leng):
if list[i] == '+' or list[i] == '-':
while ysj.top is not None:
jy.append(ysj.pop())
num = num - 1
ysj.push(list[i])
num = num + 1
elif list[i] == '/' or list[i] == '*':
while ysj.top == '/' or ysj.top == '*':
jy.append(ysj.pop())
num = num - 1
ysj.push(list[i])
num = num + 1
else:
jy.append(int(list[i]))
for i in range(1, num + 1):
jy.append(ysj.pop())
for i in range(0, len(jy)):
print(jy[i], end=" ")
I'm trying to convert the equation from infix form to postfix form using Stack class.
This code works when I type in
1 + 2 * 3
but doesn't work well when I type in
1 * 2 + 3 or 1 * 2 * 3 or 1 + 2 + 3
I think there's something wrong with my while loop but I can't figure out what part is wrong. Please help me.
You forgot to insert None to top when the list gets empty, and you are trying to remove a item when the list is empty:
class Stack:
def __init__(self):
self.stack=[]
self.top = None
def empty(self):
return not self.stack
def push(self, item):
self.stack.append(item)
self.top = item
def pop(self):
if not self.empty(): # remove item only if the stack is not empty
a = self.stack.pop()
# after removing a item, check if the stack is empty
if self.empty(): # if it is, set the top as None
self.top = None
return a
else:
print("Empty stack")
I am trying to implement iterative deepening search for the k - puzzle. I have managed to find the goal node. However, I am unable to backtrack from the goal node to the start node to find the optimal moves. I think it has something to do with repeated states in IDS. Currently, I am keeping track of all visited states in the IDS algorithm.
This is the current implementation of my algorithm. In the code below, moves_dict stores each node's previous state and move to get to current state.
import os
import sys
from itertools import chain
from collections import deque
# Iterative Deepening Search (IDS)
class Node:
def __init__(self, state, empty_pos = None, depth = 0):
self.state = state
self.depth = depth
self.actions = ["UP", "DOWN", "LEFT", "RIGHT"]
if empty_pos is None:
self.empty_pos = self.find_empty_pos(self.state)
else:
self.empty_pos = empty_pos
def find_empty_pos(self, state):
for x in range(n):
for y in range(n):
if state[x][y] == 0:
return (x, y)
def find_empty_pos(self, state):
for x in range(n):
for y in range(n):
if state[x][y] == 0:
return (x, y)
def do_move(self, move):
if move == "UP":
return self.up()
if move == "DOWN":
return self.down()
if move == "LEFT":
return self.left()
if move == "RIGHT":
return self.right()
def swap(self, state, (x1, y1), (x2, y2)):
temp = state[x1][y1]
state[x1][y1] = state[x2][y2]
state[x2][y2] = temp
def down(self):
empty = self.empty_pos
if (empty[0] != 0):
t = [row[:] for row in self.state]
pos = (empty[0] - 1, empty[1])
self.swap(t, pos, empty)
return t, pos
else:
return self.state, empty
def up(self):
empty = self.empty_pos
if (empty[0] != n - 1):
t = [row[:] for row in self.state]
pos = (empty[0] + 1 , empty[1])
self.swap(t, pos, empty)
return t, pos
else:
return self.state, empty
def right(self):
empty = self.empty_pos
if (empty[1] != 0):
t = [row[:] for row in self.state]
pos = (empty[0] , empty[1] - 1)
self.swap(t, pos, empty)
return t, pos
else:
return self.state, empty
def left(self):
empty = self.empty_pos
if (empty[1] != n - 1):
t = [row[:] for row in self.state]
pos = (empty[0] , empty[1] + 1)
self.swap(t, pos, empty)
return t, pos
else:
return self.state, empty
class Puzzle(object):
def __init__(self, init_state, goal_state):
self.init_state = init_state
self.state = init_state
self.goal_state = goal_state
self.total_nodes = 1
self.total_visited = 0
self.max_frontier = 0
self.depth = 0
self.visited = {}
self.frontier_node = []
self.move_dict = {}
def is_goal_state(self, node):
return node.state == self.goal_state
def is_solvable(self):
flat_list = list(chain.from_iterable(self.init_state))
num_inversions = 0
for i in range(max_num):
current = flat_list[i]
for j in range(i + 1, max_num + 1):
next = flat_list[j]
if current > next and next != 0:
num_inversions += 1
if n % 2 != 0 and num_inversions % 2 == 0:
return True
elif n % 2 == 0:
row_with_blank = n - flat_list.index(0) // n
return (row_with_blank % 2 == 0) == (num_inversions % 2 != 0)
else:
return False
def succ(self, node, frontier):
succs = deque()
node_str = str(node.state)
self.visited[node_str] = node.depth
self.total_visited += 1
frontier -= 1
for m in node.actions:
transition, t_empty = node.do_move(m)
transition_str = str(transition)
transition_depth = node.depth + 1
if transition_str not in self.visited or transition_depth < self.visited[transition_str]:
self.total_nodes += 1
transition_depth = node.depth + 1
transition_str = str(transition)
self.move_dict[transition_str] = (node_str, m)
succs.append(Node(transition, t_empty, transition_depth))
frontier += 1
return succs , frontier
def depth_limited(self, node, depth, frontier):
if self.is_goal_state(node):
return node
if node.depth >= depth:
return None
succs, frontier = self.succ(node, frontier)
self.max_frontier = max(self.max_frontier, frontier)
while succs:
result = self.depth_limited(succs.popleft(), depth, frontier)
if result is not None:
return result
return None
def solve(self):
if not self.is_solvable():
return ["UNSOLVABLE"]
goal_node = None
while goal_node is None:
goal_node = self.depth_limited(Node(self.init_state), self.depth, 1)
if goal_node is not None:
break
# reset statistics
self.visited = {}
self.total_nodes = 1
self.move_dict = {}
self.depth += 1
print self.depth
print "out"
print goal_node.state
solution = deque()
init_str = str(self.init_state)
current_str = str(goal_node.state)
while current_str != init_str:
current_str, move = self.move_dict[current_str]
solution.appendleft(move)
print "Total number of nodes generated: " + str(self.total_nodes)
print "Total number of nodes explored: " + str(self.total_visited)
print "Maximum number of nodes in frontier: " + str(self.max_frontier)
print "Solution depth: " + str(self.depth)
return solution
I have been cracking my head for awhile now. I use a hashMap that maps the state string to its depth and when adds the node whenever the same state appears in a shallower depth
EDIT
Optimal solution depth for this test case is 22.
init state: [[1,8,3],[5,2,4],[0,7,6]]
Goal state: [[1,2,3],[4,5,6],[7,8,0]]
im not going to implement your k puzzle but consider the following datastruct
d = {'A':{'B':{'Z':7,'Q':9},'R':{'T':0}},'D':{'G':1}}
def find_node(search_space,target,path_so_far=None):
if not path_so_far: # empty path to start
path_so_far = []
for key,value in search_space.items():
if value == target:
# found the value return the path
return path_so_far+[key]
else:
# pass the path so far down to the next step of the search space
result = find_node(search_space[key],target, path_so_far+[key])
if result:
print("Found Path:",result)
return result
Below is what I have done but it Does not handle the max requirement on insert.
how do I Give the class a max value and check it in the insert and then remove the least significant element. Then figure out what is the least significant element in the implementation.
Having some issues trying to figure this out.
import math
import random
class BinaryHeap:
def __init__(self, array, direction=1, size=100):
if(size > len(array)):
self.size = len(array)
else:
self.size = size;
self.bBinaryHeap = array[:]
if 0 < direction:
self.compare = self.greater
else:
self.compare = self.less
self.buildBinaryHeap()
def node(self, index):
return (index << 1) + 1
def parent(self, index):
return (index - 1) >> 1
def bBinaryHeapifyDown(self, index):
swap = self.bBinaryHeap[index]
while self.node(index) < self.size:
node = self.node(index)
if node + 1 < self.size and self.compare(self.bBinaryHeap[node], self.bBinaryHeap[node + 1]) > 0:
node += 1
if self.compare(swap, self.bBinaryHeap[node]) > 0:
self.bBinaryHeap[index] = self.bBinaryHeap[node];
else:
break
index = node
self.bBinaryHeap[index] = swap
def upheapify(self, index):
while 0 < index and self.compare(self.bBinaryHeap[index], self.bBinaryHeap[self.parent(index)]) < 0:
parent = self.parent(index)
swap = self.bBinaryHeap[parent]
self.bBinaryHeap[parent] = self.bBinaryHeap[index]
self.bBinaryHeap[index] = swap
index = parent
def buildBinaryHeap(self):
indices = range(0, int(self.size / 2))
reversed(indices)
for index in indices:
self.bBinaryHeapifyDown(index)
def insert(self, value):
self.shrink()
index = self.size
self.bBinaryHeap[index] = value
self.size += 1
self.upheapify(index)
def search(self, value):
for index in range(self.size):
if self.bBinaryHeap[index] == value:
return index
def delete(self, value):
index = self.search(value)
self.size -= 1
self.bBinaryHeap[index] = self.bBinaryHeap[self.size]
parent = self.parent(index)
if (index == 0) or (self.compare(self.bBinaryHeap[parent], self.bBinaryHeap[index]) < 0):
self.bBinaryHeapifyDown(index)
else:
self.upheapify(index)
def shrink(self):
capacity = len(self.bBinaryHeap)
if capacity == self.size:
self.bBinaryHeap.extend([0] * capacity)
def greater(self, value1, value2):
if value1 == value2:
return 0
elif value1 < value2:
return 1
elif value1 > value2:
return -1
def less(self, value1, value2):
if value1 == value2:
return 0
elif value1 < value2:
return -1
elif value1 > value2:
return 1
def getLevel(self, index):
return int(math.floor(math.log(index + 1, 2)))
def displayBinaryHeap(self):
printBinaryHeap = str(self.bBinaryHeap)
height = self.getLevel(self.size)
previous = -1
for index in range(self.size):
getLevel = self.getLevel(index)
n = height - getLevel
indent = int(math.pow(2, n + 1) - 2)
spacing = 2 * indent
if getLevel != previous:
printBinaryHeap += '\n'
printBinaryHeap += ' ' * indent
previous = getLevel
else:
printBinaryHeap += ' ' * spacing
printBinaryHeap += '%4d' % self.bBinaryHeap[index]
print(printBinaryHeap)
if __name__ == "__main__":
size =10
array = [random.randint(0, 100) for i in range(size)]
bBinaryHeap = BinaryHeap(array, 1, 100)
print('Binary bBinaryHeap:')
bBinaryHeap.displayBinaryHeap()
Your code has numerous indentation errors. In python, indentation counts.
As for this code:
if 0 < direction:
self.compare = self.greater
else:
self.compare = self.less
self.greater and self.less don't exist. You are doing the equivalent of this:
x = elephant
That's nice, but unless you've set the variable elephant to some value prior to that line, that is an error.
how do I Give the class a max value
class BinaryHeap:
pass
BinaryHeap.max = 10
print(BinaryHeap.max)
--output:--
10
and check it in the insert
class BinaryHeap:
max = 10
def insert(self):
print(self.max)
bh = BinaryHeap()
bh.insert()
--output:--
10
then remove the least significant element
x = 0b1111
print(x) #15
y = x >> 1
print("{:b}".format(y)) #111
print(y) #7
Then figure out what is the least significant element in the implementation
x = 0b1110
print(x) #=>14
b_str = "{:b}".format(x)
print(repr(b_str)) #=> '1110'
for direction in [1, -1]:
if direction > 0:
least_signif = b_str[-1]
else:
least_signif = b_str[0]
print(least_signif)
--output:--
0
1
from informedSearch import *
from search import *
class EightPuzzleProblem(InformedProblemState):
"""
Inherited from the InformedProblemState class. To solve
the eight puzzle problem.
"""
def __init__(self, myList, list = {}, operator = None):
self.myList = list
self.operator = operator
def __str__(self):
## Method returns a string representation of the state.
result = ""
if self.operator != None:
result += "Operator: " + self.operator + ""
result += " " + ' '.join(self.myList[0:3]) + "\n"
result += " " + ' '.join(self.myList[3:6]) + "\n"
result += " " + ' '.join(self.myList[6:9]) + "\n"
return result
def illegal(self):
## Tests whether the state is illegal.
if self.myList < 0 or self.myList > 9: return 1
return 0
def equals(self, state):
## Method to determine whether the state instance
## and the given state are equal.
return ' '.join(self.myList) == ' '.join(state.myList)
## The five methods below perform the tree traversing
def move(self, value):
nList = self.myList[:] # make copy of the current state
position = nList.index('P') # P acts as the key
val = nList.pop(position + value)
nList.insert(position + value, 'P')
nList.pop(position)
nList.insert(position, val)
return nList
def moveleft(self):
n = self.move(-1)
return EightPuzzleProblem(n, "moveleft")
def moveright(self):
n = self.move(1)
return EightPuzzleProblem(n, "moveright")
def moveup(self):
n = self.move(-3)
return EightPuzzleProblem(n, "moveup")
def movedown(self):
n = self.move(+3)
return EightPuzzleProblem(n, "movedown")
def operatorNames(self):
return ["moveleft", "moveright", "moveup", "movedown"]
def enqueue(self):
q = []
if (self.myList.index('P') != 0) and (self.myList.index('P') != 3) and (self.myList.index('P') != 6):
q.append(self.moveleft())
if (self.myList.index('P') != 2) and (self.myList.index('P') != 5) and (self.myList.index('P') != 8):
q.append(self.moveright())
if self.myList.index('P') >= 3:
q.append(self.moveup())
if self.myList.index('P') >= 5:
q.append(self.movedown())
def applyOperators(self):
return [self.moveleft(), self.moveright(), self.moveup(), self.movedown()]
def heuristic():
counter = 0
for i in range(len(self.myList)):
if ((self.myList[i] != goal.myList[i]) and self.myList[i] != 'P'):
## Position of current:
current = goal.myList.index(self.myList[i])
if current < 3: goalRow = 0
elif current < 6: goalRow = 1
else: goalRow = 2
if i < 3: initRow = 0
elif i < 6: initRow = 1
else: startRow = 2
initColumn = i % 3
goalColumn = current % 3
counter += (abs(goalColumn - initColumn) + abs(goalRow - initRow))
return counter
#Uncomment to test the starting states:
init = ['1','3','P','8','2','4','7','6','5'] #A
#init = ['1','3','4','8','6','2','P','7','5'] #B
#init = ['P','1','3','4','2','5','8','7','6'] #C
#init = ['7','1','2','8','P','3','6','5','4'] #D
#init = ['8','1','2','7','P','4','6','5','3'] #E
#init = ['2','6','3','4','P','5','1','8','7'] #F
#init = ['7','3','4','6','1','5','8','P','2'] #G
#init = ['7','4','5','6','P','3','8','1','2'] #H
goal = ['1','2','3','8','P','4','7','6','5'] #goal state
InformedSearch(EightPuzzleProblem(init), EightPuzzleProblem(goal))
I run it and it shows error
line 34, in __str__ result += " " + ' '.join(self.myList[0:3]) + "\n"
TypeError: unhashable type: 'slice'
Any Ideas?
You're setting the "list" to a dictionary as a default value: list = {} in:
def __init__(self, myList, list = {}, operator = None):
and then assigning it to myList with:
self.myList = list
A dictionary cannot be sliced like a list. So when you try to slice it:
self.myList[0:3]
it fails.
I moved this from code review because folks over there suggest this should be posted here
I'm trying to do 8-puzzle using pycharm, I will first generate a 3x3 list and then shuffle it to get the initial board state example:
[1 , 2 , 3 ]
[4 , 5 , 6 ]
[7 , 8 , 9 ]
then I'll do some random moves on it to get the goal board state:
[ 3 , 2 , 1 ]
[ 6 , 5 , 4 ]
[ 9 , 8 , 7 ]
when I set the size to be 3(3x3) it never complete the search, and when I set the size to be 2 it solves but sometimes it will exhaust the frontier list and returns nothing, which should not be possible.
EDIT
I changed the
return Solution (start_node, numExplored, memoryRequired)
to
return Solution (fr_node, numExplored, memoryRequired)
and it always return an solution for 2x2 , 3x3 is still very slow though
I have these code in Python:
def breadthFirstSearch(problem):
"""Search the shallowest nodes in the search tree first."""
frontier = util.Queue()
explored = []
numExplored = 0
memoryRequired = 0
# generate start node
start_node = Node(problem.getStartState(), None, 0, None)
# return immediately if start node is the goal state
if problem.isGoalState(start_node.state):
return Solution(start_node, 0, 0)
# push start node into frontier
frontier.push (start_node)
# while frontier list is not empty
while not frontier.isEmpty():
# get the first-in frontier node from frontier list
fr_node = frontier.pop()
explored.append(fr_node)
# get successor nodes
successors = problem.getSuccessors(fr_node.state)
numExplored += 1
# append into explored list
# if len(successors) >0:
# explored.append(fr_node)
# else:
# explored.append(fr_node)
# for each successor node
for sc_state, sc_action, sc_cost in successors:
# generate successor node
sc_node = Node(sc_state, sc_action, sc_cost, fr_node)
# check for goal state immediately after generate
if problem.isGoalState(sc_node.state): # if found solution
return Solution (sc_node, numExplored, memoryRequired)
# insert successor node into frontier list (if not found in explored and frontier)
if sc_node not in explored and sc_node not in frontier.list:
frontier.push(sc_node)
memoryRequired = max ([memoryRequired, len(frontier.list)+len(explored)])
print ('Frontier size = %d, Explored size = %d, Total size = %d ,Successor Length= %d' %(len(frontier.list), len(explored), len(frontier.list)+len(explored), len(successors)))
return Solution (start_node, numExplored, memoryRequired)
Node is defined as:
class Node:
def __init__(self, state, action, cost, parent):
self.state = state
self.cost = cost
self.action = action
self.parent = parent
if parent is None:
self.totalCost = cost
self.depth = 0
else:
self.totalCost = parent.totalCost + cost
self.depth = parent.depth + 1
def __eq__(self, other):
return hasattr(other,'state') and self.state == other.state
and then there's the file that defines NPuzzle and Puzzle state.
class ActionType:
UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'
Actions = [ActionType.UP, ActionType.DOWN, ActionType.LEFT,
ActionType.RIGHT]
class PuzzleState (SearchState):
def __init__ (self, n, board = None):
self.n = n
self.board = [[j for j in range(n*i,n*i+n)] for i in range(n)]
self.blankCellPos = self.getBlankCellPos()
def __eq__ (self, other):
if self.board == other.board:
return True
else:
return False
def deepCopy(self):
state = copy.deepcopy(self) #PuzzleState(self.n)
return state
def getBlankCellPos (self):
for i in range(self.n):
for j in range(self.n):
if self.board[i][j] == 0:
return (i,j)
def isValidAction (self, action):
(r,c)= self.blankCellPos
if action == ActionType.UP:
if r - 1 < 0:
return False
else:
return True
elif action == ActionType.DOWN:
if r + 1 > self.n-1:
return False
else:
return True
elif action == ActionType.LEFT:
if c - 1 < 0:
return False
else:
return True
elif action == ActionType.RIGHT:
if c + 1 > self.n-1:
return False
else:
return True
def getValidActions (self):
ValidActions = []
for action in Actions:
if(self.isValidAction(action) == True):
ValidActions.append(action)
return ValidActions
def move (self, action):
(r,c) = self.blankCellPos
if action == ActionType.UP:
self.blankCellPos = (r-1,c)
self.board[r][c], self.board[r-1][c] = self.board[r-1][c], self.board[r][c]
elif action == ActionType.DOWN:
self.blankCellPos = (r+1,c)
self.board[r][c], self.board[r+1][c] = self.board[r+1][c], self.board[r][c]
elif action == ActionType.LEFT:
self.blankCellPos = (r, c-1)
self.board[r][c], self.board[r][c-1] = self.board[r][c-1], self.board[r][c]
elif action == ActionType.RIGHT:
self.blankCellPos = (r, c+1)
self.board[r][c], self.board[r][c+1] = self.board[r][c+1], self.board[r][c]
def randomMove (self, numMoves):
#(r,c) = self.board.blankCellPos
ValidActions = []
actions = []
tmp = -1
for num in range(numMoves):
ValidActions = self.getValidActions()
tmp = random.choice(ValidActions)
#remove loopy choices#
if num > 0:
if actions[-1] == ActionType.UP and tmp == ActionType.DOWN:
ValidActions.remove(ActionType.DOWN)
tmp = random.choice(ValidActions)
elif actions[-1] == ActionType.DOWN and tmp == ActionType.UP:
ValidActions.remove(ActionType.UP)
tmp = random.choice(ValidActions)
elif actions[-1] == ActionType.LEFT and tmp == ActionType.RIGHT:
ValidActions.remove(ActionType.RIGHT)
tmp = random.choice(ValidActions)
elif actions[-1] == ActionType.RIGHT and tmp == ActionType.LEFT:
ValidActions.remove(ActionType.LEFT)
tmp = random.choice(ValidActions)
actions.append(tmp)
self.move(tmp)
def randomInitialize (self):
random.shuffle(self.board)
for ii, sublist in enumerate(self.board):
random.shuffle(self.board[ii])
self.blankCellPos = self.getBlankCellPos()
def display (self):
print( ' ',)
#for c in range (self.n):
print (self.board)
#print (' %d' %(c),)
class NPuzzle (SearchProblem):
def __init__ (self, n, startState = None, goalState = None):
self.n = PuzzleState(n)
self.startState = self.n.deepCopy()
self.goalState = self.n.deepCopy()
def randomStartState (self):
self.startState.randomInitialize()
def randomGoalState(self, numMoves):
self.goalState.randomMove(numMoves)
def setStartState (self, startState):
self.startState = startState
def setGoalState (self, goalState):
self.goalState = goalState
def getStartState (self):
return self.startState
def getGoalState (self):
return self.goalState
def isGoalState(self, state):
if state == self.goalState:
return True
else:
return False
def getSuccessors (self, state):
successorlist = []
validActions = state.getValidActions()
for action in validActions:
#if not deep copy what will happen?
successor = state.deepCopy()
successor.move(action)
self.cost = 1
successorlist.append([successor, action, self.cost])
return successorlist
According to what I read and what my lecturer told me , the machine should punch out something around thousands of searches every second but when I run it it only appear to be very fast at the first few thousand nodes and then slows down terribly after that.
I have no idea what's wrong. Any hint will be greatly appreciated.