Code for the Advent of Code event
aoc
advent-of-code
1# frozen_string_literal: true
2
3require_relative 'math'
4
5module AoC
6 # A 2D point.
7 class Point2
8 # @return [Numeric]
9 attr_reader :x
10
11 # @return [Numeric]
12 attr_reader :y
13
14 # @return [Numeric]
15 attr_reader :hash
16
17 # Creates a new 2D point.
18 # @param x [Numeric] The X position.
19 # @param y [Numeric] The Y position.
20 def initialize(x, y)
21 @x = x
22 @y = y
23 @hash = AoC::Math.cantor2(x, y)
24 end
25
26 # Creates a new 2D point.
27 # @param x [Numeric] The X position.
28 # @param y [Numeric] The Y position.
29 # @return [Point2]
30 def self.[](x, y) = new x, y
31
32 # @return [self]
33 def +@ = self
34
35 # @return [Point2]
36 def -@ = self.class.new(-x, -y)
37
38 # @param other [Point2]
39 # @return [Point2]
40 def +(other) = self.class.new x + other.x, y + other.y
41
42 # @param other [Point2]
43 # @return [Point2]
44 def -(other) = self.class.new x - other.x, y - other.y
45
46 # @param other [Point2]
47 # @return [Point2]
48 def *(other) = self.class.new x * other, y * other
49
50 # Divides each component of the point with `other`.
51 # Raises an error if the parameter is not a {Numeric}.
52 # @param other [Numeric]
53 # @return [Point2]
54 def /(other)
55 case other
56 when Numeric
57 self.class.new x / other, y / other
58 when Point2
59 raise 'Point2 cannot be divided by another Point2, only a number'
60 else
61 raise "Unsupported type in division: #{other.class}"
62 end
63 end
64
65 # Checks for equality with another {Point2}.
66 # @param other [Point2]
67 # @return [Boolean]
68 def ==(other) = hash == other.hash
69
70 # Checks for equality with another {Point2}.
71 # @param other [Point2]
72 # @return [Boolean]
73 def eql?(other) = hash.eql? other.hash
74
75 # Gets a string representation of the object.
76 # @return [String]
77 def to_s = "(#{x}, #{y})"
78
79 # Gets a debug-friendly string representation of the object.
80 # @return [String]
81 def inspect = "#{self.class.name}(#{x}, #{y})"
82 end
83end