Day 4
parent
30fd2fdee6
commit
98e2d05566
@ -0,0 +1,113 @@
|
|||||||
|
import 'package:aoc2020/aocbase.dart';
|
||||||
|
import 'package:aoc2020/model/readdata.dart';
|
||||||
|
|
||||||
|
// byr (Birth Year)
|
||||||
|
// iyr (Issue Year)
|
||||||
|
// eyr (Expiration Year)
|
||||||
|
// hgt (Height)
|
||||||
|
// hcl (Hair Color)
|
||||||
|
// ecl (Eye Color)
|
||||||
|
// pid (Passport ID)
|
||||||
|
// cid (Country ID)
|
||||||
|
|
||||||
|
typedef Validator = bool Function(String);
|
||||||
|
|
||||||
|
class AOC20201204 extends AOCBase {
|
||||||
|
static const List<String> eyeColors = ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth'];
|
||||||
|
// cid field is assume to be last
|
||||||
|
List<String> fields = ['byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid', 'cid'];
|
||||||
|
Map<String, Validator> valid1 = {
|
||||||
|
'byr': (val) => true,
|
||||||
|
'iyr': (val) => true,
|
||||||
|
'eyr': (val) => true,
|
||||||
|
'hgt': (val) => true,
|
||||||
|
'hcl': (val) => true,
|
||||||
|
'ecl': (val) => true,
|
||||||
|
'pid': (val) => true,
|
||||||
|
'cid': (val) => true,
|
||||||
|
};
|
||||||
|
Map<String, Validator> valid2 = {
|
||||||
|
'byr': (val) => (val.length == 4 && int.parse(val) >= 1920 && int.parse(val) <= 2002),
|
||||||
|
'iyr': (val) => (val.length == 4 && int.parse(val) >= 2010 && int.parse(val) <= 2020),
|
||||||
|
'eyr': (val) => (val.length == 4 && int.parse(val) >= 2020 && int.parse(val) <= 2030),
|
||||||
|
'hgt': (val) {
|
||||||
|
var units = val.substring(val.length - 2);
|
||||||
|
var height = int.parse(val.substring(0, val.length - 2));
|
||||||
|
if (units == 'cm') {
|
||||||
|
return height >= 150 && height <= 193;
|
||||||
|
} else {
|
||||||
|
return height >= 59 && height <= 76;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'hcl': (val) {
|
||||||
|
var regExp = RegExp(r'^#([a-fA-F0-9]{6})', caseSensitive: false, multiLine: false);
|
||||||
|
return regExp.hasMatch(val);
|
||||||
|
},
|
||||||
|
'ecl': (val) => eyeColors.contains(val),
|
||||||
|
'pid': (val) {
|
||||||
|
var regExp = RegExp(r'^([0-9]{9})$', caseSensitive: false, multiLine: false);
|
||||||
|
return regExp.hasMatch(val);
|
||||||
|
},
|
||||||
|
'cid': (val) => true,
|
||||||
|
};
|
||||||
|
// ^#([a-fA-F0-9]{6}])
|
||||||
|
|
||||||
|
// byr (Birth Year) - four digits; at least 1920 and at most 2002.
|
||||||
|
// iyr (Issue Year) - four digits; at least 2010 and at most 2020.
|
||||||
|
// eyr (Expiration Year) - four digits; at least 2020 and at most 2030.
|
||||||
|
// hgt (Height) - a number followed by either cm or in:
|
||||||
|
// If cm, the number must be at least 150 and at most 193.
|
||||||
|
// If in, the number must be at least 59 and at most 76.
|
||||||
|
// hcl (Hair Color) - a # followed by exactly six characters 0-9 or a-f.
|
||||||
|
// ecl (Eye Color) - exactly one of: amb blu brn gry grn hzl oth.
|
||||||
|
// pid (Passport ID) - a nine-digit number, including leading zeroes.
|
||||||
|
// cid (Country ID) - ignored, missing or not.
|
||||||
|
|
||||||
|
bool validate(Map<String, String> passport, Map<String, Validator> validatorFn) {
|
||||||
|
for (var field in fields) {
|
||||||
|
if (field != fields.last && passport[field] == null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (!validatorFn[field](passport[field])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int processList({List<String> input, Map<String, Validator> validatorFn}) {
|
||||||
|
var retval = 0;
|
||||||
|
var passport = <String, String>{};
|
||||||
|
for (var line in input) {
|
||||||
|
if (line.isEmpty) {
|
||||||
|
retval += validate(passport, validatorFn) ? 1 : 0;
|
||||||
|
passport = <String, String>{};
|
||||||
|
} else {
|
||||||
|
var fieldItems = line.split(' ');
|
||||||
|
for (var item in fieldItems) {
|
||||||
|
var itemSplit = item.split(':');
|
||||||
|
passport[itemSplit[0]] = itemSplit[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval += validate(passport, validatorFn) ? 1 : 0;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> a({bool test}) async {
|
||||||
|
var filename = (test ?? false) ? classStringTest : classString;
|
||||||
|
var mylist = await ReadData.readFileString(filename);
|
||||||
|
|
||||||
|
answerA = processList(input: mylist, validatorFn: valid1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> b({bool test}) async {
|
||||||
|
var filename = (test ?? false) ? classStringTest : classString;
|
||||||
|
var mylist = await ReadData.readFileString(filename);
|
||||||
|
|
||||||
|
answerB = processList(input: mylist, validatorFn: valid2);
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,27 @@
|
|||||||
|
ecl:gry pid:860033327 eyr:2020 hcl:#fffffd
|
||||||
|
byr:1937 iyr:2017 cid:147 hgt:183cm
|
||||||
|
|
||||||
|
iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884
|
||||||
|
hcl:#cfa07d byr:1929
|
||||||
|
|
||||||
|
hcl:#ae17e1 iyr:2013
|
||||||
|
eyr:2024
|
||||||
|
ecl:brn pid:760753108 byr:1931
|
||||||
|
hgt:179cm
|
||||||
|
|
||||||
|
hcl:#cfa07d eyr:2025 pid:166559648
|
||||||
|
iyr:2011 ecl:brn hgt:59in
|
||||||
|
|
||||||
|
eyr:1972 cid:100
|
||||||
|
hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926
|
||||||
|
|
||||||
|
iyr:2019
|
||||||
|
hcl:#602927 eyr:1967 hgt:170cm
|
||||||
|
ecl:grn pid:012533040 byr:1946
|
||||||
|
|
||||||
|
hcl:dab227 iyr:2012
|
||||||
|
ecl:brn hgt:182cm pid:021572410 eyr:2020 byr:1992 cid:277
|
||||||
|
|
||||||
|
hgt:59cm ecl:zzz
|
||||||
|
eyr:2038 hcl:74454a iyr:2023
|
||||||
|
pid:3556412378 byr:2007
|
||||||
Loading…
Reference in New Issue