Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env perl
- #
- # Advent of Code 2025
- # --- Day 5: Cafeteria ---
- # Solution in Perl by Matthias Muth (muthm).
- #
- use v5.36;
- sub puzzle( $input ) {
- my ( @fresh_ranges, @availables );
- for ( split "\n", $input ) {
- /^(\d+)-(\d+)/ and do { push @fresh_ranges, [ $1, $2 ]; next };
- /^(\d+)/ and do { push @availables, $1; next };
- }
- # Sort the ranges by their 'from' value, lowest to highest,
- # and sort the availables, lowest to highest.
- @fresh_ranges = sort { $a->[0] <=> $b->[0] } @fresh_ranges;
- @availables = sort { $a <=> $b } @availables;
- # Part 1
- # Move through the (sorted) availables, while at the same time moving
- # through the (sorted) ranges in sync using a 'current range'.
- # The 'current range' is the first range that *may* include the
- # current loop value because it has a 'to' value that is higher.
- # As the ranges are sorted by their 'from' value, all the ranges
- # from left to right will be considered correctly.
- # Initialize the first range.
- my $current_range = 0;
- my ( $range_from, $range_to ) = $fresh_ranges[$current_range]->@*;
- my $fresh_count = 0;
- for ( @availables ) {
- # Skip to next range that has a higher 'to' value
- # if we have left the current range.
- while ( $_ > $range_to && ++$current_range <= $#fresh_ranges ) {
- ( $range_from, $range_to ) = $fresh_ranges[$current_range]->@*;
- }
- # End the loop if we have passed beyond the last range.
- last if $_ > $range_to;
- # Increment the count if the current value is inside the current range.
- # Only the 'from' value needs to be checked, because the 'to' value
- # is certain to be higher at this point.
- ++$fresh_count
- if $_ >= $range_from;
- }
- my $part_1_result = $fresh_count;
- # Part 2:
- # Using the ranges sorted by their 'from' values, add the number
- # of items in each range.
- # To deal with overlapping ranges, keep the highest 'to' value that was
- # processed, and adjust the 'from' value of subsequent ranges to start
- # right after it, if necessary.
- my $last_processed = 0;
- $fresh_count = 0;
- for ( @fresh_ranges ) {
- ( $range_from, $range_to ) = $_->@*;
- next if $last_processed >= $range_to;
- $range_from = $last_processed + 1
- if $last_processed >= $range_from;
- $fresh_count += $range_to - $range_from + 1
- if $range_from <= $range_to;
- $last_processed = $range_to;
- }
- my $part_2_result = $fresh_count;
- return ( $part_1_result, $part_2_result );
- }
- # Usage: no command line arguments: run the example from the __DATA__section,
- # else read input data from the file given (or stdin if the file is '-').
- chomp( my $input = join "", @ARGV ? <> : <DATA> );
- my @results = puzzle( $input );
- say "part 1 answer: ", $results[0];
- say "part 2 answer: ", $results[1];
- __DATA__
- 3-5
- 10-14
- 16-20
- 12-18
- 1
- 5
- 8
- 11
- 17
- 32
Add Comment
Please, Sign In to add comment