Browse Source

Add solution for day six

Getty Ritter 4 years ago
parent
commit
caed2c3d3c
1 changed files with 127 additions and 0 deletions
  1. 127 0
      06/main.pony

+ 127 - 0
06/main.pony

@@ -0,0 +1,127 @@
+use "collections"
+use "files"
+use "format"
+use "itertools"
+
+class Orbit
+  let _name: String
+  var _orbits: Array[Orbit ref]
+
+  new create(n: String) =>
+    _name = n
+    _orbits = Array[Orbit]()
+
+  fun ref add(o: Orbit ref) =>
+    _orbits.push(o)
+
+  fun name(): String => _name
+
+  fun print(env: Env) =>
+    env.out.write(_name + ":")
+    for o in _orbits.values() do
+      env.out.write(" " + o.name())
+    end
+    env.out.print("")
+
+  fun checksum(path_len: USize): USize =>
+    var sum = path_len
+    for o in _orbits.values() do
+      sum = sum + o.checksum(path_len + 1)
+    end
+    sum
+
+  fun ref contains(n: String): Bool =>
+    (n == _name) or (Iter[Orbit](_orbits.values()).any({(o) => o.contains(n)}))
+
+  fun ref closest_parent(l: String, r: String): String ? =>
+    for o in _orbits.values() do
+      try
+        return o.closest_parent(l, r)?
+      end
+    end
+    if contains(l) and contains(r) then
+      return _name
+    end
+    error
+
+  fun ref find_distance(n: String, dist: USize = 0): USize ? =>
+    if n == _name then
+      return dist
+    end
+    for o in _orbits.values() do
+      try
+        return o.find_distance(n, dist + 1)?
+      end
+    end
+    error
+
+class System
+  var orbits: Map[String, Orbit]
+
+  new create(mapping: Array[(String, String)]) =>
+    orbits = Map[String, Orbit]()
+
+    orbits.insert("COM", Orbit("COM"))
+    for (inner_name, outer_name) in mapping.values() do
+      let outer = orbits.insert_if_absent(outer_name, Orbit(outer_name))
+      let inner = orbits.insert_if_absent(inner_name, Orbit(inner_name))
+      inner.add(outer)
+    end
+
+  fun print(env: Env) =>
+    for o in orbits.values() do
+      o.print(env)
+    end
+
+  fun checksum(): USize =>
+    try
+      orbits("COM")?.checksum(0)
+    else
+      0
+    end
+
+  fun ref closest_parent(l: String, r: String): (String | None) =>
+    try
+      orbits("COM")?.closest_parent(l, r)?
+    else
+      None
+    end
+
+  fun ref distance(parent: String, child: String): USize =>
+    try
+      orbits(parent)?.find_distance(child)?
+    else
+      0
+    end
+
+actor Main
+  new create(env: Env) =>
+    let caps = recover val FileCaps.>set(FileRead).>set(FileStat) end
+
+    let target_file = try env.args(1)? else "input.txt" end
+    try
+      with
+        file = OpenFile(FilePath(env.root as AmbientAuth, target_file, caps)?) as File
+      do
+      let mapping = Array[(String, String)]()
+      for line in file.lines() do
+        try
+          let sline = line.split(")")
+          mapping.push((sline(0)?, sline(1)?))
+        else
+          env.out.write("Failed to parse line: " + line.clone())
+        end
+      end
+      let s = System(mapping)
+      env.out.print("Checksum: " + Format.int[USize](s.checksum()))
+      s.print(env)
+      match s.closest_parent("YOU", "SAN")
+        | None => env.out.print("No connection between the two somehow?")
+        | let o: String =>
+        env.out.print("Closest parent between YOU and SAN is " + o)
+        let d1 = s.distance(o, "YOU")
+        let d2 = s.distance(o, "SAN")
+        env.out.print("Distance is " + Format.int[USize]((d1 + d2) - 2))
+      end
+      end
+    end