• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Vest / aoc-rust / 4005027531

pending completion
4005027531

Pull #19

github

GitHub
Merge 74f46dcbf into 0e0e3157b
Pull Request #19: Updated versions

2556 of 3992 branches covered (64.03%)

Branch coverage included in aggregate %.

1560 of 1560 new or added lines in 44 files covered. (100.0%)

5981 of 6247 relevant lines covered (95.74%)

624811.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.52
/adv2020/src/day4.rs
1
use itertools::Itertools;
2

3
pub fn count_simple_results(input: &str) -> usize {
2✔
4
    let passports = parse_input(input);
2✔
5
    passports.iter().filter(|pass| has_all_data(pass)).count()
6✔
6
}
2✔
7

8
pub fn count_advanced_results(input: &str) -> usize {
3✔
9
    let passports = parse_input(input);
3✔
10
    passports
3✔
11
        .iter()
12
        .filter(|pass| has_all_data(pass) && is_valid_advanced(pass))
8!
13
        .count()
14
}
3✔
15

16
fn parse_input(input: &str) -> Vec<String> {
6✔
17
    input
6✔
18
        .lines()
19
        .group_by(|elt| elt.is_empty())
42✔
20
        .into_iter()
21
        .filter(|(key, _)| !key)
24✔
22
        .map(|(_, group)| {
14✔
23
            group
14✔
24
                .collect_vec()
25
                .join(" ")
26
                .split_whitespace()
27
                .filter(|split| !split.is_empty())
92✔
28
                .join(" ")
29
        })
14✔
30
        .collect()
31
}
6✔
32

33
fn has_all_data(pass: &str) -> bool {
16✔
34
    pass.split_whitespace()
16✔
35
        .filter(|pair| {
116✔
36
            pair.starts_with("byr:")
116✔
37
                || pair.starts_with("iyr:")
102✔
38
                || pair.starts_with("eyr:")
86✔
39
                || pair.starts_with("hgt:")
70✔
40
                || pair.starts_with("hcl:")
56✔
41
                || pair.starts_with("ecl:")
40✔
42
                || pair.starts_with("pid:")
24✔
43
        })
116✔
44
        .count()
45
        >= 7
46
}
16✔
47

48
fn is_valid_advanced(pass: &str) -> bool {
12✔
49
    pass.split_whitespace()
12✔
50
        .filter(|part| {
89✔
51
            let pair: Vec<&str> = part.split(|c: char| c == ':').collect();
883✔
52

53
            if pair.len() != 2 {
89✔
54
                return false;
1✔
55
            }
56

57
            let [field, value_str] = [pair[0], pair[1]];
88✔
58
            let value = value_str.parse::<usize>();
88✔
59

60
            match field {
61
                "byr" if value.is_ok() => (1920..=2002usize).contains(&value.unwrap()),
88!
62

63
                "iyr" if value.is_ok() => (2010..=2020usize).contains(&value.unwrap()),
76!
64

65
                "eyr" if value.is_ok() => (2020..=2030usize).contains(&value.unwrap()),
65!
66

67
                "hgt" if value.is_err() && is_height(value_str) => true,
53✔
68

69
                "hcl" if is_hex_color(value_str) => true,
45✔
70

71
                "ecl" if is_eye_color(value_str) => true,
36✔
72

73
                "pid" if is_pid(value_str) => true,
26✔
74

75
                _ => false,
18✔
76
            }
77
        })
89✔
78
        .count()
79
        >= 7
80
}
12✔
81

82
fn is_hex_color(color: &str) -> bool {
17✔
83
    color
17✔
84
        .chars()
85
        .enumerate()
86
        .filter(|c: &(usize, char)| match c.0 {
115✔
87
            0 => c.1 == '#',
17✔
88
            1..=6 => "0123456789abcdefABCDEF".contains(c.1),
98!
89
            _ => false,
×
90
        })
115✔
91
        .count()
92
        == 7
93
}
17✔
94

95
fn is_eye_color(color: &str) -> bool {
12✔
96
    match color {
97
        "amb" | "blu" | "brn" | "gry" | "grn" | "hzl" | "oth" => true,
12!
98
        _ => false,
2✔
99
    }
100
}
12✔
101

102
fn is_pid(input: &str) -> bool {
18✔
103
    let value = input.parse::<usize>();
18✔
104

105
    value.is_ok() && input.len() == 9
18✔
106
}
18✔
107

108
fn is_height(input: &str) -> bool {
15✔
109
    input.len() > 2
30!
110
        && (input.ends_with("cm")
23✔
111
            && (150..=193).contains(&input[..input.len() - 2].parse::<i32>().unwrap_or(0))
10✔
112
            || (input.ends_with("in")
8✔
113
                && (59..=76).contains(&input[..input.len() - 2].parse::<i32>().unwrap_or(0))))
4✔
114
}
15✔
115

116
#[cfg(test)]
117
mod tests {
118
    use super::*;
119

120
    #[test]
121
    fn test_answers() {
2✔
122
        assert_eq!(
1✔
123
            count_simple_results(
1!
124
                r#"ecl:gry pid:860033327 eyr:2020 hcl:#fffffd
125
                                              byr:1937 iyr:2017 cid:147 hgt:183cm
126

127
                                              iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884
128
                                              hcl:#cfa07d byr:1929
129

130
                                              hcl:#ae17e1 iyr:2013
131
                                              eyr:2024
132
                                              ecl:brn pid:760753108 byr:1931
133
                                              hgt:179cm
134

135
                                              hcl:#cfa07d eyr:2025 pid:166559648
136
                                              iyr:2011 ecl:brn hgt:59in"#
137
            ),
138
            2
139
        );
140

141
        assert_eq!(
1✔
142
            count_advanced_results(
1!
143
                r#"eyr:1972 cid:100
144
                                                hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926
145

146
                                                iyr:2019
147
                                                hcl:#602927 eyr:1967 hgt:170cm
148
                                                ecl:grn pid:012533040 byr:1946
149

150
                                                hcl:dab227 iyr:2012
151
                                                ecl:brn hgt:182cm pid:021572410 eyr:2020 byr:1992 cid:277
152

153
                                                hgt:59cm ecl:zzz
154
                                                eyr:2038 hcl:74454a iyr:2023:iyr:2023
155
                                                pid:3556412378 byr:2007"#
156
            ),
157
            0
158
        );
159

160
        assert_eq!(
1✔
161
            count_advanced_results(
1!
162
                r#"pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980
163
                                                hcl:#623a2f
164

165
                                                eyr:2029 ecl:blu cid:129 byr:1989
166
                                                iyr:2014 pid:896056539 hcl:#a97842 hgt:165cm
167

168
                                                hcl:#888785
169
                                                hgt:164cm byr:2001 iyr:2015 cid:88
170
                                                pid:545766238 ecl:hzl
171
                                                eyr:2022
172

173
                                                iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719"#
174
            ),
175
            4
176
        );
177
    }
2✔
178

179
    #[test]
180
    fn test_parse_input() {
2✔
181
        let result = parse_input("abc\ndef\n\n  hij   klm");
1✔
182
        assert_eq!(result[0], String::from("abc def"));
1!
183
        assert_eq!(result[1], String::from("hij klm"));
1!
184
    }
2✔
185

186
    #[test]
187
    fn test_is_hex_color() {
2✔
188
        assert!(is_hex_color("#123abc"));
1!
189
        assert!(is_hex_color("#def890"));
1!
190
        assert!(!is_hex_color("def890"));
1!
191
        assert!(!is_hex_color("def890#"));
1!
192
        assert!(!is_hex_color("#defgab"));
1!
193
    }
2✔
194

195
    #[test]
196
    fn test_has_all_data() {
2✔
197
        assert!(has_all_data(
1!
198
            "ecl:gry pid:860033327 eyr:2020 hcl:#fffffd byr:1937 iyr:2017 cid:147 hgt:183cm"
199
        ));
200
        assert!(!has_all_data(
1!
201
            "iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884 hcl:#cfa07d byr:1929"
202
        ));
203
        assert!(has_all_data(
1!
204
            "hcl:#ae17e1 iyr:2013 eyr:2024 ecl:brn pid:760753108 byr:1931 hgt:179cm"
205
        ));
206
        assert!(!has_all_data(
1!
207
            "hcl:#cfa07d eyr:2025 pid:166559648 iyr:2011 ecl:brn hgt:59in"
208
        ));
209
    }
2✔
210

211
    #[test]
212
    fn test_is_valid_advanced() {
2✔
213
        assert!(is_valid_advanced(
1!
214
            "pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980 hcl:#623a2f"
215
        ));
216
        assert!(!is_valid_advanced(
1!
217
            "eyr:1972 cid:100 hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926"
218
        ));
219
        assert!(is_valid_advanced(
1!
220
            "iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719"
221
        ));
222
        assert!(!is_valid_advanced(
1!
223
            "hgt:59cm ecl:zzz eyr:2038 hcl:74454a iyr:2023 pid:3556412378 byr:2007"
224
        ));
225
    }
2✔
226

227
    #[test]
228
    fn test_is_pid() {
2✔
229
        assert!(is_pid("087499704"));
1!
230
        assert!(is_pid("896056539"));
1!
231
        assert!(is_pid("545766238"));
1!
232
        assert!(is_pid("093154719"));
1!
233

234
        assert!(!is_pid("186cm"));
1!
235
        assert!(!is_pid("3556412378"));
1!
236
    }
2✔
237

238
    #[test]
239
    fn test_is_height() {
2✔
240
        assert!(is_height("60in"));
1!
241
        assert!(is_height("190cm"));
1!
242
        assert!(!is_height("190in"));
1!
243
        assert!(!is_height("190"));
1!
244
        assert!(!is_height("5cm"));
1!
245
    }
2✔
246
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc