Im trying to figure what is going wrong with my code. Im trying to get right result but it's come out always random answer. Let's says for example I shuffle [ V, V, V, A, V ] I want the result to be [4, 1] but it comes out as [2, 1, 2]. Can you help me ?
class Combinaison:
types_cartes = [
Carte.AS, Carte.ROI, Carte.DAME, Carte.VALET, Carte.DIX, Carte.NEUF
]
def __init__(self, des=None):
self.nb_lancers = 1
if des is None:
self.des = self._lancer_des(5)
else:
self.des = des
def determiner_type_combinaison_sans_as(self):
valeurs = [len(list(group)) for key, group in groupby(des)]
valeurs.sort(reverse=True)
sequence1 = [0, 1, 2, 3, 4]
sequence2 = [1, 2, 3, 4, 5]
if valeurs == sequence1 or valeurs == sequence2:
return " straight "
elif valeurs[0] == 5:
return " five of a kind "
elif valeurs[0] == 4:
return " four of a kind "
elif valeurs[0] == 3:
if valeurs[1] == 2:
return " Fullhouse "
else:
return " three of a kind"
elif valeurs[0] == 2:
if valeurs[1] == 2:
return " two pairs"
else:
return " one pair"
else:
return " nothing good, reshuffle"
class Carte(Enum):
"""Énumeration des types de cartes."""
AS = 0
ROI = 1
DAME = 2
VALET = 3
DIX = 4
NEUF = 5
def __str__(self):
if self == Carte.AS:
return "A"
if self == Carte.ROI:
return "R"
if self == Carte.DAME:
return "D"
if self == Carte.VALET:
return "V"
if self == Carte.DIX:
return "X"
if self == Carte.NEUF:
return "9"
You need to sort before you groupby. It splits an iterable by equality. It does not accumulate groups.
valeurs = [len(list(group)) for key, group in groupby(sorted(des))]
But it might be better to use the collections.Counter:
valeurs = Counter(des).values()
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 days ago.
This post was edited and submitted for review 2 days ago.
Improve this question
class Hand:
def __init__(self, hand):
self.hand = hand
def rank_to_index_converter(rank):
if rank == 2:
return 0
elif rank == 3:
return 1
elif rank == 4:
return 2
elif rank == 5:
return 3
elif rank == 6:
return 4
elif rank == 7:
return 5
elif rank == 8:
return 6
elif rank == 9:
return 7
elif rank == 10:
return 8
elif rank == 'J':
return 9
elif rank == 'Q':
return 10
elif rank == 'K':
return 11
elif rank == 'A':
return 1
else:
raise ValueError
def suit_to_index_converter(suit):
if suit == 'C':
return 0
elif suit == 'D':
return 1
elif suit == 'H':
return 2
elif suit == 'S':
return 3
else:
raise ValueError
def is_consecutive(hand):
### BEGIN YOUR SOLUTION
first = 0
string = ""
count = 0
for x in hand:
#print(x[0])
if x[0] == ("J"):
if first != 10 and (count != 0):
return False
string = x[0]
elif x[0] == ("Q"):
if string != "J" and (count != 0):
return False
string = x[0]
elif x[0] == ("K"):
if string != "Q" and (count != 0):
return False
string = x[0]
elif x[0] == ("A"):
if string != "K" and (count != 0):
return False
string = x[0]
elif x[0] != ("J" or "Q" or "K" or "A"):
if (x[0] != (first + 1)) and (count != 0):
if (hand[0][0] != "A"):
return False
first = x[0]
count = count + 1
return True
def is_suit(hand):
suit = hand[0][1]
for x in hand:
if x[1] != suit:
return False
return True
def is_flush(hand):
return is_suit(hand) and not is_consecutive(hand)
def is_four_of_a_kind(hand):
count = 0
pair_num = 0
lst = [0 for i in range(13)]
for x in hand:
index = rank_to_index_converter(x[0])
lst[index] += 1
for x in lst:
if x == 4:
return True
return False
def is_full_house(hand):
count = 0
pair_num = 0
lst = [0 for i in range(13)]
for x in hand:
index = rank_to_index_converter(x[0])
lst[index] += 1
three_pair = False
pair = False
for x in lst:
if x == 3:
three_pair = True
if x == 2:
pair = True
if three_pair and pair:
return True
return False
def is_flush(hand):
count = 0
while count < (len(hand) - 2):
if hand[count][1] != hand[count + 1][1]:
return False
count += 1
return True
def is_straight(hand):
if is_consecutive(hand) and not is_suit(hand):
return True
return False
def is_three_of_a_kind(hand):
lst = [0 for i in range(13)]
for x in hand:
index = rank_to_index_converter(x[0])
lst[index] += 1
three_pair = False
for x in lst:
if x == 3:
three_pair = True
if three_pair and not is_full_house(hand) and not is_suit(hand):
return True
return False
def is_two_pair(hand):
lst = [0 for i in range(13)]
for x in hand:
index = rank_to_index_converter(x[0])
lst[index] += 1
two_pair = False
counter = 0
switch = 0
while counter != len(lst):
if lst[counter] == 2:
switch = 1
if lst[counter] == 2 & switch == 1:
two_pair = True
if two_pair and not is_full_house(hand) and not is_suit(hand) and not is_four_of_a_kind(hand) and not is_three_of_a_kind(hand):
return True
return False
def is_pair(hand):
lst = [0 for i in range(13)]
for x in hand:
index = rank_to_index_converter(x[0])
lst[index] += 1
pair = False
for x in lst:
if x == 2:
pair = True
if pair and not is_full_house(hand) and not is_suit(hand):
return True
return False
def maximum_value(hand):
sum = 0
for x in hand:
sum += rank_to_index_converter(x[0])
return sum
The is_full_house function uses the rank_to_index_converter function. The rank_to_index_converter function is defined above the is_full_house function. Why am I receiving an error that the rank_to_index_converter function is not defined?
I am lost on where to proceed; therefore, I haven't tried anything, besides copying and pasting the rank_to_index_converter function into the is_full_house function; however, it is more convenient if the rank_to_index_converter is a separate function. That is why I want to solve this issue.
I want to count the number of times both a and b occur, in both strings together, using recursion in Python.
For example, if the input was ('aabb', 'bbba'), the output would be (3,5) because there are three a's and five b's total.
What I have tried:
def counting(string1, string2):
if not string1:
return 0
elif string1[0]=='a':
return 1+counting(string[1:],string2)
else:
return counting(string[1:],string2)
def counting(string1, string2):
def counting_recurse(string_total):
if not string_total:
return (0, 0)
elif string_total[0]=='a':
a_count, b_count = counting_recurse(string_total[1:])
return (1+a_count, b_count)
elif string_total[0]== 'b':
a_count, b_count = counting_recurse(string_total[1:])
return (a_count, b_count +1 )
else:
return counting_recurse(string_total[1:])
return counting_recurse(string1 + string2)
This works on your example. Does this solve your scenario?
You can recurse until both strings are empty.
def counting(string1, string2):
if string1 or string2:
a, b = counting(string1 and string1[1:], string2 and string2[1:])
count = lambda x: (string1 and string1[0] == x or 0) + (string2 and string2[0] == x or 0)
return (a + count('a'), b + count('b'))
return (0, 0)
print(counting('aabb', 'bbba'))
This seems like a simpler solution
Explanation
If you've reached end of string, then return (0,0) for a count and b count
Otherwise, you add 1 + a_count if first character is a otherwise you add 0 + a_count.
Similarly, you add 1 + b_count if first character is b otherwise you add 0 + b_count.
a_count is defined as the first value in tuple(), b_count is the second value()
def counting_recurse(combine_string):
if not combine_string:
return (0, 0)
return (int(combine_string[0]=='a') +counting_recurse(combine_string[1:])[0],
int(combine_string[0]=='b') +counting_recurse(combine_string[1:])[1])
string1 = 'aabb'
string2 = 'bbba'
counting_recurse(string1+string2)
Output
(3, 5)
def counting(stri, char):
if len(stri) == 0:
return 0
elif stri[0] == char:
return 1 + counting(stri[1:], char)
else:
return counting(stri[1:], char)
def count(str1, str2):
return (counting(str1,'a'),counting(str2,'b'))
print("aabb","bbba")
Looks like having two strings as arguments to the function is unnecessarily complicated, since you count across both strings anyway. So why not simply define the recursive function for a single string and call it on the concatenation of the two strings you're interested in, e.g.
def count_ab(s):
if not s:
return 0, 0
first_a = int(s[0] == 'a')
first_b = int(s[0] == 'b')
further_a, further_b = count_ab(s[1:])
return first_a + further_a, first_b + further_b
count_ab('aabb' + 'bbba')
(3, 5)
The following works:
def non_recursive_imp2(*args: str) -> tuple:
sargs = tuple(map(str, args))
a_count = 0
b_count = 0
for sarg in sargs:
for ch in sarg:
if ch == "a":
a_count += 1
elif ch == "b":
b_count += 1
return (a_count, b_count)
import operator
def recursive_count(inpuht:str, _:str):
inpuht += _
if len(inpuht) < 2:
if inpuht == "a":
return (1, 0)
elif inpuht == "b":
return (0, 1)
return (0, 0)
else:
left_str = inpuht[:len(inpuht)//2]
right_str = inpuht[len(inpuht)//2:]
left_count = recursive_count(left_str, "")
right_count = recursive_count(right_str, "")
return tuple(map(operator.add, left_count, right_count))
However, it is easier to write code for a non-recursive implementation:
NON-RECURSIVE IMPLEMENTATIONS:
def non_recursive_imp(x:str, y:str) -> tuple:
merged = x + y
a_count = 0
b_count = 0
for ch in merged:
if ch == "a":
a_count +=1
elif ch == "b":
b_count +=1
return (a_count, b_count)
I am making a connect four game with X's and O's. The code for checking for four in a row/column/diagonal works but I have a lot of if statements in my code. The game fully works right now but I'm wondering if there is an easier solution to the checking. Below, I have included all my code for context.
I have tried using coordinates. It seems kind of inefficient though. The function for checking is called check.
namex = input("Player X, enter your name. ") #asks for player 1 name
nameo = input("Player O, enter your name. ") #asks for player 2 name
game = [[".", ".", ".", ".", ".", "."], #gameboard
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."],
[".", ".", ".", ".", ".", "."]]
loop = True
def output(matrix):
str1 = ""
str2 = ""
str3 = ""
str4 = ""
str5 = ""
str6 = ""
print("0 1 2 3 4 5 6 ") #print labels for columns in gameboard
for a in matrix:
row = 0
for b in a: #"a" is a column and "b" is a ./x/o
row += 1
if row == 1:
str1 += b
str1 += " "
if row == 2:
str2 += b
str2 += " "
if row == 3:
str3 += b
str3 += " "
if row == 4:
str4 += b
str4 += " "
if row == 5:
str5 += b
str5 += " "
if row == 6:
str6 += b
str6 += " "
print(str1) #print string for row 1
print(str2) #print string for row 2
print(str3) #print string for row 3
print(str4) #print string for row 4
print(str5) #print string for row 5
print(str6) #print string for row 6
def check(matrix): #function to check for four in row/column/diagonal to win
positionx = []
positiono = []
x = 0
for a in matrix:
y = 5
for b in a:
if b == "X":
positionx.append([x, y])
if b == "O":
positiono.append([x, y])
y -= 1
x += 1
for c1 in positionx:
'''check four in row/column/diagonal for x'''
for c2 in positionx:
for c3 in positionx:
for c4 in positionx:
if c4[0]-c3[0] == 1:#check for four in row
if c3[0]-c2[0] == 1:
if c2[0]-c1[0] == 1:
return "xwin"
if c4[1]-c3[1] == 1: #check for four in column
if c3[1]-c2[1] == 1:
if c2[1]-c1[1] == 1:
return "xwin"
if c4[0]-c3[0] == 1: #check four in diagonal
if c4[1]-c3[1] == 1:
if c3[0]-c2[0] == 1:
if c3[1]-c2[1] == 1:
if c2[0]-c1[0] == 1:
if c2[1]-c1[1] == 1:
return "xwin"
for d1 in positiono:
'''check four in row/column/diagonal for o'''
for d2 in positiono:
for d3 in positiono:
for d4 in positiono:
if d4[0]-d3[0] == 1: #check for four in row
if d3[0]-d2[0] == 1:
if d2[0]-d1[0] == 1:
return "owin"
if d4[1]-d3[1] == 1: #check for four in column
if d3[1]-d2[1] == 1:
if d2[1]-d1[1] == 1:
return "owin"
if d4[0]-d3[0] == 1: #check four in diagonal
if d4[1]-d3[1] == 1:
if d3[0]-d2[0] == 1:
if d3[1]-d2[1] == 1:
if d2[0]-d1[0] == 1:
if d2[1]-d1[1] == 1:
return "owin"
while loop == True:
xinput = input(namex + ", you're X. What column do you want to play in? Please enter a number 0-6 ")
xcolumn = int(xinput)
xrow = 5
occupied1 = False
while occupied1 == False:
if game[xcolumn][xrow] == ".": #if there is a "." change to "X"
game[xcolumn][xrow] = "X"
output(game)
occupied1 = True
xrow -= 1
if check(game) == "xwin":
loop = False
print(namex + " wins!")
break
if check(game) == "owin":
loop = False
print(nameo + " wins!")
break
oinput = input(nameo + ", you're O. What column do you want to play in? Please enter number 0-6 ")
ocolumn = int(oinput)
orow = 5
occupied2 = False
while occupied2 == False:
if game[ocolumn][orow] == ".": #if there is a "." change to "O"
game[ocolumn][orow] = "O"
output(game)
occupied2 = True
orow -= 1
if check(game) == "xwin":
loop = False
print(namex + " wins!")
break
if check(game) == "owin":
loop = False
print(nameo + " wins!")
break
I'm also open to any other suggestions to make my code for this game better. Thanks!
I had some spare time, so I rewrote your program. It's much more efficient now. Read the comments to understand how it works
cols = [[] for x in range(6)]
# I opted to have a matrix of COLUMNS rather than rows because you can easily
# append items to the end of the list to simulate a real tile being placed there
# it's more intuitive and saves us time, as you'll see
def checkWin(cols):
for i in range(6): # Each column
for j in range(6): # Each row
try: #check if the element at these coordinates exists yet
cols[i][j]
except IndexError:
break
# go back to next i - impossible that there's anything with a higher
# j because if a list is n items long, and we go to j (which is one
# higher than n and doesn't exist) then there can't be an element at
# index j + someNumber.
ret = False
try: #vertical: j is the index in each column, so this goes up the column
if cols[i][j] == cols[i][j+1] == cols[i][j+2] == cols[i][j+3] is not None:
ret = True
except IndexError: #one of the elements of the comparison doesn't exist
pass #We can't be sure that none of the other trials will return True
try: #horizontal
if cols[i][j] == cols[i+1][j] == cols[i+2][j] == cols[i+3][j] is not None:
ret = True
except IndexError:
pass
try: #diagonal
if cols[i][j] == cols[i+1][j+1] == cols[i+2][j+2] == cols[i+3][j+3] is not None:
ret = True
except IndexError:
pass
try: #other diagonal
if cols[i][j] == cols[i-1][j+1] == cols[i-2][j+2] == cols[i-3][j+3] is not None:
ret = True
except IndexError:
pass
if ret:
return cols[i][j]
return None # We've gone through every single possible element and there are NO matches
def printBoard(cols):
# Pretty intuitive function IMO - we swap i and j to go through rows.
returnstr = '\n1 2 3 4 5 6\n'
for i in range(6):
for j in range(6):
try:
cols[j][5-i]
except IndexError:
returnstr += '_ '
continue
returnstr += cols[j][5-i]+' '
returnstr += '\n'
print(returnstr)
playerX = input('Player X, input your name: ')
playerO = input('Player O, input your name: ')
if playerX == playerO:
print("Cannot have the same name!")
exit()
count = 0
while not checkWin(cols):
printBoard(cols)
i = input('{}, input your column (1-6): '.format(playerO if count else playerX))
try:
target = cols[int(i)-1]
if len(target) == 6:
print("Column {} is already full! Please pick another.".format(i))
continue
target.append('O' if count else 'X')
except ValueError:
print("'{}' is not a number! Try again.".format(i))
continue
except IndexError:
print("{} is not a valid column number! Please pick another.".format(i))
continue
count = (count+1) % 2
printBoard(cols)
if checkWin(cols) == 'X':
print('{} (Player X), you win!'.format(playerX))
else:
print('{} (Player O), you win!'.format(playerO))
A good start would be to write a generalized function that checks for a diagonal at an arbitrary location:
def diagonal(grid, x, y, piece):
'''
Return True if grid contains a four-in-a-row diagonal starting at coordinates
(x, y) and traveling downwards and to the right. Otherwise return False.
'''
for i in range(x, x+4):
# if this square does not contain the desired piece, return False
if grid[x+i][y+i] != piece
return False
# if we got all the way through the loop, this must be a diagonal
return True
Then you would call this function for every possible starting coordinate of a four square diagonal, for each player X and O.
To improve this function, you could add a way to check for diagonals that travel the other direction (up and to the right).
CODE SNIPPET 1: generates all possible set of brackets
class Parenthesis(object):
def __init__(self, parens):
self.parens = parens
self.my_valid_parens = {
1: ['()'],
2: ['()','()'],
}
def generate_valid_paren(self):
if self.parens <= 2:
return self.my_valid_parens[self.parens]
i = 3
while i <= self.parens:
new_set = []
for each in self.my_valid_parens[i-1]:
new_set += set([each + '()', '()' + each, '(' + each + ')'])
self.my_valid_parens[i] = list(new_set)
i += 1
if __name__ == '__main__':
num = 4
p = Parenthesis(num)
p.generate_valid_paren()
print("linesep")
print (p.my_valid_parens[num])
The problem with code 1 is that the output is generated twice after 5th output.
How can this be corrected ?
CODE SNIPPET 2: generates all possible combination of values by changing the logical '&' and '|' operator
def insert():
operands = [ 0, 0, 0, 1]
type(operands)
operators = ['|', '&']
type(operators)
for opers in product(operators, repeat=len(operands) - 1):
formula = [str(operands[0])]
for op, operand in zip(opers, operands[1:]):
formula.extend([op, str(operand)])
formula = ' '.join(formula)
print('{} = {}'.format(formula, eval(formula)))
print(" ")
Can anyone suggest me a way to join these codes so that the output could be something like this ( ( 0 | 0 ) | ( 0 & 1 ) ) = 0 i.e. the expression variables have all possible generated brackets i.e. obtained above ?
for the first part of question, Duplicate values in the valid_paren dict causing pattern to get repeated after 5 occurrence.
below will not return the duplicate pattern.
class Parenthesis(object):
def __init__(self, parens):
self.parens = parens
self.my_valid_parens = {
1: ['()'],
2: ['()'],
}
def generate_valid_paren(self):
if self.parens <= 2:
return self.my_valid_parens[self.parens]
i = 3
while i <= self.parens:
new_set = []
for each in self.my_valid_parens[i-1]:
new_set += set([each + '()', '()' + each, '(' + each + ')'])
self.my_valid_parens[i] = list(new_set)
i += 1
print(self.my_valid_parens)
if __name__ == '__main__':
num = 4
p = Parenthesis(num)
p.generate_valid_paren()
print("linesep")
print (p.my_valid_parens[num])
For second part I am still not able to understand what you are trying to achieve, can you give example from out received from above code.
In the following code, I return the integer value for the amount of consecutive numbers in a given string.
def consecutive_length(S):
if S == '':
return 0
if len(S) == 1:
return 1
if S[0] == S[1]:
return 1 + consecutive_length(S[1:])
return 1
def compress(S):
if S == '':
return 0
cons_length = consecutive_length(S)
return [cons_length] + [compress(S[cons_length:])]
When I run this print statement, the following is returned:
>>> print (compress('1111000000001111000111111111111111'))
[4, [8, [4, [3, [15, 0]]]]]
Where I really want the following to be returned:
>>> print (compress('1111000000001111000111111111111111'))
[4, 8, 4, 3, 15]
An alternative to your method is to use itertools.groupby():
from itertools import groupby
s = '1111000000001111000111111111111111'
answer = [len([digit for digit in group[1]]) for group in groupby(s)]
print(answer)
Output
[4, 8, 4, 3, 15]
Here you go:
def consecutive_length(S):
if S == '':
return 0
if len(S) == 1:
return 1
if S[0] == S[1]:
return 1 + consecutive_length(S[1:])
return 1
def compress(S):
if S == '':
return []
cons_length = consecutive_length(S)
return [cons_length] + compress(S[cons_length:])
When you return a list, [what_is_returned] will be a nested list, but when you return an integer, it will be just a list. Instead, (in compress()) ,always return a list, and remove the brackets when you use what it returns:
def consecutive_length(S):
if S == '':
return 0
if len(S) == 1:
return 1
if S[0] == S[1]:
return 1 + consecutive_length(S[1:])
return 1
def compress(S):
if S == '':
return []
cons_length = consecutive_length(S)
return [cons_length] + compress(S[cons_length:])