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])
Related
I need to create a service that can manage a dynamic resource (I'm thinking on a dynamic csv that is growing. In this case I used a list to make more easy to understand), returning the next item from an iterable.
If the list is finished, the output would be False and I need to wait that an element is added.
When the element if finally added, the generator should yield the new added item (this is the part that I can not understand how to do).
a_lst = [1, 2]
class DynamicGenerator:
"""
Generic Generator that return item by item from a_lst and
can append a new item when needed.
"""
def __init__(self):
global a_lst
def gen_lst(self):
for item in a_lst:
yield item
def grow_lst(self, new_item):
a_lst.append(new_item)
class AvailableNextIterator:
"""
Return next item from iterable if it's available,
else return False.
"""
def __init__(self, iterable):
self.iterator = iterable
def __next__(self):
return next(self.iterator, False)
dg = DynamicGenerator()
gl = dg.gen_lst()
it = AvailableNextIterator(gl)
print(it.__next__())
print(it.__next__())
print(it.__next__())
dg.grow_lst(3)
print(it.__next__())
This is the code output:
1
2
False
False
This is the output that I need:
1
2
False
3
Very simply, you exhausted the iteration before you added the last item; you already tripped the end-of-data exception for gen_list. You've dropped out of the loop, and there's no provision to re-enter. You can see this with a little simple tracing in that method:
def gen_lst(self):
for item in a_lst:
yield item
print("gen_lst is out of data")
yield "over the cliff's edge ..."
Now, the output is
1
2
gen_lst is out of data
over the cliff's edge ...
False
You seem to want a FIFO queue; I suggest that you use the available data structure in the readily-available packages, rather than trying to roll your own.
However, if this is a homework exercise:
Mark your question as such, as required by SO posting standards;
Research existing implementations.
Maintain the queue as an attribute of the instance, not an external variable. Your "generator" should check the queue directly, rather than depending on for to manage the iteration.
I have a function that iterates over a many levels nested dictionary (arg1) collecting data over each iteration, something like this:
def dummy(arg1, found=[], index=0):
found.append('xyz')
for d in arg1:
dummy(arg1[d], found, index+1)
return found
My functions work as it's supposte to, the problem is that when I call the function a second time, the found argument keeps the value from the previous function call, i.e. the return value from the second call includes the return values from the previous call. I had to add something like
if index == 0:
found=list() # restart value
to the beginning of the function to initialize the value of the found argument. Any idea why this happens? is this a bug?
No, it's not a bug; see here
To avoid this, you should do:
def dummy(arg1, found=None, index=0):
if found is None:
found = []
...
or better yet (see here):
sentinel = object()
def dummy(arg1, found=sentinel, index=0):
if found is sentinel:
found = []
...
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.
Here I have a class that contructs a node and a function that prints out the node in reverse order:
class LLNode(object):
def __init__(self, data):
'''(LLNode, object) -> NoneType
Create a new node to hold data
'''
self.data = data
self.link = None
def __str__(self):
return str(self.data)
def reverse_list(L):
if L is None: return
head = L
tail = head.link
reverse_list(tail)
print(head, end=' ')
list1 = LLNode(1)
list1.link = LLNode(2)
print(reverse_list(list1))
What I don't understand is when the print statement runs, since reverse_list(tail) is placed before it, to me it looks like it is ignored. What I find is if I switch those two lines the program will print the linked-list in-order, which makes sense to me. How does putting print after make it print in reverse? I'm not understanding the flow here.
Because by printing after the recursive call, it happens when control returns to the calling function, on the way back up the calls. Here is a simple example:
>>> def recur(x):
print("Going down ({0}).".format(x))
if not x:
print("Hit bottom")
print("Coming up ({0}).".format(x))
return None
recur(x-1)
print("Coming up ({0}).".format(x))
>>> recur(2)
Going down (2).
Going down (1).
Going down (0).
Hit bottom
Coming up (0).
Coming up (1).
Coming up (2).
Notice that what it prints is the head of the list. At each step, it "peels off" the first element of the list, stores it, then recursively calls itself on the rest of the list. On the last call, it will have only one element left. It will then print that element and return to the previous call, which will print the element it peeled off, which was the second-to-last element. That will then return to the previous call, which will print the element before that, and so on.
You can think of it as having a deck of cards, and the algorithm is, "Build a new stack by taking the top card off the deck and putting it down on top of the new stack. After you've done this with all the cards, go through the new stack from top to bottom and look at each card." As you go through the deck from top to bottom, you will put cards in the new stack from bottom to top, so you reverse the stack. Only after you've stacked all the cards into this reverse stack do you go back and look at them (which is like "printing" them), at which point you're looking at them in reverse order.
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