#!/usr/bin/perl use v5.35.0; use List::Util qw(sum); my $map_width; my @map; my @trailheads; while (<>) { $map_width ||= length; for (split //) { push @map, /\d/? 0+$_ : undef; push @trailheads, $#map if /0/; } } { my @memo; sub rating($location) { return $memo[$location] if defined $memo[$location]; my $rating = $map[$location] == 9; unless ($rating) { my $uphill = $map[$location] + 1; for my $offset (-$map_width, 1, $map_width, -1) { my $neighbour = $location + $offset; next unless 0 <= $neighbour < @map; next unless defined $map[$neighbour]; next unless $map[$neighbour] == $uphill; $rating += rating($neighbour); } } return $memo[$location] = $rating; } } say sum map {rating($_)} @trailheads;