Explain for loop - python

I was trying the below code. Kindly go through below code and help me understand what is the logic to get the below output.
I was trying to add only the first 10 values or first 9 values out of the given 11 values.
nums = [1,3,5,7,9,1,3,2,4,5,6]
def random(nums):
count = 0
for x in range(len(nums)-2):
count = count + x
return count
print("The random addition for above prog is")
print(random(nums))
output:
The random addition for above prog is
36
when I replaced with for x in range(len(nums)-2) i am getting below o/p
The random addition for above prog is
45
when I replaced with for x in range(len(nums)) i am getting below o/p
The random addition for above prog is
55
on what basis I should use the logic range(len(nums)-2) or range(len(nums)-3) in using the for loop.

You added index value that created by range, not list values.
count += x # this is one of [0,1...]
len and range's behavior is below.
len returns number of value list contains
>>> nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> len(nums)
11
range returns n length list start with 0(usable for list index)
>>> range(11)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
python's for takes one value from list, and do something and take next one value...
for i in [1,3,2]:
print(i)
1
3
2
If you want to take first 10 value of list and loop them, you can do below.
for i in range(10):
print(nums[i])
length of list can create range's arg 10 with below
len(nums) - 1
# => 11 - 1
# => 10
integrate them for first 10 values of list
for i in range(len(nums) - 1):
print(nums[i])
if you want sum random values
count = 0
>>> for i in range(len(nums) - 1):
... print(i, nums[i])
... count += nums[i]
...
(0, 1)
(1, 3)
(2, 5)
(3, 7)
(4, 9)
(5, 1)
(6, 3)
(7, 2)
(8, 4)
(9, 5)
>>> count
40
>>>
If you want to just sum first 10 value of list with loop, you can write below
count = 0
for x in nums[:10]:
count += x
nums[:10] returns list contains first 10 values of nums like [1,3,5,...8]

Related

how to fix this program to show output as 4 numbers per row in python

I have written a program where I need to input a length and it returns the digits in the Fibonacci number sequence.
Write a program that given an input n, outputs the first n Fibonacci numbers. The format of the output is that at most 4 numbers can be displayed in a row.
My problem is, when i run the program the output shows [0, 1, 1, 2, 3, 5, 8, 13, 21, 34].
I need the solution to show 4 numbers per row ie
0 1 1 2
3 5 8 13
21 34
Please find attached my code.
def number(n):
if n ==1:
print(0)
else:
li = [0, 1]
for i in range(2, n): # start the loop from second index as 'li' is assigned for 0th and 1st index
li.append(li[-1] + li[-2])
i += 1
print(li)
n = int(input('Enter a positive number:'))
number(n)
Can you please explain how I can achieve the desired result?
The trouble is this line of code:
print(li)
which only prints out a big list.
Instead, split the list into groups of 4:
li = [li[i:i+4] for i in range(0, len(li), 4)]
Now you can print each element in this list, with a newline so that they are on different lines:
print(*li, sep="\n")
This "unpacks" the list into its elements (which are themselves lists of at most length 4), then prints them out, separating each element with a newline.
Putting it all together:
def number(n):
if n ==1:
print(0)
else:
li = [0, 1]
for i in range(2, n): # start the loop from second index as 'li' is assigned for 0th and 1st index
li.append(li[-1] + li[-2])
i += 1
li = [li[i:i+4] for i in range(0, len(li), 4)]
print(*li, sep="\n")
>>> number(10)
[0, 1, 1, 2]
[3, 5, 8, 13]
[21, 34]

Seating arrangement - How do i pick only the neighbors combinations

i used itertools.combinations to list all possible combinations of a list...but how do i pick only the neighbors so that the users are all together
list =[1,2,3,4,5,6,7,8,9,10,11,12]
occupied = [2,6,7,11]
remaining seats are available... Now how do i arrange two folks together always in the available seats..
1 0
3 4
5 0
0 8
9 10
0 12
the right combinations are (1,3) (3,4) (3,5) (8,9) (9,10) (10,12) (since its two folks..we can interchange them.. so two possible ways)... altogether at the moment i have 28...how do i remove the rest..any guidance would be appreciated
/*just added my code/
import numpy as np
import itertools
from itertools import permutations, combinations, combinations_with_replacement
def seatingarrangement (arr):
arry = arr.split(',')
larr = [int(x) for x in arry]
total = (larr[0])
occ = larr[1:]
totals = [x+1 for x in range(0,total)]
print(totals)
for val in totals:
if val in occ:
item= totals.index(val)
totals[item] = 0
print(totals)
#result = list(filter(lambda x: x!=0, totals))
result = [x for x in totals if x != 0]
print(result)
comb = combinations(result,2)
data = itertools.dropwhile(lambda x: x < 5, [3, 12, 7, 1, -5])
print(list(comb))
avl = []
#total there are 8 seats and two users are to be seated next to each other always ... #moreover the seats are not all consecutive
for i,x in enumerate(totals):
if (i+1)%2 == 0:
print('even#:',i+1,'is :',x)
data = itertools.dropwhile()
print(data)
else:
print('odd#:',i+1,'is :',x)
I'd suggest a method that verifies the validity of a pair, regarding the occupied list and the position
def is_pair_valid(pair, occupied_list):
# check occupied
x, y = min(pair), max(pair)
if x in occupied_list or y in occupied_list:
return False
# check neighbours
diff = y - x
return diff in (2, 1, -2) if x % 2 == 1 else diff in (2, -1, -2)
odd number : the other should be at distance +2, +1 or -2 (ex 3 with 1,4,5)
even number : the other should be at distance +2, -1 or -2 (ex 4 with 2,3,6)
Then
values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
occupied = [2, 6, 7, 11]
for p in filter(lambda x: is_pair_valid(x, occupied), combinations(values, r=2)):
print(p)
Gives the correct
(1, 3)
(3, 4)
(3, 5)
(8, 10)
(9, 10)
(10, 12)

How to count the number of items in several bins using loop in python? details showed in picture

Question details showed in the picture Thanks for your help.
Write a function histogram(values, dividers) that takes as argument a sequence of values and a sequence of bin dividers, and returns the histogram as a sequence of a suitable type (say, an array) with the counts in each bin. The number of bins is the number of dividers + 1; the first bin has no lower limit and the last bin has no upper limit. As in (a), elements that are equal to one of the dividers are counted in the bin below.
For example, suppose the sequence of values is the numbers 1,..,10 and the bin dividers are array(2, 5, 7); the histogram should be array(2, 3, 2, 3).
Here is my code
def histogram(values, dividers):
count=0
for element in values:
index=0
i=0
count[i]=0
while index < len(dividers) - 2:
if element <= dividers[index]:
i=dividers[index]
count[i] += 1
index=len(dividers)
elif element > dividers[index] and element <= dividers[index+1]:
i=dividers[index]
count[i] += 1
index= len(dividers)
index += 1
return count[i]
from bisect import bisect_left
# Using Python builtin to find where value is in dividers
(this is O(log n) for each value)
def histogram(values, dividers):
count = [0]*(1+len(dividers))
for element in values:
i = bisect_left(dividers, element)
count[i] += 1
return count
values = list(range(1, 11)) # list from 1 through 10
bins = [2, 5, 7]
c = histogram(values, bins) # Result [2, 3, 2, 3]
Explanation of histogram
1. bisect_left finds the bin the index the value should be inserted
2. We update count array according to this index. Count array size is
(1+len(bins)), to allow for values > bins[-1]
A simple implementation would be to prepare a list of counters of size len(dividers)+1.
Go through all numbers provided:
if your current number is bigger then the largest bin-divider, increment the last bins counter
else go through all dividers until your number is no longer bigger as it, and increment that bin-counter by 1
This leads to:
def histogram(values, dividers):
bins = [0 for _ in range(len(dividers)+1)]
print (bins)
for num in values:
if num > dividers[-1]:
bins[-1] += 1
else:
k = 0
while num > dividers[k]:
k+=1
bins[k] += 1
return bins
print(histogram(range(20),[2,4,9]))
Output:
# counts
[3, 2, 5, 10]
Explanation
Dividers: [2,4,9]
Bins: [ 2 and less | 4 | 9 | 10 and more ]
Numbers: 0..19
0, 1, 2 -> not bigger then 9, smaller/equal 2
3, 4 -> not bigger then 9, smaller/equal 4
5, 6, 7, 8, 9 -> not bigger then 9, smaller/equal 9
10, 11, 12, 13, 14, 15, 16, 17, 18, 19 -> bigger 9
This is a naive implementation and there are faster ones using tree like data structures for more performance. Consider a divider of [5,6,7] and a list of [7,7,7,7,7,7] this would run 6 times (6*7) testing for bins 3 times (bigger then 5, bigger then 6, not bigger then 7) == 18 unrolled loops.
There are more efficient algos possible using better suited data structures.

How can I find the indices of any two of the numbers, whose sum is equal to the target sum in Python?

I'm doing this test on testdome.com for practicing , and it's failing some test case. Can anyone help me pointing out the logic error in my code?
This is the question for my code:
"Write a function that, when passed a list and a target sum, returns, efficiently with respect to time used, two distinct zero-based indices of any two of the numbers, whose sum is equal to the target sum.
If there are no two numbers, the function should return None.
For example, find_two_sum([3, 1, 5, 7, 5, 9], 10) should return a single tuple containing any of the following pairs of indices:
0 and 3 (or 3 and 0) because addition of 3 and 7 is 10.
1 and 5 (or 5 and 1) because addition of 1 and 9 is 10.
2 and 4 (or 4 and 2) because addition of 5 and 5 is 10.
def find_two_sum(numbers, target_sum):
sss=list(dict.fromkeys(numbers))
if (sss == None or len(sss) < 2): return None
for item in sss:
tesn=target_sum-item
if tesn in sss:
if numbers.index(item)==numbers.index(tesn):
continue
else:
return numbers.index(item),numbers.index(tesn)
return None
print(find_two_sum([3, 1, 5, 7, 5, 9], 10))
They have four test cases and my code can only pass first two test cases.
Example case:Wrong answer ( to return [0,2] because 3 of index 0 + 7 of index 3 is 10)
Distinct numbers with and without solutions: Wrong answer
Duplicate numbers with and without solutions: Wrong answer
Performance test with a large list of numbers: Wrong answer
My take on the problem:
def find_two_sum(lst, n):
indices = {}
for idx, num in enumerate(lst):
indices.setdefault(num, []).append(idx)
for k, v in indices.items():
i = v.pop()
if n - k in indices and indices[n-k]:
return i, indices[n-k].pop()
print( find_two_sum([3, 1, 5, 7, 5, 9], 6) )
print( find_two_sum([3, 1, 5, 7, 5, 9], 10) )
print( find_two_sum([1, 2, 1, 8], 10) )
print( find_two_sum([5, 5], 10) )
print( find_two_sum([11], 10) )
Prints:
(1, 4)
(0, 3)
(1, 3)
(1, 0)
None
I believe you have to add a check for the two indexes to be distinct.
For example here:
print(find_two_sum([3, 1, 5, 7, 5, 9], 6))
The function will give an answer of (0, 0) which wouldn't be correct, though these are the indexes of 3, which gives a sum of 6 with itself .
Here, I've added the check for distinct indexes:
def find_two_sum(numbers, target_sum):
sss = list(dict.fromkeys(numbers))
if (sss == None or len(sss) < 2): return None
tup=()
for item in sss:
item_index = numbers.index(item)
tesn = target_sum - item
if tesn in sss:
tesn_index = numbers.index(tesn)
if item_index!=tesn_index:
return (item_index, tesn_index)
return None
One flaw in the logic is that sss does not contain duplicates that may exist in the original list - you have lost information. You are assuming there are no duplicates in the original list: list.index(n) will return the index of the first item equal to n so you can end up with a result with duplicate indices
>>> a = [3, 1, 5, 7, 5, 9]
>>> item = 5
>>> tesn = 5
>>> a.index(item),a.index(tesn)
(2, 2)
>>>
Your algorithm has a flaw e.g. find_two_sum([5, 2], 10) gives (0, 0).
This is because when you check item in sss, it's gonna evaluate to true when item is 5, there is only a single 5 in the input list.
This answer seems to be 50% correct.
def find_two_sum(numbers, target_sum):
for n in numbers:
for i in numbers[numbers.index(n)+1:]:
if n+i==target_sum:
return(numbers.index(n),numbers.index(i))
break
return None
print(find_two_sum([3, 1, 5, 7, 5, 9], 10))

Python nested for-loops & break statement

I'm working my way through an official Python tutorial and I can't for the life of me figure out how the nested for loops work in example 4.4:
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print n, '==', x, '*', n/x
break
else:
# loop fell through w/o finding a factor
print n, 'is a prime number'
range(2, 10) produces:n = [2, 3, 4, 5, 6, 7, 8, 9]
,so the way I understand it the inner for loop: for x in range(2, n):
should produce (x, n-1) and thus the following pairs of x, n with each iteration:
(2, 1), (3, 2), (4, 3), (5, 4), (6, 5), (7, 6), (8, 7), (9, 8).
Now, obviously that would never produce n % x == 0 but that's the only way I can think about it.
When I print this piece of code:
for n in range(2, 10):
for x in range(2, n):
print x, n
to check what numbers will be generated, it returns (the first 6 pairs):
2 3
2 4
3 4
2 5
3 5
4 5
How can the first pair x, n be 2, 3 if the first n is 2 - 1 since the last position of range() will be excluded. I'm utterly and miserably lost.
The reason is that range(x,x) returns an empty list. In the first iteration you call for x in range(2, n) with n=2. This loop is completely skipped and Python continues with the next iteration of the outer-loop.
Using the second code snippet for example:
for n in range(2, 10):
n doesn't start from 2 - 1, it starts with 2, then 3, 4, until 9.
In the nested loop:
for x in range(2, n):
When n is 2, for x in range(2, 2) is an empty range. When n is 3, x could be 2, generating the first valid pair 2 3. When n is 4, x could be 2 and 3, generating the second the third pair 2 4 and 3 4. The rest is similar.

Categories