Skip to content

Commit

Permalink
day 7 - part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Alin committed Dec 9, 2024
1 parent b28262f commit 113cc25
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 46 deletions.
18 changes: 14 additions & 4 deletions benchmarks/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,18 @@ mod day_07_benches {
day_07::part_one(divan::black_box(include_str!("../assets/input_day_07.txt")));
}

// #[divan::bench]
// fn part_two() {
// day_06::part_two(divan::black_box(include_str!("../assets/input_day_06.txt")));
// }
#[divan::bench]
fn part_one_rtl() {
day_07::part_one_rtl(divan::black_box(include_str!("../assets/input_day_07.txt")));
}

#[divan::bench(sample_count = 10)]
fn part_two() {
day_07::part_two(divan::black_box(include_str!("../assets/input_day_07.txt")));
}

#[divan::bench(sample_count = 10)]
fn part_two_rtl() {
day_07::part_two_rtl(divan::black_box(include_str!("../assets/input_day_07.txt")));
}
}
35 changes: 20 additions & 15 deletions benchmarks/output.txt
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
benchmarks fastest │ slowest │ median │ mean │ samples │ iters
├─ day_01_benches │ │ │ │ │
│ ├─ part_one 49.12 µs │ 145 µs │ 49.51 µs │ 50.98 µs │ 100 │ 100
│ ├─ part_one_zip 47.74 µs │ 54.66 µs │ 49.49 µs │ 49.77 µs │ 100 │ 100
│ ├─ part_two 66.37 µs │ 84.83 µs │ 71.08 µs │ 71.14 µs │ 100 │ 100
│ ╰─ part_two_filter 77.2 µs │ 85.24 µs │ 81.91 µs │ 81.14 µs │ 100 │ 100
│ ├─ part_one 49.08 µs │ 85.87 µs │ 50.91 µs │ 51.2 µs │ 100 │ 100
│ ├─ part_one_zip 48.41 µs │ 91.74 µs │ 49.45 µs │ 50.68 µs │ 100 │ 100
│ ├─ part_two 71.83 µs │ 109.6 µs │ 75.95 µs │ 77.22 µs │ 100 │ 100
│ ╰─ part_two_filter 76.91 µs │ 98.54 µs │ 77.56 µs │ 79.15 µs │ 100 │ 100
├─ day_02_benches │ │ │ │ │
│ ├─ part_one 127 µs │ 146 µs │ 130.4 µs │ 131.1 µs │ 100 │ 100
│ ╰─ part_two 162.9 µs │ 185.7 µs │ 168.2 µs │ 168.8 µs │ 100 │ 100
│ ├─ part_one 127.2 µs │ 248.7 µs │ 133.9 µs │ 136.8 µs │ 100 │ 100
│ ╰─ part_two 162 µs │ 290 µs │ 166.6 µs │ 173.2 µs │ 100 │ 100
├─ day_03_benches │ │ │ │ │
│ ├─ part_one 234 µs │ 717.2 µs │ 240.6 µs │ 246.1 µs │ 100 │ 100
│ ├─ part_two 296.1 µs │ 418.7 µs │ 301.2 µs │ 304.4 µs │ 100 │ 100
│ ╰─ part_two_split 206.2 µs │ 254.5 µs │ 210.2 µs │ 211.6 µs │ 100 │ 100
│ ├─ part_one 231 µs │ 458.1 µs │ 235.9 µs │ 245.4 µs │ 100 │ 100
│ ├─ part_two 290.5 µs │ 417.2 µs │ 295.4 µs │ 300.5 µs │ 100 │ 100
│ ╰─ part_two_split 198.6 µs │ 370.7 µs │ 211.3 µs │ 221.8 µs │ 100 │ 100
├─ day_04_benches │ │ │ │ │
│ ├─ part_one 349.7 µs │ 411.3 µs │ 357.8 µs │ 360.2 µs │ 100 │ 100
│ ╰─ part_two 337.4 µs │ 363.9 µs │ 350 µs │ 350.3 µs │ 100 │ 100
│ ├─ part_one 353.9 µs │ 491.6 µs │ 369.6 µs │ 377.2 µs │ 100 │ 100
│ ╰─ part_two 334.5 µs │ 403 µs │ 340.1 µs │ 346.7 µs │ 100 │ 100
├─ day_05_benches │ │ │ │ │
│ ├─ part_one 173.5 µs │ 197.5 µs │ 181 µs │ 181.3 µs │ 100 │ 100
│ ╰─ part_two 228.1 µs │ 270 µs │ 243.6 µs │ 244.2 µs │ 100 │ 100
╰─ day_06_benches │ │ │ │ │
╰─ part_one 51.83 µs │ 63.04 µs │ 53.56 µs │ 53.57 µs │ 100 │ 100
│ ├─ part_one 201.2 µs │ 276.3 µs │ 216.7 µs │ 219.1 µs │ 100 │ 100
│ ╰─ part_two 317.1 µs │ 465.4 µs │ 338.6 µs │ 342.7 µs │ 100 │ 100
├─ day_06_benches │ │ │ │ │
│ ╰─ part_one 54.41 µs │ 80.58 µs │ 56.24 µs │ 56.27 µs │ 100 │ 100
╰─ day_07_benches │ │ │ │ │
├─ part_one 177.2 ms │ 276.3 ms │ 181.1 ms │ 184.4 ms │ 100 │ 100
├─ part_one_rtl 164.8 ms │ 246.5 ms │ 167.2 ms │ 168.8 ms │ 100 │ 100
├─ part_two 10.14 s │ 10.64 s │ 10.26 s │ 10.3 s │ 10 │ 10
╰─ part_two_rtl 7.59 s │ 7.97 s │ 7.661 s │ 7.705 s │ 10 │ 10

4 changes: 2 additions & 2 deletions src/day_06/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub fn part_one(file: &str) -> i32 {

let dir = (-1, 0);

let mut guard_pos: (i32, i32) = (-1, -1);
let mut guard_pos: (i32, i32);

for row in 0..matrix.len() {
for col in 0..matrix[0].len() {
Expand Down Expand Up @@ -77,6 +77,6 @@ fn move_into_direction(
exit_found
}

pub fn part_two(file: &str) -> i32 {
pub fn part_two(_file: &str) -> i32 {
0
}
227 changes: 202 additions & 25 deletions src/day_07/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,91 @@ fn prepare(file: &str) -> HashMap<i64, Vec<i64>> {
hash_map
}

fn generate_combinations(len: usize, operators: &Vec<char>) -> Vec<Vec<char>> {
let mut combinations = Vec::new();

let total_combinations = operators.len().pow(len as u32);

for i in 0..total_combinations {
let mut combination = Vec::with_capacity(len);
let mut num = i;
for _ in 0..len {
combination.push(operators[num % operators.len()]);
num /= operators.len();
}
combinations.push(combination);
}

combinations
}

fn evaluate_left_to_right(tokens: Vec<&str>) -> i64 {
let mut result = tokens[0].parse::<i64>().expect("Invalid number");

let mut iter = tokens.iter().skip(1);
while let (Some(&op), Some(&num)) = (iter.next(), iter.next()) {
let number = num.parse::<i64>().expect("Invalid number");
match op {
"+" => result += number,
"*" => result *= number,
"|" => {
result = (result.to_string() + &number.to_string())
.parse::<i64>()
.unwrap()
}
_ => panic!("Unsupported operator: {}", op),
}
}

result
}

#[allow(dead_code)]
fn evaluate_right_to_left_with_target(tokens: &[&str], target: i64) -> bool {
if tokens.len() == 1 {
return tokens[0].parse::<i64>().map_or(false, |n| n == target);
}

let last_number = tokens[tokens.len() - 1]
.parse::<i64>()
.expect("Invalid number");

let remaining_tokens = &tokens[..tokens.len() - 2];
let operator = tokens[tokens.len() - 2];

match operator {
"+" => {
let new_target = target - last_number;
evaluate_right_to_left_with_target(remaining_tokens, new_target)
}
"*" => {
if target % last_number == 0 {
let new_target = target / last_number;
evaluate_right_to_left_with_target(remaining_tokens, new_target)
} else {
false
}
}
"|" => {
let last_str = last_number.to_string();
let target_str = target.to_string();
if target_str.ends_with(&last_str) {
let new_target = target_str[..target_str.len() - last_str.len()]
.parse::<i64>()
.unwrap_or(-1);
evaluate_right_to_left_with_target(remaining_tokens, new_target)
} else {
false
}
}
_ => panic!("Unsupported operator: {}", operator),
}
}

pub fn part_one(file: &str) -> i64 {
let mut count = 0;
let map = prepare(file);
let operators = vec!['+', '*'];

let mut combinations_map: HashMap<i64, Vec<Vec<char>>> = HashMap::new();

Expand All @@ -32,7 +114,7 @@ pub fn part_one(file: &str) -> i64 {
if val.is_none() {
combinations_map.insert(
combination_size,
generate_combinations((combination_size - 1) as usize),
generate_combinations((combination_size - 1) as usize, &operators),
);
}

Expand Down Expand Up @@ -61,41 +143,136 @@ pub fn part_one(file: &str) -> i64 {
count
}

fn generate_combinations(len: usize) -> Vec<Vec<char>> {
let mut combinations = Vec::new();
let total_combinations = 2_usize.pow(len as u32);
#[allow(dead_code)]
pub fn part_one_rtl(file: &str) -> i64 {
let mut count = 0;
let map = prepare(file);
let operators = vec!['+', '*'];

for i in 0..total_combinations {
let mut combination = Vec::with_capacity(len);
for j in 0..len {
if i & (1 << j) != 0 {
combination.push('*');
} else {
combination.push('+');
let mut combinations_map: HashMap<i64, Vec<Vec<char>>> = HashMap::new();

for (key, value) in map.iter() {
let combination_size = value.len() as i64;

let val = combinations_map.get(&combination_size);

if val.is_none() {
combinations_map.insert(
combination_size,
generate_combinations((combination_size - 1) as usize, &operators),
);
}

let combination = combinations_map.get(&combination_size).unwrap();

for comb in combination {
let mut merged: Vec<String> = Vec::new();
for (i, v) in value.iter().enumerate() {
merged.push(v.to_string());
if i < comb.len() {
merged.push(comb[i].to_string());
}
}

let merged_str: Vec<&str> = merged.iter().map(|s| s.as_str()).collect();

let result = evaluate_right_to_left_with_target(&merged_str, *key);

if result {
count += key;
break;
}
}
combinations.push(combination);
}

combinations
count
}

fn evaluate_left_to_right(tokens: Vec<&str>) -> i64 {
let mut result = tokens[0].parse::<i64>().expect("Invalid number");
pub fn part_two(file: &str) -> i64 {
let mut count = 0;
let map = prepare(file);
let operators = vec!['+', '*', '|'];

let mut iter = tokens.iter().skip(1);
while let (Some(&op), Some(&num)) = (iter.next(), iter.next()) {
let number = num.parse::<i64>().expect("Invalid number");
match op {
"+" => result += number,
"*" => result *= number,
_ => panic!("Unsupported operator: {}", op),
let mut combinations_map: HashMap<i64, Vec<Vec<char>>> = HashMap::new();

for (key, value) in map.iter() {
let combination_size = value.len() as i64;

let val = combinations_map.get(&combination_size);

if val.is_none() {
combinations_map.insert(
combination_size,
generate_combinations((combination_size - 1) as usize, &operators),
);
}

let combination = combinations_map.get(&combination_size).unwrap();

for comb in combination {
let mut merged: Vec<String> = Vec::new();
for (i, v) in value.iter().enumerate() {
merged.push(v.to_string());
if i < comb.len() {
merged.push(comb[i].to_string());
}
}

let merged_str: Vec<&str> = merged.iter().map(|s| s.as_str()).collect();

let result = *key == evaluate_left_to_right(merged_str);

if result {
count += key;
break;
}
}
}

result
count
}

pub fn part_two(file: &str) -> i64 {
0
#[allow(dead_code)]
pub fn part_two_rtl(file: &str) -> i64 {
let mut count = 0;
let map = prepare(file);
let operators = vec!['+', '*', '|'];

let mut combinations_map: HashMap<i64, Vec<Vec<char>>> = HashMap::new();

for (key, value) in map.iter() {
let combination_size = value.len() as i64;

let val = combinations_map.get(&combination_size);

if val.is_none() {
combinations_map.insert(
combination_size,
generate_combinations((combination_size - 1) as usize, &operators),
);
}

let combination = combinations_map.get(&combination_size).unwrap();

for comb in combination {
let mut merged: Vec<String> = Vec::new();
for (i, v) in value.iter().enumerate() {
merged.push(v.to_string());
if i < comb.len() {
merged.push(comb[i].to_string());
}
}

let merged_str: Vec<&str> = merged.iter().map(|s| s.as_str()).collect();

let result = evaluate_right_to_left_with_target(&merged_str, *key);

if result {
count += key;
break;
}
}
}

count
}

0 comments on commit 113cc25

Please sign in to comment.