Getting prime numbers from a list - python

Given a list lst = [121, 4, 37, 441, 7, 16] , I would like to remove from it all numbers that repeat themselves, resulting in a new string that would be lst = [37,7] (the prime numbers of the original string).
So far I'd only managed to put out this code:
def func(lst,x):
y = []
for i in lst:
for x in range (1, i):
if (i % x) == 0 :
y.append(i)
return y
print(func(lst,3))
Instead of getting lst = [37,7], I'm getting this weird looking list:
[121, 121, 4, 4, 37, 441, 441, 441, 441, 441, 441, 441, 441, 7, 16, 16, 16, 16]
Is there any way I can make this work ?

As this feels like a homework question, I won't give working code, but a strategy. You want to ensure that only the numbers of the original list remain, or filter out the numbers that are not prime.
Slightly more formally, "for each number in the list, determine if it's prime, and if so, include it in a new list".
Your code is 90% there, but your kernel (the primality test) is not correct. The key to testing primality is to ensure that each possible integer divisor does not evenly divide the number in question.
For example, if testing 6, the list of possible "0 remainder" integer divisors is
[1, 2, 3, 4, 5, 6]
The first and last numbers (1 and 6) don't mean anything as far as primality (6/1 is 6, and 6/6 is 1). So, your list of possible divisors to test is now
[2, 3, 4, 5]
From here, I think an insight you're missing in your code is that for a number to be prime, all of its possible divisors must not produce an even number (i.e., remainder of 0).

from math import sqrt
def func(n)
list1=[]
list2=[]
for z in (all(i % x for x in range(2,int(sqrt(i)+1))) for i in n):
list1.append(z)
for i,j in enumerate(list1):
if j == True:
list2.append(n[i])
return list2

Related

take a number and sum its digits

I'm working through this Kata and although I've looked through the solutions none are quite similar enough to mine to answer my question.
Problem Text: The number 89 is the first integer with more than one digit that fulfills the property partially introduced in the title of this kata. What's the use of saying "Eureka"? Because this sum gives the same number.
In effect: 89 = 8^1 + 9^2
The next number in having this property is 135.
See this property again: 135 = 1^1 + 3^2 + 5^3
We need a function to collect these numbers, that may receive two integers a, b that defines the range [a, b] (inclusive) and outputs a list of the sorted numbers in the range that fulfills the property described above.
def sum_dig_pow(a, b): # range(a, b + 1) will be studied by the function
# your code here
lst = []
n = 1
tot = 0
for i in range(a,b):
if i > 9:
spl = str(i).split()
for item in spl:
tot += int(item) ** n
n += 1
if tot == i:
lst.append(i)
else:
lst.append(i)
return lst
Tests are returning "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] should equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 89]".
I cannot figure out why it's passing 10 and not appending 89. I'm sure there's a more efficient way to do this as well but I'm still learning so want to be working in basics of loops, conditionals,etc.
This line is incorrect:
spl = str(i).split()
The split method will split a string on spaces by default and return a list. So passing i=10 gives back spl = ['10'], a list with one element. Instead, just iterate over each of the digits in the string.
for item in str(i):
...
Follow up: you can shorten your code by using enumerate to count the index of each digit.
def sum_dig_pow(a,b):
return [sum(int(y)**(i+1) for i,y in enumerate(str(x))) for x in range(a,b)]
Rather than spending a lot of time converting things from numbers to strings and back, try using arithmetic. To iterate over the digits of a number n, take n modulo ten (to get the least-significant digit) and then divide by ten (to peel off that least-significant digit). For example, the digits of 123 (in reverse order) are [(123 % 10), (12 % 10), (1 % 10)]
Thinking of it in terms of functions, first get the digits:
def digits_of_n(n):
result = []
while n > 0:
result.append(n % 10)
n = n / 10 # in python 3, use 3 // 10 for integer division
return reversed(result) # reverse list to preserve original order
then get the sum of the powers:
def sum_of_ith_powers(numbers):
result = 0
for i, n in enumerate(numbers): # the digits are ordered most-significant to least, as we would expect
result += n ** 1
return result
now you can just call sum_of_ith_powers(digits_of_n(n)) and you have an answer. If you like, you can give that operation a name:
def sum_of_digit_powers(n):
return sum_of_ith_powers(digits_of_n(n))
and you can then name the function that solves the kata:
def solve_kata(a, b):
return [sum_of_digit_powers(n) for n in range (a, b)]
You can use a generator, sum and enumerate in order to simplify your code like this example:
def sum_dig_pow(a,b):
for k in range(a,b+1):
if k > 9:
number_sum = sum(int(j)**i for i,j in enumerate(str(k), 1))
if k is number_sum:
yield k
else:
yield k
print(list(sum_dig_pow(1,10)))
print(list(sum_dig_pow(1,90)))
print(list(sum_dig_pow(1,10000)))
print(list(sum_dig_pow(10,1000)))
print(list(sum_dig_pow(1,900000)))
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 89]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 89, 135, 175]
[89, 135, 175]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 89, 135, 175]
li = []
def sum_dig_pow(a, b):
for i in range(a, b+1):
sum1 = 0
for ind, val in enumerate(str(i), 1):
sum1 += pow(int(val), int(ind))
if i == sum1:
li.append(i)
return li
print(sum_dig_pow(1, 11))

Determining Practical Numbers

So I am given a fraction and must determine if the denominator is a practical number. Description of a practical number: What is a practical number?
I already have a function that returns all the factors of the number:
def factorFinder(x):
#Pre: Valid Integer for students
#Post: Returns list of factors for that number
#Takes the number of students as argument and returns all factors for that number
lst = []
for i in range(1, x+1):
if x % i == 0:
lst.append(i)
return(lst)
and a function that given a list of factors as arguments returns a list of sums of all its sublists:
import itertools
def sumsOfSublists(lst):
# Pre: a non-empty list
# Post: returns a list of sums of all possible list sublists of length >= 2
# given a list, returns a sorted list containing sums of
# all combinations of sublists of length 2..list_length
sumList = []
for i in range(2, len(lst)+1):
zlist = list(itertools.combinations(lst,i))
for el in zlist:
sumList.append(sum(el))
return sorted(sumList)
I don't know how to go about testing if the number is practical or not. I don't really understand the concept of a "practical number" even after reading about it on multiple websites. So I guess really, this is more of a math question if anything.
Also given two number I need to print out the egyptian fractions for them. (i.e) given 7/8 should print the following: (1/2)+(1/4)+(1/8). All numerators must be 1.
Looks like you've done all the heavy lifting you just need a check:
def is_practical(n):
s = set(sumsOfSublists(factorFinder(n)))
return all(i in s for i in range(1, n))
Is there any reason you are sorting the sums into a list? sets are much quicker to look up. See https://wiki.python.org/moin/TimeComplexity
I reformulate your wiki-article and hope that it is helpful to you - because as AChampion has said - you have already done all the heavy lifting ;)
n is is a practical number if:
let l = [1, 2, ... n-1] // all number smaller than n
let divs = [i for i in range(1,n) if n%i==0] // all divisors of n (I associate a factor is prime cause of the term factorization of a number, so probably you should change factor to divisor in your question)
Now you have to write all numbers of l as sum of numbers from divs, where you can use all numbers of divs one or zero times
for example n = 12 is a practical number because:
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
divs = [1, 2, 3, 4, 6]
l[0] = divs[0], l[1] = divs[1], ... , l[10] = divs[0]+divs[3]+divs[4]=1+4+6=11 // l[1] = divs[0]+divs[0] is not allowed because you may use each number of divs only once
In opposite n = 3 is not a practical number because:
l = [1, 2]
divs = [1]
l[0] = divs[0], l[1] = mööööp
Here is also a straightforward implementation of my explanation (but you can also keep the nice work you have already done!):
from itertools import combinations
def isPracticalNumber(n):
l = [i for i in range(1, n)]
divs = [i for i in range(1, n) if n % i == 0]
possibleSums = set()
for i in range(1, len(divs)+1):
combinationsOfLengthI = combinations(divs, i)
for combi in combinationsOfLengthI:
possibleSums.add(sum(combi))
return all([i in possibleSums for i in l])
if __name__ == '__main__':
print(isPracticalNumber(12)) # True
print(isPracticalNumber(3)) # False
practicalNumbers = [1, 2, 4, 6, 8, 12, 16, 18, 20, 24, 28, 30, 32, 36, 40, 42, 48, 54, 56, 60, 64, 66, 72, 78, 80, 84, 88, 90, 96, 100, 104, 108, 112, 120, 126, 128, 132, 140, 144, 150]
calculatedPracticalNumbers = [i for i in range(1, 151) if isPracticalNumber(i)]
print(len(calculatedPracticalNumbers) == len(practicalNumbers) and all([i in practicalNumbers for i in calculatedPracticalNumbers]))

Equalizing the elements in a list

I'm attempting to equalize a list of elements. In short, I have an array of x length with each element y being in range from 0 - 100000. To accomplish what I'm trying to do, all elements in the list must be relatively equal to each other (as far as is possible).
Here's some sample output of my current function:
>>> equal([1, 4, 1])
[2, 2, 2]
>>> equal([2, 4, 5, 9])
[5, 5, 5, 5]
>>> equal([2, 2])
[2, 2]
>>> equal([1, 2, 3, 4, 5, 6, 7, 8, 9])
[5, 5, 5, 5, 5, 5, 5, 5, 5]
>>> equal([2, 4, 6, 8, 10, 20, 30, 40])
[15, 15, 15, 15, 15, 15, 15, 15]
>>> equal([343, 452, 948, 283, 394, 238, 283, 984, 236, 847, 203])
[474, 474, 474, 474, 474, 474, 474, 474, 473, 473, 473]
And the associated code:
def equal(l):
# The number of times we distribute to the new loop
loops = reduce(lambda x, y: x + y, l)
# Initializes a new list as such: [0, 0, 0 .. len(l)]
nl = [0 for x in range(len(l))]
# Counts how far we've iterated into our new list
x = 0
for i in range(loops):
# Add 1 to this element and move on to the next element in the list
nl[x] += 1
x += 1
# Ensure we don't traverse past the end of the list
if x > len(nl) - 1:
x = 0
return nl
The problem right now is that once you get to extremely large lists (100+ elements with large values) it gets really slow. Is there some idiom I'm missing here that would make this more efficient?
All of your examples have output lists with all equal integers [*], which of course is not possible in the general case.
[*] except one, where it seems you want earlier items to be bigger, later ones smaller, independently of what original items where big or small; see later if that is in fact your spec.
Assuming (you never actually bother to say that, you know!-) that "all items integers" is a constraint, I'd start with
minel = sum(l) // len(l)
which is the minimum value to assign to each output element. This leaves a "shortage" of
numex = sum(l) - minel * len(l)
items that must be set to minel + 1 to keep the sum equal (another constraint you never clearly express...:-).
Which ones? Presumably those that were largest in the first place.
(Added: or maybe not, according to your last example, where it seems the items that need to be made larger are just the earliest ones. If that's the case, then obviously:
[minel+1] * numex + [minel] * (len(l) - numex)
will be fine. The rest of the answer assumes you may want some connection of input items to corresponding output ones, a harder problem).
So pick those, e.g as bigs = set(heapq.nlargest(l, numex)), and
[minel + (x in bigs) for x in l]
is going to be a pretty close approximation to the "equalized" list you seek (exploiting the fact that a bool is worth 0 or 1 in arithmetic:-).
The one little glitch is for a list with duplicates -- more than numex items might satisfy the x in bigs test!
In this case you presumably want to randomly pick which numex items get to be incremented by 1 (the others staying at minel). But guessing exactly what you want for such a case in your totally under-specified desires is stretching guesses a point too much, so I'll let it rest here for now -- you can clarify your specs, ideally with examples where this formula doesn't do what you exactly want and what you would want instead, by editing your question appropriately.
Here you go. Simply find the whole number average and remainder and return the appropriate number of average+1 and average elements to give the same sum. The code below leverages the builtin divmod to give the whole quotient and remainder, and the fact that multiplying a list such as [x]*5 returns [x,x,x,x,x]:
def equal(l):
q,r = divmod(sum(l),len(l))
return [q+1]*r + [q]*(len(l)-r)
print(equal([2,1]))
print(equal([1, 4, 1]))
print(equal([2, 4, 5, 9]))
print(equal([2, 2]))
print(equal([1, 2, 3, 4, 5, 6, 7, 8, 9]))
print(equal([2, 4, 6, 8, 10, 20, 30, 40]))
print(equal([343, 452, 948, 283, 394, 238, 283, 984, 236, 847, 203]))
Output:
[2, 1]
[2, 2, 2]
[5, 5, 5, 5]
[2, 2]
[5, 5, 5, 5, 5, 5, 5, 5, 5]
[15, 15, 15, 15, 15, 15, 15, 15]
[474, 474, 474, 474, 474, 474, 474, 474, 473, 473, 473]

Generating a list of EVEN numbers in Python

Basically I need help in generating even numbers from a list that I have created in Python:
[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, ...]
I have tried a couple different methods, but every time I print, there are odd numbers mixed in with the evens!
I know how to generate even/odd numbers if I were to do a range of 0-100, however, getting only the even numbers from the previous mentioned list has me stumped!
P.S. I've only been using python for a couple days, if this turns out to be extremely simple, thanks in advance!
EDIT: Thanks for all the replies, with your help I've gotten through this little problem.
Here is what I ended up with to complete a little excercise asking to sum the even numbers of fibonacci sequence:
F = [1, 2]
while F[-1] < 4000000
F.append(F[-1] + F[-2])
sum(F[1::3])
4613732
Use a list comprehension (see: Searching a list of objects in Python)
myList = [<your list>]
evensList = [x for x in myList if x % 2 == 0]
This is good because it leaves list intact, and you can work with evensList as a normal list object.
Hope this helps!
The following sample should solve your problem.
Newlist = []
for x in numList:
if x % 2 == 0:
print x
Newlist.append(x)
You can do this with a list comprehension:
evens = [n for n in numbers if n % 2 == 0]
You can also use the filter function.
evens = filter(lambda x: x % 2 == 0,numbers)
If the list is very long it may be desirable to create something to iterate over the list rather than create a copy of half of it using ifilter from itertools:
from itertools import ifilter
evens = ifilter(lambda x: x % 2 == 0,numbers)
Or by using a generator expression:
evens = (n for n in numbers if n % 2 == 0)
In your specific case my_list[1::3] will work. There are always two odd integers between even integers in fibonacci: even, odd, odd, even, odd, odd.....
>>> my_list = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368]
>>>
...
>>> my_list[1::3]
[2, 8, 34, 144, 610, 2584, 10946, 46368]
Just check this
A = [i for i in range(101)]
B = [x for x in A if x%2 == 0]
print B
iterate through the list and use the modulo operator to check even
for number in list:
if (number % 2) == 0:
##EVEN
Just for fun, checking if number%2 != 1 also works ;)
evens=[x for x in evens_and_odds if number%2 != 1 ]
Note that you can do some clever things to separate out evens and odds in one loop:
evens=[]
odds=[]
numbers=[ evens, odds ]
for x in evens_and_odds:
numbers[x%2 == 1].append(x)
print evens
print odds
The above trick works because logical expressions (==, >, etc.) operating on numbers True (1) and/or False (0).
You can use list comprehension to generate a new list that contains only the even members from your original list.
data = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
then:
new_data = [i for i in data if not i%2]
yields
[2, 8, 34, 144]
Or alternatively use a generator expression if you don't need all of the numbers
at once:
new_data = (i for i in data if not i%2)
The values then would be availabe as needed, for instance if you used a for loop:
e.g.,
for val in new_data:
print val
The advantage of the generator expression is that the whole list is not generated and stored in memory at once, but values are generated as you need them which makes less demand on memory. There are other important differences you might want to read up on at some point if you are interested.
Instead of generating all Fibonacci numbers then filtering for evens, why not generate just the even values?
def even_fibs():
a,b = 1,2
while True:
yield b
a,b = a+2*b, 2*a+3*b
generates [2, 8, 34, 144, 610, 2584, 10946 ...]
then your sum code becomes:
total = 0
for f in even_fibs():
if f >= 4000000:
break
else:
total += f
or
from itertools import takewhile
total = sum(takewhile(lambda n: n<4000000, even_fibs()))
a = range(0,1000)
b = []
for c in a:
if c%2==0:
b.append(c)
print b
You could do this using the filter function as follows:
F = [1, 2]
while F[-1] < 4000000:
F.append(F[-1] + F[-2])
print(F)
print('\n')
#create the variable that could store the sorted values from the list you have created.
sorted_number=list(filter(lambda x:x%2==0,F))
print(sorted_number)
You could use a for and if loop using the length function, like this:
for x in range(len(numList)):
if x%2 == 0:
print(x)
NewList.append(x)
Basically you should create a variable and put your list in and then sort your even numbers list by adding it only the even numbers
numbers = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, ...]
even = [e for e in numbers if e%2==0]
Here are some of the different ways to get even numbers:
CASE 1
in this case, you have to provide a range
lst = []
for x in range(100):
if x%2==0:
lst.append(x)
print(lst)
CASE 2
this is a function and you have to pass a parameter to check if it is an even no or not
def even(rangeno):
for x in range(rangeno):
if rangeno%2 == 0:
return rangeno
else:
return 'No an Even No'
even(2)
CASE 3
checking the values in the range of 100 to get even numbers through function with list comprehension
def even(no):
return [x for x in range(no) if x%2==0]
even(100)
CASE 4
This case checks the values in list and prints even numbers through lambda function. and this case is suitable for the above problem
lst = [2,3,5,6,7,345,67,4,6,8,9,43,6,78,45,45]
no = list(filter(lambda x: (x % 2 == 0), lst))
print(no)

Odd behavior of stacked filter() calls

So I'm getting some interesting behaviour from some filters stacked within a for loop.
I'll start with a demonstration:
>>> x = range(100)
>>> x = filter(lambda n: n % 2 == 0, x)
>>> x = filter(lambda n: n % 3 == 0, x)
>>> list(x)
[0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96]
Here we get the expected output. We have a range within a filter within a filter, and the filter conditions are stacking as we want them to. Now here comes my problem.
I have written a function for calculating the relative primes of a number. It looks like this:
def relative_primes(num):
'''Returns a list of relative primes, relative to the given number.'''
if num == 1:
return []
elif is_prime(num):
return list(range(1, num))
result = range(1, num)
for factor in prime_factors(num):
# Why aren't these filters stacking properly?
result = filter(lambda n: n % factor != 0, result)
return list(result)
For whatever reason, the filter is only being applied to the LAST factor in the list acquired from prime_factors(). Example:
>>> prime_factors(30)
[2, 3, 5]
>>> relative_primes(30)
[1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 18, 19, 21, 22, 23, 24, 26, 27, 28, 29]
We can see that no multiples of 2 or 3 were removed from the list. Why is this happening? Why does the above example work, but the filters in the for loop don't?
In Python 3.x, filter() returns a generator instead of a list. As such, only the final value of factor gets used since all three filters use the same factor. You will need to modify your lambda slightly in order to make it work.
result = filter(lambda n, factor=factor: n % factor != 0, result)
The evaluation of the iterators is lazy. All filters will be evaluated only in the statement
return list(result)
By that time, the value of factor is the last prime factor. The lambda functions only contain a reference to the local name factor and will use whatever value is assigned to that name at the time of execution.
One way to fix this is to convert to a list in every iteration.
As a sidenote, a much easier implementation of this function is
from fractions import gcd
def relative_primes(n):
return [i for i in range(1, n) if gcd(n, i) == 1]
Edit: If you are after performance instead of simplicity, you can also try this one:
def relative_primes(n):
sieve = [1] * n
for i in range(2, n):
if not sieve[i] or n % i:
continue
sieve[::i] = [0] * (n // i)
return list(itertools.compress(range(n), sieve))
If I understood you correctly and Two integers are relatively prime if they share no common positive factors (divisors) except 1. Using the notation to denote the greatest common divisor, two integers a and b are relatively prime if gcd(a,b)==1. then you can use the fractions module in the following way.
from fractions import gcd
num = 30
relative_primes = filter(lambda x: gcd(x,num) == 1, xrange(1,num))

Categories

Resources