Skip to content

Commit 37c06e0

Browse files
committed
refactor: apply aoc-rust-common to 2015 days 11-15
1 parent 6fb9836 commit 37c06e0

6 files changed

Lines changed: 205 additions & 576 deletions

File tree

2015/src/day11.rs

Lines changed: 32 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
use crate::Exercise;
1+
use aoc_rust_common::Solution;
2+
use std::fmt::Display;
23

3-
struct EleventhDay {
4-
exercise: Exercise,
5-
}
4+
pub struct Day11;
65

76
fn increment(character: char) -> char {
87
match character {
@@ -11,15 +10,16 @@ fn increment(character: char) -> char {
1110
}
1211
}
1312

14-
fn has_two_non_overlapping_pairs(password: &mut str) -> bool {
13+
fn has_two_non_overlapping_pairs(password: &str) -> bool {
1514
let mut pairs = 0;
1615
let mut index = 0;
16+
let chars: Vec<char> = password.chars().collect();
1717
loop {
18-
if index >= password.len() - 1 {
18+
if index >= chars.len() - 1 {
1919
break;
2020
}
21-
let character = password.chars().nth(index).unwrap();
22-
let next_character = password.chars().nth(index + 1).unwrap();
21+
let character = chars[index];
22+
let next_character = chars[index + 1];
2323
if character == next_character {
2424
pairs += 1;
2525
index += 2;
@@ -30,16 +30,11 @@ fn has_two_non_overlapping_pairs(password: &mut str) -> bool {
3030
pairs >= 2
3131
}
3232

33-
fn is_valid_password(password: &mut str) -> bool {
33+
fn is_valid_password(password: &str) -> bool {
34+
let chars: Vec<char> = password.chars().collect();
3435
let mut triples = 0;
35-
for window in password.chars().collect::<Vec<char>>().windows(3) {
36-
if window[0] == 'i' || window[0] == 'o' || window[0] == 'l' {
37-
return false;
38-
}
39-
if window[1] == 'i' || window[1] == 'o' || window[1] == 'l' {
40-
return false;
41-
}
42-
if window[2] == 'i' || window[2] == 'o' || window[2] == 'l' {
36+
for window in chars.windows(3) {
37+
if window.iter().any(|&c| c == 'i' || c == 'o' || c == 'l') {
4338
return false;
4439
}
4540
if window[0] as u8 + 1 == window[1] as u8 && window[1] as u8 + 1 == window[2] as u8 {
@@ -57,87 +52,53 @@ fn create_new_password(password: String) -> String {
5752
let mut password = password;
5853
loop {
5954
password = increment_password(password);
60-
if is_valid_password(&mut password) {
55+
if is_valid_password(&password) {
6156
break;
6257
}
6358
}
6459
password
6560
}
6661

6762
fn increment_password(password: String) -> String {
68-
let mut password = password;
69-
let mut index = password.len() - 1;
63+
let mut chars: Vec<char> = password.chars().collect();
64+
let mut index = chars.len() - 1;
7065
loop {
71-
let character = password.chars().nth(index).unwrap();
66+
let character = chars[index];
7267
let new_character = increment(character);
73-
password.replace_range(index..=index, &new_character.to_string());
68+
chars[index] = new_character;
7469
if new_character == 'a' {
70+
if index == 0 { break; }
7571
index -= 1;
7672
} else {
7773
break;
7874
}
7975
}
80-
password
76+
chars.iter().collect()
8177
}
8278

83-
impl EleventhDay {
84-
fn solve_first(&self, is_prod: bool) -> String {
85-
if is_prod {
86-
self.first(self.exercise.content.clone())
87-
} else {
88-
self.first(self.exercise.example.clone())
89-
}
90-
}
91-
92-
fn solve_second(&self, is_prod: bool) -> String {
93-
if is_prod {
94-
self.second(self.exercise.content.clone())
95-
} else {
96-
self.second(self.exercise.example.clone())
97-
}
98-
}
79+
impl Solution for Day11 {
80+
fn year(&self) -> u32 { 2015 }
81+
fn day(&self) -> u32 { 11 }
9982

100-
fn first(&self, content: String) -> String {
101-
create_new_password(content)
83+
fn part1(&self, input: &str) -> Box<dyn Display> {
84+
Box::new(create_new_password(input.trim().to_owned()))
10285
}
10386

104-
fn second(&self, _content: String) -> String {
105-
"asd".to_owned()
87+
fn part2(&self, input: &str) -> Box<dyn Display> {
88+
let p1 = create_new_password(input.trim().to_owned());
89+
Box::new(create_new_password(p1))
10690
}
10791
}
10892

10993
#[cfg(test)]
11094
mod tests {
11195
use super::*;
112-
const EXAMPLE: &str = include_str!("inputs/11_test.txt");
113-
const PROD: &str = include_str!("inputs/11_prod.txt");
114-
115-
#[test]
116-
fn test_valid_password() {
117-
let is_valid = is_valid_password(&mut "abcdffaa".to_owned());
118-
assert_eq!(is_valid, true);
119-
}
12096

12197
#[test]
122-
#[ignore = "Takes too long"]
123-
fn first_test() {
124-
let mut first_exercise = EleventhDay {
125-
exercise: Exercise {
126-
content: String::from(PROD),
127-
example: String::from(EXAMPLE),
128-
},
129-
};
130-
131-
let expected_example = "abcdffaa";
132-
let expected_prod = "hxbxxyzz";
133-
134-
let result_example = first_exercise.solve_first(false);
135-
let result_prod = first_exercise.solve_first(true);
136-
assert_eq!(expected_example, result_example);
137-
assert_eq!(expected_prod, result_prod);
138-
139-
let expected_prod = "hxcaabcc";
140-
let result_prod = create_new_password(result_prod);
141-
assert_eq!(expected_prod, result_prod);
98+
fn test_day11() {
99+
assert!(is_valid_password("abcdffaa"));
100+
assert!(!is_valid_password("hijklmmn"));
101+
assert!(!is_valid_password("abbceffg"));
102+
assert!(!is_valid_password("abbcegjk"));
142103
}
143104
}

2015/src/day12.rs

Lines changed: 21 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
use crate::Exercise;
1+
use aoc_rust_common::Solution;
2+
use std::fmt::Display;
23
use serde_json::Value;
34

4-
struct TwelvfthDay {
5-
exercise: Exercise,
6-
}
5+
pub struct Day12;
76

87
fn count_value(value: &Value) -> i32 {
98
match value {
10-
Value::Number(e) => e.as_i64().unwrap() as i32,
9+
Value::Number(e) => e.as_i64().unwrap_or(0) as i32,
1110
Value::Array(array) => array.iter().map(count_value).sum(),
1211
Value::Object(object) => object.values().map(count_value).sum(),
1312
_ => 0,
@@ -16,10 +15,10 @@ fn count_value(value: &Value) -> i32 {
1615

1716
fn skip_red(value: &Value) -> i32 {
1817
match value {
19-
Value::Number(e) => e.as_i64().unwrap() as i32,
18+
Value::Number(e) => e.as_i64().unwrap_or(0) as i32,
2019
Value::Array(array) => array.iter().map(skip_red).sum(),
2120
Value::Object(object) => {
22-
if object.values().any(|v| v == "red") {
21+
if object.values().any(|v| v.as_str() == Some("red")) {
2322
0
2423
} else {
2524
object.values().map(skip_red).sum()
@@ -29,63 +28,31 @@ fn skip_red(value: &Value) -> i32 {
2928
}
3029
}
3130

32-
impl TwelvfthDay {
33-
fn solve_first(&self, is_prod: bool) -> i64 {
34-
if is_prod {
35-
self.first(&self.exercise.content)
36-
} else {
37-
self.first(&self.exercise.example)
38-
}
39-
}
40-
41-
fn solve_second(&self, is_prod: bool) -> i64 {
42-
if is_prod {
43-
self.second(&self.exercise.content)
44-
} else {
45-
self.second(&self.exercise.example)
46-
}
47-
}
31+
impl Solution for Day12 {
32+
fn year(&self) -> u32 { 2015 }
33+
fn day(&self) -> u32 { 12 }
4834

49-
fn first(&self, content: &str) -> i64 {
50-
let value: Value = serde_json::from_str(content).unwrap();
51-
count_value(&value) as i64
35+
fn part1(&self, input: &str) -> Box<dyn Display> {
36+
let value: Value = serde_json::from_str(input).unwrap();
37+
Box::new(count_value(&value) as i64)
5238
}
5339

54-
fn second(&self, content: &str) -> i64 {
55-
let value: Value = serde_json::from_str(content).unwrap();
56-
skip_red(&value) as i64
40+
fn part2(&self, input: &str) -> Box<dyn Display> {
41+
let value: Value = serde_json::from_str(input).unwrap();
42+
Box::new(skip_red(&value) as i64)
5743
}
5844
}
5945

6046
#[cfg(test)]
6147
mod tests {
6248
use super::*;
63-
const EXAMPLE: &str = include_str!("inputs/12_test.txt");
64-
const PROD: &str = include_str!("inputs/12_prod.txt");
6549

6650
#[test]
67-
fn first_test() {
68-
let mut first_exercise = TwelvfthDay {
69-
exercise: Exercise {
70-
content: String::from(PROD),
71-
example: String::from(EXAMPLE),
72-
},
73-
};
74-
75-
let expected_example = 3;
76-
let expected_prod = 156366;
77-
78-
let result_example = first_exercise.solve_first(false);
79-
let result_prod = first_exercise.solve_first(true);
80-
assert_eq!(expected_example, result_example);
81-
assert_eq!(expected_prod, result_prod);
82-
83-
let expected_example = 3;
84-
let expected_prod = 96852;
85-
86-
let result_example = first_exercise.solve_second(false);
87-
let result_prod = first_exercise.solve_second(true);
88-
assert_eq!(expected_example, result_example);
89-
assert_eq!(expected_prod, result_prod);
51+
fn test_day12() {
52+
let day = Day12;
53+
assert_eq!(day.part1("[1,2,3]").to_string(), "6");
54+
assert_eq!(day.part1(r#"{"a":2,"b":4}"#).to_string(), "6");
55+
assert_eq!(day.part2("[1,2,3]").to_string(), "6");
56+
assert_eq!(day.part2(r#"[1,{"c":"red","a":2},3]"#).to_string(), "4");
9057
}
9158
}

0 commit comments

Comments
 (0)