use aoc; use std::io::{BufRead, BufReader, Read}; use aoc::Day; use regex::Regex; struct Day4 {} enum Direction { Horizontal, Vertical, DiagonalDown, DiagonalUp, } impl Day4 { fn parse_input(&self, input: BufReader>) -> Vec { input .lines() .map(|l| { l .unwrap() .trim() .to_string() }) .collect::>() } fn _diagonal_half_loop(&self, input: &Vec) -> Vec { let mut out: Vec = vec![]; for y in 0..input.len() { let mut out_row = String::new(); for (x, row) in input[0..y + 1].iter().rev().enumerate() { out_row.push(row.chars().nth(x).unwrap()); } out.push(out_row) } out } fn _rotate(&self, input: &Vec) -> Vec { let mut output: Vec = vec![]; for (i, _) in input[0].char_indices() { let mut line_out = String::new(); for line in input { let a = line.chars().nth(i).unwrap(); line_out.push(a) } output.push(line_out.chars().rev().collect::()); } output } fn _mirror(&self, input: &Vec) -> Vec { input .iter() .map(|l| { l .chars() .rev() .collect::() }) .collect::>() } fn diagonal_loop(&self, input: &Vec) -> Vec { let mut first_half: Vec = self._diagonal_half_loop(input); let rev_input = input .iter() .rev() .map(|row| { row .chars() .rev() .collect::() }) .collect::>(); let mut second_half = self ._diagonal_half_loop(&rev_input) .iter() .rev() .collect::>()[1..] .iter() .map(|row| { row .chars() .rev() .collect::() }) .collect::>(); first_half.append(&mut second_half); first_half } fn loop_over_puzzle(&self, input: &Vec, direction: Direction, rev: bool) -> Vec { let _input = if rev { self._rotate(&self._rotate(&input)) } else { input.clone() }; match direction { Direction::Horizontal => _input, Direction::Vertical => self._mirror(&self._rotate(&_input)), Direction::DiagonalUp => self.diagonal_loop(&_input), Direction::DiagonalDown => self.diagonal_loop(&self._rotate(&_input)), } } } impl Day for Day4 { fn example_input(&self) -> &'static str { r#" MMMSXXMASM MSAMXMSMSA AMXSXMAAMM MSAMASMSMX XMASAMXAMM XXAMMXXAMA SMSMSASXSS SAXAMASAAA MAMMMXMMMM MXMXAXMASX "#.trim() // r#" // 123 // 456 // 789 // "#.trim() } fn example_result_part_1(&self) -> &'static str { "18" } fn example_result_part_2(&self) -> &'static str { "9" } fn part_1(&self, input: BufReader>) -> String { let puzzle = self.parse_input(input); let mut all_possibilities: Vec = vec![]; all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::Horizontal, false)); all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::Horizontal, true)); all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::Vertical, false)); all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::Vertical, true)); all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::DiagonalUp, false)); all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::DiagonalUp, true)); all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::DiagonalDown, false)); all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::DiagonalDown, true)); let re = Regex::new("XMAS"); all_possibilities .into_iter() .map(|l| { re .clone() .unwrap() .find_iter(&l) .count() }) .sum::() .to_string() } fn part_2(&self, input: BufReader>) -> String { let puzzle = self.parse_input(input); let mut all_possibilities: Vec = vec![]; all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::DiagonalUp, false)); all_possibilities.append(&mut self.loop_over_puzzle(&puzzle, Direction::DiagonalDown, false)); let re = Regex::new("MAS|SAM"); all_possibilities .into_iter() .map(|l| { re .clone() .unwrap() .find_iter(&l) .map(|m| println!("{:#?}", m)) .count() }) .sum::() .to_string() } } fn main() { aoc::main(&Day4 {}); } #[cfg(test)] mod tests { use super::*; #[test] fn test_day4() { aoc::test_day(&Day4 {}); } }