class BinaryStringList():
def __init_(self):
self.item = []
def strAdd(self,item):
self.items.append(item)
def finditem(self, item):
if len(self)==0:
print("List is empty!")
else:
midpoint = len(self)//2
if self[midpoint]==item:
print("Item Found ", item)
else:
if item<self[midpoint]:
return finditem(self[:midpoint], item)
else:
return finditem(self[midpoint+1:], item)
So where I am finding I have an issue is when trying to add items to the list. If i do something like:
alist = BinaryStringList()
alist.strAdd("test1")
my code fails stating object has no attribute. Not sure why it is failing since I have almost the exact same code for another program except the find is using a sequential search where as this is a binary search.
You have multiple syntax errors in your code. Also recursion doesn't work that way, you need to have a base condition which returns. This solution will work, but I strongly suggest you to solve simpler problems using recursion to understand how it works.
class BinaryStringList:
def __init__(self): # You had 1 _ after init
self.items = [] # Typo, should have been items.
def strAdd(self,item):
self.items.append(item)
def finditem(self, item):
return self.binser(self.items, item)
def binser(self, items, item):
if len(items)==0:
return
midpoint = len(items)/2 # len(self) means nothing, it should be len(self.items)
if items[midpoint]==item:
return item
else:
if item<items[midpoint]:
return self.binser(items[:midpoint], item) #self[:midpoint] means nothing, you needed self.items[:midpoint]
else:
return self.binser(items[midpoint+1:], item)
binser = BinaryStringList()
binser.strAdd(1) # You added a string here. Your logic won't work with string.
binser.strAdd(2)
binser.strAdd(3)
binser.strAdd(5)
binser.strAdd(8)
binser.strAdd(9)
binser.strAdd(10)
print binser.finditem(1)
print binser.finditem(10)
print binser.finditem(5)
print binser.finditem(11)
(there are other ways of solving binary search too - i.e. iterative approach, passing low/high index values rather than splicing the input array). Try to solve binary search using those two approaches.
Binary search with passing low/high index values, your signature for binser will look like: def binser(self, low, high, item):
Your code is failing because you misspelled __init__. You need two underscores on each side, or it's just a weirdly named method. Since you lack a __init__, the default __init__ (which sets no attributes) is used, and you don't have an item or items attribute. You need to fix the __init__, and use a consistent name for items:
class BinaryStringList():
def __init__(self): # <-- Added extra trailing underscore
self.items = [] # Fixed name to be items, not item
You have many other problems here (you're not maintaining sorted order, so binary search won't work, you haven't implemented __getitem__ so self[midpoint] won't work so you'd need self.items[midpoint], lack of __len__ means len(self) won't work either, etc.), but the two issues above are what specifically makes you get the AttributeError.
Related
Right now, I have a base 10 to base 2 converter that works, however it always prints none at the end of every conversion.
base_two=0
def binary_recursion(base_ten):
global base_two
if base_ten==0:
print(base_two)
return
c=0
while base_ten//2**c>1:
c+=1
base_two+=10**c
if c==0:
print(base_two)
return
binary_recursion(base_ten-2**c)
I tried returning base_two as opposed to printing it, but that doesn't return a number, it also just returns None. Can anyone help me pinpoint my mistake?
def node(document_info, next_node):
return {'data': document_info, 'next': next_node}
def insert(head, new_document_info):
#insert new document into the linked list head
#returns the head of the modified list
if head is None:
return node(new_document_info, None)
if new_document_info[1] <= head['data'][1]:
return node(new_document_info, head)
head['next'] = insert(head['next'], new_document_info)
return head
Here's a slightly modified way of doing insertion sort, from my answer to you last question. You would start with head = None and then every time you add a print job do head = insert(head, document_info). Or after collecting all of your print jobs do something like
head = None
for document_info in list_queue:
head = insert(head, document_info)
You are not adding new element into queue. Assuming list_queue is a queue.
Queue has put function to add a new element into it.
def make_job():
temp_list=[]
list_queue = Queue()
for line in print_list:
if line[:6]=='submit': #If the command is submit, then the file must be placed in its
a=line.split() #correct spot in the linked list
del(a[0])
list_queue.put(a)#Contains file id, and the time required to print
temp_list.append(list_queue)
organize(list_queue) #Places the file in its correct spot in the linked list
else:
break
The Python queue module has a class called PriorityQueue that does exactly what you're looking for. For your situation, using it would look something like this:
class Job(object):
def __init__(self, name, print_time):
self.name = name
self.print_time = print_time
def __lt__(self, other):
return self.print_time < other.print_time
import queue as _queue # Need to rename the module so it doesn't conflict with your 'queue' function
my_queue = _queue.PriorityQueue()
def make_job():
for line in print_list:
if line[:6]=='submit':
a=line.split()
del(a[0])
new_job=queue(a) # queue(a) now returns a Job, e.g. Job('101', 40), instead of a 2-element list
my_queue.put(new_job)
else:
break
Once my_queue has been constructed, then repeated calls to my_queue.get() will return the Jobs ordered by print_time.
If you want to be able to inspect the contents of the queue without removing elements (get removes the element it returns), you could append the Jobs to a list and call list_queue.sort() after every insertion. If this is a performance concern, you could find the right spot in the list yourself and call list_queue.insert(i, a). Deferring to Python's list.sort has some advantages, though; namely, it's stable.
Lastly, if you don't want to define a new class, you could use sorted or list.sort with a custom sorting function. This takes the place of the __lt__ member I defined for Job.
new_job=queue(a) # queue(a) is your original function, which returns 2-element lists like ['101', 40]
list_queue.append(new_job)
list_queue.sort(key=lambda a,b: return a[1]<b[1])
I'm implementing some basic data structures in preparation for an exam and have come across the following issue. I want to implement an unsorted linked list, and have already implemented a pop() method, however I don't know, either syntactically or conceptually, how to make a function sometimes take an argument, sometimes not take an argument. I hope that makes sense.
def pop(self):
current = self.head
found = False
endOfList = None
while current != None and not found:
if current.getNext() == None:
found = True
endOfList = current.getData()
self.remove(endOfList)
self.count = self.count - 1
else:
current = current.getNext()
return endOfList
I want to know how to make the statement unsortedList.pop(3) valid, 3 being just an example and unsortedList being a new instance of the class.
The basic syntax (and a common use case) for using a parameter with a default value looks like this:
def pop(self, index=None):
if index is not None:
#Do whatever your default behaviour should be
You then just have to identify how you want your behaviour to change based on the argument. I am just guessing that the argument should specify the index of the element that should be pop'ed from the list.
If that is the case you can directly use a valid default value instead of None e.g. 0
def pop(self, index=0):
First, add a parameter with a default value to the function:
def pop(self, item=None):
Now, in the code, if item is None:, you can do the "no param" thing; otherwise, use item. Whether you want to switch at the top, or lower down in the logic, depends on your logic. In this case, item is None probably means "match the first item", so you probably want a single loop that checks item is None or current.data == item:.
Sometimes you'll want to do this for a parameter that can legitimately be None, in which case you need to pick a different sentinel. There are a few questions around here (and blog posts elsewhere) on the pros and cons of different choices. But here's one way:
class LinkedList(object):
_sentinel = object()
def pop(self, item=_sentinel):
Unless it's valid for someone to use the private _sentinel class member of LinkedList as a list item, this works. (If that is valid—e.g., because you're building a debugger out of these things—you have to get even trickier.)
The terminology on this is a bit tricky. Quoting the docs:
When one or more top-level parameters have the form parameter = expression, the function is said to have “default parameter values.”
To understand this: "Parameters" (or "formal parameters") are the things the function is defined to take; "arguments" are things passed to the function in a call expression; "parameter values" (or "actual parameters", but this just makes things more confusing) are the values the function body receives. So, it's technically incorrect to refer to either "default parameters" or "parameters with default arguments", but both are quite common, because even experts find this stuff confusing. (If you're curious, or just not confused yet, see function definitions and calls in the reference documentation for full details.)
Is your exam using Python specifically? If not, you may want to look into function overloading. Python doesn't support this feature, but many other languages do, and is a very common approach to solving this kind of problem.
In Python, you can get a lot of mileage out of using parameters with default values (as Michael Mauderer's example points out).
def pop(self, index=None):
prev = None
current = self.head
if current is None:
raise IndexError("can't pop from empty list")
if index is None:
index = 0 # the first item by default (counting from head)
if index < 0:
index += self.count
if not (0 <= index < self.count):
raise IndexError("index out of range")
i = 0
while i != index:
i += 1
prev = current
current = current.getNext()
assert current is not None # never happens if list is self-consistent
assert i == index
value = current.getData()
self.remove(current, prev)
##self.count -= 1 # this should be in self.remove()
return value
I'm implementing a disjoint set system in Python, but I've hit a wall. I'm using a tree implementation for the system and am implementing Find(), Merge() and Create() functions for the system.
I am implementing a rank system and path compression for efficiency.
The catch is that these functions must take the set of disjoint sets as a parameter, making traversing hard.
class Node(object):
def __init__(self, value):
self.parent = self
self.value = value
self.rank = 0
def Create(values):
l = [Node(value) for value in values]
return l
The Create function takes in a list of values and returns a list of singular Nodes containing the appropriate data.
I'm thinking the Merge function would look similar to this,
def Merge(set, value1, value2):
value1Root = Find(set, value1)
value2Root = Find(set, value2)
if value1Root == value2Root:
return
if value1Root.rank < value2Root.rank:
value1Root.parent = value2Root
elif value1Root.rank > value2Root.rank:
value2Root.parent = value1Root
else:
value2Root.parent = value1Root
value1Root.rank += 1
but I'm not sure how to implement the Find() function since it is required to take the list of Nodes and a value (not just a node) as the parameters. Find(set, value) would be the prototype.
I understand how to implement path compression when a Node is taken as a parameter for Find(x), but this method is throwing me off.
Any help would be greatly appreciated. Thank you.
Edited for clarification.
The implementation of this data structure becomes simpler when you realize that the operations union and find can also be implemented as methods of a disjoint set forest class, rather than on the individual disjoint sets.
If you can read C++, then have a look at my take on the data structure; it hides the actual sets from the outside world, representing them only as numeric indices in the API. In Python, it would be something like
class DisjSets(object):
def __init__(self, n):
self._parent = range(n)
self._rank = [0] * n
def find(self, i):
if self._parent[i] == i:
return i
else:
self._parent[i] = self.find(self._parent[i])
return self._parent[i]
def union(self, i, j):
root_i = self.find(i)
root_j = self.find(j)
if root_i != root_j:
if self._rank[root_i] < self._rank[root_j]:
self._parent[root_i] = root_j
elif self._rank[root_i] > self._rank[root_j]:
self._parent[root_j] = root_i
else:
self._parent[root_i] = root_j
self._rank[root_j] += 1
(Not tested.)
If you choose not to follow this path, the client of your code will indeed have to have knowledge of Nodes and Find must take a Node argument.
Clearly merge function should be applied to pair of nodes.
So find function should take single node parameter and look like this:
def find(node):
if node.parent != node:
node.parent = find(node.parent)
return node.parent
Also wikipedia has pseudocode that is easily translatable to python.
Find is always done on an item. Find(item) is defined as returning the set to which the item belongs. Merger as such must not take nodes, merge always takes two items/sets. Merge or union (item1, item2) must first find(item1) and find(item2) which will return the sets to which each of these belong. After that the smaller set represented by an up-tree must be added to the taller. When a find is issued, always retrace the path and compress it.
A tested implementation with path compression is here.
I have my own tree-isch data structure in memory and want to use the
gtk GenericTreeModel to display it. On some levels in my tree I have
dictionaries, on some other levels lists.
(I do not want the TreeStore, because then I have to link /
copy things around. I want to operate on the original data.)
My idea is to use a dictionary / list iterator when implementing the
method on_get_iter(). For the top level element the method looks
like (some code skipped):
def on_get_iter(self, path):
return self.__my_data.get_dict().iteritems()
The method on_iter_next() is very simple:
def on_iter_next(self, rowref):
try:
return rowref.next()
except StopIteration:
return None
But then there is the need to get the data. This is done with
on_get_value(). I have no idea how to implement this:
def on_get_value(self, rowref, column):
# What to write here?
The documentation says, that the value of the current row should be
returned here. IMHO 'rowref.next()' does the wrong thing, because it
does not get the current but the next element.
IMHO there is no way to access the current element of an iterator (see
PEP 234).
Is there a way to use the GenericTreeModel with standard iterators
like dictionary or list iterators?
Update:
I found a workaround for this. Using the following iterator instead of the standard ones works for me; the constructor gets the standard dictionary / list iterator.
class GTMIterator:
def __init__(self, iterator):
self.__iterator = iterator
self.__current = None
self.next()
def next(self):
try:
self.__current = self.__iterator.next()
except StopIteration:
return None
return self.__current
def current(self):
return self.__current
But: IMHO this is only a workaround and not a 'clean' solution.
One the way to do this would be as follows:
def on_get_iter(self, path):
...
iterator = self.__my_data.get_dict().iteritems()
data = iterator.next()
return {'iterator': iterator, 'data': data}
def on_iter_next(self, rowref):
try:
iterator = rowref['iterator']
next_data = iterator.next()
return {'iterator': iterator, 'data': next_data}
except StopIteration:
return None
def on_get_value(self, rowref, column):
key, value = rowref['data']
return value[column]
The key here is that the on_* functions may return any user data object that
they wish. That object is automatically wrapped in a gtk.TreeIter using
gtk.GenericTreeModel.create_tree_iter and unwrapped again when calling
another on_* function using gtk.GenericTreeModel.get_user_data.
Hence, instead of returning just a python iterator, the key and value returned
by the last call to next method can be stored to access it in case it's
needed when calling to some other method.
You need to implement GtkTreeModel interface in your data-keeping object.
GtkTreeview use as model any GObject implementing that interface.
For futher references look at Overview of GtkTreeModel, GtkTreeView, and friends
I'm trying to remove an item from a sorted list. If the item is not in the list, then the list remains unchanged. If the item occurs multiple times, only one occurrence of the item is removed. Again, I'm not allowed to use build-in list functions, but for the time being, I'm just trying to get the code to just work!
class SortedList:
def __init__(self):
self.s_list = []
def insert(self, item):
self.s_list.append(item)
def remove(self, item):
finalSet=[]
for item in self.s_list:
if item not in finalSet:
finalSet.append(item)
return finalSet
def __str__(self):
return str(self.s_list)
Your remove function seems very confused.
def remove(self, item):
finalSet=[]
for item in self.s_list:
if item not in finalSet:
finalSet.append(item)
return finalSet
Why are you creating a new list, shouldn't you be modifying the existing list?
There are two different item in the function. One is a parameter to the function, the other is in the loop. The one in the loop replaces the parameter. Give them different names
You return with the list almost right away, you probably don't want to return until after the loop is completed. Your return statement is intended too far
Since you've confused two different variables by giving them the same name, I can't guess what you were actually trying to do inside the loop.
Other Question
Full page about topic