### Perl Weekly Challenge: Week 260

#### Challenge 1:

Unique Occurrences

You are given an array of integers, `@ints`.

Write a script to return 1 if the number of occurrences of each value in the given array is unique or 0 otherwise.

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

The number 1 occurred 3 times.
The number 2 occurred 2 times.
The number 3 occurred 1 time.

All occurrences are unique, therefore the output is 1.
``````
##### Example 2
``````Input: @ints = (1,2,3)
Output: 0
``````
##### Example 3
``````Input: @ints = (-2,0,1,-2,1,1,0,1,-2,9)
Output: 1
``````

In my Raku solution, the first thing I did was create a hash to store how many times each value was seen.

``````my %count;
``````

Then I did the actual counting.

``````@ints.map({ %count{\$_}++ });
``````

If the total number of values seen is equal to the unique number of values seen, we print 1 otherwise we print 0.

``````say %count.values.elems == %count.values.unique.elems ?? 1 !! 0;
``````

(Full code on Github.)

For the Perl version I once again had to reach into my archive of previous challenges; this time to find a replacement for `.unique()`. With that, it looks pretty similar to the Raku version.

``````my %count;
map { \$count{\$_}++ } @ints;
say scalar values %count == scalar unique([values %count]) ? 1 : 0;
``````

(Full code on Github.)

#### Challenge 2:

Dictionary Rank

You are given a word, `\$word`.

Write a script to compute the dictionary rank of the given word.

##### Example 1
``````Input: \$word = 'CAT'
Output: 3

All possible combinations of the letters:
CAT, CTA, ATC, TCA, ACT, TAC

Arrange them in alphabetical order:
ACT, ATC, CAT, CTA, TAC, TCA

CAT is the 3rd in the list.
Therefore the dictionary rank of CAT is 3.
``````
##### Example 2
``````Input: \$word = 'GOOGLE'
Output: 88
``````
##### Example 3
``````Input: \$word = 'SECRET'
Output: 255
``````

Raku can solve this in one slightly long line.

``````say %(@*ARGS[0].comb.permutations.map({\$_.join}).sort.unique.kv.reverse){@*ARGS[0]} + 1
``````

(Full code on Github.)

Starting from somewhere near the beginning, we get the word from the command line and split it into a list of characters with `.comb()`. Then we find all the permutations of that list with `.permutations()`. We want strings not list so we join all those permutation lists back with `.map()` and `.join()`. These strings are then sorted into dictionary order with `.sort()` and duplicates are filtered out with `.unique()`. At this point, we have a list of strings. `.kv()` converts a list or array into key-value pairs where the value is an element of the list and the key is the index of the element in the list. `.Hash` casts this list of pairs into a hash. But this hash is backwards for our purposes; we want to be able to look up the index based on the word not the other way around so we call `.reverse()` which makes keys values and values keys. I wrapped up this whole statement in `%( ... )`. This treats the key-value list as a hash. Now we can use the standard hash `{}` syntax to look up the index of the word. One more slight problem though; array indexing starts from 0 but according to the spec, the rank should be 1-based. So we have to add 1 to get the final answer.

For perl we need a `unique()` replacement as in Challenge 1 and the `permute()` function I have used in previous challenges.

``````my @permutations;
permute { push @permutations, \@_; } (split //, \$word);
``````

I need an explicit hash to store the dictionary ranks.

``````my %rank;
``````

And then I can populate the hash with my permuted strings. The keys are the strings themselves, and the values are their index in the list of permutations.

``````my \$index = 1;
for my \$perm (sort (unique([map { join q{}, @{\$_} } @permutations]))) {
\$rank{\$perm} = \$index++;
}
``````

Finally, I can look up the rank of the word and print it.

``````say \$rank{\$word};
``````

(Full code on Github.)