re: Daily Challenge #77 - Bird Mountain VIEW POST

FULL DISCUSSION
 

Not as elegant as I hoped. Debugging output included.

#!/usr/bin/perl
use warnings;
use strict;

use List::Util qw{ max };

sub populate {
    my ($view) = @_;
    my @grid;
    my $y = 1;
    my $max_x = 0;
    for my $line (split /\n/, $view) {
        my $x = 0;
        for my $char (split //, " $line") {
            $grid[$y][$x++] = (0, undef)[$char eq ' '];
            $max_x = $x if $x > $max_x;
        }
        ++$y;
    }
    return $max_x, @grid, []
}

sub height {
    my ($view) = @_;
    my ($max_x, @grid) = populate($view);
    my @height = map [ map defined $_ ? 0 : -1, @{ $grid[$_] }[0 .. $max_x] ],
                 0 .. $#grid;
    my $max_height = 0;
    my $change = 1;
    while ($change) {
        undef $change;
        show(@height);
        my @next = map [ @$_ ], @height;
        for my $x (0 .. $max_x) {
            for my $y (0 .. $#grid) {
                my @neighbours
                    = map $height[ $_->[1] ][ $_->[0] ] // -1,
                      grep $_->[1] >= 0 && $_->[0] >= 0,
                      [$x-1, $y], [$x+1, $y], [$x, $y-1], [$x, $y+1];
                if ($height[$y][$x] == 0
                    && grep $_ == $max_height - 1, @neighbours
                ) {
                    $next[$y][$x] = 1 + max(@neighbours);
                    $change = 1;
                }
            }
        }
        @height = @next;
        ++$max_height unless $max_height;
        ++$max_height;
    }
    return $max_height - 2
}

sub show {
    for my $line (@_) {
        printf '%3s', $_ for @$line;
        print "\n";
    }
    print "\n";
}

use Test::More tests => 4;

is height(<< '__INPUT__'), 2;
^^^
^^^
^^^
__INPUT__

is height(<< '__INPUT__'), 2;
^^^^^^^
^^^^^^^
^^^^^^^
^^^ ^^^
^^^^^^^
^^^^^^^
^^^^^^^
__INPUT__

is height(<< '__INPUT__'), 4;
^^^^^^^
^^^^^^^
^^^^^^^
^^^^^^^
^^^^^^^
^^^^^^^
^^^^^^^
__INPUT__

is height(<< '__INPUT__'), 3;
^^^^^^
 ^^^^^^^^
  ^^^^^^^
  ^^^^^
  ^^^^^^^^^^^^^
  ^^^^^^
  ^^^^
__INPUT__
code of conduct - report abuse