### Perl Weekly Challenge: Week 228

#### Challenge 1:

Unique Sum

You are given an array of integers.

Write a script to find out the sum of unique elements in the given array.

##### Example 1
``````Input: @int = (2, 1, 3, 2)
Output: 4

In the given array we have 2 unique elements (1, 3).
``````
##### Example 2
``````Input: @int = (1, 1, 1, 1)
Output: 0

In the given array no unique element found.
``````
##### Example 3
``````Input: @int = (2, 1, 3, 4)
Output: 10

In the given array every element is unique.
``````

Hooray! we can do a Raku one-liner again. What the code below does is to use the `.classify()` method on the list of command line arguments. This produces a hash where the keys are values found in the list and the values (bit of overlapping terminology there) are the number of times that value occured. We `.grep()` through that to find the keys which only occurred once. Why not use the more appropriate-sounding `.unique()` method? Because that will include all values that occured but only count them once. So e.g. calling it on example 1 would give us `1, 2, 3` not `1, 3` which is what we want. We now have a list of pairs. We use `.map({.key})` to get the first member of each pair. (I suspect there is a more succint way of doing this but I couldn't think of it.) `.sum()` totals the resulting list and `.say()` prints that total. list and finally

``````@*ARGS.classify({\$_}).grep({.value==1}).map({.key}).sum.say
``````

(Full code on Github.)

Perl needs some help as usual. The function `classifyUnique()` actually combines the `.classify()`, `.grep()` and `.map()` steps of the Raku version.

``````sub classifyUnique {
my %count;

for my \$n (@_) {
\$count{\$n}++;
}
return grep { \$count{\$_} == 1; } keys %count;
}
``````

`sum()` emulates the Raku method of the same name.

``````sub sum {
my \$total = 0;

for my \$elem (@_) {
\$total += \$elem;
}

return \$total;
}
``````

With these helpers, the core of the Perl version also becomes a one-liner.

``````say sum(classifyUnique(@ARGV));
``````

(Full code on Github.)

#### Challenge 2:

Empty Array

You are given an array of integers in which all elements are unique.

Write a script to perform the following operations until the array is empty and return the total count of operations.

``````If the first element is the smallest then remove it otherwise move it to the end.
``````
##### Example 1
``````Input: @int = (3, 4, 2)
Ouput: 5

Operation 1: move 3 to the end: (4, 2, 3)
Operation 2: move 4 to the end: (2, 3, 4)
Operation 3: remove element 2: (3, 4)
Operation 4: remove element 3: (4)
Operation 5: remove element 4: ()
``````
##### Example 2
``````Input: @int = (1, 2, 3)
Ouput: 3

Operation 1: remove element 1: (2, 3)
Operation 2: remove element 2: (3)
Operation 3: remove element 3: ()
``````

This one was very easy. Here is the Raku version.

We declare a variable to count the operations.

``````my \$ops = 0;
``````

While me have elements left...

``````while @ints.elems {
``````

If the first element is equal to the smallest (found with `.min()`.) ...

``````    if @ints[0] == @ints.min {
``````

...It is removed from the list...

``````        @ints.shift;
``````

...otherwise it is removed from the list and replaced at the end of the list.

``````    } else {
@ints.push(@ints.shift);
}
``````

In either case an operation has been performed so the counter is incremented.

``````    \$ops++;
}
``````

When there are no elements left, the number of operations is printed out.

``````say \$ops;
``````

(Full code on Github.)

The Perl is mostly the same.

``````my \$ops = 0;

while (scalar @ints) {
``````

Except we don't have `.min()` so we have to provide our own `min()` function.

``````    if (\$ints[0] == min(@ints)) {
shift @ints;
} else {
push @ints, shift @ints;
}
\$ops++;
}

say \$ops;
``````

`min()` looks like this. All it does is sort the input array in ascending numerical order and returns the first element which will be the smallest.

``````sub min {
return ( sort { \$a <=> \$b } @_)[0];
}
``````

(Full code on Github.)