68 lines
1.1 KiB
Perl
68 lines
1.1 KiB
Perl
#!/usr/bin/env perl
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use List::Util qw(reduce);
|
|
|
|
my @reports;
|
|
while (<>) {
|
|
my @numbers = split;
|
|
next unless @numbers;
|
|
push @reports, \@numbers;
|
|
}
|
|
|
|
print "Part 1:\n";
|
|
my $safe_reports = reduce { $a + $b } map { is_safe(@$_) } @reports;
|
|
print $safe_reports . "\n";
|
|
|
|
print "Part 2:\n";
|
|
$safe_reports = reduce { $a + $b } map { is_safe_with_modification(@$_) } @reports;
|
|
print $safe_reports . "\n";
|
|
|
|
sub is_safe {
|
|
return (is_increasing(@_) || is_decreasing(@_)) && max_diff(@_);
|
|
}
|
|
|
|
sub is_safe_with_modification {
|
|
return 1 if is_safe(@_);
|
|
|
|
# This is really dumb...
|
|
for (my $i = 0; $i < @_; $i++) {
|
|
my @to_test = @_;
|
|
splice @to_test, $i, 1;
|
|
return 1 if is_safe(@to_test);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
sub is_increasing {
|
|
my $prev = shift;
|
|
for (@_) {
|
|
return 0 if ($_ <= $prev);
|
|
$prev = $_;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
sub is_decreasing {
|
|
my $prev = shift;
|
|
for (@_) {
|
|
return 0 if ($_ >= $prev);
|
|
$prev = $_;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
sub max_diff {
|
|
my $prev = shift;
|
|
|
|
for (@_) {
|
|
if ((abs($_ - $prev) > 3) || (abs($_ - $prev) < 1)) {
|
|
return 0;
|
|
}
|
|
$prev = $_;
|
|
}
|
|
return 1;
|
|
}
|