by Arne Sommer

# Unique Rank with Raku

[280] Published 14. March 2024.

This is my response to The Weekly Challenge #260.

## Challenge #260.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 ```
File: unique-occurences-bag ```#! /usr/bin/env raku unit sub MAIN (*@ints where all(@ints) ~~ Int && @ints.elems > 0, # [1] :v(:\$verbose)); my @freq = @ints.Bag.values; # [2] say ": Frequencies: @freq[]" if \$verbose; say @freq.repeated ?? 0 !! 1; # [3] ```

[1] All the arguments, of which there must be at least one, must be integers.

[2] Turn the array into a `Bag`, a hash like structure where the original data are the keys and the original frequency are the values. Then we use `values` to get a list of frequencies.

See docs.raku.org/routine/Bag for more information about `Bag`.

See docs.raku.org/routine/values for more information about `values`.

[3] `repeated` will give us a list of values that occur more than once. Thus we print 1 if all the occurrences are unique and 0 otherwise.

See docs.raku.org/routine/repeated for more information about `repeated`.

Running it:

```\$ ./unique-occurences 1 2 2 1 1 3 1 \$ ./unique-occurences 1 2 3 0 \$ ./unique-occurences -- -2 0 1 -2 1 1 0 1 -2 9 1 ```

The `--` is there to halt the parsing of command line options, as `-2` will be treated as an option otherwise.

Looking good.

With verbose mode:

```\$ ./unique-occurences -v 1 2 2 1 1 3 : Frequencies: 1 3 2 1 \$ ./unique-occurences -v 1 2 3 : Frequencies: 1 1 1 0 \$ ./unique-occurences -v -- -2 0 1 -2 1 1 0 1 -2 9 : Frequencies: 4 3 2 1 1 ```

## Challenge #260.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 ```
File: dictionary-rank ```#! /usr/bin/env raku unit sub MAIN (\$word where \$word.chars > 0, :v(:\$verbose)); # [1] my \$perm = \$word.comb.sort.permutations>>.join.unique; # [2] say ": Permutations: \$perm[]" if \$verbose; my \$index = (\$perm.grep: \$word, :k).first; # [3] say \$index +1; # [4] ```

[1] Ensure at least one character in the word.

[2] Using `permutations` on an array of characters gives us all the ways we can combine them. If we sort the characters, then the output will also be sorted. The result so far is an array of arrays. We apply `>>.join` the inner arrays, so that we end ut with words. The `unique` will get rid of duplicates, which we get if we have repeated letters in the input string.

[3] Look for the given word in the array of permutations, using `grep`. Adding the `:k` (keys) adverb gives us the keys instead of the values themselves, and the key in an array context is the index. This is an array, with one element, so we use `first` to get it.

See docs.raku.org/routine/first for more information about `first`.

[4] The rank starts with 1 as the first one, so we add 1 to the zero based index.

Running it:

```\$ ./dictionary-rank CAT 3 \$ ./dictionary-rank GOOGLE 88 \$ ./dictionary-rank SECRET 255 ```

Looking good.

With verbose mode:

```./dictionary-rank -v CAT : Permutations: ACT ATC CAT CTA TAC TCA 3 \$ ./dictionary-rank -v GOOGLE : Permutations: EGGLOO EGGOLO EGGOOL EGLGOO ... OOGLGE OOLEGG OOLGEG OOLGGE 88 \$ ./dictionary-rank -v SECRET : Permutations: CEERST CEERTS CEESRT CEESTR ... TSEREC TSRCEE TSRECE TSREEC ```

I have abbreviated the verbose output for the second and third example.

And that's it.