-2

Here's a doubt I am facing here.

The code with its purpose in docstring is below :

This is the correct code but I am confused about the final 'if statement' in the blackjack_hand_greater_than(a,b) function.

Here, the 'if statement' is not True for total_1 > total_2 even if it is(* checked through print statements). I am not getting what is the need of adding 'or total_2 > 21' .

def blackjack_hand_greater_than(hand_1, hand_2):
    """
    Return True if hand_1 beats hand_2, and False otherwise.
    
    In order for hand_1 to beat hand_2 the following must be true:
    - The total of hand_1 must not exceed 21
    - The total of hand_1 must exceed the total of hand_2 OR hand_2's total must exceed 21
    
    Hands are represented as a list of cards. Each card is represented by a string.
    
    When adding up a hand's total, cards with numbers count for that many points. Face
    cards ('J', 'Q', and 'K') are worth 10 points. 'A' can count for 1 or 11.
    
    When determining a hand's total, you should try to count aces in the way that 
    maximizes the hand's total without going over 21. e.g. the total of ['A', 'A', '9'] is 21,
    the total of ['A', 'A', '9', '3'] is 14.
    
    Examples:
    >>> blackjack_hand_greater_than(['K'], ['3', '4'])
    True
    >>> blackjack_hand_greater_than(['K'], ['10'])
    False
    >>> blackjack_hand_greater_than(['K', 'K', '2'], ['3'])
    False
    """
    print("hand1 = ",hand_1)
    print("hand2 = ",hand_2)
    total_1 = get_total(hand_1)
    total_2 = get_total(hand_2)
    print(total_1 <= 21)
    print(total_1 > total_2)
    if (total_1 <= 21) and (total_1>total_2 or total_2 > 21):
        return True
    else :
        return False

def get_total(hands) :
    values = {'A': 1 ,'2': 2, '3' : 3, '4' : 4 ,'5' : 5, '6' : 6,'7': 7, '8' : 8, '9' : 9, '10' : 10 , 'J' :10 , 'Q':10, 'K':10}
    total = 0
    aces = 0
    
    for x in hands:
        if x == 'A' :
            aces += 1
        total += values[x]
#         print(total)
        
    while aces>0 and total + 10 <= 21 :
        total += 10
        aces -=1
    
    print(total)
    return total
# Check your answer
q3.check()

The error after removing the 2nd operand of 'or', the error received is as follows :

hand1 = ['J', 'A'] hand2 = ['6'] 21 6 True True

hand1 = ['9'] hand2 = ['9', 'Q', '8', 'A'] 9 28 True False

Incorrect: Expected return value of True given hand_1=['9'], hand_2=['9', 'Q', '8', 'A'], but got False instead.

novice
  • 3
  • 2
  • I am not a poker player, but I would first understand my problem in terms of poker rules to find these conditions rather than force them by hand. Such force scenarios encounter oftentimes impossible mathematical situation, which are unexpected. – Bruno Peixoto Feb 05 '23 at 20:43

4 Answers4

0

To win a blackjack hand, you need to be closer to 21 than the dealer but not above 21. If you're above 21 ("bust"), you lose, no matter which hand the dealer has. If you're at 21 or below, you win if the dealer busts, or if the dealer does not bust but has fewer points than you do. If we denote the score of your hand as total_1 and the total of the dealer's hand as total_2, then this is logically equivalent to if (total_1 <= 21) and (total_1>total_2 or total_2 > 21): If you bust, the first condition will be False, and since we're in a conjunction, the overall expression will evaluate to False. If you're at 21 or below, you still haven't won for sure - you need to either have more than the dealer, or the delaer must bust. That's the disjunction that forms the second term in the conjunction: total_1>total_2 or total_2 > 21.

In other words, the issue is not one of coding or of logic, but of blackjack rules.

Schnitte
  • 1,193
  • 4
  • 16
0

The 'if statement':

if (total_1 <= 21) and (total_1>total_2 or total_2 > 21):
    return True
else:
    return False

It is saying that if (total_1 is less than or equal to) and (total_1 is greater than total_2) or (total_2 greater than 21)

for example in the the combinations of it would look like this:

if (True) and (True or False):# this would return True because `True and (True or False) make True` 
    return True
else:
    return False
Flow
  • 846
  • 9
  • 24
  • You changed the parenthesis in your written description, which changes the meaning. – Mark Feb 05 '23 at 20:48
  • @Mark Interesting here is that where the parentheses are, actually doesn't matter. Just check all the possible cases to see it for yourself ... and come back here to prove me wrong if I have overseen something. – Claudio Feb 05 '23 at 23:02
  • @Claudio compare `(False) and (False) or (True)` -> True with `(False) and (False or True)` -> False – Mark Feb 05 '23 at 23:08
  • Thanks for pointing it out ... somehow I have overseen the case. Will delete my comment. OK? (tested only with the first term of `and` set True ...) – Claudio Feb 05 '23 at 23:15
  • Another one is `False and (True or True)` which without or other set parentheses gives True not False. In two of eight cases it makes a difference. – Claudio Feb 05 '23 at 23:34
  • Hello @Flow, I agree with the logic you have provided but I am confused with the logic here! I had initially used - if (total_1 <= 21) and (total_1>total_2). But it results True in the case of total_1 = 9 and total_2 = 28. My question is why is the 'and' operator not taking the second operand in hand in my statement? – novice Feb 07 '23 at 11:47
  • @novice there is a big chance that the first statement is false so it is not going to the next statement or the other statement is false. They both have to be true in the if statement. – Flow Feb 09 '23 at 02:02
0

I think I may have got what you are actually wondering about:

If you let the ( ) stay as they are if (total_1 <= 21) and (total_1>total_2 or total_2 > 21):, it is strictly logical that the or condition will return True if only ONE of the operands is True ( total_2 > 21 ) and because total_1 <= 21 is also True the entire expression evaluates to True. No doubt that this is correct.

BUT ... let's remove the parentheses ( ) in the condition and see what happens. Logically the first operand for and is True, but the second is False, so ... the condition should evaluate to False, right? But running the code:

total_1 =  9; total_2 = 28
if total_1 <= 21 and total_1>total_2 or total_2 > 21:
    print(True)
else :
    print(False)

prints True ...

How does it come?

Python evaluates the expressions from left to the right. So first the and condition will be evaluated and gives False, BUT ... the expression has also an or, so the False from the and condition is now the operand of the or condition which second term is True, so, that the entire expression evaluates then to True.

Is THIS what you are wondering about considering chained and and or?

Check again from scratch: Expected return value of True given hand_1=['9'], hand_2=['9', 'Q', '8', 'A'], but got False instead. Then you will see that it actually can't be as you have it in mind.

Another problem with understanding can be wrong assumptions about the rules of the game as pointed out by Schnitte:

the issue is not one of coding or of logic, but of blackjack rules.

Claudio
  • 7,474
  • 3
  • 18
  • 48
  • Hello @Claudio, I am confused with the logic here! I had initially used - if (total_1 <= 21) and (total_1>total_2). But it results True in the case of total_1 = 9 and total_2 = 28. My question is why is the 'and' operator not taking the second operand in hand? – novice Feb 07 '23 at 11:43
  • Hello @novice . What you state must be the result of some kind of mistake. The if-condition gives `False`. Check again running `total_1=9; total_2=28; print( (total_1 <= 21) and (total_1>total_2) )` which gives False. And write the if-condition again yourself to see that it gives `False` and not `True` as you seem to believe it did. Probably you actually used `or` but somehow believed it is an `and`. – Claudio Feb 07 '23 at 20:17
  • yes you are right! When I tried to incorporate the given condition, it throws the error - " Incorrect: Expected return value of True given hand_1=['9'], hand_2=['9', 'Q', '8', 'A'], but got False instead. " which must be false but the program expects True. – novice Feb 08 '23 at 14:54
0

Im shared how can I solved it

1-I split the numbers and letters 2-I sorted the letter in order letter A is the last one

def sum_hand(hand):
#hand.sort(reverse=True)

letter=[]
number=[]
for n in hand:
    if n.isnumeric():
        number.append(n)
    else:
        letter.append(n)
      

#print('letter--',letter)
#print('number--',number)

letter.sort(reverse=True)
number.sort(reverse=True)
number.extend(letter)

hand = number
#hand = sorted(number) + sorted(letter,reverse:True)
print(hand)
      

#print(hand)
result_hand=0

for card in hand:
    if (card == 'J' or card == 'Q' or card == 'K'):
        result_hand += 10
    elif (card.isdigit()):
        result_hand += int(card)
    else:
        if(result_hand <= 10):
            result_hand += 10
        else:
            result_hand += 1
            
return result_hand


def blackjack_hand_greater_than(hand_1, hand_2):


result_hand1 = sum_hand(hand_1)
result_hand2 = sum_hand(hand_2)

print('hand1-', result_hand1 , ' hand2', result_hand2)

if result_hand1 > 21:
    return False

if result_hand2 > 21:
    return True
        

if (result_hand1 > result_hand2 ):
    return True
else:
    return False