-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday4.adb
196 lines (142 loc) · 5.13 KB
/
day4.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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
with Ada.Integer_Text_IO;
with Ada.IO_Exceptions;
with Ada.Text_IO;
with Ada.Strings.Fixed;
procedure Day4 is
type Field is
(byr,
iyr,
eyr,
hgt,
hcl,
ecl,
pid,
cid);
package Field_IO is new Ada.Text_IO.Enumeration_IO (Field);
type Field_Present_T is Array (Field) of Boolean;
Null_Field_Present_C : constant Field_Present_T :=
(others => False);
Valid_Passport_C : constant Field_Present_T :=
(others => True);
Valid_Passport_CID_C : constant Field_Present_T :=
( cid => False,
others => True);
Token : Field;
Line_Pos : Natural;
Col : Natural := 0;
Field_Present_P1 : Field_Present_T := Null_Field_Present_C;
Field_Present_P2 : Field_Present_T := Null_Field_Present_C;
Valid_Count_P1 : Natural := 0;
Valid_Count_P2 : Natural := 0;
function Check_Value
(Line : String;
Token : Field)
return Boolean
is
Trim_Line : String := Line;
Line_Pos : Natural := 0;
Value : Natural;
type Eye_Colour is
(amb, blu, brn, gry, grn, hzl, oth);
package Eye_O is new Ada.Text_IO.Enumeration_IO (Eye_Colour);
Eye : Eye_Colour;
subtype Byr_Valid is Positive range 1920 .. 2002;
subtype Iyr_Valid is Positive range 2010 .. 2020;
subtype Eyr_Valid is Positive range 2020 .. 2030;
subtype Height_CM_Valid is Positive range 150 .. 193;
subtype Height_IN_Valid is Positive range 59 .. 76;
subtype PID_Valid is Natural range 0 .. 999999999;
Result : Boolean := False;
begin
Ada.Strings.Fixed.Delete (Trim_Line, 1, 4);
case Token is
when Byr =>
Ada.Integer_Text_IO.Get(Trim_Line, Value, Line_Pos);
Result := Value in Byr_Valid;
when Iyr =>
Ada.Integer_Text_IO.Get(Trim_Line, Value, Line_Pos);
Result := Value in Iyr_Valid;
when Eyr =>
Ada.Integer_Text_IO.Get(Trim_Line, Value, Line_Pos);
Result := Value in Eyr_Valid;
when Hgt =>
Ada.Integer_Text_IO.Get(Trim_Line, Value, Line_Pos);
Line_Pos := Ada.Strings.Fixed.Index(Line, "cm");
if Line_Pos /= 0 and then Value in Height_CM_Valid then
Result := True;
end if;
Line_Pos := Ada.Strings.Fixed.Index(Line, "in");
if Line_Pos /= 0 and then Value in Height_IN_Valid then
Result := True;
end if;
when Hcl =>
if Trim_Line (1) = '#' and then Trim_Line'Length >= 7 then
for I in 2 .. 7 loop
if Trim_Line (I) not in '0' .. '9' and then
Trim_Line (I) not in 'a' .. 'f'
then
exit;
end if;
-- if we get here, then it was valid.
Result := True;
end loop;
end if;
when Ecl =>
Eye_O.Get (Trim_Line, Eye, Line_Pos);
-- This is guarded by the exception anyway, but I might get rid of it.
Result := Eye'Valid;
when Pid =>
Ada.Integer_Text_IO.Get(Trim_Line, Value, Line_Pos);
Result := Value in PID_Valid and then Line_Pos = 9;
when Cid =>
null;
end case;
return Result;
exception
when E : Ada.IO_Exceptions.Data_Error =>
return False;
end Check_Value;
begin
loop
declare
Line : String := Ada.Text_IO.Get_Line;
begin
if Line'Length > 0 then
Col := 0;
while Col < Line'Length loop
Field_IO.Get(Line, Token, Line_Pos);
Field_Present_P1 (Token) := True;
Field_Present_P2 (Token) := Check_Value (Line, Token);
Line_Pos := Ada.Strings.Fixed.Index(Line, " ", Line_Pos);
Ada.Strings.Fixed.Delete (Line, 1, Line_Pos);
Col := Col + Line_Pos;
exit when Line_Pos = 0;
end loop;
elsif Line'Length = 0 then
-- End of record - check status
if Field_Present_P1 = Valid_Passport_C or else
Field_Present_P1 = Valid_Passport_CID_C then
Valid_Count_P1 := Valid_Count_P1 + 1;
end if;
if Field_Present_P2 = Valid_Passport_C or else
Field_Present_P2 = Valid_Passport_CID_C then
Valid_Count_P2 := Valid_Count_P2 + 1;
end if;
Field_Present_P1 := Null_Field_Present_C;
Field_Present_P2 := Null_Field_Present_C;
end if;
end;
exit when Ada.Text_IO.End_Of_File;
end loop;
-- Check final line.
if Field_Present_P1 = Valid_Passport_C or else
Field_Present_P1 = Valid_Passport_CID_C then
Valid_Count_P1 := Valid_Count_P1 + 1;
end if;
if Field_Present_P2 = Valid_Passport_C or else
Field_Present_P2 = Valid_Passport_CID_C then
Valid_Count_P2 := Valid_Count_P2 + 1;
end if;
Ada.Text_IO.Put_Line("Valid Part 1: " & Valid_Count_P1'Img);
Ada.Text_IO.Put_Line("Valid Part 2: " & Valid_Count_P2'Img);
end Day4;