day4
This commit is contained in:
@@ -4,3 +4,4 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
regex = "1.11.1"
|
||||||
|
|||||||
80
day4/Readme.md
Normal file
80
day4/Readme.md
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
--- Day 4: Ceres Search ---
|
||||||
|
"Looks like the Chief's not here. Next!" One of The Historians pulls out a device and pushes the only button on it. After a brief flash, you recognize the interior of the Ceres monitoring station!
|
||||||
|
|
||||||
|
As the search for the Chief continues, a small Elf who lives on the station tugs on your shirt; she'd like to know if you could help her with her word search (your puzzle input). She only has to find one word: XMAS.
|
||||||
|
|
||||||
|
This word search allows words to be horizontal, vertical, diagonal, written backwards, or even overlapping other words. It's a little unusual, though, as you don't merely need to find one instance of XMAS - you need to find all of them. Here are a few ways XMAS might appear, where irrelevant characters have been replaced with .:
|
||||||
|
|
||||||
|
```
|
||||||
|
..X...
|
||||||
|
.SAMX.
|
||||||
|
.A..A.
|
||||||
|
XMAS.S
|
||||||
|
.X....
|
||||||
|
```
|
||||||
|
|
||||||
|
The actual word search will be full of letters instead. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
MMMSXXMASM
|
||||||
|
MSAMXMSMSA
|
||||||
|
AMXSXMAAMM
|
||||||
|
MSAMASMSMX
|
||||||
|
XMASAMXAMM
|
||||||
|
XXAMMXXAMA
|
||||||
|
SMSMSASXSS
|
||||||
|
SAXAMASAAA
|
||||||
|
MAMMMXMMMM
|
||||||
|
MXMXAXMASX
|
||||||
|
```
|
||||||
|
|
||||||
|
In this word search, XMAS occurs a total of 18 times; here's the same word search again, but where letters not involved in any XMAS have been replaced with .:
|
||||||
|
|
||||||
|
```
|
||||||
|
....XXMAS.
|
||||||
|
.SAMXMS...
|
||||||
|
...S..A...
|
||||||
|
..A.A.MS.X
|
||||||
|
XMASAMX.MM
|
||||||
|
X.....XA.A
|
||||||
|
S.S.S.S.SS
|
||||||
|
.A.A.A.A.A
|
||||||
|
..M.M.M.MM
|
||||||
|
.X.X.XMASX
|
||||||
|
```
|
||||||
|
Take a look at the little Elf's word search. How many times does XMAS appear?
|
||||||
|
|
||||||
|
Your puzzle answer was 2462.
|
||||||
|
|
||||||
|
The first half of this puzzle is complete! It provides one gold star: *
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
The Elf looks quizzically at you. Did you misunderstand the assignment?
|
||||||
|
|
||||||
|
Looking for the instructions, you flip over the word search to find that this isn't actually an XMAS puzzle; it's an X-MAS puzzle in which you're supposed to find two MAS in the shape of an X. One way to achieve that is like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
M.S
|
||||||
|
.A.
|
||||||
|
M.S
|
||||||
|
```
|
||||||
|
|
||||||
|
Irrelevant characters have again been replaced with . in the above diagram. Within the X, each MAS can be written forwards or backwards.
|
||||||
|
|
||||||
|
Here's the same example from before, but this time all of the X-MASes have been kept instead:
|
||||||
|
|
||||||
|
```
|
||||||
|
.M.S......
|
||||||
|
..A..MSMS.
|
||||||
|
.M.S.MAA..
|
||||||
|
..A.ASMSM.
|
||||||
|
.M.S.M....
|
||||||
|
..........
|
||||||
|
S.S.S.S.S.
|
||||||
|
.A.A.A.A..
|
||||||
|
M.M.M.M.M.
|
||||||
|
..........
|
||||||
|
```
|
||||||
|
In this example, an X-MAS appears 9 times.
|
||||||
|
|
||||||
|
Flip the word search from the instructions back over to the word search side and try again. How many times does an X-MAS appear?
|
||||||
@@ -7,4 +7,4 @@ XXAMMXXAMA
|
|||||||
SMSMSASXSS
|
SMSMSASXSS
|
||||||
SAXAMASAAA
|
SAXAMASAAA
|
||||||
MAMMMXMMMM
|
MAMMMXMMMM
|
||||||
MXMXAXMASX
|
MXMXAXMASX
|
||||||
131
day4/src/main.rs
131
day4/src/main.rs
@@ -1,3 +1,130 @@
|
|||||||
fn main() {
|
use regex::Regex;
|
||||||
println!("Hello, world!");
|
|
||||||
|
struct Direction(char, usize, i32, bool);
|
||||||
|
|
||||||
|
impl Direction {
|
||||||
|
fn new(start: char, position: usize, length: usize) -> Vec<Self> {
|
||||||
|
let (next, is_forward) = match start {
|
||||||
|
'X' => ('M', true),
|
||||||
|
'S' => ('A', false),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let mut directions = vec![Direction(next, position, 0, is_forward)];
|
||||||
|
if position >= 3 {
|
||||||
|
directions.push(Direction(next, position - 1, -1, is_forward));
|
||||||
|
}
|
||||||
|
if position + 3 < length {
|
||||||
|
directions.push(Direction(next, position + 1, 1, is_forward));
|
||||||
|
}
|
||||||
|
directions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_char(c: char, is_forward: bool) -> char {
|
||||||
|
match (c, is_forward) {
|
||||||
|
('X', true) => 'M',
|
||||||
|
('M', true) => 'A',
|
||||||
|
('A', true) => 'S',
|
||||||
|
('S', true) => 'E',
|
||||||
|
('S', false) => 'A',
|
||||||
|
('A', false) => 'M',
|
||||||
|
('M', false) => 'X',
|
||||||
|
('X', false) => 'E',
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prob1() {
|
||||||
|
let input = std::fs::read_to_string("input.txt").unwrap();
|
||||||
|
let lines = input.lines();
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
let re_xmas = Regex::new(r"XMAS").unwrap();
|
||||||
|
let re_samx = Regex::new(r"SAMX").unwrap();
|
||||||
|
let re_single = Regex::new(r"[XS]").unwrap();
|
||||||
|
let mut candidates = vec![];
|
||||||
|
for line in lines {
|
||||||
|
let line = line.trim();
|
||||||
|
let line_length = line.len();
|
||||||
|
|
||||||
|
let mut new_candidates = vec![];
|
||||||
|
for direction in candidates.iter() {
|
||||||
|
let Direction(char_should_be, position, step, is_forward) = direction;
|
||||||
|
if line.chars().nth(*position).unwrap() == *char_should_be {
|
||||||
|
let next = next_char(*char_should_be, *is_forward);
|
||||||
|
if next == 'E' {
|
||||||
|
count += 1;
|
||||||
|
} else {
|
||||||
|
new_candidates.push(Direction(
|
||||||
|
next,
|
||||||
|
(*position as i32 + step) as usize,
|
||||||
|
*step,
|
||||||
|
*is_forward,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count += re_xmas.find_iter(line).count();
|
||||||
|
count += re_samx.find_iter(line).count();
|
||||||
|
|
||||||
|
for m in re_single.find_iter(line) {
|
||||||
|
let position = m.start();
|
||||||
|
new_candidates.append(&mut Direction::new(
|
||||||
|
m.as_str().chars().next().unwrap(),
|
||||||
|
position,
|
||||||
|
line_length,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
candidates = new_candidates;
|
||||||
|
}
|
||||||
|
println!("{count}");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn opposite_char(c: Option<&char>) -> Result<char, ()> {
|
||||||
|
match c {
|
||||||
|
Some('S') => Ok('M'),
|
||||||
|
Some('M') => Ok('S'),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prob2() {
|
||||||
|
let input = std::fs::read_to_string("input.txt").unwrap();
|
||||||
|
let mut lines = input.lines();
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
let re_a = Regex::new(r"A").unwrap();
|
||||||
|
let mut prev_line = lines.next().unwrap().trim().chars().collect::<Vec<char>>();
|
||||||
|
let mut candidates = vec![];
|
||||||
|
for line in lines {
|
||||||
|
let line = line.trim();
|
||||||
|
let last_index = line.len() - 1;
|
||||||
|
let chars = line.chars().collect::<Vec<char>>();
|
||||||
|
for ((c1, pos1), (c2, pos2)) in candidates {
|
||||||
|
if chars[pos1] == c1 && chars[pos2] == c2 {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
candidates = vec![];
|
||||||
|
for m in re_a.find_iter(line) {
|
||||||
|
let position = m.start();
|
||||||
|
if position == 0 || position == last_index {
|
||||||
|
continue;
|
||||||
|
} else if let Ok(c1) = opposite_char(prev_line.get(position - 1)) {
|
||||||
|
if let Ok(c2) = opposite_char(prev_line.get(position + 1)) {
|
||||||
|
candidates.push(((c1, position + 1), (c2, position - 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_line = chars;
|
||||||
|
}
|
||||||
|
println!("{count}");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
prob1();
|
||||||
|
prob2();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user