Working out the jug problem in python

Search for a command to run...

No comments yet. Be the first to comment.
During in the process of reverse engineering binaries, a common problem arises. How do I reverse engineer stripped binaries? There are no symbols to break on, offsets change, scripts don't work, and you ask yourself why am I doing this? Luckily there...

When I was learning how to tackle pwn challenges in CTFs, I had a tough time finding a single, clear guide that could show me the ropes of actually carrying out these exploits. That's why I decided to put together a complete guide that covers everyth...

Using python to capture and project data

Intro This is a write-up for PicoCTF 2022: Buffer Overflow 1. This is one of my favourite challenges to do. I recommend solving it for yourself before you read this write-up. What is a Buffer Overflow? Before we get started we need to first know what...

What is a BadUSB? A BadUSB is a USB device that acts as a keyboard and injects preprogrammed keystrokes into a computer. A BadUSB is Indistinguishable from a generic keyboard, making it near impossible to detect and patch. You can setup reverse shell...

Everyone knows the classic water jug problem. You are by a stream with a 5-Litre and a 7-Litre bucket. How do you measure out 6-Litres in the fewest possible pourings? You first fill up the 7 and so on.

You might not have seen this particular problem but you have definitely heard of a problem like this. But what many people do not know about this problem is you can actually solve it using the points of a Parallelogram or what some people call a pool table. If you translate your starting amount of water as 5 litres in the 5-litre jug, then you can translate it to (0,5). You can keep it bouncing off the points until you desired amount in the x or y. The parallelogram does the exact same thing as what we just did in the table above.

I found that it was easier to find the patterns if I made the parallelogram a rectangle. There are 4 different variables you need to use this. The current x and y, the method you are using and the side & top length. Once you have those 4 variables you can make any table. I strongly recommend following each line with your finger as I tell you the rules:

The Total Method is when you add up the x and y and then flip it to the other side of the rectangle. If you look at the start point of the line and the endpoint of the line then the x+y will equal the same. There are 2 rules in the total method
The swap method swaps the x or y depending on which line it is on. The swap method is made up of 4 smaller rules that each change specific variables in the coordinates depending on which side of the rectangle you are using the swap method on.
We can also find out that to start the bouncing of the parallelogram, it will always start with the total method and then switch to the swap method and then back to the total method and so on.
The Swap Method
jugs = []
numberOfJugs = 2
def swapMethod(x,y, tLength, sLength):
#input:(0, y) output: (tLength, y)
if x == 0:
print("added")
return tLength, y
#input: (x, 0) output: (x, min)
elif y == 0:
print("else ", x, sLength)
return x,sLength
#input: (x, sLength) output: (x, 0)
elif y == sLength:
print("x: ",x, "y: ", y,)
return x,0
#Input:(tLength, y) output:(0, y)
elif x == tLength:
print(0,y)
return 0,y
...
The Total Method
...
def totalMethod(x,y, maxi, minu):
#Going horizontally down
if x == 0 or y == minu:
return min(maxi, (x+y)), max((x+y-maxi), 0)
#Going horizontally up
else:
return max((x+y-minu), 0), min(minu, (x+y))
...
The calling
...
targetCapacity = 6 # Change this
tLength, sLength = 7,5 #Change this
x,y = 0,5 # Change this
history = f'''
_____{tLength}___{sLength}_|
01 | {x} | {y} |
'''
# First time one will always be the Total method
x,y = totalMethod(x,y, tLength, sLength)
past = 0
history += f'02 | {x} | {y} |\n'
for i in range(0,10):
if x == targetCapacity or y == targetCapacity:
break
if past == 0: # calls swapmethod
x,y = swapMethod(x,y,tLength,sLength)
past = 1
else: #calls totalMethod
x,y = totalMethod(x,y, tLength, sLength)
past = 0
history += f'{i+3:02} | {x} | {y} |\n'
print(history)
Full code here
If you want to see a more complete version with inputs look on my GitHub here. Thanks to my math teacher for showing me this problem. It was a fun challenge.