Skip to content

Commit

Permalink
Create Circuit class in 2024 day 24
Browse files Browse the repository at this point in the history
  • Loading branch information
sim642 committed Dec 24, 2024
1 parent 62912a6 commit 5b54798
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 47 deletions.
90 changes: 46 additions & 44 deletions src/main/scala/eu/sim642/adventofcode2024/Day24.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,49 +15,51 @@ object Day24 {
case Gate(lhs: String, op: Op, rhs: String)
}

type Circuit = Map[String, Wire]
case class Circuit(wireMap: Map[String, Wire]) {
def zValue: Long = {
val memo = mutable.Map.empty[String, Boolean]

def getZValue(circuit: Circuit): Long = {
def evalName(name: String): Boolean =
memo.getOrElseUpdate(name, evalWire(wireMap(name)))

val memo = mutable.Map.empty[String, Boolean]

def evalName(name: String): Boolean =
memo.getOrElseUpdate(name, evalWire(circuit(name)))
def evalWire(wire: Wire): Boolean = wire match {
case Wire.Input(value) => value
case Wire.Gate(lhs, op, rhs) =>
val left = evalName(lhs)
val right = evalName(rhs)
op match {
case Op.And => left && right
case Op.Or => left || right
case Op.Xor => left != right
}
}

def evalWire(wire: Wire): Boolean = wire match {
case Wire.Input(value) => value
case Wire.Gate(lhs, op, rhs) =>
val left = evalName(lhs)
val right = evalName(rhs)
op match {
case Op.And => left && right
case Op.Or => left || right
case Op.Xor => left != right
}
wireMap.keys
.filter(_.startsWith("z"))
.toSeq
.sorted
.foldRight(0L)({ case (zName, acc) =>
acc << 1 | (if (evalName(zName)) 1 else 0)
})
}

circuit.keys
.filter(_.startsWith("z"))
.toSeq
.sorted
.foldRight(0L)({ case (zName, acc) =>
acc << 1 | (if (evalName(zName)) 1 else 0)
})
}
def swapped(name1: String, name2: String): Circuit =
Circuit(wireMap + (name1 -> wireMap(name2)) + (name2 -> wireMap(name1)))

private def withInputValue(inputPrefix: String, value: Long): Circuit = {
val (newCircuit, remainingValue) = wireMap.keys
.filter(_.startsWith(inputPrefix))
.toSeq
.sorted
.foldLeft((wireMap, value))({ case ((circuit, value), prefixName) =>
(circuit + (prefixName -> Wire.Input((value & 1) == 1L)), value >> 1)
})
assert(remainingValue == 0)
Circuit(newCircuit)
}

def swap(circuit: Circuit, name1: String, name2: String): Circuit =
circuit + (name1 -> circuit(name2)) + (name2 -> circuit(name1))

def changeInput(circuit: Circuit, prefix: String, value: Long): Circuit = {
val (a, b) = circuit.keys
.filter(_.startsWith(prefix))
.toSeq
.sorted
.foldLeft((circuit, value))({ case ((circuit, value), prefixName) =>
(circuit + (prefixName -> Wire.Input((value & 1) == 1L)), value >> 1)
})
assert(b == 0)
a
def withXValue(value: Long): Circuit = withInputValue("x", value)
def withYValue(value: Long): Circuit = withInputValue("y", value)
}

def parseInput(s: String): (String, Wire.Input) = s match {
Expand All @@ -75,12 +77,12 @@ object Day24 {
case s"$inputs\n\n$gates" =>
val inputMap = inputs.linesIterator.map(parseInput).toMap
val gateMap = gates.linesIterator.map(parseGate).toMap
inputMap ++ gateMap
Circuit(inputMap ++ gateMap)
}

def printCircuitDot(circuit: Circuit): Unit = {
println("digraph circuit {")
for ((name, wire) <- circuit) {
for ((name, wire) <- circuit.wireMap) {
wire match {
case Wire.Input(value) =>
println(s" $name;")
Expand All @@ -97,14 +99,14 @@ object Day24 {

def main(args: Array[String]): Unit = {
val circuit = parseCircuit(input)
println(getZValue(circuit))
val circuit2 = swap(swap(swap(swap(circuit, "z21", "nhn"), "tvb", "khg"), "z33", "gst"), "z12", "vdc")
println(circuit.zValue)
val circuit2 = circuit.swapped("z21", "nhn").swapped("tvb", "khg").swapped("z33", "gst").swapped("z12", "vdc")
printCircuitDot(circuit2)
println(getZValue(circuit2))
println(circuit2.zValue)
println("51401618891888")

val circuit3 = changeInput(changeInput(circuit2, "x", 0), "asdasd", 0)
println(getZValue(circuit3))
val circuit3 = circuit2.withXValue(0)
println(circuit3.zValue)

println(Seq("z21", "nhn", "tvb", "khg", "z33", "gst", "z12", "vdc").sorted.mkString(","))
// part 2: gst,khg,nhn,tvb,vdc,z12,z21,z33 - correct
Expand Down
6 changes: 3 additions & 3 deletions src/test/scala/eu/sim642/adventofcode2024/Day24Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ class Day24Test extends AnyFunSuite {
|tnw OR pbm -> gnj""".stripMargin

test("Part 1 examples") {
assert(getZValue(parseCircuit(exampleInput)) == 4)
assert(getZValue(parseCircuit(exampleInput2)) == 2024)
assert(parseCircuit(exampleInput).zValue == 4)
assert(parseCircuit(exampleInput2).zValue == 2024)
}

test("Part 1 input answer") {
assert(getZValue(parseCircuit(input)) == 51410244478064L)
assert(parseCircuit(input).zValue == 51410244478064L)
}
}

0 comments on commit 5b54798

Please sign in to comment.