Last active
May 18, 2023 15:57
-
-
Save Jessime/a1a751aaa35da244b2e76b5809d01740 to your computer and use it in GitHub Desktop.
To disable a bomb, Detective John McClane must measure out exactly 4 gallons of water, and place the resulting weight on a scale. His tools are yours: a 3-gallon and a 5-gallon jug—and a single fountain. https://www.popsci.com/solve-water-puzzle-die-hard-3/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from dataclasses import dataclass | |
from typing import Optional, Callable | |
def fill_b3(b3, b5): | |
return 3, b5 | |
def fill_b5(b3, b5): | |
return b3, 5 | |
def empty_b3(b3, b5): | |
return 0, b5 | |
def empty_b5(b3, b5): | |
return b3, 0 | |
def b3_into_b5(b3, b5): | |
return max(0, b3 - (5 - b5)), min(5, b3+b5) | |
def b5_into_b3(b3, b5): | |
return min(3, b3 + b5), max(0, b5 - (3-b3)) | |
ACTIONS = [fill_b3, fill_b5, empty_b3, empty_b5, b3_into_b5, b5_into_b3] | |
ACTION_2_DESC = { | |
fill_b3: "Fill bucket3 from the well. End state is: ", | |
fill_b5: "Fill bucket5 from the well. End state is: ", | |
empty_b3: "Empty bucket3. End state is: ", | |
empty_b5: "Empty bucket5. End state is: ", | |
b3_into_b5: "Move the contents of bucket3 into bucket5. End state is: ", | |
b5_into_b3: "Move the contents of bucket5 into bucket3. End state is: ", | |
None: "" | |
} | |
@dataclass() | |
class Node: | |
state: tuple[int, int] | |
parent: Optional["Node"] = None | |
func: Optional[Callable] = None | |
def find_solution(): | |
seen_states = {(0, 0)} | |
root = Node((0, 0)) | |
current_level = [root] | |
while True: | |
new_level = [] | |
for node in current_level: | |
for action in ACTIONS: | |
end_state = action(*node.state) | |
if end_state not in seen_states: | |
seen_states.add(end_state) | |
new_node = Node(end_state, node, action) | |
new_level.append(new_node) | |
if sum(end_state) == 4: | |
return new_node | |
current_level = new_level | |
def print_lineage(node): | |
parent = node.parent | |
lineage = [] | |
while True: | |
if parent is None: | |
break | |
lineage.insert(0, node) | |
node = node.parent | |
parent = node.parent | |
for node in lineage: | |
print(ACTION_2_DESC[node.func], node.state) | |
if __name__ == "__main__": | |
print_lineage(find_solution()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Fill bucket3 from the well. End state is: (3, 0) | |
Move the contents of bucket3 into bucket5. End state is: (0, 3) | |
Fill bucket3 from the well. End state is: (3, 3) | |
Move the contents of bucket3 into bucket5. End state is: (1, 5) | |
Empty bucket5. End state is: (1, 0) | |
Move the contents of bucket3 into bucket5. End state is: (0, 1) | |
Fill bucket3 from the well. End state is: (3, 1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment