# RabbitFarm

### 2023-02-05

#### Into the Odd Wide Valley

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

## Part 1

You are given an array of integers. Write a script to print 1 if there are THREE consecutive odds in the given array otherwise print 0.

### Solution

``````
use v5.36;
use boolean;

sub three_consecutive_odds{
my @numbers = @_;
my \$consecutive_odds = 0;
{
my \$x = pop @numbers;
\$consecutive_odds++   if 1 == (\$x & 1);
\$consecutive_odds = 0 if 0 == (\$x & 1);
return true if 3 == \$consecutive_odds;
redo if @numbers;
}
return false;
}

MAIN:{
say three_consecutive_odds(1, 5, 3, 6);
say three_consecutive_odds(2, 6, 3, 5);
say three_consecutive_odds(1, 2, 3, 4);
say three_consecutive_odds(2, 3, 5, 7);
}
``````

### Sample Run

``````
\$ perl perl/ch-1.pl
1
0
0
1
``````

## Part 2

Given a profile as a list of altitudes, return the leftmost widest valley. A valley is defined as a subarray of the profile consisting of two parts: the first part is non-increasing and the second part is non-decreasing. Either part can be empty.

### Solution

``````
use v5.36;
use boolean;
use FSA::Rules;

sub widest_valley_rules{
my @altitudes = @_;
my @downslope;
my @upslope;
my \$fsa = FSA::Rules->new(
move => {
do => sub{  my \$state = shift;
\$state->machine->{altitude}  = [] if(!\$state->machine->{altitude});
\$state->machine->{plateau}   = [] if(!\$state->machine->{plateau});
\$state->machine->{downslope} = [] if(!\$state->machine->{downslope});
\$state->machine->{upslope}   = [] if(!\$state->machine->{upslope});
my \$previous_altitudes = \$state->machine->{altitude};
my \$current_altitude = shift @altitudes;
push @{\$previous_altitudes}, \$current_altitude
},
rules => [ done      => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
!defined(\$previous_altitudes->[@{\$previous_altitudes} - 1])
},
move      => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
@{\$previous_altitudes} ==  1;
},
plateau   => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(@{\$previous_altitudes} == 2){
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] == \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{plateau}}, \$previous_altitudes->[@{\$previous_altitudes} - 2], \$previous_altitudes->[@{\$previous_altitudes} - 1];
}
}
},
plateau   => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(@{\$previous_altitudes} > 2){
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] == \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{plateau}}, \$previous_altitudes->[@{\$previous_altitudes} - 1];
}
}
},
downslope => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(@{\$previous_altitudes} == 2){
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] < \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{downslope}}, \$previous_altitudes->[@{\$previous_altitudes} - 2], \$previous_altitudes->[@{\$previous_altitudes} - 1];
}
}
},
downslope => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(@{\$previous_altitudes} > 2){
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] < \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{downslope}}, \$previous_altitudes->[@{\$previous_altitudes} - 1];
}else{false}
}
},
upslope => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(@{\$previous_altitudes} == 2){
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] > \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{upslope}}, \$previous_altitudes->[@{\$previous_altitudes} - 2], \$previous_altitudes->[@{\$previous_altitudes} - 1];
}
}
},
upslope => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(@{\$previous_altitudes} > 2){
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] > \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{upslope}}, \$previous_altitudes->[@{\$previous_altitudes} - 1];
}
}
},
],
},
plateau => {
do => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
my \$current_altitude = shift @altitudes;
push @{\$previous_altitudes}, \$current_altitude;
},
rules => [ done      => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
!defined(\$previous_altitudes->[@{\$previous_altitudes} - 1])
},
plateau   => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] == \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{plateau}}, \$previous_altitudes->[@{\$previous_altitudes} - 1];
}
},
downslope => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] < \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{downslope}}, @{\$state->machine->{plateau}};
push @{\$state->machine->{downslope}}, \$previous_altitudes->[@{\$previous_altitudes} - 1];
\$state->machine->{plateau} = [];
}
},
upslope   => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] > \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{upslope}}, @{\$state->machine->{plateau}};
push @{\$state->machine->{upslope}}, \$previous_altitudes->[@{\$previous_altitudes} - 1];
\$state->machine->{plateau} = [];
}
}
],
},
downslope => {
do => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
my \$current_altitude = shift @altitudes;
push @{\$previous_altitudes}, \$current_altitude;
},
rules => [ done      => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
!defined(\$previous_altitudes->[@{\$previous_altitudes} - 1])
},
plateau   => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] == \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{plateau}}, \$previous_altitudes->[@{\$previous_altitudes} - 2], \$previous_altitudes->[@{\$previous_altitudes} - 1];
#pop @{\$state->machine->{downslope}};true;
}
},
downslope => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] < \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{downslope}}, \$previous_altitudes->[@{\$previous_altitudes} - 1];
}
},
upslope   => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] > \$previous_altitudes->[@{\$previous_altitudes} - 2]){
\$state->machine->{upslope} = [];
push @{\$state->machine->{upslope}}, \$previous_altitudes->[@{\$previous_altitudes} - 1];
}
},
],
},
upslope => {
do => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
my \$current_altitude = shift @altitudes;
push @{\$previous_altitudes}, \$current_altitude;
},
rules => [ done      => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
!defined(\$previous_altitudes->[@{\$previous_altitudes} - 1])
},
done      => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
\$previous_altitudes->[@{\$previous_altitudes} - 1] < \$previous_altitudes->[@{\$previous_altitudes} - 2];
},
plateau   => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] == \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{plateau}}, \$previous_altitudes->[@{\$previous_altitudes} - 2], \$previous_altitudes->[@{\$previous_altitudes} - 1];
}
},
upslope   => sub{  my \$state = shift;
my \$previous_altitudes = \$state->machine->{altitude};
if(\$previous_altitudes->[@{\$previous_altitudes} - 1] > \$previous_altitudes->[@{\$previous_altitudes} - 2]){
push @{\$state->machine->{upslope}}, \$previous_altitudes->[@{\$previous_altitudes} - 1];
}
}
],
},
done => {
do => sub { my \$state = shift;
say q/Valley: / . join(q/, /,  @{\$state->machine->{downslope}}, @{\$state->machine->{upslope}});
}
},
);
return \$fsa;
}

sub widest_valley{
my \$rules = widest_valley_rules(@_);
\$rules->start;
\$rules->switch until \$rules->at(q/done/);
my \$graph_viz = \$rules->graph();
}

MAIN:{
widest_valley 1, 5, 5, 2, 8;
widest_valley 2, 6, 8, 5;
widest_valley 2, 1, 2, 1, 3;
}
``````

### Sample Run

``````
\$ perl perl/ch-2.pl
Valley: 5, 5, 2, 8
Valley: 2, 6, 8
Valley: 2, 1, 2
``````

## References

Challenge 202

posted at: 18:39 by: Adam Russell | path: /perl | permanent link to this entry