See https://www.youtube.com/watch?v=q6M_pco_5Vo or https://en.wikipedia.org/wiki/Water_pouring_puzzle
https://kotlinlang.org/docs/reference/
https://kotlinlang.org/api/latest/jvm/stdlib/index.html
-
Transform
HelloWorld
to a Kotlin class -
Remove boilerplate
-
create a
Glass
data class withcapacity
, andcurrent
Int, with 0 as default value forcurrent
-
create
empty
method returning anotherGlass
usingcopy
method intoGlass
-
outside the class, create an extension method
fill
returning anotherGlass
usingcopy
method -
create a
State
data class with aList
ofGlass
-
(bonus) create a secondary constructor for
State
with avararg
ofGlass
-
create a
Move
class -
create a
Empty
data class with a glassindex
(an Int) that extends theMove
class overridetoString
using String template -
create a
Fill
data class with a glassindex
(an Int) that extends theMove
class overridetoString
using String template -
create a
Pour
data class withfrom
andto
glass index that extends theMove
class overridetoString
using String template -
(bonus) seal the
Move
class -
(bonus) create a computed property (custom getter) to get the missing part into a
Glass
(capacity - current
) -
define a
solve
function with form and toState
and returning aList
ofMove
do not implement the function, useTODO()
for the moment -
create a
main
method, into this method create initial state 0/8, 0/5, and 0/3Glass
create final state 4/8, 0/5, and 0/3Glass
-
call
solve
to obtain result display all moves usingforEach
with a lambda -
create a
process
method that taking aMove
a returning a newState
into theState
usemapIndexed
on glasses, awhen
to match differentMove
Note:if-then-else
is a expression (i.e. can return a value) -
Into the
Glass
class (or with an extension method) create the method (operator) than allow the syntaxnewGlass = glass + 4
create the method (operator) than allow the syntaxnewGlass = glass - 3
use these operators inState#process
method -
create method
availableMoves
returningList
of availableMove
into theState
Class Note: avoid empty an already emptied class Note: avoid fill an already filled class Note: you cannot pour a glass to itself -
(bonus) create helper function
isEmpty
andisFill
inGlass
-
(bonus) transform helper function
isEmpty
andisFill
to lazy val inGlass
-
create a private
solveAux
recursive function with aList
ofPair
ofState
andList
ofMove
, with a targetState
, and with aSet
of already visitedState
returning theList
ofMove
skip implementation withTODO()
-
implements
solve
function with thesolveAux
method -
for the
sloveAux
real implementation first implement the terminal case -
then create the next
List
ofPair<State, List<Move>>
-
create the new
List
of visitedState
-
finish the recursion
-
(bonus) use a
typealias
forPair<State, List<Move>>
-
(bonus) use a
tailrec
-
(bonus) make
solveAux
an internal function intosolve
, remove thetarget
argument (closure) -
(bonus) safety check for data class using
init
block -
(bonus) safety check
solve
andsolveAux
-
drink non-empty glass ;-)
Solve 0/8, 0/5, 0/3 --> 4/8, 0/5, 0/3 in 8 moves:
Fill 1 (0/8, 5/5, 0/3)
Pour 1 in 0 (5/8, 0/5, 0/3)
Fill 1 (5/8, 5/5, 0/3)
Pour 0 in 2 (2/8, 5/5, 3/3)
Empty 2 (2/8, 5/5, 0/3)
Pour 1 in 0 (7/8, 0/5, 0/3)
Pour 0 in 2 (4/8, 0/5, 3/3)
Empty 2 (4/8, 0/5, 0/3)