+23
2025/Cargo.lock
+23
2025/Cargo.lock
···
13
13
version = "0.1.0"
14
14
dependencies = [
15
15
"anyhow",
16
+
"atoi_simd",
17
+
"memchr",
16
18
]
19
+
20
+
[[package]]
21
+
name = "atoi_simd"
22
+
version = "0.17.0"
23
+
source = "registry+https://github.com/rust-lang/crates.io-index"
24
+
checksum = "8ad17c7c205c2c28b527b9845eeb91cf1b4d008b438f98ce0e628227a822758e"
25
+
dependencies = [
26
+
"debug_unsafe",
27
+
]
28
+
29
+
[[package]]
30
+
name = "debug_unsafe"
31
+
version = "0.1.3"
32
+
source = "registry+https://github.com/rust-lang/crates.io-index"
33
+
checksum = "85d3cef41d236720ed453e102153a53e4cc3d2fde848c0078a50cf249e8e3e5b"
34
+
35
+
[[package]]
36
+
name = "memchr"
37
+
version = "2.7.6"
38
+
source = "registry+https://github.com/rust-lang/crates.io-index"
39
+
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
+2
2025/Cargo.toml
+2
2025/Cargo.toml
+48
-6
2025/src/days/one/secret_entrance.rs
+48
-6
2025/src/days/one/secret_entrance.rs
···
1
+
use atoi_simd::parse as parse_i32;
2
+
1
3
pub fn main() -> anyhow::Result<()> {
2
4
crate::run("Secret Entrance", "inputs/day1.txt", parse, part_a, part_b)
3
5
}
4
6
5
-
fn parse(input: &str) -> Vec<i32> {
6
-
input
7
-
.lines()
8
-
.filter(|line| !line.is_empty())
9
-
.filter_map(|line| line.replace("L", "-").replace("R", "").parse().ok())
10
-
.collect()
7
+
fn parse(input: &[u8]) -> Vec<i32> {
8
+
let mut out = Vec::with_capacity(4503);
9
+
let mut start = 0;
10
+
11
+
while start < input.len() {
12
+
let end = match memchr::memchr(b'\n', &input[start..]) {
13
+
Some(index) => start + index,
14
+
None => input.len(),
15
+
};
16
+
let line = &input[start..end];
17
+
18
+
if !line.is_empty() {
19
+
let mut buf = [0u8; 4];
20
+
let mut len = 0usize;
21
+
let mut seen_digit = false;
22
+
23
+
for &b in line {
24
+
match b {
25
+
b'L' => {
26
+
if len == 0 {
27
+
buf[len] = b'-';
28
+
len += 1;
29
+
}
30
+
}
31
+
b'0'..=b'9' => {
32
+
seen_digit = true;
33
+
buf[len] = b;
34
+
len += 1;
35
+
}
36
+
_ => {
37
+
len = 0;
38
+
break;
39
+
}
40
+
}
41
+
}
42
+
if seen_digit && len > 0 {
43
+
if let Ok(num) = parse_i32(&buf[..len]) {
44
+
out.push(num);
45
+
}
46
+
}
47
+
}
48
+
49
+
start = end + 1;
50
+
}
51
+
52
+
out
11
53
}
12
54
13
55
fn part_a(input: Vec<i32>) -> usize {
+4
-2
2025/src/lib.rs
+4
-2
2025/src/lib.rs
···
13
13
) -> Result<()>
14
14
where
15
15
T: Clone,
16
-
P: Fn(&str) -> T,
16
+
P: Fn(&[u8]) -> T,
17
17
A: Fn(T) -> RA,
18
18
B: Fn(T) -> RB,
19
19
RA: Display,
20
20
RB: Display,
21
21
{
22
+
let file = &fs::read_to_string(input_path)?;
23
+
let bytes = file.as_bytes();
22
24
let label_parse = format!("{name} Parse");
23
25
let parse_start = Instant::now();
24
-
let input = parse(&fs::read_to_string(input_path)?);
26
+
let input = parse(bytes);
25
27
let parse_elapsed = parse_start.elapsed();
26
28
println!("{label_parse}");
27
29
println!("{}", "-".repeat(label_parse.len()));
+14
2025/src/main.rs
+14
2025/src/main.rs
···
1
+
#![feature(test)]
2
+
extern crate test;
3
+
1
4
fn main() -> anyhow::Result<()> {
2
5
aoc2025::days::one::secret_entrance::main()?;
3
6
Ok(())
4
7
}
8
+
9
+
#[cfg(test)]
10
+
mod tests {
11
+
use aoc2025::days;
12
+
use test::Bencher;
13
+
14
+
#[bench]
15
+
fn day1(b: &mut Bencher) {
16
+
b.iter(|| days::one::secret_entrance::main())
17
+
}
18
+
}