# Perl Weekly Challenge 201.

My solutions (task 1 and task 2 ) to the The Weekly Challenge - 201.

``````Submitted by: Mohammad S Anwar
You are given an array of unique numbers.

Write a script to find out all missing numbers in the range 0..\$n where \$n is the
array size.

Example 1
Input: @array = (0,1,3)
Output: 2

The array size i.e. total element count is 3, so the range is 0..3.
The missing number is 2 in the given array.
Example 2
Input: @array = (0,1)
Output: 2

The array size is 2, therefore the range is 0..2.
The missing number is 2.
``````

I make a hash of seen values and filter out unseen ones. This makes a short oneliner:

``````perl -E '@s{@ARGV}=(1)x@ARGV; say join " ", @ARGV, "->", grep {!\$s{\$_}} 0..@ARGV' 0 1 3
perl -E '@s{@ARGV}=(1)x@ARGV; say join " ", @ARGV, "->", grep {!\$s{\$_}} 0..@ARGV' 0 1
``````

Results:

``````0 1 3 -> 2
0 1 -> 2
``````

The full code is essentially the same. I just add a usage message and check the input for unique values.

`````` 1  # Perl weekly challenge 201
2  # Task 1:  Missing Numbers
3  #
5  use v5.36;
6  my %seen;
7  die <<~ "FIN" unless @ARGV;
8      Usage: \$0 N1 [N2...]
9      to find the missing numbers from the sequence N1 N2...
10      FIN
11  @seen{@ARGV}=(1)x@ARGV;
12  die "Expected unique values" unless 0+@ARGV==0+keys %seen;
13  say join " ", @ARGV, "->", grep {!\$seen{\$_}} 0..@ARGV;
``````

Example:

``````./ch-1.pl 0 1 3
./ch-1.pl 0 1
``````

``````Submitted by: Robbie Hatley
You are given an integer, \$n > 0.

Write a script to determine the number of ways of putting \$n pennies in a row of piles of
ascending heights from left to right.

Example
Input: \$n = 5
Output: 7

Since \$n=5, there are 7 ways of stacking 5 pennies in ascending piles:

1 1 1 1 1
1 1 1 2
1 2 2
1 1 3
2 3
1 4
5
``````

I can solve this problem recursively. To make an ascending row of piles with `\$n` pennies with at most `\$m` pennies in each pile (with `\$m≤\$n`), I can make a single rightmost pile of `\$p` pennies with `\$p≤\$m`, and I’m left with `\$n-\$p` pennies to make a row of piles with no more than `\$p` pennies in each (so that the resulting row is ascending). This fits a longish oneliner:

``````perl -MList::Util=sum -E '
say "\$_->", f(\$_, \$_) for @ARGV; sub f(\$n,\$m){return 1 if \$n==0; sum map{f(\$n-\$_,\$_)} 1..(\$m<=\$n?\$m:\$n)}
' 1 2 3 4 5 6
``````

Results:

``````1->1
2->2
3->3
4->5
5->7
6->11
``````

The full code is almost identical. I just add a test, some minimal optimization and memoization to reduce the cost of recursion.

`````` 1  # Perl weekly challenge 201
2  # Task 2:  Penny Piles
3  #
5  use v5.36;
6  use List::Util qw(min sum);
7  use Memoize;
8  memoize "rows";
9  die <<~"FIN" unless @ARGV;
10      Usage: \$0 N1 [N2...]
11      to obtain the number of ascending rows of piles of Ni coins.
12      FIN
13  say "\$_->", rows(\$_, \$_) for @ARGV;
14  sub rows(\$coins,\$max){
15      return 1 if \$coins==0;
16      return sum map{rows(\$coins-\$_,min(\$_, \$coins-\$_))} 1..min(\$coins, \$max)
17  }
``````

Example:

``````./ch-2.pl `seq 6`
``````

Results:

``````1->1
2->2
3->3
4->5
5->7
6->11
``````

Other examples:

``````./ch-2.pl -1 0 100
``````

Results:

``````-1->
0->1
100->190569292
``````
Written on January 23, 2023