Me and my partner have been working on this for a few hours and can't figure this out. The directions are vague in some areas and our professor did not do a good job of breaking it down to help us. Here is a link to the directions. I believe they are not very clear but please correct me if I am wrong and just overthinking it https://imgur.com/a/huHnwos
I believe that our biggest problems are the unlock(combination) and set_new_combination(new_combination) methods. I can figure out the str() method as that one isn't very hard to do. We've tried the things our professor has told us to try but they have been unsuccessful.
class Lock:
def __init__(self, combination = 0):
self.combination = combination
self.locked = False
def lock(self):
self.locked = True
def unlock(self, combination):
if combination == True or combination == 0:
self.locked = False
def set_new_combination(self, new_combination):
if self.locked == False:
self.combination = new_combination
def is_locked(self):
if self.locked == True or self.combination == True:
return True
else:
return False
def __eq__(self, other):
if other is not None and type(other) == type(self):
if self.combination == other.new_combination:
return False
def __str__(self):
return self.combination, ',', self.locked
The expected result should be a working basic combination lock.
Here's my implementation based on the inctructions provided, with comments where it deviates from your code.
class Lock:
def __init__(self, combination = 0): # No change here
self.combination = combination
self.locked = False
def lock(self):
# Although a test of self.locked is redundant, the instructions state
# "...if invoked a second time this, method should do nothing."
if not self.locked:
self.locked = True
def unlock(self, combination):
# You were not testing the stored combination against the one passed to the method.
# it does not matter if the stored combination is zero or a different number,
# you still need to check for equality.
# You also need a test as with lock() to satisfy the "if invoked a second time this,
# method should do nothing" requirement.
if self.locked and self.combination == combination:
self.locked = False
def set_new_combination(self, new_combination):
# You can simply the `if` condition, there's no need to test against False
if not self.locked:
self.combination = new_combination
def is_locked(self):
# I don't know why you are testing the self.combination value, you
# only need to return the state of the lock
return self.locked
def __eq__(self, other):
# You have the correct guard conditions but were returning False when
# the combinations matched. You can simply return the comparison result.
if other is not None and type(other) == type(self):
return self.combination == other.new_combination
def __str__(self):
# For some reason the output format specified for this appears to put it in a list
# (the square brackets) but as it's only for display we'll "fake" the list.
# The `if` statement prints the word 'locked' or 'unlocked' depending on the
# `self.locked` state.
return '[{}, {}]'.format(self.combination, 'locked' if self.locked else 'unlocked')
There are couple of problems with your code. First, if statement in your unlock method will be executed only if combination == 0 or combination == 1, which has nothing to do with lock's combination (self.combination). In your is_locked method you should only return self.locked, no need for if. __eq__ method can also be simplified. And __str__ method should actually return String.
class Lock:
def __init__(self, combination = 0):
self.combination = combination
self.locked = False
def lock(self):
self.locked = True
def unlock(self, combination):
if self.combination == combination:
self.locked = False
def set_new_combination(self, new_combination):
if not self.locked:
self.combination = new_combination
def is_locked(self):
return self.locked
def __eq__(self, other):
return isinstance(other, Lock) and self.combination == other.combination
def __str__(self):
return f'{self.combination}, { "locked" if self.locked else "unlocked"}'
Your unlockmethod is trying to compare a boolean to a number (the combination). Change it to look like this:
def unlock(self, combination):
if combination == self.combination:
self.locked = False
You also did this in your is_locked method, so that should be changed too:
def is_locked(self):
return self.locked
(Any time you find yourself writing something along the lines of if x return True else return False you can almost always replace this with return x if the conditional is simple).
set_new_combination works fine; I don't know what issue you saw with it.
Finally, your __str__ method should actually return a string:
def __str__(self):
return '[' + str(self.combination) + ', ' + 'locked' if self.locked else 'unlocked' + ']'
Related
For some context I am trying to write a parser for a search language. At the moment I have a bunch of class methods for accepting a token given that it satisfies a certain criterion, however it seems that their general structure/format can be encapsulated with the (newly written) method _accept_generic.
class Parser(object):
...
def now(self):
# now = self._tokens[self._pos] if not self.end() else None
# print(now, self._pos)
return self._tokens[self._pos] if not self.end() else None
def end(self):
return self._pos == self._length
def step(self):
self._pos += 1
def _accept_generic(self, criterion):
if not self.end():
if criterion:
self.step()
return True
return False
def _accept(self, char):
return self._accept_generic(self.now() == char)
# if not self.end():
# if self.now() == char:
# self.step()
# return True
# return False
def _accept_re(self, regex):
return self._accept_generic(regex.match(self.now()))
# if not self.end():
# if regex.match(self.now()):
# self.step()
# return True
# return False
def _accept_any_res(self, *regexes):
return self._accept_generic(any([r.match(self.now()) for r in regexes]))
# if any([r.match(self.now()) for r in regexes]):
# self.step()
# return True
# return False
def _accept_all_res(self, *regexes):
return self._accept_generic(all([r.match(self.now()) for r in regexes]))
# if all([r.match(self.now()) for r in regexes]):
# self.step()
# return True
# return False
The problem with the current code is that it will throw errors (since the criterion is being evaluated in the function argument rather than within the if statement if not self.end()). Is there any way using e.g. functools to allow the functions to inherit the generic's structure, with the ability to specify new arguments in the child functions' code, and not have to write the same code blocks repeatedly? functools.partialmethods doesn't really do what I'm looking for.
You can make the criterion a function and pass it to _accept_generic:
def _accept(self, char):
return self._accept_generic(lambda c=char: self.now() == c)
Then call in _accept_generic:
def _accept_generic(self, criterion):
if not self.end():
if criterion():
self.step()
return True
return False
I have a class for a Dialogue system as follows
class DIALOGUE(object):
def __init__(self, place, who, sTime, eTime, isActive, mood, menuText, func, repeatable, num):
self.place = place
self.who = who
self.sTime = sTime
self.eTime = eTime
self.isActive = isActive
self.mood = mood
self.menuText = menuText
self.func = func
self.repeatable = repeatable
self.num = num
#property
def ACheck(self):
global Date
if self.sTime == "none":
return True
else:
tHour,tMin = self.sTime.split(":")
if tHour >= Date.Hour and tMin <= Date.Minute:
tHour,tMin = self.eTime.split(":")
if tHour < Date.Hour and tMin < Date.Minute:
return True
return False
#property
def BCheck(self):
global Act
if self.who == Act:
return True
else:
return False
#property
def CCheck(self):
global Location
if self.place == Location:
return True
if self.place == "none":
return True
return False
#property
def DCheck(self):
if self.repeatable:
return True
else:
if self.num > 0:
return False
else:
return True
#property
def CanChat(self):
if self.isActive and self.ACheck and self.BCheck and self.CCheck and self.DCheck:
return True
else:
return False
def SetActive(self):
self.isActive = True
def Do(self):
self.num += 1
renpy.call(self.func)
Most of this should be self explanatory but I parse an XML file into a list of Instances of this class.
The user is presented with a list of available dialogues based on what Location they are in, what time of day it is and what NPC they have selected. If the dialogue is not repeatable The DCheck method looks at whether or not the dialogue has been completed before i.e if the dialogue is not repeatable and self.num > 0 the method will return False
Essentially it loops through all the dialogues and carries out i.CanChat and if this value returns True, the Dialogue is added to the menu
The issue I'm having is that the Check methods aren't returning the correct value. Specifically DCheck is returning True all the time, regardless of whether the Dialogue is repeatable or not, and ignoring the value of self.num
The class is created in an init python: block and then the xml file is parsed in a separate python block which is called from inside the start label
It's probably something really simple but I can't figure it out.
The list of instances is parsed as follows
Dialogues = []
for j in Dialo:
JPlace = j.find('Place').text
JWho = j.find('Who').text
JsTime = j.find('Start').text
JeTime = j.find('End').text
JMood = int(j.find('Mood').text)
JText = j.find('Text').text
JFunc = j.find('Func').text
JRep = j.find('Rep').text
if JRep == "True":
Jrep = True
else:
Jrep = False
Dialogues.append(DIALOGUE(JPlace, JWho, JsTime, JeTime, False, JMood, JText, JFunc, JRep, 0))
The method for creating the menu is as follows
def TalkCheck():
talks = []
talks.append(("Nevermind.", "none"))
for i, q in enumerate(Dialogues):
if q.CanChat:
talks.append((q.menuText,i))
renpy.say(None, "", interact=False)
talkchoice = renpy.display_menu(talks)
if talkchoice <> "none":
talkchoice = int(talkchoice)
Dialogues[talkchoice].Do()
Your question is incomplete - you didn't post a MCVE, we don't know the effective values for "repeatble" and "num" that leads to this behaviour, and we don't even know if it's using Python 2.x or Python 3.x - so we can just try and guess. Now since you mention that you "parse an XML file into a list of instances", I stronly suspect you are running Python 2.x and passing those values as strings instead of (resp.) boolean and int. In Python 2, "-1" (string) compares greater than 0 (int) - it raises a TypeError in Python 3.x -, and in both cases a non-empty string evals to True in a boolean context (bool('False') == True). Since there's no obvious logical error in your method implementation, that's the only explanation I can think of.
BTW, expressions have a boolean values and return exits the function, so you can simplify your code:
#property
def DCheck(self):
if self.repeatable:
return True
return self.num > 0
I wanna implement a class overloading and conclude if an event with a given point of time for example 12:59:50 happens before another event so the output is true or false, just a simple comparison test. I implemented it, as you can see, but, i'm pretty much sure this is not the most pythonic or better to say, objected oriented approach to carry out the tasks. I'm new to python so is there any improvement out there ?
Thanks
def __lt__(self, other):
if self.hour < other.hour:
return True
elif (self.hour == other.hour) and (self.minute < other.minute):
return True
elif (self.hour == other.hour) and (self.minute == other.minute) and (self.second < other.second):
return True
else:
return False
Tuples (and other sequences) already perform the type of lexicographic comparison you are implementing:
def __lt__(self, other):
return (self.hour, self.minute, self.second) < (other.hour, other.minute, other.second)
The operator module can clean that up a little:
from operator import attrgetter
def __lt__(self, other):
hms = attrgetter("hour", "minute", "second")
return hms(self) < hms(other)
I am trying to implement a 2-3 tree but I am having trouble with the find method.
This method given an int as parameter should return the node that contains the int.
The problem is that sometimes it works, sometimes it does't and I don't know why.
I have added a test print. For a particular int that I know for sure that is part of the tree, the code executes the print statement, meaning that it has found the node, but does not return this node. Instead it return False which is at the end of the code.
Can you help me solving this ?
def find(self,data,node=0): #return problem ???
if node==0:
a=self.root
else:
a=node
if a.data2==None:
if data==a.data: ### here is the problem
print("qwertyuiop") ### it does not execute the return statement
return a
elif data < a.data:
if a.left!=None:
return self.find(data,a.left)
elif data > a.data:
if a.right!=None:
return self.find(data,a.right)
else:
if a.data2!=None:
if (data==a.data or data==a.data2):
return a
elif data<a.data:
if a.left!=None:
return self.find(data,a.left)
elif (data>a.data and data<a.data2):
if a.middle!=None:
return self.find(data,a.middle)
elif data>a.data2:
if a.right!=None:
return self.find(data,a.right)
print("Not Found") ### function executes this print
return False
self.root is the root of the tree and is an object of the following class
class Node:
def __init__(self, data=None, left=None, right=None):
self.data = data
self.data2 = None
self.data3 = None
self.left = left
self.right = right
self.middle = None
self.middle2 = None
Binary Search Tree:
class Nodeee:
def __init__(self, data=None, left=None, right=None):
self.data = data
self.left = left
self.right = right
class BST:
def __init__(self, root=None):
self.c=[]
self.total=0
self.root = None
def parent(self,data,node=5):
def search(nodee,cc,data):
if data==cc.data:
return nodee
else:
if data<cc.data:
nodee=cc
return search(nodee,cc.left,data)
elif data>cc.data:
nodee=cc
return search(nodee,cc.right,data)
print("Parent Error")
return False
if node==self.root:
print("Root has no parent")
else:
a=self.root
c=self.root
return search(a,c,data)
def lookup(self,data,node=0):
if node==0:
a=self.root
else:
a=node
if data < a.data:
if a.left==None:
return a
else:
return self.lookup(data,a.left)
elif data > a.data:
if a.right==None:
return a
else:
return self.lookup(data,a.right)
def find(self,data,node=0):
if node==0:
a=self.root
else:
a=node
if data==a.data:
print("WTF")
return a
elif data < a.data:
if a.left!=None:
return self.find(data,a.left)
elif data > a.data:
if a.right!=None:
return self.find(data,a.right)
print("Not Found")
return False
def find2(self,data,node=0):
if node==0:
a=self.root
else:
a=node
if data==a.data:
return True
elif data < a.data:
return self.find2(data,a.left)
elif data > a.data:
return self.find2(data,a.right)
return False
def is_empty(self):
if self.root==None:
return True
def is_leaf(self,n):
if (n.left==None and n.right==None):
return True
return False
def delete(self):
self.root=None
def insert(self, data):
if self.root==None:
self.root=Nodeee(data)
self.total+=1
return True
else:
b=self.lookup(data)
if data < b.data:
b.left=Nodeee(data)
self.total+=1
return True
elif data > b.data:
b.right=Nodeee(data)
self.total+=1
return True
print("Insert Error !")
return False
def inorder_swap(self,data):
a=self.find(data)
b=a.right
while self.is_leaf(b)!=True:
if b.left!=None:
b=b.left
elif b.left==None:
b=b.right
temp=a.data
a.data=b.data
b.data=temp
def remove(self,data):
a=self.find(data)
if self.is_leaf(a)==True:
b=self.parent(data)
if b.left==a:
b.left=None
elif b.right==a:
b.right=None
elif self.is_leaf(a)==False:
if a.left==None:
b=self.parent(data)
if b.left==a:
b.left=b.left.right
elif b.right==a:
b.right=b.right.right
elif a.right==None:
b=self.parent(data)
if b.left==a:
b.left=b.left.left
elif b.right==a:
b.right=b.right.left
elif (a.left!=None and a.right!=None):
self.inorder_swap(data)
self.remove(data)
def inorder(self,node):
if node!=None:
self.inorder(node.left)
self.c.append(node.data)
self.inorder(node.right)
def inorder_print(self):
self.c=[]
self.inorder(self.root)
print("\nStart")
for x in range(len(self.c)):
print(self.c[x], end=",")
print("\nFinish\n")
a=BST()
print(a.insert(234)==True)
print(a.insert(13)==True)
print(a.insert(65)==True)
print(a.insert(658)==True)
print(a.insert(324)==True)
print(a.insert(86)==True)
print(a.insert(5)==True)
print(a.insert(76)==True)
print(a.insert(144)==True)
print(a.insert(546)==True)
print(a.insert(2344)==True)
print(a.insert(1213)==True)
print(a.insert(6345)==True)
print(a.insert(653348)==True)
print(a.insert(35324)==True)
print(a.insert(8463)==True)
print(a.insert(5555)==True)
print(a.insert(76539)==True)
print(a.insert(14499)==True)
print(a.insert(59999946)==True)
a.inorder_print()
a.remove(35324)
a.remove(1213)
a.remove(2344)
a.remove(144)
a.remove(5555)
a.remove(6345)
a.remove(59999946)
a.remove(76)
print(a.root.data)
a.inorder_print()
def inorder_swap(self,data):
a=self.find(data)
b=a.right
while self.is_leaf(b)!=True:
if b.left!=None:
b=b.left
elif b.left==None:
b=b.right
temp=a.data
a.data=b.data
b.data=temp
a here is the node containing the passed data. This method does nothing else than swapping a's data with some leaf's data (first one while finds), thereby distorting the tree order. A follow-up find on the same data therefore fails and returns False. Since your code has no error checks, this results in an AttributeError.
You probably want to move nodes around in inorder_swap. However you only assign to the local name b. If you want to change nodes, then you need to use b.left = or b.right =.
It might be that there are more problems, that I don't see right now.
Also your code has several style problems, some of them:
You have four functions doing the same: find, find2, lookup and search in parent.
Most of the naming is not informative or even confusing.
Lines like if a.right==None: should be written as if not a.right: (or maybe if a.right is None:).
Check the return value of functions and don't just assume they return a valid node if they might not (i.e. find might return False instead of a node). Or alternatively use exception handling.
If you have an if ... elif ... elif block you don't have to check the last possibility if it is sure to be true, for example:
if b.left!=None:
# something
elif b.left==None:
# something else
should be
if b.left:
# something
else:
# something else
Greetings, currently I am refactoring one of my programs, and I found an interesting problem.
I have Transitions in an automata. Transitions always have a start-state and an end-state. Some Transitions have a label, which encodes a certain Action that must be performed upon traversal. No label means no action. Some transitions have a condition, which must be fulfilled in order to traverse this condition, if there is no condition, the transition is basically an epsilon-transition in an NFA and will be traversed without consuming an input symbol.
I need the following operations:
check if the transition has a label
get this label
add a label to a transition
check if the transition has a condition
get this condition
check for equality
Judging from the first five points, this sounds like a clear decorator, with a base transition and two decorators: Labeled and Condition. However, this approach has a problem: two transitions are considered equal if their start-state and end-state are the same, the labels at both transitions are equal (or not-existing) and both conditions are the same (or not existing). With a decorator, I might have two transitions Labeled("foo", Conditional("bar", Transition("baz", "qux"))) and Conditional("bar", Labeled("foo", Transition("baz", "qux"))) which need a non-local equality, that is, the decorators would need to collect all the data and the Transition must compare this collected data on a set-base:
class Transition(object):
def __init__(self, start, end):
self.start = start
self.end = end
def get_label(self):
return None
def has_label(self):
return False
def collect_decorations(self, decorations):
return decorations
def internal_equality(self, my_decorations, other):
try:
return (self.start == other.start
and self.end == other.end
and my_decorations = other.collect_decorations())
def __eq__(self, other):
return self.internal_equality(self.collect_decorations({}), other)
class Labeled(object):
def __init__(self, label, base):
self.base = base
self.label = label
def has_label(self):
return True
def get_label(self):
return self.label
def collect_decorations(self, decorations):
assert 'label' not in decorations
decorations['label'] = self.label
return self.base.collect_decorations(decorations)
def __getattr__(self, attribute):
return self.base.__getattr(attribute)
Is this a clean approach? Am I missing something?
I am mostly confused, because I can solve this - with longer class names - using cooperative multiple inheritance:
class Transition(object):
def __init__(self, **kwargs):
# init is pythons MI-madness ;-)
super(Transition, self).__init__(**kwargs)
self.start = kwargs['start']
self.end = kwargs['end']
def get_label(self):
return None
def get_condition(self):
return None
def __eq__(self, other):
try:
return self.start == other.start and self.end == other.end
except AttributeError:
return False
class LabeledTransition(Transition):
def __init__(self, **kwargs):
super(LabeledTransition).__init__(**kwargs)
self.label = kwargs['label']
def get_label(self):
return self.label
def __eq__(self):
super_result = super(LabeledTransition, self).__eq__(other)
try:
return super_result and self.label == other.label
except AttributeError:
return False
class ConditionalTransition(Transition):
def __init__(self, **kwargs):
super(ConditionalTransition, self).__init__(**kwargs)
self.condition = kwargs['condition']
def get_condition(self):
return self.condition
def __eq__(self, other):
super_result = super(ConditionalTransition, self).__eq__(other)
try:
return super_result and self.condition = other.condition
except AttributeError:
return False
# ConditionalTransition about the same, with get_condition
class LabeledConditionalTransition(LabeledTransition, ConditionalTransition):
pass
the class LabledConditionalTransition behaves exactly as expected - and having no code in there is appealing and I do not thing MI is confusing at this size.
Of course, the third option would be to just hammer everything into a single transition class with a bunch of in has_label/has_transition.
So... I am confused. Am I missing something? Which implementation looks better? How do you handle similar cases, that is, objects which look like a Decorator could handle them, but then, such a non-local method comes around?
EDIT:
Added the ConditionalTransition-class. Basically, this kinda behaves like the decorator, minus the order created by the order of creating the decorators, the transition checks for start and end being correct, the LabeledTransition-class checks for label being correct and ConditionalTransition checks for condition being correct.
I think its clear that nobody really understands your question. I would suggest putting it in context and making it shorter. As an example, here's one possible implementation of the state pattern in python, please study it to get an idea.
class State(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
class Automaton(object):
def __init__(self, instance, start):
self._state = start
self.transitions = instance.transitions()
def get_state(self):
return self._state
def set_state(self, target):
transition = self.transitions.get((self.state, target))
if transition:
action, condition = transition
if condition:
if condition():
if action:
action()
self._state = target
else:
self._state = target
else:
self._state = target
state = property(get_state, set_state)
class Door(object):
open = State('open')
closed = State('closed')
def __init__(self, blocked=False):
self.blocked = blocked
def close(self):
print 'closing door'
def do_open(self):
print 'opening door'
def not_blocked(self):
return not self.blocked
def transitions(self):
return {
(self.open, self.closed):(self.close, self.not_blocked),
(self.closed, self.open):(self.do_open, self.not_blocked),
}
if __name__ == '__main__':
door = Door()
automaton = Automaton(door, door.open)
print 'door is', automaton.state
automaton.state = door.closed
print 'door is', automaton.state
automaton.state = door.open
print 'door is', automaton.state
door.blocked = True
automaton.state = door.closed
print 'door is', automaton.state
the output of this programm would be:
door is open
closing door
door is closed
opening door
door is open
door is open
From the code that was posted, the only difference between Transition and Labeled Transition is the return of get_lable() and has_label(). In which case you can compress these two a single class that sets a label attribute to None and
return self.label is not None
in the has_label() function.
Can you post the code for the ConditionalTransition class? I think this would make it clearer.