123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- use "collections"
- use "files"
- use "itertools"
- primitive Math
- fun gcd(x: ISize, y: ISize): ISize =>
- var a = x
- var b = y
- var d: USize = 0
- while ((a % 2) == 0) and ((b % 2) == 0) do
- a = a / 2
- b = b / 2
- d = d + 1
- end
- while a != b do
- if (a % 2) == 0 then a = a / 2
- elseif (b % 2) == 0 then b = b / 2
- elseif a > b then a = (a - b) / 2
- else b = (b - a) / 2
- end
- end
- if d > 0 then
- a * (2 << (d-1)).isize()
- else
- a
- end
- // A basic two-dimensional point class
- class val Point is Hashable
- let x: ISize
- let y: ISize
- new val create(_x: ISize, _y: ISize) =>
- x = _x
- y = _y
- // because we want to use this as a key in a hashmap
- fun hash(): USize =>
- // hey this is probably bad, huh?
- (x.hash() + y.hash()).usize()
- fun eq(other: Point): Bool =>
- (x == other.x) and (y == other.y)
- fun ne(other: Point): Bool => not eq(other)
- fun sub(other: Point): Point =>
- Point(x - other.x, y - other.y)
- fun simplify(): Point =>
- let d = Math.gcd(x, y)
- Point(x/d, y/d)
- actor Asteroid
- let _loc: Point
- let _field: AsteroidField tag
- let _io: IO tag
- let _visible: Map[Point, Point] = Map[Point, Point]()
- new create(p: Point, field: AsteroidField tag, io: IO tag) =>
- _loc = p
- _field = field
- _io = io
- be print() =>
- _io.print("Asteroid(" + _loc.x.string() + ", " + _loc.y.string() + ")")
- be find_visible(loc: Point, other: Asteroid) =>
- None
- actor AsteroidField
- var _io: IO
- var _locs: Set[Point] = Set[Point]()
- new create(io: IO) =>
- _io = io
- be register(p: Point) =>
- _locs.set(p)
- be print() =>
- _io.print("whoo")
- actor IO
- let _env: Env
- new create(env: Env) =>
- _env = env
- be print(str: String) =>
- _env.out.print(str)
- actor Main
- new create(env: Env) =>
- let io = IO(env)
- let field = AsteroidField(io)
- build_field(env, io, field)
- field.print()
- fun build_field(env: Env, io: IO, field: AsteroidField): (Array[Asteroid] | None) =>
- let caps = recover val FileCaps.>set(FileRead).>set(FileStat) end
- let target_file = try env.args(1)? else "input.txt" end
- try
- var asteroids: Array[Asteroid] = Array[Asteroid]()
- with
- file = OpenFile(FilePath(env.root as AmbientAuth, target_file, caps)?) as File
- do
- for (y, line) in Iter[String](file.lines()).enum() do
- for (x, char) in Iter[U8](line.values()).enum() do
- if char == '#' then
- let p = Point(x.isize(), y.isize())
- field.register(p)
- asteroids.push(Asteroid(p, field, io))
- end
- end
- end
- end
- for a in asteroids.values() do
- a.print()
- end
- asteroids
- else
- env.err.print("Couldn't read file `" + target_file + "`")
- env.exitcode(99)
- end
|