Skip to content

Commit b2d17e5

Browse files
committed
feat(aoc-2023): day 07 part 1 and part 2 ... not the slightest idea what is going on tho
1 parent 6911ace commit b2d17e5

5 files changed

Lines changed: 1176 additions & 0 deletions

File tree

2023/build.sbt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,12 @@ libraryDependencies ++= Seq(
7575

7676
// To learn more about multi-project builds, head over to the official sbt
7777
// documentation at http://www.scala-sbt.org/documentation.html
78+
79+
//increase the memory available to the JVM
80+
javacOptions ++= Seq(
81+
"-Xms5G",
82+
"-Xmx10G",
83+
"-XX:MaxMetaspaceSize=1024m",
84+
"-XX:ParallelGCThreads=16",
85+
"-XX:+ExitOnOutOfMemoryError"
86+
)
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package com.markkovari.adventofcode.day07
2+
3+
import scala.math.Ordering.Implicits.*
4+
5+
object DataDefs:
6+
enum Card:
7+
case Num(n: Int)
8+
case Ten
9+
case Jack
10+
case Queen
11+
case King
12+
case Ace
13+
lazy val value: Int = this match
14+
case Ace => 14
15+
case King => 13
16+
case Queen => 12
17+
case Jack => 11
18+
case Ten => 10
19+
case Num(n) => n
20+
lazy val jokerValue: Int = this match
21+
case Ace => 14
22+
case King => 13
23+
case Queen => 12
24+
case Ten => 10
25+
case Num(n) => n
26+
case Jack => 1
27+
28+
given Ordering[Card] with
29+
def compare(x: Card, y: Card): Int = x.value - y.value
30+
31+
enum Rank:
32+
case HighCard, OnePair, TwoPairs, ThreeOfAKind, FullHouse, FourOfAKind,
33+
FiveOfAKind
34+
35+
import Rank.*
36+
37+
given Ordering[Rank] with // part 1
38+
def compare(x: Rank, y: Rank): Int = x.ordinal compare y.ordinal
39+
40+
case class Hand(cards: Seq[Card]):
41+
private lazy val partition = cards
42+
.groupMapReduce(identity)(_ => 1)(_ + _)
43+
.values
44+
.toList
45+
.sorted
46+
lazy val rank: Rank = partition match
47+
case List(5) => FiveOfAKind
48+
case List(1, 4) => FourOfAKind
49+
case List(2, 3) => FullHouse
50+
case List(1, 1, 3) => ThreeOfAKind
51+
case List(1, 2, 2) => TwoPairs
52+
case List(1, 1, 1, 2) => OnePair
53+
case _ => HighCard
54+
55+
private lazy val isAllJokers = cards.forall(_ == Card.Jack)
56+
private lazy val indexedCards = cards.zipWithIndex
57+
private lazy val (jokers, others) =
58+
indexedCards.partition((card, _) => card == Card.Jack)
59+
private lazy val nonJokers = others.map(_._1).distinct
60+
private lazy val substitutes =
61+
for nonJoker <- nonJokers
62+
yield jokers.map((_, index) => (nonJoker, index))
63+
private lazy val subbedHands =
64+
for sub <- substitutes
65+
yield Hand((others ++ sub).sortBy(_._2).map(_._1))
66+
lazy val jokerRank: Rank =
67+
if isAllJokers then FiveOfAKind else subbedHands.maxBy(_.rank).rank
68+
69+
given Ordering[Hand] with
70+
def compare(x: Hand, y: Hand): Int =
71+
Ordering[Rank].compare(x.rank, y.rank) match
72+
case 0 => Ordering[Seq[Card]].compare(x.cards, y.cards)
73+
case n => n
74+
75+
case class Bid(hand: Hand, bid: Int)
76+
77+
given Ordering[Bid] with
78+
def compare(x: Bid, y: Bid): Int = Ordering[Hand].compare(x.hand, y.hand)
79+
80+
object Joker:
81+
given Ordering[Card] with
82+
def compare(x: Card, y: Card): Int = x.jokerValue - y.jokerValue
83+
84+
given Ordering[Hand] with
85+
def compare(x: Hand, y: Hand): Int =
86+
Ordering[Rank].compare(x.jokerRank, y.jokerRank) match
87+
case 0 => Ordering[Seq[Card]].compare(x.cards, y.cards)
88+
case n => n
89+
90+
given Ordering[Bid] with
91+
def compare(x: Bid, y: Bid): Int = Ordering[Hand].compare(x.hand, y.hand)
92+
93+
object Parsing:
94+
95+
import DataDefs.*
96+
import Card.*
97+
98+
extension (char: Char)
99+
def toCard: Card = char match
100+
case 'A' => Ace
101+
case 'K' => King
102+
case 'Q' => Queen
103+
case 'J' => Jack
104+
case 'T' => Ten
105+
case n => Num(n.asDigit)
106+
107+
def parseHand(hand: String): Hand = Hand(hand.map(_.toCard))
108+
109+
def lineToBid(line: String): Bid = line match
110+
case s"$hand $bid" => Bid(parseHand(hand), bid.toInt)
111+
112+
object Solving:
113+
114+
import DataDefs.*
115+
116+
def solve(lines: Seq[String])(using Ordering[Bid]): Long = lines
117+
.map(Parsing.lineToBid)
118+
.sorted
119+
.zipWithIndex
120+
.map((bid, index) => bid.bid * (index + 1))
121+
.sum
122+
123+
def part1(input: String): Long = {
124+
Solving.solve(input.linesIterator.toSeq)
125+
}
126+
127+
def part2(input: String): Long = {
128+
import DataDefs.Joker.given
129+
Solving.solve(input.linesIterator.toSeq)
130+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
32T3K 765
2+
T55J5 684
3+
KK677 28
4+
KTJJT 220
5+
QQQJA 483

0 commit comments

Comments
 (0)