diff --git a/examples/2024/01.txt b/examples/2024/01.txt new file mode 100644 index 0000000..b8af9ad --- /dev/null +++ b/examples/2024/01.txt @@ -0,0 +1,6 @@ +3 4 +4 3 +2 5 +1 3 +3 9 +3 3 diff --git a/examples/2024/02.txt b/examples/2024/02.txt new file mode 100644 index 0000000..b49c10d --- /dev/null +++ b/examples/2024/02.txt @@ -0,0 +1,6 @@ +7 6 4 2 1 +1 2 7 8 9 +9 7 6 2 1 +1 3 2 4 5 +8 6 4 4 1 +1 3 6 7 9 diff --git a/examples/2024/04.txt b/examples/2024/04.txt new file mode 100644 index 0000000..1bb64a4 --- /dev/null +++ b/examples/2024/04.txt @@ -0,0 +1,17 @@ +S.MX +.A.M +S.MA +M.MS +.A.. +S.S. +S.S. +.A.. +M.M. +M.SS +.A.A +M.SM +SAMX +.... +M... +AA.. +S.S. diff --git a/examples/2024/06.txt b/examples/2024/06.txt new file mode 100644 index 0000000..a4eb402 --- /dev/null +++ b/examples/2024/06.txt @@ -0,0 +1,10 @@ +....#..... +.........# +.......... +..#....... +.......#.. +.......... +.#..^..... +........#. +#......... +......#... diff --git a/src/bin/2024/01.rs b/src/bin/2024/01.rs index 23b1fde..5356d1c 100644 --- a/src/bin/2024/01.rs +++ b/src/bin/2024/01.rs @@ -1,9 +1,18 @@ -use advent_of_code::strings::{convert_to_array, parsenumber, splitspace}; +use advent_of_code::strings::{convert_to_array, parsenumber}; #[allow(unused_imports)] use advent_of_code::{include_data, include_example}; include_data!(DATA 2024 01); +pub fn splitspace(input: &str) -> (u32, u32) { + println!("{}", input); + let mut output = input.split_ascii_whitespace(); + ( + parsenumber(output.next().unwrap()), + parsenumber(output.next().unwrap()), + ) +} + fn distance(leftlist: &Vec, rightlist: &Vec) -> u32 { let mut distance = 0; for i in 0..leftlist.len() { @@ -38,8 +47,8 @@ fn main() { let mut leftlist = Vec::::with_capacity(1000); let mut rightlist = Vec::::with_capacity(1000); for (left, right) in convert_to_array::<_, _, '\n'>(DATA, splitspace) { - leftlist.push(parsenumber(left)); - rightlist.push(parsenumber(right)); + leftlist.push(left); + rightlist.push(right); } leftlist.sort(); rightlist.sort(); diff --git a/src/bin/2024/02.rs b/src/bin/2024/02.rs index 4eb9faa..cbbd67d 100644 --- a/src/bin/2024/02.rs +++ b/src/bin/2024/02.rs @@ -101,7 +101,7 @@ fn safe(record: Vec) -> bool { } fn main() { - let numbers = convert_to_array::<_,_,'\n'>(DATA, get_numbers); + let numbers = convert_to_array::<_, _, '\n'>(DATA, get_numbers); let mut safe_reports = 0; let mut safe_with_dampener = 0; for report in numbers { diff --git a/src/bin/2024/03.rs b/src/bin/2024/03.rs index fa98d31..db64628 100644 --- a/src/bin/2024/03.rs +++ b/src/bin/2024/03.rs @@ -31,8 +31,8 @@ fn main() { ("do()", _) => parse = true, ("don't()", _) => parse = false, (_, true) => { - let a = parsenumber(capture.name("i").unwrap().as_str()); - let b = parsenumber(capture.name("j").unwrap().as_str()); + let a = parsenumber::(capture.name("i").unwrap().as_str()); + let b = parsenumber::(capture.name("j").unwrap().as_str()); sum += a * b } (_, _) => {} diff --git a/src/bin/2024/04.rs b/src/bin/2024/04.rs index 814feeb..37d6dcc 100644 --- a/src/bin/2024/04.rs +++ b/src/bin/2024/04.rs @@ -1,78 +1,220 @@ -#[allow(unused_variables)] -use std::ops::RangeInclusive; +use std::ops::Neg; +#[allow(unused_variables)] #[allow(unused_imports)] use advent_of_code::{include_data, include_example}; +use advent_of_code::{ + matrix, + strings::{convert_to_array, line_to_char}, +}; -include_data!(DATA 2024 04); +include_example!(DATA 2024 04); -#[derive(Debug, Clone)] -enum Direction { - Forward(usize, usize), - Backward(usize, usize), +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)] +struct TextPos { + startx: usize, + starty: usize, + endx: usize, + endy: usize, + length: usize, } -impl Direction { - fn iter(&self) -> RangeInclusive { - let (from, to) = match self { - Direction::Forward(from, to) => (from, to), - Direction::Backward(to, from) => (from, to), - }; - *from..=*to +#[inline] +fn dist(a: (usize, usize), b: (usize, usize)) -> (i32, i32) { + (a.0 as i32 - b.0 as i32, a.1 as i32 - b.1 as i32) +} + +#[inline] +fn dist_abs(a: (usize, usize), b: (usize, usize)) -> (usize, usize) { + let t = dist(a, b); + (t.0.abs() as usize, t.1.abs() as usize) +} + +impl TextPos { + const fn center(self) -> (usize, usize) { + ( + self.startx.saturating_add(self.endx).div_ceil(2), + self.starty.saturating_add(self.endy).div_ceil(2), + ) + } + + fn crossing(self, other: &&Self) -> bool { + if self.length != other.length && self.length != 3 { + todo!() + } + if self.center() != other.center() { + return false; + } + true } } -fn main() { - let table: Vec> = DATA - .split('\n') - .map(|line| line.chars().collect()) - .collect(); - let length = table[0].len(); - let mut xmas; - let mut amount = 0; - let directions = [ - Direction::Forward(0, length - 1), - Direction::Backward(0, length - 1), +#[test] +fn test_crossing() { + let cases = [ + ( + TextPos { + startx: 0, + starty: 0, + endx: 2, + endy: 2, + length: 3, + }, + TextPos { + startx: 0, + starty: 0, + endx: 2, + endy: 2, + length: 3, + }, + true, + ), + ( + TextPos { + startx: 1, + starty: 0, + endx: 1, + endy: 2, + length: 3, + }, + TextPos { + startx: 0, + starty: 1, + endx: 2, + endy: 1, + length: 3, + }, + true, + ), + ( + TextPos { + startx: 0, + starty: 0, + endx: 2, + endy: 0, + length: 3, + }, + TextPos { + startx: 1, + starty: 0, + endx: 2, + endy: 0, + length: 3, + }, + false, + ), ]; - for r in directions.clone() { - for c in directions.clone() { - println!("Horizontal: {:?}, vertical: {:?}", r.clone(), c.clone()); - for row in r.iter() { - xmas = 0; - for column in c.iter() { - println!( - "Row {}, Column {}, dir {:?} {:?}", - row, - column, - r.clone(), - c.clone() - ); - match (xmas, table[row][column]) { - (_x, 'X') => { - xmas = 1; - //println!("Found X, previous was {}", _x) - } - (1, 'M') => { - xmas = 2; - //println!("Found XM") - } - (2, 'A') => { - xmas = 3; - //println!("Found XMA") - } - (3, 'S') => { - xmas = 0; - amount += 1; - //println!("found XMAS in {}:{}", row, column); - } - (_x, _ch) => { - xmas = 0; - //println!("Reset, was {}({})", _x, _ch) + for case in cases { + assert_eq!(case.0.crossing(&&case.1), case.2) + } +} + +fn valid(x: usize, y: i32, max: usize) -> Option { + let tmp = if y < 0 { + x.checked_sub(y.neg() as usize) + } else { + x.checked_add(y as usize) + }; + if let Some(xi) = tmp { + if xi < max { + return Some(xi); + } + } + None +} + +fn validxy( + x: usize, + y: usize, + modx: i32, + mody: i32, + heigth: usize, + length: usize, +) -> Option<(usize, usize)> { + if let Some(xi) = valid(x, modx, length) { + if let Some(yi) = valid(y, mody, heigth) { + return Some((xi, yi)); + } + } + None +} + +fn find_text(data: Vec>, length: usize, heigth: usize, text: &str) -> (usize, usize) { + let first: char = text.chars().nth(0).unwrap(); + let mut amount = 0; + let mut found; + let mut character; + let mut chars; + let mut coords = Vec::new(); + let mut currentpos; + for row in 0..heigth { + for column in 0..length { + let char = data[row][column]; + if char != first { + continue; + } + + for (x, y) in matrix(false, true, true) { + if x == y && y == 0 { + continue; + } + found = 1; + chars = text.chars(); + chars.next(); + loop { + character = chars.next(); + if character == None { + amount += 1; + currentpos = TextPos { + startx: row, + starty: column, + endx: (row as i32 + x * found) as usize, + endy: (column as i32 + y * found) as usize, + length: text.len(), + }; + coords.push(currentpos); + break; + } + if let Some((posmodx, posmody)) = + validxy(row, column, x * found, y * found, length, heigth) + { + if data[posmodx][posmody] == character.unwrap() { + found += 1; + } else { + break; } + } else { + break; } } } } } - println!("There are {} XMAS in text", amount); + let mut xtexts = Vec::new(); + for node in coords.clone() { + for o in coords.iter().filter(|other| node.crossing(other)) { + let other = *o; + if node == other { + continue; + } + let x = (node.min(other), node.max(other)); + if !xtexts.contains(&x) { + xtexts.push(x); + } + } + } + println!("{:?}", xtexts); + (amount, xtexts.len()) +} + +fn main() { + let table = convert_to_array(DATA, line_to_char); + let length = table[0].len(); + let (amount, _) = find_text(table.clone(), length, table.len(), "XMAS"); + println!("There are {} XMAS in text", amount); + let (amount, amount_cross) = find_text(table.clone(), length, table.len(), "MAS"); + println!( + "There are {} MAS in text, are {} crossed", + amount, amount_cross + ); } diff --git a/src/strings.rs b/src/strings.rs index 30f2e8b..5c04842 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -1,11 +1,6 @@ use num::{pow::Pow, Integer}; use std::ops::AddAssign; -pub fn splitspace(input: &str) -> (&str, &str) { - let mut output = input.split_ascii_whitespace(); - (output.next().unwrap().trim(), output.next().unwrap().trim()) -} - pub fn parsenumber + Pow + AddAssign + Copy>( input: &str, ) -> T {