package Ġn rx us . dro pto ken Ċ Ċ /// ĠThe Ġnumbers Ġin Ġtokens Ġrepresent Ġa Ġplayer Ġid ; Ġwhere Ġthe Ġid Ġ> Ġ 0 Ċ /// ĠAny Ġ" ho les " Ġin Ġthe Ġboard Ġgame Ġare Ġden oted Ġby Ġ- 1 Ċ class ĠSquare Board ( private Ġval Ġlength : ĠInt , Ġval Ġtokens : ĠMutable List < Int >) Ġ{ ĊĠĠĠ Ġsealed Ġclass ĠState Ġ{ ĊĠĠĠĠĠĠĠ Ġobject ĠIn Progress Ġ: ĠState () ĊĠĠĠĠĠĠĠ Ġdata Ġclass ĠDone ( val Ġwinner : ĠInt ?) Ġ: ĠState () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġdrop ( column : ĠInt , Ġplayer : ĠInt ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġout Ġof Ġcolumn Ġbounds ĊĠĠĠĠĠĠĠ Ġif Ġ( column Ġ< Ġ 0 Ġ|| Ġcolumn Ġ>= Ġlength ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġfind Ġfirst Ġempty Ġposition Ġon Ġthis Ġcolumn ĊĠĠĠĠĠĠĠ Ġvar Ġposition Ġ= Ġcolumn ĊĠĠĠĠĠĠĠ Ġwhile Ġ( tokens . getOrElse ( position ) Ġ{ Ġ- 1 Ġ} Ġ!= Ġ- 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġposition Ġ+= Ġlength ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġout Ġof Ġrow Ġbounds ĊĠĠĠĠĠĠĠ Ġif Ġ( position Ġ>= Ġlength Ġ* Ġlength ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġout Ġof Ġrow Ġbounds ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġfill Ġwith Ġ- 1 Ġuntil Ġthe Ġposition Ġif Ġnecessary ĊĠĠĠĠĠĠĠ Ġtokens . addAll (( 0 .. position Ġ- Ġtokens . size ). map Ġ{ Ġ- 1 Ġ}) ĊĊĠĠĠĠĠĠĠ Ġtokens [ position ] Ġ= Ġplayer ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġstate (): ĠState Ġ{ ĊĠĠĠĠĠĠĠ Ġwhen Ġ( val Ġwin ning Row Ġ= Ġwin ning Row ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull Ġ-> ĠUnit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġreturn ĠState . Done ( tokens [ win ning Row Ġ* Ġlength ]) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġwhen Ġ( val Ġwin ning Column Ġ= Ġwin ning Column ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull Ġ-> ĠUnit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġreturn ĠState . Done ( tokens [ win ning Column ]) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġwhen Ġ( val Ġright Up Winner Ġ= Ġright Up Winner ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull Ġ-> ĠUnit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġreturn ĠState . Done ( right Up Winner ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġwhen Ġ( val Ġleft Up Winner Ġ= Ġleft Up Winner ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnull Ġ-> ĠUnit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġreturn ĠState . Done ( left Up Winner ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( tokens . size Ġ!= Ġlength Ġ* Ġlength Ġ|| Ġtokens . any Ġ{ Ġit Ġ== Ġ- 1 Ġ}) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠState . InProgress ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠState . Done ( null ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġleft Up Winner (): ĠInt ? Ġ= Ġ( 0 Ġuntil Ġlength ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. map NotNull Ġ{ Ġtokens . get OrNull ( it Ġ* Ġlength Ġ+ Ġ( length Ġ- Ġit Ġ- Ġ 1 )) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( has Winner ( it )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit [ 0 ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġright Up Winner (): ĠInt ? Ġ= Ġ( 0 Ġuntil Ġlength ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. map NotNull Ġ{ Ġtokens . get OrNull ( it Ġ* Ġlength Ġ+ Ġit ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( has Winner ( it )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit [ 0 ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġwin ning Column (): ĠInt ? Ġ= Ġ( 0 Ġuntil Ġlength ). find Ġ{ Ġi Ġ-> ĊĠĠĠĠĠĠĠ Ġval Ġcolumn Ġ= Ġ( 0 Ġuntil Ġlength ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map NotNull Ġ{ Ġj Ġ-> Ġtokens . get OrNull ( i Ġ+ Ġlength Ġ* Ġj ) Ġ} ĊĠĠĠĠĠĠĠ Ġhas Winner ( column ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġwin ning Row (): ĠInt ? Ġ= Ġ( 0 Ġuntil Ġlength ). find Ġ{ Ġi Ġ-> ĊĠĠĠĠĠĠĠ Ġval Ġrow Ġ= Ġ( 0 Ġuntil Ġlength ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġj Ġ-> Ġtokens . getOrElse ( i Ġ* Ġlength Ġ+ Ġj ) Ġ{ Ġ- 1 Ġ} Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Not Ġ{ Ġit Ġ== Ġ- 1 Ġ} ĊĠĠĠĠĠĠĠ Ġhas Winner ( row ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġhas Winner ( cells : ĠList < Int >): ĠBoolean Ġ= Ġif Ġ( cells . size Ġ< Ġlength ) Ġ{ ĊĠĠĠĠĠĠĠ Ġfalse ĊĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠ Ġcells . distinct (). count () Ġ== Ġ 1 ĊĠĠĠ Ġ} Ċ }