Advent of Code 2022
Day 1
This one seems to be rather easy, just adding the calories and find the biggest number. The twist is also not too hard, a great puzzle to warm up this year.
Part 1
Spoiler: sollution
66719
198551
let getMostCalloriesElf = () => {
let data =
DayOneInput.data
|> Js.String.split("\n\n")
|> Js.Array.map(elf => {
elf
|> Js.String.split("\n")
|> Js.Array.map(item => {
let value = Belt.Int.fromString(item)
switch value {
| Some(v) => v
| None => 0
}
})
|> Js.Array.reduce(\"+", 0)
})
|> Js.Array.sortInPlaceWith((a, b) => b - a)
data
}
Day 2
Today we get a twist that requires you to puzzle a bit more.
Part 1
Spoiler: sollution
15632
14416
type hand = Rock | Paper | Scissor
let isHandWinning = ((oponent, yours)) => {
switch oponent {
| Rock => yours === Paper
| Paper => yours === Scissor
| Scissor => yours === Rock
}
}
let isDraw = ((oponent, yours): (hand, hand)) => oponent === yours
let handScore = hand => {
let base = switch hand {
| (_, Rock) => 1
| (_, Paper) => 2
| (_, Scissor) => 3
}
switch (isDraw(hand), isHandWinning(hand)) {
| (true, _) => base + 3
| (false, true) => base + 6
| (false, false) => base + 0
}
}
exception Invalid_Token
let tokenToHand = token => {
switch token {
| "A" => Rock
| "X" => Rock
| "B" => Paper
| "Y" => Paper
| "C" => Scissor
| "Z" => Scissor
| _ => raise(Invalid_Token)
}
}
let convertWinStatusToHand = hand => {
switch hand {
| (Rock, Rock) => (Rock, Scissor) // Lose
| (Rock, Paper) => (Rock, Rock) // Draw
| (Rock, Scissor) => (Rock, Paper) // Win
| (Paper, Rock) => (Paper, Rock)
| (Paper, Paper) => (Paper, Paper)
| (Paper, Scissor) => (Paper, Scissor)
| (Scissor, Rock) => (Scissor, Paper)
| (Scissor, Paper) => (Scissor, Scissor)
| (Scissor, Scissor) => (Scissor, Rock)
}
}
let calculateStrategyScore = () => {
DayTwoInput.data
|> Js.String.split("\n")
|> Js.Array.map(round => {
let tokens = round |> Js.String.split(" ")
let hand = (tokenToHand(tokens[0]), tokenToHand(tokens[1]))
let score = handScore(hand)
score
})
|> Js.Array.reduce(\"+", 0)
}
let calculateStrategyScore2 = () => {
DayTwoInput.data
|> Js.String.split("\n")
|> Js.Array.map(round => {
let tokens = round |> Js.String.split(" ")
let winStatus = (tokenToHand(tokens[0]), tokenToHand(tokens[1]))
// Convert win statuses to hands first in this version of the solution
let hand = convertWinStatusToHand(winStatus)
let score = handScore(hand)
score
})
|> Js.Array.reduce(\"+", 0)
}
Day 3
Spoiler: sollution part 1
Data is defined like this:
let indexToPrioTuple = (charOffset, indexOffset, index, (_char, _index)): (string, int) => (
Js.String2.fromCharCode(charOffset + index),
index + indexOffset,
)
let prios = Belt.Array.concat(
Belt.Array.make(26, ("a", 0))->Belt.Array.mapWithIndex(indexToPrioTuple(97, 1)),
Belt.Array.make(26, ("a", 0))->Belt.Array.mapWithIndex(indexToPrioTuple(65, 27)),
)
let data = "ZNNvFWHqLNPZHHqPTHHnT
............
CgBClZfCflPflNZRvfQswwmwmwQsQhgppdhm"
let lineToRucksack = line => {
let length = Js.String2.length(line) / 2
let sackOne = Js.String2.slice(line, ~from=0, ~to_=length)->Js.String2.split("")
let sackTwo = Js.String2.sliceToEnd(line, ~from=length)->Js.String2.split("")
(sackOne, sackTwo)
}
let tokensToRucksacks = tokens => {
Js.String2.split(tokens, "\n")->Belt.Array.map(lineToRucksack)
}
let findDoublesInRucksack = ((sackOne, sackTwo)) => {
Belt.Array.getBy(sackOne, item => {
Belt.Array.some(sackTwo, other => other === item)
})
}
let getPrioForToken = token => {
switch token {
| None => 0
| Some(token) => {
let result = Belt.Array.getBy(DayThreeInput.prios, ((t, _p)) => t === token)
switch result {
| Some((_, prio)) => prio
| None => 0
}
}
}
}
let getAllDoublesInRucksacks = () => {
let rucksacks = tokensToRucksacks(DayThreeInput.data)
Belt.Array.map(rucksacks, findDoublesInRucksack)
->Belt.Array.map(getPrioForToken)
->Belt.Array.reduce(0, \"+")
}
7878
Spoiler: sollution part 2
let rec chunk = (array, length) => {
let part = Belt.Array.slice(array, ~offset=0, ~len=length)
let rest = Belt.Array.sliceToEnd(array, length)
switch rest {
| [] => list{part}
| _ => list{part, ...chunk(rest, length)}
}
}
let badgePrioInGroup = (group: array<array<string>>) => {
let leader = Belt.Array.get(group, 0)
let second = Belt.Array.get(group, 1)
let third = Belt.Array.get(group, 2)
switch (leader, second, third) {
| (Some(leader), Some(second), Some(third)) =>
Belt.Array.getBy(leader, token => {
let s = Belt.Array.getBy(second, t => token === t)
let t = Belt.Array.getBy(third, t => token === t)
switch (s, t) {
| (Some(_), Some(_)) => true
| (_, _) => false
}
})->DayThree.getPrioForToken
| (_, _, _) => 0
}
}
let rec calculateTotalPrioForBadges = groups => {
switch groups {
| list{} => 0
| list{group, ...rest} => badgePrioInGroup(group) + calculateTotalPrioForBadges(rest)
}
}
let getElfGroups = () => {
Js.String2.split(DayThreeInput.data, "\n")
->Belt.Array.map(Js.String.split(""))
->chunk(3)
->calculateTotalPrioForBadges
}
2760