main.pony 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. use "collections"
  2. use "files"
  3. use "itertools"
  4. primitive Math
  5. fun gcd(x: ISize, y: ISize): ISize =>
  6. var a = x
  7. var b = y
  8. var d: USize = 0
  9. while ((a % 2) == 0) and ((b % 2) == 0) do
  10. a = a / 2
  11. b = b / 2
  12. d = d + 1
  13. end
  14. while a != b do
  15. if (a % 2) == 0 then a = a / 2
  16. elseif (b % 2) == 0 then b = b / 2
  17. elseif a > b then a = (a - b) / 2
  18. else b = (b - a) / 2
  19. end
  20. end
  21. if d > 0 then
  22. a * (2 << (d-1)).isize()
  23. else
  24. a
  25. end
  26. // A basic two-dimensional point class
  27. class val Point is Hashable
  28. let x: ISize
  29. let y: ISize
  30. new val create(_x: ISize, _y: ISize) =>
  31. x = _x
  32. y = _y
  33. // because we want to use this as a key in a hashmap
  34. fun hash(): USize =>
  35. // hey this is probably bad, huh?
  36. (x.hash() + y.hash()).usize()
  37. fun eq(other: Point): Bool =>
  38. (x == other.x) and (y == other.y)
  39. fun ne(other: Point): Bool => not eq(other)
  40. fun sub(other: Point): Point =>
  41. Point(x - other.x, y - other.y)
  42. fun simplify(): Point =>
  43. let d = Math.gcd(x, y)
  44. Point(x/d, y/d)
  45. actor Asteroid
  46. let _loc: Point
  47. let _field: AsteroidField tag
  48. let _io: IO tag
  49. let _visible: Map[Point, Point] = Map[Point, Point]()
  50. new create(p: Point, field: AsteroidField tag, io: IO tag) =>
  51. _loc = p
  52. _field = field
  53. _io = io
  54. be print() =>
  55. _io.print("Asteroid(" + _loc.x.string() + ", " + _loc.y.string() + ")")
  56. be find_visible(loc: Point, other: Asteroid) =>
  57. None
  58. actor AsteroidField
  59. var _io: IO
  60. var _locs: Set[Point] = Set[Point]()
  61. new create(io: IO) =>
  62. _io = io
  63. be register(p: Point) =>
  64. _locs.set(p)
  65. be print() =>
  66. _io.print("whoo")
  67. actor IO
  68. let _env: Env
  69. new create(env: Env) =>
  70. _env = env
  71. be print(str: String) =>
  72. _env.out.print(str)
  73. actor Main
  74. new create(env: Env) =>
  75. let io = IO(env)
  76. let field = AsteroidField(io)
  77. build_field(env, io, field)
  78. field.print()
  79. fun build_field(env: Env, io: IO, field: AsteroidField): (Array[Asteroid] | None) =>
  80. let caps = recover val FileCaps.>set(FileRead).>set(FileStat) end
  81. let target_file = try env.args(1)? else "input.txt" end
  82. try
  83. var asteroids: Array[Asteroid] = Array[Asteroid]()
  84. with
  85. file = OpenFile(FilePath(env.root as AmbientAuth, target_file, caps)?) as File
  86. do
  87. for (y, line) in Iter[String](file.lines()).enum() do
  88. for (x, char) in Iter[U8](line.values()).enum() do
  89. if char == '#' then
  90. let p = Point(x.isize(), y.isize())
  91. field.register(p)
  92. asteroids.push(Asteroid(p, field, io))
  93. end
  94. end
  95. end
  96. end
  97. for a in asteroids.values() do
  98. a.print()
  99. end
  100. asteroids
  101. else
  102. env.err.print("Couldn't read file `" + target_file + "`")
  103. env.exitcode(99)
  104. end