Understanding the functioning of 'and' and 'or'

118 views Asked by At

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.

4

There are 4 answers

0
pablo ovando On BEST ANSWER

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
0
Schnitte On

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.

7
Flow On

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
3
Claudio On

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.