Skip to content

Instantly share code, notes, and snippets.

@olakra
Last active February 8, 2019 20:02
Show Gist options
  • Save olakra/ac03718ae703a9b76d9c5c13828b2a32 to your computer and use it in GitHub Desktop.
Save olakra/ac03718ae703a9b76d9c5c13828b2a32 to your computer and use it in GitHub Desktop.
You have two water containers with different capacities and you're trying to measure out a third quantity. How?

Water Jug Riddle

MIT license follow olakra Awesome Kotlin Badge

Problem

You have two containers. One can hold 7 liters of water and the other can hold 11 liters. You also have access to a sink with a faucet. You can do any of these three things as many times as you like:

  • Fill one of the containers to the top with water.
  • Completely empty one of the containers into the sink.
  • Pour the contents of one container into the other until the second container is full (or until the first container is empty).

Given these conditions, is it possible to measure out exactly 5 liters of water? How?

Explaination

  • If the first bottle is empty, fill it until it's full
  • If the first bottle is full, transfer the water to the second bottle
  • Once the second bottle is full, empty it
  • Repeat until either of the bottle has 5 liters

Dependencies

Build & Run

$ kotlinc simulation.kt -include-runtime -d simulation.jar
$ java -jar simulation.jar
class Container(val capacity: Int) {
var usedCapacity: Int = 0
private set
fun availableCapacity() = capacity - usedCapacity
fun isFull() = usedCapacity == capacity
fun isEmpty() = usedCapacity == 0
fun doFill(quantity: Int = capacity) {
usedCapacity += quantity
}
fun doEmpty() {
usedCapacity = 0
}
fun doPour(otherContainer: Container) {
val availableForTransfer = otherContainer.availableCapacity()
usedCapacity = when {
availableForTransfer >= usedCapacity -> {
otherContainer.doFill(usedCapacity)
0
}
else -> {
otherContainer.doFill(availableForTransfer)
usedCapacity - availableForTransfer
}
}
}
override fun toString(): String = when {
isEmpty() -> "{ used: <empty> }"
isFull() -> "{ used: <full> }"
else -> "{ used: $usedCapacity of $capacity L }"
}
}
class Simulation(val containers: Pair<Container, Container>, private val target: Int = 0) {
fun run(): Int {
var pass = 1
do {
when {
containers.first.isEmpty() -> containers.first.doFill()
containers.first.isFull() -> containers.first.doPour(containers.second)
containers.second.isFull() -> containers.second.doEmpty()
containers.second.availableCapacity() == target -> {
containers.second.doEmpty()
containers.second.doFill(target)
}
else -> containers.first.doPour(containers.second)
}
pass += 1
} while (containers.first.usedCapacity != target && containers.second.usedCapacity != target)
return pass
}
override fun toString(): String = "[0]=${containers.first}, [1]=${containers.second}"
}
fun main() {
val simulations = arrayOf(Simulation(Pair(Container(7), Container(11)), 5), Simulation(Pair(Container(11), Container(7)), 5))
simulations.forEachIndexed { index, simulation ->
println("simulation[$index] where first's capacity is ${simulation.containers.first.capacity} L and second's capacity is ${simulation.containers.second.capacity} L, took ${simulation.run()} passes")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment