-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolutionb.scala
89 lines (81 loc) · 2.98 KB
/
solutionb.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import scala.util.matching.Regex
trait Node
case class In() extends Node
case class Root(left: String, right: String) extends Node
case class Op(
op: (Long, Long) => Long,
leftInv: (Long, Long) => Long,
rightInv: (Long, Long) => Long,
left: String,
right: String,
) extends Node
case class Num(value: Long) extends Node
object Solution {
val inPattern: Regex = """^(humn): .*$""".r
val rootPattern: Regex = """^(root): (\w+) . (\w+)$""".r
val addPattern: Regex = """^(\w+): (\w+) \+ (\w+)$""".r
val subPattern: Regex = """^(\w+): (\w+) - (\w+)$""".r
val mulPattern: Regex = """^(\w+): (\w+) \* (\w+)$""".r
val divPattern: Regex = """^(\w+): (\w+) / (\w+)$""".r
val numPattern: Regex = """^(\w+): (\d+)$""".r
def known(nodes: Map[String, Node], current: String): Boolean =
nodes(current) match {
case In() => false
case Op(_, _, _, left, right) => known(nodes, left) && known(nodes, right)
case Num(_) => true
}
def evaluate(nodes: Map[String, Node], current: String): Long =
nodes(current) match {
case Op(op, _, _, left, right) =>
op(evaluate(nodes, left), evaluate(nodes, right))
case Num(value) => value
}
def solve(nodes: Map[String, Node], current: String, other: Long): Long =
nodes(current) match {
case In() => other
case Op(_, leftInv, rightInv, left, right) =>
if (known(nodes, left)) {
val subResult = evaluate(nodes, left)
val unknown = rightInv(other, subResult)
solve(nodes, right, unknown)
} else {
val subResult = evaluate(nodes, right)
val unknown = leftInv(other, subResult)
solve(nodes, left, unknown)
}
case Num(value) => value
}
def solve(nodes: Map[String, Node], current: String): Long =
nodes(current) match {
case Root(left, right) =>
if (known(nodes, left)) {
val subResult = evaluate(nodes, left)
solve(nodes, right, subResult)
} else {
val subResult = evaluate(nodes, right)
solve(nodes, left, subResult)
}
}
def main(args: Array[String]): Unit = {
val nodes = io.Source.stdin.getLines().map { line =>
line match {
case inPattern(id) =>
(id, In())
case rootPattern(id, left, right) =>
(id, Root(left, right))
case addPattern(id, left, right) =>
(id, Op(_ + _, _ - _, (other, subResult) => other - subResult, left, right))
case subPattern(id, left, right) =>
(id, Op(_ - _, _ + _, (other, subResult) => subResult - other, left, right))
case mulPattern(id, left, right) =>
(id, Op(_ * _, _ / _, (other, subResult) => other / subResult, left, right))
case divPattern(id, left, right) =>
(id, Op(_ / _, _ * _, (other, subResult) => subResult / other, left, right))
case numPattern(id, value) =>
(id, Num(value.toLong))
}
}.toMap
val result = solve(nodes, "root")
println(result)
}
}