Skip to content

Commit

Permalink
Roc 2023-07 * **
Browse files Browse the repository at this point in the history
  • Loading branch information
Janiczek committed Dec 7, 2023
1 parent 4f9b7f2 commit 9a3df77
Show file tree
Hide file tree
Showing 2 changed files with 252 additions and 2 deletions.
251 changes: 251 additions & 0 deletions src/Year2023/Day07.roc
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
app "hello"
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.0/bkGby8jb0tmZYsy2hg1E_B2QrCgcSTxdUlHtETwm5m4.tar.br" }
imports [
pf.Stdout,
"../../input202307.txt" as realInput : Str
]
provides [main] to pf


#main = part1 realInput
main = part2 realInput
#main = part1 testInput
#main = part2 testInput

testInput : Str
testInput =
"32T3K 765\nT55J5 684\nKK677 28\nKTJJT 220\nQQQJA 483"

cardValue : Str -> Nat
cardValue = \char ->
when char is
"A" -> 13
"K" -> 12
"Q" -> 11
"J" -> 10
"T" -> 9
"9" -> 8
"8" -> 7
"7" -> 6
"6" -> 5
"5" -> 4
"4" -> 3
"3" -> 2
"2" -> 1
_ -> crash "weird card value"

Category: [
FiveOfAKind,
FourOfAKind,
FullHouse,
ThreeOfAKind,
TwoPair,
OnePair,
HighCard,
]

frequencies : List a -> Dict a Nat
frequencies = \list ->
list
|> List.walk
(Dict.empty {})
(\counter,el ->
current =
counter
|> Dict.get el
|> Result.withDefault 0

counter
|> Dict.insert el (current + 1)
)


invert : Dict a b -> Dict b (List a)
invert = \dict ->
dict
|> Dict.toList
|> List.map (\(k,v) -> (v,k))
|> List.walk
(Dict.empty {})
(\acc,(k,v) ->
acc
|> Dict.update k
(\maybeV ->
when maybeV is
Missing -> Present [v]
Present vs -> Present (List.append vs v)
)
)

categorize : Str -> Category
categorize = \hand ->

counts : Dict Nat (List Str)
counts =
hand
|> Str.graphemes
|> frequencies
|> invert

if Dict.contains counts 5 then
FiveOfAKind
else if Dict.contains counts 4 then
FourOfAKind
else if Dict.contains counts 3 && Dict.contains counts 2 then
FullHouse
else if Dict.contains counts 3 then
ThreeOfAKind
else if Dict.get counts 2 |> Result.map List.len == Ok 2 then
TwoPair
else if Dict.contains counts 2 then
OnePair
else
HighCard

categoryValue : Category -> Nat
categoryValue = \cat ->
when cat is
FiveOfAKind -> 7
FourOfAKind -> 6
FullHouse -> 5
ThreeOfAKind -> 4
TwoPair -> 3
OnePair -> 2
HighCard -> 1

compareHand : Str, Str -> [LT,EQ,GT]
compareHand = \a,b ->
catA = categorize a
catB = categorize b
when Num.compare (categoryValue catA) (categoryValue catB) is
LT -> LT
GT -> GT
EQ ->
cardsA = a |> Str.graphemes |> List.map cardValue
cardsB = b |> Str.graphemes |> List.map cardValue
compareList cardsA cardsB


compareList : List Nat, List Nat -> [LT,EQ,GT]
compareList = \a,b ->
when (a,b) is
([],[]) -> EQ
(_,[]) -> GT
([],_) -> LT
([anA, .. as restA],[anB, .. as restB]) ->
when Num.compare anA anB is
LT -> LT
GT -> GT
EQ -> compareList restA restB

compareLine : {hand: Str, bid: Nat},{hand: Str, bid: Nat} -> [LT,EQ,GT]
compareLine = \a,b ->
compareHand a.hand b.hand

parse : Str -> List {hand: Str, bid: Nat}
parse = \input ->
input
|> Str.split "\n"
|> List.dropIf (\s -> s == "")
|> List.map parseLine

parseLine : Str -> {hand: Str, bid: Nat}
parseLine = \line ->
when Str.split line " " is
[hand, bidStr] ->
{
hand: hand,
bid: Str.toNat bidStr |> crashResult "bid not int",
}
_ ->
crash "weird parseLine"

crashResult : Result a *, Str -> a
crashResult = \result,label ->
when result is
Ok a -> a
Err _ -> crash label

##### PART 1 #####

expect part1Pure testInput == 6440

part1Pure : Str -> Nat
part1Pure = \input ->
input
|> parse
|> List.sortWith compareLine
|> List.mapWithIndex (\line,i -> line.bid * (i+1))
|> List.sum

part1 = \input ->
input
|> part1Pure
|> Inspect.toStr
|> Stdout.line

######### PART 2 #########

part2 = \input ->
input
|> parse
|> List.sortWith compareLineWithJokers
|> List.mapWithIndex (\line,i -> line.bid * (i+1))
|> List.sum
|> Inspect.toStr
|> Stdout.line

compareLineWithJokers : {hand: Str, bid: Nat},{hand: Str, bid: Nat} -> [LT,EQ,GT]
compareLineWithJokers = \a,b ->
compareHandWithJokers a.hand b.hand

compareHandWithJokers : Str, Str -> [LT,EQ,GT]
compareHandWithJokers = \a,b ->
catA = categorizeWithJokers a
catB = categorizeWithJokers b
when Num.compare (categoryValue catA) (categoryValue catB) is
LT -> LT
GT -> GT
EQ ->
cardsA = a |> Str.graphemes |> List.map cardValueWithJokers
cardsB = b |> Str.graphemes |> List.map cardValueWithJokers
compareList cardsA cardsB

allCardsWithoutJ : List Str
allCardsWithoutJ =
Str.graphemes "AKQT98765432"

categorizeWithJokers : Str -> Category
categorizeWithJokers = \hand ->
allCardsWithoutJ
|> List.map (\card ->
hand
|> replaceJWith card
|> categorize
)
|> List.sortWith (\a,b -> Num.compare (categoryValue a) (categoryValue b))
|> List.last
|> crashResult "categorize with jokers - list.last"

replaceJWith : Str, Str -> Str
replaceJWith = \hand,card ->
hand
|> Str.replaceEach "J" card

cardValueWithJokers : Str -> Nat
cardValueWithJokers = \char ->
when char is
"A" -> 13
"K" -> 12
"Q" -> 11
"T" -> 10
"9" -> 9
"8" -> 8
"7" -> 7
"6" -> 6
"5" -> 5
"4" -> 4
"3" -> 3
"2" -> 2
"J" -> 1
_ -> crash "weird card value (with jokers)"
3 changes: 1 addition & 2 deletions watch-roc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ INPUT="src/Year${YEAR}/Day${DAY}.roc"

chokidar '**/*.roc' | while read WHATEVER; do
clear && tput reset && echo -en "\033c\033[3J"
# roc test "${INPUT}" &&
RUST_BACKTRACE=full roc dev "${INPUT}"
roc test "${INPUT}" && RUST_BACKTRACE=full roc dev "${INPUT}"
done;

0 comments on commit 9a3df77

Please sign in to comment.