by Arne Sommer

Nimbly Fuscous with Raku

[120] Published 21. March 2021.

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

Challenge #104.1: FUSC Sequence

Write a script to generate first 50 members of `FUSC Sequence`. Please refer to OEIS for more information.

The sequence defined as below:

```fusc(0) = 0 fusc(1) = 1 for n > 1: when n is even: fusc(n) = fusc(n / 2), when n is odd: fusc(n) = fusc((n-1)/2) + fusc((n+1)/2) ```

This is yet another sequence that would have fitted right in in my Centenary Sequences with Raku article series.

We can set up this as a sequence with `gather`/`take`:

File: fusc-seq ```#! /usr/bin/env raku unit sub MAIN (\$limit = 50); # [1] my \$fusc := gather # [2] { take 0; # [3] take 1; # [4] my \$index = 1; # [5] loop # [6] { \$index++; # [7] take \$fusc[\$index / 2]; # [8] \$index++; # [7] take \$fusc[(\$index - 1)/2] + \$fusc[(\$index +1)/2]; # [9] } } say \$fusc[^\$limit].join(", "); # [10] ```

[1] Default to the first 50 values.

[2] A `gather` block to gather the following values.

[3] The first value, with `take`.

[4] The second value.

[5] The sequence relies on previous values, hence the need for the index.

[6] En eternal loop. Note that we used binding (`:=` in [2]), so the values are not computed until we need them.

[7] Update the index.

[8] This is the value, when the index is even.

[9] And this is the value, when the index is odd.

[10] Print the requested number of values.

See my Raku Gather, I Take article or docs.raku.org/syntax/gather take for more information about `gather`/`take`.

Running it:

```\$ ./fusc-seq 10 0, 1, 1, 2, 1, 3, 2, 3, 1, 4 \$ ./fusc-seq 0, 1, 1, 2, 1, 3, 2, 3, 1, 4, 3, 5, 2, 5, 3, 4, 1, 5, 4, 7, 3, 8, 5, 7, 2, \ 7, 5, 8, 3, 7, 4, 5, 1, 6, 5, 9, 4, 11, 7, 10, 3, 11, 8, 13, 5, 12, 7, 9, 2, 9 ```

Note that this program (as opposed to a recursive approach) only calculates each value once. The next time we need a prior value (in [8] or [9]), it looks it up in the the `\$fusc` variable. We got built in caching, for free.

Challenge #104.2: NIM Game

Write a script to simulate the `NIM Game`.

It is played between 2 players. For the purpose of this task, let assume you play against the machine.

There are 3 simple rules to follow:

```a) You have 12 tokens b) Each player can pick 1, 2 or 3 tokens at a time c) The player who picks the last token wins the game ```

The program is not very smart. It picks the number of tokens (1, 2 or 3) by random. Except when there is 3 or less tokens left, when it takes them all.

File: nim-game ```#! /usr/bin/env raku unit sub MAIN; my \$tokens = 12; # [1] loop # [2] { say "Remaining tokens: \$tokens"; my \$count = prompt "How many tokens do you want (1,2,3): "; # [3] die unless \$count == any(1,2,3); # [4] \$tokens -= \$count; # [5] if \$tokens <= 0 # [6] { say "You won!"; last; # [6a] } say "Remaining tokens: \$tokens"; \$count = \$tokens <= 3 ?? \$tokens !! (1,2,3).pick; # [7] say "Machine picked \$count tokens"; \$tokens -= \$count; # [5] if \$tokens <= 0 # [8] { say "The Machine won!"; last; # [8a] } } ```

[1] The game starts with 12 tokens.

[2] An eternal loop. Note the two (explicit) exits with `last`, in [6a] and [8a].

[3] Use `prompt` to get user input, after printing the text (if any).

[4] Using an `any` junction to check that the input values is one of 1, 2 or 3. Terminate the program if not. (This is not very user friendly, but it can be considered a suitable punishment for typing in something illegal.)

[5] Update the number of tokens left.

[6] It is ok to specify more tokens than we have left. You win if you take the last one(s).

[7] The machine player takes all the remaining tokens, if there afre 3 or less of them. if not, it picks a random number between 1 and 3 (with `pick`).

[8] Has the machine player won?

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

Running it:

```\$ ./nim-game Remaining tokens: 12 How many tokens do you want (1,2,3): 3 Remaining tokens: 9 Machine picked 3 tokens Remaining tokens: 6 How many tokens do you want (1,2,3): 2 Remaining tokens: 4 Machine picked 3 tokens Remaining tokens: 1 How many tokens do you want (1,2,3): 1 You won! \$ ./nim-game Remaining tokens: 12 How many tokens do you want (1,2,3): 3 Remaining tokens: 9 Machine picked 1 tokens Remaining tokens: 8 How many tokens do you want (1,2,3): 3 Remaining tokens: 5 Machine picked 2 tokens Remaining tokens: 3 How many tokens do you want (1,2,3): 2 Remaining tokens: 1 Machine picked 1 tokens The Machine won! ```

You win if you can arrange a situation where there are 4 tokens left when it is the other user's turn.

And that's it.