Portioning 15 units of Liquid (Math Brainteaser)

Otis

Elite Member
Joined
Apr 22, 2015
Messages
4,414
The following brainteaser asks for the most-efficient solution. I've found multiple solutions, and I was able to shorten two of them. My answer with the least number of steps appears below, but how could I determine whether it is the most-efficient?

You have three unmarked containers. Their volumes are 6 units, 10 units and 15 units. The 6-unit and 10-unit containers are empty. The largest container is full of a desirable, liquid beverage. Transfer liquid between the containers such that you measure exactly 2 units of beverage for yourself to drink, while leaving exactly 8 units in the 10-unit container and 5 units in the 6-unit container.

I proceeded based on the following:

Containers may not be changed in any way (eg: markings may not be added, no container may be placed inside another, additional "containers" may not be used, etc). Each time liquid is poured somewhere else, it counts as a step.

Code:
0   0  15
6   0   9
6   9   0
0   9   6
6   3   6
0   3  12
3   0  12
3  10   2
3  10   0
0  10   3
6   4   3
6   0   7
0   6   7
6   6   1
2  10   1
2   0  11
0   2  11
6   2   5
0   8   5
5   8   0

?

[imath]\;[/imath]
 
A shorter solution is possible. I found it by writing a computer program, so unless there's a mistake in my code then I've found the shortest possible solution. I'll wait a couple of days before posting my answer because it feels like I cheated. Here's a clue if anyone wants it...
Drink from the 6 unit container
 
A shorter solution is possible. I found it by writing a computer program, so unless there's a mistake in my code then I've found the shortest possible solution. I'll wait a couple of days before posting my answer because it feels like I cheated. Here's a clue if anyone wants it...
Drink from the 6 unit container
I might be misinterpreting your clue, but the OP states you drink out of the 15-unit container.
 
A shorter solution is possible ... I'll wait a couple of days before posting
You could put the code in a spoiler. (I'm interested in the logic of efficiency.)

But if your answer has half or less as many steps than in my answer, then I may not want to see it! ?

[imath]\;[/imath]
 
[0,0,15]
[6,0,9]
[0,6,9]
[6,6,3]
[2,10,3] Cheers?
[0,10,3]
[0,0,13]
[6,0,7]
[0,6,7]
[6,6,1]
[2,10,1]
[2,0,11]
[0,2,11]
[6,2,5]
[0,8,5]
[5,8,0]
Cheers, again ?
@Cubist Is your solution shorter than this?
 
Last edited:
[0,0,15]
[6,0,9]
[0,6,9]
[6,6,3]
[2,10,3] Cheers?
[0,10,3]
[0,0,13]
[6,0,7]
[0,6,7]
[6,6,1]
[2,10,1]
[2,0,11]
[0,2,11]
[6,2,5]
[0,8,5]
[5,8,0]
Cheers, again ?
Arrrg. My goal had been to drink as soon as possible, and, looking back, I'd gone off the rails from an arithmetic goof and then made a transcription error when double-checking the possibilities step-by-step. Sigh.

I suspect your answer matches Cubist's.

[imath]\;[/imath]
 
@Cubist Is your solution shorter than this?
No, it's the same length. Well done BBB, or B³ :LOL:, did you also write a program?

I found three, almost identical, ways of doing it in 15 steps. Here's my code that performs a brute force search...
Python:
steps=[]
maxSteps=15 # (increase this number if you want to see longer solutions

maxA=6
maxB=10
# no need for maxC=15 since there's only 15 units of fluid anyway

initialFluid=15

def pour(a, b, c):
    # Not interested in solutions longer than this...
    if len(steps)>maxSteps: return

    # Have we been in this position before?
    d=[a,b,c]
    for x in steps:
        if x==d: return # ...if so, then don't go down this route again

    # Add these amounts to the previous steps
    steps.append(d)

    # Have we reached a solution?
    if a==5 and b==8 and c==0:
        print(len(steps)-1, "steps")
        print(steps)
        print()

    else:
        # Can we drink?
        if a==2 and a+b+c==initialFluid:
            pour(0, b, c) # drink a
        if b==2 and a+b+c==initialFluid:
            pour(a, 0, c) # drink b
        if c==2 and a+b+c==initialFluid:
            pour(a, b, 0) # drink c
        
        # Pouring options...
        if a>0 and b<maxB:
            amt=a
            if b+amt>maxB: amt=maxB-b
            pour(a-amt, b+amt, c) # pour a into b
        
        if a>0:
            amt=a
            pour(a-amt, b, c+amt) # pour a into c
        
        if b>0 and a<maxA:
            amt=b
            if a+amt>maxA: amt=maxA-a
            pour(a+amt, b-amt, c) # pour b into a
        if b>0:
            amt=b
            pour(a, b-amt, c+amt) # pour b into c
        
        if c>0 and a<maxA:
            amt=c
            if a+amt>maxA: amt=maxA-a
            pour(a+amt, b, c-amt) # pour c into a
        if c>0 and b<maxB:
            amt=c
            if b+amt>maxB: amt=maxB-b
            pour(a, b+amt, c-amt) # pour c into b
        
    # Remove these amounts, [a,b,c], from the previous steps
    steps.pop()

###############################

pour(0,0,initialFluid) # Starting fluid levels
 
No, it's the same length. Well done BBB, or B³ :LOL:, did you also write a program?

I found three, almost identical, ways of doing it in 15 steps. Here's my code that performs a brute force search...
Python:
steps=[]
maxSteps=15 # (increase this number if you want to see longer solutions

maxA=6
maxB=10
# no need for maxC=15 since there's only 15 units of fluid anyway

initialFluid=15

def pour(a, b, c):
    # Not interested in solutions longer than this...
    if len(steps)>maxSteps: return

    # Have we been in this position before?
    d=[a,b,c]
    for x in steps:
        if x==d: return # ...if so, then don't go down this route again

    # Add these amounts to the previous steps
    steps.append(d)

    # Have we reached a solution?
    if a==5 and b==8 and c==0:
        print(len(steps)-1, "steps")
        print(steps)
        print()

    else:
        # Can we drink?
        if a==2 and a+b+c==initialFluid:
            pour(0, b, c) # drink a
        if b==2 and a+b+c==initialFluid:
            pour(a, 0, c) # drink b
        if c==2 and a+b+c==initialFluid:
            pour(a, b, 0) # drink c
    
        # Pouring options...
        if a>0 and b<maxB:
            amt=a
            if b+amt>maxB: amt=maxB-b
            pour(a-amt, b+amt, c) # pour a into b
    
        if a>0:
            amt=a
            pour(a-amt, b, c+amt) # pour a into c
    
        if b>0 and a<maxA:
            amt=b
            if a+amt>maxA: amt=maxA-a
            pour(a+amt, b-amt, c) # pour b into a
        if b>0:
            amt=b
            pour(a, b-amt, c+amt) # pour b into c
    
        if c>0 and a<maxA:
            amt=c
            if a+amt>maxA: amt=maxA-a
            pour(a+amt, b, c-amt) # pour c into a
        if c>0 and b<maxB:
            amt=c
            if b+amt>maxB: amt=maxB-b
            pour(a, b+amt, c-amt) # pour c into b
    
    # Remove these amounts, [a,b,c], from the previous steps
    steps.pop()

###############################

pour(0,0,initialFluid) # Starting fluid levels
No, I didn't write a program. This is how I did it, partially.

As Otis stated, we want to drink as soon as possible, so we aim to achieve 2. Then I thought of possible ways of achieving that using the 6 and 10 units containers. (2+4)=6=>(6-4)=2 and (6+4)=10. This means, first, we need 6units in the 10-container, then add 4.
[0,0,15]
[6,0,9]
[0,6,9]---Get 6 in the 10 container
Next,
[6,6,3]---Add 4 and we achieve the goal
[2,10,3]
From here, I took your advice and drink. You said you found multiple solutions. I assume they're all the same up to this point, otherwise, you wouldn't be able to give that out as a clue. I think they are all the same up to this point because it's the fastest way to achieve 2.
 
Last edited:
The red text shows the very subtle differences between them...

[0, 0, 15], [6, 0, 9], [0, 6, 9], [6, 6, 3], [2, 10, 3], [0, 10, 3], [6, 4, 3], [6, 0, 7], [0, 6, 7], [6, 6, 1], [2, 10, 1], [2, 0, 11], [0, 2, 11], [6, 2, 5], [0, 8, 5], [5, 8, 0]
[0, 0, 15], [6, 0, 9], [0, 6, 9], [6, 6, 3], [2, 10, 3], [0, 10, 3], [0, 0, 13], [6, 0, 7], [0, 6, 7], [6, 6, 1], [2, 10, 1], [2, 0, 11], [0, 2, 11], [6, 2, 5], [0, 8, 5], [5, 8, 0]
[0, 0, 15], [6, 0, 9], [0, 6, 9], [6, 6, 3], [2, 10, 3], [2, 0, 13], [0, 0, 13], [6, 0, 7], [0, 6, 7], [6, 6, 1], [2, 10, 1], [2, 0, 11], [0, 2, 11], [6, 2, 5], [0, 8, 5], [5, 8, 0]
 
Top