summaryrefslogtreecommitdiff
path: root/lib/AdventOfCode/Utils.rakumod
blob: 9abedb81575479bcfae49ec1518a78bfb51d1c96 (plain)
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
class Point {
    has Real $.x = 0;
    has Real $.y = 0;

    method Str(--> Str) {
        try { "<$.x, $.y>" } or "undefined"
    }
}

class Line {
    has Point $.p;
    has Point $.q;

    multi method new(Point $p, Point $q) {
        self.bless(:$p, :$q)
    }

    multi method new(Point :$p, Point :$q) {
        self.bless(:$p, :$q)
    }
}

sub intersection(Line $l1, Line $l2) is export {
    my $a1 = $l1.q.y - $l1.p.y;
    my $b1 = $l1.p.x - $l1.q.x;
    my $c1 = $a1 * $l1.p.x + $b1 * $l1.p.y;

    my $a2 = $l2.q.y - $l2.p.y;
    my $b2 = $l2.p.x - $l2.q.x;
    my $c2 = $a2 * $l2.p.x + $b2 * $l2.p.y;

    my $delta = $a1 * $b2 - $a2 * $b1;

    return Point.new(
        :x(($b2 * $c1 - $b1 * $c2) / $delta),
        :y(($a1 * $c2 - $a2 * $c1) / $delta)
    )
}

sub manhattan-distance(Point $p, Point $q) is export {
    abs($p.x - $q.x) + abs($p.y - $q.y)
}


class Wire is export {
    has Point @.points;

    submethod new(Str $input) {
        my @movements = $input.split(',');
        my @points;
        my $x = 0;
        my $y = 0;

        for @movements -> $move {
            if $move ~~ /$<direction> = [ <[ UDLR ]> ] $<size> = [ \d+]/ {
                given $<direction> {
                    when "U" { $y += $<size>.Int }
                    when "D" { $y += -$<size>.Int }
                    when "L" { $x += -$<size>.Int }
                    when "R" { $x += $<size>.Int }
                }
                @points.append: Point.new(:$x, :$y);
            }
        }

        self.bless(:@points);
    }

    method segments {
        @.points[0..^*-1] Z @.points[1..*]
    }

    method lines {
        gather for self.segments -> $s {
            take Line.new($s[0], $s[1]);
        }
    }
}