Skip to content

Commit 15cde6c

Browse files
author
avokadoen
committed
solve day04 in zig
1 parent 659648c commit 15cde6c

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed

days/day-04/solutions/day04.zig

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
const std = @import("std");
2+
const mem = std.mem;
3+
const io = std.io;
4+
const ArrayList = std.ArrayList;
5+
const Allocator = std.mem.Allocator;
6+
7+
const MAX_FILE_SIZE = 30_000;
8+
9+
const PassportField = enum(u8) {
10+
invalid = 0b00000000,
11+
cid = 0b00000001,
12+
byr = 0b00000010,
13+
iyr = 0b00000100,
14+
eyr = 0b00001000,
15+
hgt = 0b00010000,
16+
hcl = 0b00100000,
17+
ecl = 0b01000000,
18+
pid = 0b10000000,
19+
required = 0b11111110,
20+
21+
inline fn fromString(str: []const u8) PassportField {
22+
23+
if (mem.eql(u8, str, "byr")) return PassportField.byr;
24+
if (mem.eql(u8, str, "iyr")) return PassportField.iyr;
25+
if (mem.eql(u8, str, "eyr")) return PassportField.eyr;
26+
if (mem.eql(u8, str, "hgt")) return PassportField.hgt;
27+
if (mem.eql(u8, str, "hcl")) return PassportField.hcl;
28+
if (mem.eql(u8, str, "ecl")) return PassportField.ecl;
29+
if (mem.eql(u8, str, "pid")) return PassportField.pid;
30+
if (mem.eql(u8, str, "cid")) return PassportField.cid;
31+
32+
return PassportField.invalid;
33+
}
34+
35+
fn validate(self: PassportField, field_value: []const u8) !bool {
36+
// TODO: investigate if zig has regex in std (would probably be slower though)
37+
38+
switch(self) {
39+
.byr, .iyr, .eyr => {
40+
const value: i32 = try std.fmt.parseInt(i32, field_value, 10);
41+
42+
switch(self) {
43+
.byr => return value >= 1920 and value <= 2002,
44+
.iyr => return value >= 2010 and value <= 2020,
45+
.eyr => return value >= 2020 and value <= 2030,
46+
else => unreachable,
47+
}
48+
},
49+
50+
.hgt => {
51+
const m_index = field_value.len - 2;
52+
53+
const measure = field_value[m_index..field_value.len];
54+
const value = try std.fmt.parseInt(i32, field_value[0..m_index], 10);
55+
56+
if (mem.eql(u8, measure, "cm")) {
57+
return value >= 150 and value <= 193;
58+
}
59+
60+
if (mem.eql(u8, measure, "in")) {
61+
return value >= 59 and value <= 76;
62+
}
63+
64+
return false;
65+
},
66+
67+
.hcl => {
68+
if (field_value[0] != '#') return false;
69+
70+
var i: usize = 1;
71+
while (i < field_value.len) : (i += 1) {
72+
if (i > 6) return false;
73+
74+
switch (field_value[i]) {
75+
'a'...'f', '0'...'9' => continue,
76+
else => return false,
77+
}
78+
}
79+
80+
return true;
81+
},
82+
83+
.ecl => {
84+
if (mem.eql(u8, field_value, "amb")
85+
or mem.eql(u8, field_value, "blu")
86+
or mem.eql(u8, field_value, "brn")
87+
or mem.eql(u8, field_value, "gry")
88+
or mem.eql(u8, field_value, "grn")
89+
or mem.eql(u8, field_value, "hzl")
90+
or mem.eql(u8, field_value, "oth")
91+
) return true;
92+
93+
return false;
94+
},
95+
96+
.pid => {
97+
if (field_value.len != 9) return false;
98+
99+
var i: usize = 0;
100+
while(i < field_value.len) : (i += 1) {
101+
switch (field_value[i]) {
102+
'0'...'9' => continue,
103+
else => return false,
104+
}
105+
}
106+
107+
return true;
108+
},
109+
110+
else => return true,
111+
}
112+
113+
unreachable;
114+
}
115+
};
116+
117+
118+
pub inline fn countValidPass(bytes: []u8) struct {naive: u32, improved: u32} {
119+
var maybe_valid_passports: u32 = 0;
120+
var valid_passports: u32 = 0;
121+
122+
var fields_found_map: u8 = 0;
123+
var fields_valid: bool = true;
124+
var lines = mem.split(bytes, "\n");
125+
126+
line_read: while (lines.next()) |line| {
127+
128+
if (line.len <= 2) {
129+
if (fields_found_map >= @enumToInt(PassportField.required)) {
130+
maybe_valid_passports += 1;
131+
valid_passports += @boolToInt(fields_valid);
132+
}
133+
134+
fields_valid = true;
135+
fields_found_map = @enumToInt(PassportField.invalid);
136+
continue;
137+
}
138+
139+
var words = mem.split(line, " ");
140+
while (words.next()) |word| {
141+
var i: usize = 0;
142+
while (i < word.len) : (i += 1) {
143+
if (word[i] == ':') break;
144+
}
145+
146+
const field = PassportField.fromString(word[0..i]);
147+
fields_found_map |= @enumToInt(field);
148+
149+
const field_value = word[i + 1..word.len];
150+
const valid: bool = field.validate(field_value) catch false;
151+
fields_valid = fields_valid and valid;
152+
}
153+
}
154+
155+
return .{
156+
.naive = maybe_valid_passports,
157+
.improved = valid_passports
158+
};
159+
}
160+
161+
162+
pub fn main() anyerror!void {
163+
const in = std.io.getStdIn().reader();
164+
const stdout = std.io.getStdOut().writer();
165+
166+
var bytes: [MAX_FILE_SIZE]u8 = undefined;
167+
const length = try in.readAll(&bytes);
168+
169+
var valid_count = countValidPass(bytes[0..length]);
170+
171+
try stdout.print("{}\n", .{valid_count.naive});
172+
try stdout.print("{}\n", .{valid_count.improved});
173+
}

days/day-04/test.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ D=$(dirname $(realpath $0))
66
echo
77
echo "--- Day 4: Passport Processing ---"
88
$D/../../languages/c.sh $D/input.txt $D/output.txt $D/solutions/day04.c
9+
$D/../../languages/zig.sh $D/input.txt $D/output.txt $D/solutions/day04.zig
910
$D/../../languages/sml.sh $D/input.txt $D/output.txt $D/solutions/day04.sml
1011
$D/../../languages/go.sh $D/input.txt $D/output.txt $D/solutions/day04.tholok97.go
1112
$D/../../languages/python.sh $D/input.txt $D/output.txt $D/solutions/day04.klyve.py

0 commit comments

Comments
 (0)