# PERL WEEKLY CHALLENGE – 052

This is my 22th week participating into the weekly challenge.

### Stepping Numbers

Write a script to accept two numbers between 100 and 999. It should then print all Stepping Numbers between them.

A number is called a stepping number if the adjacent digits have a difference of 1. For example, 456 is a stepping number

For this task I just brute forced and checked that each number is a stepping number. I did some basic validation and checked that the number is a stepping number by looping through each digit and comparing it to the digit before it.

#### Perl 5 solution

``````#!/usr/bin/perl
# Test: ./ch-1.pl 100 999
use strict;
use warnings;
use feature qw /say/;

my \$start = \$ARGV[0];
my \$end   = \$ARGV[1];

# Some input validation
unless (\$start && \$end && \$end > \$start &&
\$start >= 100 && \$start < 1000 &&
\$end   >= 100 && \$end < 1000) {

say "Usage: 100 999";
exit;
}

# Check each digit if it's stepping
for my \$i (\$start .. \$end) {
my \$is_stepping = 1;
my \$prev_digit;

my @digits = split ('', \$i);
for my \$digit (@digits) {
\$is_stepping = 0 if
( defined(\$prev_digit) &&
( \$prev_digit != \$digit + 1 &&
\$prev_digit != \$digit - 1) );
\$prev_digit = \$digit;
}
say \$i if (\$is_stepping);
}
``````

Output

``````101
121
123
210
212
232
234
321
323
343
345
432
434
454
456
543
545
565
567
654
656
676
678
765
767
787
789
876
878
898
987
989``````

#### Raku solution

``````#!/usr/bin/perl
# Test: ./ch-6.p6

multi MAIN { MAIN(100, 999) };
multi MAIN(Int \$start, Int \$end) {
die "End smaller than start" if \$end < \$start;
.say for (\$start .. \$end).grep({is-stepping(\$_)});
}

sub is-stepping(\$num) {
my \$is_stepping = True;
my \$prev_digit;

for (\$num.comb) -> \$i {
\$is_stepping = False
if (\$prev_digit.defined &&
\$prev_digit != \$i + 1 &&
\$prev_digit != \$i - 1 );

\$prev_digit = \$i;
}

return \$is_stepping;
}
``````

Output

``````101
121
123
210
212
232
234
321
323
343
345
432
434
454
456
543
545
565
567
654
656
676
678
765
767
787
789
876
878
898
987
989``````

### Lucky Winner

Suppose there are following coins arranged on a table in a line in random order.

£1, 50p, 1p, 10p, 5p, 20p, £2, 2p

Suppose you are playing against the computer. Player can only pick one coin at a time from either ends. Find out the lucky winner, who has the larger amounts in total?

So I just modeled this as two players grabbing the highest coin. This results is player 2 winning and this can be tested with: `./ch-2.pl` or
`perl6 ./ch2.p6`

This isn’t the optimal strategy because they key strategy to winning is trying to get the £2 coin and the person who goes first should always gets that coin (as the coin is positioned at the odd parity). This can be done if the first player always picks the left-most coin.

The lucky winner is always the first player, if played at the optimal strategy as player #1 will always get the £1 and £2 coins.

You can test that with: `./ch2-pl --optimal` or
perl6 `./ch2-p6 --optimal`

#### Perl 5 solution

``````#!/usr/bin/perl
# Test: ./ch-2.pl --optimal
use strict;
use warnings;
use Getopt::Long;
use feature qw /say/;

# Optimal flag
my \$optimal = 0;
GetOptions ('optimal' => \\$optimal);

# Some initialization variables
my @coins = (100, 50, 1, 10, 5, 20, 200, 2);
my \$players = 2;
my \$player_turn = 0;
my @totals = map { 0 } 1 .. \$players;

# Play the game
while (scalar(@coins) > 0) {
if ( (\$optimal && \$player_turn == 0) ||
\$coins[0] > \$coins[-1] ) {
\$totals[\$player_turn] += shift @coins;
} else {
\$totals[\$player_turn] += pop @coins;
}

# Next turn
\$player_turn = (\$player_turn + 1) % \$players;
}

# Display the scores
for my \$i (1..\$players) {
say "Player \$i total: " . \$totals[\$i - 1] . 'p';
}
``````

Output (optimal)

``````Player 1 total: 306p
Player 2 total: 82p``````

Output (player picks highest coin)

``````Player 1 total: 132p
Player 2 total: 256p``````

#### Raku solution

``````# Test: perl6 ch-2.p6
use v6.d;

sub MAIN(Bool :\$optimal = False) {
# Some initialization variables
my @coins = (100, 50, 1, 10, 5, 20, 200, 2);
my \$players = 2;
my \$player_turn = 0;
my @totals = map { 0 }, 1 .. \$players;

# Play the game
while (@coins.elems > 0) {
if ( (\$optimal && \$player_turn == 0) ||
@coins[0] > @coins[*-1] ) {
@totals[\$player_turn] += @coins.shift;
} else {
@totals[\$player_turn] += @coins.pop;
}

# Next turn
\$player_turn = (\$player_turn + 1) % \$players;
}

for (1..\$players) -> \$i {
say "Player \$i total: " ~ @totals[\$i - 1] ~ 'p';
}
}
``````

Output (optimal)

``````Player 1 total: 306p
Player 2 total: 82p``````

Output (player picks highest coin)

``````Player 1 total: 132p
Player 2 total: 256p``````