Compare commits

..

13 Commits

Author SHA1 Message Date
4b44cfba67 aoc3 2025-12-08 16:43:09 +01:00
f22f67161b aoc4 2025-12-08 16:43:00 +01:00
6465a1597a aoc7 2025-12-08 16:42:42 +01:00
b0bde44ff4 aoc8 2025-12-08 16:42:18 +01:00
fd853da84e aoc7 part 2 2025-12-07 22:56:56 +01:00
fad32426b9 aoc7 2025-12-07 22:10:38 +01:00
eb4d08968b aoc6 2025-12-07 10:32:26 +01:00
00f434a9c1 project structure update 2025-12-05 09:36:52 +01:00
6b350ded94 project structure update 2025-12-04 16:42:42 +01:00
498680aaca project structure update 2025-12-04 16:42:13 +01:00
2744cf76dd project structure update 2025-12-04 16:42:04 +01:00
2429d7a4dd aoc_4 fast version 2025-12-04 16:38:57 +01:00
f28c4bb28d aoc_2 fast version 2025-12-03 14:17:23 +01:00
21 changed files with 1209 additions and 36 deletions

View File

@@ -5,6 +5,8 @@ edition = "2024"
[dev-dependencies]
criterion = { version = "0.7", features = ["html_reports"] }
[build]
rustflags = ["-C", "target-cpu=native"]
[[bench]]
name = "bench_aoc_1"
@@ -16,5 +18,33 @@ harness = false
[[bench]]
name = "bench_aoc_3"
harness = false
[[bench]]
name = "bench_aoc_4"
harness = false
[[bench]]
name = "bench_aoc_5"
harness = false
[[bench]]
name = "bench_aoc_6"
harness = false
[[bench]]
name = "bench_aoc_7"
harness = false
[[bench]]
name = "bench_aoc_8"
harness = false
[dependencies]
strength_reduce = "0.2.4"
bstr = "1.12.1"
[profile.bench]
opt-level = 3
lto = "fat" # "Link Time Optimization" - Critical for micro-benchmarks
codegen-units = 1 # Slows compile time, but makes faster code
panic = "abort" # Removes stack unwinding checks (faster)
[profile.release]
debug = true
overflow-checks = true

29
benches/bench_aoc_4.rs Normal file
View File

@@ -0,0 +1,29 @@
use std::hint::black_box;
use criterion::{criterion_group, criterion_main, Criterion};
use aoc2025::aoc::aoc_4;
fn bench_aoc_4_part1(c: &mut Criterion) {
let input = black_box(include_bytes!("../src/aoc/input/full_input_aoc4.txt"));
c.bench_function("bench_aoc4 part 1", |b| b.iter(|| aoc_4::solve_p1(input)));
}
fn bench_aoc_4_part1_f(c: &mut Criterion) {
let input = black_box(include_bytes!("../src/aoc/input/full_input_aoc4.txt"));
c.bench_function("bench_aoc4 part 1 fast", |b| b.iter(|| aoc_4::solve_p1_f(input)));
}
fn bench_aoc_4_part2(c: &mut Criterion) {
let input = black_box(include_str!("../src/aoc/input/full_input_aoc4.txt"));
c.bench_function("bench_aoc4 part 2", |b| b.iter(|| aoc_4::solve_p2(input)));
}
fn bench_aoc_4_part2_f(c: &mut Criterion) {
let input = black_box(include_bytes!("../src/aoc/input/full_input_aoc4.txt"));
c.bench_function("bench_aoc4 part 2 fast", |b| b.iter(|| aoc_4::solve_p2_f(input)));
}
criterion_group!(
benches_p4,
bench_aoc_4_part1,
bench_aoc_4_part1_f,
bench_aoc_4_part2,
bench_aoc_4_part2_f
);
criterion_main!(benches_p4);

20
benches/bench_aoc_5.rs Normal file
View File

@@ -0,0 +1,20 @@
use std::hint::black_box;
use criterion::{criterion_group, criterion_main, Criterion};
use aoc2025::aoc::aoc_5;
fn bench_aoc_5_part1(c: &mut Criterion) {
let input = black_box(include_str!("../src/aoc/input/full_input_aoc5.txt"));
c.bench_function("bench_aoc5 part 1", |b| b.iter(|| aoc_5::solve_p1(input)));
}
fn bench_aoc_5_part2(c: &mut Criterion) {
let input = black_box(include_str!("../src/aoc/input/full_input_aoc5.txt"));
c.bench_function("bench_aoc5 part 2", |b| b.iter(|| aoc_5::solve_p2(input)));
}
criterion_group!(
benches_p5,
bench_aoc_5_part1,
bench_aoc_5_part2
);
criterion_main!(benches_p5);

22
benches/bench_aoc_6.rs Normal file
View File

@@ -0,0 +1,22 @@
use std::hint::black_box;
use criterion::{criterion_group, criterion_main, Criterion};
use aoc2025::aoc::aoc_6;
fn bench_aoc_6_part1(c: &mut Criterion) {
let input = black_box(include_str!("../src/aoc/input/full_input_aoc6.txt"));
c.bench_function("bench_aoc6 part 1", |b| b.iter(|| aoc_6::solve_p1(input)));
}
fn bench_aoc_6_part2(c: &mut Criterion) {
let input = black_box(include_str!("../src/aoc/input/full_input_aoc6.txt"));
c.bench_function("bench_aoc6 part 2", |b| b.iter(|| aoc_6::solve_p2_f(input)));
}
criterion_group!(
benches_p6,
bench_aoc_6_part1,
bench_aoc_6_part2,
);
criterion_main!(benches_p6);

22
benches/bench_aoc_7.rs Normal file
View File

@@ -0,0 +1,22 @@
use std::hint::black_box;
use criterion::{criterion_group, criterion_main, Criterion};
use aoc2025::aoc::aoc_7;
fn bench_aoc_7_part1(c: &mut Criterion) {
let input = black_box(include_str!("../src/aoc/input/full_input_aoc7.txt"));
c.bench_function("bench_aoc7 part 1", |b| b.iter(|| aoc_7::solve_p1(input)));
}
fn bench_aoc_7_part2(c: &mut Criterion) {
let input = black_box(include_bytes!("../src/aoc/input/full_input_aoc7.txt"));
c.bench_function("bench_aoc7 part 2", |b| b.iter(|| aoc_7::solve_p2(input)));
}
criterion_group!(
benches_p7,
bench_aoc_7_part1,
bench_aoc_7_part2,
);
criterion_main!(benches_p7);

15
benches/bench_aoc_8.rs Normal file
View File

@@ -0,0 +1,15 @@
use std::hint::black_box;
use criterion::{criterion_group, criterion_main, Criterion};
use aoc2025::aoc::aoc_8;
fn bench_aoc_8_part1(c: &mut Criterion) {
let input = black_box(include_str!("../src/aoc/input/full_input_aoc8.txt"));
c.bench_function("bench_aoc8 part 1", |b| b.iter(|| aoc_8::solve_p1(input)));
}
criterion_group!(
benches_p8,
bench_aoc_8_part1,
);
criterion_main!(benches_p8);

View File

@@ -1,3 +1,8 @@
pub mod aoc_1;
pub mod aoc_2;
pub mod aoc_3;
pub mod aoc_4;
pub mod aoc_5;
pub mod aoc_6;
pub mod aoc_7;
pub mod aoc_8;

View File

@@ -1,28 +1,238 @@
use std::io::BufRead;
pub fn solve_p1(input: &str ) -> u64 {
pub fn solve_p1(input: &str) -> u64 {
let mut answer = 0;
for line in input.split(',') {
let (num1, num2) = line.split_once('-').map(|n| {(n.0.parse::<u64>().unwrap(), n.1.parse::<u64>().unwrap())}).unwrap();
for i in num1..=num2 {
let (num1, num2) = line
.split_once('-')
.map(|n| (n.0.parse::<u64>().unwrap(), n.1.parse::<u64>().unwrap()))
.unwrap();
for i in num1..=num2 {
let text = i.to_string();
if text.len()%2 == 0 {
let splits = text.split_at(text.len()/2);
if splits.0==splits.1 {
answer +=i;
if text.len() % 2 == 0 {
let splits = text.split_at(text.len() / 2);
if splits.0 == splits.1 {
answer += i;
}
}
}
}
answer
}
pub fn solve_p2(input: &str ) -> u64 {
const POW10: [u64; 10] = [
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
];
pub fn solve_p1_f(input: &str) -> u64 {
let mut total_answer = 0;
for line in input.split(',') {
let Some((s1, s2)) = line.split_once('-') else {
continue;
};
let n1: u64 = s1.parse().unwrap();
let n2: u64 = s2.parse().unwrap();
// Iterate through possible "half lengths".
// u64 max is ~1.8e19, so max length is 19.
// We only care about even lengths: 2, 4, 6... 18.
// So 'half_len' goes from 1 to 9.
let half_len = n1.ilog10() / 2 + 1;
let power_of_10 = POW10[half_len as usize];
let multiplier = power_of_10 + 1;
// X must be a number with exactly 'half_len' digits.
// Range for X: [10^(d-1), 10^d - 1]
let x_min_digits = POW10[(half_len - 1) as usize];
let x_max_digits = power_of_10 - 1;
// X must also satisfy: n1 <= X * multiplier <= n2
// Therefore: n1/multiplier <= X <= n2/multiplier
// We use ceiling for lower bound and floor for upper bound.
let x_min_val = (n1 + multiplier - 1) / multiplier;
let x_max_val = n2 / multiplier;
// Find the intersection of valid digits and valid values
let start = x_min_digits.max(x_min_val);
let end = x_max_digits.min(x_max_val);
if start <= end {
// Sum of numbers N = X * multiplier
// Sum = multiplier * Sum(X for X in start..=end)
// Sum(start..=end) = (start + end) * count / 2
let count = end - start + 1;
let sum_x = (start + end) * count / 2;
total_answer += sum_x * multiplier;
}
}
total_answer
}
pub fn solve_p1_bytes(bytes: &[u8]) -> u64 {
let mut total_answer = 0;
let mut i = 0;
let len = bytes.len();
while i < len {
// 1. Parse N1 and count its digits (c1)
let mut n1: u64 = 0;
let mut c1: usize = 0;
while i < len {
let b = bytes[i];
if b == b'-' {
i += 1;
break;
}
n1 = n1 * 10 + (b & 0x0F) as u64;
c1 += 1;
i += 1;
}
// 2. Parse N2 and count its digits (c2)
let mut n2: u64 = 0;
while i < len {
let b = bytes[i];
if b == b',' {
i += 1;
break;
}
n2 = n2 * 10 + (b & 0x0F) as u64;
i += 1;
}
let half_len = (c1 + 1) >> 1; // Bitwise division by 2
// --- INLINED MATH (No function call overhead) ---
let power_of_10 = POW10[half_len];
let multiplier = power_of_10 + 1;
let x_min_digits = POW10[half_len - 1];
let x_max_digits = power_of_10 - 1;
// Fast ceiling division: (n1 + m - 1) / m
let x_min_val = (n1 + multiplier - 1) / multiplier;
let x_max_val = n2 / multiplier;
// Branchless max/min
let start = if x_min_digits > x_min_val {
x_min_digits
} else {
x_min_val
};
let end = if x_max_digits < x_max_val {
x_max_digits
} else {
x_max_val
};
if start <= end {
let count = end - start + 1;
// Formula: Sum = multiplier * (start + end) * count / 2
total_answer += multiplier * (start + end) * count / 2;
}
}
total_answer
}
pub fn solve_p1_unsafe(input: &str) -> u64 {
let mut total_answer = 0;
// Get raw pointers
let mut ptr = input.as_ptr();
// Calculate the end address
let end = unsafe { ptr.add(input.len()) };
while ptr < end {
// 1. Parse N1 (Unsafe, no bounds check)
let mut n1: u64 = 0;
let start_ptr = ptr;
loop {
// Read byte directly from memory
let b = unsafe { *ptr };
if b == b'-' {
ptr = unsafe { ptr.add(1) }; // Skip '-'
break;
}
// Fast ASCII conversion
n1 = n1 * 10 + (b & 0x0F) as u64; // b & 0x0F is faster than b - b'0'
ptr = unsafe { ptr.add(1) };
}
// Calculate digits of N1 using pointer difference (Instant)
// (Current ptr is at dash + 1) - (Start ptr) - 1 (for the dash)
let c1 = (ptr as usize - start_ptr as usize - 1) as u8;
// 2. Parse N2
let mut n2: u64 = 0;
// let start_ptr2 = ptr; // Not strictly needed unless you want c2
loop {
// Check if we hit end of string (EOF protection)
if ptr == end {
break;
}
let b = unsafe { *ptr };
if b == b',' {
ptr = unsafe { ptr.add(1) }; // Skip ','
break;
}
// Only valid digits here
n2 = n2 * 10 + (b & 0x0F) as u64;
ptr = unsafe { ptr.add(1) };
}
// --- LOGIC ---
// c1 is enough because we know the length difference is <= 1.
// If c1 is even, we check c1. If c1 is odd, we check c1 + 1 (which is c2).
// Trick: We need to check 'c1' if it's even, or 'c1+1' if c1 is odd.
// Let's just calculate the specific half_len we care about.
// If c1 is even (e.g. 2), we want half_len=1.
// If c1 is odd (e.g. 3), we want half_len=2 (because target must be len 4).
// Formula: half_len = (c1 + 1) / 2
let half_len = ((c1 + 1) >> 1) as usize;
let power_of_10 = unsafe { *POW10.get_unchecked(half_len) };
let multiplier = power_of_10 + 1;
let x_min_digits = unsafe { *POW10.get_unchecked(half_len - 1) };
let x_max_digits = power_of_10 - 1;
let x_min_val = (n1 + multiplier - 1).div_euclid(multiplier);
let x_max_val = n2 / multiplier;
let start = if x_min_digits > x_min_val {
x_min_digits
} else {
x_min_val
};
let end = if x_max_digits < x_max_val {
x_max_digits
} else {
x_max_val
};
if start <= end {
let count = end - start + 1;
total_answer += multiplier * (start + end) * count / 2;
}
}
total_answer
}
pub fn solve_p2(input: &str) -> u64 {
let mut answer = 0;
for line in input.split(',') {
let num_range = line.split('-').map(|num| { num.parse::<u64>().unwrap_or(0) }).collect::<Vec<u64>>();
let num_range = line
.split('-')
.map(|num| num.parse::<u64>().unwrap_or(0))
.collect::<Vec<u64>>();
for i in num_range[0]..=num_range[1] {
let text = i.to_string();
for j in 1..=text.len() / 2 {

View File

@@ -1,3 +1,4 @@
use std::simd::prelude::*;
pub fn solve_p1(input: &[u8]) -> u32 {
let mut answer = 0;
let mut i = 1;
@@ -36,37 +37,58 @@ pub fn solve_p1(input: &[u8]) -> u32 {
pub fn solve_p1_fast(input: &[u8]) -> u32 {
let mut answer = 0;
let mut i = 1;
let len = input.len();
let size = input.len()/100 -1;
//let size = 1;
const LANES: usize = 33;
let mut idx = 0;
type SimdVec = Simd<u8, LANES>;
for j in 0..size {
let line = &input[idx..idx+100];
//println!("{:?}", line);
for i in (1..=9) {
let target = SimdVec::splat(58-i);
let mut num = input[0];
let mut num2 = input[1];
while i < len {
let mut j = i;
num = input[j-1];
num2 = input[j];
let (prefix, chunks, suffix) = line.as_simd::<LANES>();
while input[j+1] != 10 {
// 4. Process the main SIMD chunks
let mask :u128 = (chunks[0].simd_eq(target).to_bitmask() as u128) | (chunks[1].simd_eq(target).to_bitmask() as u128) << LANES | (chunks[2].simd_eq(target).to_bitmask() as u128) << 2*LANES ;
let count = mask.count_ones() ;
// println!("{:?} ", count);
if input[j] > num {
num = input[j];
num2 = input[j + 1];
} else if input[j] > num2 {
num2 = input[j];
}
j +=1;
if j+2 == len {
if count >= 2 {
answer += ((10 * (10 - i)) + 10 -i) as u32;
break;
} else if count == 1 {
if 58-i == suffix[0] {
answer += ((10 * (10-i)) + suffix[0] - 48) as u32;
break;
}
if (58-i)-1 == suffix[0] {
answer += ((10 * (10-i)) + suffix[0] - 48) as u32;
break;
}
let idx = mask.trailing_zeros() as usize +1;
//println!("{:?}, {}, {}", line, idx, 58-i);
let line = &line[idx..100];
let mut num = suffix[0];
//println!("{:?}", line);
for v in line.iter() {
if v > &num {
num = *v;
}
}
//println!("{}", num);
answer += (((10 - i) * 10) + num -48) as u32;
break;
}
}
idx += 101;
if input[j] > num2 {
num2 =input[j ];
}
answer += (((num - 48) * 10) + num2 - 48) as u32;
// 5. Handle the remaining elements (head and tail) via standard scalar iteration
// These are the parts of the array that didn't fit into a perfect 32-byte chunk
i = j + 3;
//println!("nines {}", count + scalar_check(prefix) + scalar_check(suffix));
}
answer
@@ -103,7 +125,6 @@ pub fn solve_p2(input: &[u8]) -> u64 {
pub fn solve_p2_fast(input: &[u8]) -> u64 {
let mut answer = 0;
for line in input.split(|&x| x == 10) {
let mut end = line.len() - 12;
let total = 12;

289
src/aoc/aoc_4.rs Normal file
View File

@@ -0,0 +1,289 @@
use std::simd::prelude::*;
pub fn solve_p1(input: &[u8]) -> u64 {
let mut answer = 0;
let mut data:Vec<&u8> = Vec::with_capacity(32768);
let mut len = 141;
for line in input.split(|&x| {x == b'\n'}) {
let mut data_line: Vec<&u8> = line.iter().collect();
data_line.insert(0, &b'0');
data_line.insert(data_line.len(), &b'0');
len = data_line.len();
data.append(&mut data_line);
}
let size = 139;
for (i,char) in data.clone().into_iter().enumerate() {
let mut count = 0;
if *char == b'0' || *char == b'.' {
continue;
}
if char == &b'@' {
if i as i32 - len as i32 > 0 {
if data[i - (len-1)] == &b'@' {
count += 1;
}
if data[i - len] == &b'@' {
count += 1;
}
if data[i - (len + 1)] == &b'@' {
count += 1;
}
}
if i + len < (len * size) {
if data[i + len +1] == &b'@' {
count += 1;
}
if data[i + len] == &b'@' {
count += 1;
}
if data[i + len -1] == &b'@' {
count += 1;
}
}
if data[i - 1] == &b'@' {
count += 1;
}
if data[i + 1] == &b'@' {
count += 1;
}
if count < 4 {
//println!("count = {}", count);
answer += 1;
}
}
count = 0;
}
answer
}
pub fn solve_p1_f(input: &[u8]) -> u64 {
let mut answer = 0;
let len = 140;
let target = SimdVec::splat(b'@');
const LANES: usize = 8;
type SimdVec = Simd<u8, LANES>;
let mut data = [0;8];
let offsets = usizex8::from_array([0, 1, 2, 140, 142, 240, 241, 242]);
for i in len+1..input.len()-len-1 {
if input[i] == b'@' {
data= [input[i-1], input[i+1], input[i+len], input[i +len +1], input[i+len -1], input[i-len], input[i -(len +1)], input[i-(len -1)]];
let chk = SimdVec::from_array(data);
let count = chk.simd_eq(target).to_bitmask().count_ones();
//let count = vals.simd_eq(target).to_bitmask().count_ones();
if count <4 {
answer += 1;
}
}
}
for i in 1..len {
if input[i] == b'@' {
data= [input[i-1], input[i+1], input[i+len], input[i +len +1], input[i+len -1], 0,0,0];
let chk = SimdVec::from_array(data);
let count = chk.simd_eq(target).to_bitmask().count_ones();
if count <4 {
answer += 1;
}
}
}
for i in input.len()-len..input.len()-1 {
if input[i] == b'@' {
data= [input[i-1], input[i+1], input[i-len], input[i -(len +1)], input[i-(len-1)], 0,0,0];
let chk = SimdVec::from_array(data);
let count = chk.simd_eq(target).to_bitmask().count_ones();
if count <4 {
answer += 1;
}
}
}
if input[len] == b'@' {
data= [input[len-1], input[len+1], input[0], 0, input[1], 0,0,0];
let chk = SimdVec::from_array(data);
let count = chk.simd_eq(target).to_bitmask().count_ones();
if count <4 {
answer += 1;
}
}
let idx = input.len()-len -1;
if input[idx] == b'@' {
data= [input[idx-1], 0, input[idx - len], input[idx + len], input[idx - (len + 1)], input[idx + (len -1)],0,0];
let chk = SimdVec::from_array(data);
let count = chk.simd_eq(target).to_bitmask().count_ones();
if count <4 {
answer += 1;
}
}
if input[0] == b'@'{
answer += 1;
}
if input[input.len()-1] == b'@'{
answer += 1;
}
answer
}
pub fn solve_p2(input: &str) -> u16 {
let mut answer = 0;
let mut data:Vec<Vec<char>> = Vec::with_capacity(256);
for line in input.split('\n') {
let mut data_line: Vec<char> = line.chars().collect();
data_line.insert(0, '0');
data_line.insert(data_line.len(), '0');
data.push(data_line);
}
let len = data[0].len();
let size = data.len();
let mut data: Vec<&char> = data.iter().flatten().collect();
let mut ans = 0;
loop {
for (i, char) in data.clone().iter().enumerate() {
let mut count = 0;
if *char == &'0' || *char == &'.' {
continue;
}
if *char == &'@' {
if i as i32 - len as i32 > 0 {
if data[i - (len - 1)] == &'@' {
count += 1;
}
if data[i - len] == &'@' {
count += 1;
}
if data[i - (len + 1)] == &'@' {
count += 1;
}
}
if i + len < (len * size) {
if data[i + len + 1] == &'@' {
count += 1;
}
if data[i + len] == &'@' {
count += 1;
}
if data[i + len - 1] == &'@' {
count += 1;
}
}
if data[i - 1] == &'@' {
count += 1;
}
if data[i + 1] == &'@' {
count += 1;
}
if count < 4 {
data[i] = &'-';
ans += 1;
}
}
count = 0;
}
if ans == 0 {
break;
} else {
answer += ans;
}
ans = 0;
}
answer
}
pub fn solve_p2_f(input: &[u8]) -> u64 {
let mut input = input.to_vec();
let mut answer = 0;
let len = 140;
let target = SimdVec::splat(b'@');
const LANES: usize = 8;
type SimdVec = Simd<u8, LANES>;
let mut ans = 0;
loop {
for i in len + 1..input.len() - len - 1 {
if input[i] == b'@' {
let data = [input[i - 1], input[i + 1], input[i + len], input[i + len + 1], input[i + len - 1], input[i - (len + 1)], input[i - (len - 1)], input[i - len]];
let (pre, chk, post) = data.as_simd();
let count = chk[0].simd_eq(target).to_bitmask().count_ones();
if count < 4 {
ans += 1;
input[i] = b'.';
}
}
}
for i in 1..len {
if input[i] == b'@' {
let data = [input[i - 1], input[i + 1], input[i + len], input[i + len + 1], input[i + len - 1], 0, 0, 0];
let (pre, chk, post) = data.as_simd();
let count = chk[0].simd_eq(target).to_bitmask().count_ones();
if count < 4 {
ans += 1;
input[i] = b'.';
}
}
}
for i in input.len() - len..input.len() - 1 {
if input[i] == b'@' {
let data = [input[i - 1], input[i + 1], input[i - len], input[i - (len + 1)], input[i - (len - 1)], 0, 0, 0];
let (pre, chk, post) = data.as_simd();
let count = chk[0].simd_eq(target).to_bitmask().count_ones();
if count < 4 {
ans += 1;
input[i] = b'.';
}
}
}
if input[len] == b'@' {
let data = [input[len - 1], input[len + 1], input[0], 0, input[1], 0, 0, 0];
let (pre, chk, post) = data.as_simd();
let count = chk[0].simd_eq(target).to_bitmask().count_ones();
if count < 4 {
ans += 1;
input[len] = b'.';
}
}
let idx = input.len() - len - 1;
if input[idx] == b'@' {
let data = [input[idx - 1], 0, input[idx - len], input[idx + len], input[idx - (len + 1)], input[idx + (len - 1)], 0, 0];
let (pre, chk, post) = data.as_simd();
let count = chk[0].simd_eq(target).to_bitmask().count_ones();
if count <4 {
ans += 1;
input[idx] = b'.';
}
}
if input[0] == b'@'{
ans += 1;
input[0] = b'.';
}
let idx = input.len()-1;
if input[idx] == b'@'{
ans += 1;
input[idx] = b'.';
}
if ans == 0 {
break;
}else {
answer += ans;
ans = 0;
}
}
answer
}

72
src/aoc/aoc_5.rs Normal file
View File

@@ -0,0 +1,72 @@
pub fn solve_p1(input: &str) -> u64 {
let mut answer = 0;
let mut parse_range = true;
let mut ranges = Vec::new();
let mut numbers = Vec::new();
for line in input.lines() {
if line.is_empty() {
parse_range = false;
continue;
}
if parse_range {
let nums = line.split("-").map(|x| x.parse::<u64>().unwrap()).collect::<Vec<_>>();
ranges.push(nums);
} else {
let num = line.parse::<u64>().unwrap();
numbers.push(num);
}
}
ranges.sort();
for num in numbers {
for range in &ranges{
if num >= range[0] {
if num <= range[1] {
answer += 1;
break;
}
} else {
break;
}
}
}
//println!("{:?} {:?}", ranges, numbers);
answer
}
pub fn solve_p2(input: &str) -> u64 {
let mut answer = 0;
let mut ranges = Vec::new();
for line in input.lines() {
if line.is_empty() {
break;
}
let nums = line.split("-").map(|x| x.parse::<u64>().unwrap()).collect::<Vec<_>>();
ranges.push(nums);
}
ranges.sort();
let mut new_ranges:Vec<Vec<u64>> = Vec::new();
let mut new_range = Vec::<u64>::new();
new_range.push(ranges[0][0]);
new_range.push(ranges[0][1]);
for range in ranges.iter() {
if range[0] >= new_range[0] && range[0] <= new_range[1] {
if range[1] > new_range[1] {
new_range[1] = range[1];
}
}else if range[0] > new_range[1] {
new_ranges.push(Vec::from([new_range[0], new_range[1]]));
new_range[0] = range[0];
new_range[1] = range[1];
}
}
new_ranges.push(Vec::from([new_range[0], new_range[1]]));
for range in new_ranges {
answer += range[1] - range[0] + 1;
}
answer
}

158
src/aoc/aoc_6.rs Normal file
View File

@@ -0,0 +1,158 @@
pub fn solve_p1(input: &str) -> u64 {
let mut answer = 0;
let lines = input.lines().count();
let input = input.split_ascii_whitespace().collect::<Vec<_>>();
// println!("{:?}", input.len()/lines);
let len = input.len()/lines;
for i in 0..len {
if input[i+(lines-1)*len] == "+" {
let mut sum = input[i].parse::<u64>().unwrap();
for j in 1..lines-1{
sum += input[i+ len* j].parse::<u64>().unwrap();
}
answer += sum;
} else {
let mut product = input[i].parse::<u64>().unwrap();
for j in 1..lines-1{
product *= input[i+ len* j].parse::<u64>().unwrap();
}
answer += product;
}
}
answer
}
pub fn solve_p2(input: &str) -> u64 {
let mut answer = 0;
let lines = 4;
let input = input.lines().collect::<Vec<_>>();
//println!("{:?}", input);
let mut len = [0;5];
for i in 0..lines{
len[i] = input[i].len();
}
let max_idx = *len.iter().max().unwrap();
let mut temp_ans = 0;
let mut start_idx = 0;
let mut op = false;
for i in 0..max_idx{
if i == start_idx {
if input[4].chars().collect::<Vec<_>>()[i] == '+'{
op = false;
}else {
op = true;
}
}
let mut num1 = ' ';
if i < len[0] {
num1 = input[0].chars().collect::<Vec<_>>()[i];
}
let mut num2 = ' ';
if i < len[1] {
num2 = input[1].chars().collect::<Vec<_>>()[i];
}
let mut num3 = ' ';
if i < len[2] {
num3 = input[2].chars().collect::<Vec<_>>()[i];
}
let mut num4 = ' ';
if i < len[3] {
num4 = input[3].chars().collect::<Vec<_>>()[i];
}
let full_num = format!("{}{}{}{}",num1 , num2 , num3, num4).trim().parse::<u64>().unwrap_or(0);
if full_num != 0 {
if op {
if temp_ans != 0{
temp_ans *= full_num;
} else {
temp_ans = full_num;
}
} else {
temp_ans += full_num;
}
}else {
//println!("{}", temp_ans);
answer += temp_ans;
start_idx = i+1;
temp_ans = 0;
}
}
answer += temp_ans;
answer
}
pub fn solve_p2_f(input: &str) -> u64 {
let mut answer = 0;
let lines = 4;
let input = input.lines().map(| x| {x.chars().collect()}).collect::<Vec<Vec<char>>>();
println!("{:?}", input);
let mut len = [0;5];
for i in 0..lines{
len[i] = input[i].len();
}
let max_idx = *len.iter().max().unwrap();
let mut temp_ans = 0;
let mut start_idx = 0;
let mut op = false;
for i in 0..max_idx{
if i == start_idx {
if input[4][i] == '+'{
op = false;
}else {
op = true;
}
}
let mut num1 = ' ';
if i < len[0] {
num1 = input[0][i];
}
let mut num2 = ' ';
if i < len[1] {
num2 = input[1][i];
}
let mut num3 = ' ';
if i < len[2] {
num3 = input[2][i];
}
let mut num4 = ' ';
if i < len[3] {
num4 = input[3][i];
}
let full_num = format!("{}{}{}{}",num1 , num2 , num3, num4).trim().parse::<u64>().unwrap_or(0);
if full_num != 0 {
if op {
if temp_ans != 0{
temp_ans *= full_num;
} else {
temp_ans = full_num;
}
} else {
temp_ans += full_num;
}
}else {
//println!("{}", temp_ans);
answer += temp_ans;
start_idx = i+1;
temp_ans = 0;
}
}
answer += temp_ans;
answer
}

83
src/aoc/aoc_7.rs Normal file
View File

@@ -0,0 +1,83 @@
pub fn solve_p1(input: &str) -> u64 {
let mut answer = 0;
let lines = input.lines().count();
let mut data = Vec::new();
for line in input.lines() {
let chars = line.chars().collect::<Vec<char>>();
data.push(chars);
}
let start_idx = data[0].iter().len() / 2 ;
data[1][start_idx] = '|';
for (i,line) in data.clone().iter().enumerate() {
//println!("{:?}", data[i]);
for (j,char) in line.iter().enumerate() {
//println!("{}", data[i][j]);
if data[i][j] == '^' {
if data[i-1][j] == '|' {
answer += 1;
data[i][j+1] = '|';
data[i][j-1] = '|';
data[i+1][j-1] = '|';
data[i+1][j+1] = '|';
}
}
else if data[i][j] == '|' {
if i+1 < data.len() {
if data[i+1][j] != '^' {
data[i+1][j] = '|';
}
}
}
}
}
answer
}
pub fn solve_p2(input: &[u8]) -> u64 {
let mut answer = 0;
let mut data = Vec::with_capacity(256);
for line in input.split(|x1| {*x1 == b'\n'}).step_by(1) {
let chars = line.into_iter().map(|mut x| {if x == &b'.' {x = &0; *x as u64} else {*x as u64}}).collect::<Vec<u64>>();
data.push(chars);
}
let start_idx = data[0].iter().len() / 2 ;
data[0][start_idx] = 1;
for i in 0..data.len() {
//println!("{:?}", data[i]);
for j in 0..data[0].len(){
//println!("{}", data[i][j]);
if data[i][j] == 94 {
data[i][j] = 0;
//println!("{}", data[i][j]);
if data[i-1][j] != 0 || data[i][j-1] == 49 {
//println!("{}", data[i-1][j]);
let power = data[i-1][j];
data[i][j-1] += power;
data[i][j+1] += power;
data[i+1][j-1] = data[i][j-1];
data[i+1][j+1] = data[i][j+1];
}
}
else if data[i][j] != 0 {
//println!("{}", data[i][j]);
if i+1 < data.len() {
if data[i+1][j] != 94 {
data[i+1][j] = data[i][j];
}
}
}
}
answer = data[data.len()-1].iter().sum();
}
answer
}

56
src/aoc/aoc_8.rs Normal file
View File

@@ -0,0 +1,56 @@
pub fn solve_p1(input: &str) -> u64 {
let mut answer = 0;
let mut cords = Vec::new();
for line in input.lines() {
let data = line.split(',').flat_map(|d| d.parse::<i64>()).collect_array::<3>().unwrap();
cords.push(data);
}
//println!("{:?}", cords);
let mut closest:Vec<[i64; 3]> = Vec::new();
let mut pairs:Vec<([i64;3], [i64;3])> = Vec::new();
for i in 0..cords.len() {
let mut distance = i64::MAX;;
for j in 0..cords.len() {
if i != j {
let distance_x = cords[i][0] - cords[j][0];
let distance_y = cords[i][1] - cords[j][1];
let distance_z = cords[i][2] - cords[j][2];
let new_distance = ((distance_x.pow(2) + distance_y.pow(2)) + distance_z.pow(2)).isqrt() ;
if new_distance < distance {
distance = new_distance;
if i < closest.len() {
closest[i] = cords[j];
} else {
closest.insert(i, cords[j]);
}
}
}
}
}
for i in 0..closest.len() {
if !pairs.contains(&(cords[i], closest[i])) && !pairs.contains(&(closest[i], cords[i])) {
if cords[i][0] < closest[i][0] {
pairs.push((cords[i], closest[i]));
} else {
pairs.push((closest[i], cords[i]));
}
}
}
pairs.sort_unstable();
//vec of vecs containing all cords combined together
let mut circuits: Vec<Vec<[i64;3]>> = Vec::new();
//circuits[0].push(pairs[0].0);
for i in 0..pairs.len() {
}
// make tree, insert data check if cord in tree
//println!("{:?}", pairs);
answer
}

View File

@@ -0,0 +1,10 @@
..@@.@@@@.
@@@.@.@.@@
@@@@@.@.@@
@.@@@@..@.
@@.@@@@.@@
.@@@@@@@.@
.@.@.@.@@@
@.@@@.@@@@
.@@@@@@@@.
@.@.@@@.@.

View File

@@ -0,0 +1,11 @@
3-5
10-14
16-20
12-18
1
5
8
11
17
32

View File

@@ -0,0 +1,4 @@
123 328 51 64
45 64 387 23
6 98 215 314
* + * +

View File

@@ -0,0 +1,16 @@
.......S.......
...............
.......^.......
...............
......^.^......
...............
.....^.^.^.....
...............
....^.^...^....
...............
...^.^...^.^...
...............
..^...^.....^..
...............
.^.^.^.^.^...^.
...............

View File

@@ -0,0 +1,20 @@
162,817,812
57,618,57
906,360,560
592,479,940
352,342,300
466,668,158
542,29,236
431,825,988
739,650,466
52,470,668
216,146,977
819,987,18
117,168,530
805,96,715
346,949,466
970,615,88
941,993,340
862,61,35
984,92,344
425,690,689

View File

@@ -1 +1,3 @@
#![feature(portable_simd)]
#![feature(exact_length_collection)]
pub mod aoc;

View File

@@ -1,13 +1,62 @@
#![feature(portable_simd)]
#![feature(exact_length_collection)]
extern crate core;
// Enable the nightly feature
pub mod aoc;
use crate::aoc::*;
fn main() {
/*
let input = include_bytes!("aoc/input/full_input_aoc3.txt");
let answer = aoc_3::solve_p1(input);
println!("{}", answer);
let input2 = include_bytes!("aoc/input/full_input_aoc3.txt");
let answer = aoc_3::solve_p1_fast(input2);
println!("{}", answer);
*/
/*
let input = include_bytes!("aoc/input/full_input_aoc4.txt");
let answer = aoc_4::solve_p1_f(input);
println!("{}", answer);
let input = include_bytes!("aoc/input/full_input_aoc4.txt");
let answer = aoc_4::solve_p1(input);
println!("{}", answer);
*/
/*
let input = include_str!("aoc/input/full_input_aoc5.txt");
let answer = aoc_5::solve_p1(input);
println!("{}", answer);
let input = include_str!("aoc/input/test_input_aoc5.txt");
let answer = aoc_5::solve_p2(input);
println!("{}", answer);
*/
/*
let input = include_str!("aoc/input/full_input_aoc6.txt");
let answer = aoc_6::solve_p1(input);
println!("answer: {}", answer);
let input = include_str!("aoc/input/full_input_aoc6.txt");
let answer = aoc_6::solve_p2(input);
println!("answer: {}", answer);
*/
/*
let input = include_str!("aoc/input/full_input_aoc7.txt");
let answer = aoc_7::solve_p1(input);
println!("answer: {}", answer);
let input = include_bytes!("aoc/input/full_input_aoc7.txt");
let answer = aoc_7::solve_p2(input);
println!("answer: {}", answer);
*/
let input = include_str!("aoc/input/test_input_aoc8.txt");
let answer = aoc_8::solve_p1(input);
println!("answer: {}", answer);
}
#[test]
@@ -63,3 +112,32 @@ fn test_aoc_3_part2() {
172787336861064
);
}
#[test]
fn test_aoc_4_part1() {
assert_eq!(
aoc_4::solve_p1(include_bytes!("aoc/input/full_input_aoc4.txt")),
1486
);
}
#[test]
fn test_aoc_4_part2() {
assert_eq!(
aoc_4::solve_p2_f(include_bytes!("aoc/input/full_input_aoc4.txt")),
9024
);
}
#[test]
fn test_aoc_5_part1() {
assert_eq!(
aoc_5::solve_p1(include_str!("aoc/input/full_input_aoc5.txt")),
865
);
}
#[test]
fn test_aoc_5_part2() {
assert_eq!(
aoc_5::solve_p2(include_str!("aoc/input/full_input_aoc5.txt")),
352556672963116
);
}