Related
We have a given number from 2 to N. Each number divisible should appear as below:
[(2,4), (2,6), (2,8),(3,9),(3,12),(3,15),(4,8),(4,12),(4,16) ...] upto N
numbers.
I tried it myself (see below), but I am not getting the expected output as above (which is the one I want).
>>> [(a, b) for a in range(5) for b in range(5) if a%2 == 0 and b %2==0]
>>> [(0, 0), (0, 2), (0, 4), (2, 0), (2, 2), (2, 4), (4, 0), (4, 2), (4, 4)]
NOTE: Any number divisible by n (where n is a whole number - 1, 2, 3, 4 ...) is a multiple of n.
You can try:
n = int(input("Enter a number: "))
multiples = [(a, b) for a in range(2, n + 1) for b in range(2, n + 1) if b%a == 0 and a != b]
print (multiples)
where n is the number "below" which the number of multiples is printed for a specific number, but using n + 1 prints the number of multiples "up to" n (only if it is possible).
For example, when n = 10, it will give this output, [(2, 4), (2, 6), (2, 8), (2, 10), (3, 6), (3, 9), (4, 8), (5, 10)].
This has two conditions: b%a == 0, which makes sure that a is not zero, as b / 0 == math error and b%a checks whether the second number is a factor of the first number, or not.
Without b%a == 0, you would have:
[(2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (2, 9), (3, 2), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (4, 2), (4, 3), (4, 5), (4, 6), (4, 7), (4, 8), (4, 9), (5, 2), (5, 3), (5, 4), (5, 6), (5, 7), (5, 8), (5, 9), (6, 2), (6, 3), (6, 4), (6, 5), (6, 7), (6, 8), (6, 9), (7, 2), (7, 3), (7, 4), (7, 5), (7, 6), (7, 8), (7, 9), (8, 2), (8, 3), (8, 4), (8, 5), (8, 6), (8, 7), (8, 9), (9, 2), (9, 3), (9, 4), (9, 5), (9, 6), (9, 7), (9, 8)]
Since you do not want a equal to b (3 == 3), you can use a != b, so don't have to worry about getting (3, 3) or (4, 4) etc.
To get the maximum number of multiples for a good range of numbers ( 2 to n) , I would use a larger sample such as n = 50, which will give this output:
[(2, 4), (2, 6), (2, 8), (2, 10), (2, 12), (2, 14), (2, 16), (2, 18), (2, 20), (2, 22), (2, 24), (2, 26), (2, 28), (2, 30), (2, 32), (2, 34), (2, 36), (2, 38), (2, 40), (2, 42), (2, 44), (2, 46), (2, 48), (2, 50), (3, 6), (3, 9), (3, 12), (3, 15), (3, 18), (3, 21), (3, 24), (3, 27), (3, 30), (3, 33), (3, 36), (3, 39), (3, 42), (3, 45), (3, 48), (4, 8), (4, 12), (4, 16), (4, 20), (4, 24), (4, 28), (4, 32), (4, 36), (4, 40), (4, 44), (4, 48), (5, 10), (5, 15), (5, 20), (5, 25), (5, 30), (5, 35), (5, 40), (5, 45), (5, 50), (6, 12), (6, 18), (6, 24), (6, 30), (6, 36), (6, 42), (6, 48), (7, 14), (7, 21), (7, 28), (7, 35), (7, 42), (7, 49), (8, 16), (8, 24), (8, 32), (8, 40), (8, 48), (9, 18), (9, 27), (9, 36), (9, 45), (10, 20), (10, 30), (10, 40), (10, 50), (11, 22), (11, 33), (11, 44), (12, 24), (12, 36), (12, 48), (13, 26), (13, 39), (14, 28), (14, 42), (15, 30), (15, 45), (16, 32), (16, 48), (17, 34), (18, 36), (19, 38), (20, 40), (21, 42), (22, 44), (23, 46), (24, 48), (25, 50)]
Hope this helps!
[(a, b) for a in range(5) for b in range(5)]
gives tuples containing all the combinations of pairs of numbers starting from, and including 0, up to (but not including) 5.
a%2 == 0 is checking for a being even. Likewise for b%2 == 0, so you are finding tuples of even numbers from the unfiltered list above, hence your output.
If you don't want zero, start at 1, e.g. range(1,5) or range(2, 5).
In fact, you need to avoid zeros.
To check the second number is a factor of the first, check b%a, having made sure a won't be zero.
So more like this:
>>> [(a, b) for a in range(2, 5) for b in range(2, 5) if b%a == 0]
[(2, 2), (2, 4), (3, 3), (4, 4)]
To avoid (3,3) or other cases add a != b to the condition in the list comprehension.
[(a, b) for a in range(2, 5) for b in range(2, 5) if b%a == 0 and a!=b]
[(2, 4)]
If you then want each second number to just appear once, you can subsequently filter that list.
I want to produce something between a permutation and a combination for a list of tuples. If, for example, I have the list
list_of_tuples = [(1,20), (1,21), (2,18), (2,19)]
I want to create all possible "combinations" of 3 tuples so that I want the list to include the result [(1,20), (1,20), (1,20)] but I consider [(1,20), (1,20), (1,21)] to be identical to [(1,20), (1,21), (1,20)] and [(1,21), (1,20), (1,20)] and want to keep only one of these (doesn't matter which one).
In other words, if the "combination" includes the same tuples as another "combination", I don't want to keep the other one(s).
I've tried something like
list_of_lists = [list_of_tuples]*3
results = list(itertools.product(*list_of_lists))
results = set(results)
But by using set() I lose [(1,20), (1,20), (1,20)] and all the other results that have the same tuple three times.
Use itertools.combinations_with_replacement, which should produce exactly what you describe:
>>> from itertools import combinations_with_replacement
>>> list_of_tuples = [(1,20), (1,21), (2,18), (2,19)]
>>> list(combinations_with_replacement(list_of_tuples, 3))
[((1, 20), (1, 20), (1, 20)),
((1, 20), (1, 20), (1, 21)),
((1, 20), (1, 20), (2, 18)),
((1, 20), (1, 20), (2, 19)),
((1, 20), (1, 21), (1, 21)),
((1, 20), (1, 21), (2, 18)),
((1, 20), (1, 21), (2, 19)),
((1, 20), (2, 18), (2, 18)),
((1, 20), (2, 18), (2, 19)),
((1, 20), (2, 19), (2, 19)),
((1, 21), (1, 21), (1, 21)),
((1, 21), (1, 21), (2, 18)),
((1, 21), (1, 21), (2, 19)),
((1, 21), (2, 18), (2, 18)),
((1, 21), (2, 18), (2, 19)),
((1, 21), (2, 19), (2, 19)),
((2, 18), (2, 18), (2, 18)),
((2, 18), (2, 18), (2, 19)),
((2, 18), (2, 19), (2, 19)),
((2, 19), (2, 19), (2, 19))]
You could also try this:
from itertools import product
from collections import Counter
list_of_tuples = [(1,20), (1,21), (2,18), (2,19)]
list_of_lists = [list_of_tuples] * 3
seen = set()
unique = []
for prod in product(*list_of_lists):
curr = frozenset(Counter(prod).items())
if curr not in seen:
seen.add(curr)
unique.append(prod)
print(unique)
Which Outputs:
[((1, 20), (1, 20), (1, 20)),
((1, 20), (1, 20), (1, 21)),
((1, 20), (1, 20), (2, 18)),
((1, 20), (1, 20), (2, 19)),
((1, 20), (1, 21), (1, 21)),
((1, 20), (1, 21), (2, 18)),
((1, 20), (1, 21), (2, 19)),
((1, 20), (2, 18), (2, 18)),
((1, 20), (2, 18), (2, 19)),
((1, 20), (2, 19), (2, 19)),
((1, 21), (1, 21), (1, 21)),
((1, 21), (1, 21), (2, 18)),
((1, 21), (1, 21), (2, 19)),
((1, 21), (2, 18), (2, 18)),
((1, 21), (2, 18), (2, 19)),
((1, 21), (2, 19), (2, 19)),
((2, 18), (2, 18), (2, 18)),
((2, 18), (2, 18), (2, 19)),
((2, 18), (2, 19), (2, 19)),
((2, 19), (2, 19), (2, 19))]
Are you looking something like this?
list_of_tuples = [(1,20), (1,21), (2,18), (2,19)]
import itertools
data=[]
for i in itertools.product(list_of_tuples,repeat=3):
data.append(i)
dict_1=[]
for i in data:
if sorted(i,key=lambda x:x[1]) not in dict_1:
dict_1.append(sorted(i,key=lambda x:x[1]))
print(dict_1)
output:
[[(1, 20), (1, 20), (1, 20)], [(1, 20), (1, 20), (1, 21)], [(2, 18), (1, 20), (1, 20)], [(2, 19), (1, 20), (1, 20)], [(1, 20), (1, 21), (1, 21)], [(2, 18), (1, 20), (1, 21)], [(2, 19), (1, 20), (1, 21)], [(2, 18), (2, 18), (1, 20)], [(2, 18), (2, 19), (1, 20)], [(2, 19), (2, 19), (1, 20)], [(1, 21), (1, 21), (1, 21)], [(2, 18), (1, 21), (1, 21)], [(2, 19), (1, 21), (1, 21)], [(2, 18), (2, 18), (1, 21)], [(2, 18), (2, 19), (1, 21)], [(2, 19), (2, 19), (1, 21)], [(2, 18), (2, 18), (2, 18)], [(2, 18), (2, 18), (2, 19)], [(2, 18), (2, 19), (2, 19)], [(2, 19), (2, 19), (2, 19)]]
I am trying to represent the following as a list comprehension:
L = []
for x in range(n):
for y in range(x):
L.append( (x, y) )
I have done nested list comprehension in the more typical matrix scenario where the inner loop range is not dependent on the outer loop.
I have considered there may be solutions in itertools, using product() or chain() but have been unsuccessful there as well.
Remember to wrap the x, y in parentheses this is the only slight caveat that if omitted leads to a SyntaxError.
Other than that, the translation is pretty straightforward; the order of the fors inside the comprehension is similar to that with the nested statements:
n = 5
[(x, y) for x in range(n) for y in range(x)]
Yields similar results to its nested loop counterpart:
[(1, 0),
(2, 0),
(2, 1),
(3, 0),
(3, 1),
(3, 2),
(4, 0),
(4, 1),
(4, 2),
(4, 3)]
List comprehensions are designed to make a straightforward translation of that loop possible:
[ (x,y) for x in range(3) for y in range(x) ]
Is that not what you wanted?
Below is the example to convert your code to list comprehension.
>>> n = 10
>>> [ (x,y) for x in range(n) for y in range(x)]
[(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2), (4, 3), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4), (6, 0), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (7, 0), (7, 1), (7, 2), (7, 3), (7, 4), (7, 5), (7, 6), (8, 0), (8, 1), (8, 2), (8, 3), (8, 4), (8, 5), (8, 6), (8, 7), (9, 0), (9, 1), (9, 2), (9, 3), (9, 4), (9, 5), (9, 6), (9, 7), (9, 8)]
Alternatively, you achieve the same result using itertools library (sharing it just for your knowledge info, but is not recommended for this problem statement):
>>> import itertools
>>> list(itertools.chain.from_iterable(([(list(itertools.product([x], range(x)))) for x in range(n)])))
[(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2), (4, 3), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4), (6, 0), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (7, 0), (7, 1), (7, 2), (7, 3), (7, 4), (7, 5), (7, 6), (8, 0), (8, 1), (8, 2), (8, 3), (8, 4), (8, 5), (8, 6), (8, 7), (9, 0), (9, 1), (9, 2), (9, 3), (9, 4), (9, 5), (9, 6), (9, 7), (9, 8)]
If I use:
[(x, y) for x in range(5) for y in range(0, x * 6)]
I get
[(1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (2, 9), (2, 10), (2, 11), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (3, 10), (3, 11), (3, 12), (3, 13), (3, 14), (3, 15), (3, 16), (3, 17), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (4, 7), (4, 8), (4, 9), (4, 10), (4, 11), (4, 12), (4, 13), (4, 14), (4, 15), (4, 16), (4, 17), (4, 18), (4, 19), (4, 20), (4, 21), (4, 22), (4, 23)]
Why is the first element (1, 0)?
Because when x is 0, y in range(0, x * 6) becomes y in range(0, 0), which is an empty range.
First, let's take a look at what the double for loop means:
[(x, y) for x in range(5) for y in range(0, x * 6)]
is the same as:
answer = []
for x in range(5):
for y in range(0, x*6):
answer.append((x,y))
[source]
So in the first iteration of x, x takes the value 0. Therefore, the inner expression becomes
for y in range(0, 0*6)
which is the same as
for i in range(0, 0)
Well, range(0,0) has no elements in it. Therefore, the inner loop never creates elements when x=0
I have a list of lists
a= [ [1,2,3],[4,5,6,7],[8,9,10] ]
I want to get all possible combinations of length 2 among the lists
ie
[ [1,4] ,[1,5], [1,6] , [1,7] , [1,8], [1,9] , [1,10] , [2,4], [2,5] etc etc ]
You can use itertools.combinations and itertools.product for this:
>>> from itertools import combinations, product, chain, starmap
>>> [p for c in combinations(a, 2) for p in product(*c)]
[(1, 4), (1, 5), (1, 6), (1, 7), (2, 4), (2, 5), (2, 6), (2, 7), (3, 4), (3, 5), (3, 6), (3, 7), (1, 8), (1, 9), (1, 10), (2, 8), (2, 9), (2, 10), (3, 8), (3, 9), (3, 10), (4, 8), (4, 9), (4, 10), (5, 8), (5, 9), (5, 10), (6, 8), (6, 9), (6, 10), (7, 8), (7, 9), (7, 10)]
#or list(chain(*starmap(product, combinations(a, 2))))