I need a program that picks four cards from a deck and computes their sum.
Note that ace = 1, jack = 11, queen = 12, and king = 13. Upon computing their sum, check if that sum is equal to 24. If it is, record that. In the end, the program should display the number of combinations that sum to 24.
Here is what I have:
def selfour():
total = 0
cards = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
for a in range(52):
for b in range(1, 52):
for c in range(2, 52):
for d in range(3, 52):
print(cards[a], cards[b], cards[c], cards[d])
if (cards[a] + cards[b] + cards[c] + cards[d]) == 24:
total += 1
return total
def main():
print(selfour())
main()
I'm not too sure if this program yield the correct answer, but it is inefficient. If anybody can provide help to make this code more efficient, that would be great. I'm fairly certain that this does not yield a correct answer, so help with that would be great, too.
Thanks
Itertools is your friend. You can do this in a one liner:
import itertools
cards = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
def selfour():
return sum(sum(i) == 24 for i in itertools.combinations(cards, 4))
You are thinking about the cards not being equal to each other, but you're not quite getting it.
for a in range(52):
for b in range(1, 52):
needs to be something like:
for a in range(52):
for b in range(52):
if b == a:
continue
There is a module called itertools that has combinations that does what you want. With it your nested for loops can become:
from itertools import combinations
for a in combinations(cards, 4):
if sum(a) == 24:
total += 1
I'm not 100% sure if this is correct, but I was able to do:
from itertools import combinations
def sel(it, cnt=4, val=24):
return sum(sum(_) == val for _ in combinations(it, cnt))
cards = # ...
print(sel(cards, 4, 24)) # => 12517
Edit: Sorry, I'm sure new answers have been posted. I was writing this as soon as it came up but got distracted before I posted it.
This is what I ended up using for the code:
import itertools
cards = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
def selfour():
total = 0
for z in itertools.combinations(cards, 4):
if sum(z) == 24:
total += 1
return total
def main():
print(selfour())
main()
Thanks to help from users, this code is much more efficient and clean.
Also, other beginners can easily follow this if need -
-Thanks
Related
I am trying to build list similar to this
Position = [1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8,
9, 9, 9, 9, 9, 9, 9,
10, 10, 10, 10, 10, 10, 10,
11, 11, 11, 11, 11, 11, 11,
12, 12, 12, 12, 12, 12, 12,
13, 13, 13, 13, 13, 13, 13,
14, 14, 14, 14, 14, 14, 14,
15, 15, 15, 15, 15, 15, 15]
With the list comprehension like below (with one if statement), only the first 7 elements can be created. How can I add multiple if statements?
d = 1
position = [d if i<7 else d+1 for i in range (105)]
No need for even a single if; just use integer division
[1+i//7 for i in range (7*15)]
Use numpy for creating a list of some value with some repetition, append them together
import numpy as np
numbers_i_want = np.arange(1, 16, 1, dtype=int) #last number not included
arr = np.array([])
for n in numbers_i_want:
temp = np.full(
shape=10, # how many ints
fill_value=n #what int
)
arr= np.concatenate((arr,temp))
print(arr)
The simplest solution in the standard library is to chain multiple iterables together.
from itertools import chain, repeat
Position = list(chain.from_iterable(repeat(i, 7) for i in range(1, 16)))
or use two generators
Position = list(x for i in range(1, 16) for x in repeat(i, 7))
Or, since int values are immutable, list multiplication is a viable solution.
Position = list(chain.from_iterable([i]*7 for i in range(1, 16)))
Position = list(x for i in range(1, 16) for x in [i]*7)
This question already has answers here:
Why does "a == x or y or z" always evaluate to True? How can I compare "a" to all of those?
(8 answers)
Closed 2 years ago.
Hello I am trying to add numbers to a new list in a for loop if condintions match. However I do not get the result I was hopping for. For me it seems like the for loop stops after the first encounter of a match ever though i is probably analized.
print(months_list)
for i in months_list:
n_days_list = []
if i == 1 or 3 or 5 or 7 or 8 or 10 or 12:
n_days_list.append(31)
elif i == 2:
n_days_list.append(28)
else:
n_days_list.append(30)
print(n_days_list)
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
[31]
Thanks for the help.
The reason why the length of ur code's output is 1 is because you are initializing the n_days_list to [] at each iteration which means u are removing the effect of the previous iteration.
However, if u remove "n_days_list = []", you will end up with a list of length of n_days_list containing only 31 that's bcz the first condition is always true because if i == 1 or 3 or 5 or.... is equivalent to if i == 1 or True or True or.... since the numbers 3, 5.... are different than 0 hence they are True. So just change to if i == 1 or i == 3 or i == 5 or.... and remove that n_days_list = []
and u will be set to go.
for some homework, my teacher decided to give us a coding challenge that she couldn't work out herself. The challenge was that given a list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] rotate every second value right along the list while keeping every 3rd value stationary.
Below is the code I have tried to use but it only keeps the value at position 0 stationary, whereas I need to keep the values at positions [0, 2, 4, 6, 8, 10]
rotation = list(teams) # copy the list
random.shuffle(rotation)
fixtures = []
for i in range(0, len(teams)-1):
fixtures.append(rotation)
rotation = [rotation[0]] + [rotation[-1]] + rotation[1:-1]
The expected result should be that he first iteration of the list should return [1, 12, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10] and the second iteration should return [1, 10, 3, 12, 5, 2, 7, 4, 9, 6, 11, 8]
From your expected output, you need to keep every 2nd element of the list, which can be extracted by [::2]:
rotate = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
rotate[::2]
#[1, 3, 5, 7, 9, 11]
The other elements which require shuffling can be extracted by [1::2]:
rotate[1::2]
#[2, 4, 6, 8, 10, 12]
Now you just need to move the last element of the 2nd list to the top. There are many ways to do it, but I got lazy and use the below:
result = [rotate[1::2].pop(-1)] + rotate[1::2][:-1]
Then you can join the amended lists together:
r = [(a,b) for a,b in zip(rotate[::2],result)]
r = [x for i in r for x in i]
r
#[1, 12, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10]
def rotate(x):
y = x[:]
for i, v in enumerate(x[:-1]):
if str(i/2)[-1] == '0':
x[i+1] = y[i-1]
return x
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
print(rotate(x)) #[1, 12, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10]
print(rotate(x)) #[1, 10, 3, 12, 5, 2, 7, 4, 9, 6, 11, 8]
If divided into subtask, then
import itertools
def func(array):
const_part = array[::2] # get constant part
ch_part = array[1::2] # get changing part
ch_part = ch_part[-1:] + ch_part[:-1] # items shift in changing part
return list(itertools.chain.from_iterable(zip(const_part,ch_part))) # construct list back
I am trying to implement differential cryptanalysis on an sbox for a DES algorithm, and I'm receiving this error.
This is my code so far:
s1=[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]
b=[]
for i in range(0, 63):
j=ZZ(i).binary().zfill(6)
b += [s1[ZZ('0b'+j[0]+j[5])][ZZ('0b'+j[1]+j[2]+j[3]+j[4])]]
s1=mq.SBox(b)
ddt=s1.difference_distribution_matrix()
for i in range(63):
print i,ddt[i]
The error is on
b += [s1[ZZ('0b'+j[0]+j[5])][ZZ('0b'+j[1]+j[2]+j[3]+j[4])]]
s1 is a list of a single dimension.
s1[ZZ('0b'+j[0]+j[5])][ZZ('0b'+j[1]+j[2]+j[3]+j[4])] is trying to index into the return of an index.
s1[ZZ('0b'+j[0]+j[5])] pulls back the integer value in s1 is position [ZZ('0b'+j[0]+j[5])].
Then you are trying to index into the integer at position [ZZ('0b'+j[1]+j[2]+j[3]+j[4])].
That is my best guess without knowing what is happening in ZZ().
I have a list that I want to add multiple values to, and I use append(), as below, to add 10 more digits:
>>> x = [1, 2, 3, 4]
>>> x.append(5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: append() takes exactly one argument (10 given)
I kind of get what this means, so then I tried doing it with a list:
>>> x = [1, 2, 3, 4]
>>> x.append([5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
>>> x
[1, 2, 3, 4, [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]]
This isn't what I want though. It contains unnecessary square brackets. What I do want is this:
>>> x = [1, 2, 3, 4]
>>> x.what_I_want([5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
Is the first change that I made to take away the TypeError the correct change to make? Or is that why this isn't working?
It's called extend:
>>> x = [1, 2, 3, 4]
>>> x.extend([5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
http://docs.python.org/2/tutorial/datastructures.html#more-on-lists
http://docs.python.org/2/library/stdtypes.html#mutable-sequence-types
For completeness, your other options are creating a new list as a concatenation of the two lists:
>>> x = [1, 2, 3, 4]
>>> x + [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> x += [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
And assigning into the empty slice at the end:
>>> x = [1, 2, 3, 4]
>>> x[len(x):len(x)] = [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
Use extend though.
Use extend():
>>> x = [1, 2, 3, 4]
>>> x.extend([5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
Instead of typing out the numbers from 5 through 15, use a range():
>>> x = [1, 2, 3, 4]
>>> x.extend(range(5, 15))
>>> x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
The first edit that you made was correct, since you can only append one item at a time, not a tuple like (5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
The list append() method takes a single argument, which is added to the list. Thus, when you pass it a list, that list becomes the new last element of the list to which it is appended. By maintaining such consistency Python allows us to conveniently create and process lists of lists and more complicated data structures. But it does mean append() is not the answer you are looking for.
The simplest answer to your problem I can think of is
x += range(15)
This will work fine in Python 2, but in Python 3 range() is a generator, so you have to use
x += list(range(15))
Lists can be added together as can tuples, and it works just like string concatenation.
There are several ways to do this in Python.
The most common and idiomatic approach is using the extend method, to extend the list in place.
x = [1, 2, 3, 4]
y = [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
x.extend(y)
print(x)
The addition operator can also be used to do this, though it creates a new list.
x = [1, 2, 3, 4]
y = [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
z = x + y # This creates a new list `z`
print(z)
Augmented assignment can also be used, to extend the list in place.
x = x_ = [1, 2, 3, 4]
y = [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
x += y # This doesn't create a new list
assert x is x_
print(x)
A particularly esoteric approach would involve using the slice assignment. You'd only want to do this if you're looking to confuse people.
x = [1, 2, 3, 4]
y = [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
x[len(x):] = y
print(x)