"""Water Bucket Puzzle, by Al Sweigart al@inventwithpython.com
A water pouring puzzle.
More info: https://en.wikipedia.org/wiki/Water_pouring_puzzle
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, game, math, puzzle"""
import sys
print('Water Bucket Puzzle, by Al Sweigart al@inventwithpython.com')
GOAL = 4 # The exact amount of water to have in a bucket to win.
steps = 0 # Keep track of how many steps the player made to solve this.
# The amount of water in each bucket:
waterInBucket = {'8': 0, '5': 0, '3': 0}
while True: # Main game loop.
# Display the current state of the buckets:
print()
print('Try to get ' + str(GOAL) + 'L of water into one of these')
print('buckets:')
waterDisplay = [] # Contains strings for water or empty space.
# Get the strings for the 8L bucket:
for i in range(1, 9):
if waterInBucket['8'] < i:
waterDisplay.append(' ') # Add empty space.
else:
waterDisplay.append('WWWWWW') # Add water.
# Get the strings for the 5L bucket:
for i in range(1, 6):
if waterInBucket['5'] < i:
waterDisplay.append(' ') # Add empty space.
else:
waterDisplay.append('WWWWWW') # Add water.
# Get the strings for the 3L bucket:
for i in range(1, 4):
if waterInBucket['3'] < i:
waterDisplay.append(' ') # Add empty space.
else:
waterDisplay.append('WWWWWW') # Add water.
# Display the buckets with the amount of water in each one:
print('''
8|{7}|
7|{6}|
6|{5}|
5|{4}| 5|{12}|
4|{3}| 4|{11}|
3|{2}| 3|{10}| 3|{15}|
2|{1}| 2|{9}| 2|{14}|
1|{0}| 1|{8}| 1|{13}|
+------+ +------+ +------+
8L 5L 3L
'''.format(*waterDisplay))
# Check if any of the buckets has the goal amount of water:
for waterAmount in waterInBucket.values():
if waterAmount == GOAL:
print('Good job! You solved it in', steps, 'steps!')
sys.exit()
# Let the player select an action to do with a bucket:
print('You can:')
print(' (F)ill the bucket')
print(' (E)mpty the bucket')
print(' (P)our one bucket into another')
print(' (Q)uit')
while True: # Keep asking until the player enters a valid action.
move = input('> ').upper()
if move == 'QUIT' or move == 'Q':
print('Thanks for playing!')
sys.exit()
if move in ('F', 'E', 'P'):
break # Player has selected a valid action.
print('Enter F, E, P, or Q')
# Let the player select a bucket:
while True: # Keep asking until valid bucket entered.
print('Select a bucket 8, 5, 3, or QUIT:')
srcBucket = input('> ').upper()
if srcBucket == 'QUIT':
print('Thanks for playing!')
sys.exit()
if srcBucket in ('8', '5', '3'):
break # Player has selected a valid bucket.
# Carry out the selected action:
if move == 'F':
# Set the amount of water to the max size.
srcBucketSize = int(srcBucket)
waterInBucket[srcBucket] = srcBucketSize
steps += 1
elif move == 'E':
waterInBucket[srcBucket] = 0 # Set water amount to nothing.
steps += 1
elif move == 'P':
# Let the player select a bucket to pour into:
while True: # Keep asking until valid bucket entered.
print('Select a bucket to pour into: 8, 5, or 3')
dstBucket = input('> ').upper()
if dstBucket in ('8', '5', '3'):
break # Player has selected a valid bucket.
# Figure out the amount to pour:
dstBucketSize = int(dstBucket)
emptySpaceInDstBucket = dstBucketSize - waterInBucket[dstBucket]
waterInSrcBucket = waterInBucket[srcBucket]
amountToPour = min(emptySpaceInDstBucket, waterInSrcBucket)
# Pour out water from this bucket:
waterInBucket[srcBucket] -= amountToPour
# Put the poured out water into the other bucket:
waterInBucket[dstBucket] += amountToPour
steps += 1
elif move == 'C':
pass # If the player selected Cancel, do nothing.