Python Poker hand single pair counter - python

I wrote the program below to iterate through every possible poker hand and count how many of these hands are a single pair
A hand is any 5 cards.
A single pair is when two cards of the same rank (number) and the other 3 cards of all different ranks e.g. (1,2,1,3,4)
I am representing the deck of cards as a list of numbers e.g.
- 1 = ACE
- 2 = Two
- 3 = Three
...
- 11 = Jack
- 12 = Queen...
The program seems to work find however,
the number of single pair hands it finds = 1101984
But according to multiple sources the correct answer is 1098240.
Can anyone see where the error in my code is?
from itertools import combinations
# Generating the deck
deck = []
for i in range(52):
deck.append(i%13 + 1)
def pairCount(hand):
paircount = 0
for i in hand:
count = 0
for x in hand:
if x == i:
count += 1
if count == 2:
paircount += .5 #Adding 0.5 because each pair is counted twice
return paircount
count = 0
for i in combinations(deck, 5): # loop through all combinations of 5
if pairCount(i) == 1:
count += 1
print(count)

The issue is that your hand can contain the following type of cards as well -
A Three of a kind and a single pair
You are actually calculating this as a single pair as well.
I modified the code to count just the number of hands such that it contains a three of a kind as well as a single pair together. Code -
deck = []
for i in range(52):
deck.append((i//13 + 1, i%13 + 1))
def pairCount(hand):
paircount = 0
threecount = 0
for i in hand:
count = 0
for x in hand:
if x[1] == i[1]:
count += 1
if count == 2:
paircount += .5 #Adding 0.5 because each pair is counted twice
if count == 3:
threecount += 0.33333333
return (round(paircount, 0) , round(threecount, 0))
count = 0
for i in combinations(deck, 5):
if pairCount(i) == (1.0, 1.0):
count += 1
This counted the number as - 3744.
Now, if we subtract this number from the number you got - 1101984 - We get the number you are expecting - 1098240 .

Related

Function in getting the less than equal in the list and removing the duplicates

I need to count how many less than or equal numbers in the list and disregarding the duplicates.
def getVal(prices = [5,5,10], money = 5):
count = 0
for i in prices:
if money >= i and money == i:
count += 1
return count
the output of this code is:
2
How can I get the output of 1.
Convert your list into a set, and all the duplicate will be removed automatically:
def getVal(prices = [5,5,10], money = 5):
count = 0
for i in set(prices): # Add set() around the list to convert
if money >= i:
count += 1
return count
print(getVal())
Output:
1
One liner?
def getVal(prices, money):
return sum(i <= money for i in set(prices))
print(getVal([5, 5, 10], 5))
Whenever you come across avoiding duplicates, the answer is always a set.

Count the number of elements within a set of ranges

I am facing trouble on writing a function that takes 2 arguments (values, dividers) as a list and returns the number of elements in each range (determined by numbers in dividers) as one list. Elements that are equal to one of the dividers should be counted in the bin below.
I used if and elif to sort the numbers, which is sort of giving me the right idea. However, I am struggling on how to apply the fact 'number of bins = number of dividers + 1'
def histogram(values, dividers):
count1 = 0
count2 = 0
count3 = 0
index = 0
for index in range(len(values)):
if values[index] <= min(dividers):
count1 = count1 + 1
elif min(dividers) < values[index] <= min(dividers):
count2 = count2 + 1
elif values[index] > max(dividers):
count3 = count3 + 1
index = index + 1
print("Number of elements in each bin is ", [count1, count2, count3])
When I run the argument ([1,...,10], [2,5,7]) for instance, the answer should be [2,3,2,3] because the number of elements in range below 2, 2~5 (not including 5), 5~7 (not including 7) and above 7 is 2,3,2,3 respectively. However at the moment, I am getting the output [2,5,3].
P.S. My aim is writing the function without using numpy.histogram or any matplotlib related stuff
It's not the most efficient implementation, but it does not assume that values is sorted (only that dividers is):
def histogram(values, dividers):
bins = [0]*(len(dividers)+1)
extended_dividers = [-float('inf')]+dividers+[float('inf')]
for idx, divider in enumerate(extended_dividers[:-1]):
bins[idx] = len([v for v in values if divider<v<=extended_dividers[idx+1]])
return bins
Also, shouldn't the output in your example be 1,2,3,4?

How to make a non list Loop that will select 4 random numbers from 1-10, and display them, but they cannot be the same?

import random
counter = 0
count = 0
counting = 0
valueOne = 0
valueTwo = 0
while counter ==0:
playerOne = random.randint(1,10)
number = random.randint(1,10)
About right here is where I get confused. It will run the loop, but every time it runs, the random values get reset, and even if the first time it prints a random number, the second time it might print the same and so forth.
if number == playerOne:
count = count + 1
if number != playerOne:
valueOne = playerOne
if number != valueOne:
print("lotto number",number)
counting = counting + 1
if counting >= 4:
print("it took you this many trys",count)
input('play again?')
counting = 0
count = 0
Should list the numbers in 1-10 (inclusive) then randomly sample them.
random.sample(range(1,11), 4)
random.sample docs
range docs

How to reuse code to track runs of pieces on a triangular board in Python

I'm doing a project in Python, and part of it involves ranking board states in a game. This game, Sneaky Statues, is similar to Connect Four, in which you win by getting four pieces in a row. My naive estimation of a board is how many pieces you have in a row (so either 1, 2, 3 or 4.) The board is a triangle, so you can have pieces in a row horizontally, or diagonally in either direction. This is the function I'm using right now to find runs of pieces.
def score(player):
player_x = sorted(player, key=lambda statue: statue.x) #player's pieces sorted by x coordinate
player_y = sorted(player, key=lambda statue: statue.y)
max_score = [0]
count = 1
#pieces are in a horizontal line if they share a y coord and have sequential x coords
for cur_s, next_s in zip(player_x, player_x[1:]):
if cur_s.x + 1 == next_s.x and cur_s.y == next_s.y:
count += 1
else:
max_score.append(count)
count = 1
max_score.append(count)
count = 1
#pieces are diagonal if they share an x and have sequential y's
for cur_s, next_s in zip(player_y, player_y[1:]):
if cur_s.y + 1 == next_s.y and cur_s.x == next_s.x:
count += 1
else:
max_score.append(count)
count = 1
max_score.append(count)
count = 1
#they are diagonal if both x's and y's are sequential
for cur_s, next_s in zip(player_y, player_y[1:]):
if cur_s.y + 1 == next_s.y and cur_s.x + 1 == next_s.x:
count += 1
else:
max_score.append(count)
count = 1
max_score.append(count)
return max(max_score)
As far as I can tell, it's working, but I'm essentially repeating myself three times. My question is, what is the most Pythonic way for me to write this function so that I repeat myself less?
This is likely not the best but at first sight I see that you can combine all the loops into a single function that has three arguments:
def score(player):
player_x = sorted(player, key=lambda statue: statue.x) #player's pieces sorted by x coordinate
player_y = sorted(player, key=lambda statue: statue.y)
max_score = [0]
def take_count(player, x_offset, y_offset):
count = 1
for cur_s, next_s in zip(player, player[1:]):
if cur_s.x + x_offset == next_s.x and cur_s.y + y_offset == next_s.y:
count += 1
else:
max_score.append(count)
count = 1
max_score.append(count)
#pieces are in a horizontal line if they share a y coord and have sequential x coords
take_count(player_x, 1, 0)
#pieces are diagonal if they share an x and have sequental y's
take_count(player_y, 0, 1)
#they are diagonal if both x's and y's are sequential
take_count(player_y, 1, 1)
return max(max_score)

From column of results to rows with same results

I'm really a beginner with python and in classe I'm analyzing a coin toss task. The number of tosses is 1000, the results possible are 1,2. I'm asked to create row with sequences of same results (such as 1 1 1 1 1 1 1 1 and then 2 2 2 2 2,..) and give the length of the longest appearing sequence.
from numpy.random import randint, seed
seed(0)
for n in range(1000):
r = randint(1,3)
print(r)
which gives me a single column reporting the results as follows
1
2
1
1
2
1
1
I can't manage to find the appropriate code to create those rows of sequences of same results.
You are printing the result of each iteration of your for loop.
A simple solution is to create 2 lists, each containing every occurrence of either 1 or 2:
list1 = []
list2 = []
In your for loop, you can use the list.append method to add the value of r to the corresponding list:
for n in range(1000):
r = randint(1, 3)
if r == 1:
list1.append(r)
else:
list2.append(r)
This way, list1 contains every occurrence of the number 1, and list2 contains all the number 2.
You can now print both list, and use len() to get the number of elements in each list.
Try this:
count1 = 0
count2 = 0
for n in range(1000):
r = randint(1, 3)
if r == 1:
count1 += 1
elif r == 2:
count2 += 1
if count1 > count2:
print('1'*count1)
print('2'*count2)
print('Longest sequence is of 1\'s, with %s occurences' %count1)
else:
print('1'*count1)
print('2'*count2)
print('Longest sequence is of 2\'s, with %s occurences' %count2)

Categories

Resources