Skip to content

Commit

Permalink
feat: day04
Browse files Browse the repository at this point in the history
  • Loading branch information
martabal committed Dec 4, 2024
1 parent 8a5df2b commit 3e3ad42
Show file tree
Hide file tree
Showing 14 changed files with 413 additions and 106 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
[workspace]
resolver = "2"
members = ["crates/day01", "crates/day02", "crates/day03"]
members = [
"crates/helpers",
"crates/day01",
"crates/day02",
"crates/day03",
"crates/day04",
]

[workspace.dependencies]
regex = "1.11.1"
Expand Down
14 changes: 7 additions & 7 deletions c/day02.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#define MAX_VALUES 100

bool has_small_difference(int *vec, size_t size) {
for (size_t i = 0; i < size - 1; ++i) {
for (size_t i = 0; i < size - 1; i++) {
int diff = abs(vec[i + 1] - vec[i]);
if (diff < 1 || diff > 3) {
return false;
Expand All @@ -20,7 +20,7 @@ bool is_safe(int *e, size_t size) {
bool non_increasing = true;
bool non_decreasing = true;

for (size_t i = 0; i < size - 1; ++i) {
for (size_t i = 0; i < size - 1; i++) {
if (e[i] < e[i + 1]) {
non_increasing = false;
}
Expand Down Expand Up @@ -69,7 +69,7 @@ int main() {

// --- Part One ---
unsigned int safe_count = 0;
for (size_t i = 0; i < row_count; ++i) {
for (size_t i = 0; i < row_count; i++) {
if (is_safe(report[i], MAX_VALUES)) {
safe_count++;
}
Expand All @@ -78,17 +78,17 @@ int main() {

// --- Part Two ---
safe_count = 0;
for (size_t i = 0; i < row_count; ++i) {
for (size_t i = 0; i < row_count; i++) {
if (is_safe(report[i], MAX_VALUES)) {
safe_count++;
} else {
for (size_t pos = 0; pos < MAX_VALUES; ++pos) {
for (size_t pos = 0; pos < MAX_VALUES; pos++) {
if (report[i][pos] == 0)
continue;
int *new = malloc((MAX_VALUES - 1) * sizeof(int));
size_t new_count = 0;

for (size_t j = 0; j < MAX_VALUES; ++j) {
for (size_t j = 0; j < MAX_VALUES; j++) {
if (j != pos) {
new[new_count++] = report[i][j];
}
Expand All @@ -106,7 +106,7 @@ int main() {
}
printf("Part Two solution: sum is %u\n", safe_count);

for (size_t i = 0; i < row_count; ++i) {
for (size_t i = 0; i < row_count; i++) {
free(report[i]);
}
free(report);
Expand Down
11 changes: 4 additions & 7 deletions c/day03.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ static SizeVector create_size_vector(size_t initial_capacity) {
return vec;
}

static void free_size_vector(SizeVector *vec) { free(vec->data); }

static void push_back(SizeVector *vec, size_t value) {
if (vec->size == vec->capacity) {
vec->capacity = (vec->capacity * 3) / 2; // 1.5x growth
Expand Down Expand Up @@ -127,8 +125,8 @@ static int parse_with_rules(const char *message) {

if (do_positions.size == 0 && dont_positions.size == 0) {
int result = count_mul(message);
free_size_vector(&do_positions);
free_size_vector(&dont_positions);
free(do_positions.data);
free(dont_positions.data);
return result;
}

Expand All @@ -153,9 +151,8 @@ static int parse_with_rules(const char *message) {
}
}

free_size_vector(&do_positions);
free_size_vector(&dont_positions);

free(do_positions.data);
free(dont_positions.data);
return count;
}

Expand Down
2 changes: 1 addition & 1 deletion cpp/day01.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ int main() {
std::sort(left_column.begin(), left_column.end());
std::sort(right_column.begin(), right_column.end());

for (size_t i = 0; i < left_column.size(); ++i) {
for (size_t i = 0; i < left_column.size(); i++) {
sum +=
(static_cast<unsigned int>(std::abs(left_column[i] - right_column[i])));
}
Expand Down
4 changes: 2 additions & 2 deletions cpp/day02.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <vector>

bool has_small_difference(const std::vector<int> &vec) {
for (size_t i = 0; i < vec.size() - 1; ++i) {
for (size_t i = 0; i < vec.size() - 1; i++) {
int diff = std::abs(vec[i + 1] - vec[i]);
if (diff < 1 || diff > 3) {
return false;
Expand Down Expand Up @@ -59,7 +59,7 @@ int main() {
if (is_safe(e)) {
safe++;
} else {
for (size_t pos = 0; pos < e.size(); ++pos) {
for (size_t pos = 0; pos < e.size(); pos++) {
std::vector<int> new_e = e;
new_e.erase(new_e.begin() + pos);

Expand Down
40 changes: 15 additions & 25 deletions cpp/day03.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,43 +51,33 @@ class ProgramParser {
std::string::const_iterator iterator;
std::string::const_iterator end;

char peek() const { return iterator != end ? *iterator : '\0'; }
char peek() const { return (iterator != end) ? *iterator : '\0'; }

void next() {
if (iterator != end)
++iterator;
if (iterator != end) {
iterator++;
}
}

bool parse_mul() {
if (peek() == 'm') {
next();
if (peek() == 'u') {
next();
if (peek() == 'l') {
next();
return true;
}
static const std::string target = "mul";
for (char ch : target) {
if (peek() != ch) {
return false;
}
next();
}
return false;
return true;
}

std::optional<int> parseNumber() {
std::string digits;

for (int i = 0; i < 3; ++i) {
if (std::isdigit(peek())) {
digits.push_back(peek());
next();
} else {
break;
}
}

if (!digits.empty()) {
return std::stoi(digits);
while (digits.size() < 3 && std::isdigit(peek())) {
digits.push_back(peek());
next();
}
return std::nullopt;
return digits.empty() ? std::nullopt
: std::make_optional(std::stoi(digits));
}
};

Expand Down
1 change: 1 addition & 0 deletions crates/day03/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ workspace = true

[dependencies]
regex = { workspace = true, optional = true }
helpers = { path = "../helpers"}

[features]
regex=["dep:regex"]
106 changes: 43 additions & 63 deletions crates/day03/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use std::{
fs::File,
io::{BufReader, Read},
str::FromStr,
};
use std::str::FromStr;

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

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

Expand All @@ -17,25 +14,25 @@ pub struct Problem {

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
///
/// Will return `Err` if there's an error in the parsing/regex
/// Returns an error if input parsing fails.
pub fn count_mul(p: &str) -> Result<i32, Box<dyn std::error::Error>> {
let Problem { program } = p.parse()?;
let mut parser = ProgramParser::new(&program);

let program: Problem = p.parse()?;
let mut parser = ProgramParser::new(&program.program);
Ok(parser.parse())
}

fn main() {
// --- Part One ---
let message = read_file("crates/day03/input.txt").unwrap();
// --- Part One ---
let mut count = count_mul(&message).unwrap();
println!("Part One solution: sum is {count}");

Expand All @@ -44,18 +41,6 @@ fn main() {
println!("Part Two solution: sum is {count}");
}

fn find_all_indexes(haystack: &str, needle: &str) -> Vec<usize> {
let mut indexes = Vec::new();
let mut start = 0;

while let Some(pos) = haystack[start..].find(needle) {
indexes.push(start + pos);
start += pos + 1;
}

indexes
}

#[cfg(not(feature = "regex"))]
struct ProgramParser<'a> {
iterator: Peekable<Chars<'a>>,
Expand All @@ -73,26 +58,27 @@ impl<'a> ProgramParser<'a> {
let mut result = 0;

while self.iterator.peek().is_some() {
if self.parse_mul() {
if self.iterator.peek() == Some(&'(') {
let _ = self.iterator.next();
if !self.parse_mul() {
self.iterator.next();
continue;
}
if self.iterator.next_if_eq(&'(').is_none() {
continue;
}
let Some(a) = self.parse_number() else {
continue;
};

if let Some(a) = self.parse_number() {
if self.iterator.peek() == Some(&',') {
let _ = self.iterator.next();
if self.iterator.next_if_eq(&',').is_none() {
continue;
}

if let Some(b) = self.parse_number() {
if self.iterator.peek() == Some(&')') {
let _ = self.iterator.next();
let Some(b) = self.parse_number() else {
continue;
};

result += a * b;
}
}
}
}
}
} else {
let _ = self.iterator.next();
if self.iterator.next_if_eq(&')').is_some() {
result += a * b;
}
}

Expand Down Expand Up @@ -140,37 +126,39 @@ impl<'a> ProgramParser<'a> {
}
}

fn closest_greater_than(x: usize, y: &[usize]) -> Option<usize> {
let mut closest: Option<usize> = None;
fn find_all_indexes(haystack: &str, needle: &str) -> Vec<usize> {
let needle_len = needle.len();
let mut indexes = Vec::new();

for &value in y {
if value > x && (closest.is_none() || value < closest.unwrap()) {
closest = Some(value);
for (i, window) in haystack.as_bytes().windows(needle_len).enumerate() {
if window == needle.as_bytes() {
indexes.push(i);
}
}

closest
indexes
}

fn parse_with_rules(message: &str) -> i32 {
let do_substring = "do()";
let do_position = find_all_indexes(message, do_substring);
fn closest_greater_than(x: usize, y: &[usize]) -> Option<usize> {
y.iter().filter(|&&value| value > x).min().copied()
}

let dont_substring = "don't()";
let dont_position = find_all_indexes(message, dont_substring);
fn parse_with_rules(message: &str) -> i32 {
let do_positions = find_all_indexes(message, "do()");
let dont_positions = find_all_indexes(message, "don't()");

if do_position.is_empty() && dont_position.is_empty() {
if do_positions.is_empty() && dont_positions.is_empty() {
return count_mul(message).unwrap();
}

let first_substring = &message[..=do_position[0]];
let first_substring = &message[..=do_positions[0]];
let mut count = 0;
count += count_mul(first_substring).unwrap();
let mut next_dont: Option<usize> = None;

for i in do_position {
for i in do_positions {
if next_dont < Some(i) || next_dont.is_none() {
if let Some(f) = closest_greater_than(i, &dont_position) {
if let Some(f) = closest_greater_than(i, &dont_positions) {
let substring = &message[i..f];

count += count_mul(substring).unwrap();
Expand All @@ -197,11 +185,3 @@ fn count_mul(message: &str) -> Result<i32, Box<dyn std::error::Error>> {

Ok(result)
}

fn read_file(file_path: &str) -> Result<String, Box<dyn std::error::Error>> {
let file = File::open(file_path)?;
let mut reader = BufReader::new(file);
let mut content = String::new();
reader.read_to_string(&mut content)?;
Ok(content)
}
Loading

0 comments on commit 3e3ad42

Please sign in to comment.