Attempt to use reduce - python

alternatively using reduce
def is_prime_no(x): #"True" represents Prime
np = 1
if x < 2:
np = 0
else:
for i in range(3, x): #int(math.sqrt(n))
if x % i == 0:
np =0
return np
print is_prime_no(12)
def prime_check(a,b):
if is_prime_no(a) == 1 and is_prime_no(b) == 1:
return 1
else:
return 0
print "prime check result ", prime_check(13,17)
From here does not work
def list_prime_check(values):
return reduce(prime_check, values)
print "Check items in list are prime ", list_prime_check([13,17,19])
Returns 0 but not 1 - i being true

Remember that in reduce(lambda a, b: ..., ...), the return value of the function becomes the new a. Therefore, you have:
reduce(prime_check, [13, 17, 19]) # =>
prime_check(13, 17) # => 1 =>
reduce(prime_check, [1, 19]) # uhh, what? =>
prime_check(1, 19) # uh-oh...
This particular instance of the problem is better served with all:
all(...)
all(iterable) -> bool
Return True if bool(x) is True for all values x in the iterable.
If the iterable is empty, return True.
Used like so:
>>> all([is_prime_no(x) for x in [13, 17, 19]])
True

Related

How can I get the function to add the sum of the true properties in the output?

def large_sum(lst, num):
def larger(x):
return (int(x) > num)
m = list(map(larger,lst))
print(m)
large_sum([2,4,6,8,10], 7)
# [False, False, False, True, True]
I wish to get the sum of the element in [2,4,6,8,10] where m is True.
You can use itertools.compress in the following way:
from itertools import compress
def large_sum(lst, num):
def larger(x):
return (int(x) > num)
m = list(map(larger,lst))
return m
l = [2,4,6,8,10]
n = 7
res = large_sum(l, n)
print(sum(list(compress(l, res)))
I kept the original logic, but I would suggest to use #chris method as it would be better efficency-wise:
l = [2,4,6,8,10]
n = 7
sum(i for i in l if i > n)
The main thing is to use filter instead of map:
def large_sum(lst, num):
def larger(x):
return x > num
return sum(filter(larger, lst))
print(large_sum([2,4,6,8,10], 7))
# 18
map transforms each value in the list, into a boolean in this case. The original values are not there anymore, and if you sum the booleans, True is converted to 1 and False to 0, which is why you get 2.
filter, on the other hand, returns the original values, but only those for which the predicate (larger in this case) returns True, and omits the others. Then you just sum those.

Check if all values in a list are bigger than certain number x and smaller than y?

def fun_lst(lst, a, b):
if min(lst)<b and max(lst)>a:
return True
return False
How do I check if the values in the list are bigger than a and smaller than b? I tried the above, but in this example: fun_lst([-1, 3.5, 6], -2.4, 0)the function returns True and it supposed to return False.
Do this:
def fun_lst(lst, a, b):
if min(lst) > a and max(lst) < b:
return True
return False
print(fun_lst([-1, 3.5, 6], -2.4, 0) )
Output:
False
Doing min(lst) > a ensures every element is bigger than a.
Doing max(lst) < b ensures every element is smaller than b.
Alternate solution:
def fun_lst(lst, a, b):
return all(a < elem < b for elem in lst)
You can try this one liner if you like
all([num < b and num > a for num in lst])
This code here will check each item in the list, if an item is found that is not greater than a and less than b then it returns false, otherwise it returns true.
def fun_lst(lst, a, b):
for item in lst:
if not a < item < b:
return False
return True
myList = [1,2,3,4,5,6,7,8,9]
lower_limit = 3
upper_limit = 8
bool_output = all([i > lower_limit and i < upper_limit for i in myList])
print(bool_output)
False
myList = [1,2,3,4,5,6,7,8,9]
lower_limit = 0
upper_limit = 10
bool_output = all([i > lower_limit and i < upper_limit for i in myList])
print(bool_output)
True
you should try this:
def fun_lst(lst, a, b):
return all(n > a and n < b for n in lst)
If you have a provision to use numpy try this
In [1]: import numpy as np
In [3]: np.array(b)
Out[3]: array([ 3, 1, 4, 66, 8, 3, 4, 56])
In [17]: b[(2<b) & (b<5)]
Out[17]: array([3, 4, 3, 4])
Different a method:
def fun_lst(lis, x, y):
list = [i>x and i<y for i in lis]
return False if False in list else True
It's a little easy:
def fun_lst(lis, x, y):
return x<max(lis)<y
lambda version:
fun_lst = lambda lis, x, y: x<max(lis)<y
Outputs:
fun_lst([-1, 3.5, 6], -2.4, 0) #Output: False

bisection_search produce an unexpected None result

I am following an instruction to write a bisection_search:
import random
arr = list(range(11))
random.shuffle(arr)
m = 9
#list is a stack in python
def bisection_search(m, arr):
top_index = len(arr) - 1 # rather than top_index = -1
bottom_index = 0
while bottom_index <= top_index:
mid_index = (top_index + bottom_index) // 2
pivot = arr[mid_index]
if m == pivot:
return mid_index
if m > pivot:
bottom_index = mid_index + 1
else:
top_index = mid_index - 1
return None
target_index = bisection_search(m, arr)
print(target_index)
## -- End pasted text --
None
I used %paste of ipython, it return None,
Tried alternatively:
In [3]: arr
Out[3]: [4, 10, 7, 3, 0, 1, 9, 6, 2, 5, 8]
In [4]: m
Out[4]: 9
In [5]: bisection_search(m, arr)
In [6]: x = bisection_search(m, arr)
In [7]: x
In [8]: def bisection_search(m, arr):
I double-checked the codes and confirmed no bugs in.
How could it produce a None result?
As others also mentioned, bisect/binary search is only suitable for sorted sequences. You are getting None, because it will randomly jump back and forth based on the condition checking and may not end up hitting the equality check condition and return None as a result
Unless you have specific reasons to implement your own bisect, use the one already available https://docs.python.org/2/library/bisect.html.

why lambda x: x % 2 means odd number

>>> fibonacci = [0,1,1,2,3,5,8,13,21,34,55]
>>> odd_numbers = list(filter(lambda x: x % 2, fibonacci))
>>> print(odd_numbers)
[1, 1, 3, 5, 13, 21, 55]
>>> even_numbers = list(filter(lambda x: x % 2 == 0, fibonacci))
>>> print(even_numbers)
[0, 2, 8, 34]
why not like this: lambda x: x % 2 == 1
It is because x % 2 will be read as a boolean and 0 is false and 1 is true (like every number different of 0).
You can try it with
print (True == 1) # True
print (False == 0) # True
Try it online!
In boolean context, non-zero is true (and zero is false). Your version is quite legal as well, it's mostly save some typing.
It is because (x % 2) would return 1 if x is divisible by 2 else 0.Now in Boolean context
1 is for True and 0 is for False.Therefore, in filter function we use only x%2 for getting the odd numbers, because it will give 0(False) if it is divisible by 2 else 1(True).
This behaviour is due to filter function rather than lambda here.
filter definition:
As the name suggests, filter creates a list of elements for which a function returns true.
filter(func, iterable) ---> func is the function which will be executed on iterable.
So now lets see how will filter work in this case.
fibonacci = [0,1,1,2,3,5,8,13,21,34,55]
odd_numbers = list(filter(lambda x: x % 2, fibonacci))
# For each element in fibonacci:
# x = fibonacci[0]
# lambda x: x % 2 will return 0 which is equivalent to False
# Now filter will ignore this as the result of filter is False
# Next Iteration: x = fibonacci[1]
# lambda x: x % 2 will return 1 which is equivalent to True
# So filter will get this value
# therefore, odd_numbers = [1]
# So on and so forth.
Hope it helps.

What Python function could i use to find the greatest common divisor of three numbers? [duplicate]

So I'm writing a program in Python to get the GCD of any amount of numbers.
def GCD(numbers):
if numbers[-1] == 0:
return numbers[0]
# i'm stuck here, this is wrong
for i in range(len(numbers)-1):
print GCD([numbers[i+1], numbers[i] % numbers[i+1]])
print GCD(30, 40, 36)
The function takes a list of numbers.
This should print 2. However, I don't understand how to use the the algorithm recursively so it can handle multiple numbers. Can someone explain?
updated, still not working:
def GCD(numbers):
if numbers[-1] == 0:
return numbers[0]
gcd = 0
for i in range(len(numbers)):
gcd = GCD([numbers[i+1], numbers[i] % numbers[i+1]])
gcdtemp = GCD([gcd, numbers[i+2]])
gcd = gcdtemp
return gcd
Ok, solved it
def GCD(a, b):
if b == 0:
return a
else:
return GCD(b, a % b)
and then use reduce, like
reduce(GCD, (30, 40, 36))
Since GCD is associative, GCD(a,b,c,d) is the same as GCD(GCD(GCD(a,b),c),d). In this case, Python's reduce function would be a good candidate for reducing the cases for which len(numbers) > 2 to a simple 2-number comparison. The code would look something like this:
if len(numbers) > 2:
return reduce(lambda x,y: GCD([x,y]), numbers)
Reduce applies the given function to each element in the list, so that something like
gcd = reduce(lambda x,y:GCD([x,y]),[a,b,c,d])
is the same as doing
gcd = GCD(a,b)
gcd = GCD(gcd,c)
gcd = GCD(gcd,d)
Now the only thing left is to code for when len(numbers) <= 2. Passing only two arguments to GCD in reduce ensures that your function recurses at most once (since len(numbers) > 2 only in the original call), which has the additional benefit of never overflowing the stack.
You can use reduce:
>>> from fractions import gcd
>>> reduce(gcd,(30,40,60))
10
which is equivalent to;
>>> lis = (30,40,60,70)
>>> res = gcd(*lis[:2]) #get the gcd of first two numbers
>>> for x in lis[2:]: #now iterate over the list starting from the 3rd element
... res = gcd(res,x)
>>> res
10
help on reduce:
>>> reduce?
Type: builtin_function_or_method
reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
Python 3.9 introduced multiple arguments version of math.gcd, so you can use:
import math
math.gcd(30, 40, 36)
3.5 <= Python <= 3.8.x:
import functools
import math
functools.reduce(math.gcd, (30, 40, 36))
3 <= Python < 3.5:
import fractions
import functools
functools.reduce(fractions.gcd, (30, 40, 36))
A solution to finding out the LCM of more than two numbers in PYTHON is as follow:
#finding LCM (Least Common Multiple) of a series of numbers
def GCD(a, b):
#Gives greatest common divisor using Euclid's Algorithm.
while b:
a, b = b, a % b
return a
def LCM(a, b):
#gives lowest common multiple of two numbers
return a * b // GCD(a, b)
def LCMM(*args):
#gives LCM of a list of numbers passed as argument
return reduce(LCM, args)
Here I've added +1 in the last argument of range() function because the function itself starts from zero (0) to n-1. Click the hyperlink to know more about range() function :
print ("LCM of numbers (1 to 5) : " + str(LCMM(*range(1, 5+1))))
print ("LCM of numbers (1 to 10) : " + str(LCMM(*range(1, 10+1))))
print (reduce(LCMM,(1,2,3,4,5)))
those who are new to python can read more about reduce() function by the given link.
The GCD operator is commutative and associative. This means that
gcd(a,b,c) = gcd(gcd(a,b),c) = gcd(a,gcd(b,c))
So once you know how to do it for 2 numbers, you can do it for any number
To do it for two numbers, you simply need to implement Euclid's formula, which is simply:
// Ensure a >= b >= 1, flip a and b if necessary
while b > 0
t = a % b
a = b
b = t
end
return a
Define that function as, say euclid(a,b). Then, you can define gcd(nums) as:
if (len(nums) == 1)
return nums[1]
else
return euclid(nums[1], gcd(nums[:2]))
This uses the associative property of gcd() to compute the answer
Try calling the GCD() as follows,
i = 0
temp = numbers[i]
for i in range(len(numbers)-1):
temp = GCD(numbers[i+1], temp)
My way of solving it in Python. Hope it helps.
def find_gcd(arr):
if len(arr) <= 1:
return arr
else:
for i in range(len(arr)-1):
a = arr[i]
b = arr[i+1]
while b:
a, b = b, a%b
arr[i+1] = a
return a
def main(array):
print(find_gcd(array))
main(array=[8, 18, 22, 24]) # 2
main(array=[8, 24]) # 8
main(array=[5]) # [5]
main(array=[]) # []
Some dynamics how I understand it:
ex.[8, 18] -> [18, 8] -> [8, 2] -> [2, 0]
18 = 8x + 2 = (2y)x + 2 = 2z where z = xy + 1
ex.[18, 22] -> [22, 18] -> [18, 4] -> [4, 2] -> [2, 0]
22 = 18w + 4 = (4x+2)w + 4 = ((2y)x + 2)w + 2 = 2z
As of python 3.9 beta 4, it has got built-in support for finding gcd over a list of numbers.
Python 3.9.0b4 (v3.9.0b4:69dec9c8d2, Jul 2 2020, 18:41:53)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> A = [30, 40, 36]
>>> print(math.gcd(*A))
2
One of the issues is that many of the calculations only work with numbers greater than 1. I modified the solution found here so that it accepts numbers smaller than 1. Basically, we can re scale the array using the minimum value and then use that to calculate the GCD of numbers smaller than 1.
# GCD of more than two (or array) numbers - alows folating point numbers
# Function implements the Euclidian algorithm to find H.C.F. of two number
def find_gcd(x, y):
while(y):
x, y = y, x % y
return x
# Driver Code
l_org = [60e-6, 20e-6, 30e-6]
min_val = min(l_org)
l = [item/min_val for item in l_org]
num1 = l[0]
num2 = l[1]
gcd = find_gcd(num1, num2)
for i in range(2, len(l)):
gcd = find_gcd(gcd, l[i])
gcd = gcd * min_val
print(gcd)
HERE IS A SIMPLE METHOD TO FIND GCD OF 2 NUMBERS
a = int(input("Enter the value of first number:"))
b = int(input("Enter the value of second number:"))
c,d = a,b
while a!=0:
b,a=a,b%a
print("GCD of ",c,"and",d,"is",b)
As You said you need a program who would take any amount of numbers
and print those numbers' HCF.
In this code you give numbers separated with space and click enter to get GCD
num =list(map(int,input().split())) #TAKES INPUT
def print_factors(x): #MAKES LIST OF LISTS OF COMMON FACTROS OF INPUT
list = [ i for i in range(1, x + 1) if x % i == 0 ]
return list
p = [print_factors(numbers) for numbers in num]
result = set(p[0])
for s in p[1:]: #MAKES THE SET OF COMMON VALUES IN LIST OF LISTS
result.intersection_update(s)
for values in result:
values = values*values #MULTIPLY ALL COMMON FACTORS TO FIND GCD
values = values//(list(result)[-1])
print('HCF',values)
Hope it helped

Categories

Resources