I have been working on this code and I have tried to debug it for almost a day by now, but I can't seen to find where the problem lies.
I stop the debugger at line 66.
When I step into or over the code I get an error message.
Traceback (most recent call last):
File "/home/johan/pycharm-community-4.5.3/helpers/pydev/pydevd.py", line 2358, in <module>
globals = debugger.run(setup['file'], None, None, is_module)
File "/home/johan/pycharm-community-4.5.3/helpers/pydev/pydevd.py", line 1778, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "/home/johan/sdp/lets_learn_python/20_a_star_algorithm.py", line 87, in <module>
a.solve()
File "/home/johan/sdp/lets_learn_python/20_a_star_algorithm.py", line 66, in solve
closest_child.create_children()
File "/home/johan/sdp/lets_learn_python/20_a_star_algorithm.py", line 48, in create_children
child = StateString(val, self)
File "/home/johan/sdp/lets_learn_python/20_a_star_algorithm.py", line 32, in __init__
self.dist = self.get_dist()
File "/home/johan/sdp/lets_learn_python/20_a_star_algorithm.py", line 40, in get_dist
dist += abs(i - self.value.index(letter))
ValueError: substring not found
This is the code I have been working on.
This is from a tutorial by Trevor Payne.
#!usr/bin/env python
from Queue import PriorityQueue
class State(object):
def __init__(self, value, parent, start=0, goal=0):
self.children = []
self.parent = parent
self.value = value
self.dist = 0
if parent:
self.path = parent.path[:]
self.path.append(value)
self.start = parent.start
self.goal = parent.goal
else:
self.path = [value]
self.start = start
self.goal = goal
def get_dist(self):
pass
def create_children(self):
pass
class StateString(State):
def __init__(self, value, parent, start=0, goal=0):
super(StateString, self).__init__(value, parent, start, goal)
self.dist = self.get_dist()
def get_dist(self):
if self.value == self.goal:
return 0
dist = 0
for i in range(len(self.goal)):
letter = self.goal[i]
dist += abs(i - self.value.index(letter))
return dist
def create_children(self):
if not self.children:
for i in xrange(len(self.goal)-1):
val = self.value
val = val[:i] + val[i+1] + val[i] + val[i+2]
child = StateString(val, self)
self.children.append(child)
class AStarSolver:
def __init__(self,start, goal):
self.path = []
self.visited_queue = []
self.priority_queue = PriorityQueue()
self.start = start
self.goal = goal
def solve(self):
start_state = StateString(self.start, 0, self.start, self.goal)
count = 0
self.priority_queue.put((0, count, start_state))
while not self.path and self.priority_queue.qsize():
closest_child = self.priority_queue.get()[2]
closest_child.create_children()
self.visited_queue.append(closest_child.value)
for child in closest_child.children:
if child.value not in self.visited_queue:
count += 1
if not child.dist:
self.path = child.path
break
self.priority_queue.put(child.dist, count)
if not self.path:
print "Goal of {0} is not possible!".format(self.goal)
return self.path
# ================================
# MAIN
if __name__ == "__main__":
start1 = "acbda"
goal1 = "dabcd"
print "Starting..."
a = AStarSolver(start1, goal1)
a.solve()
for i in xrange(len(a.path)):
print "%d) " % i + a.path[i]
I really hope someone could help me figure this out.
You should process the case when letter doesn't exist in self.value (line 41):
dist += abs(i - self.value.index(letter))
string.index raise an exception when the letter doesnt exist. Better use string.find instead, it gives -1 if the letter not found:
dist += abs(i - self.value.find(letter))
If you want to give another value than -1 , you should test it before using it:
f = self.value.find(letter)
if f == -1:
# DO what you want
Related
Both file is placed into same directory queueLinkedList.py and r6.py
queueLinkedList.py
class Empty(Exception):
pass
class LinkedQueue:
class _node: #which is nested class
__slots__ = '_element','_next'
def __init__(self,element,next):
self._element = element
self._next = next
def __init__(self):
self._head = None
self._tail = None
self._size = 0
def enqueue(self,element):
newest = self._node(element,None)
if self.is_empty():
self._head = newest
else:
self._tail._next = newest
self._tail = newest
self._size += 1
and
r6.py
from queueLinkedList import LinkedQueue,Empty
class LinkedQueue1(LinkedQueue):
def rotate(self):
if self._size > 1:
self._tail._next ,self._tail = self._head , self._head
p = self._head._next
self._tail._next = None
self._head = p
a = LinkedQueue1()
for i in range(5):
a.enqueue(i)
a.rotate()
I get this type of error:
Traceback (most recent call last):
File "c:/Users/ATMAN/Desktop/python2/Exercise_of_ds/chapter7/exercise/r7.py", line 28, in <module>
a.enqueue(i)
File "c:\Users\ATMAN\Desktop\python2\Exercise_of_ds\chapter7\exercise\queueLinkedList.py", line 31, in enqueue
newest = self._node(element,None)
File "c:\Users\ATMAN\Desktop\python2\Exercise_of_ds\chapter7\exercise\queueLinkedList.py", line 13, in __init__
self._element = element
AttributeError: '_node' object has no attribute '_element
why i can not use element of the nested class _node into inheritance class
if should i declare init() method in child class then tell how should i declare ?
Is there a more suitable way to retrieve a range (difference between highest and lowest number) from this Binary Search Tree? I've tried returning the difference between the max & min value in the range function but nothing is working.
Here's my code:
# %load bst.py
class Node:
def __init__(self, data):
self.data = data
self.left_child = None
self.right_child = None
# self.parent = None
class BST:
def __init__(self):
self.root = None # the root of the tree
def insert(self, new_node):
if self.root is None: # is the tree empty?
self.root = new_node # if yes, new node becomes the root
return
self.insertNode(self.root, new_node)
def insertNode(self, root, new_node):
if new_node.data > root.data:
if root.right_child is not None: # does right child exist?
self.insertNode(root.right_child, new_node)
else:
root.right_child = new_node # new node becomes right child
return
else: # case where new_node.data <= root.data
if root.left_child is not None: # does left child exist?
self.insertNode(root.left_child, new_node)
else: # left child does not exist
root.left_child = new_node
# assignment starts here
def postOrder(self, node):
if node.left_child is not None: # does the left child exist?
self.postOrder(node.left_child)
if node.right_child is not None: # checking if right child exists
self.postOrder(node.right_child)
print(node.data) # visit the node
# finding maxmum of the array
def findMax(self, node):
if node.right_child is not None: # does the right child exist?
return self.findMax(node.right_child)
print(node.data) # visit the node
# finding minmum of the array
def findMin(self, node):
if node.left_child is not None: # check if left child exist
return self.findMin(node.left_child)
print(node.data) # visit the node
# finding range
def range(numbers=[8, 87]):
import statistics
statistics.range
return max(numbers) - min(numbers)
my_bst = BST()
l = [31, 67, 26, 29, 50, 15, 58, 8, 49, 87, 20]
for n in l:
n1 = Node(n)
my_bst.insert(n1)
print('maxmum of the array is')
my_bst.findMax(my_bst.root)
print('minmum of the array is')
my_bst.findMin(my_bst.root)
print('postOrdering the array follows')
my_bst.postOrder(my_bst.root)
print('range is')
my_bst.range(my_bst.root)
I've attempted but I keep getting the following error:
Traceback (most recent call last):
File "main.py", line 76, in <module>
my_bst.range(my_bst.root)
TypeError: range() takes from 0 to 1 positional arguments but 2 were given`
The range fonction should be a method, so you need to define the self parameter as the first argument of the function, like this:
class BST:
[...]
# finding range
def range(self, numbers=[8, 87]):
import statistics
statistics.range
return max(numbers) - min(numbers)
Notice that this is not a good practice to have a mutable parameter because it is not in the local scope of the function. You can fix this as bellow:
def range(self, numbers=None):
if numbers is None:
numbers = [8, 87]
import statistics
statistics.range
return max(numbers) - min(numbers)
In short, you can also write:
# finding range
def range(self, numbers=None):
numbers = numbers or [8, 87]
import statistics
statistics.range
return max(numbers) - min(numbers)
It is better to import statistics globally, like this:
import statistics
class BST:
[...]
# finding range
def range(self, numbers=None):
numbers = numbers or [8, 87]
statistics.range
return max(numbers) - min(numbers)
Notice that the statistics.range function is not called because you forget the parenthesis (and the parameters). So this is dead code.
In your main program, you try to call my_bst.range() with a my_bst.root which is a Node instance. So, you'll have a error when calculating max/min on a Node:
Traceback (most recent call last):
File "...", line 75, in <module>
my_bst.range(my_bst.root)
File "...", line 59, in range
return max(numbers) - min(numbers)
TypeError: 'Node' object is not iterable
You need to develop your algorithm by yourself.
You design doesn't make much sense. The reason you would have a separate BST class is so that you can write methods over trees that don't rely on recursion. If you're going to rely on recursion, then it makes more sense to just have a Node class, because every node is itself a binary tree.
Here's how I would rewrite the findMin, findMax and range methods of BST
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
class BST:
def __init__(self):
self.root = None
def insert(self, value):
if self.root is None:
self.root = Node(value)
else:
curr_node = self.root
while True:
if value < curr_node.data:
if curr_node.left is None:
curr_node.left = Node(value)
return
else:
curr_node = curr_node.left
elif value > curr_node.data:
if curr_node.right is None:
curr_node.right = Node(value)
return
else:
curr_node = curr_node.right
else:
return
def min(self):
if self.root is None:
raise TypeError("Empty Tree")
curr_node = self.root
while curr_node.left is not None:
curr_node = curr_node.left
return curr_node.data
def max(self):
if self.root is None:
raise TypeError("Empty Tree")
curr_node = self.root
while curr_node.right is not None:
curr_node = curr_node.right
return curr_node.data
def range(self):
return self.max() - self.min()
my_bst = BST()
l = [31, 67, 26, 29, 50, 15, 58, 8, 49, 87, 20]
for v in l:
my_bst.insert(v)
print(my_bst.range()) # 79
I am a starter & want to integrate dfs code with Fibonacci series generating code. The Fibonacci code too runs as dfs, with calls made from left to right.
The integration is incomplete still.
I have two issues :
(i) Unable to update 'path' correctly in fib(), as the output is not correctly depicting that.
(ii) Stated in fib() function below, as comment.
P.S.
Have one more issue that is concerned with program's working:
(iii) On modifying line #16 to: stack = root = stack[1:]; get the same output as before.
import sys
count = 0
root_counter = 0
#path=1
inf = -1
node_counter = 0
root =0
def get_depth_first_nodes(root):
nodes = []
stack = [root]
while stack:
cur_node = stack[0]
stack = stack[1:]
nodes.append(cur_node)
for child in cur_node.get_rev_children():
stack.insert(0, child)
return nodes
def node_counter_inc():
global node_counter
node_counter = node_counter + 1
class Node(object):
def __init__(self, id_,path):
self.id = node_counter_inc()
self.children = []
self.val = inf #On instantiation, val = -1, filled bottom up;
#except for leaf nodes
self.path = path
def __repr__(self):
return "Node: [%s]" % self.id
def add_child(self, node):
self.children.append(node)
def get_children(self):
return self.children
def get_rev_children(self):
children = self.children[:]
children.reverse()
return children
def fib(n, level, val, path):
global count, root_counter, root
print('count :', count, 'n:', n, 'dfs-path:', path)
count += 1
if n == 0 or n == 1:
path = path+1
root.add_child(Node(n, path))
return n
if root_counter == 0:
root = Node(n, path)
root_counter = 1
else:
#cur_node.add_child(Node(n, path)) -- discarded for next(new) line
root.add_child(Node(n, path))
tmp = fib(n-1, level + 1,inf, path) + fib(n-2, level + 1,inf,path+1)
#Issue 2: Need update node's val field with tmp.
#So, need suitable functions in Node() class for that.
print('tmp:', tmp, 'level', level)
return tmp
def test_depth_first_nodes():
fib(n,0,-1,1)
node_list = get_depth_first_nodes(root)
for node in node_list:
print(str(node))
if __name__ == "__main__":
n = int(input("Enter value of 'n': "))
test_depth_first_nodes()
Want to add that took idea for code from here.
Answer to the first question:
Path in this particular question is an int. It is a numbering of path from the root to a leaf in a greedy dfs manner.
This can be achieved by letting path be a global variable rather than an input to fib function. We increment the path count whenever we reach a leaf.
I have also modified the fib function to returns a node rather than a number.
import sys
count = 0
root_counter = 0
path=1
inf = -1
node_counter = 0
root = None
def node_counter_inc():
global node_counter
node_counter = node_counter + 1
print("node_counter:", node_counter)
return node_counter
class Node(object):
def __init__(self, id__,path):
print("calling node_counter_inc() for node:", n )
try:
self.id = int(node_counter_inc())
except TypeError:
self.id = 0 # or whatever you want to do
#self.id = int(node_counter_inc())
self.val = inf #On instantiation, val = -1, filled bottom up;
#except for leaf nodes
self.path = path
self.left = None
self.right = None
def __repr__(self):
return "Node" + str(self.id) + ":"+ str(self.val)
def fib(n, level, val):
# make fib returns a node rather than a value
global count, root_counter, root, path
print('count :', count, 'n:', n, 'dfs-path:', path)
count += 1
if n == 0 or n == 1:
path = path+1
new_Node = Node(n, path)
new_Node.val = n
return new_Node
#root.add_child(new_Node)
# return new_node
#if root_counter == 0:
# root = Node(n, path)
# root_counter = 1
#else:
#cur_node.add_child(Node(n, path)) -- discarded for next(new) line
# root.add_child(Node(n, path))
#tmp = fib(n-1, level + 1,inf) + fib(n-2, level + 1,inf)
#Issue 2: Need update node's val field with tmp.
#So, need suitable functions in Node() class for that.
#print('tmp:', tmp, 'level', level)
#return tmp
ans = Node(n, path)
ans.left = fib(n-1, level + 1, inf)
ans.right = fib(n-2, level + 1, inf)
ans.val = ans.left.val + ans.right.val
print("the node is", ans.id, "with left child", ans.left.id, "and right child", ans.right.id)
print("the corresponding values are", ans.val, ans.left.val, ans.right.val)
return ans
def test_depth_first_nodes():
ans = fib(n,0,-1)
print("The answer is", ans.val)
#node_list = get_depth_first_nodes(root)
#for node in node_list:
# print(str(node))
if __name__ == "__main__":
n = int(input("Enter value of 'n': "))
test_depth_first_nodes()
I'm a python/programming newb, and I am self-learning python. Unfortunately I'm really stuck! I'm in chapter 19 of "How to Think Like a Computer Scientist".
The object here is to write an implementation of a Priority Queue ADT, using a linked list.
I'm getting an error at lines 22 and 32. My understanding of this error, is that one or more of my node objects do not have the attribute "cargo". I don't understand this, as all of my node objects are assigned a cargo of "None", or some number, when they are created. The node object is written as it was given in the book.
I should mention, that LINE 31 works FINE. I only have a problem when I add LINE 32, which calls LINE 22 (which is apparently where the problem is hiding) that I get an error.
Any insight would be helpful. Thank you so much!!!
I reproduced the problem on a smaller scale:
class Node:
def __init__(self, cargo= None, next = None):
self.cargo = cargo
self.next = next
class Priority_Queue_For_Linked():
def __init__ (self):
self.max = None
self.nextmax = None
self.min = None
self.length = 0
def insert (self, cargo):
node = Node(cargo)
if self.length == 0:
node = self.max = self.min
self.length = 1
return
if node.cargo > self.max.cargo: # <--LINE 22
notmaxanymore = self.max
notmaxanymore.next = node
node = self.max
self.nextmax = notmaxanymore
self.length += 1
return
testlist = Priority_Queue_For_Linked()
testlist.insert(12)
testlist.insert(22) # <--LINE 32
And here is the error:
=== RESTART: /Users/Desktop/Programming Career/Untitled6.py ===
Traceback (most recent call last):
File "/Users/Desktop/Programming Career/Untitled6.py", line 31, in <module>
testlist.insert(22)# <--line 32
File "/Users/Desktop/Programming Career/Untitled6.py", line 21, in insert
if node.cargo > self.max.cargo:# <--line 22
AttributeError: 'NoneType' object has no attribute 'cargo'
I doubt you need more context, but in case it helps, here is all of the code:
class Node:
def __init__(self, cargo= None, next = None):
self.cargo = cargo
self.next = next
def __str__(self):
return str(self.cargo)
def print_backward (self):
if self.next != None:
tail = self.next
tail.print_backward()
print self.cargo,
def print_list(node):
while node:
print node,
node = node.next
print
class Priority_Queue_For_Linked():
def __init__ (self):
self.max = None
self.nextmax = None
self.min = None
self.length = 0
def is_empty (self):
if self.length == 0:
print "List is empty."
def insert (self, cargo):
node = Node(cargo)
if self.length == 0:
node = self.max = self.min
self.length = 1
return
if node.cargo > self.max.cargo:########40
notmaxanymore = self.max
notmaxanymore.next = node
node = self.max
self.nextmax = notmaxanymore
self.length += 1
return
if node.cargo < self.min.cargo:
notminanymore = self.min
node.next = notminanymore
node = self.min
self.length += 1
return
else:
comparisonnode = self.min.next
comparisonprev = self.min
for i in range (2, self.length):
if node.cargo < comparisonnode.cargo:
node.next = comparisonnode
comparisonprev.next = node
self.length += 1
break
comparisonnode = comparisonnode.next
comparisonprev = comparisonprev.next
def remove (self):
maxtoremove = self.max
self.max = self.nextmax
self.max.next = None
length -=1
return maxtoremove.cargo
def print_list(self):
tempnode = self.min
print "[",
while not tempnode == None:
print tempnode,
tempnode = tempnode.next
print "]"
testlist = Priority_Queue_For_Linked()
testlist.insert(12)
testlist.insert(22)#######86
When you insert your first item you have a problem in your assignments:
if self.length == 0:
node = self.max = self.min
self.length = 1
return
This will not change the value of self.max or self.min and they will stay as None, which of course won't have cargo. You also lose the node you are trying to add. I assume you wanted to do this:
self.max = self.min = node
The max attribute of the Priority_Queue_For_Linked class is defined as None in the __init__ method, and isn't changed before that if statement.
I presume you intended to assign a Node as the value of that attribute at some point, but you haven't done so.
You code tries to do self.max.cargo. In your __init__, you set self.max to None, and you never change this value anywhere else, so self.max is None. If you want to be able to use self.max, you need to set it to a real node value at some point.
this is python file im trying to make A*algorithm , but cant get it to work, I need some help , its an awesome code , its been run in latest python version for windows
from queue import PriorityQueue
class State(object):
def _init_(self,value,parent,start = 0,goal = 0):
self.children = []
self.value = value
self.parent = parent
self.dist = 0
if parent:
self.path = parent.path[:]
self.path.append(value)
self.start = parent.start
self.goal = parent.goal
else:
self.path = [value]
self.start = start
self.goal = goal
def GetDist(self):
pass
def CreateChildren(self):
pass
class State_String(State):
def _init_(self,value,parent,start = 0,goal = 0):
super(State_String,self).__init__(value,parent,start,goal)
self.dist = self.GetDist()
def GetDist(self):
if self.value == self.goal:
return 0
dist = 0
for i in range(len(self.goal)):
letter = self.goal[i]
dist += abs(i - self.value.index(letter))
return dist
def CreateChildren(self):
if not self.children:
for i in xrange(len(self.goal)-1):
val = self.value
val = val[:i] + val[i+1] + val[i] + val[i+2:]
child = State_String(val,self)
self.children.append(child)
class AStar_Solver:
def _init_(self,start,goal):
self.path = []
self.visitedQueue = []
self.priorityQueue = PriorityQueue()
self.start = start
self.goal = goal
def Solve(self):
startState = State_String(self.start,0,self.start,self.goal)
count = 0
self.priorityQueue.put((0,count,startState))
while(not self.path and self.priorityQueue.qsize()):
closestChild = self.priorityQueue.get()[2]
closestChild.CreateChildren()
self.visitedQueue.append(closestChild.value)
for child in closestChild.children:
if child.value not in self.visitedQueue:
count +=1
if not child.dist:
self.path = child.path
break
self.priorityQueue.put((child.dist,count,child))
if not self.path:
print "Goal of " + self.goal + " is not possible!"
return self.path
if _name_ == '__main__':
start1 = "hma"
goal1 = "ham"
a = AStar_Solver(start1,goal1)
a.Solve()
for i in xrange(len(a.path)):
print " %d)" %i + a.path[i]
getting these errors:
Traceback (most recent call last):
File "C:/Users/Herby/Desktop/untitled/Astar.py", line 82, in <module>
a.Solve()
File "C:/Users/Herby/Desktop/untitled/Astar.py", line 59, in Solve
startState = State_String(self.start,0,self.start,self.goal)
TypeError: object() takes no parameters
I need to know how it can be fixed
All of your init in your classes are written with single underscore instead of double underscore:
Change all init written as: _init_ to __init__
Also, this line is incorrect as well:
if _name_ == '__main__':
It needs to be double underscore for name as well
if __name__ == '__main__':
If you're interested, here is more information on why this is needed:
https://www.python.org/dev/peps/pep-0008/
In particular look at the description for: "double_leading_and_trailing_underscore"