mirror of
https://github.com/Noratrieb/advent-of-code.git
synced 2026-01-14 09:35:01 +01:00
day1
This commit is contained in:
commit
2cfee8a448
11 changed files with 240 additions and 0 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
use nix
|
||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
input*.txt
|
||||
1
2023/day1/.gitignore
vendored
Normal file
1
2023/day1/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/target
|
||||
7
2023/day1/Cargo.lock
generated
Normal file
7
2023/day1/Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "day1"
|
||||
version = "0.1.0"
|
||||
11
2023/day1/Cargo.toml
Normal file
11
2023/day1/Cargo.toml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "day1"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[profile.release]
|
||||
debug = 1
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
12
2023/day1/README.md
Normal file
12
2023/day1/README.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# day 1
|
||||
|
||||
benchmarks:
|
||||
|
||||
Ensure that `input.txt` contains many, many copies of the actual input, the actual input is way too small.
|
||||
|
||||
`cargo build --release && hyperfine 'target/release/day1 naive' 'target/release/day1 zero_alloc' 'target/release/day1 branchless'`
|
||||
```
|
||||
target/release/day1 branchless ran
|
||||
1.52 ± 0.06 times faster than target/release/day1 zero_alloc
|
||||
7.74 ± 0.27 times faster than target/release/day1 naive
|
||||
```
|
||||
76
2023/day1/src/branchless.rs
Normal file
76
2023/day1/src/branchless.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
pub unsafe fn part2(input: &str) {
|
||||
let sum = input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let bytes = line.as_bytes();
|
||||
|
||||
let mut digits = [0_u8; 128];
|
||||
|
||||
assert!(bytes.len() <= digits.len());
|
||||
|
||||
let mut i = 0;
|
||||
|
||||
while i < bytes.len() {
|
||||
let mut insert = |b| digits[i] |= b;
|
||||
|
||||
// in memory:
|
||||
// o n e X X X X X
|
||||
// in the integer bytes:
|
||||
// X X X X X e n o
|
||||
let block = bytes.as_ptr().add(i).cast::<u64>().read_unaligned().to_le();
|
||||
|
||||
let one = (block & ((1 << (8 * 1)) - 1)) as u8;
|
||||
let three = block & ((1 << (8 * 3)) - 1);
|
||||
let four = block & ((1 << (8 * 4)) - 1);
|
||||
let five = block & ((1 << (8 * 5)) - 1);
|
||||
|
||||
const fn gorble(s: &[u8]) -> u64 {
|
||||
let mut bytes = [0; 8];
|
||||
let mut i = 0;
|
||||
while i < s.len() {
|
||||
bytes[7 - i] = s[i];
|
||||
i += 1;
|
||||
}
|
||||
// like: u64::from_be_bytes([0, 0, 0, b't', b'h', b'g', b'i', b'e'])
|
||||
u64::from_be_bytes(bytes)
|
||||
}
|
||||
macro_rules! check {
|
||||
($const:ident $len:ident == $str:expr => $value:expr) => {
|
||||
const $const: u64 = gorble($str);
|
||||
insert(if $len == $const { $value } else { 0 });
|
||||
};
|
||||
}
|
||||
|
||||
insert(if one >= b'0' && one <= b'9' { one } else { 0 });
|
||||
|
||||
check!(EIGHT five == b"eight" => b'8');
|
||||
check!(SEVEN five == b"seven" => b'7');
|
||||
check!(THREE five == b"three" => b'3');
|
||||
|
||||
check!(FIVE four == b"five" => b'5');
|
||||
check!(FOUR four == b"four" => b'4');
|
||||
check!(NINE four == b"nine" => b'9');
|
||||
|
||||
check!(SIX three == b"six" => b'6');
|
||||
check!(TWO three == b"two" => b'2');
|
||||
check!(ONE three == b"one" => b'1');
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
let first = digits[..bytes.len()].iter().find(|&&d| d > b'0').unwrap();
|
||||
let last = digits[..bytes.len()]
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|&&d| d > b'0')
|
||||
.unwrap();
|
||||
|
||||
let first = (first - b'0') as u64;
|
||||
let last = (last - b'0') as u64;
|
||||
|
||||
first * 10 + last
|
||||
})
|
||||
.sum::<u64>();
|
||||
|
||||
println!("part2: {sum}");
|
||||
}
|
||||
49
2023/day1/src/main.rs
Normal file
49
2023/day1/src/main.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
use std::mem::MaybeUninit;
|
||||
|
||||
mod branchless;
|
||||
mod naive;
|
||||
mod zero_alloc;
|
||||
|
||||
fn main() {
|
||||
let kind = std::env::args().nth(1).unwrap_or("naive".into());
|
||||
|
||||
let mut input = std::hint::black_box(include_str!("../input.txt")).to_owned();
|
||||
|
||||
input.reserve(5);
|
||||
unsafe {
|
||||
input
|
||||
.as_mut_vec()
|
||||
.spare_capacity_mut()
|
||||
.fill(MaybeUninit::new(0))
|
||||
};
|
||||
|
||||
match kind.as_str() {
|
||||
"part1" => part1(&input),
|
||||
"naive" => naive::part2(&input),
|
||||
"zero_alloc" => zero_alloc::part2(&input),
|
||||
"branchless" => unsafe { branchless::part2(&input) },
|
||||
_ => {
|
||||
eprintln!("error: invalid mode, must be part1,naive,zero_alloc,branchless");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn part1(input: &str) {
|
||||
let sum = input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let mut chars = line.chars().filter(|c| c.is_ascii_digit());
|
||||
let first = chars.next().unwrap();
|
||||
let last = chars.next_back().unwrap_or(first);
|
||||
|
||||
[first, last]
|
||||
.into_iter()
|
||||
.collect::<String>()
|
||||
.parse::<u64>()
|
||||
.unwrap()
|
||||
})
|
||||
.sum::<u64>();
|
||||
|
||||
println!("part1: {sum}");
|
||||
}
|
||||
28
2023/day1/src/naive.rs
Normal file
28
2023/day1/src/naive.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
pub fn part2(input: &str) {
|
||||
let sum = input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let line = line
|
||||
.replace("one", "one1one")
|
||||
.replace("two", "two2two")
|
||||
.replace("three", "three3three")
|
||||
.replace("four", "four4four")
|
||||
.replace("five", "five5five")
|
||||
.replace("six", "six6six")
|
||||
.replace("seven", "seven7seven")
|
||||
.replace("eight", "eight8eight")
|
||||
.replace("nine", "nine9nine");
|
||||
let mut chars = line.chars().filter(|c| c.is_ascii_digit());
|
||||
let first = chars.next().unwrap();
|
||||
let last = chars.next_back().unwrap_or(first);
|
||||
|
||||
[first, last]
|
||||
.into_iter()
|
||||
.collect::<String>()
|
||||
.parse::<u64>()
|
||||
.unwrap()
|
||||
})
|
||||
.sum::<u64>();
|
||||
|
||||
println!("part2: {sum}");
|
||||
}
|
||||
43
2023/day1/src/zero_alloc.rs
Normal file
43
2023/day1/src/zero_alloc.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
pub fn part2(input: &str) {
|
||||
let sum = input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let bytes = line.as_bytes();
|
||||
|
||||
let mut i = 0;
|
||||
let mut first = None;
|
||||
let mut last = b'_';
|
||||
|
||||
let mut insert = |byte| {
|
||||
if first.is_none() {
|
||||
first = Some(byte);
|
||||
}
|
||||
last = byte;
|
||||
};
|
||||
|
||||
while i < bytes.len() {
|
||||
match bytes[i] {
|
||||
b @ b'0'..=b'9' => insert(b),
|
||||
b'o' if bytes.get(i..(i + 3)) == Some(b"one") => insert(b'1'),
|
||||
b't' if bytes.get(i..(i + 3)) == Some(b"two") => insert(b'2'),
|
||||
b't' if bytes.get(i..(i + 5)) == Some(b"three") => insert(b'3'),
|
||||
b'f' if bytes.get(i..(i + 4)) == Some(b"four") => insert(b'4'),
|
||||
b'f' if bytes.get(i..(i + 4)) == Some(b"five") => insert(b'5'),
|
||||
b's' if bytes.get(i..(i + 3)) == Some(b"six") => insert(b'6'),
|
||||
b's' if bytes.get(i..(i + 5)) == Some(b"seven") => insert(b'7'),
|
||||
b'e' if bytes.get(i..(i + 5)) == Some(b"eight") => insert(b'8'),
|
||||
b'n' if bytes.get(i..(i + 4)) == Some(b"nine") => insert(b'9'),
|
||||
_ => {}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
let first = (first.unwrap() - b'0') as u64;
|
||||
let last = (last - b'0') as u64;
|
||||
|
||||
first * 10 + last
|
||||
})
|
||||
.sum::<u64>();
|
||||
|
||||
println!("part2: {sum}");
|
||||
}
|
||||
11
shell.nix
Normal file
11
shell.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{ pkgs ? import <nixpkgs> { } }: pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
rustup
|
||||
];
|
||||
shellHook = ''
|
||||
export PATH=$PATH:''${CARGO_HOME:-~/.cargo}/bin
|
||||
'';
|
||||
packages = (with pkgs; [
|
||||
shellcheck
|
||||
]);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue