summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.idea/aoc2024.iml1
-rw-r--r--Cargo.toml2
-rw-r--r--day4/Cargo.toml8
-rw-r--r--day4/src/main.rs215
4 files changed, 225 insertions, 1 deletions
diff --git a/.idea/aoc2024.iml b/.idea/aoc2024.iml
index 779b5d8..5a17898 100644
--- a/.idea/aoc2024.iml
+++ b/.idea/aoc2024.iml
@@ -7,6 +7,7 @@
7 <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> 7 <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
8 <sourceFolder url="file://$MODULE_DIR$/day2/src" isTestSource="false" /> 8 <sourceFolder url="file://$MODULE_DIR$/day2/src" isTestSource="false" />
9 <sourceFolder url="file://$MODULE_DIR$/day3/src" isTestSource="false" /> 9 <sourceFolder url="file://$MODULE_DIR$/day3/src" isTestSource="false" />
10 <sourceFolder url="file://$MODULE_DIR$/day4/src" isTestSource="false" />
10 <excludeFolder url="file://$MODULE_DIR$/aoc/target" /> 11 <excludeFolder url="file://$MODULE_DIR$/aoc/target" />
11 <excludeFolder url="file://$MODULE_DIR$/target" /> 12 <excludeFolder url="file://$MODULE_DIR$/target" />
12 </content> 13 </content>
diff --git a/Cargo.toml b/Cargo.toml
index 2e030b6..fac2cfd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,3 +1,3 @@
1[workspace] 1[workspace]
2members = ["aoc", "day1", "day2", "day3"] 2members = ["aoc", "day1", "day2", "day3", "day4"]
3resolver = "2" 3resolver = "2"
diff --git a/day4/Cargo.toml b/day4/Cargo.toml
new file mode 100644
index 0000000..3161844
--- /dev/null
+++ b/day4/Cargo.toml
@@ -0,0 +1,8 @@
1[package]
2name = "day4"
3version = "0.1.0"
4edition = "2021"
5
6[dependencies]
7aoc = { path = "../aoc" }
8regex = "1.11.1"
diff --git a/day4/src/main.rs b/day4/src/main.rs
new file mode 100644
index 0000000..c788292
--- /dev/null
+++ b/day4/src/main.rs
@@ -0,0 +1,215 @@
1use aoc;
2use std::io::{BufRead, BufReader, Read};
3use aoc::Day;
4use regex::Regex;
5
6struct Day4 {}
7
8enum Direction {
9 Horizontal,
10 Vertical,
11 DiagonalDown,
12 DiagonalUp,
13}
14
15impl Day4 {
16 fn parse_input(&self, input: BufReader<Box<dyn Read>>) -> Vec<String> {
17 input
18 .lines()
19 .map(|l| {
20 l
21 .unwrap()
22 .trim()
23 .to_string()
24 })
25 .collect::<Vec<String>>()
26 }
27
28 fn _diagonal_half_loop(&self, input: &Vec<String>) -> Vec<String> {
29 let mut out: Vec<String> = vec![];
30 for y in 0..input.len() {
31 let mut out_row = String::new();
32
33 for (x, row) in input[0..y + 1].iter().rev().enumerate() {
34 out_row.push(row.chars().nth(x).unwrap());
35 }
36
37 out.push(out_row)
38 }
39
40 out
41 }
42
43 fn _rotate(&self, input: &Vec<String>) -> Vec<String> {
44 let mut output: Vec<String> = vec![];
45
46 for (i, _) in input[0].char_indices() {
47 let mut line_out = String::new();
48 for line in input {
49 let a = line.chars().nth(i).unwrap();
50 line_out.push(a)
51 }
52
53 output.push(line_out.chars().rev().collect::<String>());
54 }
55
56 output
57 }
58
59 fn _mirror(&self, input: &Vec<String>) -> Vec<String> {
60 input
61 .iter()
62 .map(|l| {
63 l
64 .chars()
65 .rev()
66 .collect::<String>()
67 })
68 .collect::<Vec<String>>()
69 }
70
71 fn diagonal_loop(&self, input: &Vec<String>) -> Vec<String> {
72 let mut first_half: Vec<String> = self._diagonal_half_loop(input);
73
74 let rev_input = input
75 .iter()
76 .rev()
77 .map(|row| {
78 row
79 .chars()
80 .rev()
81 .collect::<String>()
82 })
83 .collect::<Vec<String>>();
84
85
86 let mut second_half = self
87 ._diagonal_half_loop(&rev_input)
88 .iter()
89 .rev()
90 .collect::<Vec<_>>()[1..]
91 .iter()
92 .map(|row| {
93 row
94 .chars()
95 .rev()
96 .collect::<String>()
97 })
98 .collect::<Vec<String>>();
99
100
101 first_half.append(&mut second_half);
102 first_half
103 }
104
105 fn loop_over_puzzle(&self, input: &Vec<String>, direction: Direction, rev: bool) -> Vec<String> {
106 let _input = if rev {
107 self._rotate(&self._rotate(&input))
108 } else {
109 input.clone()
110 };
111
112
113 match direction {
114 Direction::Horizontal => _input,
115 Direction::Vertical => self._mirror(&self._rotate(&_input)),
116 Direction::DiagonalUp => self.diagonal_loop(&_input),
117 Direction::DiagonalDown => self.diagonal_loop(&self._rotate(&_input)),
118 }
119 }
120}
121
122impl Day for Day4 {
123 fn example_input(&self) -> &'static str {
124 r#"
125 MMMSXXMASM
126 MSAMXMSMSA
127 AMXSXMAAMM
128 MSAMASMSMX
129 XMASAMXAMM
130 XXAMMXXAMA
131 SMSMSASXSS
132 SAXAMASAAA
133 MAMMMXMMMM
134 MXMXAXMASX
135 "#.trim()
136 // r#"
137 // 123
138 // 456
139 // 789
140 // "#.trim()
141 }
142
143 fn example_result_part_1(&self) -> &'static str {
144 "18"
145 }
146
147 fn example_result_part_2(&self) -> &'static str {
148 "9"
149 }
150
151 fn part_1(&self, input: BufReader<Box<dyn Read>>) -> String {
152 let puzzle = self.parse_input(input);
153
154 let mut all_possibilities: Vec<String> = vec![];
155
156 all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::Horizontal, false));
157 all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::Horizontal, true));
158 all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::Vertical, false));
159 all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::Vertical, true));
160 all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::DiagonalUp, false));
161 all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::DiagonalUp, true));
162 all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::DiagonalDown, false));
163 all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::DiagonalDown, true));
164
165 let re = Regex::new("XMAS");
166 all_possibilities
167 .into_iter()
168 .map(|l| {
169 re
170 .clone()
171 .unwrap()
172 .find_iter(&l)
173 .count()
174 })
175 .sum::<usize>()
176 .to_string()
177 }
178
179 fn part_2(&self, input: BufReader<Box<dyn Read>>) -> String {
180 let puzzle = self.parse_input(input);
181
182 let mut all_possibilities: Vec<String> = vec![];
183
184 all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::DiagonalUp, false));
185 all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::DiagonalDown, false));
186
187 let re = Regex::new("MAS|SAM");
188 all_possibilities
189 .into_iter()
190 .map(|l| {
191 re
192 .clone()
193 .unwrap()
194 .find_iter(&l)
195 .map(|m| println!("{:#?}", m))
196 .count()
197 })
198 .sum::<usize>()
199 .to_string()
200 }
201}
202
203
204fn main() {
205 aoc::main(&Day4 {});
206}
207
208#[cfg(test)]
209mod tests {
210 use super::*;
211