Skip to content

Commit

Permalink
fix: simplify rust
Browse files Browse the repository at this point in the history
  • Loading branch information
martabal committed Dec 5, 2024
1 parent 46fd6b0 commit b338faa
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 130 deletions.
26 changes: 5 additions & 21 deletions crates/day03/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,16 @@
use std::str::FromStr;

#[cfg(not(feature = "regex"))]
use std::{iter::Peekable, str::Chars};

use helpers::read_file;
#[cfg(feature = "regex")]
use regex::Regex;

#[derive(Debug, Eq, PartialEq)]
pub struct Problem {
program: String,
}

impl FromStr for Problem {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self { program: s.into() })
}
}

#[cfg(not(feature = "regex"))]
/// Parses and counts the product of numbers within a "mul(a, b)" format.
/// # Errors
/// Returns an error if input parsing fails.
pub fn count_mul(p: &str) -> Result<i32, Box<dyn std::error::Error>> {
let program: Problem = p.parse()?;
let mut parser = ProgramParser::new(&program.program);
let mut parser = ProgramParser::new(p);
Ok(parser.parse())
}

Expand Down Expand Up @@ -87,11 +71,11 @@ impl<'a> ProgramParser<'a> {

fn parse_mul(&mut self) -> bool {
if self.iterator.peek() == Some(&'m') {
let _ = self.iterator.next();
self.iterator.next();
if self.iterator.peek() == Some(&'u') {
let _ = self.iterator.next();
self.iterator.next();
if self.iterator.peek() == Some(&'l') {
let _ = self.iterator.next();
self.iterator.next();

return true;
}
Expand All @@ -109,7 +93,7 @@ impl<'a> ProgramParser<'a> {
if c.is_ascii_digit() {
digits.push(*c);

let _ = self.iterator.next();
self.iterator.next();

continue;
}
Expand Down
207 changes: 110 additions & 97 deletions crates/day04/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ use std::{

use helpers::floored_division;

struct Grid {
grid: Vec<Vec<char>>,
}

fn main() {
let message = read_file("crates/day04/input.txt").unwrap();
// --- Part One ---
let mut count = count_word(&message, "XMAS");
let grid = Grid::new(message);
let mut count = grid.count_word("XMAS");
println!("Part One solution: {count}");

// --- Part Two ---
count = count_x_pattern(&message, "MAS").unwrap();
println!("Part Two solution: {count}");
count = grid.count_x_pattern("XMAS").unwrap();
println!("Part One solution: {count}");
}

fn read_file(input: &str) -> Result<Vec<Vec<char>>, Box<dyn std::error::Error>> {
Expand All @@ -28,118 +32,127 @@ fn read_file(input: &str) -> Result<Vec<Vec<char>>, Box<dyn std::error::Error>>
Ok(vec_of_vecs)
}

fn count_x_pattern(grid: &[Vec<char>], word: &str) -> Result<usize, String> {
let rows = grid.len();
let cols = if rows > 0 {
grid[0].len()
} else {
return Err("Grid must be a valid grid".to_string());
};
let word_len = word.len();
let mut count = 0;

let bounded: usize = floored_division(word_len.try_into().unwrap(), 2)
.try_into()
.unwrap();
let middle_char = word.chars().nth(bounded).unwrap();

let reverse = word.chars().rev().collect::<String>();

for r in bounded..(rows - bounded) {
for c in bounded..(cols - bounded) {
if grid[r][c] == middle_char {
let mut first_diagonal = false;
let mut second_diagonal = false;

// Check forward diagonal \
if (0..word_len)
.all(|i| grid[r - bounded + i][c - bounded + i] == word.chars().nth(i).unwrap())
{
first_diagonal = true;
}
// Check backward diagonal \
if (0..word_len).all(|i| {
grid[r - bounded + i][c - bounded + i] == reverse.chars().nth(i).unwrap()
}) {
first_diagonal = true;
}
impl Grid {
const fn new(new_grid: Vec<Vec<char>>) -> Self {
Self { grid: new_grid }
}

if first_diagonal {
// Check forward diagonal /
fn count_x_pattern(&self, word: &str) -> Result<usize, String> {
let rows = self.grid.len();
let cols = if rows > 0 {
self.grid[0].len()
} else {
return Err("Grid must be a valid grid".to_string());
};
let word_len = word.len();
let mut count = 0;

let bounded: usize = floored_division(word_len.try_into().unwrap(), 2)
.try_into()
.unwrap();
let middle_char = word.chars().nth(bounded).unwrap();

let reverse = word.chars().rev().collect::<String>();

for r in bounded..(rows - bounded) {
for c in bounded..(cols - bounded) {
if self.grid[r][c] == middle_char {
let mut first_diagonal = false;
let mut second_diagonal = false;

// Check forward diagonal \
if (0..word_len).all(|i| {
grid[r + bounded - i][c - bounded + i] == word.chars().nth(i).unwrap()
self.grid[r - bounded + i][c - bounded + i] == word.chars().nth(i).unwrap()
}) {
second_diagonal = true;
first_diagonal = true;
}
// Check backward diagonal /
// Check backward diagonal \
if (0..word_len).all(|i| {
grid[r + bounded - i][c - bounded + i] == reverse.chars().nth(i).unwrap()
self.grid[r - bounded + i][c - bounded + i]
== reverse.chars().nth(i).unwrap()
}) {
second_diagonal = true;
first_diagonal = true;
}

if second_diagonal {
count += 1;
if first_diagonal {
// Check forward diagonal /
if (0..word_len).all(|i| {
self.grid[r + bounded - i][c - bounded + i]
== word.chars().nth(i).unwrap()
}) {
second_diagonal = true;
}
// Check backward diagonal /
if (0..word_len).all(|i| {
self.grid[r + bounded - i][c - bounded + i]
== reverse.chars().nth(i).unwrap()
}) {
second_diagonal = true;
}

if second_diagonal {
count += 1;
}
}
}
}
}
}

Ok(count)
}
Ok(count)
}

fn count_word(grid: &[Vec<char>], word: &str) -> usize {
let word_chars: Vec<char> = word.chars().collect();
let word_len = word_chars.len();
let rows = grid.len();
let cols = grid[0].len();
let mut count = 0;

let directions = vec![
(0, 1), // Horizontal right
(0, -1), // Horizontal left
(1, 0), // Vertical down
(-1, 0), // Vertical up
(1, 1), // Diagonal down-right
(1, -1), // Diagonal down-left
(-1, 1), // Diagonal up-right
(-1, -1), // Diagonal up-left
];

for row in 0..rows {
for col in 0..cols {
for (dx, dy) in &directions {
let mut found = true;

for (i, _) in word_chars.iter().enumerate().take(word_len) {
let x = isize::try_from(row).unwrap() + isize::try_from(i).unwrap() * dx;
let y = isize::try_from(col).unwrap() + isize::try_from(i).unwrap() * dy;

if x < 0
|| y < 0
|| x >= rows.try_into().unwrap()
|| y >= cols.try_into().unwrap()
{
found = false;
break;
fn count_word(&self, word: &str) -> usize {
let word_chars: Vec<char> = word.chars().collect();
let word_len = word_chars.len();
let rows = self.grid.len();
let cols = self.grid[0].len();
let mut count = 0;

let directions = vec![
(0, 1), // Horizontal right
(0, -1), // Horizontal left
(1, 0), // Vertical down
(-1, 0), // Vertical up
(1, 1), // Diagonal down-right
(1, -1), // Diagonal down-left
(-1, 1), // Diagonal up-right
(-1, -1), // Diagonal up-left
];

for row in 0..rows {
for col in 0..cols {
for (dx, dy) in &directions {
let mut found = true;

for (i, _) in word_chars.iter().enumerate().take(word_len) {
let x = isize::try_from(row).unwrap() + isize::try_from(i).unwrap() * dx;
let y = isize::try_from(col).unwrap() + isize::try_from(i).unwrap() * dy;

if x < 0
|| y < 0
|| x >= rows.try_into().unwrap()
|| y >= cols.try_into().unwrap()
{
found = false;
break;
}

let u_x: usize = usize::try_from(x).unwrap();
let u_y: usize = usize::try_from(y).unwrap();

if self.grid[u_x][u_y] != word_chars[i] {
found = false;
break;
}
}

let u_x: usize = usize::try_from(x).unwrap();
let u_y: usize = usize::try_from(y).unwrap();

if grid[u_x][u_y] != word_chars[i] {
found = false;
break;
if found {
count += 1;
}
}

if found {
count += 1;
}
}
}
}

count
count
}
}
20 changes: 8 additions & 12 deletions crates/day05/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::HashMap, str::FromStr};
use std::collections::HashMap;

use helpers::read_file;

Expand All @@ -10,18 +10,17 @@ struct PrintQueueChecker {
fn main() {
let message = read_file("crates/day05/input.txt").unwrap();
// --- Part One ---
let checker = PrintQueueChecker::from_str(&message).unwrap();
let checker = PrintQueueChecker::new(&message);
println!("Part One solution: {}", checker.check_page_order());

// --- Part Two ---
println!("Part Two solution: {}", checker.check_and_sort_page_order());
}

impl FromStr for PrintQueueChecker {
type Err = String;
fn from_str(puzzle: &str) -> Result<Self, Self::Err> {
impl PrintQueueChecker {
fn new(content: &str) -> Self {
let mut rules = HashMap::new();
puzzle
content
.lines()
.take_while(|l| !l.is_empty())
.filter_map(|l| {
Expand All @@ -34,21 +33,18 @@ impl FromStr for PrintQueueChecker {
rules.entry(right).or_insert(vec![]).push(left);
});

let page_numbers = puzzle
let page_numbers = content
.lines()
.skip_while(|x| !x.is_empty())
.skip(1)
.filter_map(|l| l.split(',').map(|x| x.parse().ok()).collect())
.collect();

Ok(Self {
Self {
rules,
page_numbers,
})
}
}
}

impl PrintQueueChecker {
fn check_valid(&self, order: &[i32]) -> bool {
assert!(order.len() % 2 == 1);
for (idx, val) in order.iter().enumerate() {
Expand Down

0 comments on commit b338faa

Please sign in to comment.