@@ -10,12 +10,12 @@ object Day22 {
10
10
type Decks = (Deck , Deck )
11
11
12
12
sealed trait Part {
13
- def playWinner (decks : Decks ): Either [Decks , Decks ]
13
+ def playWinner (decks : Decks ): Either [Deck , Deck ]
14
14
15
15
def winningScore (decks : Decks ): Int = {
16
16
val winningDeck = playWinner(decks) match {
17
- case Left (( deck1, _) ) => deck1
18
- case Right ((_, deck2) ) => deck2
17
+ case Left (deck1) => deck1
18
+ case Right (deck2) => deck2
19
19
}
20
20
winningDeck
21
21
.reverseIterator
@@ -25,18 +25,20 @@ object Day22 {
25
25
}
26
26
}
27
27
28
+ // TODO: reduce duplication
29
+
28
30
object Part1 extends Part {
29
31
30
- override def playWinner (decks : Decks ): Either [Decks , Decks ] = {
31
- val roundDecks = LazyList .unfold0(decks)(playRound)
32
- val lastDecks @ (lastDeck1, _ ) = roundDecks.last
32
+ override def playWinner (decks : Decks ): Either [Deck , Deck ] = {
33
+ val roundDecks = decks #:: LazyList .unfold0(decks)(playRound) // unfold0 doesn't include first
34
+ val (lastDeck1, lastDeck2 ) = roundDecks.last
33
35
if (lastDeck1.nonEmpty)
34
- Left (lastDecks )
36
+ Left (lastDeck1 )
35
37
else
36
- Right (lastDecks )
38
+ Right (lastDeck2 )
37
39
}
38
40
39
- def playRound (decks : Decks ): Option [Decks ] = {
41
+ private def playRound (decks : Decks ): Option [Decks ] = {
40
42
val (deck1, deck2) = decks
41
43
(deck1.dequeueOption, deck2.dequeueOption) match {
42
44
case (Some ((card1, newDeck1)), Some ((card2, newDeck2))) =>
@@ -51,47 +53,45 @@ object Day22 {
51
53
}
52
54
53
55
object Part2 extends Part {
56
+ // TODO: optimize
54
57
55
- override def playWinner (decks : Decks ): Either [Decks , Decks ] = {
56
- // println(s"GAME: $decks")
57
- val roundDecks = decks #:: LazyList .unfold0(decks)(playRound)
58
+ override def playWinner (decks : Decks ): Either [Deck , Deck ] = {
59
+ val roundDecks = decks #:: LazyList .unfold0(decks)(playRound) // unfold0 doesn't include first
58
60
NaiveCycleFinder .find(roundDecks) match {
59
61
case None =>
60
- val lastDecks @ (lastDeck1, _) = roundDecks.last
61
- // println("GAME OVER (normal)")
62
+ val (lastDeck1, lastDeck2) = roundDecks.last
62
63
if (lastDeck1.nonEmpty)
63
- Left (lastDecks )
64
+ Left (lastDeck1 )
64
65
else
65
- Right (lastDecks )
66
+ Right (lastDeck2 )
66
67
case Some (cycle) =>
67
- // println("GAME OVER (cycle)")
68
- Left (cycle.cycleHead)
68
+ Left (cycle.cycleHead._1)
69
69
}
70
70
}
71
71
72
- def playRound (decks : Decks ): Option [Decks ] = {
73
- // println(s"ROUND: $decks")
72
+ private def playRound (decks : Decks ): Option [Decks ] = {
74
73
val (deck1, deck2) = decks
75
74
(deck1.dequeueOption, deck2.dequeueOption) match {
76
75
case (Some ((card1, newDeck1)), Some ((card2, newDeck2))) =>
77
- // println(s" $card1 vs $card2")
78
- // TODO: Queue has inefficient length?
79
- if (! (newDeck1.length >= card1 && newDeck2.length >= card2)) {
80
- if (card1 > card2)
76
+ val winner : Either [Any , Any ] = {
77
+ // TODO: Queue has inefficient length?
78
+ if (newDeck1.length >= card1 && newDeck2.length >= card2) {
79
+ val recDecks = (newDeck1.take(card1), newDeck2.take(card2))
80
+ playWinner(recDecks)
81
+ } else {
82
+ if (card1 > card2)
83
+ Left ()
84
+ else
85
+ Right ()
86
+ }
87
+ }
88
+
89
+ winner match {
90
+ case Left (_) =>
81
91
Some ((newDeck1.enqueue(card1).enqueue(card2), newDeck2))
82
- else
92
+ case Right (_) =>
83
93
Some ((newDeck1, newDeck2.enqueue(card2).enqueue(card1)))
84
94
}
85
- else {
86
- val recDeck1 = newDeck1.take(card1)
87
- val recDeck2 = newDeck2.take(card2)
88
- playWinner((recDeck1, recDeck2)) match {
89
- case Left (_) =>
90
- Some ((newDeck1.enqueue(card1).enqueue(card2), newDeck2))
91
- case Right (_) =>
92
- Some ((newDeck1, newDeck2.enqueue(card2).enqueue(card1)))
93
- }
94
- }
95
95
case (_, _) =>
96
96
None
97
97
}
0 commit comments