Skip to content

Optimize year2020/day01 by sorting the input for average-case speedup#86

Merged
maneatingape merged 1 commit into
maneatingape:mainfrom
erghelium:main
Jun 17, 2026
Merged

Optimize year2020/day01 by sorting the input for average-case speedup#86
maneatingape merged 1 commit into
maneatingape:mainfrom
erghelium:main

Conversation

@erghelium

@erghelium erghelium commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Description

I don't know if this counts as a performance improvement because it does not improve the algorithm per se. I think it is akin to assuming that the solutions always follow a normal distribution, i.e., after sorting, the solutions end up closer to the middle of the vector instead of the extremes. I have only tested this with three different inputs, and they all seem well-behaved. The numbers from the second input are the most interesting.

INPUT 1

From:

test year2020::day01::parse_bench ... bench:   765.28 ns/iter (+/- 65.21)
test year2020::day01::part1_bench ... bench:   253.07 ns/iter (+/- 2.33)
test year2020::day01::part2_bench ... bench: 2,255.32 ns/iter (+/- 216.54)

To:

test year2020::day01::parse_bench ... bench: 1,773.68 ns/iter (+/- 22.44)
test year2020::day01::part1_bench ... bench:   144.28 ns/iter (+/- 23.83)
test year2020::day01::part2_bench ... bench:   502.70 ns/iter (+/- 36.10)

Total save: ~853 ns (similar numbers for the third input). The increase in parsing is because the sorting is done there.

INPUT 2

From:

test year2020::day01::parse_bench ... bench:   761.73 ns/iter (+/- 63.86)
test year2020::day01::part1_bench ... bench:   214.03 ns/iter (+/- 2.65)
test year2020::day01::part2_bench ... bench: 6,403.33 ns/iter (+/- 113.83)

To:

test year2020::day01::parse_bench ... bench: 2,198.83 ns/iter (+/- 99.16)
test year2020::day01::part1_bench ... bench:   250.85 ns/iter (+/- 3.93)
test year2020::day01::part2_bench ... bench:   151.89 ns/iter (+/- 4.65)

Total save: ~4,777.52ns.

Could this be counted as a valid heuristic? I just found the behavior interesting, but no worries if you decide to skip it.

Type of change

  • Performance improvement
  • Bug fix
  • Other

Checklist

  • Pull request title and commit messages are clear and informative.
  • Documentation has been updated if necessary.
  • Code style matches the existing code. This one is somewhat subjective, but try to "fit in" by
    using the same naming conventions. Code should be portable, avoiding any
    architecture-specific intrinsics.
  • Tests pass cargo test
  • Code is formatted cargo fmt -- `find . -name "*.rs"`
  • Code is linted cargo clippy --all-targets --all-features

@maneatingape maneatingape left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice observation!

Before:

test year2020::day01::parse_bench ... bench:         576.99 ns/iter (+/- 47.59)
test year2020::day01::part1_bench ... bench:         227.95 ns/iter (+/- 4.93)
test year2020::day01::part2_bench ... bench:       9,203.40 ns/iter (+/- 1,601.62)

After:

test year2020::day01::parse_bench ... bench:       1,291.23 ns/iter (+/- 31.08)
test year2020::day01::part1_bench ... bench:         160.66 ns/iter (+/- 48.27)
test year2020::day01::part2_bench ... bench:         416.53 ns/iter (+/- 2.57)

Could this be counted as a valid heuristic?

Absolutely! This feels similar to the pivot selection of quicksort, not theoretically guaranteed to avoid the worst case O complexity, but faster in practice.

Comment thread src/year2020/day01.rs

pub fn parse(input: &str) -> Vec<usize> {
input.iter_unsigned().collect()
let mut numbers: Vec<usize> = input.iter_unsigned().collect();

@maneatingape maneatingape Jun 17, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good.

Minor suggestion: Would you mind adding a small comment, explaining this to the reader, i.e something like: It's not necessary for correctness but improves the average running time for most (all?) inputs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added the comment and squashed the commits. Let me know if this looks good.

@maneatingape maneatingape left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@maneatingape maneatingape merged commit cfdf2e8 into maneatingape:main Jun 17, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants