Trying to use the remainder operator to find positive values in a list and print them as it finds them.
ExampleList=[2,5,-34,0,389,202,8]
I guess I don't understand how to make the operator use the list and then print the values.
import sys
li = [2,5,-34,0,389,202,8]
m = sys.maxint
print [e for e in li if e == e%m]
ExampleList=[2,5,-34,0,389,202,8]
for i in ExampleList:
if ((i % 10) != (abs(i) % 10)):
print (i)
The above code works for this particular example but might not work generally because there are numbers which no matter if they are positive or negative give the same modulus results.
Well, any solution using < or related comparisons or abs isn't actually using any unique features of %. So just for fun, a kinda silly way to do it without using any special functions, and with no comparisons other than == that actually use a behavior of % in a meaningful way (as opposed to just adding % to code that would produce the correct result without it) for this purpose:
>>> li = [2,5,-34,0,389,202,8]
>>> print([x for x in li if x == x % (x ** 2 + 1)])
[2, 5, 0, 389, 202, 8]
We square x to create a value known to be larger than the absolute value of x (and add 1 to handle the special cases of 0 and 1).
Another kind of tricky approach is to use the number as the divisor in such a way as to always get a fixed value from non-negative inputs:
# 1 % (x+2 or x+1) returns 1 for 0 or positive, non-1 for negative
# Use x+2 or x+1 to avoid ZeroDivisionError for x == 0
>>> print([x for x in li if 1 == 1 % (x+2 or x+1)])
[2, 5, 0, 389, 202, 8]
# We can even avoid using == by substituting subtraction since the result
# is a fixed 1 for non-negative, though it's pretty ugly looking
>>> print([x for x in li if not 1 % (x+2 or x+1) - 1])
[2, 5, 0, 389, 202, 8]
# Or if 0 shouldn't be included in results, tweak the divisor differently:
>>> print([x for x in li if 1 == 1 % (x+1 or x)])
[2, 5, 389, 202, 8]
Related
Task: count the number of operations required to make an array's values alternate between even and odd.
Given: items = [6, 5, 9, 7, 3] (Example test case)
Operations we can do: make n number of operations: floor(item/2)
My code
def change(expected):
return 1 if (expected == 0) else 0
def getMinimumOperations(items, expected):
countOp = 0
for i in items:
if (int(i % 2 == 0) != expected):
countOp += 1
expected = change(expected)
return countOp
def minChangeToGetMinOp(items):
minStack = [getMinimumOperations(items, 1), getMinimumOperations(items, 0)]
return min(minStack)
if __name__ == "__main__":
items = [6, 5, 9, 7, 3]
print(minChangeToGetMinOp(items))
ANS: 3
What I'm asking: A good approach to solve this
Taking the comment that the division by 2 can be repeated multiple times on the same input number -- until its parity is as expected (or the number becomes 0 and the odd parity is required), the program would need an inner loop:
def getMinimumOperations(items, expected):
countOp = 0
for i in items:
while i % 2 != expected:
if not i:
return float("inf") # Not possible
i //= 2
countOp += 1
expected = 1 - expected
return countOp
def minChangeToGetMinOp(items):
return min(getMinimumOperations(items, 1), getMinimumOperations(items, 0))
if __name__ == "__main__":
items = [6, 5, 9, 7, 3]
print(minChangeToGetMinOp(items)) # 3
This seems like more of a math/logic problem than a Python problem.
To make a list's elements alternate between odd and even, either all the elements at even indices should be even and the rest odd, or all the elements at even indices should be odd and the rest even.
It appears you're not looking to change the order of elements, but to add or subtract one to make them comply.
So, to make the list comply, either you need to change all even elements at odd indices and all odd elements at even indices, or vice versa.
The answer therefore:
def needed_changes(xs):
c = sum((i + n) % 2 for i, n in enumerate(xs))
return min(c, len(xs) - c)
if __name__ == '__main__':
xs = [6, 5, 9, 7, 3]
print(needed_changes(xs))
Output:
2
The solution adds each element to its index, and then takes the mod 2 of it, so that each element becomes either 1 if the index or the value is odd, or 0 if both are odd, or both are even. As a result, the sum of those 1's will be the number of elements that need to be changed - but if that number is more than half, you could just change the rest of the elements instead, which is what the last lines decides.
Edit: From your comment it became clear that operations allowed are limited and the only operation allowed is x = floor(x / 2). This complicates the issue because this operation only results in an even outcome for every other two numbers. The pattern looks like this:
0 0 # 'even' to start with
1 0 # 'even' after 1 operation
2 1 # even to start with
3 1 # still odd after 1 op, after another 'even' (0)
4 2 # even to start with
5 2 # even after 1 op
6 3 # even to start with
7 3 # still odd after 2 ops, needs 3
8 4 # even to start with
..
So, each 4th number will be both odd, and its floor(x/2) will also be odd. If you apply the operation again, only half of those results will be even, etc.
Another way to look at the problem then: if a number's binary representation ends in a 0, it is even. If you take the floor(x/2) of a number, you're really just performing a "shift right" operation. So, if an number's binary representation has a 0 as the second least significant bit, performing the operation will make it even. And so on.
So, a solution using only that operation:
def needed_changes(xs):
ns = []
for x in xs:
n = 0
while x % 2:
n, x = n + 1, x >> 1
ns.append(n)
return min(sum(ns[0::2]), sum(ns[1::2]))
Or, if you don't like building a whole new list and want the solution to save space:
def needed_changes(xs):
ns = [0, 0]
for i, x in enumerate(xs):
n = 0
while x % 2:
n, x = n + 1, x >> 1
ns[i % 2] += n
return min(ns)
I am trying to gain a better understanding of how list comprehensions work.
I have the following function that returns true or false if a number is prime (which I found somewhere on the forum but cant remember where):
import math
def is_prime(n):
if n % 2 == 0 and n > 2:
return False
for i in range(3, int(math.sqrt(n)) + 1, 2):
if n % i == 0:
return False
return True
if I run:
[x for x in range(2, num) if is_prime(x)]
i get the desired result
[2, 3, 5, 7, 11, 13, 17, 19]
in trying to convert the whole function to a list comprehension I came up with:
[x if not (x%2==0 and x > 2) else x for x in range (2, num)
for i in range(3, int(x**(1/2))+1, 2) if not (x%i==0)]
which produces:
[10, 11, 13, 14, 16, 17, 19]
not sure where I am going wrong and would appreciate some help. In truth I think it is better to use the function in this case, but like I said I am trying to understand the list comprehension and its capabilities.
You can do this:
[n for n in range(2, num) if n % 2 != 0 and n > 2 and all(n % i != 0 for i in range(3, int(math.sqrt(n)) + 1, 2))]
although one liner just for the sake of it is not necessarily a good thing. IMO using a prime tester function like you do is better...
NOTE: what doesn't work in your try is that you modified the logic of your outer list comprehension. You still want a structure like [n for n in range(...) if (expression testing if n is prime)].
The main problem is that you're making a convoluted translation. Try simplifying the original condition so that you return "x if x==2, else x ..." as you've already done. I'm just giving you a leading hint here; from what you've done already, I think you can figure it out.
If not, try simplifying the "else" expression so you learn the logic of that clause. Then I'm sure you'll get it. You're doing well.
There are logical errors in the code above
1/2 evaluates to 0, not to 0.5. To do that, either use 0.5 or 1/2.0 or 1.0/2
Also it does not take care of 2 as a special case. as (for i in range(3, int(x**(1/2.0))+1, 2) if not (x%i==0)) is not executed
for i in range(3, int(x**(1/2.0))+1, 2) if not (x%i==0) is also a logical error as whenever this condition is true, it causes multiple entries to be added
the correct way would be
[x for x in range (2, num) if x == 2 or (x > 2 and x % 2 == 1 and len([i for i in range(3, int(x**(1/2.0))+1, 2) if x%i == 0 ])==0)]
I am new to python, and I was wondering if I could generate the fibonacci series using python's list comprehension feature. I don't know how list comprehensions are implemented.
I tried the following (the intention was to generate the first five fibonacci numbers):
series=[]
series.append(1)
series.append(1)
series += [series[k-1]+series[k-2] for k in range(2,5)]
This piece of code throws the error: IndexError: list index out of range.
Let me know if it is even possible to generate such a series using a list comprehension.
You cannot do it like that: the list comprehension is evaluated first, and then that list is added to series. So basically it would be like you would have written:
series=[]
series.append(1)
series.append(1)
temp = [series[k-1]+series[k-2] for k in range(2,5)]
series += temp
You can however solve this by using list comprehension as a way to force side effects, like for instance:
series=[]
series.append(1)
series.append(1)
[series.append(series[k-1]+series[k-2]) for k in range(2,5)]
Note that we here do not add the result to series. The list comprehension is only used such that .append is called on series. However some consider list comprehensions with side effects rather error prone: it is not very declarative and tends to introduce bugs if not done carefully.
We could write it as a clean Python list comprehension (or generator) using it's relationship to the golden ratio:
>>> series = [int((((1 + 5**0.5) / 2)**n - ((1 - 5**0.5) / 2)**n) / 5**0.5) for n in range(1, 21)]
>>> series
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
>>>
or a little more nicely as:
>>> square_root_of_five = 5**0.5
>>> Phi = (1 + square_root_of_five) / 2
>>> phi = (1 - square_root_of_five) / 2
>>>
>>> series = [int((Phi**n - phi**n) / square_root_of_five) for n in range(1, 21)]
>>> series
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
If you know how many terms of the series you will need then you can write the code compactly without a list comprehension like this.
def Fibonacci(n):
f0, f1 = 1, 1
for _ in range(n):
yield f0
f0, f1 = f1, f0+f1
fibs = list(Fibonacci(10))
print (fibs)
If you want some indefinite number of terms then you could use this, which is very similar.
def Fibonacci():
f0, f1 = 1, 1
while True:
yield f0
f0, f1 = f1, f0+f1
fibs = []
for f in Fibonacci():
fibs.append(f)
if f>100:
break
print (fibs)
When you need a potentially infinite collection of items you should perhaps consider either a function with one or more yield statements or a generator expression. I'd love to be able to make Fibonacci numbers with a generator expression but apparently one can't.
Using Assignment Expression (python >= 3.8):
s = [0, 1]
s += [(s := [s[1], s[0] + s[1]]) and s[1] for k in range(10)]
print (s)
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
To build on what Willem van Onsem said:
The conventional way to calculate the nth term of the fibonacci sequence is to sum the n-1 and n-2 terms, as you're aware. A list comprehension is designed to create a list with no side effects during the comprehension (apart from the creation of the single list). Storing the last 2 terms of the sequence during calculation of the sequence is a side-effect, therefore a list comprehension is ill-suited to the task on its own.
A safe way around this would be to make a closure generator (essentially a generator with some associated private state) that can be passed to the list comprehension such that the list comprehension does not have to worry about the details of what's being stored:
def fib_generator(n):
def fib_n_generator():
last = 1
curr = 1
if n == 0:
return
yield last
if n == 1:
return
yield curr
if n == 2:
return
ii = 2
while ii < n:
next = curr + last
yield next
last = curr
curr = next
ii += 1
return fib_n_generator()
fib = [xx for xx in fib_generator(10)]
print(fib)
Here's a one-line list comprehension solution that avoids the separate initialization step with nested ternary operators and the walrus operator (so needs Python 3.8), and also avoids the rapid onset of overflow problems that the explicit form can give you (with its **n component):
[
0 if not i else
(x := [0, 1]) and 1 if i == 1 else
not x.append(x[-2] + x[-1]) and x[-1]
for i in range(10)
]
Gives:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
This is faster than the explicit form for generating all of the values up to N. If, however, you don't want all of the values then the explicit form could be much faster, but it does suffer from overflow for some N between 1000 and 2000:
n = 2000
int((((1 + 5**0.5) / 2)**n - ((1 - 5**0.5) / 2)**n) / 5**0.5)
gives for me:
OverflowError: (34, 'Numerical result out of range')
whereas the "adding the last two values" approach can generate higher values for larger N. On my machine, I can keep going until some N between 300000 and 400000 before I run out of memory.
Thanks to Jonathan Gregory for leading me most of the way to this approach.
List comprehension of the fibonacci serie, based on the explicit formula 1:
[int((0.5+5**0.5/2)**n/5**0.5+0.5) for n in range(21)]
From Python One-Liners by Christian Mayer.
n = 10
x = [0,1]
fibs = x[0:2] + [x.append(x[-1] + x[-2]) or x[-1] for i in range(n-2)]
print(fibs)
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
The answer is you can do this with a list comprehension without the assignment operator (works even in Python 2).
I did it this way:
def Phi(number:int):
n = [1,1]
[n.append(n[i-2]+n[i-1])for i in range(2,number)]
return n
Simplification of #dhassel version (requires python 3.8 or later)
series = [i0 := 0, i1 := 1]+[i1 := i0 + (i0 := i1) for j in range(2, 5)]
One can also be written as a generator expression, but it's a bit tricky because for some reason, the obvious answer: fibo = (v for g in ((i0 := 0, i1 := 1), (i1 := i0 + (i0 := i1) for j in range(2,10))) for v in g) doesn't work (I do not exclude a bug). However, it is OK if you get the subgenerators list outside :
glist = ((i0 := 0, i1 := 1), (i1 := i0 + (i0 := i1) for j in range(2, 5)))
fibo = (v for g in glist for v in g)
# Get a number from the user.
number = int(input("enter a number"))
# Create a empty list
mylist=[]
# create list comprehension following fibonaci series
[mylist.append(0) if n==0 else mylist.append(1) if n==1 else mylist.append(mylist[-2]+mylist[-1]) for n in range(number+1)]
print(mylist)
Using List comprehension :
n = int(input())
fibonacci_list = [0,1]
[fibonacci_list.append(fibonacci_list[k-1]+fibonacci_list[k-2]) for k in range(2,n)]
if n<=0:
print('+ve numbers only')
elif n == 1:
fibonacci_list = [fibonacci_list[0]]
print(fibonacci_list)
else:
print(fibonacci_list)
maybe it's a feasible solution for this problem...
If i had a list of numbers and some maybe negative, how would i ensure all numbers in my list were positive? I can covert the items in the list to integers thats no problem.
Another question, I want to compare items in my list to an integer value say 'x' and sum all the values in my list that are less than x.
Thank you.
If you have a list Ns of numbers (if it's a list of strings as in several similar questions asked recently each will have to be made into an int, or whatever other kind of number, by calling int [[or float, etc]] on it), the list of their absolute values (if that's what you mean by "ensure") is
[abs(n) for n in Ns]
If you mean, instead, to check whether all numbers are >= 0, then
all(n >= 0 for n in Ns)
will give you a bool value respecting exactly that specification.
The sum of the items of the list that are <x is
sum(n for n in Ns if n < x)
Of course you may combine all these kinds of operations in one sweep (e.g. if you need to take the abs(n) as well as checking if it's < x, checking if it's >= 0, summing, whatever).
# input list is named "lst"
pos_list = [int(a) for a in lst if int(a) > 0]
# And num 2 (notice generator is used instead of list)
return sum(a for a in lst if a < x)
Answer / First part:
>>> a = [1, 2, -3, 4, 5, 6]
>>> b = [1, 2, 3, 4, 5, 6]
>>> max(map(lambda x: x < 0, a))
False
>>> max(map(lambda x: x < 0, b))
True
Or just use min:
>>> min(a) < 0
True
>>> min(b) < 0
False
Second part:
>>> x = 3
>>> sum(filter(lambda n: n < x, a))
>>> 0
>>> sum(filter(lambda n: n < x, b))
>>> 3
If I understand correctly your question, I guess you are asking because of some class about functional programming.
In this case, what you are asking for can be accomplished with functional programming tools available in Python.
In particular, the first point can be solved using filter, while the second with map and reduce (or, better, with map and sum).
>>>mylist = [1,2,3,-2]
>>>any(item for item in mylist if item < 0)
True
>>>mylist.pop()
-2
>>>any(item for item in mylist if item < 0)
False
answers your first question.
>>> x = 3
>>> sum(item for item in mylist if item < x)
3
answers your second question.
What is the equivalent list comprehension in python of the following Common Lisp code:
(loop for x = input then (if (evenp x)
(/ x 2)
(+1 (* 3 x)))
collect x
until (= x 1))
A list comprehension is used to take an existing sequence and perform some function and/or filter to it, resulting in a new list. So, in this case a list comprehension is not appropriate since you don't have a starting sequence. An example with a while loop:
numbers = []
x=input()
while x != 1:
numbers.append(x)
if x % 2 == 0: x /= 2
else: x = 3 * x + 1
I believe you are writing the hailstone sequence, although I could be wrong since I am not fluent in Lisp.
As far as I know, you can't do this in only a list comprehension, since each element depends on the last.
How I would do it would be this
def hailstone(n):
yield n
while n!=1
if n%2 == 0: # even
n = n / 2
else: # odd
n = 3 * n + 1
yield n
list = [ x for x in hailstone(input) ]
Of course, input would hold whatever your input was.
My hailstone function could probably be more concise. My goal was clarity.
Python doesn't have this kind of control structure built in, but you can generalize this into a function like this:
def unfold(evolve, initial, until):
state = initial
yield state
while not until(state):
state = evolve(state)
yield state
After this your expression can be written as:
def is_even(n): return not n % 2
unfold(lambda x: x/2 if is_even(x) else 3*x + 1,
initial=input, until=lambda x: x == 1)
But the Pythonic way to do it is using a generator function:
def produce(x):
yield x
while x != 1:
x = x / 2 if is_even(x) else 3*x + 1
yield x
The hackery referred to by Laurence:
You can do it in one list comprehension, it just ends up being AWFUL python. Unreadable python. Terrible python. I only present the following as a curiosity, not as an actual answer. Don't do this in code you actually want to use, only if you fancy having a play with the inner workings on python.
So, 3 approaches:
Helping List 1
1: Using a helping list, answer ends up in the helping list. This appends values to the list being iterated over until you've reached the value you want to stop at.
A = [10]
print [None if A[-1] == 1
else A.append(A[-1]/2) if (A[-1]%2==0)
else A.append(3*A[-1]+1)
for i in A]
print A
result:
[None, None, None, None, None, None, None]
[10, 5, 16, 8, 4, 2, 1]
Helping List 2
2: Using a helping list, but with the result being the output of the list comprehension. This mostly relies on list.append(...) returning None, not None evaluating as True and True being considered 1 for the purposes of arithmetic. Sigh.
A=[10]
print [A[0]*(not A.append(A[0])) if len(A) == 1
else 1 if A[-1] == 2 else (A[-1]/2)*(not A.append(A[-1]/2)) if (A[-1]%2==0)
else (3*A[-1]+1)*(not A.append(3*A[-1]+1))
for i in A]
result:
[10, 5, 16, 8, 4, 2, 1]
Referencing the List Comprehension from within
3: Not using a helping list, but referring back to the list comprehension as it's being built. This is a bit fragile, and probably wont work in all environments. If it doesn't work, try running the code on its own:
from itertools import chain, takewhile
initialValue = 10
print [i if len(locals()['_[1]']) == 0
else (locals()['_[1]'][-1]/2) if (locals()['_[1]'][-1]%2==0)
else (3*locals()['_[1]'][-1]+1)
for i in takewhile(lambda x:x>1, chain([initialValue],locals()['_[1]']))]
result:
[10, 5, 16, 8, 4, 2, 1]
So, now forget that you read this. This is dark, dark and dingy python. Evil python. And we all know python isn't evil. Python is lovely and nice. So you can't have read this, because this sort of thing can't exist. Good good.
As Kiv said, a list comprehension requires a known sequence to iterate over.
Having said that, if you had a sequence and were fixated on using a list comprehension, your solution would probably include something like this:
[not (x % 2) and (x / 2) or (3 * x + 1) for x in sequence]
Mike Cooper's answer is a better solution because it both retains the x != 1 termination, and this line doesn't read cleanly.
1
I have discovered a truly marvelous proof of this, which this margin is too narrow to contain.
In all seriousness though, I don't believe you can do this with Python list comprehensions. They have basically the same power as map and filter, so you can't break out or look at previous values without resorting to hackery.