Fibonacci sequence using codelab - python

In the following sequence, each number (except the first two) is the sum of the previous two number: 0, 1, 1, 2, 3, 5, 8, 13, .... This sequence is known as the Fibonacci sequence.
Given the positive integers m and n (with m < n) create a list consisting of the portion of the Fibonacci sequence greater than or equal to m and less than or equal to n. For example, if m is 3 and n is 6, then the list would be [3, 5] and if m is 2 and n is 20, then the list would be [2, 3, 5, 8, 13].
Associate the list with the variable fib.
Have done this far, but still getting error.
Where does it need to be fixed?
fib = [0,1,1]
result = 0
while result <=n:
result=fib[-1]+fib[-2]
if result <=n and result>=m:
fib.append(result)

# create a fibonacci series from 0 to n
f = [0,1]
for i in range(1, n+1):
x = f[i]+f[i-1]
if x > n:
break
else:
f.append(x)
# copy only those numbers of series that are in range m to n
fib = []
for i in range(0, len(f)):
if f[i] >= m and f[i] <= n:
fib.append(f[i])

You could use the code below.
fib = [0,1,1]
fibrange = [] # keeps your digits that are in range m < n
result = 0
n = 80
m = 2
while result <=n:
result =fib[-1]+fib[-2]
fib.append(result)
if result <=n and result>=m:
fibrange.append(result)
print fibrange

fib=[0,1]
i=0
while i <=n:
i=fib[-1]+fib[-2]
if i<=n:
fib.append(i)

Related

how to count the number divisible by N in given range (A to B) for multiple cases (C) in python

So basically, there are multiple cases that need to be solve by counting the number that divisible by N in given range A to B.
for example, there are 2 cases.
case 1 has A=1, B=10, N=3
case 2 has A=8, B=20, N=4
but on one condition that the input must be like this:
2 #<-- number of cases
1 #<-- A
10 #<-- B
3 #<-- N
8 #<-- A
20 #<-- B
4 #<-- N
the output will be like:
Case 1: 3 #because between 1 until 10, only 3,6,9 that divisible by 3
Case 2: 4 #because between 8 until 20, only 8,12,16,20 that divisible by 4
I have this function for reference:
def CountDiv(A,B,N):
count = 0
for i in range(A, B+1):
if i % N == 0:
count = count + 1
return count
My explanation is bad but I just don't know how to make it more clearer. I hope someone will understand and enlightened me about this problem. Thank you
The CountDiv function works. So, I'm assuming that you are asking how to properly slice your input list. If you have your input sequence in a list, this should work
seq = [ 2, #<-- number of cases
1, #<-- A
10, #<-- B
3, #<-- N
8, #<-- A
20, #<-- B
4, #<-- N
]
def slices(lst, n):
number_of_cases = lst.pop(0)
for i in range(0, n * number_of_cases, n):
yield lst[i:i + n]
def CountDiv(A,B,N):
count = 0
for i in range(A, B+1):
if i % N == 0:
count = count + 1
return count
print([CountDiv(*sub) for sub in [*slices(seq, n=3)]])
# [3, 4]
If you want the exact output you described, you can do this
for idx, sub in enumerate([*slices(seq, n=3)]):
print(f"Case {idx}: {CountDiv(*sub)}")
# Case 0: 3
# Case 1: 4
You should also combine #mozway's and my answer, like so.
def slices(lst, n):
number_of_cases = lst.pop(0)
for i in range(0, n * number_of_cases, n):
yield lst[i:i + n]
def ndiv(A, B, N):
return (B+N-(A+N-1)//N*N)//N if B>=A else 0
for idx, sub in enumerate([*slices(seq, n=3)]):
print(f"Case {idx}: {ndiv(*sub)}")
Edit on request: The * operator is used twice above to unpack elements from an iterable. For example, in the statement above, ndiv(*sub) could be replaced by ndiv(sub[0], sub[1], sub[2]). If we wanted to make it very verbose, we could write it like this
result_of_slicing = list(slices(seq, n= 3))
# [[1, 10, 3], [8, 20, 4]]
for index, a_slice in enumerate(result_of_slicing):
A, B, N = a_slice
result_of_ndiv = ndiv(A=A, B=B, N=N)
print(f"Case {index}: {result_of_ndiv}")
# Case 0: 3
# Case 1: 4
You don't need to loop over all values. You can only generate the multiple from the smallest starting point ((A+N-1)//N*N):
def ndiv(A, B, N):
return len(list((A+N-1)//N*N, B+1, N)))
Even better, calculate directly the number of values using:
def ndiv(A, B, N):
if B<A:
return 0
return (B+N-(A+N-1)//N*N)//N
example:
>>> ndiv(8,20,4)
4
>>> ndiv(1,10,3)
3
>>> ndiv(1,1,3)
0

Counting elements in 2 arrays (GFG)

I was working on a GFG question
Question:
Given two unsorted arrays arr1[] and arr2[]. They may contain duplicates. For each element in arr1[] count elements less than or equal to it in array arr2[].
Example 1:
Input:
m = 6, n = 6
arr1[] = {1,2,3,4,7,9}
arr2[] = {0,1,2,1,1,4}
Output: 4 5 5 6 6 6
Explanation: Number of elements less than
or equal to 1, 2, 3, 4, 7, and 9 in the
second array are respectively 4,5,5,6,6,6
Example 2:
Input:
m = 5, n = 7
arr1[] = {4 8 7 5 1}
arr2[] = {4,48,3,0,1,1,5}
Output: 5 6 6 6 3
Your Task :
Complete the function countEleLessThanOrEqual() that takes two array arr1[], arr2[], m, and n as input and returns an array containing the required results(the count of elements less than or equal to it in arr2 for each element in arr1 where ith output represents the count for ith element in arr1.)
Expected Time Complexity: O((m + n) * log n).
Expected Auxiliary Space: O(1).
Constraints:
1<=m,n<=10^5
1<=arr1[i],arr2[j]<=10^5
My python solution:
def countEleLessThanOrEqual(arr1,n1,arr2,n2):
#returns the required output
res=[]
arr2.sort()
for i in range(n1):
search=arr1[i]
count=0
start=0
end=n2-1
while(start<=end):
mid = int(start+(end-start)/2)
if search==arr2[mid]:
start=mid+1
elif search>arr2[mid]:
start=mid+1
elif search<arr2[mid]:
end=mid-1
count=end+1
res.append(count)
return res
When I submit it, it gives me TLE error even though my solution is similar to the one posted in the editorial:
Editorial solution:
# python implementation of For each element in 1st
# array count elements less than or equal to it
# in 2nd array
# function returns the index of largest element
# smaller than equal to 'x' in 'arr'. For duplicates
# it returns the last index of occurrence of required
# element. If no such element exits then it returns -1
def bin_search(arr, n, x):
l = 0
h = n - 1
while(l <= h):
mid = int((l + h) / 2)
# if 'x' is greater than or equal to arr[mid],
# then search in arr[mid + 1...h]
if(arr[mid] <= x):
l = mid + 1;
else:
# else search in arr[l...mid-1]
h = mid - 1
# required index
return h
# function to count for each element in 1st array,
# elements less than or equal to it in 2nd array
def countElements(arr1, arr2, m, n):
# sort the 2nd array
arr2.sort()
# for each element in first array
for i in range(m):
# last index of largest element
# smaller than or equal to x
index = bin_search(arr2, n, arr1[i])
# required count for the element arr1[i]
print(index + 1)
# driver program to test above function
arr1 = [1, 2, 3, 4, 7, 9]
arr2 = [0, 1, 2, 1, 1, 4]
m = len(arr1)
n = len(arr2)
countElements(arr1, arr2, m, n)
# This code is contributed by Aditi Sharma
You could use a binary search on the second array after sorting it in place:
from bisect import bisect_right
def lowerCount(arr1,arr2):
arr2.sort()
return [bisect_right(arr2,v) for v in arr1]
print(*lowerCount([1,2,3,4,7,9],[0,1,2,1,1,4])) # 4 5 5 6 6 6
print(*lowerCount([4, 8, 7, 5, 1],[4,48,3,0,1,1,5])) # 5 6 6 6 3
Sorting arr2 is O(N log N), and binary searches will take O(M log N) for a total of O( (N+M) log N ).
If you can't use libraries, you could always write your own bisect_right function:
def bisect_right(A,x):
lo,hi = 0,len(A)-1
while lo <= hi:
mid = (lo+hi)//2
if A[mid] <= x: lo = mid+1
else: hi = mid-1
return hi+1
#AasthaJha, would you like to try this similar but simplified alternative version:
def bin_search(A, n, x):
low, high = 0, n-1
while low <= high:
mid = (low + high) // 2
# if 'x' is greater than or equal to A[mid],
# then search in arr[mid + 1...h]
if A[mid] <= x:
low = mid + 1;
else:
high = mid -1 # else search in A[l...mid-1]
return high
# function to count for each element in 1st array,
# elements less than or equal to it in 2nd array
def countElements(A, B, m, n):
B.sort()
result = []
# loop element in A - first array
for i in range(m):
# last index of largest element smaller than or equal to x
index = bin_search(B, n, A[i])
print(index + 1) # count
result.append(index + 1)
return result
# Testing
A = [1, 2, 3, 4, 7, 9]
B = [0, 1, 2, 1, 1, 4]
m, n = len(A), len(B)
print(countElements(A, B, m, n))

MyProgrammingLab Triangular Number probelm

The question is:
A triangular number is a number that is the sum of the integers from 1 to some integer n. Thus 1 is a triangular number because it's the sum of the integers from 1 to 1; 6 is a triangular number because it's 1+2+3=6.
Given the non-negative integers m and n (with m < n), create a list of the triangular numbers between (and including) m and n. Thus if m is 3 and n is 20, the list would be: [3, 6, 10, 15]. Associate the list with the variable triangulars.
The code I've tried:
Sum = 0
triangulars = []
for i in range(m,m+n):
if (n >= m) and (m >= 0):
Sum += 1
triangulars.append(Sum)
The error I have is the programming lab recommends I use the sum function, and the results I am getting are no triangular numbers (I should get 6, 10 , 15 when m = 5 and n = 17, instead I get 5, 11, 18 and so on)
I changed it around a bit, put it in a function, renamed some variables, and threw in the test cases of m=3,n=20. I also tested several other combos including m=5,n=17. I also employed the sum() function you mentioned that you were asked to use. Here's the working code:
def triangulars(m,n):
if (n >= m) and (m >= 0):
sum_list = []
triangular_list = []
for i in range(1,n+1):
sum_list.append(i)
a_triangular = sum(sum_list)
if m <= a_triangular <= n:
print(m,n,a_triangular)
triangular_list.append(a_triangular)
print(m,n,triangular_list)
else:
print('Invalid m,n values')
m = 3
n = 20
triangulars(m,n)

How to find maximum sum in array less than N

I have array of M elements. I should find maximum sum of my array, which is less than integer number "N". All the elements in array are positive integers bigger or equal to zero. Also, sum can be non-consistent.
FOR example:
let's say M is = [1,2,3,6,0, 8, 9, 12] and N = 20, so here the answer is 20
but if M = [1,5,4,6] and N = 13, the answer is 12 - the maximum sum of array which is less than N
Problem: Find max sum from weights array, within maxCapacity
Approach: Problem is same as 0/1 Knapsack.
0/1 Knapsack problem:
Given: maxCapacity (int), weights (array) and values (array).
Find: max "value" by choosing items with total weight within
maxCapacity.
In this question:
Given: maxCapacity (int) and weights (array).
Find: max "weight" by choosing items with total weight within
maxCapacity.
Difference:
So unlike knapsack we have to maximise weight
instead of values. Thus, weight array will work as values array here.
def func(weights, maxCapacity):
knapsack = [[0 for i in range(len(weights) + 1)] for j in range(maxCapacity + 1)]
for w in range(maxCapacity + 1):
for i in range(len(weights) + 1):
if i == 0 or w == 0:
knapsack[w][i] = 0
elif weights[i - 1] <= w:
knapsack[w][i] = max(
weights[i - 1] + knapsack[w - weights[i - 1]][i - 1],
knapsack[w][i - 1],
)
else:
knapsack[w][i] = knapsack[w][i - 1]
for r in knapsack:
print(r)
return knapsack[-1][-1]
func([4, 8, 5, 9], 20)
Summary: Learn to solve 0-1 Knapsack Problem to understand this better.
First we need to check if the numbers sum is smaller than N, then save the sum as the result and the sum as the string at different lists at the same time.
So when we find the max in the list of sums is smaller than N, we can access the second list containing the strings using the same index.
M = [12, 9, 8, 4, 8, 5]
Ma = []
Ma_num = []
N = 20
for i in M:
for a in range(len(M)):
if i + M[a] <= N:
Ma.append(f"{i} + {M[a]}")
Ma_num.append(i + M[a])
max_num = Ma_num.index(max(Ma_num))
print(Ma[max_num])
Output:
12 + 8
By the way, if you meant that you wanted to see the number 20 in output, the solution is this:
M = [12, 9, 8, 4, 8, 5]
Ma = []
N = 20
for i in M:
for a in range(len(M)):
if i + M[a] <= N:
Ma.append(i + M[a])
max_num = max(Ma)
print(max_num)
Output:
20
I have a solution, first sum all number in your m array then in a loop check
sum >=n
if true return m
else sum = m - min(m)
and remove min
and check again
##############################3
check this solotion
M = [1,2,3,6,0, 8, 9, 12]
n = 20
s= 0
while s < n:
maximum = max(M)
M.remove(maximum)
if (s+ maximum)>n:
continue
s = s + maximum
print(s)
This can be solved as a Knapsack Problem
In the Knapsack problem we have a vector of values (val) and weights (wt)
We want to maximize the sum of a subset of values (val) such that
the corresponding weight is less than some max (referred to as capacity)
We can use the Knapsack algorithm by:
(1) Letting the input array corresponds to both weights and values
(2) Maximum capacity is the max sum
Code for solving Knapsack from here
def knapSack(W , wt , val, n):
# Base Case
if n == 0 or W == 0 :
return 0
# If weight of the nth item is more than Knapsack of capacity
# W, then this item cannot be included in the optimal solution
if (wt[n-1] > W):
return knapSack(W , wt , val , n-1)
# return the maximum of two cases:
# (1) nth item included
# (2) not included
else:
return max(val[n-1] + knapSack(W-wt[n-1] , wt , val , n-1),
knapSack(W , wt , val , n-1))
def max_sum(K, arr):
'''Solve using Knapsack code with (set weights and values equal to arr)'''
return knapSack(K, arr, arr, len(arr))
Test
arr = [1,5,4,6]
print(max_sum(13, arr))
#>>> Outputs 12
arr =[1,2,3,6,0, 8, 9, 12]
print(max_sum(20, arr))
#>>> Outputs 20
arr = [2,5,6,8]
print(max_sum(17, arr))
#>>> Outputs 16
Complexity
The time complexity of Knapsack solution is O(nW)
where n is the length of the array arr
W is the max sum

Find n integers in list that after multiplying equal to m

I need to print out n indexes of elements of list that after multiplying equal to some given integer. It's guaranteed that the combination exists in a list. For example, for the following input(number of elements in array, multiplication wanted number, number of elements in wanted sublist and given array):
7 60 4
30 1 1 3 10 6 4
I should get in any order
1 2 4 5
Because 1*1*10*6==60. If there are more than 1 solution I need to print any of them.
My solution works but pretty slow, how can I make it work faster?
from itertools import chain, combinations
arr = list(map(int, input().split()))
numbers = list(map(int, input().split()))
s = sorted(numbers)
def filtered_sublists(input_list, length):
return (
l for l in all_sublists(input_list)
if len(l) == length
)
def all_sublists(l):
return chain(*(combinations(l, i) for i in range(len(l) + 1)))
def multiply(arr):
result = 1
for x in arr:
result = result * x
return result
def get_indexes(data):
indexes = []
for i in range(len(data)):
if arr[1] == multiply(data[i]):
for el in data[i]:
if numbers.index(el) in indexes:
all_ind = [i for i, x in enumerate(numbers) if x == el]
for ind in all_ind:
if ind not in indexes:
indexes.append(ind)
break
else:
indexes.append(numbers.index(el))
break
return indexes
sublists = list(filtered_sublists(numbers, arr[2]))
print(*get_indexes(sublists))
The key is don't test every combination.
def combo(l, n=4, target=60, current_indices=[], current_mul=1):
if current_mul > target and target > 0:
return
elif len(current_indices) == n and current_mul == target:
yield current_indices
return
for i, val in enumerate(l):
if (not current_indices) or (i > current_indices[-1] and val * current_mul <= target):
yield from combo(l, n, target, current_indices + [i], val * current_mul)
l = [30,1,1,3,10,6,4]
for indices in combo(l, n=4, target=60):
print(*indices)
Prints:
1 2 4 5
More testcases:
l = [1,1,1,2,3,3,9]
for c, indices in combo(l, n=4, target=9):
print(*indices)
Prints:
0 1 2 6
0 1 4 5
0 2 4 5
1 2 4 5
We can use a memoized recursion for an O(n * k * num_factors), solution, where num_factors depends on how many factors of the target product we can create. The recurrence should be fairly clear from the code. (Zeros aren't handled but those should be pretty simple to add extra handling for.)
Pythonesque JavaScript code:
function f(A, prod, k, i=0, map={}){
if (i == A.length || k == 0)
return []
if (map[[prod, k]])
return map[[prod, k]]
if (prod == A[i] && k == 1)
return [i]
if (prod % A[i] == 0){
const factors = f(A, prod / A[i], k - 1, i + 1, map)
if (factors.length){
map[[prod, k]] = [i].concat(factors)
return map[[prod, k]]
}
}
return f(A, prod, k, i + 1, map)
}
var A = [30, 1, 1, 3, 10, 6, 4]
console.log(JSON.stringify(f(A, 60, 4)))
console.log(JSON.stringify(f(A, 60, 3)))
console.log(JSON.stringify(f(A, 60, 1)))
You could start from the target product and recursively divide by factors in the remaining list until you get down to 1 and after using the specified number of factors. This has the advantage of quickly eliminating whole branches of recursion under numbers that are not a factor of the target product.
Handling zero values in the list and a target product of zero requires a couple of special conditions at the start and while traversing factors.
For example:
def findFactors(product, count, factors, offset=0):
if product == 0: return sorted((factors.index(0)+i)%len(factors) for i in range(count))
if not count: return [] if product == 1 else None
if not factors: return None
for i,factor in enumerate(factors,1):
if factor == 0 or product%factor != 0: continue
subProd = findFactors(product//factor,count-1,factors[i:],i+offset)
if subProd is not None: return [i+offset-1]+subProd
r = findFactors(60, 4, [30,1,1,3,10,6,4])
print(r) # [1, 2, 4, 5]
r = findFactors(60, 4, [30,1,1,0,3,10,6,4])
print(r) # [1, 2, 5, 6]
r = findFactors(0, 4, [30,1,1,3,10,6,0,4])
print(r) # [0, 1, 6, 7]

Categories

Resources