iToverDose/Software· 26 APRIL 2026 · 04:02

How sorting ranges and IDs boosted Advent of Code 2025 Day 5 efficiency

A software engineer optimized their brute-force approach for Advent of Code 2025 Day 5 by leveraging sorted ranges and ingredient IDs. This reduced 200,000 operations to fewer than 200, delivering a correct solution.

DEV Community3 min read0 Comments

Advent of Code 2025 has once again challenged developers to think beyond brute-force solutions, and Day 5 offered a perfect opportunity to refine algorithmic thinking. The problem required matching ingredient IDs against a list of numeric ranges, a task that could easily spiral into inefficient territory without careful optimization.

From brute-force to strategic optimization

The initial instinct for many programmers might be to iterate through each ingredient ID and check it against every range until a match is found. With 1,000 IDs and nearly 200 ranges provided in the puzzle input, this approach could theoretically involve up to 200,000 operations. While the runtime might still be acceptable in practice, it lacks elegance—and more importantly, it doesn’t scale well if the inputs grow larger in future challenges.

However, a simple yet powerful insight emerged: sorting. By sorting both the list of IDs and the ranges based on their lower boundaries, each subsequent range could be checked against a progressively smaller subset of IDs. This reduced the number of comparisons from 1,000 iterations per range down to a maximum of 200 range checks across all IDs, drastically cutting unnecessary comparisons.

Leveraging sorted data for faster lookups

The revised algorithm began by parsing the input into two sorted lists:

let [ranges, ids] = input.split('\n\n');

ranges = ranges
  .split('\n')
  .map(str => str.split('-').map(Number))
  .sort((a, b) => a[0] - b[0]);

ids = ids
  .split('\n')
  .map(Number)
  .sort((a, b) => a - b);

This preprocessing step transformed the puzzle from a high-overhead search into an efficient sieve. By filtering IDs within each range and removing matched IDs immediately, the algorithm avoided duplicate matches and ensured each ID was only counted once.

ranges.reduce((count, range) => {
  let matches = ids.filter(el => el >= range[0] && el <= range[1]);
  ids.splice(ids.indexOf(matches[0]), matches.length);
  count += matches.length;
  return count;
}, 0);

Testing with the example input confirmed correctness, and running the solution on the actual puzzle input produced the expected result—validating both the logic and efficiency of the approach.

Expanding beyond matching: merging overlapping ranges

Part 2 of Day 5 introduced a new twist: instead of simply counting matching IDs, the task required counting all numbers contained within the ranges. Given the potential scale of the input, generating a full list of every number was infeasible.

The solution hinged on recognizing that overlapping ranges could be merged into continuous intervals. With the ranges already sorted by their starting points, the algorithm could traverse them sequentially, merging any adjacent or overlapping intervals into consolidated pairs.

let part2 = [];
part2.push(ranges.splice(0, 1).flat());

ranges.forEach(range => {
  if (range[0] <= part2[part2.length - 1][1]) {
    part2[part2.length - 1][1] = range[1];
  } else {
    part2.push(range);
  }
});

This method ensured that overlapping ranges like [10, 14], [12, 18], and [16, 20] were merged into a single interval [10, 20], reducing complexity and eliminating redundant counting.

The final step involved summing the count of integers in each merged range using a simple arithmetic formula:

let answer = part2.reduce((total, range) => {
  total += range[1] - range[0] + 1;
  return total;
}, 0);

While the initial run on the puzzle input produced a result that was too low, debugging revealed a subtle issue in range merging logic—underscoring the importance of thorough testing even after apparent correctness.

Building scalable solutions for future challenges

The evolution from brute-force to optimized algorithms on Day 5 highlights a core principle in competitive programming and software engineering: efficiency is not just about speed—it’s about scalability and maintainability. By prioritizing sorting and merging, the solution transformed an O(n·m) problem into an O(n log n) one, setting a strong foundation for handling larger inputs in future challenges.

As Advent of Code 2025 continues, developers are reminded that the most robust solutions often lie not in writing faster loops, but in rethinking how data is structured and processed. The next puzzle may demand a different kind of insight, but the lesson remains: algorithmic elegance is the ultimate performance enhancer.

AI summary

Advent of Code 2025’in 5. gününde brute-force’tan optimize edilmiş algoritmalara geçiş yaparak performansı nasıl artırabileceğinizi keşfedin. Sıralama ve aralık birleştirme teknikleriyle kodunuzu hızlandırın.

Comments

00
LEAVE A COMMENT
ID #M914UB

0 / 1200 CHARACTERS

Human check

3 + 6 = ?

Will appear after editor review

Moderation · Spam protection active

No approved comments yet. Be first.