Tree Building Logic Trouble - python

I am writing a simple app that incorporates a tree that represents the English language. I have done something similar in C++, but this is my first venture at building a tree in Python.
englishWords = []
englishFile = open("english.txt")
for line in englishFile:
englishWords.append(line.rstrip())
class Node:
def __init__(self, value):
self.Value = value
self.checked = False
self.Pointers = []
self.numPointers = 0
def addNode(self, value):
x = Node(value)
self.Pointers.append(x)
return x
headString = "HEAD"
Head = Node(headString)
def buildPointers(parent, info, nodeList):
x = 0
y = len(nodeList)
while x < y :
if parent.numPointers == 0:
newNode = parent.addNode(info)
parent.numPointers = parent.numPointers + 1
buildPointers(newNode, nodeList[x+1], nodeList)
break
else:
for i in parent.Pointers:
if info == i.Value:
buildPointers(i, nodeList[x+1], nodeList)
continue
else:
newNode = parent.addNode(info)
parent.numPointers = parent.numPointers + 1
buildPointers(newNode, nodeList[x+1], nodeList)
continue
def treeBuild(lyst):
for i in lyst:
iList = list(i)
buildPointers(Head, iList[0], iList)
treeBuild(englishWords)
As soon as I run the code Windows says "python.exe has stopped running" it's probably something simple that I have overlooked, so feel free to rip into me or the way I wrote this. I would love any criticism that will help make me a better programmer.

Basically this isn't really pythonic, numerous errors here but I guess the main issue would be using too much recursion, something python "out of the box" isn't very good at.
It limits default recursion depth to 1000 steps. and you probably need more. here is a question and answer explaining how to change this default.
also another good advice would be changing the recursion to use generators like in this blog post
p.s: since you don't change the value of x the while loop might run forever in some cases wouldn't it? (I didn't fully understand the algorithm so I'm not sure)
EDIT: to make this a little more pythonic I would change the populating part to use with context manager:
with open("english.txt") as english_file:
for line in english_file ..
BTW a much better way, not loading million strings into a list would be changing the populating part to a generator function, yielding an english word everytime - much more efficient and pythonic. you can read about context managers and generator functions here
Another edit: learining idiomatic python The best place to start would be opening a python shell and:
import this
the "zen of python" would appear.
a good opinionated guide to modern python development including libs, best practice, reading recommendations and writing idomatic python would be Hitchhikers guide to python by kenneth reitz.
and a similar source, more focused one, is writing idiomatic Python
good luck!

You're not actually reducing the nodeList when you recurse causing the infinite recursion. You will also not break out of the loop properly when you finish processing a word. The following buildnodelist completes at the very least. I won't guarantee that it works as desired though since I only modified some blocking lines:
def buildPointers(parent, info, nodeList):
if parent.numPointers == 0:
newNode = parent.addNode(info)
parent.numPointers = parent.numPointers + 1
if len(nodeList) > 1:
buildPointers(newNode, nodeList[x+1], nodeList[1:])
else:
for i in parent.Pointers:
if info == i.Value:
if len(nodeList) > 1:
buildPointers(i, nodeList[x+1], nodeList[1:])
else:
newNode = parent.addNode(info)
parent.numPointers = parent.numPointers + 1
if len(nodeList) > 1:
buildPointers(newNode, nodeList[x+1], nodeList[1:])
Essentially, I've removed the While loop and passed slices of the 1st element of nodeList if it has more than 1 item in it.

Related

Is there a better way to implement a generalized "changing" idiom for Python?

The phrase "repeat until the value stops changing" is common in algorithms and the implementation in real programming languages has always felt a bit clumsy. I've been using the following generalized function to clean up my algorithms where clarity trumps efficiency:
def changing(o):
ret = getattr(changing, 'last_value_', None) != o
changing.last_value_ = copy.deepcopy(o)
return ret
used in the following way:
first = collections.defaultdict(set)
while changing(first):
for left, right in GRAMMAR:
right = right[0]
if right in T:
first[left].add(right)
else:
first[left] = first[left] | first[right]
Clearly this is grossly inefficient and doesn't work if the first value is None and could be accomplished less brute-force if we knew the data structure ahead of time and how it changed.
But is there a better way in Python to accomplish the "this value is clearly different from this other value"?

OOP vs non-OOP implementation in Python on small scale real-time-ish application [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am new to OOP side of python and I am wondering if it is worth to refactor my non-OOP programming code to an OOP code. my code is as follows:
import time
import numpy as np
import pandas as pd
def choices_chooser(possibilities):
final_choice = None
while final_choice is None:
temp_input = input(f'please enter one of the following: {possibilities}\n')
if temp_input == 'True': temp_input = True
elif temp_input == 'False':temp_input = False
if temp_input in possibilities:
final_choice= temp_input
else:
print('typo! plz enter again')
return final_choice
def status_updater(dic, key, possibilities):
if key in dic and type(possibilities) in {list,tuple}:
print(f"the status of {key} before modification: {dic[key]}")
print('now we are changing it')
dic[key]= choices_chooser(possibilities)
print(f"the status of {key} after modification: {dic[key]}")
def funcA(df):df['Be'] *= -1.5
def funcB(df):df['Ch'] *= -2
def funcC(df):df['De'] *= -3
def funcD(df):df['Ep'] *= -4
def funcE(df):df['Fi'] *= -5
def funcF(df):df['Al'] *= -6
func_dict = {'Al': funcA,
'Be': funcB,
'Ch': funcC,
'De': funcD,
'Ep': funcE,
'Fi': funcF}
options_lst = [True, False]
status = ['Null']+['Al','Be','Ch','De','Ep','Fi']
status_dict = dict.fromkeys(status, False)
status_count = dict.fromkeys(status, 0)
status_index = 0
next_status_index = 1
previous_status_index = None
num_of_iteration = 0
num_of_complete_run = 0
df = pd.DataFrame(np.ones((4, len(status))), columns = status)
while num_of_complete_run < 1:
time.sleep(0.2)
num_of_iteration += 1
current_state = status[status_index]
next_state = status[next_status_index]
if previous_status_index is None:
print(f'current state: {current_state};next_state: {next_state}; iteration: {num_of_iteration}')
else:
previous_state = status[previous_status_index]
print(f'previous state: {previous_state}; current state: {current_state}; next state: {next_state}; iteration: {num_of_iteration}')
status_updater(status_dict,
next_state,
options_lst)
if status_dict[next_state]:
previous_status_index = status_index
status_index = next_status_index
previous_state = status[previous_status_index]
current_state = status[status_index]
print(f'we have attained a new state\n' + '-----'*10)
if current_state == 'Be':
print('after state Beta we may directly skip to De, depending on RNG')
next_state = choices_chooser(['Ch','De'])
next_status_index = status.index(next_state)
elif current_state == 'De':
print('after state Delta we may directly skip to Fi, depending on RNG')
next_state = choices_chooser(['Ep','Fi'])
next_status_index = status.index(next_state)
elif current_state == 'Fi':
print('we are at state Fi, which means a full run has been completed')
num_of_complete_run += 1
next_status_index = 1
next_state = status[next_status_index]
else:
next_status_index += 1
next_state = status[next_status_index]
print(f'previous state: {previous_state}; current state: {current_state}; next state: {next_state}')
#'do something unique at state {current_state}
func_dict[current_state](df)
status_count[current_state] += 1
This is my attempt to create a real-time-ish application. It has status variables. Different functions are run at different states. Whether certain states will be visited next depends on the user's input. The code terminates when the status 'Fi' has been reached once.
I am asking for help here because I have almost 0 knowledge when it comes to good program designs, technical debts, or basically any in-depth knowledge about what/when to do OOP and how to do it correctly.
My questions are the following:
1) Is it worth to refactor my non-OOP programming code to an OOP code?
2) If so, what should I pay extra care and attention to in the process? if not, what can I do to improve the existing code?
3) When should we convert a non-OOP code to OOP code and when shouldn't
4) Do you mind posting an example of what a good OOP version of this code is like in the answer?(I mean if one had to learn how to OOP, might as well learn from a great example)
Thank you guys in advance.
——
EDIT1:
changed “functional peogramming” to non-OOP to better reflect the situation
If you need your program to do only one thing and do it well, just use functional programming. If your program need to do more than one set of different things to do, use OOP. For example, if you build an app to calculate some scientific things (for example, velocity, gravity, etc.) you make it as OOP, 1 object only for GUI, 1 object to set things up and call calculation object, and other to perform calculation.
Other example if you build a web app, use one object to send view to user, 1/more object to set things up and calling the object to take things from database (with different usage for each object, i.e. one for home, one for user control, one for calculating item etc.), and last one/more object to operate the database (CRUD), it could be different object accessing different databases.(this one is called MVC model).
If your code slowly becoming spaghetti code and isn't readable, consider using OOP.
I'm not really an expert but that's how I do things for 4 years now.

Python TypeError: 'function' object is not subscriptable in nested function when i try to implement switch case

I am trying to code a random decision between 3 machines.
Since Python does not have any switch/case function, I resorted to if and elif.
Each machine (line1(),line2(),line3()) has its own function as well.
However, I have been getting errors.
Please advise me on what is going wrong.
machine_choice = [1,2,3]
selected_machine = random.choice(machine_choice)
print(selected_machine)
def machines(selected_machine):
if selected_machine == 1:
print("machine 1 randomly selected")
line1()
elif selected_machine == 2:
print("machine 2 randomly selected")
line2()
else:
print("machine 3 randomly selected")
line3()
machines(selected_machine)
def line1():
if machine1["hardness"] < rev[i][1]["condition"]:
print("\tMachine 1 hardness breached, will take 30mins for changing the system")
machine1["hardness"] = 10
time = line1
machine1["schedule"].append([d,"machine 1",time,"change",30.,time.add(minutes=30)])
print("\tno activities from {} to {}".format(time,time.add(minutes=30)))
time = time.add(minutes=30)
print("\tdone changing at time: ",time)
print("\tcurrent log: ",machine1["schedule"],"\n")
d+=1
line1=time
#line1 = max(time,line1,line2)
machine1["schedule"].append([d,"machine 1",line1,"feeding",5.,line1.add(minutes=5)])
line1 = line1.add(minutes=5)
d+=1
machine1["schedule"].append([d,"machine 1",line1,rev[i][0],rev[i][1]["duration"],line1.add(minutes=rev[i][1]["duration"])])
line1 = line1.add(minutes=rev[i][1]["duration"])
time = time.add(minutes=5)
d+=1
if rev[i][1]["quantity"] == 0:
i += 1
I am trying to code a random decision between 3 machines.
In Python, functions are nothing special, you can use them just like any other object.
def machine_one():
return 'Machine One'
def machine_two():
return 'Machine Two'
def machine_three():
return 'Machine Three'
machines = [machine_one, machine_two, machine_three]
print(random.choice(machines)())
The message means that you try to access to some python object defined as a function as if it were an array. The most likely candidate looking as the code you provided is machine_choice.
But please provide a working minimal example, which in that case means including import of necessary modules (random) and lines function.
Regarding the purpose of the code (faking a switch) the cascaded if solution is usually not a very good solution. Using random.choice with an array or a dictionnary or an array with random number as key or index would be much more pythonic.
Also using switch is a common code smell in OO programming and is often best replaced using object polymorphism and a factory.
You may have a look at python switch replacement for details.

Circular Buffer Python implementation

I wrote the code for a circular buffer for an interviewstreet question. But as it happened, two testcases passed and the others are failing. The failure of the cause: index out f range. I tried several testcases after that to reproduce the failure. Unfortunately none of them reproduce the error. Here is the code.
Implement a circular buffer of size N. Allow the caller to append, remove and list the contents of the buffer. Implement the buffer to achieve maximum performance for each of the operations.
"A" n - Append the following n lines to the buffer. If the buffer is full they replace the older entries.
"R" n - Remove first n elements of the buffer. These n elements are the ones that were added earliest among the current elements.
"L" - List the elements of buffer in order of their inserting time.
"Q" - Quit.
class circbuffer():
#initialization
def __init__(self,size):
self.maximum=size
self.data=[]
self.current=0
#appending when the buffer is not full
def append(self,x):
if len(self.data)==self.maximum:
self.current=0
self.data[self.current]=x
self.current=(self.current+1)%self.maximum
self.__class__=bufferfull
else:
self.data.append(x)
def remove(self,x):
if self.data:
self.data.pop(0)
def cget(self):
return self.data
class bufferfull:
def append(self,x):
if len(self.data)<self.maximum:
self.data.insert(self.current, x)
else:
self.data[self.current]=x
self.current=(self.current+1)%self.maximum
def remove(self,x):
if self.data:
if self.current>len(self.data):
self.current=0
self.data.pop(self.current)
def cget(self):
return self.data[self.current:]+self.data[:self.current]
n=input()
buf=circbuffer(n)
outputbuf=[]
while True:
com=raw_input().split(' ')
if com[0]=='A':
n=int(com[1])
cominput=[]
for i in xrange(n):
cominput.append(raw_input())
for j in cominput:
buf.append(j)
elif com[0]=="R":
n=int(com[1])
for i in range(n):
buf.remove(i)
elif com[0]=="L":
for i in buf.cget():
outputbuf.append(i)
elif com[0]=="Q":
break
for i in outputbuf:
print i
The error is pointing to self.data.pop(self.current) in class bufferfull. I cannot get the test data from the interviewstreet people. I am trying to come up with testcase myself to reproduce the error.
Any insights?
One bug is here:
def remove(self,x):
if self.data:
if self.current>len(self.data):
self.current=0
self.data.pop(self.current)
If self.current == len(self.data), you'll try to pop a non-existent element.
As a general remark, your implementation is way too complicated and for that reason wouldn't score very highly in my book (others might view this differently). #9000's comment to your question sums it up nicely:
Keep it simple. Don't be clever when you can be straightforward in the same number of lines. All you need is a head pointer, a tail pointer, and a list of a fixed size. You don't need any fancy metaprogramming stuff whatsoever. – #9000
It looks like you are trying to stop the index out of range error with the code below, but the condition you are checking is wrong.
if self.current > len(self.data):
self.current = 0
self.data.pop(self.current)
If you call self.data.pop(len(self.data)) you will definitely get that error since lists are 0-indexed. You probably meant:
if self.current >= len(self.data):
self.current = 0
self.data.pop(self.current)

What abut this crazy sequence of loops and ifs? Ideas to improve this code?

This code is currently working, but it looks terrible - and probably can be much improved in terms of performance.
Any Suggestions?
def OnClick():
global Selection, touch, set_elsb, set_vreg, set_els, BAR_Items
A = viz.pick(0, viz.WORLD, all=False)
if touch != A: return
for i in BAR_Items:
if not set_els: break
elif BAR_Items[i] == A or SHAPES[i+"_SHP"] == A:
if i in Selection:
Selection.remove(i)
BAR_Items[i].clearActions()
VFrame.SetStatusText(frame, i + " has been deselected")
viz.director( do_chart )
else:
Selection.append(i)
Thank you very much!
It's a few more lines of code but I think it's clearer.
def OnClick():
if not set_els: return
# swap this with the line above if viz.pick has side effects that should occur
A = viz.pick(0, viz.WORLD, all=False)
if touch != A: return
keys = (key for key in BAR_Items
if BAR_Items[key] == A or SHAPES[key+"_SHP"] == A)
for key in keys:
if key in Selection:
Selection.remove(key)
BAR_Items[key].clearActions()
VFrame.SetStatusText(frame, key + " has been deselected")
viz.director(do_chart)
else:
Selection.append(key)
That entire global statement served no purpose as you weren't assigning to any of them. Calling attributes and setting keys don't require the global keyword.
My normal approach to this would be to re-factor some of it out into small methods. This generally makes it more testable and easier to read.
If set_els is not changed outside during this code execution then:
def OnClick():
global Selection, touch, set_elsb, set_vreg, set_els, BAR_Items
if set_els: return
A = viz.pick(0, viz.WORLD, all=False)
if touch != A: return
for i in BAR_Items:
if not (BAR_Items[i] == A or SHAPES[i+"_SHP"] == A): continue
if i in Selection:
Selection.remove(i)
BAR_Items[i].clearActions()
VFrame.SetStatusText(frame, i + " has been deselected")
viz.director( do_chart )
else:
Selection.append(i)
Anyway, my bad code detector flashes with red light when it sees such a code, especially with such amount of globals.
It is very common to assume that if code is ugly, confusing, or hard to follow, it must therefore be inefficient.
Many people also think that if you want to make code go faster, you have to uglify it.
I've seen way ugly confusing code, some of which ran very fast, and other of which had massive performance problems.
I've also seen clean, clear, beautiful code of which the same could be said.
My experience - speed and beauty are independent.

Categories