by Arne Sommer

# MIS-ing with Raku

 Published 18. March 2023.

This is my response to The Weekly Challenge #208.

## Challenge #208.1: Minimum Index Sum

You are given two arrays of strings.

Write a script to find out all common strings in the given two arrays with minimum index sum. If no common strings found returns an empty list.

Example 1: ```Input: @list1 = ("Perl", "Raku", "Love") @list2 = ("Raku", "Perl", "Hate") Output: ("Perl", "Raku") There are two common strings "Perl" and "Raku". Index sum of "Perl": 0 + 1 = 1 Index sum of "Raku": 1 + 0 = 1 ``` Example 2: ```Input: @list1 = ("A", "B", "C") @list2 = ("D", "E", "F") Output: () No common string found, so no result. ``` Example 3: ```Input: @list1 = ("A", "B", "C") @list2 = ("C", "A", "B") Output: ("A") There are three common strings "A", "B" and "C". Index sum of "A": 0 + 1 = 1 Index sum of "B": 1 + 2 = 3 Index sum of "C": 2 + 0 = 2 ```

File: File: minimum-index-sum ```#! /usr/bin/env raku unit sub MAIN (\$list1 = "Perl Raku Love", \$list2 = "Raku Perl Hate", #  :v(\$verbose)); my @list1 = \$list1.words; #  my @list2 = \$list2.words; # [a2] die "Repetitions in list1" if @list1.elems != @list1.unique.elems; #  die "Repetitions in list2" if @list2.elems != @list2.unique.elems; # [3a] my \$mis = Inf; #  my @common; #  for ^@list1.elems -> \$i #  { next unless @list1[\$i] eq any(@list2); #  for ^@list2.elems -> \$j #  { if @list1[\$i] eq @list2[\$j] #  { my \$sum = \$i + \$j; #  say ": Index sum of \"@list1[\$i]\": \$i + \$j = \$sum" if \$verbose; next if \$sum > \$mis; #  @common = () if \$sum < \$mis; #  \$mis = \$sum; #  @common.push: @list1[\$i]; #  } } } say @common.elems #  ?? "(" ~ @common.map({ "\"\$_\"" }).join(", ") ~ ")" # [15a] !! "()"; # [15b] ```

 The list of words as two space separated quoted strings, with default values.

 Get the words.

 The challenge does not tell us how to cope with duplicates in the lists themselves, but I have chosen to make that illegal (as the index for a duplicate word would give more than one answer. I enforce this by removing duplucates, and compare the array lengths.

 We are looking for the «minimum index sum», i.e. minimizing this value.

 The common strings with the currently «minimum index sum» will end up here.

 Iterate over the indices of the words in the first list. The caret (`^`) means «upto, but not including».

 Skip the inner loop (over the second list of words), if the `any` junction tells us that we do not have a match (i.e. no common words).

See docs.raku.org/routine/any for more information about the `any` Junction.

 Iterate over the indices of the words in the second list.

 Are the two words equal?

 Compute the index sum.

 Disregard this pair (of words, or indices) if the new sum is higher than the «minimum index sum».

 Empty the lits of empty strings if the new sum is lower than the old one, as we have found a new value for «minimum index sum».

 Update the «minimum index sum». Note that this will also be done if the two variables have the same value.

 Add the string (taken from the first list) to the list of common strings.

 Do we have a result (common strings). If so, print them with the required formating apllied [15a]. If not, print an ampty set of parens [15b].

Running it:

```\$ ./minimum-index-sum ("Perl", "Raku") \$ ./minimum-index-sum "A B C" "D E F" () \$ ./minimum-index-sum "A B C" "C A B" ("A") ```

Looking good.

With verbose mode:

```\$ ./minimum-index-sum -v : Index sum of "Perl": 0 + 1 = 1 : Index sum of "Raku": 1 + 0 = 1 ("Perl", "Raku") \$ ./minimum-index-sum -v "A B C" "D E F" () \$ ./minimum-index-sum -v "A B C" "C A B" : Index sum of "A": 0 + 1 = 1 : Index sum of "B": 1 + 2 = 3 : Index sum of "C": 2 + 0 = 2 ("A") ```

## Challenge #208.2: Duplicate and Missing

You are given an array of integers in sequence with one missing and one duplicate.

Write a script to find the duplicate and missing integer in the given array. Return -1 if none found.

For the sake of this task, let us assume the array contains no more than one duplicate and missing.

Example 1: ```Input: @nums = (1,2,2,4) Output: (2,3) Duplicate is 2 and Missing is 3. ``` Example 2: ```Input: @nums = (1,2,3,4) Output: -1 No duplicate and missing found. ``` Example 3: ```Input: @nums = (1,2,3,3) Output: (3,4) Duplicate is 3 and Missing is 4. ```

File: duplicate-and-missing ```! /usr/bin/env raku unit sub MAIN (\$nums = "1 2 2 4", :v(\$verbose)); #  my @nums = \$nums.words; #  die "Not increasing values" unless [<=] @nums; #  my \$duplicate = @nums.repeated; #  say ": Duplicate: \$duplicate" if \$verbose; my \$current = @nums.shift; #  while (@nums.elems) #  { if @nums != \$current + 1 #  { say ": Missing: { \$current + 1 }" if \$verbose; say "(\$duplicate, { \$current + 1 })"; #  exit; #  } \$current = @nums.shift; #  } say "-1"; #  ```

 A space separated quoted string (as in the first program) with the values, so that we can have a default value.

 Get the words.

 Using the Reduction Metaoperator `[]` to enforce that all the values are lower or equal (the `<=` operator) to the next value.

See docs.raku.org/language/operators#Reduction_metaoperators for more information about the Reduction Metaoperator `[]`.

 The `repeated` methods gives us a list of repeated values, in this case just one element according to the challenge - and thus the duplicate we are looking for.

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

 Get the first value.

 As long as there are more elements.

 The first element in the remaining list should have the value after (+1) the current value. We have found the missing value if it is not.

 Print the duplicate value (from ) and the missing value.

 Exit.

 Get ready for the next iteration of the loop (in ).

 No match (i.e. not reached `exit` above); say so.

Running it:

```\$ ./duplicate-and-missing "1 2 2 4" (2, 3) \$ ./duplicate-and-missing "1 2 3 4" -1 \$ ./duplicate-and-missing "1 2 3 3" (3, 4) ```

Looking good.

With verbose mode, even though it does not really provide any new insights:

```\$ ./duplicate-and-missing -v "1 2 2 4" : Duplicate: 2 : Missing: 3 (2, 3) \$ ./duplicate-and-missing -v "1 2 3 4" : Duplicate: -1 \$ ./duplicate-and-missing -v "1 2 3 3" : Duplicate: 3 : Missing: 4 (3, 4) ```

And that's it.