Skip to content

Instantly share code, notes, and snippets.

@sungkmi
Last active January 1, 2022 14:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sungkmi/8f9ed15e8ff98eaa41bfaa78c81c6ea3 to your computer and use it in GitHub Desktop.
Save sungkmi/8f9ed15e8ff98eaa41bfaa78c81c6ea3 to your computer and use it in GitHub Desktop.
package lascala.aoc2021.day1_10.day3
case class DiagnosticReport(
width: Int,
bits: Seq[BigInt],
)
extension (bits: Seq[BigInt])
def mostCommonBit(index: Int): Boolean =
bits.map(_.testBit(index)).count(_ == true) * 2 >= bits.size
extension (d: DiagnosticReport)
def buildByPositionBit(f: Int => Boolean): BigInt =
val bitSeq = for (i <- 0 until d.width) yield if f(i) then '1' else '0'
BigInt(bitSeq.reverse.mkString, 2)
def gamma: BigInt = buildByPositionBit(d.bits.mostCommonBit(_))
def epsilon: BigInt = buildByPositionBit(!d.bits.mostCommonBit(_))
def powerComsumption: BigInt = gamma * epsilon
def chooseByIterativeFiltering(
filter: (Int, Seq[BigInt]) => Seq[BigInt],
): BigInt =
@annotation.tailrec
def loop(index: Int, bits: Seq[BigInt]): BigInt =
if bits.size == 1 then bits.head
else loop(index - 1, filter(index, bits))
loop(d.width - 1, d.bits)
def oxygen: BigInt = chooseByIterativeFiltering { (index, bits) =>
val mostCommon = bits.mostCommonBit(index)
bits.filter(_.testBit(index) == mostCommon)
}
def co2: BigInt = chooseByIterativeFiltering { (index, bits) =>
val leastCommon = !bits.mostCommonBit(index)
bits.filter(_.testBit(index) == leastCommon)
}
def lifeSupporting: BigInt = oxygen * co2
end extension
object DiagnosticReport:
def parse(s: String): DiagnosticReport =
val lines = s.split("\n")
DiagnosticReport(
width = lines.head.size,
bits = lines.map { line => BigInt(line, 2) },
)
def solve1(s: String): BigInt = DiagnosticReport.parse(s).powerComsumption
def solve2(s: String): BigInt = DiagnosticReport.parse(s).lifeSupporting
@main def part1: Unit =
val ans = solve1(input)
println(ans)
@main def part2: Unit =
val ans = solve2(input)
println(ans)
//val input = """111111010011
package lascala.aoc2021.day1_10.day3
import minitest.SimpleTestSuite
import hedgehog.minitest.HedgehogSupport
import hedgehog.*
object Day3Test extends SimpleTestSuite with HedgehogSupport:
val exampleInput: String = """00100
11110
10110
10111
10101
01111
00111
11100
10000
11001
00010
01010"""
example("day3 - gammaRate") {
val d = DiagnosticReport.parse(exampleInput)
d.gammaRate.toString(2) ==== "10110"
}
example("day3 - epsilonRate") {
val d = DiagnosticReport.parse(exampleInput)
d.epsilonRate ==== 9
}
example("day3 - oxygen") {
val d = DiagnosticReport.parse(exampleInput)
d.oxygen ==== 23
}
example("day3 - co2") {
val d = DiagnosticReport.parse(exampleInput)
d.co2 ==== 10
}
example("day3 - solve1") {
solve1(exampleInput) ==== 198
}
example("day3 - solve2") {
solve2(exampleInput) ==== 230
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment