So for the following code I have been trying to use singly linked lists in python to calculate the sum of a list based on the even numbers within that list. I've written the code for the linked list portion I believe but I'm stumped on how to get it to actually take the even numbers only and sum them. Right now my code looks something like this:
def createList(plist):
linkedList = None
# goes backwards, adding each element to the beginning
# of the list.
for index in range(len(plist)-1, -1, -1):
linkedList = insertValueHead(linkedList, plist[index])
return linkedList
def sumEvens(linkedList): #This is what I'm looking for help with
.... #code
def testSumEvens():
myList = createList([14, 21, 29, 2, 16, 49, -26])
print "The sum of the even numbers in the first list is ", sumEvens(myList)
myList = createList([])
print "The sum of the even numbers in an empty list is ", sumEvens(myList)
myList = createList([5, 15, 25])
print "The sume of the even numbers in the final list is ", sumEvens(myList)
How would I go about making this create a sum of these lists? Such as in the first, 14 + 2 + 16?
As previously mentioned taking the modulous % of a number will yield the remainder. Thus if n%2 is 0, then the number is even. You could implement sumEvens like this...
def sumEvens(linkedList):
runningSum = 0
for number in linkedList:
if number % 2 == 0:
runningSum += number
print number
print runningSum
sumEvens([14, 21, 29, 2, 16, 49, -26]) # prints 6 (14+2+16-26)
here is a very basic linked list example
class LLNode:
def __init__(self,value):
self.next = None
self.val = value
def __float__(self):
return float(self.val)
def __int__(self):
return int(self.val)
def __str__(self):
return str(self.val)
class LL:
head =None
def iterNodes(self):
tmp = self.head
while tmp is not None:
yield tmp
tmp = tmp.next
def iterInts(self):
for node in self.iterNodes():
try:
yield int(node)
except ValueError:
pass
def iterFloats(self):
for node in self.iterNodes():
try:
yield float(node)
except ValueError:
pass
def iterStrings(self):
for node in self.iterNodes():
yield str(node)
def insert(self,value):
nn = LLNode(value)
if self.head is None:
self.head = nn
else:
list(self.iterNodes())[-1].next = nn
l = LL()
l.insert(1)
l.insert(2)
l.insert(3)
l.insert(4)
l.insert(5)
l.insert(6)
print "Sum of Even:",sum([n for n in l.iterInts() if n%2 == 0])
print "Sum of Odd:", sum([n for n in l.iterInts() if n%2 != 0])
the iterFunctions are the ones of primary interest to you I think
Related
Im trying to append 2 arrays using python classes.
def __init__(self):
self.inArray = [0 for i in range(10)]
self.count = 0
def get(self, i):
return self.inArray[i]
def set(self, i, e):
self.inArray[i] = e
def length(self):
return self.count
def append(self, e):
self.inArray[self.count] = e
self.count += 1
if len(self.inArray) == self.count:
self._resizeUp() # resize array if reached capacity
def insert(self, i, e):
for j in range(self.count,i,-1):
self.inArray[j] = self.inArray[j-1]
self.inArray[i] = e
self.count += 1
if len(self.inArray) == self.count:
self._resizeUp() # resize array if reached capacity
def remove(self, i):
self.count -= 1
val = self.inArray[i]
for j in range(i,self.count):
self.inArray[j] = self.inArray[j+1]
return val
def __str__(self):
return str(self.inArray[:self.count])
def _resizeUp(self):
newArray = [0 for i in range(2*len(self.inArray))]
for j in range(len(self.inArray)):
newArray[j] = self.inArray[j]
self.inArray = newArray
def appendAll(self, A):
self.ls = [2,3,4,5]
ls = ls.append(A)
Im trying to write a function appendAll(self,A) that appends all elements of the array A in the array list (the one represented by self).
For example, if ls is [2,3,4,5] then ls.appendAll([42,24]) changes ls to [2,3,4,5,42,24].
This is all I can think of doing but I'm just stuck, any help will be appreciated
You can also just do like so (Basically just like extend).
ls += A
your code:
1. def appendAll(self, A):
2. self.ls = [2,3,4,5]
3. ls = ls.append(A)
The append function does not return a list
it operates on the original list.
the append function is also not what you are looking for,
because this will happen:
[2, 3, 4, 5, [42, 24]]
but extend will look like so:
[2, 3, 4, 5, 42,24]
Remember!
both functions do not return a new list
they simply operate on the given list.
You can use extend(
Have a look at What is the difference between Python's list methods append and extend? )
ls = ls.extend(A)
in your code :
def appendAll(self, A):
self.ls = [2,3,4,5]
self.ls = self.ls.extend(A)
def str_tree(atree,indent_char ='.',indent_delta=2):
def str_tree_1(indent,atree):
if atree == None:
return ''
else:
answer = ''
answer += str_tree_1(indent+indent_delta,atree.right)
answer += indent*indent_char+str(atree.value)+'\n'
answer += str_tree_1(indent+indent_delta,atree.left)
return answer
return str_tree_1(0,atree)
def build_balanced_bst(l):
d = []
if len(l) == 0:
return None
else:
mid = (len(l)-1)//2
if mid >= 1:
d.append(build_balanced_bst(l[:mid]))
d.append(build_balanced_bst(l[mid:]))
else:
return d
The build_balanced_bst(l) takes in a list of unique values that are sorted in increasing order. It returns a reference to the root of a well-balanced binary search tree. For example, calling build_ballanced_bst( list(irange(1,10)) returns a binary search tree of height 3 that would print as:
......10
....9
..8
......7
....6
5
......4
....3
..2
....1
The str_tree function prints what the build_balanced_bst function returns
I am working on the build_balanced_bst(l) function to make it apply to the str_tree function. I used the middle value in the list as the root’s value.
But when I call the function as the way below:
l = list(irange(1,10))
t = build_balanced_bst(l)
print('Tree is\n',str_tree(t),sep='')
it doesn't print anything. Can someone help me to fix my build_balanced_bst(l) function?
Keeping the str_tree method as it is, here's the remaining code.
class Node:
"""Represents a single node in the tree"""
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def build_balanced_bst(lt):
"""
Find the middle element in the sorted list
and make it root.
Do same for left half and right half recursively.
"""
if len(lt) == 1:
return Node(lt[0])
if len(lt) == 0:
return None
mid = (len(lt)-1)//2
left = build_balanced_bst(lt[:mid])
right = build_balanced_bst(lt[mid+1:])
root = Node(lt[mid], left, right)
return root
ordered_list = list(range(1,11))
bst=build_balanced_bst(ordered_list)
bst_repr = str_tree(bst)
print(bst_repr)
The output comes out as follows:
......10
....9
..8
......7
....6
5
......4
....3
..2
....1
I have a node class in python which is something like this
class Node:
def __init__(self, value, next, prev, rand):
self.value = value
self.next = next
self.prev = prev
self.rand = rand
I create a list out of this by creating nodes and setting the appropriate pointers. Now, i want to pretty print this list : like [1] --> [2] --> [3] and so on. If there is a random pointer along with next it will be [1] --> [2] --> [3,4] -->[4] for example. here 2 next is 3 and 2 rand is 4 while 3 next is 4. I am trying to do this with the built-in str() method in the node class it self. I have it as below as of now
#pretty print a node
def __str__(self):
if self.next is None:
return '[%d]' % (self.value)
else:
return '[%d]-->%s' % (self.value, str(self.next))
This pretty prints it without the random pointer. But I am not able to incorporate the random pointer printing in this. I tried couple of approaches, but it's messing up the brackets. How would i go about this ?
Thanks
Try factoring the printing of the pointers out, that way it may be clearer:
#pretty print a node
def __str__(self):
if self.next is None:
return self.stringify_pointers()
else:
return '%s-->%s' % (self.stringify_pointers(), str(self.next))
def stringify_pointers(self):
s = '['
if self.next:
s += str(self.next) + (',' if self.rand else '')
if self.rand:
# <> to distinguish rand from next
s += '<%s>' % str(self.rand)
return s + ']'
One way to do it is using array slices on the string and injecting the random value into the next node string like this
def __str__(self):
if self.next is None:
return '[%d]' % (self.value)
else:
nn = str(self.next)
if self.rand != None:
nn = '%s,%d%s' % (nn[:2], self.rand, nn[2:])
return '[%d]-->%s' % (self.value, nn)
Trying to write a function that will iterate over the linked list, sum up all of the odd numbers and then display the sum. Here is what I have so far:
def main():
array = eval(input("Give me an array of numbers: "))
ArrayToList(array)
print(array[0])
print(array[1])
print(array[2])
print(array[3])
print(sumOdds(array))
def isOdd(x):
return x % 2 != 0
def sumOdds(array):
if (array == None):
return 0
elif (isOdd(head(array))):
return head(array) + sumOdds(tail(array))
else:
return sumOdds(tail(array))
main()
I can't get it to actually print the sum though. Can anybody help me out with that?
Here is the output of the program when I run it:
$ python3 1.py
Give me an array of numbers: [11, 5, 3, 51]
Traceback (most recent call last):
File "1.py", line 22, in <module>
main()
File "1.py", line 10, in main
print(sumOdds(array))
File "1.py", line 19, in sumOdds
return head(array) + sumOdds(tail(array))
File "1.py", line 18, in sumOdds
elif (isOdd(head(array))):
File "/Users/~/cs150/practice3/friday/List.py", line 34, in head
return NodeValue(items)
File "/Users/~/cs150/practice3/friday/List.py", line 12, in NodeValue
def NodeValue(n): return n[0]
TypeError: 'int' object is not subscriptable
I'd suggest NOT using eval, for starters.
If you just want input from the console just go for raw_input and prompt the user to enter commas or some other delimiting character.
number_string = raw_input("Give me a string of numbers separated by commas, plz.")
Once you have this you can use list comprehension to glean the actual list from the data. int() is pretty good about ignoring whitespace. Maybe this is what yourArrayToList() does, but this works as well.
number_list = [int(x) for x in number_string.split(",")]
Also, if you want to simply iterate over the list and print the received values, might I suggest a for loop instead of just hard-coding the first four items?
for num in number_list:
print num
Additionally, the if (array == None) is a bit less pythonic than if not array:, and really the sum() function is smart enough to just return 0 if the list has no length anyway.
def sum_the_odds(yourlist):
return sum([x for x in yourlist if x % 2 == 1])
So to put it in context:
def sum_the_odds(yourlist):
return sum([x for x in yourlist if x % 2 == 1])
def main():
number_string = raw_input("Give me a string of numbers separated by commas, plz.")
number_list = [int(x) for x in number_string.split(",")]
for num in number_list:
print num
print sum_the_odds(number_list)
I would just implement a filter/reduce function from within the list and just pass a function into the filter_reduce(func) function to accumulate the sum of the filtered items.
You can check out the live demo here: Python Fiddle
def calc_product(a, b):
return a * b
def calc_summation(a, b):
return a + b
def is_odd(x):
return x % 2 != 0
l = linked_list()
l.insert_end(1)
l.insert_end(2)
l.insert_end(3)
l.insert_end(5)
l.insert_beginning(0)
l.insert_after(4, 3)
print 'List:', l
print 'Size:', l.size()
# Calculates the sum of all odd values in the list:
print 'Summation:', l.filter_reduce(calc_summation, is_odd)
# Calculates the product of all values with the accumulator
# initialized at 10.
print 'Product:', l.filter_reduce(calc_product, lambda x: True, 10)
Output
List: 0, 1, 2, 3, 4, 5
Size: 6
Summation: 9
Product: 1200
linked_list.py
class linked_list():
class node():
def __init__(self, data=None):
self.data = data
self.next = None
def __str__(self):
return str(data)
class list_iterator():
def __init__(self, current_node=None):
self.current_node = current_node
def hasNext(self):
return self.current_node.next is not None
def next(self):
if not self.hasNext():
return None
self.current_node = self.current_node.next;
return self.current_node.data;
def __init__(self):
self.head = None
self._size = 0
def iterator(self):
return self.list_iterator(self.head)
def is_empty(self):
return self.head is None
def size(self):
return self._size
def insert_after(self, data, index):
new_node = self.node(data)
curr_node = self.head
i = 0
while curr_node is not None and i < index:
curr_node = curr_node.next
i += 1
new_node.next = curr_node.next
curr_node.next = new_node
self._size += 1
def insert_beginning(self, data):
new_node = self.node(data)
if self.is_empty():
self.head = new_node
else:
new_node.next = self.head
self.head = new_node
self._size += 1
def insert_end(self, data):
new_node = self.node(data)
if self.is_empty():
self.head = new_node
else:
curr_node = self.head
while curr_node.next is not None:
curr_node = curr_node.next
curr_node.next = new_node
self._size += 1
def filter_reduce(self, reduce_func, filter_func=None, initializer=None):
it = self.iterator()
if initializer is None:
try:
initializer = it.next()
except StopIteration:
raise TypeError('reduce() of empty sequence with no initial value')
accum_value = initializer
while it.hasNext():
data = it.next()
if filter_func is None or filter_func(data):
accum_value = reduce_func(accum_value, data)
return accum_value
def __str__(self):
s, it = '', self.iterator()
while it.hasNext():
s += str(it.next())
if it.hasNext():
s += ', '
return s
Your line ArrayToList(array) is suspicious. Because I don't know what it is suppose to do. I suspect it is suppose to convert your python list into a customly defined version of a list. If this is the case, I'm guessing it has a return value. So try changing your main function to do this:
def main():
user_input = eval(input("Give me an array of numbers: "))
custom_list = ArrayToList(user_input) # convert user input to a custom list.
print(sumOdds(custom_list))
You could see if that works for you.
The actual problem you are having is with the tail() function (or your understanding of what tail is suppose to return). As it is, tail is returning an int and you are expecting it to return a list. If you didn't write the tail function, try using just the tail function and observe its output to gain a good understanding of how it should be used. I suggest just running this code and seeing what it does:
def main():
print(tail([1, 2, 3, 4])) # Your code assumes tail returns [2, 3, 4]
here this is the node definition
class Node(object):
def __init__(self,value=None):
self.value = value
self.next = None
this is the conversion for the code a number to linked list
def number_to_list(number):
head,tail = None,None
p = True
for x in str(number):
if x=='-':
p = False
continue
else:
if p:
node = Node(int(x))
else:
node = Node(int("-"+x))
if head:
tail.next = node
else:
head = node
tail = node
return head
pass
this is code for conversion of linked list to number
def list_to_number(head):
neg = False
num = ''
for number in head:
val = str(number)
if (val.find('-')!= -1):
neg = True
num=num+val.replace('-','')
if (neg==False):
return int(num)
else:
return -1*int(num)
pass
here it is the test cases
def test_number_to_list():
import listutils
head = number_to_list(120)
assert [1,2,0] == listutils.from_linked_list(head)
assert 120 == list_to_number(head)
head = number_to_list(0)
assert [0] == listutils.from_linked_list(head)
assert 0 == list_to_number(head)
head = number_to_list(-120)
assert [-1, -2, 0] == listutils.from_linked_list(head)
assert -120 == list_to_number(head)
here from_linked_list means
# avoids infinite loops
def from_linked_list(head):
result = []
counter = 0
while head and counter < 100: # tests don't use more than 100 nodes, so bail if you loop 100 times.
result.append(head.value)
head = head.next
counter += 1
return result
at last in this the problem is while converting the linked list to single number it is encountering an error i.e.,node object is not iterable
please help me out of this to write the code
def list_to_number(head):
neg = False
num = ''
for number in head:
val = str(number)
TypeError: 'Node' object is not iterable
here this is the traceback
The
for number in head:
is not a correct way to iterate of the list.
You need to start from head and then follow the chain of next references.
Note that if __iter__ is defined on Node like this:
class Node(object):
def __init__(self,value=None):
self.value = value
self.next = None
def __iter__(self):
that = self
while that is not None:
yield that.value
that = that.next
Then:
for number in head:
Would actually work.