Skip to content

Commit b567cbc

Browse files
committed
refactor: apply aoc-rust-common to 2015 days 3-5
1 parent 902825a commit b567cbc

4 files changed

Lines changed: 92 additions & 176 deletions

File tree

2015/src/day03.rs

Lines changed: 26 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::collections::HashMap;
2-
3-
use crate::{Exercise, Solvable};
2+
use aoc_rust_common::Solution;
3+
use std::fmt::Display;
44

55
type Position = (i32, i32);
66

@@ -48,87 +48,62 @@ impl Santa {
4848
}
4949
}
5050

51-
struct ThirdDay {
52-
exercise: Exercise,
53-
}
51+
pub struct Day03;
5452

5553
fn get_visited_multiple_times(first: Santa, second: Santa) -> usize {
5654
let mut visited = HashMap::new();
5755
for (key, value) in first.visited.iter() {
58-
visited.insert(key, value);
56+
visited.insert(*key, *value);
5957
}
6058
for (key, value) in second.visited.iter() {
61-
visited.insert(key, value);
59+
visited.insert(*key, *value);
6260
}
6361
visited.values().filter(|&x| *x >= &1).count()
6462
}
6563

66-
impl Solvable for ThirdDay {
67-
fn solve_first(&self, is_prod: bool) -> i64 {
68-
if is_prod {
69-
self.first(&self.exercise.content)
70-
} else {
71-
self.first(&self.exercise.example)
72-
}
73-
}
64+
impl Solution for Day03 {
65+
fn year(&self) -> u32 { 2015 }
66+
fn day(&self) -> u32 { 3 }
7467

75-
fn solve_second(&self, is_prod: bool) -> i64 {
76-
if is_prod {
77-
self.second(&self.exercise.content)
78-
} else {
79-
self.second(&self.exercise.example)
80-
}
81-
}
82-
fn first(&self, content: &str) -> i64 {
68+
fn part1(&self, input: &str) -> Box<dyn Display> {
8369
let mut santa = Santa::new();
84-
for direction in content.chars() {
70+
for direction in input.chars() {
8571
santa.move_to(direction);
8672
}
87-
santa.get_visited_multiple() as i64
73+
Box::new(santa.get_visited_multiple() as i64)
8874
}
8975

90-
fn second(&self, content: &str) -> i64 {
76+
fn part2(&self, input: &str) -> Box<dyn Display> {
9177
let mut santa = Santa::new();
9278
let mut robo_santa = Santa::new();
93-
for direction in content.chars().enumerate() {
79+
for direction in input.chars().enumerate() {
9480
if direction.0 % 2 == 0 {
9581
santa.move_to(direction.1);
9682
} else {
9783
robo_santa.move_to(direction.1);
9884
}
9985
}
100-
get_visited_multiple_times(santa, robo_santa) as i64
86+
Box::new(get_visited_multiple_times(santa, robo_santa) as i64)
10187
}
10288
}
10389

10490
#[cfg(test)]
10591
mod tests {
10692
use super::*;
107-
const EXAMPLE: &str = include_str!("inputs/3_test.txt");
108-
const PROD: &str = include_str!("inputs/3_prod.txt");
10993

11094
#[test]
111-
fn first_test() {
112-
let first_exercise = ThirdDay {
113-
exercise: Exercise {
114-
content: String::from(PROD),
115-
example: String::from(EXAMPLE),
116-
},
117-
};
118-
119-
let expected_example = 4;
120-
let expected_prod = 2572;
121-
122-
let result_example = first_exercise.solve_first(false);
123-
let result_prod = first_exercise.solve_first(true);
124-
assert_eq!(expected_example, result_example);
125-
assert_eq!(expected_prod, result_prod);
95+
fn test_day03() {
96+
let day = Day03;
97+
const PROD: &str = include_str!("inputs/3_prod.txt");
98+
99+
assert_eq!(day.part1(">").to_string(), "2");
100+
assert_eq!(day.part1("^>v<").to_string(), "4");
101+
assert_eq!(day.part1("^v^v^v^v^v").to_string(), "2");
102+
assert_eq!(day.part1(PROD).to_string(), "2572");
126103

127-
let expected_example = 3;
128-
let expected_prod = 2631;
129-
let result_example = first_exercise.solve_second(false);
130-
let result_prod = first_exercise.solve_second(true);
131-
assert_eq!(expected_example, result_example);
132-
assert_eq!(expected_prod, result_prod);
104+
assert_eq!(day.part2("^v").to_string(), "3");
105+
assert_eq!(day.part2("^>v<").to_string(), "3");
106+
assert_eq!(day.part2("^v^v^v^v^v").to_string(), "11");
107+
assert_eq!(day.part2(PROD).to_string(), "2631");
133108
}
134109
}

2015/src/day04.rs

Lines changed: 16 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,36 @@
1-
use crate::{Exercise, Solvable};
1+
use aoc_rust_common::Solution;
2+
use std::fmt::Display;
23
use md5;
34

4-
struct FourthDay {
5-
exercise: Exercise,
6-
}
5+
pub struct Day04;
76

8-
impl Solvable for FourthDay {
9-
fn solve_first(&self, is_prod: bool) -> i64 {
10-
if is_prod {
11-
self.first(&self.exercise.content)
12-
} else {
13-
self.first(&self.exercise.example)
14-
}
15-
}
7+
impl Solution for Day04 {
8+
fn year(&self) -> u32 { 2015 }
9+
fn day(&self) -> u32 { 4 }
1610

17-
fn solve_second(&self, is_prod: bool) -> i64 {
18-
if is_prod {
19-
self.second(&self.exercise.content)
20-
} else {
21-
self.second(&self.exercise.example)
22-
}
23-
}
24-
fn first(&self, content: &str) -> i64 {
11+
fn part1(&self, input: &str) -> Box<dyn Display> {
2512
let mut counter = 0;
13+
let content = input.trim();
2614
loop {
2715
let data = format!("{}{}", content, counter);
2816
let calculated_hash = md5::compute(data);
2917
let hash_as_string = format!("{:x}", calculated_hash);
3018
if hash_as_string.starts_with("00000") {
31-
return counter;
19+
return Box::new(counter as i64);
3220
}
3321
counter += 1;
3422
}
3523
}
3624

37-
fn second(&self, content: &str) -> i64 {
25+
fn part2(&self, input: &str) -> Box<dyn Display> {
3826
let mut counter = 0;
27+
let content = input.trim();
3928
loop {
4029
let data = format!("{}{}", content, counter);
4130
let calculated_hash = md5::compute(data);
4231
let hash_as_string = format!("{:x}", calculated_hash);
4332
if hash_as_string.starts_with("000000") {
44-
return counter;
33+
return Box::new(counter as i64);
4534
}
4635
counter += 1;
4736
}
@@ -51,32 +40,12 @@ impl Solvable for FourthDay {
5140
#[cfg(test)]
5241
mod tests {
5342
use super::*;
54-
const EXAMPLE: &str = include_str!("inputs/4_test.txt");
55-
const PROD: &str = include_str!("inputs/4_prod.txt");
5643

5744
#[test]
5845
#[ignore = "Takes too long"]
59-
fn first_test() {
60-
let first_exercise = FourthDay {
61-
exercise: Exercise {
62-
content: String::from(PROD),
63-
example: String::from(EXAMPLE),
64-
},
65-
};
66-
67-
let expected_example = 1048970;
68-
let expected_prod = 346386;
69-
70-
let result_example = first_exercise.solve_first(false);
71-
let result_prod = first_exercise.solve_first(true);
72-
assert_eq!(expected_example, result_example);
73-
assert_eq!(expected_prod, result_prod);
74-
75-
let expected_example = 5714438;
76-
let expected_prod = 9958218;
77-
let result_example = first_exercise.solve_second(false);
78-
let result_prod = first_exercise.solve_second(true);
79-
assert_eq!(expected_example, result_example);
80-
assert_eq!(expected_prod, result_prod);
46+
fn test_day04() {
47+
let day = Day04;
48+
assert_eq!(day.part1("abcdef").to_string(), "609043");
49+
assert_eq!(day.part1("pqrstuv").to_string(), "1048970");
8150
}
8251
}

2015/src/day05.rs

Lines changed: 41 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,62 @@
1-
use crate::{Exercise, Solvable};
2-
use iter_tools::Itertools;
1+
use aoc_rust_common::Solution;
2+
use std::fmt::Display;
33
use rayon::prelude::*;
44

5-
struct FifthDay {
6-
exercise: Exercise,
7-
vowels: Vec<char>,
8-
filters: Vec<String>,
9-
}
10-
11-
impl Solvable for FifthDay {
12-
fn solve_first(&self, is_prod: bool) -> i64 {
13-
if is_prod {
14-
self.first(&self.exercise.content)
15-
} else {
16-
self.first(&self.exercise.example)
17-
}
18-
}
5+
pub struct Day05;
196

20-
fn solve_second(&self, is_prod: bool) -> i64 {
21-
if is_prod {
22-
self.second(&self.exercise.content)
23-
} else {
24-
self.second(&self.exercise.example)
25-
}
26-
}
7+
impl Solution for Day05 {
8+
fn year(&self) -> u32 { 2015 }
9+
fn day(&self) -> u32 { 5 }
2710

28-
fn first(&self, content: &str) -> i64 {
29-
content
11+
fn part1(&self, input: &str) -> Box<dyn Display> {
12+
let vowels = ['a', 'e', 'i', 'o', 'u'];
13+
let filters = ["ab", "cd", "pq", "xy"];
14+
15+
Box::new(input
3016
.par_lines()
31-
.filter(|line: &&str| line.chars().filter(|c| self.vowels.contains(c)).count() >= 3)
32-
.filter(|line: &&str| {
33-
line.chars()
34-
.enumerate()
35-
.any(|(i, c)| i > 0 && c == line.chars().nth(i - 1).unwrap())
17+
.filter(|line| line.chars().filter(|c| vowels.contains(c)).count() >= 3)
18+
.filter(|line| {
19+
let chars: Vec<char> = line.chars().collect();
20+
chars.windows(2).any(|w| w[0] == w[1])
3621
})
37-
.filter(|line: &&str| !self.filters.iter().any(|filter| line.contains(filter)))
38-
.count() as i64
22+
.filter(|line| !filters.iter().any(|&f| line.contains(f)))
23+
.count() as i64)
3924
}
4025

41-
fn second(&self, content: &str) -> i64 {
42-
content
26+
fn part2(&self, input: &str) -> Box<dyn Display> {
27+
Box::new(input
4328
.par_lines()
44-
.filter(|line| line.len() >= 3)
45-
.filter(|line: &&str| {
46-
line.chars()
47-
.enumerate()
48-
.any(|(i, c)| i > 2 && c == line.chars().nth(i - 2).unwrap())
29+
.filter(|line| {
30+
let chars: Vec<char> = line.chars().collect();
31+
chars.windows(3).any(|w| w[0] == w[2])
4932
})
50-
.filter(|line: &&str| {
51-
line.chars()
52-
.tuple_windows()
53-
.any(|(c1, c2)| line.matches(&format!("{}{}", c1, c2)).count() > 1)
33+
.filter(|line| {
34+
let chars: Vec<char> = line.chars().collect();
35+
(0..chars.len() - 1).any(|i| {
36+
let pair = &line[i..i+2];
37+
line[i+2..].contains(pair)
38+
})
5439
})
55-
.count() as i64
40+
.count() as i64)
5641
}
5742
}
5843

5944
#[cfg(test)]
6045
mod tests {
6146
use super::*;
62-
const EXAMPLE: &str = include_str!("inputs/5_test.txt");
63-
const PROD: &str = include_str!("inputs/5_prod.txt");
6447

6548
#[test]
66-
fn first_test() {
67-
let mut first_exercise = FifthDay {
68-
exercise: Exercise {
69-
content: String::from(PROD),
70-
example: String::from(EXAMPLE),
71-
},
72-
vowels: vec!['a', 'e', 'i', 'o', 'u'],
73-
filters: vec![
74-
String::from("ab"),
75-
String::from("cd"),
76-
String::from("pq"),
77-
String::from("xy"),
78-
],
79-
};
80-
81-
let expected_example = 2;
82-
let expected_prod = 255;
83-
84-
let result_example = first_exercise.solve_first(false);
85-
let result_prod = first_exercise.solve_first(true);
86-
assert_eq!(expected_example, result_example);
87-
assert_eq!(expected_prod, result_prod);
88-
89-
first_exercise.exercise.example =
90-
String::from("qjhvhtzxzqqjkmpb\nxxyxx\nuurcxstgmygtbstg\nieodomkazucvgmuy");
91-
92-
let expected_example = 2;
93-
let expected_prod = 55;
94-
let result_example = first_exercise.solve_second(false);
95-
let result_prod = first_exercise.solve_second(true);
96-
assert_eq!(expected_example, result_example);
97-
assert_eq!(expected_prod, result_prod);
49+
fn test_day05() {
50+
let day = Day05;
51+
assert_eq!(day.part1("ugknbfddgicrmopn").to_string(), "1");
52+
assert_eq!(day.part1("aaa").to_string(), "1");
53+
assert_eq!(day.part1("jchzalrnumimnmhp").to_string(), "0");
54+
assert_eq!(day.part1("haegwjzuvuyypxyu").to_string(), "0");
55+
assert_eq!(day.part1("dvszwmarrgswjxmb").to_string(), "0");
56+
57+
assert_eq!(day.part2("qjhvhtzxzqqjkmpb").to_string(), "1");
58+
assert_eq!(day.part2("xxyxx").to_string(), "1");
59+
assert_eq!(day.part2("uurcxstgmygtbstg").to_string(), "0");
60+
assert_eq!(day.part2("ieodomkazucvgmuy").to_string(), "0");
9861
}
9962
}

2015/src/main.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
mod day01;
22
mod day02;
3+
mod day03;
4+
mod day04;
5+
mod day05;
36

47
use aoc_rust_common::run_solution;
58
use day01::Day01;
69
use day02::Day02;
10+
use day03::Day03;
11+
use day04::Day04;
12+
use day05::Day05;
713

814
fn main() {
915
run_solution(Day01);
1016
run_solution(Day02);
17+
run_solution(Day03);
18+
run_solution(Day04);
19+
run_solution(Day05);
1120
}

0 commit comments

Comments
 (0)