About coding this binary tree in Python - python

I have a question about coding up a binary tree, and I'm currently stuck on it.
Basically, the algorithm is as follows where at the initial node, we have the following objects: 1,2,3 placed in order as (None,2,3) with object 3 > object 2 > object 1. In each stage of the tree, one object can move to their immediate right or left and be placed with another object if that object that is moving is smaller than the object that is placed at the current position. If the position to the immediate right or left has a None position, then only the smallest number may move over from the right or left position. For example, it is possible to have the events of (None,0,2+3) and (None,1+2,3) after the initial node.
Hence, the tree is as follows:
I am wondering how to code this up in Python. I dont really care about the replicating events so at each point, I am only interested in the unique tuples/events that occurs.
Im not sure but a rough idea I have is to do this:
def recursion():
pos = list(range(1,4))
index = 0
values = list(range(1,4))
tree = []
if pos[index+1] > pos[index]:
pos[index + 1] -= pos[index+1]
pos[index + 2] += pos[index+1]
tree.append(pos)
if pos[index+1] < pos[index]:
pos[index+1] += pos[index]
pos[index] -= pos[index]
tree.append(pos)
else:
recursion()
return tree
Any help would be greatly appreciated.

Related

Create a Tree of Object Recursively (Python)

i would like to create a tree of objects called State.
Each State has a list of 4 robots and each states have differents robots coordinates.
The goal is to create a graph which will be solved by a Breadth First Search Algorithm.
(The original game is RicochetRobot maybe you guys know it).
class State:
def __init__(self,parent,childs,robots,cpt,):
self.parent = parent
self.childs = childs
self.robots = robots
self.cpt = cpt
I created a function create_child to do this
def create_child(self,depth):
#UP
#Depth is the tree height
if depth==0:
print("STOP")
return
else :
for i in range(4):
#Copying the robots of the current object
temp = copy.deepcopy(self.robots)
#Getting robot to move index
temp_robot = temp[i]
#removing this robot from the list
temp.pop(i)
#Moving up the robot and inserting it in the list
#Moving up is a simple function which increment the y of the robot
temp.insert(i,moving_up(temp_robot,create_board(init_robot())))
#Adding a new child into childs list
self.childs.append(State(self,self.childs,temp,self.cpt+1))
#Decrementing the depth
depth-=1
#Recursivity
for child in self.childs:
child.create_child(depth)
My problem is that when depth = 0 , it print STOP,but it doesnt return None, and the function keep going.
Anynone knows from where it come froms?
Also, if you can give advice on how to make my tree in an easier way it would be nice.
Alright so i think i found a solution , here it is :
depth = 1
parent = Initial_State
for j in range(depth):
for i in range(len(parent.childs)-1):
parent.childs[i].create_child()
parent = parent.childs[i]
It seems to be working. I dont use recursion anymore, i do it in a more iterative way and outside the function and it seems good.
Thank you

Why my solution is unable to solve 8puzzle problem for boards that require more than 1 move?

I am trying to solve 8 puzzle problem in python given here in this assignment -https://www.cs.princeton.edu/courses/archive/fall12/cos226/assignments/8puzzle.html
My goal state is a little different from what is mentioned in the assignment -
#GOAL STATE
goal_state = [[0,1,2],[3,4,5],[6,7,8]]
The buggy part, it seems, is the isSolvable function. It is implemented correctly but while testing the board, it considers the goal state to be the one in which relative order is maintained and blank can be anywhere. So it might be the case that a board is solvable but it might not lead to the current defined goal state. So I am unable to think of a method in which I can test for all the possible goal states while running the solver function *
Also, my solver function was wrongly implemented. I was only considering the neighbor which had the minimum manhattan value and when I was hitting a dead end, I was not considering other states. This can be done by using a priority queue. I am not exactly sure as to how to proceed to implement it. I have written a part of it(see below) which is also kind of wrong as I not pushing the parent into the heap. Kindly provide me guidance for that.
Here is my complete code -
https://pastebin.com/q7sAKS6a
Updated code with incomplete solver function -
https://pastebin.com/n4CcQaks
I have used manhattan values to calculate heuristic values and hamming value to break the tie.
my isSolvable function, manhattan function and solver function:
isSolvable function -
#Conditions for unsolvability -->
#https://www.geeksforgeeks.org/check-instance-8-puzzle-solvable/
def isSolvable(self):
self.one_d_array = []
for i in range(0,len(self.board)):
for j in range(0,len(self.board)):
self.one_d_array.append(self.board[i][j])
inv_count = 0
for i in range(0,len(self.one_d_array)-1):
for j in range(i+1, len(self.one_d_array)):
if (self.one_d_array[i] != 0 and self.one_d_array[j] != 0 and self.one_d_array[i] > self.one_d_array[j]):
inv_count = inv_count + 1
if(inv_count % 2 == 0):
print("board is solvable")
return True
else:
print("board is not solvable")
return False
Manhattan function
def manhattan_value(self,data=None):
manhattan_distance = 0
for i in range(0,len(data)):
for j in range(0,len(data)):
if(data[i][j] != self.goal_state[i][j] and data[i][j] != 0):
#correct position of the element
x_goal , y_goal = divmod(data[i][j],3)
manhattan_distance = manhattan_distance + abs(i-x_goal) + abs(j-y_goal)
return manhattan_distance
Updated Solver function
#implement A* algorithm
def solver(self):
moves = 0
heuristic_value = []
prev_state = []
curr_state = self.board
output = []
heap_array = []
store_manhattan_values = []
if(curr_state == self.goal_state):
print("goal state reached!")
print(curr_state)
print("number of moves required to reach goal state --> {}".format(moves))
else:
while(True):
min_heuristic_value = 99999999999
min_pos = None
moves = moves + 1
output = self.get_neighbours(curr_state)
for i in range(len(output)):
store_manhattan_values.append([self.manhattan_value(output[i]),i])
#print(store_manhattan_values)
for i in range(len(store_manhattan_values)):
heapq.heappush(heap_array,store_manhattan_values[i])
#print(heap_array)
#print(heapq.heappop(heap_array)[1])
#if(moves > 1):
# return
return
Please refer to the PASTEBIN link for complete code and all the references (https://pastebin.com/r7TngdFc).
Updated code with incomplete solver function -
https://pastebin.com/n4CcQaks
In the given link for my code (based on my tests and debugging so far) -
These functions are working correctly - manhatten_value, hamming_value, append_in_list, get_neighbours
What does these functions do -
isSolvable - tells if the board can be solved or not
manhattan_value - calculates the manhattan value of the board passed to it.
hamming_value - calculates the hamming value of the board passed to it.
append_in_list - helper function for getting neighbours. It swaps values then save the resultant state in an array and then reswaps them to return to original position for further swapping and getting other possible states.
get_neighbours - gets all the possible neighbors which can be formed by swapping places with blank element(0 element).
solver - implements the A* algorithm
I am unable to find my mistake. Kindly guide me in this problem. Thank you in advance for your help!
I am apologizing in advance as I am unable to produce a minimal version of my code for this problem. I can not think of any way to use all the functions and produce a minimal version of the code.
(Note, this answer is different than the earlier revision about which many of the comments below were relating to.)
I don't see how the current code implements a queue. It seems like the while loop in the solver picks one new board state each time from a list of possible moves, then considers the next list generated by this new board state.
On the other hand, a priority queue, from what I understand, would have all the (valid) neighbours from the current board state inserted into it and prioritised such that the next chosen board state to be removed from the queue and examined will be the one with highest priority.
(To be completely sure in debugging, I might add a memoisation to detect if the code ends up also revisiting board states -- ah, on second thought, I believe the stipulation in the assignment description that the number of current moves be added to the priority assignment would rule out the same board state being revisited if the priority queue is correctly observed, so memoisation may not be needed.)

Perfect Binary Tree with correct data

I am having a problem trying to fill the data a perfect binary tree with a known number of nodes with the correct data. Basically, I have an implementation that creates this:
7
5 6
1 2 3 4
However, I am looking to create a tree like this:
7
3 6
1 2 4 5
My current implementation for inserting the nodes of a tree is as follows.
def _add_node(self, val, ref = None):
# reference to root of tree
ref = self.root if ref is None else ref
if ref.right is None:
ref.right = Node(val, ref)
return
elif ref.left is None:
ref.left = Node(val, ref)
return
else:
parent = (val - 1) / 2
if parent % 2 == 0:
self._add_node(val, ref.left)
else:
self._add_node(val, ref.right)
Given x nodes I create a tree using range(x) and calling add_node(i) for each iteration. This works fine except its order is incorrect.
For the life of me I cannot figure out an easy way to set the values to represent the bottom layout rather than the top. Can anyone help me out?
This seems to be an issue with the order that you are entering data in. How are you passing in the data?
Also think about your implementation. You check to see whether the right child is empty and if it is you place the node there. However, if it isn't you move on to the left node. This is where the issue is happening.
Assuming you are passing in the data in reverse chronological order you start with 7 at the root. Then you move to 6 which you place in the right node. Then move on to 5; you check to see whether the right node is empty, which is isn't because it is filled with 6, so you move on to check if the left node is empty and find that it is. So you place 5 there.
Do you see the issue?
You need to figure out a way to get around this issue, but hopefully this was good in helping you debug.
Good Luck!

Recursion and Binary Trees

#Get length of the longest path through recursion
def max_height(node):
if not node:
return 0
left = max_height(node.left) #Base Case based on my understanding
right = max_height(node.right) #Base Case based on my understanding
return max_height(left, right) + 1
I keep calling the max_height to get the length but I'm getting an error. I've thought of three possibilities:
1) I misunderstand the concept of the base case and I don't actually have a base case.
2) I'm not properly spacing Python code.
3) I'm not recursively getting the height of the BST at all but rather the width of the tree, which is affecting later calculations.
I know it is similar to this question, but the main difference is that I'm really trying to use recursion , where the other question used iteration and merely called it recursion.
how to find the height of a node in binary tree recursively
The base case is where the recursion stops and you have one: not node (node == None)
I don't see an issue with the spacing... Make sure you use only tabs or only spaces
This does produce the height: the number of nodes from root to leaf along the longest root-leaf path. At every node level, you add 1, and follow the higher subtree.
def max_height(node):
if not node: # this is the base case:
return 0 # where all recursive calls eventually stop
left = max_height(node.left) # <- these are the recursive calls:
right = max_height(node.right) # <- function x is called inside function x
return max(left, right) + 1 # max here, not max_height
Note that this is merely a more verbose version of this answer to the question you linked.
All answered were right but, I faced little problem while writing inside the class;
So, the code goes like this, I hope this helps.
class Tree(object):
def height(self, root):
if root == None: #root == None
return 0
else:
return 1 + max(self.height(root->left), self.height(root->left))
t = Tree()
t.height(t)

Count repetitive node in Binary Search Tree

I am trying to write a function to count the repetitive node in a Binary Search Tree (assume that this tree accept repetition). Here is a line of code that I have
def count(treeroot,item,y):
if treeroot==None:
return 0
elif treeroot.getData()==item:
return 1
else:
return count(treeroot.getLeft(),item,y)+count(treeroot.getRight(),item,y)
where y is the starting number of the search (such as search for how many 10 in the tree, we do count(treeroot,10,0)
However, I tried to put 3 number 10 in and I only receive back the count of 1.
Can anyone tell me what is wrong with my code and how to fix it
You stop recursing down the tree as soon as you found the first item. You need to keep recursing:
def count(treeroot,item,y):
if treeroot==None:
return 0
elif treeroot.getData()==item:
return 1 + count(treeroot.getLeft(),item,y)+count(treeroot.getRight(),item,y)
else:
return count(treeroot.getLeft(),item,y)+count(treeroot.getRight(),item,y)
I hope you see the problem with your algorithm though: You will visit each and every node of the tree, even if you know that there will be no 10s to the left of 9s or to the right of 11s.

Categories