I am struggling to find a way to check if every other number in my list is of an alternating parity (i.e. even, odd, even, odd, etc.)
[1,2,3,4] # odd, even, odd, even (True, because they alternate)
[1,3,2,4] # odd, odd, even, even (False, because they don't alternate)
Anyone have any idea how I can check for this?
You can use the Python modulus operator % on adjacent values within an input list and check for equality while iterating.
If you choose this route and efficiency is a concern, I advise you use 3rd party libraries such as NumPy / numba so the iteration does not take place at Python level:
from numba import jit
#jit(nopython=True)
def check_alt_parity(L):
for i in range(len(L)-1):
if L[i] % 2 == L[i+1] % 2:
return False
return True
def check_alt_parity_list(L):
for i in range(len(L)-1):
if L[i] % 2 == L[i+1] % 2:
return False
return True
A = [1, 2, 3, 4] * 10000
B = [1, 3, 2, 4] * 10000
%timeit check_alt_parity(A) # 780 µs
%timeit check_alt_parity_list(A) # 9.09 ms
Here
def alter(ls):
for i in range(len(ls)-1):
if ls[i]%2 == ls[i+1]%2:
return False
return True
You can iterate over all indices of your sequence and then compare it with the next one:
def is_alternating_parity(seq):
for i in range(len(seq) - 1):
if seq[i] % 2 == seq[i + 1] % 2:
return False
return True
print(is_alternating_parity([1, 2, 3, 4])) # True
print(is_alternating_parity([1, 3, 2, 4])) # False
Try this function, l for list comprehension and getting bool for odd or even, then checking if all are true (the every second even index element is all True or all False, and same with every odd index element:
def oddeven_alter(l):
l=[i%2 for i in l]
return all([any([all(l[::2]),all(not i for i in l[::2])]),any([all(l[1::2]),all(not i for i in l[1::2])])])
)
print(oddeven_alter([1,2,3,4]))
print(oddeven_alter([1,3,2,4]))
Output:
True
False
Kind of complex looking tho
Related
So I programmed this code to find whether all numbers in a list are multiples of a number k: or not, but it doesn't seem to work. can anyone give some examples for me to draw ideas from?
Use %7 instead of //7. // will give you whole number quotient and % will give you remainder. Let use say some number 49, 49//7 is 7 and 49%7 is 0. Another example 26, 26//7 is 3 and 26%7 is 5
There two issues with your code.
First you need to use % to get the rest of the division x / k.
Second as you're doing it, you exit the function as soon as you have found a number
in your list that is a multiple of k: you don't check remaining items in your list.
Here is a modified version of your code:
k = 4
a: list= [3, 4, 4, 3]
def allMultiplesofK(k, a):
for x in list(a):
if x % k != 0:
return False
return True # all items of a are multiples of k
print(allMultiplesofK(k, a))
In your code the return inside the loop will quit the loop as soon as the condition will be satisfied, so, it will will not check all numbers in the list. You can use for example list comprehension and the all function from the standard library, see docs,
def allMultiplesofK(k, a):
return all(map(lambda p: p % k == 0, a))
return all([p % k == 0 for p in a]) # with list comprehension
k = 4
a: list= [3, 4, 4, 8]
print(allMultiplesofK(k, a))
# False
a: list= [12, 4, 4, 8]
print(allMultiplesofK(k, a))
# True
You aren't actually checking every item of the loop.
for x in list(a):
if x // k == 0:
return True
if x // k != 0:
return False
This is returning from the function after only checking the first item in the list.
Also the way you are checking if one number is divisible by another isn't quite right. You should be using the modulo operator "%". This operator gives you the remainder after the division.
3 % 4 = 3 # since 4 goes into 3, 0 times with 3 remaining.
Therefore your program should become:
k = 4
a: list= [3, 4, 4, 3]
def allMultiplesofK(k, a):
for x in list(a):
if x % k != 0:
return False
return True
print(allMultiplesofK(k, a))
Use modulo instead of floor division.
Floor division:
This will gives you the quotient
Modulus:
This will give you the remainder.
k = 4
a = [3, 4, 4, 3]
def allMultiplesofK(k, a):
for x in list(a):
if x % k == 0:
return True
else:
return False
print(allMultiplesofK(k, a))
output: False
But this will not give all numbers result i.e it will print last values 3%4 False.
result = [True if i % k == 0 else False for i in a]
print(result)
Output: [False, True, True, False]
I have,
def geometric(lst):
'checks whether the integers in list lst form a geometric sequence'
for i in range(1, len(lst) - 1):
if lst[i] * 2 == "don't know what to check here":
return True
else:
return False
I'm not sure how to apply that to check if all the indices. Would prefer this done within a for-loop. any help would be appreciated!
I think this works:
def geometric(lst):
for i in range(len(lst) - 2):
if lst[i] * lst[i + 2] != lst[i + 1] ** 2:
return False
return True
This is based on the idea that for any three consecutive terms a, b, c, the ratio between the first two must equal the ratio between the last two, i.e. b/a = c/b. Rearranging this gives a * c == b ** 2. It's much better to use the form without division, because division introduces rounding errors. This function even works if the common ratio is not an integer (e.g. [4, 6, 9]).
Edit
The above answer does not handle lists containing 0 correctly.
A correct version is:
def geometric(lst):
for i in range(len(lst) - 2):
if lst[i] * lst[i + 2] != lst[i + 1] ** 2:
return False
for i in range(len(lst) - 1):
if lst[i] == 0 and lst[i + 1] != 0:
return False
return True
This returns True for [1, 0, 0] (common ratio 0) but False for [0, 0, 1]. The original version returned True for both.
It may be better to disallow common ration 0. This would mean changing the second loop to return False for any list of length 2 or more containing 0.
As sam2090 has pointed out, the right side of the condition in line 4 has been left empty. If the common ratio of the geometric sequence is 2 (maybe it's something that you would actually want to pass as a parameter of the function), then the expression should be:
if lst[i] == lst[i-1] * 2
The left-hand side of the statement refers to the current number in the itertion (i), while the right-hand side of the statement refers to the previous number (i-1) and multiplies its value by 2.
Also, in the foor loop, be sure you iterate until the last element in the list, so you should write:
for i in range(1, len(lst)):
and not
for i in range(1, len(lst) - 1):
m = range(1, 2000000, 2)
sum1 = 2
for x in xrange(1, 2000000, 2):
for y in m:
if x != y:
if x%y == 0:
m.remove(x)
if all(x%y != 0):
sum1 += x
That's what I've written. It's about a problem, trying to add all the primes bellow two million. My problem is in the all() statement. What I want to happen is to check if x is a prime; that is true only if every x%y gives a remainder.
Also if I use a can I use a statement (break?) to stop the loop if y > x/3 like so:
m = range(1, 2000000, 2)
sum1 = 2
for x in xrange(1, 2000000, 2):
for y in m:
if y > x/3:
break
else:
if x != y:
if x%y == 0:
m.remove(x)
if all(x%y != 0):
sum1 += x
You have to pass a sequence or iterable to all -- it just tests whether or not all the items passed to it evaluate as true. Here's the right way to use all:
>>> all([True, True, True])
True
>>> all([True, False, True])
False
>>> all([x > 5 for x in range(10)])
False
>>> all([x > 5 for x in range(6, 10)])
True
>>> all(x > 5 for x in range(6, 10))
True
That last one is the best, because it takes advantage of short-circuiting.
However, your call to all in your code is pointless. The idea behind your code, it seems to me, is to go through all the values in m and remove those that are divisible by any number between 2 and 2000000. Once you've done that, m will contain only prime numbers.
Of course, your code still won't work if you remove all. That's because you're actually testing whether each number in m is divisible by the numbers [1, 3, 5, 7...1999999]. (That's the sequence signified by xrange(1, 2000000, 2). Because you start at 1, and everything is divisible by 1, your code will count nothing as prime. And then, once you remove 1 from that sequence, anything divisible by 2 will be counted as prime by your code! You should think more carefully about which numbers you actually have to test in your inner loop.
Finally, you should think about how many loops this code will complete. Even once you have this working, it will take a very long time to generate a result. You should test it on smaller numbers first; and then, you should think about how to reduce the number of loops. (And -- only after you've thought about it a bit -- read this.)
But once you have this working, all you have to do is call sum on your list of primes.
Your use of all is incorrect, if you look at the documentation for it, it takes an iterable.
What you may be trying to do is use a generator expression, something of the form:
sum(x**2 for x in range(10))
which is very similar to the list comprehension
[x**2 for x in range(10)]
However, use of all in this manner wouldn't suddenly stop the generator expression, if it found a divisor. Use of any and checking for x == 0 would stop sooner, but as the code is currently formatted, would check for many divisors before deeming something prime.
This would be more appropriate:
primes = []
MAX = 2000000
number = 2
while number < MAX:
for prime in primes:
if number % prime == 0:
number += 1
continue
primes.append(number)
number += 1
total = sum(primes)
all() takes an iterable for an argument. In your situation, you would use it like this:
all(x%y for y in m)
where x%y for y in m is a generator expression.
If I have an iterable
[item1, item2, item3, item4...]
all(iterable) is equivalent to:
item1 and item2 and item3 and item4...'
I've made a small function which, given a tuple, compares if all elements in this tuple is of the same sign.
E.g., tuple = [-1, -4, -6, -8] is good, while [-1, -4, 12, -8] is bad. I am not sure I've made the smartest implementation, so I know this is the place to ask.
def check_consistent_categories(queryset):
try:
first_item = queryset[0].amount
if first_item < 0:
for item in queryset:
if item > 0:
return False
return True
else:
for item in queryset:
if item < 0:
return False
return True
except:
return False
This might help you:
def all_same_sign(ints):
return all(x < 0 for x in ints) or all(x > 0 for x in ints)
You may want to change < and > to <= and >= depending on how you want to treat 0.
After #EOL's solution, but works without list indexing or iterating multiple times.
def all_same_sign(sequence):
items = iter(sequence)
try:
first = items.next() > 0
except StopIteration:
return True
return all((item > 0) == first for item in items)
This also occurred to me, but doesn't take advantage of all/any short-circuiting:
def all_same_sign(sequence):
return len(set(item > 0 for item in sequence)) <= 1
Just one unrelated nit, since you are doing this:
try:
[...]
except:
[...]
You are ignoring all of the exceptions, be very careful my friend, this will be hiding lots of bugs, instead always be precise while doing exception handling e.g:
try:
[...]
except IndexError:
# Handle out of index
except IOError:
# Handle I/O error
etc. Keep this in mind while coding a larger python application.
Here is a nice pythonic way of doing this (using all()):
from math import copysign
sign = lambda x: copysign(1, x) # Sign function
def check_consistent_categories(sequence):
main_sign = sign(sequence[0])
return all(sign(y) == main_sign for y in sequence)
(for Python 2.6+, which introduced the math.copysign() function). This solution considers that 0 is positive.
Mark Byers' solution is more flexible, though, and it is also arguably more legible.
Why not take advantage of the fact that if all numbers are the same sign, then the sum of the absolute value of each individual number will be equal to the absolute value of the sum of each number?
def check_sign(queryset):
return abs(sum(queryset)) == sum(map(abs, queryset))
Example Showing Details of the Math
Case 1: All numbers have the same sign
a = (-1, -4, -8)
sum(a) = -13
abs(sum(a)) = 13 # the absolute value of the tuple's sum
map(abs, a) = [1, 4, 8]
sum(map(abs, a)) = 13 # the tuple's sum of each element's absolute value
Both methods yield 13, so the signs are the same.
Case 2: Not all numbers have the same sign
b = (-1, 4, 8)
sum(b) = 11
abs(sum(b)) = 11 # the absolute value of the tuple's sum
map(abs, b) = [1, 4, 8]
sum(map(abs, b)) = 13 # the tuple's sum of each element's absolute value
The methods yield different numbers (11 and 13), so the signs are not all the same.
Here is one that works fine with generators etc. too
def all_same_sign(ints):
ints = iter(ints)
first_is_positive = next(ints) > 0
return all( (x>0) == first_is_positive for x in ints)
If ints is empty, you get a StopIteration exception.
This version gorups 0 with the negative numbers. Use >= if you wish to group with the positive numbers instead
def all_same_sign(iterable):
# Works with any iterable producing any items that can be compared to zero.
# Iterates through the input no more than once, and this fact is immediately
# obvious from the code.
# Exits as soon as a bad combination has been detected.
pos = neg = zero = False
for item in iterable:
if item > 0:
pos = True
elif item < 0:
neg = True
else:
zero = True
# Adjust the following statement if a different
# treatment of zero is required.
# Redundant parentheses added for clarity.
if (pos and neg) or zero:
return False
return True
If your numbers are sorted you only need to compare the ends. If not you could sort them:
def same_sign(numbers):
numbers = sorted(numbers)
#if numbers[0]==0: return True Uncomment if you consider 0 positive
if numbers[0]*numbers[-1]>0: return True
return False
If you changed this to >=0 zero would be considered sign neutral. I'm not sure if this is a better implementation than the current answers, but it could be faster for large sets of data.
Using the principal that multiplying your numbers gives a positive result if they all the same, else negative,
import operator
def all_same_sign(intlist):
return reduce(operator.mul, intlist) > 0
>>> all_same_sign([-1, -4, -6, -8])
True
>>> all_same_sign([-1, -4, 12, -8])
False
This doesn't handle zeros though...
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.