Skip to content

Commit c060feb

Browse files
committed
Add a bunch of 2020 days
Why did I do this?
1 parent e2c4329 commit c060feb

File tree

8 files changed

+403
-0
lines changed

8 files changed

+403
-0
lines changed

src/aoc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
pub mod y2015;
1111
pub mod y2018;
1212
pub mod y2019;
13+
pub mod y2020;
1314
pub mod y2021;
1415
pub mod y2022;
1516
pub mod y2023;

src/aoc/y2020/day00.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) 2025 Lexi Robinson
2+
//
3+
// Licensed under the EUPL, Version 1.2
4+
//
5+
// You may not use this work except in compliance with the Licence.
6+
// You should have received a copy of the Licence along with this work. If not, see:
7+
// <https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12>.
8+
// See the Licence for the specific language governing permissions and limitations under the Licence.
9+
10+
pub fn part_1(data: crate::DataIn) -> crate::AoCResult<String> {
11+
let ret = data.count();
12+
Ok(ret.to_string())
13+
}
14+
15+
inventory::submit!(crate::AoCDay {
16+
year: "2020",
17+
day: "0",
18+
part_1: crate::AoCPart {
19+
main: part_1,
20+
example: part_1
21+
},
22+
part_2: None
23+
});

src/aoc/y2020/day01.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright (c) 2025 Lexi Robinson
2+
//
3+
// Licensed under the EUPL, Version 1.2
4+
//
5+
// You may not use this work except in compliance with the Licence.
6+
// You should have received a copy of the Licence along with this work. If not, see:
7+
// <https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12>.
8+
// See the Licence for the specific language governing permissions and limitations under the Licence.
9+
10+
use std::collections::HashSet;
11+
12+
use itertools::Itertools;
13+
14+
use crate::AoCError;
15+
16+
pub fn part_1(data: crate::DataIn) -> crate::AoCResult<String> {
17+
let nums: Vec<u64> = data.map(|line| line.parse()).try_collect()?;
18+
let num_set: HashSet<_> = nums.iter().copied().collect();
19+
20+
let ret = nums
21+
.into_iter()
22+
.find_map(|num| {
23+
let target = 2020 - num;
24+
if num_set.contains(&target) {
25+
Some(num * target)
26+
} else {
27+
None
28+
}
29+
})
30+
.ok_or(AoCError::new("No matching numbers found"))?;
31+
Ok(ret.to_string())
32+
}
33+
34+
pub fn part_2(data: crate::DataIn) -> crate::AoCResult<String> {
35+
let nums: Vec<u64> = data.map(|line| line.parse()).try_collect()?;
36+
let num_set: HashSet<_> = nums.iter().copied().collect();
37+
38+
let ret = nums
39+
.iter()
40+
.enumerate()
41+
.find_map(|(i, num1)| {
42+
nums.iter()
43+
.skip(i + 1)
44+
.filter(|num2| **num2 + *num1 < 2020)
45+
.find_map(|num2| {
46+
let target = 2020 - num1 - num2;
47+
if num_set.contains(&target) {
48+
Some(num1 * num2 * target)
49+
} else {
50+
None
51+
}
52+
})
53+
})
54+
.ok_or(AoCError::new("No matching numbers found"))?;
55+
Ok(ret.to_string())
56+
}
57+
58+
inventory::submit!(crate::AoCDay {
59+
year: "2020",
60+
day: "1",
61+
part_1: crate::AoCPart {
62+
main: part_1,
63+
example: part_1
64+
},
65+
part_2: Some(crate::AoCPart {
66+
main: part_2,
67+
example: part_2
68+
})
69+
});

src/aoc/y2020/day02.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (c) 2025 Lexi Robinson
2+
//
3+
// Licensed under the EUPL, Version 1.2
4+
//
5+
// You may not use this work except in compliance with the Licence.
6+
// You should have received a copy of the Licence along with this work. If not, see:
7+
// <https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12>.
8+
// See the Licence for the specific language governing permissions and limitations under the Licence.
9+
use std::str::FromStr;
10+
11+
use itertools::Itertools;
12+
use lazy_static::lazy_static;
13+
use regex::Regex;
14+
15+
struct Policy {
16+
a: usize,
17+
b: usize,
18+
letter: char,
19+
password: String,
20+
}
21+
22+
impl FromStr for Policy {
23+
type Err = crate::AoCError;
24+
25+
fn from_str(s: &str) -> Result<Self, Self::Err> {
26+
lazy_static! {
27+
static ref RE: Regex = Regex::new(r"^(\d+).(\d+) (.): (.+)$").unwrap();
28+
}
29+
30+
let matches = RE
31+
.captures(s)
32+
.ok_or_else(Self::Err::new_from_regex(s, &RE))?;
33+
34+
Ok(Self {
35+
a: matches[1].parse()?,
36+
b: matches[2].parse()?,
37+
letter: matches[3].chars().next().unwrap(),
38+
password: matches[4].to_owned(),
39+
})
40+
}
41+
}
42+
43+
impl Policy {
44+
fn part_1(&self) -> bool {
45+
let range = self.a..=self.b;
46+
range.contains(&(self.password.chars().filter(|c| *c == self.letter).count()))
47+
}
48+
49+
fn part_2(&self) -> bool {
50+
let chars = self.password.chars().collect_vec();
51+
chars.get(self.a - 1).is_some_and(|c| *c == self.letter)
52+
^ chars.get(self.b - 1).is_some_and(|c| *c == self.letter)
53+
}
54+
}
55+
56+
pub fn part_1(data: crate::DataIn) -> crate::AoCResult<String> {
57+
let policies: Vec<Policy> = data.map(|line| line.parse()).try_collect()?;
58+
let ret = policies.into_iter().filter(|p| p.part_1()).count();
59+
Ok(ret.to_string())
60+
}
61+
62+
pub fn part_2(data: crate::DataIn) -> crate::AoCResult<String> {
63+
let policies: Vec<Policy> = data.map(|line| line.parse()).try_collect()?;
64+
let ret = policies.into_iter().filter(|p| p.part_2()).count();
65+
Ok(ret.to_string())
66+
}
67+
68+
inventory::submit!(crate::AoCDay {
69+
year: "2020",
70+
day: "2",
71+
part_1: crate::AoCPart {
72+
main: part_1,
73+
example: part_1
74+
},
75+
part_2: Some(crate::AoCPart {
76+
main: part_2,
77+
example: part_2
78+
}),
79+
});

src/aoc/y2020/day03.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Copyright (c) 2025 Lexi Robinson
2+
//
3+
// Licensed under the EUPL, Version 1.2
4+
//
5+
// You may not use this work except in compliance with the Licence.
6+
// You should have received a copy of the Licence along with this work. If not, see:
7+
// <https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12>.
8+
// See the Licence for the specific language governing permissions and limitations under the Licence.
9+
10+
use std::fmt::Display;
11+
12+
use crate::{CharGrid, CommonGrid, Coord2D, Grid, symbols};
13+
14+
enum GridState {
15+
Snow,
16+
Tree,
17+
}
18+
19+
impl TryFrom<char> for GridState {
20+
type Error = crate::AoCError;
21+
22+
fn try_from(value: char) -> Result<Self, Self::Error> {
23+
Ok(match value {
24+
'.' => Self::Snow,
25+
'#' => Self::Tree,
26+
_ => return Err(Self::Error::new_from_char(value)),
27+
})
28+
}
29+
}
30+
31+
impl Display for GridState {
32+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33+
match self {
34+
Self::Snow => symbols::VOID,
35+
Self::Tree => symbols::TREE,
36+
}
37+
.fmt(f)
38+
}
39+
}
40+
41+
fn toboggonate(grid: &Grid<GridState>, dir: Coord2D) -> usize {
42+
let mut pos = Coord2D { x: 0, y: 0 };
43+
let mut trees = 0;
44+
loop {
45+
match grid.get(&pos) {
46+
Some(GridState::Tree) => trees += 1,
47+
Some(_) => (),
48+
None => {
49+
log::debug!("Fell of the end of the map at {pos}");
50+
break;
51+
}
52+
}
53+
pos += dir;
54+
pos.x %= grid.width as i32;
55+
}
56+
57+
trees
58+
}
59+
60+
pub fn part_1(data: crate::DataIn) -> crate::AoCResult<String> {
61+
let grid: Grid<GridState> = Grid::new_from_chars(data)?;
62+
log::debug!("\n{grid:#}");
63+
let ret = toboggonate(&grid, Coord2D { x: 3, y: 1 });
64+
Ok(ret.to_string())
65+
}
66+
67+
pub fn part_2(data: crate::DataIn) -> crate::AoCResult<String> {
68+
let grid: Grid<GridState> = Grid::new_from_chars(data)?;
69+
log::debug!("\n{grid:#}");
70+
let ret: usize = [
71+
Coord2D { x: 1, y: 1 },
72+
Coord2D { x: 3, y: 1 },
73+
Coord2D { x: 5, y: 1 },
74+
Coord2D { x: 7, y: 1 },
75+
Coord2D { x: 1, y: 2 },
76+
]
77+
.into_iter()
78+
.map(|coord| toboggonate(&grid, coord))
79+
.product();
80+
81+
Ok(ret.to_string())
82+
}
83+
84+
inventory::submit!(crate::AoCDay {
85+
year: "2020",
86+
day: "3",
87+
part_1: crate::AoCPart {
88+
main: part_1,
89+
example: part_1
90+
},
91+
part_2: Some(crate::AoCPart {
92+
main: part_2,
93+
example: part_2
94+
}),
95+
});

0 commit comments

Comments
 (0)