checkio (water jars)

You stand by the edge of a lake with two empty jars. You notice that both of the jars have a volume. You can fill each jar with water from the lake, pour water from one jar to other or pour water back into lake. You should measure the volume of water in either jar. The required volume of water may be in either of the jars and it does not matter which.

Each action is described as a string of two symbols: from and to. The jars are marked as 1 and 2, the lake is marked 0. If you want to take water from the lake and fill first jar, then it's "01". To pour water from second jar into the first would be "21". Dump water out of the first jar and back into the lake would be "10". When you fill a jar from the lake, that jars volume will be full. When you pour water out a jar and into the lake, that jars volume will be empty. If you pour water from one jar to another, you can only pour as much as will fill the full volume of the receiving jar.

The function has three arguments: The volume of first jar, the volume of second jar and the goal. All arguments are positive integers (number > 0). You should return a list with action's sequence. If a solution does not exist, then return an empty list.
The solution must contain the minimum possible number of steps

Input: The volume of first jar, the volume of second jar and the goal. Positive integers.

Output: A sequence of steps. A list with strings.

Example:

?
1
2
checkio(5, 7, 6) == ['02', '21', '10', '21', '02', '21', '10', '21', '02', '21']
checkio(3, 4, 1) == ["02", "21"]

经典的倒水问题,求最少的操作序列
from collections import deque

def checkio(first_volume, second_volume, goal):
    actions = {
        "01": lambda f, s: (first_volume, s),
        "02": lambda f, s: (f, second_volume),
        "12": lambda f, s: (
            f - (second_volume - s if f > second_volume - s else f),
            second_volume if f > second_volume - s else s + f),
        "21": lambda f, s: (
            first_volume if s > first_volume - f else s + f,
            s - (first_volume - f if s > first_volume - f else s),
        ),
        "10": lambda f, s: (0, s),
        "20": lambda f, s: (f, 0)
    }

    first, second = 0, 0
    queue = deque()
    queue.append((first, second))
    visit = {(first, second):1}
    last = {}
    end = None

    while queue:
        node = queue.popleft()
        if node[0] == goal or node[1] == goal:
            end = node
            break
        for act in ['01', '02', '12', '21', '10', '20']: 
            first, second = actions[act](node[0], node[1])
            if (first, second) not in visit:
                queue.append((first, second))
                visit[(first, second)] = 1
                last[(first, second)] = node, act

    ans = []
    status = end
    while status != (0, 0):
        ans.append(last[status][1])
        status = last[status][0]
    ans.reverse()
    return ans


你可能感兴趣的:(checkio (water jars))