Skip to content

Instantly share code, notes, and snippets.

@deanbot
Created December 4, 2020 15:06
Show Gist options
  • Save deanbot/8f1b8f917c1415e81e4781261f446d3e to your computer and use it in GitHub Desktop.
Save deanbot/8f1b8f917c1415e81e4781261f446d3e to your computer and use it in GitHub Desktop.
Advent Of Code 2020 Day 4 in dart
void main() {
final List<Object> solutions = [
SolutionA(),
SolutionB()
];
solutions.forEach((s) => print(s.toString()));
}
// Full inputs at https://adventofcode.com/2020/day/4/input
var inputAdvent4 = """pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980
hcl:#623a2f
eyr:2029 ecl:blu cid:129 byr:1989
iyr:2014 pid:896056539 hcl:#a97842 hgt:165cm
hcl:#888785
hgt:164cm byr:2001 iyr:2015 cid:88
pid:545766238 ecl:hzl
eyr:2022
iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719
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""";
List<Passport> _parseInputs(String inputs) => inputs
.split("\n\n")
.where((e) => e.isNotEmpty)
.map<Passport>((e) => Passport.fromString(e))
.toList();
var _passports = _parseInputs(inputAdvent4);
class Passport {
Map<String, String> _data = {};
static final passportFields = const <String>{
'byr', // (Birth Year)
'iyr', // (Issue Year)
'eyr', // (Expiration Year)
'hgt', // (Height)
'hcl', // (Hair Color)
'ecl', // (Eye Color)
'pid', // (Passport ID)
'cid', // (Country ID)
};
Passport.fromString(String input) {
// replace new lines with spaces
input.replaceAll(RegExp(r'\n'), ' ').split(' ').forEach((e) {
var p = e.split(':');
if (passportFields.contains(p[0])) {
var key = p[0];
this._data[key] = p[1];
}
});
}
bool isSet(String key) => _data.containsKey(key) && _data[key].isNotEmpty;
bool hasAllFields(Set<String> requiredFields) =>
requiredFields.every((f) => isSet(f));
bool allFieldsValid(Map<String, Function(String)> validations) =>
validations.keys.every((k) {
if (!isSet(k)) {
return false;
}
var v = _data[k];
var valid = validations[k](v);
return valid;
});
}
abstract class AdventSolution {
final int day;
final String name;
AdventSolution(this.day, this.name);
String get solution => getSolution();
// implement in subclass
String getSolution();
@override
String toString() {
return "Advent Of Code, "
"Day $day "
"${name.isNotEmpty ? name : ''} "
"solution: $solution";
}
}
abstract class _Day4Solution extends AdventSolution {
_Day4Solution(name) : super(4, name);
}
class SolutionA extends _Day4Solution {
SolutionA() : super("A");
String getSolution() {
var requiredFields = <String>{...Passport.passportFields.toList()};
requiredFields.remove('cid');
return _passports
.map<bool>((p) => p.hasAllFields(requiredFields))
.where((element) => element)
.toList()
.length
.toString();
}
}
class SolutionB extends _Day4Solution {
SolutionB() : super("B");
String getSolution() {
var validations = <String, Function(String)>{
// four digits; at least 1920 and at most 2002.
'byr': (v) {
var iv = int.parse(v);
return v.length == 4 && iv >= 1920 && iv <= 2002;
},
// four digits; at least 2010 and at most 2020.
'iyr': (v) {
var iv = int.parse(v);
return v.length == 4 && iv >= 2010 && iv <= 2020;
},
// four digits; at least 2020 and at most 2030.
'eyr': (v) {
var iv = int.parse(v);
return v.length == 4 && iv >= 2020 && iv <= 2030;
},
// 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.
'hgt': (v) {
if (v.contains('cm')) {
var p = v.split('cm'), pv = p.length > 0 ? int.parse(p[0]) : 0;
return pv >= 150 && pv <= 193;
} else if (v.contains('in')) {
var p = v.split('in'), pv = p.length > 0 ? int.parse(p[0]) : 0;
return pv >= 59 && pv <= 76;
} else {
return false;
}
},
// a # followed by exactly six characters 0-9 or a-f
'hcl': (v) {
return RegExp(r'#[a-f|0-9]{6}').hasMatch(v);
},
// exactly one of: amb blu brn gry grn hzl oth.
'ecl': (v) {
var valid = ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth'];
return valid.contains(v);
},
// a nine-digit number, including leading zeroes.
'pid': (v) {
return v.length == 9 && int.tryParse(v) != null;
},
};
return _passports
.map<bool>((p) => p.allFieldsValid(validations))
.where((v) => v)
.toList()
.length
.toString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment