by Arne Sommer

# Chowla Squared with Raku and Perl

 Published 25. April 2021.

This is my response to the Perl Weekly Challenge #109.

## Challenge #109.1: Chowla Numbers

Write a script to generate first 20 `Chowla Numbers`, named after, Sarvadaman D. S. Chowla, a London born Indian American mathematician. It is defined as: ```C(n) = sum of divisors of n except 1 and n ``` NOTE: Updated the above definition as suggested by Abigail [2021/04/19 18:40].

Output: ```0, 0, 0, 2, 0, 5, 0, 6, 3, 7, 0, 15, 0, 9, 8, 14, 0, 20, 0, 21 ```

This is yet another situation where `gather`/`take` is the obvious choice to set up the sequence.

The procedure giving divisors has been copied from my Centenary Sequences with Raku Part 5 - Divisors and Factors article.

File: chowla-numbers ```#! /usr/bin/env raku unit sub MAIN (\$limit = 20, :v(:\$verbose)); my \$chowla := gather { my \$index = 1; loop { my @divisors = divisors(\$index, :not-self, :not-one); #  say "\$index with divisors: { @divisors.join(", ") }" if \$verbose; take @divisors.sum; #  \$index++; } } say \$chowla[^\$limit].join(", "); #  sub divisors (\$number, :\$not-self, :\$not-one) { my @divisors; for (\$not-one ?? 2 !! 1) .. \$number/2 -> \$candidate { @divisors.push: \$candidate if \$number %% \$candidate; } @divisors.push: \$number unless \$not-self; return @divisors; } ```

 Get the diviors for the number n.

 Return the sum.

 Print the required number of values from the sequence.

Running it:

```\$ ./chowla-numbers 0, 0, 0, 2, 0, 5, 0, 6, 3, 7, 0, 15, 0, 9, 8, 14, 0, 20, 0, 21 \$ ./chowla-numbers 25 0, 0, 0, 2, 0, 5, 0, 6, 3, 7, 0, 15, 0, 9, 8, 14, 0, 20, 0, 21, 10, 13, 0, \ 35, 5 \$ ./chowla-numbers 5 0, 0, 0, 2, 0 ```

### A Perl Version

This is straight forward translation of the Raku version. Note that «gather/take» can be replaced with a simple loop, just as I did last week.

File: chowla-numbers-perl ```#! /usr/bin/env perl use strict; use warnings; use feature 'say'; use feature 'signatures'; use List::Util 'sum'; no warnings "experimental::signatures"; my \$limit = \$ARGV // 20; my @chowla; for my \$index (1 .. \$limit) { my @divisors = divisors(\$index, 1, 1); push(@chowla, (sum(@divisors) // 0)); } say join(", ", @chowla); sub divisors (\$number, \$not_self, \$not_one) { my @divisors; for my \$candidate ( (\$not_one ? 2 : 1) .. \$number/2) { push(@divisors, \$candidate) unless \$number % \$candidate; } push(@divisors, \$number) unless \$not_self; return @divisors; } ```

Running it gives the same result as the Raku version:

```\$ ./chowla-numbers-perl 0, 0, 0, 2, 0, 5, 0, 6, 3, 7, 0, 15, 0, 9, 8, 14, 0, 20, 0, 21 ```

## Challenge #109.2: Four Squares Puzzle

You are given four squares as below with numbers named a,b,c,d,e,f,g.

``` (1) (3) ╔══════════════╗ ╔══════════════╗ ║ ║ ║ ║ ║ a ║ ║ e ║ ║ ║ (2) ║ ║ (4) ║ ┌───╫──────╫───┐ ┌───╫─────────┐ ║ │ ║ ║ │ │ ║ │ ║ │ b ║ ║ d │ │ f ║ │ ║ │ ║ ║ │ │ ║ │ ║ │ ║ ║ │ │ ║ │ ╚══════════╪═══╝ ╚═══╪══════╪═══╝ │ │ c │ │ g │ │ │ │ │ │ │ │ │ └──────────────┘ └─────────────┘ ``` Write a script to place the given unique numbers in the square box so that sum of numbers in each box is the same.

Example: ```Input: 1,2,3,4,5,6,7 Output: a = 6 b = 4 c = 1 d = 5 e = 2 f = 3 g = 7 Box 1: a + b = 6 + 4 = 10 Box 2: b + c + d = 4 + 1 + 5 = 10 Box 3: d + e + f = 5 + 2 + 3 = 10 Box 4: f + g = 3 + 7 = 10 ```

We have four equations (shown as box 1, box 2, box 3, and box 4). The four sums must be equal for us to get a solution. The actual right hand value does not matter.

No solutions at all is a possibility. Note that if we have one solution, we have at least one more as we can flip the squares horizontally (giving the order 4, 3, 2 and 1).

File: four-squares-puzzle ```#! /usr/bin/env raku unit sub MAIN (*@values where @values.elems ==7 && all(@values) ~~ Numeric, #  :s(:\$short), #  :a(:\$all) = \$short); #  for @values.permutations -> @perm #  { if check-values(@perm) #  { if \$short #  { say "a=@perm, b=@perm, c=@perm, d=@perm, e=@perm," ~ "f=@perm, g=@perm"; } else { my (\$a, \$b, \$c, \$d, \$e, \$f, \$g); #  say "a = { \$a = @perm }"; say "b = { \$b = @perm }"; say "c = { \$c = @perm }"; say "d = { \$d = @perm }"; say "e = { \$e = @perm }"; say "f = { \$f = @perm }"; say "g = { \$g = @perm }"; say ""; say "Box 1: a + b = \$a + \$b = { \$a + \$b }"; say "Box 2: b + c + d = \$b + \$c + \$d = { \$b + \$c + \$d }"; say "Box 3: d + e + f = \$d + \$e + \$f = { \$d + \$e + \$f }"; say "Box 4: f + g = \$f + \$g = { \$f + \$g }"; say "" if \$all; #  } last unless \$all; #  } } sub check-values (@values) # [5a] { my (\$a, \$b, \$c, \$d, \$e, \$f, \$g) = @values; #  return \$a + \$b == \$b + \$c + \$d == \$d + \$e + \$f == \$f + \$g; # [6a] } ```

 Get the values in a single array (a so called «slurpt array»; given with the leading `*`.

 Use «short mode» to get a single line for each match. This enables «all mode» as well.

 We are done when we have found one match, unless «all mode» is used.

 The `permutations` method gives us the list in every possible sorted order, which is exactly what we need for the equations in .

 Do we have a match?.

 Note the assignemnt to individual variables, as that makes the code more readable than using offsets. Return `True` if the equations in [6a] are good.

 In «short mode», print a single line only for the match.

 Nicely named variables.

 Assign and print in one go.

 Quit after the first match, unless asked to do them all.

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

Running it:

```\$ ./four-squares-puzzle 1 2 3 4 5 6 7 a = 3 b = 7 c = 2 d = 1 e = 5 f = 4 g = 6 Box 1: a + b = 3 + 7 = 10 Box 2: b + c + d = 7 + 2 + 1 = 10 Box 3: c + d + e = 1 + 5 + 4 = 10 Box 4: f + g = 4 + 6 = 10 ```

We did not get the same result as given in the challenge, but it is valid.

Let us try wth «all mode»:

```\$ ./four-squares-puzzle -a 1 2 3 4 5 6 7 a = 3 b = 7 c = 2 d = 1 e = 5 f = 4 g = 6 Box 1: a + b = 3 + 7 = 10 Box 2: b + c + d = 7 + 2 + 1 = 10 Box 3: d + e + f = 1 + 5 + 4 = 10 Box 4: f + g = 4 + 6 = 10 a = 4 b = 5 c = 3 d = 1 e = 6 f = 2 g = 7 Box 1: a + b = 4 + 5 = 9 Box 2: b + c + d = 5 + 3 + 1 = 9 Box 3: d + e + f = 1 + 6 + 2 = 9 Box 4: f + g = 2 + 7 = 9 a = 4 b = 7 c = 1 d = 3 e = 2 f = 6 g = 5 Box 1: a + b = 4 + 7 = 11 Box 2: b + c + d = 7 + 1 + 3 = 11 Box 3: d + e + f = 3 + 2 + 6 = 11 Box 4: f + g = 6 + 5 = 11 a = 5 b = 6 c = 2 d = 3 e = 1 f = 7 g = 4 Box 1: a + b = 5 + 6 = 11 Box 2: b + c + d = 6 + 2 + 3 = 11 Box 3: d + e + f = 3 + 1 + 7 = 11 Box 4: f + g = 7 + 4 = 11 a = 6 b = 4 c = 1 d = 5 e = 2 f = 3 g = 7 Box 1: a + b = 6 + 4 = 10 Box 2: b + c + d = 4 + 1 + 5 = 10 Box 3: d + e + f = 5 + 2 + 3 = 10 Box 4: f + g = 3 + 7 = 10 a = 6 b = 4 c = 5 d = 1 e = 2 f = 7 g = 3 Box 1: a + b = 6 + 4 = 10 Box 2: b + c + d = 4 + 5 + 1 = 10 Box 3: d + e + f = 1 + 2 + 7 = 10 Box 4: f + g = 7 + 3 = 10 a = 7 b = 2 c = 6 d = 1 e = 3 f = 5 g = 4 Box 1: a + b = 7 + 2 = 9 Box 2: b + c + d = 2 + 6 + 1 = 9 Box 3: d + e + f = 1 + 3 + 5 = 9 Box 4: f + g = 5 + 4 = 9 a = 7 b = 3 c = 2 d = 5 e = 1 f = 4 g = 6 Box 1: a + b = 7 + 3 = 10 Box 2: b + c + d = 3 + 2 + 5 = 10 Box 3: d + e + f = 5 + 1 + 4 = 10 Box 4: f + g = 4 + 6 = 10 ```

Not really readable. «Short mode» to the rescue:

```\$ four-squares-puzzle -a -s 1 2 3 4 5 6 7 a=3, b=7, c=2, d=1, e=5, f=4, g=6 a=4, b=5, c=3, d=1, e=6, f=2, g=7 a=4, b=7, c=1, d=3, e=2, f=6, g=5 a=5, b=6, c=2, d=3, e=1, f=7, g=4 a=6, b=4, c=1, d=5, e=2, f=3, g=7 a=6, b=4, c=5, d=1, e=2, f=7, g=3 a=7, b=2, c=6, d=1, e=3, f=5, g=4 a=7, b=3, c=2, d=5, e=1, f=4, g=6 ```

We got 8 solutions, and the fifth one (marked with green) is the same as given in the challenge.

We can try a set of values that cannot give a solution:

```\$ four-squares-puzzle -a -s 1 1 1 1 1 1 1 ```

No solutions, thankfully…

### Perl

This is a straight forwardish translation of the Raku version. Perl does not support permutations out of «Algorithm::Combinatorics» module does. (I have used it before; see my Magical Sum with Raku and Perl article.)

File: four-squares-puzzle-perl ```#! /usr/bin/env perl use strict; use warnings; use feature 'say'; use feature 'signatures'; no warnings "experimental::signatures"; use Getopt::Long; use Algorithm::Combinatorics 'permutations'; my \$short = 0; my \$all = 0; GetOptions("short" => \\$short, "all" => \\$all); \$all = 1 if \$short; my @values = @ARGV; for my \$perm (permutations(\@values)) { if (check_values(@\$perm)) { my (\$a, \$b, \$c, \$d, \$e, \$f, \$g) = @\$perm; if (\$short) { say "a=\$a, b=\$b, c=\$c, d=\$d, e=\$e, f=\$f, g=\$g"; } else { say "a = \$a"; say "b = \$b"; say "c = \$c"; say "d = \$d"; say "e = \$e"; say "f = \$f"; say "g = \$g"; say ""; say "Box 1: a + b = \$a + \$b = " . (\$a + \$b); say "Box 2: b + c + d = \$b + \$c + \$d = " . (\$b + \$c + \$d); say "Box 3: d + e + f = \$d + \$e + \$f = " . (\$d + \$e + \$f); say "Box 4: f + g = \$f + \$g = " . (\$f + \$g); say "" if \$all; } last unless \$all; } } sub check_values (@values) { my (\$a, \$b, \$c, \$d, \$e, \$f, \$g) = @values; my \$box1 = \$a + \$b; my \$box2 = \$b + \$c + \$d; my \$box3 = \$d + \$e + \$f; my \$box4 = \$f + \$g; return (\$box1 == \$box2 && \$box3 == \$box4 && \$box1 == \$box3) #  } ```

 Perl does not support nesting equations (as e.g. `\$a == \$b == \$c`, which is valid in Raku), so we have to write it like this.

Running it gives the same result as the Raku version:

```\$ ./four-squares-puzzle-perl 1 2 3 4 5 6 7 a = 3 b = 7 c = 2 d = 1 e = 5 f = 4 g = 6 Box 1: a + b = 3 + 7 = 10 Box 2: b + c + d = 7 + 2 + 1 = 10 Box 3: d + e + f = 1 + 5 + 4 = 10 Box 4: f + g = 4 + 6 = 10 \$ ./four-squares-puzzle-perl -short 1 2 3 4 5 6 7 a=3, b=7, c=2, d=1, e=5, f=4, g=6 a=4, b=5, c=3, d=1, e=6, f=2, g=7 a=4, b=7, c=1, d=3, e=2, f=6, g=5 a=5, b=6, c=2, d=3, e=1, f=7, g=4 a=6, b=4, c=1, d=5, e=2, f=3, g=7 a=6, b=4, c=5, d=1, e=2, f=7, g=3 a=7, b=2, c=6, d=1, e=3, f=5, g=4 a=7, b=3, c=2, d=5, e=1, f=4, g=6 ```

And that's it.