# Perl Challenge 91: Jumping Numbers and Counting Numbers

Another week blogging a Perl Weekly Challenge!

### TASK #1 › Count Number

Submitted by: Mohammad S Anwar

You are given a positive number`$N`

.Write a script to count number and display as you read it.

Given the 80s Yes album *90125*, we’d go *“one zero, one one, one two, one five, one nine”*, or `1011121519`

.

Which *can* get ambiguous if you start counting large numbers, because if there were 101112 `1`

s and 51 `9`

s, it would give the same output. But eh.

I didn’t do cleanup, because even if this was a negative number, we don’t have to worry about anything `\D`

, so I just go through `0..9`

, get the number of instances and add to the output.

Notice how the examples don’t start out with `00`

to indicate a lack of zeroes? `if`

or `grep`

to the rescue! I wrote a solution that used `for`

and `if`

and another that uses `map`

and `grep`

.

But we want to count the number of times a character is used, and splitting the string into an array is wasteful of memory. So, how do you get the count of the times a character is used? We’ll switch prog rock bands and go to Rush’s classic *2112*. A first stop is `$x = $N =~ /2/g`

, but that’ll just say *“I found it!”*, or `1`

in boolean parlance. We’ll grab the `2`

with `$x = $N =~ /(2)/`

, but that’s just proving it was a 2, which we’re already sure of. We want every `2`

, so we run `$x = $N =~ /(2)/g`

and get `22`

, but we want `2`

meaning we have two `2`

s.

The solution is as follows `$x = () = $N =~ /(2)/`

, which forces a list context and gives us the size of the list. `=()=`

is sometimes called the **goatse** operator, and if you don’t know why, don’t look it up.

#### Let’s See The Code

```
#!/usr/bin/env perl
use strict;
use warnings;
use feature qw{ say signatures state };
no warnings qw{ experimental };
my @examples = qw{1122234 2333445 12345 90125 };
for my $example (@examples) {
my $output = count_number($example);
my $o2 = count_number2($example);
say ' input: ' . $example;
say ' output: ' . $output;
say 'output2: ' . $o2;
say '';
}
sub count_number( $input ) {
my $output = '';
for my $i ( 0 .. 9 ) {
my $x = () = $input =~ /($i)/gmx;
$output .= $x . $i if $x;
}
return $output;
}
sub count_number2( $input ) {
return join '', map {
my $x = () = $input =~ /($_)/g;
$x . $_; }
grep { $input =~ /$_/ } 0 .. 9;
}
```

### TASK #2 › Jump Game

Submitted by: Mohammad S Anwar

You are given an array of positive numbers`@N`

, where value at each index determines how far you are allowed to jump further.Write a script to decide if you can jump to the last index. Print

1if you are able to reach the last index otherwise0.

We’ll run through the two examples, first with `1, 2, 1, 2`

:

- index is
`0`

and`$n[0]`

is`1`

, so we add`1`

to the index - index is
`1`

and`$n[1]`

is`1`

, so we add`2`

to the index - index is
`3`

and that’s the last index —`0,1,2,3`

— and we have a*win!*

In contrast, with `2, 1, 1, 0, 2`

:

- index is
`0`

and`$n[0]`

is`2`

, so we add`2`

to the index - index is
`2`

and`$n[2]`

is`1`

, so we add`1`

to the index - index is
`3`

and`$n[3]`

is`0`

, so we add`0`

to the index - index is
`3`

and`$n[3]`

is`0`

, so we add`0`

to the index - I think we’ve seen this one before…

We’ve hit one failure point: we can’t move the index to progress. (It says *array of positive numbers*, and zero is neither positive nor negative, but I’ll work with it.) The easier failure point is when we’ve gone past the end of the array. Going negative would introduce `$n[-1]`

, which is simply the end of the index, but we’re *sure* that *array of positive numbers* excludes negative numbers, so that won’t happen. We’d have to add a case to handle that if so, but otherwise, it’s simply

- if this is the last index, win
- if this is beyond the last index, lose
- if the current value is zero, lose
- if this is below the last index, add the current value to the current index and go again

*(My first pass had code to extract the last index to test against, but I decided to rewrite without that value. It may be slightly clearer, but I like it better this way.)*

#### Let’s See The Code

```
sub jump_game( @n ) {
say join ' ', @n;
my $i = 0;
while (1) {
if ( !defined $n[$i] ) { last }
if ( $n[$i] == 0 ) { last }
if ( defined $n[$i] && !defined $n[ $i + 1 ] ) { return 1 }
$i += $n[$i];
}
return 0;
}
```

```
1 2 1 2
1
2 1 1 0 2
0
1 9 9 2
0
```