def problem(n):
myList = []
for i in range(2, n):
if n % i == 0:
myList.append(i)
return myList
with this code I was wondering how you would get the factors for example 12 to print out as[[6,2],[3,4]] something like this dosnt have to be in same order thanks.
This should work for you:
import math
def problem(n):
myList = []
for i in range(2, int(math.sqrt(n) + 1)):
if n % i == 0:
myList.append([i, int(n/i)])
return myList
To get the factor pair, this divides n by i, if i is a factor, which will by i's pair.
example:
print(problem(12)) #output: [[2, 6], [3, 4]]
Another way. Loop using range and check if is_integer
num = 12
set([tuple(sorted(j)) for j in [[i, int(num/i)] for i in range(2,num) if (num/i).is_integer()]]
)
#Output:
#{(2, 6), (3, 4)}
You are almost correct . Using range you are not taking the number. Just add n+1 instead of n. That should work. Also you are not stroing the divident in the list. I added that too.
def problem(n):
myList = []
for i in range(2, n+1):
if n % i == 0 and [int(n/i),i] not in myList:
myList.append([i,int(n/i)])
return myList
In order to do the division only once:
for i in range(2, int(math.sqrt(n) + 1)):
d, m = divmod(n, i)
if m == 0:
myList.append([i, d])
You will not get duplicates with upper limit sqrt(n)
Related
I am solving a programming problem and i am stuck at one place..
import itertools
N=int(input())
#finding all prime between a range
primes=[x for x in range(2, N) if all(x % y != 0 for y in range(2, x))]
print(primes)
try:
pairs=[min(p for p in itertools.combinations(primes, 2) if sum(p) == N)]
except:
pairs=[(p for p in itertools.combinations(primes, 2) if sum(p) == N)]
print(*pairs)
in this code i want to find that least valued pair of prime numbers that can be sum up together to equalize the value of N
for ex:
case1)
if i input 74 then it returns [71,3]
although 74 can be made out even by other cobinations but there is 3 which is least among the all combinations
case2)
if i input 4
this code will return [2,3] as answer,,idk why..
and the expected answer is [2,2]..stating that only this combination is possible to get the sum equals to N
you are getting empty generator object as response not [2, 3] this is list of prime numbers
Yours solution to work use itertools.combinations_with_replacement
import itertools
N = int(input())
#finding all prime between a range
primes = [x for x in range(2, N) if all(x % y != 0 for y in range(2, x))]
print(primes)
try:
pairs = [min(p for p in itertools.combinations_with_replacement(primes, 2) if sum(p) == N)]
except:
pairs = [p for p in itertools.combinations_with_replacement(primes, 2) if sum(p) == N]
for pair in pairs:
print(pair)
Output:
[2, 3] # list of prime number for input 4
(2, 2) # solution
I've following code that I need to convert to list-comprehension (one liner). However, I am unable to do so.
The code calculates prime numbers up-to input range of A.
def sieve(A):
l = []
f = lambda x : int(x**0.5)
for p in range(2,A+1):
for i in range(2, f(p) + 1):
if p % i == 0:
break
else:
l.append(p)
return l
So far I've following which does not work. Especially the break within for-loop is throwing me off.
list(set([val for sublist in [[p for i in range(2, f(p) + 1) if p %i != 0 ] for p in range(2,A) ] for val in sublist]))
EDIT
Adding constraints for the problem.
The code can only be one statement, without eval or exec. The code must be at most 160 character long.
[p for p in range(2,A+1) if next((i for i in range(2, int(p**0.5) + 1) if (p % i) == 0),None)==None]
Code is 100 chars long.
We use next() to break out of the iteration.
Explanation
def sieve(A):
[p for p in range(2,A+1) if getFirstDiv(p)==None]
def getFirstDiv(p):
next(divIter(p),None)
def divIter(p):
return (i for i in range(2, int(p**0.5) + 1) if (p % i) == 0)
OUTPUT
15 --> [2, 3, 5, 7, 11, 13]
10 --> [2, 3, 5, 7]
This one liner will do it:
[r for r in [i*all([i if i%j!=0 else 0 for j in range(2,i)]) for i in range(2,x)] if r>0]
You just need to set x (the maximum value).
Note: it is not particularly efficient, although I'm guessing efficiency isn't the aim of this question.
Explanation (expanded code):
filtered = []
primes = []
for i in range(2,x):
# Check that all numbers up to i do not divide i
# I realise we only need to check up to int(sqrt(i))
condition = all([i if i%j!=0 else 0 for j in range(2,i)])
# Exploit Python's treatment of bool: number*True = number and number*False=0
filtered.append( i*condition )
for r in filtered:
# Take out all the zeros
if r>0:
primes.append(r)
I have a simple example,
Create a program that asks the user for a number and then prints out a list of all the divisors of that number.
And i am solving it like this:
n = 4
list_range = list(range(1,n+1))
divisor_list = []
divisor_list.append([i for i in list_range if n%i==0])
print divisor_list
#output:
#[[1, 2, 4]]
I want the output to be [1, 2, 4]
I can achieve this by:
n = 4
list_range = list(range(1,n+1))
divisor_list = []
for i in list_range:
if n % i == 0:
divisor_list.append(i)
print divisor_list
#output:
#[1, 2, 4]
But is there a better way of achieving this ?
It makes no sense to loop through all range of numbers, it's a waste! Just try to prove there are no more divisors after n/2, here's another benchmarked version comparing an alternative method f2:
import math
import timeit
def f1(num):
return [i for i in range(1, num + 1) if num % i == 0]
def f2(num):
square_root = int(math.sqrt(num)) + 1
output = []
for i in range(1, square_root):
if (num % i == 0 and i * i != num):
output.append(i)
output.append(num / i)
if (num % i == 0 and i * i == num):
output.append(i)
return output
def bench(f, N):
for n in range(1, N):
f(N)
N = 10000
print timeit.timeit('bench(f1, N)', setup='from __main__ import bench, f1, N', number=1)
print timeit.timeit('bench(f2, N)', setup='from __main__ import bench, f2, N', number=1)
Results on my cpu are:
4.39642974016
0.124005777533
f2 won't give a sorted list, but that's irrelevant, you didn't mention that in your question
Use extend:
divisor_list.extend([i for i in list_range if n%i==0])
You can use assign the result of the list comprehension to the variable.
You don't need to initialize divisor_list as an empty sequence at all. The comprehension you're appending is the actual answer you're looking for.
divisor_list = [i for i in list_range if n%i==0]
You don't need append, just use:
divisor_list = [i for i in list_range if n% i == 0]
This way you just assign the result of list comprehension, giving you one clean list. No need to append a list, that will nest a list in a list, and no need to initialize as an empty list. That's redundant because you add to the list just the next line. Just assign to list comprehension. As #joel goldstick mentioned, you can just loop over half of list_range because nothing will be a division if it's more than 1/2 the number:
list_range = list(range(1, (n / 2) + 1))
I want to find a sequence of n consecutive integers within a sorted list and return that sequence. This is the best I can figure out (for n = 4), and it doesn't allow the user to specify an n.
my_list = [2,3,4,5,7,9]
for i in range(len(my_list)):
if my_list[i+1] == my_list[i]+1 and my_list[i+2] == my_list[i]+2 and my_list[i+3] == my_list[i]+3:
my_sequence = list(range(my_list[i],my_list[i]+4))
my_sequence = [2,3,4,5]
I just realized this code doesn't work and returns an "index out of range" error, so I'll have to mess with the range of the for loop.
Here's a straight-forward solution. It's not as efficient as it might be, but it will be fine unless you have very long lists:
myarray = [2,5,1,7,3,8,1,2,3,4,5,7,4,9,1,2,3,5]
for idx, a in enumerate(myarray):
if myarray[idx:idx+4] == [a,a+1,a+2,a+3]:
print([a, a+1,a+2,a+3])
break
Create a nested master result list, then go through my_sorted_list and add each item to either the last list in the master (if discontinuous) or to a new list in the master (if continuous):
>>> my_sorted_list = [0,2,5,7,8,9]
>>> my_sequences = []
>>> for idx,item in enumerate(my_sorted_list):
... if not idx or item-1 != my_sequences[-1][-1]:
... my_sequences.append([item])
... else:
... my_sequences[-1].append(item)
...
>>> max(my_sequences, key=len)
[7, 8, 9]
A short and concise way is to fill an array with numbers every time you find the next integer is the current integer plus 1 (until you already have N consecutive numbers in array), and for anything else, we can empty the array:
arr = [4,3,1,2,3,4,5,7,5,3,2,4]
N = 4
newarr = []
for i in range(len(arr)-1):
if(arr[i]+1 == arr[i+1]):
newarr += [arr[i]]
if(len(newarr) == N):
break
else:
newarr = []
When the code is run, newarr will be:
[1, 2, 3, 4]
#size = length of sequence
#span = the span of neighbour integers
#the time complexity is O(n)
def extractSeq(lst,size,span=1):
lst_size = len(lst)
if lst_size < size:
return []
for i in range(lst_size - size + 1):
for j in range(size - 1):
if lst[i + j] + span == lst[i + j + 1]:
continue
else:
i += j
break
else:
return lst[i:i+size]
return []
mylist = [2,3,4,5,7,9]
for j in range(len(mylist)):
m=mylist[j]
idx=j
c=j
for i in range(j,len(mylist)):
if mylist[i]<m:
m=mylist[i]
idx=c
c+=1
tmp=mylist[j]
mylist[j]=m
mylist[idx]=tmp
print(mylist)
What is the easiest way to get a list of whole factor pairs of a given integer?
For example: f(20) would return [(1,20), (2,10), (4,5)].
def f(value):
factors = []
for i in range(1, int(value**0.5)+1):
if value % i == 0:
factors.append((i, value / i))
return factors
Or the same thing using a list comprehension:
def f(val):
return [(i, val / i) for i in range(1, int(val**0.5)+1) if val % i == 0]
Or this:
def f(n):
factors_list = []
for i in xrange(1, int(n**0.5) + 1):
if n % i == 0:
factors_list.append((i, n/i))
return factors_list
print f(20)
EDIT: Or in a one-liner using list comprehension:
def f(n):
return [(i, n / i) for i in xrange(1, int(n**0.5) + 1) if n % i == 0]
print f(36)
EDIT2: If you want the function to work for negative integers (as well as 0 and positive integers) use:
def f(n):
return [(i, n / i) for i in xrange(1, int(math.sqrt(math.fabs(n))) + 1) if n % i == 0]
print f(-36)
How about this:
def f(n):
from itertools import takewhile
if not isinstance(n,int):
raise ValueError("supplied %s type, requires integer input" %(type(n).__name__))
return [(i,n/i) for i in takewhile(lambda x:x*x<n,xrange(1,n)) if (n%i)==0]