-
Notifications
You must be signed in to change notification settings - Fork 0
/
day12.adb
149 lines (131 loc) · 4.36 KB
/
day12.adb
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
with Ada.Text_IO;
procedure Day12 is
type Action_T is
(N, E, S, W, L, R, F);
subtype Direction_T is Action_T range N .. W;
subtype Rotation_T is Action_T range L .. R;
type Position_T is record
X : Integer;
Y : Integer;
Dir : Direction_T;
end record;
Zero_Position : constant Position_T := (0, 0, E);
Position : Position_T := Zero_Position;
Action : Action_T;
Units : Integer;
Position_P2 : Position_T := Zero_Position;
Waypoint : Position_T := (10, 1, E);
procedure Move
(Position : in out Position_T;
Direction : in Direction_T;
Amount : in Integer)
is
begin
case Direction is
when N =>
Position.Y := Position.Y + Amount;
when S =>
Position.Y := Position.Y - Amount;
when E =>
Position.X := Position.X + Amount;
when W =>
Position.X := Position.X - Amount;
end case;
end Move;
procedure Rotate
(Position : in out Position_T;
Rotation : in Rotation_T;
Amount : in Integer)
is
Rotation_Amount : constant Integer := Amount / 90;
begin
case Rotation is
when L =>
Position.Dir := Direction_T'Val ((Direction_T'Pos (Position.Dir) - Rotation_Amount) mod 4);
when R =>
Position.Dir := Direction_T'Val ((Direction_T'Pos (Position.Dir) + Rotation_Amount) mod 4);
end case;
end Rotate;
procedure Rotate_2
(Position : in out Position_T;
Rotation : in Rotation_T;
Amount : in Integer)
is
Initial_Position : constant Position_T := Position;
begin
case Rotation is
when L =>
if Amount = 90 then
Position.X := -Initial_Position.Y;
Position.Y := Initial_Position.X;
elsif Amount = 180 then
Position.X := -Initial_Position.X;
Position.Y := -Initial_Position.Y;
elsif Amount = 270 then
Position.X := Initial_Position.Y;
Position.Y := -Initial_Position.X;
end if;
when R =>
if Amount = 90 then
Position.X := Initial_Position.Y;
Position.Y := -Initial_Position.X;
elsif Amount = 180 then
Position.X := -Initial_Position.X;
Position.Y := -Initial_Position.Y;
elsif Amount = 270 then
Position.X := -Initial_Position.Y;
Position.Y := Initial_Position.X;
end if;
end case;
end Rotate_2;
procedure Move_2
(Position : in out Position_T;
Waypoint : in Position_T;
Amount : in Integer)
is
begin
Position.X := Position.X + (Amount * Waypoint.X);
Position.Y := Position.Y + (Amount * Waypoint.Y);
end Move_2;
begin
loop
declare
Line : constant String := Ada.Text_IO.Get_Line;
begin
Action := Action_T'Value (Line (1..1));
Units := Integer'Value (Line (2 .. Line'Length));
case Action is
when N .. W =>
Move -- Part 1
(Position => Position,
Direction => Action,
Amount => Units);
Move -- Part 2
(Position => Waypoint,
Direction => Action,
Amount => Units);
when L .. R =>
Rotate -- Part 1
(Position => Position,
Rotation => Action,
Amount => Units);
Rotate_2 -- Part 2
(Position => Waypoint,
Rotation => Action,
Amount => Units);
when F =>
Move -- Part 1
(Position => Position,
Direction => Position.Dir,
Amount => Units);
Move_2 -- Part 2
(Position => Position_P2,
Waypoint => Waypoint,
Amount => Units);
end case;
end;
exit when Ada.Text_IO.End_Of_File;
end loop;
Ada.Text_IO.Put_Line ("Manhattan: " & Integer (abs (Position.X) + abs (Position.Y))'Img);
Ada.Text_IO.Put_Line ("Manhattan2:" & Integer (abs (Position_P2.X) + abs (Position_P2.Y))'Img);
end Day12;