# Perl Weekly Challenge 222.

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

``````Submitted by: Mohammad S Anwar
You are given a list of positive integers, @ints.

Write a script to find the total matching members after sorting the list increasing order.

Example 1
Input: @ints = (1, 1, 4, 2, 1, 3)
Output: 3

Original list: (1, 1, 4, 2, 1, 2)
Sorted list  : (1, 1, 1, 2, 3, 4)

Compare the two lists, we found 3 matching members (1, 1, 2).
Example 2
Input: @ints = (5, 1, 2, 3, 4)
Output: 0

Original list: (5, 1, 2, 3, 4)
Sorted list  : (1, 2, 3, 4, 5)

Compare the two lists, we found 0 matching members.
Example 3
Input: @ints = (1, 2, 3, 4, 5)
Output: 5

Original list: (1, 2, 3, 4, 5)
Sorted list  : (1, 2, 3, 4, 5)

Compare the two lists, we found 5 matching members.
``````

We can simply follow instructions: sort the input array, filter its indices by comparing the sorted and unsorted versions and count them. This yields a short oneliner:

``````perl -E '@s=sort {\$a<=>\$b} @i=@ARGV; @o=grep {\$s[\$_]==\$i[\$_]}0..@i-1; say "@i -> ", 0+@o' 1 1 4 2 1 3
``````

Results:

``````1 1 4 2 1 3 -> 3
``````

Other examples:

``````perl -E '@s=sort {\$a<=>\$b} @i=@ARGV; @o=grep {\$s[\$_]==\$i[\$_]}0..@i-1; say "@i -> ", 0+@o' 5 1 2 3 4
perl -E '@s=sort {\$a<=>\$b} @i=@ARGV; @o=grep {\$s[\$_]==\$i[\$_]}0..@i-1; say "@i -> ", 0+@o' 1 2 3 4 5
``````

Results:

``````5 1 2 3 4 -> 0
1 2 3 4 5 -> 5
``````

The full code is almost identical.

`````` 1  # Perl weekly challenge 222
2  # Task 1:  Matching Members
3  #
5  use v5.36;
6  die <<~"FIN" unless @ARGV;
7      Usage: \$0 N1 [N2....]
8      to count how many members of the list N1 N2... match the members of the
9      corresponding sorted list
10      FIN
11  my @sorted=sort {\$a<=>\$b} my @in=@ARGV;
12  my @out=grep {\$sorted[\$_]==\$in[\$_]} 0..@in-1;
13  say "@in -> ", 0+@out;
``````

Examples:

``````./ch-1.pl 1 1 4 2 1 3
./ch-1.pl 5 1 2 3 4
./ch-1.pl 1 2 3 4 5
``````

Results:

``````1 1 4 2 1 3 -> 3
5 1 2 3 4 -> 0
1 2 3 4 5 -> 5
``````

``````Submitted by: Mohammad S Anwar
You are given an array of positive integers, @ints.

Write a script to find the last member if found otherwise return 0.
Each turn pick 2 biggest members (x, y) then decide based on the
following conditions, continue this until you are left with 1 member or none.

a. if x == y then remove both members

b. if x != y then remove both members and add new member (y-x)

Example 1:
Input: @ints = (2, 7, 4, 1, 8, 1)
Output: 1

Step 1: pick 7 and 8, we remove both and add new member 1 => (2, 4, 1, 1, 1).
Step 2: pick 2 and 4, we remove both and add new member 2 => (2, 1, 1, 1).
Step 3: pick 2 and 1, we remove both and add new member 1 => (1, 1, 1).
Step 4: pick 1 and 1, we remove both => (1).
Example 2:
Input: @ints = (1)
Output: 1
Example 3:
Input: @ints = (1, 1)
Output: 0

Step 1: pick 1 and 1, we remove both and we left with none.
``````

To solve this challenge, I first sort the numbers in descending order, chose the first two, subtract them, splice at appropriate position if positive (doing a dumb search) and repeat until only one or zero numbers remain. This fits a two-liner:

``````perl -MList::Util=first -E '
@l=sort {\$b<=>\$a}@ARGV; while(@l>1){(\$x, \$y)=splice @l,0,2; next unless \$x-=\$y;
\$i=(first {\$l[\$_]<=\$x} 0..@l-1)//@l+1; splice @l,\$i,0,\$x;} say "@ARGV->", \$l[0]//0
' 2 7 4 1 8 1
``````

Results:

``````2 7 4 1 8 1->1
``````

Other examples:

``````perl -MList::Util=first -E '
@l=sort {\$b<=>\$a}@ARGV; while(@l>1){(\$x, \$y)=splice @l,0,2; next unless \$x-=\$y;
\$i=(first {\$l[\$_]<=\$x} 0..@l-1)//@l+1; splice @l,\$i,0,\$x;} say "@ARGV->", \$l[0]//0
' 1
perl -MList::Util=first -E '
@l=sort {\$b<=>\$a}@ARGV; while(@l>1){(\$x, \$y)=splice @l,0,2; next unless \$x-=\$y;
\$i=(first {\$l[\$_]<=\$x} 0..@l-1)//@l+1; splice @l,\$i,0,\$x;} say "@ARGV->", \$l[0]//0
' 1 1
perl -MList::Util=first -E '
@l=sort {\$b<=>\$a}@ARGV; while(@l>1){(\$x, \$y)=splice @l,0,2; next unless \$x-=\$y;
\$i=(first {\$l[\$_]<=\$x} 0..@l-1)//@l+1; splice @l,\$i,0,\$x;} say "@ARGV->", \$l[0]//0
' 8 7 2
``````

Results:

``````1->1
1 1->0
8 7 2->1
``````

The full code is similar:

`````` 1  # Perl weekly challenge 222
2  # Task 2:  Last Member
3  #
5  use v5.36;
6  use List::Util qw(first all);
7  die <<~"FIN" unless @ARGV;
8      Usage: \$0 N1 [N2...]
9      to find last member from list N1 N2...
10      after iteratively eliminating equal pairs
11      and replacing unequal pairs by their differences,
12      starting from the highest values.
13      FIN
14  # If non-positive are allowed, the result 0 becomes ambiguous.
15  # Not necessary to check for integers, though.
16  die "Expected positive numbers" unless all {\$_>0} @ARGV;
17  my @list = sort {\$b <=> \$a} @ARGV;
18  while(@list>1){
19      my (\$x, \$y)=splice @list, 0, 2; # Remove largest two elements.
20      next unless \$x-=\$y;             # Were they equal?
21      my \$i=(first {\$list[\$_]<=\$x} 0..@list - 1) // @list + 1; # No. Fin where to insert difference
22      splice @list, \$i, 0, \$x;
23  }
24  say "@ARGV->", \$list[0]//0; # Print single remaining element or 0 if none.
``````

Examples:

``````./ch-2.pl 2 7 4 1 8 1
./ch-2.pl 1
./ch-2.pl 1 1
``````

Results:

``````2 7 4 1 8 1->1
1->1
1 1->0
``````
Written on June 19, 2023