[User]
On a set of coasters we have, there's a picture of a teacup.   On the rim of the teacup the word   **TEA**   appears a number of times separated by bullet characters   (•).

It occurred to me that if the bullet were removed and the words run together,   you could start at any letter and still end up with a meaningful three-letter word.

So start at the   **T**   and read   **TEA**.   Start at the   **E**   and read   **EAT**,   or start at the   **A**   and read   **ATE**.

That got me thinking that maybe there are other words that could be used rather that   **TEA**.   And that's just English.   What about Italian or Greek or ... um ... Telugu.

For English, we will use the unixdict (now) located at:   unixdict.txt.

(This will maintain continuity with other Rosetta Code tasks that also use it.)

Task

Search for a set of words that could be printed around the edge of a teacup.   The words in each set are to be of the same length, that length being greater than two (thus precluding   **AH**   and   **HA**,   for example.)

Having listed a set, for example   [**ate tea eat**],   refrain from displaying permutations of that set, e.g.:   [**eat tea ate**]   etc.

The words should also be made of more than one letter   (thus precluding   **III**   and   **OOO**   etc.)

The relationship between these words is (using ATE as an example) that the first letter of the first becomes the last letter of the second.   The first letter of the second becomes the last letter of the third.   So   **ATE**   becomes   **TEA**   and   **TEA**   becomes   **EAT**.

All of the possible permutations, using this particular permutation technique, must be words in the list.

The set you generate for   **ATE**   will never included the word   **ETA**   as that cannot be reached via the first-to-last movement method.

Display one line for each set of teacup rim words.

Other tasks related to string operations:

Metrics

* Array length
* String length
* Copy a string
* Empty string  (assignment)

Counting

* Word frequency
* Letter frequency
* Jewels and stones
* I before E except after C
* Bioinformatics/base count
* Count occurrences of a substring
* Count how many vowels and consonants occur in a string

Remove/replace

* XXXX redacted
* Conjugate a Latin verb
* Remove vowels from a string
* String interpolation (included)
* Strip block comments
* Strip comments from a string
* Strip a set of characters from a string
* Strip whitespace from a string -- top and tail
* Strip control codes and extended characters from a string

Anagrams/Derangements/shuffling

* Word wheel
* ABC problem
* Sattolo cycle
* Knuth shuffle
* Ordered words
* Superpermutation minimisation
* Textonyms (using a phone text pad)
* Anagrams
* Anagrams/Deranged anagrams
* Permutations/Derangements

Find/Search/Determine

* ABC words
* Odd words
* Word ladder
* Semordnilap
* Word search
* Wordiff  (game)
* String matching
* Tea cup rim text
* Alternade words
* Changeable words
* State name puzzle
* String comparison
* Unique characters
* Unique characters in each string
* Extract file extension
* Levenshtein distance
* Palindrome detection
* Common list elements
* Longest common suffix
* Longest common prefix
* Compare a list of strings
* Longest common substring
* Find common directory path
* Words from neighbour ones
* Change e letters to i in words
* Non-continuous subsequences
* Longest common subsequence
* Longest palindromic substrings
* Longest increasing subsequence
* Words containing "the" substring
* Sum of the digits of n is substring of n
* Determine if a string is numeric
* Determine if a string is collapsible
* Determine if a string is squeezable
* Determine if a string has all unique characters
* Determine if a string has all the same characters
* Longest substrings without repeating characters
* Find words which contains all the vowels
* Find words which contain the most consonants
* Find words which contains more than 3 vowels
* Find words whose first and last three letters are equal
* Find words with alternating vowels and consonants

Formatting

* Substring
* Rep-string
* Word wrap
* String case
* Align columns
* Literals/String
* Repeat a string
* Brace expansion
* Brace expansion using ranges
* Reverse a string
* Phrase reversals
* Comma quibbling
* Special characters
* String concatenation
* Substring/Top and tail
* Commatizing numbers
* Reverse words in a string
* Suffixation of decimal numbers
* Long literals, with continuations
* Numerical and alphabetical suffixes
* Abbreviations, easy
* Abbreviations, simple
* Abbreviations, automatic

Song lyrics/poems/Mad Libs/phrases

* Mad Libs
* Magic 8-ball
* 99 bottles of beer
* The Name Game (a song)
* The Old lady swallowed a fly
* The Twelve Days of Christmas

Tokenize

* Text between
* Tokenize a string
* Word break problem
* Tokenize a string with escaping
* Split a character string based on change of character

Sequences

* Show ASCII table
* De Bruijn sequences
* Summarize and say sequence
* Generate lower case ASCII alphabet

[Assistant]
(formerly Perl 6)

**Works with**: Rakudo version 2019.07.1

There doesn't seem to be any restriction that the word needs to consist only of lowercase letters, so words of any case are included. Since the example code specifically shows the example words (TEA, EAT, ATE) in uppercase, I elected to uppercase the found words.

As the specs keep changing, this version will accept ANY text file as its dictionary and accepts parameters to configure the minimum number of characters in a word to consider and whether to allow mono-character words.

Defaults to unixdict.txt, minimum 3 characters and mono-character 'words' disallowed. Feed a file name to use a different word list, an integer to --min-chars and/or a truthy value to --mono to allow mono-chars.

```
my %*SUB-MAIN-OPTS = :named-anywhere;

unit sub MAIN ( $dict = 'unixdict.txt', :$min-chars = 3, :$mono = False );

my %words;
$dict.IO.slurp.words.map: { .chars < $min-chars ?? (next) !! %words{.uc.comb.sort.join}.push: .uc };

my @teacups;
my %seen;

for %words.values -> @these {
    next if !$mono && @these < 2;
    MAYBE: for @these {
        my $maybe = $_;
        next if %seen{$_};
        my @print;
        for ^$maybe.chars {
            if $maybe ∈ @these {
                @print.push: $maybe;
                $maybe = $maybe.comb.list.rotate.join;
            } else {
                @print = ();
                next MAYBE
            }
        }
        if @print.elems {
            @teacups.push: @print;
            %seen{$_}++ for @print;
        }
    }
}

say .unique.join(", ") for sort @teacups;

```

Defaults:

Command line: raku teacup.p6

```
APT, PTA, TAP
ARC, RCA, CAR
ATE, TEA, EAT
```

Allow mono-chars:

Command line: raku teacup.p6 --mono=1

```
AAA
APT, PTA, TAP
ARC, RCA, CAR
ATE, TEA, EAT
III
```

Using a larger dictionary:

words.txt file from https://github.com/dwyl/english-words

Command line: raku teacup.p6 words.txt --min-chars=4 --mono=Allow

```
AAAA
AAAAAA
ADAD, DADA
ADAR, DARA, ARAD, RADA
AGAG, GAGA
ALIT, LITA, ITAL, TALI
AMAN, MANA, ANAM, NAMA
AMAR, MARA, ARAM, RAMA
AMEL, MELA, ELAM, LAME
AMEN, MENA, ENAM, NAME
AMOR, MORA, ORAM, RAMO
ANAN, NANA
ANIL, NILA, ILAN, LANI
ARAR, RARA
ARAS, RASA, ASAR, SARA
ARIS, RISA, ISAR, SARI
ASEL, SELA, ELAS, LASE
ASER, SERA, ERAS, RASE
DENI, ENID, NIDE, IDEN
DOLI, OLID, LIDO, IDOL
EGOR, GORE, OREG, REGO
ENOL, NOLE, OLEN, LENO
ESOP, SOPE, OPES, PESO
ISIS, SISI
MMMM
MORO, OROM, ROMO, OMOR
OOOO
```


[User]
There are quite a number of temperature scales. For this task we will concentrate on four of the perhaps best-known ones:
Kelvin, Celsius, Fahrenheit, and Rankine.

The Celsius and Kelvin scales have the same magnitude, but different null points.

:   0 degrees Celsius corresponds to 273.15 kelvin.
:   0 kelvin is absolute zero.

The Fahrenheit and Rankine scales also have the same magnitude, but different null points.

:   0 degrees Fahrenheit corresponds to 459.67 degrees Rankine.
:   0 degrees Rankine is absolute zero.

The Celsius/Kelvin and Fahrenheit/Rankine scales have a ratio of 5 : 9.

Task

Write code that accepts a value of kelvin, converts it to values of the three other scales, and prints the result.

Example

```
K  21.00

C  -252.15

F  -421.87

R  37.80

```

[Assistant]
(formerly Perl 6)

**Translation of**: Perl

```
my %scale =
    Celcius    => { factor => 1  , offset => -273.15 },
    Rankine    => { factor => 1.8, offset =>    0    },
    Fahrenheit => { factor => 1.8, offset => -459.67 },
;

my $kelvin = +prompt "Enter a temperature in Kelvin: ";
die "No such temperature!" if $kelvin < 0;

for %scale.sort {
    printf "%12s: %7.2f\n", .key, $kelvin * .value<factor> + .value<offset>;
}

```

Output:

```
Enter a temperature in Kelvin: 21
     Celcius: -252.15
  Fahrenheit: -421.87
     Rankine:   37.80

```

Alternative version that accepts the input in any of the four scales:

```
while my $answer = prompt 'Temperature: ' {
    my $k = do given $answer {
        when s/:i C $// { $_ + 273.15 }
        when s/:i F $// { ($_ + 459.67) / 1.8 }
        when s/:i R $// { $_ / 1.8 }
        when s/:i K $// { $_ }
        default         { $_ }
    }
    say "  { $k }K";
    say "  { $k - 273.15 }℃";
    say "  { $k * 1.8 - 459.67 }℉";
    say "  { $k * 1.8 }R";
}

```

Output:

```
Temperature: 0
  0K
  -273.15℃
  -459.67℉
  0R
Temperature: 0c
  273.15K
  0℃
  32℉
  491.67R
Temperature: 212f
  373.15K
  100℃
  212℉
  671.67R
Temperature: -40c
  233.15K
  -40℃
  -40℉
  419.67R
```


[User]
Task

Clear the terminal window.

[Assistant]
(formerly Perl 6)

```
sub clear { print qx[clear] }
clear;

```


[User]
Task

Display a word in various colours on the terminal.

The system palette, or colours such as Red, Green, Blue, Magenta, Cyan, and Yellow can be used.

Optionally demonstrate:

* How the system should determine if the terminal supports colour
* Setting of the background colour
* How to cause blinking or flashing (if supported by the terminal)

[Assistant]
(formerly Perl 6)

```
use Terminal::ANSIColor;

say colored('RED ON WHITE', 'bold red on_white');
say colored('GREEN', 'bold green');
say colored('BLUE ON YELLOW', 'bold blue on_yellow');
say colored('MAGENTA', 'bold magenta');
say colored('CYAN ON RED', 'bold cyan on_red');
say colored('YELLOW', 'bold yellow');

```


[User]
Task

Demonstrate how to achieve movement of the terminal cursor:

:   * how to move the cursor one position to the left
    * how to move the cursor one position to the right
    * how to move the cursor up one line (without affecting its horizontal position)
    * how to move the cursor down one line (without affecting its horizontal position)
    * how to move the cursor to the beginning of the line
    * how to move the cursor to the end of the line
    * how to move the cursor to the top left corner of the screen
    * how to move the cursor to the bottom right corner of the screen

For the purpose of this task, it is not permitted to overwrite any characters or attributes on any part of the screen (so outputting a space is not a suitable solution to achieve a movement to the right).

Handling of out of bounds locomotion

This task has no specific requirements to trap or correct cursor movement beyond the terminal boundaries, so the implementer should decide what behavior fits best in terms of the chosen language.   Explanatory notes may be added to clarify how an out of bounds action would behave and the generation of error messages relating to an out of bounds cursor position is permitted.

[Assistant]
(formerly Perl 6)

```
shell "tput cub1";                  # one position to the left
shell "tput cuf1";                  # one position to the right
shell "tput cuu1";                  # up one line
shell "tput cud1";                  # down one line
shell "tput cr";                    # beginning of line
shell "tput home";                  # top left corner

$_ = qx[stty -a </dev/tty 2>&1];
my $rows = +m/'rows '    <(\d+)>/;
my $cols = +m/'columns ' <(\d+)>/;

shell "tput hpa $cols";             # end of line
shell "tput cup $rows $cols";       # bottom right corner

```


[User]
Task

Move the cursor to column   **3**,   row   **6**,   and display the word   "Hello"   (without the quotes),   so that the letter   **H**   is in column   **3**   on row   **6**.

[Assistant]
(formerly Perl 6)
Assuming an ANSI terminal:

```
print "\e[6;3H";
print 'Hello';

```


[User] Determine the height and width of the terminal, and store this information into variables for subsequent use.

[Assistant]
(formerly Perl 6)
Using *stty* just for the heck of it.

```
my $stty = qx[stty -a];
my $lines = $stty.match(/ 'rows '    <( \d+/);
my $cols  = $stty.match(/ 'columns ' <( \d+/);
say "$lines $cols";

```


[User]
Task

Display an extended (non ASCII) character onto the terminal.

Specifically, display a    £    (GBP currency sign).

[Assistant]
(formerly Perl 6)
To demonstrate we're not limited to Latin-1, we'll print the fullwidth variant.

```
say '￡';
say "\x[FFE1]";
say "\c[FULLWIDTH POUND SIGN]";
0xffe1.chr.say;

```


[User] The task is to hide the cursor and show it again.

[Assistant]
(formerly Perl 6)

```
say 'Hiding the cursor for 5 seconds...';
run 'tput', 'civis';
sleep 5;
run 'tput', 'cvvis';

```


[User]
Task

Display a word in inverse video   (or reverse video)   followed by a word in normal video.

[Assistant]
(formerly Perl 6)

```
say "normal";
run "tput", "rev";
say "reversed";
run "tput", "sgr0";
say "normal";

```


[User] Determine the character displayed on the screen at column 3, row 6 and store that character in a variable. Note that it is permissible to utilize system or language provided methods or system provided facilities, system maintained records or available buffers or system maintained display records to achieve this task, rather than query the terminal directly, if those methods are more usual for the system type or language.

[Assistant]
(formerly Perl 6)

**Translation of**: Python

```
use NCurses;

# Reference:
# https://github.com/azawawi/perl6-ncurses

# Initialize curses window
my $win = initscr() or die "Failed to initialize ncurses\n";

# Print random text in a 10x10 grid

for ^10 { mvaddstr($_ , 0, (for ^10 {(41 .. 90).roll.chr}).join )};

# Read

my $icol = 3 - 1;
my $irow = 6 - 1;

my $ch = mvinch($irow,$icol);

# Show result

mvaddstr($irow, $icol+10, 'Character at column 3, row 6 = ' ~ $ch.chr);

mvaddstr( LINES() - 2, 2, "Press any key to exit..." );

# Refresh (this is needed)
nc_refresh;

# Wait for a keypress
getch;

# Cleanup
LEAVE {
    delwin($win) if $win;
    endwin;
}

```

Output:

```
+W18:5I<1N
N-I.HG45SK
BFJY8:AK)8
J+4U<H1++:
RP>BX-/19Y
URDESVX;HX  Character at column 3, row 6 = D
J7+X3@E<BG
M;?2U<8+FI
)@BG,:D)O1
)>A-=LDY-.

  Press any key to exit...

```


[User]
Task

Clear the screen, output something on the display, and then restore the screen to the preserved state that it was in before the task was carried out.

There is no requirement to change the font or kerning in this task, however character decorations and attributes are expected to be preserved.   If the implementer decides to change the font or kerning during the display of the temporary screen, then these settings need to be restored prior to exit.

[Assistant]
(formerly Perl 6)

```
print "\e[?1049h\e[H";
say "Alternate buffer!";

for 5,4...1 {
    print "\rGoing back in: $_";
    sleep 1;
}

print "\e[?1049l";

```


[User]
Create a routine to obtain data entry using a specific place on the terminal screen. Data entry fields should be restricted to a specific length, and it should not be possible for the cursor to move beyond the input length.

The routine should accept parameters for row number, column number and input length, and should obtain a string
value entered by the user.

For the purpose of this task, obtain input from the user, showing data entry at row 3, column 5, with input width restricted to a maximum of 8 characters.

Note: In this task input wrapping is not allowed. (See Terminal control/Restricted width positional input/With wrapping) for input wrapping variant.

For a similar task using a graphical user interface, see Graphical User Interface/Restricted width positional input/No wrapping.

[Assistant]
(formerly Perl 6)

**Works with**: Rakudo version 2018.10

Should work with any termios compatible terminal.

All printable character keys work, as does backspace and enter. Ctrl-c to exit. All other keys / key-combos are ignored.

```
use Term::termios;

constant $saved   = Term::termios.new(fd => 1).getattr;
constant $termios = Term::termios.new(fd => 1).getattr;
# raw mode interferes with carriage returns, so
# set flags needed to emulate it manually
$termios.unset_iflags(<BRKINT ICRNL ISTRIP IXON>);
$termios.unset_lflags(<ECHO ICANON IEXTEN ISIG>);
$termios.setattr(:DRAIN);

END {
    $saved.setattr(:NOW); # reset terminal to original settings
    print "\e[?25h \e[H\e[J"; # clear and reset screen
}

my $row     = 3;
my $column  = 5;
my $field   = '';
my $spacer  = ' ' x 8;
my $pointer = 0;

my ($rows,$cols) = qx/stty size/.words; # get screen size

my @screen = "\e[41m{' ' x $cols}\e[0m" xx $rows;

update($spacer);

loop {
    my $key = $*IN.read(4).decode;
    given $key {
        when ' '..'~' {
            if $pointer < 8 {
                $field ~= $_;
                $spacer = ' ' x 8 - $field.chars;
                $pointer +=1;
                update($field~$spacer)
            }
        }
        when "\c[127]" { # backspace
            if $pointer > 0 {
                $field.=substr(0,*-1);
                $spacer = ' ' x 8 - $field.chars;
                $pointer -= 1;
                update($field~$spacer)
            }
        }
        when "\c[13]" {
            update('        ');
            print "\e[10;6H\e[1;33;41mYou entered: $field\e[0m\e[$row;{$column}H";
            $field = '';
            $pointer = 0;
        }
        when "\c[0003]" { exit } # Ctrl-c
        default { }
    }
}

sub update ($str) {
    ($rows,$cols) = qx/stty size/.words;
    @screen = "\e[41m{' ' x $cols}\e[0m" xx $rows;
    print "\e[H\e[J{@screen.join: "\n"}\e[$row;{$column}H$str\e[$row;{$column + $pointer}H";
}

```


[User]
Create a routine to obtain data entry using a specific place on the terminal screen.

Data entry fields should be restricted to a specific length,   and the cursor should not move beyond the input length.

The routine should accept parameters for row number,   column number,   and input length,   and should obtain a string value entered by the user.

For the purpose of this task,   obtain input from the user,   showing data entry at   row   **3**,   column   **5**,   with input width restricted to a maximum of   **8**   characters.

Note:   in this task input wrapping is allowed.   If the length of input exceeds the maximum width, the left hand side of the field should disappear, allowing additional input to be obtained.   However, the cursor must not move beyond the designated input length.

It is permissible to use navigation keys to see input field length.

(See Terminal control/Restricted width positional input/No wrapping for similar input routine with no wrapping).

For a similar task using a graphical user interface,   see   Graphical User Interface/Restricted width positional input/With wrapping.

[Assistant]
(formerly Perl 6)

**Works with**: Rakudo version 2018.10

Should work with any termios compatible terminal.

All printable character keys (except Tab) work, as does backspace and enter. Ctrl-c to exit. All other keys / key-combos are ignored.

```
use Term::termios;

constant $saved   = Term::termios.new(fd => 1).getattr;
constant $termios = Term::termios.new(fd => 1).getattr;
# raw mode interferes with carriage returns, so
# set flags needed to emulate it manually
$termios.unset_iflags(<BRKINT ICRNL ISTRIP IXON>);
$termios.unset_lflags(<ECHO ICANON IEXTEN ISIG>);
$termios.setattr(:DRAIN);

END {
    $saved.setattr(:NOW); # reset terminal to original settings
    print "\e[?25h \e[H\e[J"; # clear and reset screen
}

my $row     = 3;
my $column  = 5;
my $field   = '';
my $spacer  = ' ' x 8;
my $pointer = 0;

my ($rows,$cols) = qx/stty size/.words; # get screen size

my @screen = "\e[41m{' ' x $cols}\e[0m" xx $rows;

update($spacer);

loop {
    my $key = $*IN.read(4).decode;
    given $key {
        when ' '..'~' {
            if $pointer < 8 {
                $field ~= $_;
                $spacer = ' ' x 8 - $field.chars;
                $pointer +=1;
                update($field~$spacer)
            } elsif $pointer >= 8 {
                $field ~= $_;
                $spacer = '';
                update($field.substr(*-8))
            }
        }
        when "\c[127]" { # backspace
            if $pointer > 0 {
                $field.=substr(0,*-1);
                $spacer = ' ' x (8 - $field.chars max 0);
                $pointer -= 1 if $field.chars < 8;
                my $display = $field.chars < 8 ?? $field !! $field.substr(*-8);
                update($display~$spacer)
            }
        }
        when "\c[13]" {
            update('        ');
            print "\e[10;6H\e[1;33;41mYou entered: $field\e[0m\e[$row;{$column}H";
            $field = '';
            $pointer = 0;
        }
        when "\c[0003]" { exit } # Ctrl-c
        default { }
    }
}

sub update ($str) {
    ($rows,$cols) = qx/stty size/.words;
    @screen = "\e[41m{' ' x $cols}\e[0m" xx $rows;
    print "\e[H\e[J{@screen.join: "\n"}\e[$row;{$column}H$str\e[$row;{$column + $pointer}H";
}

```


[User]
Task

Make the terminal running the program ring its "bell".

On modern terminal emulators, this may be done by playing some other sound which might or might not be configurable, or by flashing the title bar or inverting the colors of the screen, but was classically a physical bell within the terminal.   It is usually used to indicate a problem where a wrong character has been typed.

In most terminals, if the   Bell character   (ASCII code **7**,    `\a`  in C)   is printed by the program, it will cause the terminal to ring its bell.   This is a function of the terminal, and is independent of the programming language of the program, other than the ability to print a particular character to standard out.

[Assistant]
(formerly Perl 6)

```
print 7.chr;

```


[User]
The task is to check that the terminal supports Unicode output, before outputting a Unicode character. If the terminal supports Unicode, then the terminal should output a Unicode delta (U+25b3). If the terminal does not support Unicode, then an appropriate error should be raised.

Note that it is permissible to use system configuration data to determine terminal capabilities if the system provides such a facility.

[Assistant]
(formerly Perl 6)

```
die "Terminal can't handle UTF-8"
    unless first(*.defined, %*ENV<LC_ALL LC_CTYPE LANG>) ~~ /:i 'utf-8'/;
say "△";

```

Output:

```
△
```


[User]
|  |
| --- |
| This page uses content from **Wikipedia**. The original article was at Ternary logic. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance) |

In logic, a **three-valued logic** (also **trivalent**, **ternary**, or **trinary logic**, sometimes abbreviated **3VL**) is any of several many-valued logic systems in which there are three truth values indicating *true*, *false* and some indeterminate third value.

This is contrasted with the more commonly known bivalent logics (such as classical sentential or boolean logic) which provide only for *true* and *false*.

Conceptual form and basic ideas were initially created by Łukasiewicz, Lewis and Sulski.

These were then re-formulated by Grigore Moisil in an axiomatic algebraic form, and also extended to *n*-valued logics in 1945.

**Example *Ternary Logic Operators* in *Truth Tables*:**

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| *not* a  | ¬ | | | --- | --- | | True | False | | Maybe | Maybe | | False | True | | a *and* b  |  |  |  |  | | --- | --- | --- | --- | | ∧ | True | Maybe | False | | True | True | Maybe | False | | Maybe | Maybe | Maybe | False | | False | False | False | False | | a *or* b  |  |  |  |  | | --- | --- | --- | --- | | ∨ | True | Maybe | False | | True | True | True | True | | Maybe | True | Maybe | Maybe | | False | True | Maybe | False | |
| *if* a *then* b  |  |  |  |  | | --- | --- | --- | --- | | ⊃ | True | Maybe | False | | True | True | Maybe | False | | Maybe | True | Maybe | Maybe | | False | True | True | True | | a *is equivalent to* b  |  |  |  |  | | --- | --- | --- | --- | | ≡ | True | Maybe | False | | True | True | Maybe | False | | Maybe | Maybe | Maybe | Maybe | | False | False | Maybe | True | |

Task

* Define a new type that emulates *ternary logic* by storing data **trits**.
* Given all the binary logic operators of the original programming language, reimplement these operators for the new *Ternary logic* type **trit**.
* Generate a sampling of results using **trit** variables.
* Kudos for actually thinking up a test case algorithm where *ternary logic* is intrinsically useful, optimises the test case algorithm and is preferable to binary logic.

Note:   **Setun**   (Сетунь) was a   balanced ternary   computer developed in 1958 at   Moscow State University.   The device was built under the lead of   Sergei Sobolev   and   Nikolay Brusentsov.   It was the only modern   ternary computer,   using three-valued ternary logic

[Assistant]
(formerly Perl 6)

**Works with**: rakudo version 2018.03

The precedence of each operator is specified as equivalent to an existing operator. We've taken the liberty of using a double arrow for implication, to avoid confusing it with ⊃, (U+2283 SUPERSET OF).

```
# Implementation:
enum Trit <Foo Moo Too>;

sub prefix:<¬> (Trit $a) { Trit(1-($a-1)) }

sub infix:<∧> (Trit $a, Trit $b) is equiv(&infix:<*>) { $a min $b }
sub infix:<∨> (Trit $a, Trit $b) is equiv(&infix:<+>) { $a max $b }

sub infix:<⇒> (Trit $a, Trit $b) is equiv(&infix:<..>) { ¬$a max $b }
sub infix:<≡> (Trit $a, Trit $b) is equiv(&infix:<eq>) { Trit(1 + ($a-1) * ($b-1)) }

# Testing:
say '¬';
say "Too {¬Too}";
say "Moo {¬Moo}";
say "Foo {¬Foo}";

sub tbl (&op,$name) {
    say '';
    say "$name   Too Moo Foo";
    say "   ╔═══════════";
    say "Too║{op Too,Too} {op Too,Moo} {op Too,Foo}";
    say "Moo║{op Moo,Too} {op Moo,Moo} {op Moo,Foo}";
    say "Foo║{op Foo,Too} {op Foo,Moo} {op Foo,Foo}";
}

tbl(&infix:<∧>, '∧');
tbl(&infix:<∨>, '∨');
tbl(&infix:<⇒>, '⇒');
tbl(&infix:<≡>, '≡');

say '';
say 'Precedence tests should all print "Too":';
say ~(
    Foo ∧ Too ∨ Too ≡ Too,
    Foo ∧ (Too ∨ Too) ≡ Foo,
    Too ∨ Too ∧ Foo ≡ Too,
    (Too ∨ Too) ∧ Foo ≡ Foo,

    ¬Too ∧ Too ∨ Too ≡ Too,
    ¬Too ∧ (Too ∨ Too) ≡ ¬Too,
    Too ∨ Too ∧ ¬Too ≡ Too,
    (Too ∨ Too) ∧ ¬Too ≡ ¬Too,

    Foo ∧ Too ∨ Foo ⇒ Foo ≡ Too,
    Foo ∧ Too ∨ Too ⇒ Foo ≡ Foo,
);

```

Output:

```
¬
Too Foo
Moo Moo
Foo Too

∧   Too Moo Foo
   ╔═══════════
Too║Too Moo Foo
Moo║Moo Moo Foo
Foo║Foo Foo Foo

∨   Too Moo Foo
   ╔═══════════
Too║Too Too Too
Moo║Too Moo Moo
Foo║Too Moo Foo

⇒   Too Moo Foo
   ╔═══════════
Too║Too Moo Foo
Moo║Too Moo Moo
Foo║Too Too Too

≡   Too Moo Foo
   ╔═══════════
Too║Too Moo Foo
Moo║Moo Moo Moo
Foo║Foo Moo Too

Precedence tests should all print "Too":
Too Too Too Too Too Too Too Too Too Too
```


[User]
Task

Using a well-known testing-specific library/module/suite for your language, write some tests for your language's entry in Palindrome.

If your language does not have a testing specific library well known to the language's community then state this or omit the language.

[Assistant]
(formerly Perl 6)

```
use Test;

sub palin( Str $string) { so $string.lc.comb(/\w/) eq  $string.flip.lc.comb(/\w/) }

for
    'A man, a plan, a canal: Panama.'           => True,
    'My dog has fleas'                          => False,
    "Madam, I'm Adam."                          => True,
    '1 on 1'                                    => False,
    'In girum imus nocte et consumimur igni'    => True,
    ''                                          => True
{
  my ($test, $expected-result) = .kv;
    is palin($test), $expected-result,
        "\"$test\" is {$expected-result??''!!'not '}a palindrome.";
}

done-testing;

```

Output:

```
1..6
ok 1 - "1 on 1" is not a palindrome.
ok 2 - "My dog has fleas" is not a palindrome.
ok 3 - "A man, a plan, a canal: Panama." is a palindrome.
ok 4 - "" is a palindrome.
ok 5 - "Madam, I'm Adam." is a palindrome.
ok 6 - "In girum imus nocte et consumimur igni" is a palindrome.
```


[User]
Mathematically,

* the integers **Z** are included in the rational numbers **Q**,
* which are included in the real numbers **R**,
* which can be generalized to the complex numbers **C**.

This means that each of those larger sets, and the data types used to represent them, include some integers.

Task[edit]

Given a rational, real, or complex number of any type, test whether it is mathematically an integer.

Your code should handle all numeric data types commonly used in your programming language.

Discuss any limitations of your code.

Definition

For the purposes of this task, integerness means that a number could theoretically be represented as an integer at no loss of precision *(given an infinitely wide integer type)*.
In other words:

| Set | Common representation | C++ type | Considered an integer... |
| --- | --- | --- | --- |
| rational numbers **Q** | fraction | `std::ratio` | ...if its denominator is 1 (in reduced form) |
| real numbers **Z** *(approximated)* | fixed-point |  | ...if it has no non-zero digits after the decimal point |
| floating-point | `float`, `double` | ...if the number of significant decimal places of its mantissa isn't greater than its exponent |
| complex numbers **C** | pair of real numbers | `std::complex` | ...if its real part is considered an integer and its imaginary part is zero |

Extra credit

Optionally, make your code accept a `tolerance` parameter for fuzzy testing. The tolerance is the maximum amount by which the number may differ from the nearest integer, to still be considered an integer.

This is useful in practice, because when dealing with approximate numeric types (such as floating point), there may already be round-off errors from previous calculations. For example, a float value of `0.9999999998` might actually be intended to represent the integer `1`.

Test cases

| Input | | Output | | Comment |
| --- | --- | --- | --- | --- |
| Type | Value | exact | tolerance = 0.00001 |
| decimal | `25.000000` | true | |  |
| `24.999999` | false | true |  |
| `25.000100` | false | |  |
| floating-point | `-2.1e120` | true | | This one is tricky, because in most languages it is too large to fit into a native integer type. It is, nonetheless, mathematically an integer, and your code should identify it as such. |
| `-5e-2` | false | |  |
| `NaN` | false | |  |
| `Inf` | false | | This one is debatable. If your code considers it an integer, that's okay too. |
| complex | `5.0+0.0i` | true | |  |
| `5-5i` | false | |  |

(The types and notations shown in these tables are merely examples – you should use the native data types and number literals of your programming language and standard library. Use a different set of test-cases, if this one doesn't demonstrate all relevant behavior.)

---

[Assistant]
(formerly Perl 6)

In Raku, all numeric types have a method called narrow, which returns an object with the same value but of the most appropriate type. So we can just check if *that* object is an Int. This works even with floats with large exponents, because the Int type supports arbitrarily large integers.

For the extra credit task, we can add another multi candidate that checks the distance between the number and it's nearest integer, but then we'll have to handle complex numbers specially.

```
multi is-int ($n) { $n.narrow ~~ Int }

multi is-int ($n, :$tolerance!) {
    abs($n.round - $n) <= $tolerance
}

multi is-int (Complex $n, :$tolerance!) {
    is-int($n.re, :$tolerance) && abs($n.im) < $tolerance
}

# Testing:

for 25.000000, 24.999999, 25.000100, -2.1e120, -5e-2, Inf, NaN, 5.0+0.0i, 5-5i {
    printf "%-7s  %-9s  %-5s  %-5s\n", .^name, $_,
        is-int($_),
        is-int($_, :tolerance<0.00001>);
}

```

Output:

```
Rat      25         True   True
Rat      24.999999  False  True
Rat      25.0001    False  False
Num      -2.1e+120  True   True
Num      -0.05      False  False
Num      Inf        False  False
Num      NaN        False  False
Complex  5+0i       True   True
Complex  5-5i       False  False

```


[User]
Task

Get the text in a string that occurs between a start and end delimiter.
Programs will be given a search string, a start delimiter string, and an end delimiter string. The delimiters will not be unset, and will not be the empty string.

The value returned should be the text in the search string that occurs between the **first** occurrence of the start delimiter (starting after the text of the start delimiter) and the **first** occurrence of the end delimiter after that.

If the start delimiter is not present in the search string, a blank string should be returned.

If the end delimiter is not present after the end of the first occurrence of the start delimiter in the search string, the remainder of the search string after that point should be returned.

There are two special values for the delimiters. If the value of the start delimiter is "start", the beginning of the search string will be matched. If the value of the end delimiter is "end", the end of the search string will be matched.

Example 1. Both delimiters set

```
           Text: "Hello Rosetta Code world"
           Start delimiter: "Hello "
           End delimiter: " world"
           Output: "Rosetta Code"

```

Example 2. Start delimiter is the start of the string

```
           Text: "Hello Rosetta Code world"
           Start delimiter: "start"
           End delimiter: " world"
           Output: "Hello Rosetta Code"

```

Example 3. End delimiter is the end of the string

```
           Text: "Hello Rosetta Code world"
           Start delimiter: "Hello"
           End delimiter: "end"
           Output: "Rosetta Code world"

```

Example 4. End delimiter appears before and after start delimiter

```
           Text: "</div><div style=\"chinese\">你好嗎</div>"
           Start delimiter: "<div style=\"chinese\">"
           End delimiter: "</div>"
           Output: "你好嗎"

```

Example 5. End delimiter not present

```
           Text: "<text>Hello <span>Rosetta Code</span> world</text><table style=\"myTable\">"
           Start delimiter: "<text>"
           End delimiter: "<table>"
           Output: "Hello <span>Rosetta Code</span> world</text><table style=\"myTable\">"

```

Example 6. Start delimiter not present

```
           Text: "<table style=\"myTable\"><tr><td>hello world</td></tr></table>"
           Start delimiter: "<table>"
           End delimiter: "</table>"
           Output: ""

```

Example 7. Multiple instances of end delimiter after start delimiter (match until the first one)

```
           Text: "The quick brown fox jumps over the lazy other fox"
           Start delimiter: "quick "
           End delimiter: " fox"
           Output: "brown"

```

Example 8. Multiple instances of the start delimiter (start matching at the first one)

```
           Text: "One fish two fish red fish blue fish"
           Start delimiter: "fish "
           End delimiter: " red"
           Output: "two fish"

```

Example 9. Start delimiter is end delimiter

```
           Text: "FooBarBazFooBuxQuux"
           Start delimiter: "Foo"
           End delimiter: "Foo"
           Output: "BarBaz"

```

Other tasks related to string operations:

Metrics

* Array length
* String length
* Copy a string
* Empty string  (assignment)

Counting

* Word frequency
* Letter frequency
* Jewels and stones
* I before E except after C
* Bioinformatics/base count
* Count occurrences of a substring
* Count how many vowels and consonants occur in a string

Remove/replace

* XXXX redacted
* Conjugate a Latin verb
* Remove vowels from a string
* String interpolation (included)
* Strip block comments
* Strip comments from a string
* Strip a set of characters from a string
* Strip whitespace from a string -- top and tail
* Strip control codes and extended characters from a string

Anagrams/Derangements/shuffling

* Word wheel
* ABC problem
* Sattolo cycle
* Knuth shuffle
* Ordered words
* Superpermutation minimisation
* Textonyms (using a phone text pad)
* Anagrams
* Anagrams/Deranged anagrams
* Permutations/Derangements

Find/Search/Determine

* ABC words
* Odd words
* Word ladder
* Semordnilap
* Word search
* Wordiff  (game)
* String matching
* Tea cup rim text
* Alternade words
* Changeable words
* State name puzzle
* String comparison
* Unique characters
* Unique characters in each string
* Extract file extension
* Levenshtein distance
* Palindrome detection
* Common list elements
* Longest common suffix
* Longest common prefix
* Compare a list of strings
* Longest common substring
* Find common directory path
* Words from neighbour ones
* Change e letters to i in words
* Non-continuous subsequences
* Longest common subsequence
* Longest palindromic substrings
* Longest increasing subsequence
* Words containing "the" substring
* Sum of the digits of n is substring of n
* Determine if a string is numeric
* Determine if a string is collapsible
* Determine if a string is squeezable
* Determine if a string has all unique characters
* Determine if a string has all the same characters
* Longest substrings without repeating characters
* Find words which contains all the vowels
* Find words which contain the most consonants
* Find words which contains more than 3 vowels
* Find words whose first and last three letters are equal
* Find words with alternating vowels and consonants

Formatting

* Substring
* Rep-string
* Word wrap
* String case
* Align columns
* Literals/String
* Repeat a string
* Brace expansion
* Brace expansion using ranges
* Reverse a string
* Phrase reversals
* Comma quibbling
* Special characters
* String concatenation
* Substring/Top and tail
* Commatizing numbers
* Reverse words in a string
* Suffixation of decimal numbers
* Long literals, with continuations
* Numerical and alphabetical suffixes
* Abbreviations, easy
* Abbreviations, simple
* Abbreviations, automatic

Song lyrics/poems/Mad Libs/phrases

* Mad Libs
* Magic 8-ball
* 99 bottles of beer
* The Name Game (a song)
* The Old lady swallowed a fly
* The Twelve Days of Christmas

Tokenize

* Text between
* Tokenize a string
* Word break problem
* Tokenize a string with escaping
* Split a character string based on change of character

Sequences

* Show ASCII table
* De Bruijn sequences
* Summarize and say sequence
* Generate lower case ASCII alphabet

[Assistant]
(formerly Perl 6)

**Works with**: Rakudo version 2017.12

It seems somewhat pointless to write a special purpose routine to do text matching as built-in primitives can do so more flexibly and concisely, but whatever.

This version doesn't use strings for meta indexes ('start' and 'end'), rather it accepts regex assertions which are parsed differently from strings. This allows much more robust and fine grained control over what does and doesn't match. (and allows delimiter strings of 'start' and 'end' incidentally.) See the 11th example below which will confound nearly all of the current string-only based implementations.

```
sub text-between ( $text, $start, $end ) {
    return $/»[0]».Str if $text ~~ m:g/ $start (.*?) $end /;
    []
}

# Testing
my $text = 'Hello Rosetta Code world';

# String start and end delimiter
put '1> ', $text.&text-between( 'Hello ', ' world' );

# Regex string start delimiter
put '2> ', $text.&text-between( rx/^/, ' world' );

# Regex string end delimiter
put '3> ', $text.&text-between( 'Hello ',  rx/$/ );

# End delimiter only valid after start delimiter
put '4> ', '</div><div style="chinese">你好嗎</div>'\
    .&text-between( '<div style="chinese">', '</div>' );

# End delimiter not found, default to string end
put '5> ', '<text>Hello <span>Rosetta Code</span> world</text><table style="myTable">'\
    .&text-between( '<text>', rx/'<table>' | $/ );

# Start delimiter not found, return blank string
put '6> ', '<table style="myTable"><tr><td>hello world</td></tr></table>'\
    .&text-between( '<table>', '</table>' );

# Multiple end delimiters, match frugally
put '7> ', 'The quick brown fox jumps over the lazy other fox'\
    .&text-between( 'quick ', ' fox' );

# Multiple start delimiters, match frugally
put '8> ', 'One fish two fish red fish blue fish'\
    .&text-between( 'fish ', ' red' );

# Start delimiter is end delimiter
put '9> ', 'FooBarBazFooBuxQuux'\
    .&text-between( 'Foo', 'Foo' );

# Return all matching strings when multiple matches are possible
put '10> ', join ',', $text.&text-between( 'e', 'o' );

# Ignore start and end delimiter string embedded in longer words
put '11> ', 'Soothe a guilty conscience today, string wrangling is not the best tool to use for this job.'\
    .&text-between( rx/«'the '/, rx/' to'»/ );

```

Output:

```
1> Rosetta Code
2> Hello Rosetta Code
3> Rosetta Code world
4> 你好嗎
5> Hello <span>Rosetta Code</span> world</text><table style="myTable">
6>
7> brown
8> two fish
9> BarBaz
10> ll,tta C, w
11> best tool
```


[User]
Task

Write a program that takes in a user inputted word and prints out possible words that are valid in the English dictionary.
Please state any dictionaries or files/binaries/dependencies used in your program. Do show the similarity of the inputted word and outcome as a percentage. Any algorithm can be used to accomplish this task.

Resources

Github Repo
Raw Text, Save as .txt file
Hamming Distance
Jaro-Winkler Distance
SoundEx Algorithm
SoundEx Algorithm Wiki
Dice's Coefficient
Dice Coefficient Wiki

Possible Output

```
Input word:
complition

compaction : 80.00% similar.
completion : 90.00% similar.
completions : 81.82% similar.
complexion : 80.00% similar.

```

Extension

1. How can you make the accuracy of your program higher?

[Assistant]
(formerly Perl 6)

### Hamming distance

**Translation of**: Java

```
sub MAIN ( Str $user_word = 'complition', Str $filename = 'words.txt' ) {
    my @s1 = $user_word.comb;
    my @listed = gather for $filename.IO.lines -> $line {
        my @s2 = $line.comb;

        my $correct = 100 * sum( @s1 Zeq @s2)
                          / max(+@s1,   +@s2);

        my $score = ( $correct >= 100            and @s1[0] eq @s2[0] ) ?? 100
                 !! ( $correct >=  80            and @s1[0] eq @s2[0] ) ?? $correct
                 !! ( $line.contains($user_word) and @s1 * 2 > @s2    ) ?? 80
                 !!                                                        0;
        take [$score, $line] if $score;
    }

    @listed = @listed[$_] with @listed.first: :k, { .[0] == 100 };

    say "{.[0].fmt('%.2f')}% {.[1]}" for @listed;
}

```

Output:

```
80.00% compaction
90.00% completion
81.82% completions
80.00% complexion

```

### Sorenson-Dice

Sorenson-Dice tends to return relatively low percentages even for small differences, especially for short words. We need to "lower the bar" to get any results at all. Different variations of the algorithm do or don't regularize case. This one does, though it doesn't much matter for the tested words.

Using unixdict.txt from www.puzzlers.org

```
sub sorenson ($phrase, %hash) {
    my $match = bigram $phrase;
    %hash.race.map: { [(2 * ($match ∩ .value) / ($match + .value)).round(.001), .key] }
}

sub bigram (\these) { Bag.new( flat these.fc.words.map: { .comb.rotor(2 => -1)».join } ) }

# Load the dictionary
my %hash = './unixdict.txt'.IO.slurp.words.race.map: { $_ => .&bigram };

# Testing
for <complition inconsqual Sørenson> -> $w {
    say "\n$w:";
    .say for sorenson($w, %hash).grep(*.[0] >= .55).sort({-.[0],~.[1]}).head(10);
}

```

Output:

```
complition:
[0.778 completion]
[0.737 competition]
[0.737 composition]
[0.706 coalition]
[0.7 incompletion]
[0.667 complexion]
[0.667 complicity]
[0.667 decomposition]
[0.632 compilation]
[0.632 compunction]

inconsqual:
[0.609 inconsequential]
[0.588 continual]
[0.571 squall]
[0.556 conceptual]
[0.556 inconstant]

Sørenson:
[0.714 sorenson]
[0.667 benson]
[0.615 swenson]
[0.571 evensong]
[0.571 sorensen]
```


[User]
This task has been flagged for clarification. Code on this page in its current state may be flagged incorrect once this task has been clarified. See this page's Talk page for discussion.

Often data is produced by one program, in the wrong format for later use by another program or person. In these situations another program can be written to parse and transform the original data into a format useful to the other. The term "Data Munging" is often used in programming circles for this task.

A request on the comp.lang.awk newsgroup led to a typical data munging task:

```
I have to analyse data files that have the following format:
Each row corresponds to 1 day and the field logic is: $1 is the date,
followed by 24 value/flag pairs, representing measurements at 01:00,
02:00 ... 24:00 of the respective day. In short:

<date> <val1> <flag1> <val2> <flag2> ...  <val24> <flag24>

Some test data is available at:
... (nolonger available at original location)

I have to sum up the values (per day and only valid data, i.e. with
flag>0) in order to calculate the mean. That's not too difficult.
However, I also need to know what the "maximum data gap" is, i.e. the
longest period with successive invalid measurements (i.e values with
flag<=0)
```

The data is free to download and use and is of this format:

Data is no longer available at that link. Zipped mirror available here (offsite mirror).

```
1991-03-30	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1
1991-03-31	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	20.000	1	20.000	1	20.000	1	35.000	1	50.000	1	60.000	1	40.000	1	30.000	1	30.000	1	30.000	1	25.000	1	20.000	1	20.000	1	20.000	1	20.000	1	20.000	1	35.000	1
1991-03-31	40.000	1	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2
1991-04-01	0.000	-2	13.000	1	16.000	1	21.000	1	24.000	1	22.000	1	20.000	1	18.000	1	29.000	1	44.000	1	50.000	1	43.000	1	38.000	1	27.000	1	27.000	1	24.000	1	23.000	1	18.000	1	12.000	1	13.000	1	14.000	1	15.000	1	13.000	1	10.000	1
1991-04-02	8.000	1	9.000	1	11.000	1	12.000	1	12.000	1	12.000	1	27.000	1	26.000	1	27.000	1	33.000	1	32.000	1	31.000	1	29.000	1	31.000	1	25.000	1	25.000	1	24.000	1	21.000	1	17.000	1	14.000	1	15.000	1	12.000	1	12.000	1	10.000	1
1991-04-03	10.000	1	9.000	1	10.000	1	10.000	1	9.000	1	10.000	1	15.000	1	24.000	1	28.000	1	24.000	1	18.000	1	14.000	1	12.000	1	13.000	1	14.000	1	15.000	1	14.000	1	15.000	1	13.000	1	13.000	1	13.000	1	12.000	1	10.000	1	10.000	1

```

Only a sample of the data showing its format is given above. The full example file may be downloaded here.

Structure your program to show statistics for each line of the file, (similar to the original Python, Perl, and AWK examples below), followed by summary statistics for the file. When showing example output just show a few line statistics and the full end summary.

[Assistant]
(formerly Perl 6)

```
my @gaps;
my $previous = 'valid';

for $*IN.lines -> $line {
    my ($date, @readings) = split /\s+/, $line;
    my @valid;
    my $hour = 0;
    for @readings -> $reading, $flag {
        if $flag > 0 {
            @valid.push($reading);
            if $previous eq 'invalid' {
                @gaps[*-1]{'end'} = "$date $hour:00";
                $previous = 'valid';
            }
        }
        else
        {
            if $previous eq 'valid' {
                @gaps.push( {start => "$date $hour:00"} );
            }
            @gaps[*-1]{'count'}++;
            $previous = 'invalid';
        }
        $hour++;
    }
    say "$date: { ( +@valid ?? ( ( [+] @valid ) / +@valid ).fmt("%.3f") !! 0 ).fmt("%8s") }",
        " mean from { (+@valid).fmt("%2s") } valid.";
};

my $longest = @gaps.sort({-$^a<count>})[0];

say "Longest period of invalid readings was {$longest<count>} hours,\n",
    "from {$longest<start>} till {$longest<end>}."

```

Output:

```
1990-01-01:   26.818 mean from 22 valid.
1990-01-02:   17.083 mean from 24 valid.
1990-01-03:   58.958 mean from 24 valid.
1990-01-04:   75.000 mean from 24 valid.
1990-01-05:   47.083 mean from 24 valid.
...
(many lines omitted)
...
2004-12-27:    2.483 mean from 23 valid.
2004-12-28:    3.383 mean from 23 valid.
2004-12-29:    2.448 mean from 23 valid.
2004-12-30:    2.839 mean from 23 valid.
2004-12-31:    2.057 mean from 23 valid.
Longest period of invalid readings was 589 hours,
from 1993-02-09 1:00 till 1993-03-05 14:00.

```


[User]
The following task concerns data that came from a pollution monitoring station with twenty-four instruments monitoring twenty-four aspects of pollution in the air. Periodically a record is added to the file, each record being a line of 49 fields separated by white-space, which can be one or more space or tab characters.

The fields (from the left) are:

```
 DATESTAMP [ VALUEn FLAGn ] * 24

```

i.e. a datestamp followed by twenty-four repetitions of a floating-point instrument value and that instrument's associated integer flag. Flag values are >= 1 if the instrument is working and < 1 if there is some problem with it, in which case that instrument's value should be ignored.

A sample from the full data file readings.txt, which is also used in the Text processing/1 task, follows:

Data is no longer available at that link. Zipped mirror available here

```
1991-03-30	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1
1991-03-31	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	10.000	1	20.000	1	20.000	1	20.000	1	35.000	1	50.000	1	60.000	1	40.000	1	30.000	1	30.000	1	30.000	1	25.000	1	20.000	1	20.000	1	20.000	1	20.000	1	20.000	1	35.000	1
1991-03-31	40.000	1	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2	0.000	-2
1991-04-01	0.000	-2	13.000	1	16.000	1	21.000	1	24.000	1	22.000	1	20.000	1	18.000	1	29.000	1	44.000	1	50.000	1	43.000	1	38.000	1	27.000	1	27.000	1	24.000	1	23.000	1	18.000	1	12.000	1	13.000	1	14.000	1	15.000	1	13.000	1	10.000	1
1991-04-02	8.000	1	9.000	1	11.000	1	12.000	1	12.000	1	12.000	1	27.000	1	26.000	1	27.000	1	33.000	1	32.000	1	31.000	1	29.000	1	31.000	1	25.000	1	25.000	1	24.000	1	21.000	1	17.000	1	14.000	1	15.000	1	12.000	1	12.000	1	10.000	1
1991-04-03	10.000	1	9.000	1	10.000	1	10.000	1	9.000	1	10.000	1	15.000	1	24.000	1	28.000	1	24.000	1	18.000	1	14.000	1	12.000	1	13.000	1	14.000	1	15.000	1	14.000	1	15.000	1	13.000	1	13.000	1	13.000	1	12.000	1	10.000	1	10.000	1

```

Task

1. Confirm the general field format of the file.
2. Identify any DATESTAMPs that are duplicated.
3. Report the number of records that have good readings for all instruments.

[Assistant]
(formerly Perl 6)

**Translation of**: Perl

**Works with**: Rakudo version 2018.03

This version does validation with a single Raku regex that is much more readable than the typical regex, and arguably expresses the data structure more straightforwardly.
Here we use normal quotes for literals, and \h for horizontal whitespace.

Variables like $good-record that are going to be autoincremented do not need to be initialized.

The .push method on a hash is magical and loses no information; if a duplicate key is found in the pushed pair, an array of values is automatically created of the old value and the new value pushed. Hence we can easily track all the lines that a particular duplicate occurred at.

The .all method does "junctional" logic: it autothreads through comparators as any English speaker would expect. Junctions can also short-circuit as soon as they find a value that doesn't match, and the evaluation order is up to the computer, so it can be optimized or parallelized.

The final line simply greps out the pairs from the hash whose value is an array with more than 1 element. (Those values that are not arrays nevertheless have a .elems method that always reports 1.) The .pairs is merely there for clarity; grepping a hash directly has the same effect.
Note that we sort the pairs after we've grepped them, not before; this works fine in Raku, sorting on the key and value as primary and secondary keys. Finally, pairs and arrays provide a default print format that is sufficient without additional formatting in this case.

```
my $good-records;
my $line;
my %dates;

for lines() {
    $line++;
    / ^
    (\d ** 4 '-' \d\d '-' \d\d)
    [ \h+ \d+'.'\d+ \h+ ('-'?\d+) ] ** 24
    $ /
        or note "Bad format at line $line" and next;
    %dates.push: $0 => $line;
    $good-records++ if $1.all >= 1;
}

say "$good-records good records out of $line total";

say 'Repeated timestamps (with line numbers):';
.say for sort %dates.pairs.grep: *.value.elems > 1;

```

Output:

```
5017 good records out of 5471 total
Repeated timestamps (with line numbers):
1990-03-25 => [84 85]
1991-03-31 => [455 456]
1992-03-29 => [819 820]
1993-03-28 => [1183 1184]
1995-03-26 => [1910 1911]
```


[User]
A company currently pays a fixed sum for the use of a particular licensed software package.   In determining if it has a good deal it decides to calculate its maximum use of the software from its license management log file.

Assume the software's licensing daemon faithfully records a checkout event when a copy of the software starts and a checkin event when the software finishes to its log file.

An example of checkout and checkin events are:

```
 License OUT @ 2008/10/03_23:51:05 for job 4974
 ...
 License IN  @ 2008/10/04_00:18:22 for job 4974

```

Task

Save the 10,000 line log file from   here   into a local file, then write a program to scan the file extracting both the maximum licenses that were out at any time, and the time(s) at which this occurs.

Mirror of log file available as a zip here (offsite mirror).

[Assistant]
(formerly Perl 6)
Add some error trapping as recommended by Dijkstra. Not particularly necessary for this specific example but it doesn't hurt to be proactive.

Redirecting the mlijobs.txt file to STDIN:

```
my %licenses;

%licenses<count max> = 0,0;

for $*IN.lines -> $line {
    my ( $license, $date_time );
    ( *, $license, *, $date_time ) = split /\s+/, $line;
    if $license eq 'OUT' {
        %licenses<count>++;
        if %licenses<count> > %licenses<max> {
            %licenses<max>   = %licenses<count>;
            %licenses<times> = [$date_time];
        }
        elsif %licenses<count> == %licenses<max> {
            %licenses<times>.push($date_time);
        }
    }
    elsif $license eq 'IN' {
        if %licenses<count> == %licenses<max> {
            %licenses<times>[*-1] ~= " through " ~ $date_time;
        }
        %licenses<count>--;
    }
    else {
        # Not a licence OUT or IN event, do nothing
    }
};

my $plural = %licenses<times>.elems == 1 ?? '' !! 's';

say "Maximum concurrent licenses in use: {%licenses<max>}, in the time period{$plural}:";
say join ",\n", %licenses<times>.list;

```

Example output:

```
Maximum concurrent licenses in use: 99, in the time periods:
2008/10/03_08:39:34 through 2008/10/03_08:39:45,
2008/10/03_08:40:40 through 2008/10/03_08:40:47

```


[User]
When developing a Website it is occasionally necessary to handle text that is received without formatting, and present it in a pleasing manner. to achieve this the text needs to be converted to HTML.

Write a converter from plain text to HTML.

The plain text has no formatting information.

It may have centered headlines, numbered sections, paragraphs, lists, and URIs. It could even have tables.

Simple converters restrict themselves at identifying paragraphs, but i believe more can be done if the text is analyzed.

You are not requested to copy the algorithm from the existing solutions but use whatever faculties available in your language to best solve the problem.

The only requirement is to ensure that the result is valid xhtml.

[Assistant]
(formerly Perl 6)

**Works with**: Rakudo version 2019.11

The task specs are essentially non-existent. "Make a best guess at how to render mark-up free text"? Anything that could be trusted at all would either be extremely trivial or insanely complex. And it shows by the the task example writers staying away in droves. Five examples after seven years!?

Rather than waste time on that noise, I'll demonstrate POD6 to HTML conversion. POD6 is a simple, text-only mark-up used for Raku documentation. (It's Plain Old Documentation for Raku) It uses pretty simple textual markup and has multiple tools to convert the POD6 document in to many other formats, HTML among them.

It is **not** markup free, but it is actually usable in production.

```
use Pod::To::HTML;
use HTML::Escape;

my $pod6 = q:to/POD6/;
=begin pod

A very simple Pod6 document.

This is a very high-level, hand-wavey overview. There are I<lots> of other
options available.

=head1 Section headings

=head1 A top level heading

=head2 A second level heading

=head3 A third level heading

=head4 A fourth level heading

=head1 Text

Ordinary paragraphs do not require an explicit marker or delimiters.

Alternatively, there is also an explicit =para marker that can be used to
explicitly mark a paragraph.

=para
This is an ordinary paragraph.
Its text  will   be     squeezed     and
short lines filled.

=head1 Code

Enclose code in a =code block (or V<C< >> markup for short, inline samples)

=begin code
    my $name = 'Rakudo';
    say $name;
=end code

=head1 Lists

=head3 Unordered lists

=item  Grumpy
=item  Dopey
=item  Doc
=item  Happy
=item  Bashful
=item  Sneezy
=item  Sleepy

=head3 Multi-level lists

=item1  Animal
=item2  Vertebrate
=item2  Invertebrate

=item1  Phase
=item2  Solid
=item2  Liquid
=item2  Gas

=head1 Formatting codes

Formatting codes provide a way to add inline mark-up to a piece of text.

All Pod6 formatting codes consist of a single capital letter followed
immediately by a set of single or double angle brackets; Unicode double angle
brackets may be used.

Formatting codes may nest other formatting codes.

There are many formatting codes available, some of the more common ones:

=item1 V<B< >> Bold
=item1 V<I< >> Italic
=item1 V<U< >> Underline
=item1 V<C< >> Code
=item1 V<L< >> Hyperlink
=item1 V<V< >> Verbatim (Don't interpret anything inside as POD markup)

=head1 Tables

There is quite extensive markup to allow rendering tables.

A simple example:

=begin table :caption<Mystery Men>
        The Shoveller   Eddie Stevens     King Arthur's singing shovel
        Blue Raja       Geoffrey Smith    Master of cutlery
        Mr Furious      Roy Orson         Ticking time bomb of fury
        The Bowler      Carol Pinnsler    Haunted bowling ball
=end table

=end pod
POD6

# for display on Rosettacode
say escape-html render($pod6);

# normally
#say render($pod6);

```

Returns something like:

```
<!doctype html>
<html lang="en">
    <head>
        <title></title>
        <meta charset="UTF-8" />
        <style>
        kbd { font-family: "Droid Sans Mono", "Luxi Mono", "Inconsolata", monospace }
        samp { font-family: "Terminus", "Courier", "Lucida Console", monospace }
        u { text-decoration: none }
        .nested {
            margin-left: 3em;
        }
        aside, u { opacity: 0.7 }
        a[id^="fn-"]:target { background: #ff0 }
        </style>
        <link rel="stylesheet" href="//design.raku.org/perl.css">

    </head>
    <body class="pod">
    <div id="___top"></div>

    <nav class="indexgroup">
<table id="TOC">
<caption><h2 id="TOC_Title">Table of Contents</h2></caption>
    <tr class="toc-level-1"><td class="toc-number">1</td><td class="toc-text"><a href="#Section_headings">Section headings</a></td></tr>
 <tr class="toc-level-1"><td class="toc-number">2</td><td class="toc-text"><a href="#A_top_level_heading">A top level heading</a></td></tr>
 <tr class="toc-level-2"><td class="toc-number">2.1</td><td class="toc-text"><a href="#A_second_level_heading">A second level heading</a></td></tr>
 <tr class="toc-level-3"><td class="toc-number">2.1.1</td><td class="toc-text"><a href="#A_third_level_heading">A third level heading</a></td></tr>
 <tr class="toc-level-4"><td class="toc-number">2.1.1.1</td><td class="toc-text"><a href="#A_fourth_level_heading">A fourth level heading</a></td></tr>
 <tr class="toc-level-1"><td class="toc-number">3</td><td class="toc-text"><a href="#Text">Text</a></td></tr>
    <tr class="toc-level-1"><td class="toc-number">4</td><td class="toc-text"><a href="#Code">Code</a></td></tr>
      <tr class="toc-level-1"><td class="toc-number">5</td><td class="toc-text"><a href="#Lists">Lists</a></td></tr>
 <tr class="toc-level-3"><td class="toc-number">5.0.1</td><td class="toc-text"><a href="#Unordered_lists">Unordered lists</a></td></tr>
        <tr class="toc-level-3"><td class="toc-number">5.0.2</td><td class="toc-text"><a href="#Multi-level_lists">Multi-level lists</a></td></tr>
        <tr class="toc-level-1"><td class="toc-number">6</td><td class="toc-text"><a href="#Formatting_codes">Formatting codes</a></td></tr>
           <tr class="toc-level-1"><td class="toc-number">7</td><td class="toc-text"><a href="#Tables">Tables</a></td></tr>

</table>
</nav>

    <div class="pod-body">
    <p>A very simple Pod6 document.</p>
<p>This is a very high-level, hand-wavey overview. There are <em>lots</em> of other options available.</p>
<h1 id="Section_headings"><a class="u" href="#___top" title="go to top of document">Section headings</a></h1>
<h1 id="A_top_level_heading"><a class="u" href="#___top" title="go to top of document">A top level heading</a></h1>
<h2 id="A_second_level_heading"><a class="u" href="#___top" title="go to top of document">A second level heading</a></h2>
<h3 id="A_third_level_heading"><a class="u" href="#___top" title="go to top of document">A third level heading</a></h3>
<h4 id="A_fourth_level_heading"><a class="u" href="#___top" title="go to top of document">A fourth level heading</a></h4>
<h1 id="Text"><a class="u" href="#___top" title="go to top of document">Text</a></h1>
<p>Ordinary paragraphs do not require an explicit marker or delimiters.</p>
<p>Alternatively, there is also an explicit =para marker that can be used to explicitly mark a paragraph.</p>
<p>This is an ordinary paragraph. Its text will be squeezed and short lines filled.</p>
<h1 id="Code"><a class="u" href="#___top" title="go to top of document">Code</a></h1>
<p>Enclose code in a =code block (or C< > markup for short, inline samples)</p>
<pre class="pod-block-code">    my $name = 'Rakudo';
    say $name;
</pre>
<h1 id="Lists"><a class="u" href="#___top" title="go to top of document">Lists</a></h1>
<h3 id="Unordered_lists"><a class="u" href="#___top" title="go to top of document">Unordered lists</a></h3>
<ul><li><p>Grumpy</p>
</li>
<li><p>Dopey</p>
</li>
<li><p>Doc</p>
</li>
<li><p>Happy</p>
</li>
<li><p>Bashful</p>
</li>
<li><p>Sneezy</p>
</li>
<li><p>Sleepy</p>
</li>
</ul>
<h3 id="Multi-level_lists"><a class="u" href="#___top" title="go to top of document">Multi-level lists</a></h3>
<ul><li><p>Animal</p>
</li>
<ul><li><p>Vertebrate</p>
</li>
<li><p>Invertebrate</p>
</li>
</ul>
<li><p>Phase</p>
</li>
<ul><li><p>Solid</p>
</li>
<li><p>Liquid</p>
</li>
<li><p>Gas</p>
</li>
</ul>
</ul>
<h1 id="Formatting_codes"><a class="u" href="#___top" title="go to top of document">Formatting codes</a></h1>
<p>Formatting codes provide a way to add inline mark-up to a piece of text.</p>
<p>All Pod6 formatting codes consist of a single capital letter followed immediately by a set of single or double angle brackets; Unicode double angle brackets may be used.</p>
<p>Formatting codes may nest other formatting codes.</p>
<p>There are many formatting codes available, some of the more common ones:</p>
<ul><li><p>B< > Bold</p>
</li>
<li><p>I< > Italic</p>
</li>
<li><p>U< > Underline</p>
</li>
<li><p>C< > Code</p>
</li>
<li><p>L< > Hyperlink</p>
</li>
<li><p>V< > Verbatim (Don't interpret anything inside as POD markup)</p>
</li>
</ul>
<h1 id="Tables"><a class="u" href="#___top" title="go to top of document">Tables</a></h1>
<p>There is quite extensive markup to allow rendering tables.</p>
<p>A simple example:</p>
<table class="pod-table">
<caption>Mystery Men</caption>
<tbody>
<tr> <td>The Shoveller</td> <td>Eddie Stevens</td> <td>King Arthur's singing shovel</td> </tr> <tr> <td>Blue Raja</td> <td>Geoffrey Smith</td> <td>Master of cutlery</td> </tr> <tr> <td>Mr Furious</td> <td>Roy Orson</td> <td>Ticking time bomb of fury</td> </tr> <tr> <td>The Bowler</td> <td>Carol Pinnsler</td> <td>Haunted bowling ball</td> </tr>
</tbody>
</table>
    </div>

    </body>
</html>
```


[User]
When entering text on a phone's digital pad it is possible that a particular combination of digits corresponds to more than one word. Such are called textonyms.

Assuming the digit keys are mapped to letters as follows:

```
    2 -> ABC
    3 -> DEF
    4 -> GHI
    5 -> JKL
    6 -> MNO
    7 -> PQRS
    8 -> TUV
    9 -> WXYZ

```

Task

Write a program that finds textonyms in a list of words such as
Textonyms/wordlist   or
unixdict.txt.

The task should produce a report:

```
There are #{0} words in #{1} which can be represented by the digit key mapping.
They require #{2} digit combinations to represent them.
#{3} digit combinations represent Textonyms.

```

Where:

```
#{0} is the number of words in the list which can be represented by the digit key mapping.
#{1} is the URL of the wordlist being used.
#{2} is the number of digit combinations required to represent the words in #{0}.
#{3} is the number of #{2} which represent more than one word.

```

At your discretion show a couple of examples of your solution displaying Textonyms.

E.G.:

```
 2748424767 -> "Briticisms", "criticisms"

```

Extra credit

Use a word list and keypad mapping other than English.

Other tasks related to string operations:

Metrics

* Array length
* String length
* Copy a string
* Empty string  (assignment)

Counting

* Word frequency
* Letter frequency
* Jewels and stones
* I before E except after C
* Bioinformatics/base count
* Count occurrences of a substring
* Count how many vowels and consonants occur in a string

Remove/replace

* XXXX redacted
* Conjugate a Latin verb
* Remove vowels from a string
* String interpolation (included)
* Strip block comments
* Strip comments from a string
* Strip a set of characters from a string
* Strip whitespace from a string -- top and tail
* Strip control codes and extended characters from a string

Anagrams/Derangements/shuffling

* Word wheel
* ABC problem
* Sattolo cycle
* Knuth shuffle
* Ordered words
* Superpermutation minimisation
* Textonyms (using a phone text pad)
* Anagrams
* Anagrams/Deranged anagrams
* Permutations/Derangements

Find/Search/Determine

* ABC words
* Odd words
* Word ladder
* Semordnilap
* Word search
* Wordiff  (game)
* String matching
* Tea cup rim text
* Alternade words
* Changeable words
* State name puzzle
* String comparison
* Unique characters
* Unique characters in each string
* Extract file extension
* Levenshtein distance
* Palindrome detection
* Common list elements
* Longest common suffix
* Longest common prefix
* Compare a list of strings
* Longest common substring
* Find common directory path
* Words from neighbour ones
* Change e letters to i in words
* Non-continuous subsequences
* Longest common subsequence
* Longest palindromic substrings
* Longest increasing subsequence
* Words containing "the" substring
* Sum of the digits of n is substring of n
* Determine if a string is numeric
* Determine if a string is collapsible
* Determine if a string is squeezable
* Determine if a string has all unique characters
* Determine if a string has all the same characters
* Longest substrings without repeating characters
* Find words which contains all the vowels
* Find words which contain the most consonants
* Find words which contains more than 3 vowels
* Find words whose first and last three letters are equal
* Find words with alternating vowels and consonants

Formatting

* Substring
* Rep-string
* Word wrap
* String case
* Align columns
* Literals/String
* Repeat a string
* Brace expansion
* Brace expansion using ranges
* Reverse a string
* Phrase reversals
* Comma quibbling
* Special characters
* String concatenation
* Substring/Top and tail
* Commatizing numbers
* Reverse words in a string
* Suffixation of decimal numbers
* Long literals, with continuations
* Numerical and alphabetical suffixes
* Abbreviations, easy
* Abbreviations, simple
* Abbreviations, automatic

Song lyrics/poems/Mad Libs/phrases

* Mad Libs
* Magic 8-ball
* 99 bottles of beer
* The Name Game (a song)
* The Old lady swallowed a fly
* The Twelve Days of Christmas

Tokenize

* Text between
* Tokenize a string
* Word break problem
* Tokenize a string with escaping
* Split a character string based on change of character

Sequences

* Show ASCII table
* De Bruijn sequences
* Summarize and say sequence
* Generate lower case ASCII alphabet

[Assistant]
(formerly Perl 6)

```
my $src = 'unixdict.txt';

my @words = slurp($src).lines.grep(/ ^ <alpha>+ $ /);

my @dials = @words.classify: {
    .trans('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
        => '2223334445556667777888999922233344455566677778889999');
}

my @textonyms = @dials.grep(*.value > 1);

say qq:to 'END';
    There are {+@words} words in $src which can be represented by the digit key mapping.
    They require {+@dials} digit combinations to represent them.
    {+@textonyms} digit combinations represent Textonyms.
    END

say "Top 5 in ambiguity:";
say "    ",$_ for @textonyms.sort(-*.value)[^5];

say "\nTop 5 in length:";
say "    ",$_ for @textonyms.sort(-*.key.chars)[^5];

```

Output:

```
There are 24978 words in unixdict.txt which can be represented by the digit key mapping.
They require 22903 digit combinations to represent them.
1473 digit combinations represent Textonyms.

Top 5 in ambiguity:
    269 => amy any bmw bow box boy cow cox coy
    729 => paw pax pay paz raw ray saw sax say
    2273 => acre bard bare base cape card care case
    726 => pam pan ram ran sam san sao scm
    426 => gam gao ham han ian ibm ibn

Top 5 in length:
    25287876746242 => claustrophobia claustrophobic
    7244967473642 => schizophrenia schizophrenic
    666628676342 => onomatopoeia onomatopoeic
    49376746242 => hydrophobia hydrophobic
    2668368466 => contention convention
```


[User]
ISAAC is a cryptographically secure pseudo-random number generator (CSPRNG) and stream cipher. It was developed by Bob Jenkins from 1993 (http://burtleburtle.net/bob/rand/isaac.html) and placed in the Public Domain. ISAAC is fast - especially when optimised - and portable to most architectures in nearly all programming and scripting languages.
It is also simple and succinct, using as it does just two 256-word arrays for its state.

ISAAC stands for "Indirection, Shift, Accumulate, Add, and Count" which are the principal bitwise operations employed.
To date - and that's after more than 20 years of existence - ISAAC has not been broken (unless GCHQ or NSA did it, but they wouldn't be telling).
ISAAC thus deserves a lot more attention than it has hitherto received and it would be salutary to see it more universally implemented.

Task

Translate ISAAC's reference C or Pascal code into your language of choice.

The RNG should then be seeded with the string "this is my secret key" and
finally the message "a Top Secret secret" should be encrypted on that key.
Your program's output cipher-text will be a string of hexadecimal digits.

Optional: Include a decryption check by re-initializing ISAAC and performing
the same encryption pass on the cipher-text.

Please use the C or Pascal as a reference guide to these operations.

Two encryption schemes are possible:
(1) XOR (Vernam) or
(2) Caesar-shift mod 95 (Vigenère).
XOR is the simplest; C-shifting offers greater security.

You may choose either scheme, or both, but please specify which you used.
Here are the alternative sample outputs for checking purposes:

```
Message: a Top Secret secret
Key    : this is my secret key
XOR    : 1C0636190B1260233B35125F1E1D0E2F4C5422
MOD    : 734270227D36772A783B4F2A5F206266236978
XOR dcr: a Top Secret secret
MOD dcr: a Top Secret secret

```

No official seeding method for ISAAC has been published, but for this task
we may as well just inject the bytes of our key into the randrsl array,
padding with zeroes before mixing, like so:

```
// zeroise mm array
FOR i:= 0 TO 255 DO mm[i]:=0;
// check seed's highest array element
m := High(seed);
// inject the seed
FOR i:= 0 TO 255 DO BEGIN
	// in case seed[] has less than 256 elements.
	IF i>m THEN randrsl[i]:=0
		ELSE randrsl[i]:=seed[i];
END;
// initialize ISAAC with seed
RandInit(true);

```

ISAAC can of course also be initialized with a single 32-bit unsigned integer in the manner of traditional RNGs, and indeed used as such for research and gaming purposes.
But building a strong and simple ISAAC-based stream cipher - replacing the irreparably broken RC4 - is our goal here: ISAAC's intended purpose.

[Assistant]
(formerly Perl 6)

```
my uint32 (@mm, @randrsl, $randcnt, $aa, $bb, $cc);
my \ϕ := 2654435769; constant MOD = 95; constant START = 32;

constant MAXINT = uint.Range.max;
enum CipherMode < ENCIPHER DECIPHER NONE >;

sub mix (\n) {
   sub mix1 (\i, \v) {
      n[i] +^= v;
      n[(i+3)%8] += n[i];
      n[(i+1)%8] += n[(i+2)%8];
   }
   mix1 0, n[1]+<11; mix1 1, n[2]+>2; mix1 2, n[3]+<8; mix1 3, n[4]+>16;
   mix1 4, n[5]+<10; mix1 5, n[6]+>4; mix1 6, n[7]+<8; mix1 7, n[0]+>9 ;
}

sub randinit(\flag) {
   $aa = $bb = $cc = 0;
   my uint32 @n = [^8].map({ ϕ });
   for ^4 { mix @n };
   for 0,8 … 255 -> $i {
      { for (0..7) { @n[$^j] += @randrsl[$i + $^j] } } if flag;
      mix @n;
      for (0..7) { @mm[$i + $^j] = @n[$^j] }
   }
   if flag {
      for 0,8 … 255 -> $i {
         for ^8 { @n[$^j] += @mm[$i + $^j] };
         mix @n;
         for ^8 { @mm[$i + $^j] = @n[$^j] };
      }
   }
   isaac;
   $randcnt = 0;
}

sub isaac() {
   $cc++;
   $bb += $cc;
   for ^256 -> $i {
      my $x = @mm[$i];
      given ($i % 4) {
         when 0 { $aa +^= ($aa +< 13) }
         when 1 { $aa +^= (($aa +& MAXINT) +>  6) }
         when 2 { $aa +^= ($aa +<  2) }
         when 3 { $aa +^= (($aa +& MAXINT) +> 16) }
      }
      $aa += @mm[($i + 128) % 256];
      my $y = @mm[(($x +& MAXINT) +> 2) % 256] + $aa + $bb;
      @mm[$i] = $y;
      $bb = @mm[(($y +& MAXINT) +> 10) % 256] + $x;
      @randrsl[$i] = $bb;
   }
   $randcnt = 0;
}

sub iRandom {
   my $result = @randrsl[$randcnt++];
   if ($randcnt > 255) {
      isaac;
      $randcnt = 0;
   }
   return $result;
}

sub iSeed(\seed, \flag) {
    @mm = [^256].race.map({0});
    my \m = seed.chars;
    @randrsl = [^256].hyper.map({ $^i ≥ m ?? 0 !! seed.substr($^i,1).ord });
    randinit(flag);
}

sub iRandA { return iRandom() % MOD + START };

sub vernam(\M) { ( map { (iRandA() +^ .ord ).chr }, M.comb ).join };

sub caesar(CipherMode \m, \ch, $shift is copy, \Modulo, \Start) {
    $shift = -$shift if m == DECIPHER;
    my $n = (ch.ord - Start) + $shift;
    $n %= Modulo;
    $n += Modulo if $n < 0;
    return (Start + $n).chr;
}

sub caesarStr(CipherMode \m, \msg, \Modulo, \Start) {
   my $sb = '';
   for msg.comb {
        $sb ~= caesar m, $^c, iRandA(), Modulo, Start;
   }
   return $sb;
}

multi MAIN () {
   my \msg = "a Top Secret secret";
   my \key = "this is my secret key";

   iSeed key, True ;
   my $vctx = vernam msg;
   my $cctx = caesarStr ENCIPHER, msg,  MOD, START;

   iSeed key, True ;
   my $vptx = vernam $vctx;
   my $cptx = caesarStr DECIPHER, $cctx, MOD, START;

   my $vctx2hex = ( map { .ord.fmt('%02X') }, $vctx.comb ).join('');
   my $cctx2hex = ( map { .ord.fmt('%02X') }, $cctx.comb ).join('');

   say "Message : ", msg;
   say "Key     : ", key;
   say "XOR     : ", $vctx2hex;
   say "XOR dcr : ", $vptx;
   say "MOD     : ", $cctx2hex;
   say "MOD dcr : ", $cptx;
}

```

Output:

```
Message : a Top Secret secret
Key     : this is my secret key
XOR     : 1C0636190B1260233B35125F1E1D0E2F4C5422
XOR dcr : a Top Secret secret
MOD     : 734270227D36772A783B4F2A5F206266236978
MOD dcr : a Top Secret secret

```


[User]
Write a program that accepts a name as input and outputs the lyrics to the Shirley Ellis song "The Name Game".

The regular verse

Unless your name begins with a vowel (A, E, I, O, U), 'B', 'F' or 'M' you don't have to care about special rules.
The verse for the name 'Gary' would be like this:

```
   Gary, Gary, bo-bary
   Banana-fana fo-fary
   Fee-fi-mo-mary
   Gary!

```

At the end of every line, the name gets repeated without the first letter: Gary becomes ary
If we take (X) as the full name (Gary) and (Y) as the name without the first letter (ary) the verse would look like this:

```
   (X), (X), bo-b(Y)
   Banana-fana fo-f(Y)
   Fee-fi-mo-m(Y)
   (X)!

```

Vowel as first letter of the name

If you have a vowel as the first letter of your name (e.g. Earl) you do not truncate the name.
The verse looks like this:

```
   Earl, Earl, bo-bearl
   Banana-fana fo-fearl
   Fee-fi-mo-mearl
   Earl!

```

'B', 'F' or 'M' as first letter of the name

In case of a 'B', an 'F' or an 'M' (e.g. Billy, Felix, Mary) there is a special rule.
The line which would 'rebuild' the name (e.g. bo-billy) is sung without the first letter of the name.
The verse for the name Billy looks like this:

```
   Billy, Billy, bo-illy
   Banana-fana fo-filly
   Fee-fi-mo-milly
   Billy!

```

For the name 'Felix', this would be right:

```
   Felix, Felix, bo-belix
   Banana-fana fo-elix
   Fee-fi-mo-melix
   Felix!

```

Other tasks related to string operations:

Metrics

* Array length
* String length
* Copy a string
* Empty string  (assignment)

Counting

* Word frequency
* Letter frequency
* Jewels and stones
* I before E except after C
* Bioinformatics/base count
* Count occurrences of a substring
* Count how many vowels and consonants occur in a string

Remove/replace

* XXXX redacted
* Conjugate a Latin verb
* Remove vowels from a string
* String interpolation (included)
* Strip block comments
* Strip comments from a string
* Strip a set of characters from a string
* Strip whitespace from a string -- top and tail
* Strip control codes and extended characters from a string

Anagrams/Derangements/shuffling

* Word wheel
* ABC problem
* Sattolo cycle
* Knuth shuffle
* Ordered words
* Superpermutation minimisation
* Textonyms (using a phone text pad)
* Anagrams
* Anagrams/Deranged anagrams
* Permutations/Derangements

Find/Search/Determine

* ABC words
* Odd words
* Word ladder
* Semordnilap
* Word search
* Wordiff  (game)
* String matching
* Tea cup rim text
* Alternade words
* Changeable words
* State name puzzle
* String comparison
* Unique characters
* Unique characters in each string
* Extract file extension
* Levenshtein distance
* Palindrome detection
* Common list elements
* Longest common suffix
* Longest common prefix
* Compare a list of strings
* Longest common substring
* Find common directory path
* Words from neighbour ones
* Change e letters to i in words
* Non-continuous subsequences
* Longest common subsequence
* Longest palindromic substrings
* Longest increasing subsequence
* Words containing "the" substring
* Sum of the digits of n is substring of n
* Determine if a string is numeric
* Determine if a string is collapsible
* Determine if a string is squeezable
* Determine if a string has all unique characters
* Determine if a string has all the same characters
* Longest substrings without repeating characters
* Find words which contains all the vowels
* Find words which contain the most consonants
* Find words which contains more than 3 vowels
* Find words whose first and last three letters are equal
* Find words with alternating vowels and consonants

Formatting

* Substring
* Rep-string
* Word wrap
* String case
* Align columns
* Literals/String
* Repeat a string
* Brace expansion
* Brace expansion using ranges
* Reverse a string
* Phrase reversals
* Comma quibbling
* Special characters
* String concatenation
* Substring/Top and tail
* Commatizing numbers
* Reverse words in a string
* Suffixation of decimal numbers
* Long literals, with continuations
* Numerical and alphabetical suffixes
* Abbreviations, easy
* Abbreviations, simple
* Abbreviations, automatic

Song lyrics/poems/Mad Libs/phrases

* Mad Libs
* Magic 8-ball
* 99 bottles of beer
* The Name Game (a song)
* The Old lady swallowed a fly
* The Twelve Days of Christmas

Tokenize

* Text between
* Tokenize a string
* Word break problem
* Tokenize a string with escaping
* Split a character string based on change of character

Sequences

* Show ASCII table
* De Bruijn sequences
* Summarize and say sequence
* Generate lower case ASCII alphabet

[Assistant]
(formerly Perl 6)

**Works with**: Rakudo version 2018.03

Meh. The rules leave out some corner cases (see Steve) but what the heck, technically correct is the best kind of correct.

```
sub mangle ($name, $initial) {
    my $fl = $name.lc.substr(0,1);
    $fl ~~ /<[aeiou]>/
    ?? $initial~$name.lc
    !! $fl eq $initial
    ?? $name.substr(1)
    !! $initial~$name.substr(1)
}

sub name-game (Str $name) {
    qq:to/NAME-GAME/;
    $name, $name, bo-{ mangle $name, 'b' }
    Banana-fana fo-{ mangle $name, 'f' }
    Fee-fi-mo-{ mangle $name, 'm' }
    $name!
    NAME-GAME
}

say .&name-game for <Gary Earl Billy Felix Mike Steve>

```

Output:

```
Gary, Gary, bo-bary
Banana-fana fo-fary
Fee-fi-mo-mary
Gary!

Earl, Earl, bo-bearl
Banana-fana fo-fearl
Fee-fi-mo-mearl
Earl!

Billy, Billy, bo-illy
Banana-fana fo-filly
Fee-fi-mo-milly
Billy!

Felix, Felix, bo-belix
Banana-fana fo-elix
Fee-fi-mo-melix
Felix!

Mike, Mike, bo-bike
Banana-fana fo-fike
Fee-fi-mo-ike
Mike!

Steve, Steve, bo-bteve
Banana-fana fo-fteve
Fee-fi-mo-mteve
Steve!

```


[User]
The sieve of Eratosthenes: you've been there; done that; have the T-shirt. The sieve of Eratosthenes was ancient history when Euclid was a schoolboy. You are ready for something less than 3000 years old. You are ready for The sieve of Sundaram.

Starting with the ordered set of +ve integers, mark every third starting at 4 (4;7;10...).

Step through the set and if the value is not marked output 2\*n+1. So from 1 to 4 output 3 5 7.

4 is marked so skip for 5 and 6 output 11 and 13.

7 is marked, so no output but now also mark every fifth starting at 12 (12;17;22...)

as per to 10 and now mark every seventh starting at 17 (17;24;31....)

as per for every further third element (13;16;19...) mark every (9th;11th;13th;...) element.

The output will be the ordered set of odd primes.

Using your function find and output the first 100 and the millionth Sundaram prime.

The faithless amongst you may compare the results with those generated by The sieve of Eratosthenes.

References

* The article on Wikipedia.

**Comment on the Sundaram Sieve**

In case casual readers and programmers read the above blurb and get the impression that something several thousand years newer must needs be better than the "old" Sieve of Eratosthenes (SoE), do note the only difference between the Sieve of Sundaram (SoS) and the odds-only SoE is that the SoS marks as composite/"culls" according to **all odd "base" numbers** as is quite clear in the above description of how to implement it and the above linked Wikipedia article (updated), and the SoE marks as composite/"culls" according to only the previously determined unmarked primes (which are all odd except for two, which is not used for the "odds-only" algorithm); the time complexity (which relates to the execution time) is therefore O(n log n) for the SoS and O(n log log n) for the SoE, which difference can make a huge difference to the time it takes to sieve as the ranges get larger. It takes about a billion "culls" to sieve odds-only to a billion for the SoE, whereas it takes about 2.28 billion "culls" to cull to the same range for the SoS, which implies that the SoS must be about this ratio slower for this range with the memory usage identical. Why would one choose the SoS over the SoE to save a single line of code at the cost of this much extra time? The Wren comparison at the bottom of this page makes that clear, as would implementing the same in any language.

[Assistant]
```
my $nth = 1_000_000;

my $k = Int.new: 2.4 * $nth * log($nth) / 2;

my int @sieve;

@sieve[$k] = 0;

race for (1 .. $k).batch(1000) -> @i {
  for @i -> int $i {
    my int $j = $i;
    while (my int $l = $i + $j + 2 * $i * $j++) < $k {
        @sieve[$l] = 1;
    }
  }
}

@sieve[0] = 1;

say "First 100 Sundaram primes:";
say @sieve.kv.map( { next if $^v; $^k * 2 + 1 } )[^100]».fmt("%4d").batch(10).join: "\n";

say "\nOne millionth:";
my ($count, $index);
for @sieve {
    $count += !$_;
    say $index * 2 + 1 and last if $count == $nth;
    ++$index;
}

```

Output:

```
First 100 Sundaram primes:
   3    5    7   11   13   17   19   23   29   31
  37   41   43   47   53   59   61   67   71   73
  79   83   89   97  101  103  107  109  113  127
 131  137  139  149  151  157  163  167  173  179
 181  191  193  197  199  211  223  227  229  233
 239  241  251  257  263  269  271  277  281  283
 293  307  311  313  317  331  337  347  349  353
 359  367  373  379  383  389  397  401  409  419
 421  431  433  439  443  449  457  461  463  467
 479  487  491  499  503  509  521  523  541  547

One millionth:
15485867

```


[User]
Task

Write a program that outputs the lyrics of the Christmas carol *The Twelve Days of Christmas*.
The lyrics can be found here.

(You must reproduce the words in the correct order, but case, format, and punctuation are left to your discretion.)

Other tasks related to string operations:

Metrics

* Array length
* String length
* Copy a string
* Empty string  (assignment)

Counting

* Word frequency
* Letter frequency
* Jewels and stones
* I before E except after C
* Bioinformatics/base count
* Count occurrences of a substring
* Count how many vowels and consonants occur in a string

Remove/replace

* XXXX redacted
* Conjugate a Latin verb
* Remove vowels from a string
* String interpolation (included)
* Strip block comments
* Strip comments from a string
* Strip a set of characters from a string
* Strip whitespace from a string -- top and tail
* Strip control codes and extended characters from a string

Anagrams/Derangements/shuffling

* Word wheel
* ABC problem
* Sattolo cycle
* Knuth shuffle
* Ordered words
* Superpermutation minimisation
* Textonyms (using a phone text pad)
* Anagrams
* Anagrams/Deranged anagrams
* Permutations/Derangements

Find/Search/Determine

* ABC words
* Odd words
* Word ladder
* Semordnilap
* Word search
* Wordiff  (game)
* String matching
* Tea cup rim text
* Alternade words
* Changeable words
* State name puzzle
* String comparison
* Unique characters
* Unique characters in each string
* Extract file extension
* Levenshtein distance
* Palindrome detection
* Common list elements
* Longest common suffix
* Longest common prefix
* Compare a list of strings
* Longest common substring
* Find common directory path
* Words from neighbour ones
* Change e letters to i in words
* Non-continuous subsequences
* Longest common subsequence
* Longest palindromic substrings
* Longest increasing subsequence
* Words containing "the" substring
* Sum of the digits of n is substring of n
* Determine if a string is numeric
* Determine if a string is collapsible
* Determine if a string is squeezable
* Determine if a string has all unique characters
* Determine if a string has all the same characters
* Longest substrings without repeating characters
* Find words which contains all the vowels
* Find words which contain the most consonants
* Find words which contains more than 3 vowels
* Find words whose first and last three letters are equal
* Find words with alternating vowels and consonants

Formatting

* Substring
* Rep-string
* Word wrap
* String case
* Align columns
* Literals/String
* Repeat a string
* Brace expansion
* Brace expansion using ranges
* Reverse a string
* Phrase reversals
* Comma quibbling
* Special characters
* String concatenation
* Substring/Top and tail
* Commatizing numbers
* Reverse words in a string
* Suffixation of decimal numbers
* Long literals, with continuations
* Numerical and alphabetical suffixes
* Abbreviations, easy
* Abbreviations, simple
* Abbreviations, automatic

Song lyrics/poems/Mad Libs/phrases

* Mad Libs
* Magic 8-ball
* 99 bottles of beer
* The Name Game (a song)
* The Old lady swallowed a fly
* The Twelve Days of Christmas

Tokenize

* Text between
* Tokenize a string
* Word break problem
* Tokenize a string with escaping
* Split a character string based on change of character

Sequences

* Show ASCII table
* De Bruijn sequences
* Summarize and say sequence
* Generate lower case ASCII alphabet

[Assistant]
(formerly Perl 6)

```
my @days = <first second third fourth fifth sixth seventh eighth ninth tenth eleventh twelfth>;

my @gifts = lines q:to/END/;
  And a partridge in a pear tree.
  Two turtle doves,
  Three french hens,
  Four calling birds,
  Five golden rings,
  Six geese a-laying,
  Seven swans a-swimming,
  Eight maids a-milking,
  Nine ladies dancing,
  Ten lords a-leaping,
  Eleven pipers piping,
  Twelve drummers drumming,
END

sub nth($n) { say "On the @days[$n] day of Christmas, my true love gave to me:" }

nth(0);
say @gifts[0].subst('And a','A');

for 1 ... 11 -> $d {
    say '';
    nth($d);
    say @gifts[$_] for $d ... 0;
}

```

Output:

```
On the first day of Christmas, my true love gave to me:
  A partridge in a pear tree.

On the second day of Christmas, my true love gave to me:
  Two turtle doves,
  And a partridge in a pear tree.

On the third day of Christmas, my true love gave to me:
  Three french hens,
  Two turtle doves,
  And a partridge in a pear tree.

On the fourth day of Christmas, my true love gave to me:
  Four calling birds,
  Three french hens,
  Two turtle doves,
  And a partridge in a pear tree.
.
.
.
On the twelfth day of Christmas, my true love gave to me:
  Twelve drummers drumming,
  Eleven pipers piping,
  Ten lords a-leaping,
  Nine ladies dancing,
  Eight maids a-milking,
  Seven swans a-swimming,
  Six geese a-laying,
  Five golden rings,
  Four calling birds,
  Three french hens,
  Two turtle doves,
  And a partridge in a pear tree.
```


[User]
|  |
| --- |
| This page uses content from **Wikipedia**. The original article was at Thiele's interpolation formula. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance) |

**Thiele's interpolation formula** is an interpolation formula for a function *f*(•) of a single variable.   It is expressed as a continued fraction:

:   :   f
        (
        x
        )
        =
        f
        (

        x

        1
        )
        +

        x
        −

        x

        1

        ρ

        1
        (

        x

        1
        ,

        x

        2
        )
        +

        x
        −

        x

        2

        ρ

        2
        (

        x

        1
        ,

        x

        2
        ,

        x

        3
        )
        −
        f
        (

        x

        1
        )
        +

        x
        −

        x

        3

        ρ

        3
        (

        x

        1
        ,

        x

        2
        ,

        x

        3
        ,

        x

        4
        )
        −

        ρ

        1
        (

        x

        1
        ,

        x

        2
        )
        +
        ⋯
        {\displaystyle {\displaystyle f(x)=f(x\_{1})+{\cfrac {x-x\_{1}}{\rho \_{1}(x\_{1},x\_{2})+{\cfrac {x-x\_{2}}{\rho \_{2}(x\_{1},x\_{2},x\_{3})-f(x\_{1})+{\cfrac {x-x\_{3}}{\rho \_{3}(x\_{1},x\_{2},x\_{3},x\_{4})-\rho \_{1}(x\_{1},x\_{2})+\cdots }}}}}}}}

ρ
{\displaystyle {\displaystyle \rho }}
   represents the   reciprocal difference,   demonstrated here for reference:

:   :   ρ

        1
        (

        x

        0
        ,

        x

        1
        )
        =

        x

        0
        −

        x

        1

        f
        (

        x

        0
        )
        −
        f
        (

        x

        1
        )
        {\displaystyle {\displaystyle \rho \_{1}(x\_{0},x\_{1})={\frac {x\_{0}-x\_{1}}{f(x\_{0})-f(x\_{1})}}}}

:   :   ρ

        2
        (

        x

        0
        ,

        x

        1
        ,

        x

        2
        )
        =

        x

        0
        −

        x

        2

        ρ

        1
        (

        x

        0
        ,

        x

        1
        )
        −

        ρ

        1
        (

        x

        1
        ,

        x

        2
        )
        +
        f
        (

        x

        1
        )
        {\displaystyle {\displaystyle \rho \_{2}(x\_{0},x\_{1},x\_{2})={\frac {x\_{0}-x\_{2}}{\rho \_{1}(x\_{0},x\_{1})-\rho \_{1}(x\_{1},x\_{2})}}+f(x\_{1})}}

:   :   ρ

        n
        (

        x

        0
        ,

        x

        1
        ,
        …
        ,

        x

        n
        )
        =

        x

        0
        −

        x

        n

        ρ

        n
        −
        1
        (

        x

        0
        ,

        x

        1
        ,
        …
        ,

        x

        n
        −
        1
        )
        −

        ρ

        n
        −
        1
        (

        x

        1
        ,

        x

        2
        ,
        …
        ,

        x

        n
        )
        +

        ρ

        n
        −
        2
        (

        x

        1
        ,
        …
        ,

        x

        n
        −
        1
        )
        {\displaystyle {\displaystyle \rho \_{n}(x\_{0},x\_{1},\ldots ,x\_{n})={\frac {x\_{0}-x\_{n}}{\rho \_{n-1}(x\_{0},x\_{1},\ldots ,x\_{n-1})-\rho \_{n-1}(x\_{1},x\_{2},\ldots ,x\_{n})}}+\rho \_{n-2}(x\_{1},\ldots ,x\_{n-1})}}

Demonstrate Thiele's interpolation function by:

1. Building a   **32**   row *trig table* of values   for

   x
   {\displaystyle {\displaystyle x}}
      from   **0**   by   **0.05**   to   **1.55**   of the trig functions:
   * **sin**
   * **cos**
   * **tan**
2. Using columns from this table define an inverse - using Thiele's interpolation - for each trig function;
3. Finally: demonstrate the following well known trigonometric identities:
   * 6 × sin-1 ½ =

     π
     {\displaystyle {\displaystyle \pi }}
   * 3 × cos-1 ½ =

     π
     {\displaystyle {\displaystyle \pi }}
   * 4 × tan-1 1 =

     π
     {\displaystyle {\displaystyle \pi }}

[Assistant]
(formerly Perl 6)

**Works with**: rakudo version 2018.09

Implemented to parallel the generalized formula, making for clearer, but slower, code. Offsetting that, the use of `Promise` allows concurrent calculations, so running all three types of interpolation should not take any longer than running just one (presuming available cores).

```
# reciprocal difference:
multi sub ρ(&f, @x where * < 1) { 0 } # Identity
multi sub ρ(&f, @x where * == 1) { &f(@x[0]) }
multi sub ρ(&f, @x where * > 1) {
    ( @x[0] - @x[* - 1] )       # ( x - x[n] )
    / (ρ(&f, @x[^(@x - 1)])     # / ( ρ[n-1](x[0], ..., x[n-1])
    - ρ(&f, @x[1..^@x]) )       # - ρ[n-1](x[1], ..., x[n]) )
    + ρ(&f, @x[1..^(@x - 1)]);  # + ρ[n-2](x[1], ..., x[n-1])
}

# Thiele:
multi sub thiele($x, %f, $ord where { $ord == +%f }) { 1 } # Identity
multi sub thiele($x, %f, $ord) {
  my &f = {%f{$^a}};                # f(x) as a table lookup

  # must sort hash keys to maintain order between invocations
  my $a = ρ(&f, %f.keys.sort[^($ord +1)]);
  my $b = ρ(&f, %f.keys.sort[^($ord -1)]);

  my $num = $x - %f.keys.sort[$ord];
  my $cont = thiele($x, %f, $ord +1);

  # Thiele always takes this form:
  return $a - $b + ( $num / $cont );
}

## Demo
sub mk-inv(&fn, $d, $lim) {
  my %h;
  for 0..$lim { %h{ &fn($_ * $d) } = $_ * $d }
  return %h;
}

sub MAIN($tblsz = 12) {

  my ($sin_pi, $cos_pi, $tan_pi);
  my $p1 = Promise.start( { my %invsin = mk-inv(&sin, 0.05, $tblsz); $sin_pi = 6 * thiele(0.5, %invsin, 0) } );
  my $p2 = Promise.start( { my %invcos = mk-inv(&cos, 0.05, $tblsz); $cos_pi = 3 * thiele(0.5, %invcos, 0) } );
  my $p3 = Promise.start( { my %invtan = mk-inv(&tan, 0.05, $tblsz); $tan_pi = 4 * thiele(1.0, %invtan, 0) } );
  await $p1, $p2, $p3;

  say "pi = {pi}";
  say "estimations using a table of $tblsz elements:";
  say "sin interpolation: $sin_pi";
  say "cos interpolation: $cos_pi";
  say "tan interpolation: $tan_pi";
}

```

Output:

```
pi = 3.14159265358979
estimations using a table of 12 elements:
sin interpolation: 3.14159265358961
cos interpolation: 3.1387286696692
tan interpolation: 3.14159090545243
```