python for and while loop for tuples - python

I'm a beginner in python and was wondering why this function doesn't work. It is syntactically correct.
This function is supposed to collect every odd tuple item and I used a for loop as follows:
def oddTuples(aTup):
result = ()
for i in aTup:
if i % 2 == 0:
result += (aTup[i],)
return result
This is the 'correct' answer using while loop.
def oddTuples(aTup):
# a placeholder to gather our response
rTup = ()
index = 0
# Idea: Iterate over the elements in aTup, counting by 2
# (every other element) and adding that element to
# the result
while index < len(aTup):
rTup += (aTup[index],)
index += 2
return rTup
If anybody can help me, it would be much appreciated!
UPDATE
Okay, I got the problem, by 'i' I was merely collecting the real value within that tuple. I've fixed that, but this code is catching only some of the odd-idexed items, not all of them....
def oddTuples(aTup):
result = ()
for i in aTup:
index = aTup.index(i)
if index % 2 == 0:
result += (aTup[index],)
return result

Your for loop is iterating over the values in aTup, not the index of the values.
It appears your want your code to iterate over the index of the values or through a range of numbers starting with 0 and ending with the length of the tuple minus one and then use that number as the index to pull the value out of the tuple.

I didn't catch it on one go since it was syntactically correct too, but the error you are having is due to you iterating over the objects of the tuple (aTup) and not the indices. See here:
for i in aTup: # <-- For each *object* in the tuple and NOT indices
if i % 2 == 0:
result += (aTup[i],)
To fix the problem, use range() and len() over the aTup so that it iterates over the indices of the tuple instead, and change the if statement accordingly:
for i in range(len(aTup)):
if aTup[i] % 2 == 0:
result += (aTup[i],)
An alternative solution is to keep your object iterations but append the object directly to the result tuple instead of indexing:
for i in aTup:
if i % 2 == 0:
result += (i,)
Hope ths helped!

The reason is you are not using index..In below code i is not an index but the element in tuple but you are calling aTup[i] assuming i is an index which is not.
The below code will work fine - No need of doing aTup[i] or range.
def oddTuples(aTup):
result = ()
for i in aTup:
if i % 2 == 0:
result += (i,)
return result

Try replacing
def oddTuples(aTup):
result = ()
for i in aTup:
index = aTup.index(i)
if index % 2 == 0:
result += (aTup[index],)
return result
With
def oddTuples(aTup):
result = ()
for i in aTup:
index = aTup.index(i)
result += (aTup[index],)
return result
To fix you issue of it only doing the even numbered ones.

In simple words , if your tuple is
tup = (1, 2, 3, 4, 5 , 1000);
When your code is checking if each item is % 2 == 0 or not which is not what you want, from your description , you want only the items with odd index
So if you try the tuple above , you will get the following error:
IndexError: tuple index out of range , because for the 1000 it satisfy your condition and will do what is said in the if , trying to add the aTup(1000) (element of index 1000 in your input tuple) which doesn't exist as the tuple is only of 6 elements to your resultTuple
For this for loop to work , you can use the following method
def oddTuples(aTup):
result = ()
for i in aTup:
index = tup.index(i) # getting the index of each element
if index % 2 == 0:
result += (aTup[index],)
print(aTup[index])
return result
# Testing the function with a tuple
if __name__ == "__main__":
tup = (1, 2, 3, 7, 5, 1000, 1022)
tup_res = oddTuples(tup)
print(tup_res)
The result of this will be
1
3
5
1022
(1, 3, 5, 1022)
Process finished with exit code 0

Related

Python - List Binary Search without bisect

I have a list and I want to binary_search a key(number).
My code is below but I don't have a clue what to do where the bold text on code is:
(What to do with this? Is an other function? int imid = midpoint(imin, imax))
List = []
x = 1
#Import 20 numbers to list
for i in range (0,20):
List.append (i)
print (List)
key = input("\nGive me a number for key: ")
def midpoint(imin, imax):
return point((imin+imax)/2)
def binary_search(List,key,imin,imax,point):
while (imax >= imin):
int imid = midpoint(imin, imax)
if(List[imid] == key):
return imid;
elif (List[imid] < key):
imin = imid + 1;
else:
imax = imid - 1;
return KEY_NOT_FOUND;
print (binary_search(key))
midpoint(imin, imax)
binary_search(List,key,imin,imax,point)
It doesn't seem to be doing anything for you; remove the call to midpoint, and point, and just have
def binary_search(List,key,imin,imax,point):
while (imax >= imin):
imid = (imin + imax) / 2
(However, there are some things wrong with your code, and it won't work with just that change;
You create a list called List then try to append to an uninitialized variable called myList
You 'import 20 random' numbers, but range() is not random, it's a simple sequence 1, 2, 3, 4...
range already returns a list, no need to count through it and copy it, just use it
You call binary_search with an empty List, a key, and three uninitialized variables
binary_search assumes the list is sorted, which it is, but if the comment about 'random numbers' was correct, it wouldn't be.
)

Python: Determine whether list of lists contains a defined sequence

I have a list of sublists, and I want to see if any of the integer values from the first sublist plus one are contained in the second sublist. For all such values, I want to see if that value plus one is contained in the third sublist, and so on, proceeding in this fashion across all sublists. If there is a way of proceeding in this fashion from the first sublist to the last sublist, I wish to return True; otherwise I wish to return False. For each value in the first sublist, I want to see if one can find that value plus n in each sublist reading left to right, where n is the index value of that sublist within the larger list.. (Sorry for the clumsy phrasing--I'm not sure how to clean up my language without using many more words.)
EDIT: (The previous articulation of desired output is ambiguous.) For each value in the first sublist, I want to see if one can find that value plus n in each sublist reading left to right, where n is the index value of that sublist within the larger list.
Here's what I wrote.
a = [ [1,3],[2,4],[3,5],[6],[7] ]
def find_list_traversing_walk(l):
for i in l[0]:
index_position = 0
first_pass = 1
walking_current_path = 1
while walking_current_path == 1:
if first_pass == 1:
first_pass = 0
walking_value = i
if walking_value+1 in l[index_position + 1]:
index_position += 1
walking_value += 1
if index_position+1 == len(l):
print "There is a walk across the sublists for initial value ", walking_value - index_position
return True
else:
walking_current_path = 0
return False
print find_list_traversing_walk(a)
My question is: Have I overlooked something simple here, or will this function return True for all true positives and False for all true negatives? Are there easier ways to accomplish the intended task? I would be grateful for any feedback others can offer!
You can view the desired operation as a reduction on a sequence of sets where the reducing operation is the following function:
In [25]: def func(x, y):
....: return set([t+1 for t in x]) & set(y)
....:
That is, func takes two collections, adds 1 to each element in the first collection, and returns the intersection of that and the second collection. Apply this function sequentially across a. If the final result is not an empty set, the answer is True:
In [29]: a = [ [1,3],[2,4],[3,5],[6],[7] ]
In [30]: bool(reduce(func, a))
Out[30]: True
In [31]: b = [ [1],[2,4],[5] ]
In [32]: bool(reduce(func, b))
Out[32]: False
(bool converts a non-empty set to True and an empty set to False.)
Note that if the input is typically a very long sequence, and you expect to know that the answer is False within a few steps, this is not a very efficient solution, since it always traverses the entire input.
Are there easier ways to accomplish the intended task?
Yes, it will be easier to define a recursive solution:
def find(lst, index):
if index == len(lst)-1:
return True
for i in lst[index]:
if i+1 in lst[index+1]:
return find(lst, index+1)
else:
return False
a = [ [1,3],[2,4],[3,5],[6],[7] ]
print find(a, 0) # prints "True"
a = [ [1,3],[2,4],[3,5],[6],[7], [9] ]
print find(a, 0) # prints "False"
UPDATE
What you describe in your comment is a bit more complex (the need for the next+1 to be one of the "guys" that were used before) - but not much:
def find(lst, part_res, index):
if index == len(lst)-1:
return True
found = False
new_part_res = []
for i in part_res:
if i+1 in lst[index+1]:
found = True
new_part_res.append(i+1)
if not found:
return False
else:
return find(lst, new_part_res, index+1)
a = [ [1,3],[2,4],[3,5],[6],[7] ]
print find(a, a[0], 0) # True
a = [ [1],[2,4],[5] ]
print find(a, a[0], 0) # False
I also thought it was expressed better recursively. If I understood your problem correctly, this is what I came up with.
a = [ [1,3],[2,4],[3,5],[6],[7] ]
b = [ [1],[2,4],[5] ]
c = [ [1,3],[2,4],[3,5],[6, 4],[5, 7] ]
def foo(data):
if len(data) == 1:
return True
return all(item + 1 in data[1] for item in data[0]) and foo(data[1:])
print foo(a), foo(b), foo(c)
>>>
False False True
>>>

Smallest Number in a List - Python

I am trying to write a function that takes a list input and returns the index of the smallest number in that list.
For example,
minPos( [5,4,3,2,1] ) → 4
When I run my function, I get a List Index error, can someone please help? Thanks. I cannot use the built in function min().
def MinPos(L):
Subscript = 0
Hydrogen = 1
SmallestNumber = L[Subscript]
while L[Subscript] < len(L):
while L[Subscript] < L[Subscript + Hydrogen]:
Subscript += 1
return SmallestNumber
while L[Subscript] > L[Subscript + Hydrogen]:
Subscript += 1
return SmallestNumber
def main():
print MinPos( [-5,-4] )
Maybe something like this:
>>> def min_pos(L):
... min = None
... for i,v in enumerate(L):
... if min is None or min[1] > v:
... min = (i,v)
... return min[0] if min else None
>>> min_pos([1,3,4,5])
0
>>> min_pos([1,3,4,0,5])
3
Edit: Return None if empty list
Since you already know how to find the minimum value, you simply feed that value to the index() function to get the index of this value in the list. I.e,
>>> n = ([5,4,3,2,1])
>>> n.index(min(n))
4
This will return the index of the minimum value in the list. Note that if there are several minima it will return the first.
I would recommend use of for ... and enumarate():
data = [6, 3, 2, 4, 2, 5]
try:
index, minimum = 0, data[0]
for i, value in enumerate(data):
if value < minimum:
index, minimum = i, value
except IndexError:
index = None
print index
# Out[49]: 2
EDIT added guard against empty data

python recursive pascal triangle

After completing an assignment to create pascal's triangle using an iterative function, I have attempted to recreate it using a recursive function. I have gotten to the point where I can get it to produce the individual row corresponding to the number passed in as an argument. But several attempts to have it produce the entire triangle up to and including that row have failed. I even tried writing a separate function which iterates over the range of the input number and calls the recursive function with the iterated digit while appending the individual lines to list before returning that list. The desired output should be a list of lists where each internal list contains one row of the triangle. Like so:
[[1], [1, 1], [1, 2, 1]...]
Instead it returns a jumbled mess of a nested list completely filled with 1's.
Here is the recursive function in question, without the second function to append the rows (I really wanted 1 all inclusive function anyway):
def triangle(n):
if n == 0:
return []
elif n == 1:
return [1]
else:
new_row = [1]
last_row = triangle(n-1)
for i in range(len(last_row)-1):
new_row.append(last_row[i] + last_row[i+1])
new_row += [1]
return new_row
To be clear, I have already completed the assigned task, this is just to provide a deeper understanding of recursion...
Iterative solution:
def triangle(n):
result = []
for row in range(n):
newrow = [1]
for col in range(1, row+1):
newcell = newrow[col-1] * float(row+1-col)/col
newrow.append(int(newcell))
result.append(newrow)
return result
You just need to pass a list of lists through the recursion, and pick off the last element of the list (i.e. the last row of the triangle) to build your new row. Like so:
def triangle(n):
if n == 0:
return []
elif n == 1:
return [[1]]
else:
new_row = [1]
result = triangle(n-1)
last_row = result[-1]
for i in range(len(last_row)-1):
new_row.append(last_row[i] + last_row[i+1])
new_row += [1]
result.append(new_row)
return result
An alternative to happydave's solution, using tail recursion:
def triangle(n, lol=None):
if lol is None: lol = [[1]]
if n == 1:
return lol
else:
prev_row = lol[-1]
new_row = [1] + [sum(i) for i in zip(prev_row, prev_row[1:])] + [1]
return triangle(n - 1, lol + [new_row])
I think its shod be helpful, this code draw triangle and do it recursively:
def traingle(n):
if n == 1:
print(1)
return [1]
else:
answer = [1]
print_able = '1 '
previos = traingle(n-1)
for index in range(len(previos)-1):
eleman = previos[index]+previos[index+1]
answer.append(eleman)
print_able += str(eleman)+' '
answer.append(1)
print_able += '1'
print(print_able)
return answer
end = int(input())
traingle(end)
Yes, as Karl Knechtel also showed, recursive Pascal Triangle can go this way :
P=lambda h:(lambda x:x+[[x+y for x,y in zip(x[-1]+[0],[0]+x[-1])]])(P(h-1))if h>1 else[[1]]
print(P(10))

counting odd numbers in a list python

This is a part of my homework assignment and im close to the final answer but not quite yet. I need to write a function that counts odd numbers in a list.
Create a recursive function count_odd(l) which takes as its only argument a list of integers. The function will return a count of the number of list elements that are odd, i.e., not evenly divisible by 2.\
>>> print count_odd([])
0
>>> print count_odd([1, 3, 5])
3
>>> print count_odd([2, 4, 6])
0
>>> print count_odd([0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144])
8
Here is what i have so far:
#- recursive function count_odd -#
def count_odd(l):
"""returns a count of the odd integers in l.
PRE: l is a list of integers.
POST: l is unchanged."""
count_odd=0
while count_odd<len(l):
if l[count_odd]%2==0:
count_odd=count_odd
else:
l[count_odd]%2!=0
count_odd=count_odd+1
return count_odd
#- test harness
print count_odd([])
print count_odd([1, 3, 5])
print count_odd([2, 4, 6])
print count_odd([0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144])
Can u help explain what im missing. The first two test harness works fine but i cant get the final two. Thanks!
Since this is homework, consider this pseudo-code that just counts a list:
function count (LIST)
if LIST has more items
// recursive case.
// Add one for the current item we are counting,
// and call count() again to process the *remaining* items.
remaining = everything in LIST except the first item
return 1 + count(remaining)
else
// base case -- what "ends" the recursion
// If an item is removed each time, the list will eventually be empty.
return 0
This is very similar to what the homework is asking for, but it needs to be translate to Python and you must work out the correct recursive case logic.
Happy coding.
def count_odd(L):
return (L[0]%2) + count_odd(L[1:]) if L else 0
Are slices ok? Doesn't feel recursive to me, but I guess the whole thing is kind of against usual idioms (i.e. - recursion of this sort in Python):
def countOdd(l):
if l == list(): return 0 # base case, empty list means we're done
return l[0] % 2 + countOdd(l[1:]) # add 1 (or don't) depending on odd/even of element 0. recurse on the rest
x%2 is 1 for odds, 0 for evens. If you are uncomfortable with it or just don't understand it, use the following in place of the last line above:
thisElement = l[0]
restOfList = l[1:]
if thisElement % 2 == 0: currentElementOdd = 0
else: currentElementOdd = 1
return currentElementOdd + countOdd(restOfList)
PS - this is pretty recursive, see what your teacher says if you turn this in =P
>>> def countOdd(l):
... return fold(lambda x,y: x+(y&1),l,0)
...
>>> def fold(f,l,a):
... if l == list(): return a
... return fold(f,l[1:],f(a,l[0]))
All of the prior answers are subdividing the problem into subproblems of size 1 and size n-1. Several people noted that the recursive stack might easily blow out. This solution should keep the recursive stack size at O(log n):
def count_odd(series):
l = len(series) >> 1
if l < 1:
return series[0] & 1 if series else 0
else:
return count_odd(series[:l]) + count_odd(series[l:])
The goal of recursion is to divide the problem into smaller pieces, and apply the solution to the smaller pieces. In this case, we can check if the first number of the list (l[0]) is odd, then call the function again (this is the "recursion") with the rest of the list (l[1:]), adding our current result to the result of the recursion.
def count_odd(series):
if not series:
return 0
else:
left, right = series[0], series[1:]
return count_odd(right) + (1 if (left & 1) else 0)
Tail recursion
def count_odd(integers):
def iter_(lst, count):
return iter_(rest(lst), count + is_odd(first(lst))) if lst else count
return iter_(integers, 0)
def is_odd(integer):
"""Whether the `integer` is odd."""
return integer % 2 != 0 # or `return integer & 1`
def first(lst):
"""Get the first element from the `lst` list.
Return `None` if there are no elements.
"""
return lst[0] if lst else None
def rest(lst):
"""Return `lst` list without the first element."""
return lst[1:]
There is no tail-call optimization in Python, so the above version is purely educational.
The call could be visualize as:
count_odd([1,2,3]) # returns
iter_([1,2,3], 0) # could be replaced by; depth=1
iter_([2,3], 0 + is_odd(1)) if [1,2,3] else 0 # `bool([1,2,3])` is True in Python
iter_([2,3], 0 + True) # `True == 1` in Python
iter_([2,3], 1) # depth=2
iter_([3], 1 + is_odd(2)) if [2,3] else 1
iter_([3], 1 + False) # `False == 0` in Python
iter_([3], 1) # depth=3
iter_([], 1 + is_odd(3)) if [3] else 1
iter_([], 2) # depth=4
iter_(rest([]), 2 + is_odd(first([])) if [] else 2 # bool([]) is False in Python
2 # the answer
Simple trampolining
To avoid 'max recursion depth exceeded' errors for large arrays all tail calls in recursive functions can be wrapped in lambda: expressions; and special trampoline() function can be used to unwrap such expressions. It effectively converts recursion into iterating over a simple loop:
import functools
def trampoline(function):
"""Resolve delayed calls."""
#functools.wraps(function)
def wrapper(*args):
f = function(*args)
while callable(f):
f = f()
return f
return wrapper
def iter_(lst, count):
#NOTE: added `lambda:` before the tail call
return (lambda:iter_(rest(lst), count+is_odd(first(lst)))) if lst else count
#trampoline
def count_odd(integers):
return iter_(integers, 0)
Example:
count_odd([1,2,3])
iter_([1,2,3], 0) # returns callable
lambda:iter_(rest(lst), count+is_odd(first(lst))) # f = f()
iter_([2,3], 0+is_odd(1)) # returns callable
lambda:iter_(rest(lst), count+is_odd(first(lst))) # f = f()
iter_([3], 1+is_odd(2)) # returns callable
lambda:iter_(rest(lst), count+is_odd(first(lst))) # f = f()
iter_([], 1+is_odd(3))
2 # callable(2) is False
I would write it like this:
def countOddNumbers(numbers):
sum = 0
for num in numbers:
if num%2!=0:
sum += numbers.count(num)
return sum
not sure if i got your question , but as above something similar:
def countOddNumbers(numbers):
count=0
for i in numbers:
if i%2!=0:
count+=1
return count
Generator can give quick result in one line code:
sum((x%2 for x in nums))

Categories

Resources