This commit is contained in:
Stefan Bühler 2020-12-04 19:37:36 +01:00
commit 493336905c
12 changed files with 2972 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

5
Cargo.lock generated Normal file
View File

@ -0,0 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aoc2020"
version = "0.1.0"

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "aoc2020"
version = "0.1.0"
authors = ["Stefan Bühler <stbuehler@web.de>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

200
data/day1/input Normal file
View File

@ -0,0 +1,200 @@
1934
1702
1571
1737
1977
1531
1428
1695
1794
1101
13
1164
1235
1289
1736
1814
1363
1147
1111
1431
1765
1515
1184
1036
1803
1791
1638
1809
1283
1980
1854
1878
1574
1352
1151
730
1581
1990
1919
2003
1538
1663
1735
1772
1830
1152
1022
1774
1544
1551
1835
1383
1614
1396
1715
1530
295
1208
1978
1104
1691
1176
1183
1909
1192
1535
1924
1268
1969
1954
1760
1077
1734
1371
1676
1933
1400
1928
1982
1541
1106
1248
1346
1782
1142
1849
1798
1362
1379
1886
1265
1226
1751
1575
1027
1710
1601
1205
1922
1452
1206
1263
2000
1957
1951
1834
1533
1149
1245
1564
1182
1237
1013
1254
1895
1504
1480
1556
1821
1589
1864
1573
1698
1927
1434
516
1722
1360
1940
1212
1329
1675
1812
1917
1302
1604
1336
1233
1405
1179
1169
1081
1941
1553
1236
1824
1923
1938
1475
1446
1545
1853
1664
317
1489
1884
1743
1621
1128
1474
1505
394
1387
1509
1627
1914
1913
1949
1843
1847
1882
1486
1082
1802
1645
1690
1629
1377
2004
1044
1191
1014
1857
1813
1572
1055
1002
1721
1273
1417
1968
1888
1863
1278
1141
1964
1259
1823
1181
1779

1000
data/day2/input Normal file

File diff suppressed because it is too large Load Diff

323
data/day3/input Normal file
View File

@ -0,0 +1,323 @@
.#....#..##.#..####....#.......
......#..#....#....###......#.#
#..#.....#..............##.#.#.
#.#...#....#...#......##..#..#.
...#..#.##..#..#........###.#.#
...#.#..........#.........##...
...#.#....#.#....#..#......#...
..##.#.....#.......#.###..#..##
..#.......#.......#....##......
....##........##.##...#.###.##.
#.......#.......##..#......#...
..##.............##.#......#...
...#.####....#.....#...##......
.............##.#......#.......
..#...#....#......#....#.......
..#....#..#............#.......
##...#..#........##..#......#..
##........##........#.#.......#
#.......#........#.#..#....###.
.....#..#.#..........##...#....
..##...#......#.#...#..#...#...
##.##...#......#....#....#...#.
#.......#..#.#..#....#..###.#.#
#.............#.#....#..#.#....
...#.......###.#.##.##.#...#..#
.##.......##..##...#..###......
.......#.#.#.#..####..#..#..#..
...##......#.#.##.###....#.###.
###......###......#.#####..#...
..#........##..#..##.##..#...#.
.....##..#...#..#.##.....#.#...
#......#.##....#..##.#....#.#..
##.#.##..#................#....
......#.#....#......##.....#...
..#...##..#..#...#..#.#..#.....
........#.#.#.##...#.#.....#.#.
#.#......#.....##..#...#.......
..#.#......#...........###.....
......##....#....##..#..#.#.#.#
##....#.###...#......#..#...#..
#.#.##....###...####.......#..#
##...........#.....#........#.#
.##.#..#.....#......#.......#..
##..##..###....#.........##....
..#..#..#.##...#.#...#........#
#.##.###...#.......#...........
.........#.................#...
#.##...#.....#..##........#....
....#.#...##...#...........#...
.#.....#.#..#...##..##.....#...
.#.....####....#..##..#........
...#..#......##.#..##.#.#.#..#.
.##.#.....#.....#...#.......##.
......#..#..#......#...####....
.......#......##..#..##.....#..
......#.#..#...#..#.#..........
....##.........#...............
.#....#..##.....#....##.##.....
#.#.....#...#....####....#.#...
#.....#....#.#...#.............
...#..#.....#....##..#..#......
...#.#............#...........#
###.#..#.#......#.....##.....#.
####....#....###.....#..#.#####
.###..#...#.#..#......##.#.#.#.
.....#.##.#....#..##....#..#..#
...#....#...##.....#......#.#..
....#...#....#...#....#.....#.#
.#.....#.....#.#..#......#..#..
..#..##....##.##....#.....##...
#..##...#.##...#..#.#.#.....#..
...#..##.#..#....#.#....######.
..........#..#.....#....#...##.
#.#####.#.###..#.....#.........
#....#......#..#.#.##.##..###..
..#...###.#.#....##.##...##....
.......#....#..#...##......#...
...#.#...#..#.....#..##.#......
###..##...........#............
..#....#.##....#.#..##...#.....
##....#...#....#.....#.#..##...
..............#.##.#..#..##.###
......#..#..#..#.#....###...##.
.#...#..#.#.#....#..........#..
..#.#.....#..#...........#.##..
...#.#......#......#..#..#.#...
...#....#.#.#.....#...#.##..#..
.#.#..#...#........##.......#..
##..........#..#...#....###.#..
#.....###......#..#.#.#....#.#.
..###.......#.#...............#
#....#.....#.#......#..##.##...
#.##.#.#....#..#.#...#.#...#..#
#....#..#...........#.......#..
...#.####.....#.........###.##.
......#..#.....#..........#..#.
#...#.#..####...#...#.#.##...##
.##.........#......#.#.#.......
.......##...##.##....###...##..
...#..#....#..#.#.#.....#.#....
#....#.#.#.......##..###..##...
......#............#.#...#..#..
#.#.....#......#...#.......###.
...#.#................#...#....
.....#......#.#..#...##.#.#...#
#....#.#..#..#..##..#.##..#....
#.................#..#....#....
..#....#.......####....###.....
.#..#.#.#...###..#...#..###....
..#..#.#......#.###..........#.
.....#......#.......##....##.#.
.#....#........#.#.##.#........
#.#..##..#..#.#...####....##...
...#....#.#..#...#..........#..
.#.....#.##....#...##..........
....##....#.....#.....#...#.###
.#...##.#.#..##..#...#.#..#..#.
..#.......#.##.....#.#........#
...#...#.....##..#.#.#....#....
...#.....#.......##.........#.#
.##.....#..#.#...#.#...#.#...#.
...........#...#.###..#...#..#.
#.##........#..###.##...####...
.#.....#.#...##...#..#..#...##.
..#....#..#...#.....#.....##...
..###..#.#.....##........#.##..
.#.#..##........#.##....#..#.##
.####.#..##..#.#..#....##....#.
.##....##...#.#........#.......
....#..#..#...#..#..#..#.#.....
...#......................#....
#.....#.#....#..#..#.#..#....#.
##.....#.....##..........###...
.#..#..............#...##.#.#.#
...#...#.#.............#.#..#.#
..#.....#.......#......#.#.....
.###.#..#..#..#.#..#.....#.....
.....##..##...##.......#....###
.#........###...##..#....##....
#....#.#......##..#....#.##..#.
#....#.#...#........##...###...
.#.....#...#.###....#.##.#.####
###......#....#...#....##..#..#
##....#..###......#...#.#.#....
..........#......##.#..#.......
.#..#......###.........##...#..
....#......#....#.........#.#.#
##.#.#...#.#...#...#..#......#.
....#.##.........#..#.....##.#.
........#...#..#.#.#.#.....##..
..#......#.#.#..#.....##.......
..............#....#....##.#..#
....#.#.....#....#.#.###.#....#
..#..........#..#......#.##..#.
...#...#.#.............#..#....
#.......#..#..##.........##..#.
..##..#............#.....#.....
....#.#..##...#.#..#.........#.
........#.......#.##....#....#.
...#.....#.#.....#.#....#......
..#......##.#.............#.#.#
#.#.............#.#.....#......
.##....##.#.....#....#...##....
.#.#....##....#.....##.........
...#.....#.....#.....#..#.###..
.......#....#...##.#...#...#..#
..#.#.......#...###.#...#....#.
.....###..##....###.#.##.......
....#..................##.#.##.
.#.......###.##...#.#.....#....
....#....##...##.....#.#...#..#
#..#.....#......##...#....#....
#..##.........#.....#...#......
...#..##.......##......#..#####
.#..###.###.#.##........#......
.#...#....#....#.#....#...##...
##........#....#.........##..#.
.#.....##............#.#.......
....#....#...........###.....##
.#......#.#.#..#....#.#.....##.
......#.##.#..##....#.#.#..#...
#....#......#...#..####........
......#..#..##..#.......#.#..#.
##....##.###.#...#.##.#..#.###.
.#.........#...##...#.#......#.
..#.#...........####.#....##.##
.....#.#..##.#...###...#..#.#..
...#..#..##.#...#.....#.##...##
..##......##..........#..###...
.#......##.....#.##....#.#.##.#
...#.......##..##.....#....#...
.##...#...#....#..#............
#..#....#...........#..........
......#...#.#.......#...#.##..#
..#.###..#.....#.....#..#.....#
....#....#..........##....#..#.
.......##.#.#.#......#....#...#
####..#.###........#..#......#.
#........##.#.#.#.............#
.#......#......#..#.##.....#...
.....##.##......##.#.....#.#.#.
.......##.#.....##.......#.#.#.
.#.#..#.#..#.##...#.#....#.#..#
.#..##....#..#...##.......#..#.
.#.#..#.......#................
#........#.#.#......#.#.#.#....
##......#...#..##.#...##.##....
##.#..#...........##...#..###..
......#.####...#........#.#.#..
...#........##..###.#.#...#...#
.#.....##..#......##......###..
..#.#...#......#..#..##.#.....#
#....#..#.#..........#...#.....
.#......#.##..###..#.#....#..##
.......#.......#..#..#......#..
..##.....##.#..#..#.....##.....
........#.##...#.#.#..#..#..#..
...#.######.........#.....#..##
.#.#............#....#.........
#...#....###.#......#.#........
#.........#....#...##..........
....#...........#.###.#...###..
.........#........#.#.#..#...#.
.#.......#.#.....#.#.....#.##..
.....#.......#.....#.#.#.......
#.##..#..##.......#...#......#.
.###.....##...##.#...##.##.#.#.
...#......##..##............#.#
...#......................#..##
#..#..#................#...#...
#..#....#.#.#...##.......#..#..
....#.#..###.##...#..#.###..#..
..#...#....####.#............#.
......#....#.#...#.#.#.........
#...#........#.....##..###.#..#
#....#...#...##...#..#....##...
#..#...#..#.......#.#..##.#..#.
#.#..........#...........##....
.#...###...#......#.......#.#.#
.........#.........#...#...##..
##.#..###......##..#.....#..#..
....##...............#.....#...
.....#.....###.#.....#.#.......
....#..#......###..#..##..#....
......................#.....#..
..#..#...##....##....#........#
..#....#...#...#.......#.....#.
...##.#.#.##......#.#.#.#.####.
.###...#..#......#.#..#........
#..#...##.#..#..##..##....#...#
...#...#..#..#..#........#..##.
.##....#.##.#....#...#.#.#....#
#..#....#..#....#.......##..#.#
...#.#....####...........#...#.
#...#####...#.#..#......#...#.#
.##....#.#.#..#......#..##.....
..........#..#.#.#.....##......
.....#....#..................#.
.........#...#...#....#..###...
.#.#.#....#....................
......##............##.###..#..
#.#...#........####.##..#.#.##.
#........#.#.#.#..#.##.....#...
......####..#.##.......#....#..
.........#...#...#.....#.......
..##.....#...#...#.....##.....#
....#...##....#.....#..#..##.##
..#.........##...##..###..#....
#....#.#.........##.###.#...##.
.##...#....#..#..#.#....##.....
##..#..#..#...........#.##....#
....#..........#...#..#.....#..
........###..#..#.#.#.....##...
#...#...#..###............###..
..#.....#.#.#..#..#.#..#......#
..#...##..#....#...#......#....
#....#........##.....#..##....#
#.....#.#.#..#.......##.#.#.##.
..##...#...#.....#..........#..
##.....#....#......#..........#
......#..#..........#.#..####..
......#...#............##...##.
..#.......##.......#...###.###.
.#..#.#.#...#..##.#......#.#...
.##.....##.#.#...#.##.........#
#.#.######...........#.#####.#.
........#.##...##....##.#.##.#.
....#......#.....#.....###...##
#..............#.#....#.#....#.
....#..###.#.........##.#.#....
..#.#.#..##....####..........#.
...#..#.......#................
...#....#..............#....#..
.....#...#...#....#.#.#..#...#.
......##.............###.##..##
.#...#.#..#......#..#.##.......
##.....#.....#.##...#....#.....
..#..#.#.#.#.#..........#..###.
##..........#........#....#.#..
.....#...#........#.#..###....#
.###.#........#.##......#.#...#
#...##....#....#....##.#.#.....
.....#.#............#..........
..#.##....................#....
.....#..#..#.#..#.##.......#...
.....###......#......##......##
#.....#.#.......##.......#...#.
.#.#...#......#..###...#.....#.
#.#..#...#..##.....#...#.#..#..
.....#.#..........#..#.........
.###..##..##.....#...#...#..##.
#...#.#....#.......##..#.......
###...#.#.#..#.......#......#..
....##........#..........##....
............#....#...........#.
#..#.#....##..#.#..#......##...
.###....##...#....##..........#
.###........#........###.....#.
...#...#.#......#...#....#.....
.###.......#.........#.........
....##.#......#...###......##.#
.###...#..##.....##.......#....
.#.#...#..#.##....#........#...

1146
data/day4/input Normal file

File diff suppressed because it is too large Load Diff

35
src/bin/day1/main.rs Normal file
View File

@ -0,0 +1,35 @@
const INPUT: &str = include_str!("../../../data/day1/input");
fn main() {
let expenses: Vec<_> = INPUT.split_whitespace().map(|s| s.parse::<u32>().unwrap()).collect();
'outer: for (pos, &exp1) in expenses.iter().enumerate() {
for &exp2 in expenses[pos+1..].iter() {
if exp1 + exp2 == 2020 {
println!(
"Found: {exp1} + {exp2} = 2020; {exp1} * {exp2} = {}",
exp1 * exp2,
exp1 = exp1,
exp2 = exp2,
);
break 'outer;
}
}
}
'outer2: for (pos, &exp1) in expenses.iter().enumerate() {
for (pos2, &exp2) in expenses[pos+1..].iter().enumerate() {
for &exp3 in expenses[pos2+1..].iter() {
if exp1 + exp2 + exp3 == 2020 {
println!(
"Found: {exp1} + {exp2} + {exp3} = 2020; {exp1} * {exp2} * {exp3} = {}",
exp1 * exp2 * exp3,
exp1 = exp1,
exp2 = exp2,
exp3 = exp3,
);
break 'outer2;
}
}
}
}
}

69
src/bin/day2/main.rs Normal file
View File

@ -0,0 +1,69 @@
use std::convert::TryInto;
const INPUT: &str = include_str!("../../../data/day2/input");
struct Policy {
min: usize,
max: usize,
chr: char,
}
impl Policy {
fn parse(text: &str) -> Self {
let tokens: Vec<_> = text.trim().split_whitespace().collect();
let [range, chr]: [&str; 2] = tokens.try_into().unwrap();
let tokens: Vec<_> = range.split("-").collect();
let [min, max]: [&str; 2] = tokens.try_into().unwrap();
assert!(chr.len() == 1);
let chr = chr.chars().next().unwrap();
let min = min.parse::<usize>().unwrap();
let max = max.parse::<usize>().unwrap();
Self { min, max, chr }
}
fn test(&self, input: &str) -> bool {
let count = input.chars().filter(|&c| c == self.chr).count();
count >= self.min && count <= self.max
}
fn test_crazy(&self, input: &str) -> bool {
let chars: Vec<_> = input.chars().collect();
assert!(self.min > 0 && self.max > 0);
assert!(self.min <= chars.len() && self.max <= chars.len());
(chars[self.min-1] == self.chr) != (chars[self.max-1] == self.chr)
}
}
struct Entry {
policy: Policy,
password: String,
}
impl Entry {
fn parse(line: &str) -> Self {
let tokens: Vec<_> = line.split(":").collect();
let [policy, password]: [&str; 2] = tokens.try_into().unwrap();
Self {
policy: Policy::parse(policy),
password: password.trim().into(),
}
}
fn parse_list(input: &str) -> Vec<Self> {
input.lines().map(Self::parse).collect()
}
fn valid(&self) -> bool {
self.policy.test(&self.password)
}
fn valid_crazy(&self) -> bool {
self.policy.test_crazy(&self.password)
}
}
fn main() {
let entries = Entry::parse_list(INPUT);
println!("Valid entries: {}", entries.iter().filter(|e| e.valid()).count());
println!("Crazy valid entries: {}", entries.iter().filter(|e| e.valid_crazy()).count());
}

65
src/bin/day3/main.rs Normal file
View File

@ -0,0 +1,65 @@
const INPUT: &str = include_str!("../../../data/day3/input");
struct Forest {
pub rows: usize,
stride: usize,
trees: Vec<bool>,
}
impl Forest {
fn parse(text: &str) -> Self {
let first_line = text.lines().next().unwrap();
let stride = first_line.len();
let mut trees = Vec::new();
let mut rows = 0;
for line in text.lines() {
assert_eq!(line.len(), stride);
trees.extend(line.as_bytes().iter().map(|&c| c == b'#'));
rows += 1;
}
Self {
rows,
stride,
trees,
}
}
fn is_tree(&self, row: usize, column: u64) -> bool {
assert!(row < self.rows);
let column = (column % self.stride as u64) as usize;
self.trees[column + row * self.stride]
}
fn hit_trees(&self, slope_y: usize, slope_x: u64) -> u64 {
let mut row = slope_y;
let mut col = slope_x;
let mut hits = 0;
while row < self.rows {
if self.is_tree(row, col) {
hits += 1;
}
row += slope_y;
col += slope_x;
}
hits
}
}
const TEST_SLOPES: &[(usize, u64)] = &[
(1, 1),
(1, 3),
(1, 5),
(1, 7),
(2, 1),
];
fn main() {
let forest = Forest::parse(INPUT);
println!("Hit trees: {}", forest.hit_trees(1, 3));
println!(
"Hit product: {}",
TEST_SLOPES.iter().map(|(slope_y, slope_x)| {
forest.hit_trees(*slope_y, *slope_x)
}).product::<u64>(),
);
}

13
src/bin/day4/main.rs Normal file
View File

@ -0,0 +1,13 @@
pub mod passport;
use passport::Passport;
const INPUT: &str = include_str!("../../../data/day4/input");
fn main() {
let passports = Passport::parse_list(INPUT);
let all_required_fields: Vec<_> = passports.iter().filter(|p| p.require_all_but_country_id()).collect();
println!("Required fields Passports: {}", all_required_fields.len());
let valid: Vec<_> = passports.iter().filter(|p| p.valid()).collect();
println!("Valid Passports: {}", valid.len());
}

106
src/bin/day4/passport.rs Normal file
View File

@ -0,0 +1,106 @@
#[derive(Clone, Debug, Default)]
pub struct Passport {
// "byr": birth_year
pub birth_year: Option<String>,
// "iyr": issue_year
pub issue_year: Option<String>,
// "eyr": expiration_year
pub expiration_year: Option<String>,
// "hgt": height
pub height: Option<String>,
// "hcl": hair_color
pub hair_color: Option<String>,
// "ecl": eye_color
pub eye_color: Option<String>,
// "pid": passport_id
pub passport_id: Option<String>,
// "cid": country_id
pub country_id: Option<String>,
}
impl Passport {
pub fn parse(text: &str) -> Self {
let mut result = Self::default();
for token in text.split_whitespace() {
let colon = token.find(':').expect("missing separator");
let key = &token[..colon];
let value = &token[colon+1..];
match key {
"byr" => result.birth_year = Some(value.into()),
"iyr" => result.issue_year = Some(value.into()),
"eyr" => result.expiration_year = Some(value.into()),
"hgt" => result.height = Some(value.into()),
"hcl" => result.hair_color = Some(value.into()),
"ecl" => result.eye_color = Some(value.into()),
"pid" => result.passport_id = Some(value.into()),
"cid" => result.country_id = Some(value.into()),
_ => panic!("unknown field {:?}", key),
}
}
result
}
pub fn parse_list(text: &str) -> Vec<Self> {
text.split("\n\n").map(Self::parse).collect()
}
pub fn require_all_but_country_id(&self) -> bool {
self.birth_year.is_some() &
self.issue_year.is_some() &
self.expiration_year.is_some() &
self.height.is_some() &
self.hair_color.is_some() &
self.eye_color.is_some() &
self.passport_id.is_some()
}
fn _valid(&self) -> Option<()> {
let birth_year = self.birth_year.as_ref()?.parse::<u16>().ok()?;
if birth_year < 1920 || birth_year > 2002 {
return None;
}
let issue_year = self.issue_year.as_ref()?.parse::<u16>().ok()?;
if issue_year < 2010 || issue_year > 2020 {
return None;
}
let expiration_year = self.expiration_year.as_ref()?.parse::<u16>().ok()?;
if expiration_year < 2020 || expiration_year > 2030 {
return None;
}
let height = self.height.as_ref()?;
if height.ends_with("cm") {
let height = height[..height.len() - 2].parse::<u16>().ok()?;
if height < 150 || height > 193 {
return None;
}
} else if height.ends_with("in") {
let height = height[..height.len() - 2].parse::<u16>().ok()?;
if height < 59 || height > 76 {
return None;
}
} else {
return None;
}
let hair_color = self.hair_color.as_ref()?;
if !hair_color.starts_with("#") || hair_color.len() != 7 {
return None;
}
if !hair_color[1..].chars().all(|c| (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) {
return None;
}
let eye_color = self.eye_color.as_ref()?;
match eye_color.as_str() {
"amb"|"blu"|"brn"|"gry"|"grn"|"hzl"|"oth" => (),
_ => return None,
}
let passport_id = self.passport_id.as_ref()?;
if passport_id.len() != 9 || !passport_id.chars().all(|c| c.is_ascii_digit()) {
return None;
}
Some(())
}
pub fn valid(&self) -> bool {
self._valid().is_some()
}
}