[User]
Task

**Summary:** Find and print the mentions of a given string in the recent chat logs from a chatroom. Only use your programming language's standard library.

**Details:**

The Tcl Chatroom is an online chatroom. Its conversations are logged. It's useful to know if someone has mentioned you or your project in the chatroom recently. You can find this out by searching the chat logs. The logs are publicly available at http://tclers.tk/conferences/tcl/. One log file corresponds to the messages from one day in Germany's current time zone. Each chat log file has the name YYYY-MM-DD.tcl where YYYY is the year, MM is the month and DD the day. The logs store one message per line. The messages themselves are human-readable and their internal structure doesn't matter.

Retrieve the chat logs from the last 10 days via HTTP. Find the lines that include a particular substring and print them in the following format:

```
<log file URL>
------
<matching line 1>
<matching line 2>
...
<matching line N>
------

```

The substring will be given to your program as a command line argument.

You need to account for the possible time zone difference between the client running your program and the chat log writer on the server to not miss any mentions. (For example, if you generated the log file URLs naively based on the local date, you could miss mentions if it was already April 5th for the logger but only April 4th for the client.) What this means in practice is that you should either generate the URLs in the time zone Europe/Berlin or, if your language can not do that, add an extra day (today + 1) to the range of dates you check, but then make sure to not print parts of a "not found" page by accident if a log file doesn't exist yet.

The code should be contained in a single-file script, with no "project" or "dependency" file (e.g., no requirements.txt for Python). It should only use a given programming language's standard library to accomplish this task and not rely on the user having installed any third-party packages.

If your language does not have an HTTP client in the standard library, you can speak raw HTTP 1.0 to the server. If it can't parse command line arguments in a standalone script, read the string to look for from the standard input.

[Assistant]
(formerly Perl 6)

**Works with**: Rakudo version 2018.04

No dependencies or third party libraries huh? How about no modules, no requires, no libraries, no imports at all. Implemented using a bare compiler, strictly with built-ins. (Which makes it kind-of verbose, but thems the trade-offs.)

```
my $needle = @*ARGS.shift // '';
my @haystack;

# 10 days before today, Zulu time
my $begin = DateTime.new(time).utc.earlier(:10days);
say "         Executed at: ", DateTime.new(time).utc;
say "Begin searching from: $begin";

# Today - 10 days through today
for $begin.Date .. DateTime.now.utc.Date -> $date {

    # connect to server, use a raw socket
    my $http = IO::Socket::INET.new(:host('tclers.tk'), :port(80));

    # request file
    $http.print: "GET /conferences/tcl/{$date}.tcl HTTP/1.0\n\n";

    # retrieve file
    my @page = $http.lines;

    # remove header
    @page.splice(0, 8);

    # concatenate multi-line entries to a single line
    while @page {
        if @page[0].substr(0, 13) ~~ m/^'m '\d\d\d\d'-'\d\d'-'\d\d'T'/ {
            @haystack.push: @page.shift;
        }
        else {
            @haystack.tail ~= '␤' ~ @page.shift;
        }
    }

    # close socket
    $http.close;
}

# ignore times before 10 days ago
@haystack.shift while @haystack[0].substr(2, 22) lt $begin.Str;

# print the first and last line of the haystack
say "First and last lines of the haystack:";
.say for |@haystack[0, *-1];
say "Needle: ", $needle;
say  '-' x 79;

# find and print needle lines
.say if .contains( $needle ) for @haystack;

```

Output:

Sample output using a needle of 'github.com'

```
         Executed at: 2017-05-05T02:13:55Z
Begin searching from: 2017-04-25T02:13:55Z
First and last lines of the haystack:
m 2017-04-25T02:25:17Z ijchain {*** TakinOver leaves}
m 2017-05-05T02:14:52Z {} {rmax has become available}
Needle: github.com
-------------------------------------------------------------------------------
m 2017-04-28T07:33:59Z ijchain {<Napier> https://github.com/Dash-OS/tcl-modules/blob/master/react-0.5.tm}
m 2017-04-28T07:35:40Z ijchain {<Napier> https://github.com/Dash-OS/tcl-modules/blob/master/react/reducer-0.5.tm}
m 2017-04-28T08:25:39Z ijchain {<Napier> https://github.com/Dash-OS/tcl-modules/blob/master/examples/react.md}
m 2017-04-28T08:45:01Z ijchain {<Napier> https://github.com/Dash-OS/tcl-modules/blob/master/examples/react.md}
m 2017-04-28T09:21:22Z ijchain {<Napier> decorators damnit! :-P https://github.com/Dash-OS/tcl-modules/blob/master/decorator-1.0.tm}
m 2017-04-28T15:42:28Z jima https://gist.github.com/antirez/6ca04dd191bdb82aad9fb241013e88a8
m 2017-04-28T16:20:22Z ijchain {<dbohdan> Look at what I've just made: https://github.com/dbohdan/ptjd}
m 2017-04-29T05:48:13Z ijchain {<dbohdan> The brackets, rather than braces, are there because the [catch] is used for metaprogramming: https://github.com/dbohdan/ptjd/blob/c0a77ecfb34c619e30ec7c5e9f448879d41282e2/tests.tcl#L48}
m 2017-04-29T14:49:08Z ijchain {<dbohdan> If you want CI for Windows builds, it should possible to set it up relatively easily with AppVeyor and the Git mirror at https://github.com/tcltk/tcl}
m 2017-04-29T14:50:58Z ijchain {<dbohdan> Here's an example: https://github.com/dbohdan/picol/blob/trunk/appveyor.yml}
m 2017-04-29T20:33:25Z ijchain {<Napier> https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms}
m 2017-04-30T08:20:05Z ijchain {<bairui> AvL_42: fwiw, I like and use Apprentice: https://github.com/romainl/Apprentice}
m 2017-04-30T21:35:22Z ijchain {<Napier> https://github.com/Dash-OS/tcl-modules#cswitch-flags-----expr-script-}
m 2017-05-01T04:16:00Z ijchain {<bairui> avl42: https://github.com/dahu/DiffLine  --  see if that helps with your next long-line vimdiff. DISCLAIMER: It *shouldn't* eat your hard-drive, but buyer beware, check the code and test it on unimportant stuff first.}
m 2017-05-01T07:08:26Z ijchain {<dbohdan> Do take a look at this one, though: https://github.com/dbohdan/sqawk/blob/master/lib/tabulate.tcl#L74}
m 2017-05-01T07:09:28Z ijchain {<dbohdan> And at https://github.com/dbohdan/jimhttp/blob/master/arguments.tcl}
m 2017-05-01T08:14:05Z ijchain {<dbohdan> I've reimplemented part of tcltest recently (with pretty colors!), and I'm pretty with this solution: https://github.com/dbohdan/ptjd/blob/master/tests.tcl#L49}
m 2017-05-03T14:57:24Z ijchain {<dbohdan> I think Tcl is okay to pretty good for compilery things if you already know how to do them. For instance, I found writing this tokenizer in Tcl a breeze: https://github.com/dbohdan/jimhttp/blob/master/json.tcl#L380}
m 2017-05-04T16:19:55Z stu {rkeene, files Makefile.in, itzev and spoto.conf are spotoconf: https://github.com/aryler/Tclarc4random/}
m 2017-05-04T20:26:28Z dgp https://github.com/flightaware/Tcl-bounties/issues/25
```


[User]
Task

Show how to return more than one value from a function.

[Assistant]
(formerly Perl 6)

Each function officially returns one value, but by returning a List or Seq you can transparently return a list of arbitrary (even infinite) size. The calling scope can destructure the list using assignment, if it so chooses:

```
sub addmul($a, $b) {
    $a + $b, $a * $b
}

my ($add, $mul) = addmul 3, 7;

```

In this example, the variable $add now holds the number 10, and $mul the number 21.


[User]
Task

Take a string and reverse it.

For example, "asdf" becomes "fdsa".

Extra credit

Preserve Unicode combining characters.

For example, "as⃝df̅" becomes "f̅ds⃝a", not "̅fd⃝sa".

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.08

Raku handles graphemes, multi-byte characters and emoji correctly by default.

```
say "hello world".flip;
say "as⃝df̅".flip;
say 'ℵΑΩ 駱駝道 🤔 🇸🇧 🇺🇸 🇬🇧 👨👩👧👦🆗🗺'.flip;
```

Output:

```
dlrow olleh
f̅ds⃝a
🗺🆗👨👩👧👦 🇬🇧 🇺🇸 🇸🇧 🤔 道駝駱 ΩΑℵ
```


[User]
The task is to create a function that reverses the gender of the text of a string.

The function should take one arguments being a string to undergo the gender change.

The returned string should contain this initial string, with all references to be gender switched.

```
print rev_gender("She was a soul stripper. She took my heart!")
He was a soul stripper. He took my heart!
```

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)
Mechanically, this task is trivial. Raku provides several flexible and powerful methods to wrangle text. Linguistically, this task is impossible (and laughable). Mappings are non-regular and in many cases, non-deterministic without semantic analysis of the content and context, which is **WAY** beyond what anyone is going to invest in a Rosettacode task. Whatever.

For extremely limited circumstances such as this example, this should suffice. Notice case matching and replication. Handles contractions, but ignores embedded matching text.

```
say S:g:ii/«'she'»/he/ given "She was a soul stripper. She took my heart! They say she's going to put me on a shelf.";

```

Output:

```
He was a soul stripper. He took my heart! They say he's going to put me on a shelf.
```


[User]
Task
:   * Read an entire (input) file   (into memory or buffers).
    * Display the lines/records of the entire file in reverse order.
    * Show the results here, on this page.

For the input file, use the following **five** lines (records):

```
 "Diplomacy is the art of                                    ◄■■■■■■ starts in column 3.
   saying  'Nice Doggy'                                      ◄■■■■■■ starts in column 5,
until you can find a rock."                                  ◄■■■■■■ starts in column 2,
                                                             ◄■■■■■■ (a blank line),
                            --- Will Rodgers                 ◄■■■■■■ starts in column 30.

```

You can (or may) assume there are no superfluous trailing blanks,   and that line four has one blank.

Also, don't include the rightmost informative comments   (◄■■■■■■),   as they are not meant to be part of the file.

Reference: Bash tac command

[Assistant]
Not going to bother testing with the task recommended file. It demonstrates nothing to do with file handling, record separators, memory conservation or anything useful. May as well just be "Reverse this list" for all the good it does.

### Lots of assumptions

Simplest thing that could possibly satisfy the extremely vague task description and completely glossing over all of the questions raised on the discussion page.

ASSUMPTIONS:

* File is redirected into STDIN from command line.
* Is a Unix or Windows format text file.
* Is in UTF8 encoding or some subset thereof.
* May hold entire file in memory.

```
.put for reverse lines

```

### Few assumptions

Processes a small (configurable) number of bytes at a time so file can be multi-terabyte and it will handle with ease. *Does* assume Latin 1 for reduced complexity.

No assumptions were made concerning line/record termination, full stop.

Run the following to generate nul.txt. (digits 1 through 6 repeated 8 times with double null as record separators):

```
   raku -e'print join "\x00\x00", (1..6).map: * x 8' > nul.txt

```

```
my $input-record-separator = "\x00\x00";

my $fh = open("nul.txt".IO, :r, :bin);
$fh.seek(0, SeekFromEnd); # start at the end of the file

my $bytes = 5 min $fh.tell - 1; # read in file 5 bytes at a time (or whatever)

$fh.seek(-$bytes, SeekFromCurrent);

my $buffer = $fh.read($bytes).decode('Latin1'); # assume Latin1 for reduced complexity

loop {
    my $seek = ($fh.tell < $bytes * 2) ?? -$fh.tell !! -$bytes * 2;
    $fh.seek($seek, SeekFromCurrent);
    $buffer = $buffer R~ $fh.read((-$seek - $bytes) max 0).decode('Latin1');
    if $buffer.contains: $input-record-separator {
        my @rest;
        ($buffer, @rest) = $buffer.split: $input-record-separator;
        .say for reverse @rest; # emit any full records that have been processed
    }
    last if $fh.tell < $bytes;
}

say $buffer; # emit any remaining record

```

Output:

```
66666666
55555555
44444444
33333333
22222222
11111111
```


[User]
Task

Reverse the order of all tokens in each of a number of strings and display the result;   the order of characters within a token should not be modified.

Example

`Hey you, Bub!`    would be shown reversed as:    `Bub! you, Hey`

Tokens are any non-space characters separated by spaces (formally, white-space);   the visible punctuation form part of the word within which it is located and should not be modified.

You may assume that there are no significant non-visible characters in the input.   Multiple or superfluous spaces may be compressed into a single space.

Some strings have no tokens, so an empty string   (or one just containing spaces)   would be the result.

**Display** the strings in order   (1st, 2nd, 3rd, ···),   and one string per line.

(You can consider the ten strings as ten lines, and the tokens as words.)

Input data

```
             (ten lines within the box)
 line
     ╔════════════════════════════════════════╗
   1 ║  ---------- Ice and Fire ------------  ║
   2 ║                                        ║  ◄─── a blank line here.
   3 ║  fire, in end will world the say Some  ║
   4 ║  ice. in say Some                      ║
   5 ║  desire of tasted I've what From       ║
   6 ║  fire. favor who those with hold I     ║
   7 ║                                        ║  ◄─── a blank line here.
   8 ║  ... elided paragraph last ...         ║
   9 ║                                        ║  ◄─── a blank line here.
  10 ║  Frost Robert -----------------------  ║
     ╚════════════════════════════════════════╝

```

Cf.

* Phrase reversals

[Assistant]
(formerly Perl 6)
We'll read input from stdin

```
say ~.words.reverse for lines

```

Output:

```
------------ Fire and Ice ----------

Some say the world will end in fire,
Some say in ice.
From what I've tasted of desire
I hold with those who favor fire.

... last paragraph elided ...

----------------------- Robert Frost
```


[User]
A positive integer ***n*** is said to be a Rhonda number to base ***b*** if the product of the base ***b*** digits of ***n*** is equal to ***b*** times the sum of ***n'***s prime factors.

*These numbers were named by Kevin Brown after an acquaintance of his whose residence number was 25662, a member of the base 10 numbers with this property.*

**25662** is a Rhonda number to base-**10**. The prime factorization is **2 × 3 × 7 × 13 × 47**; the product of its base-**10** digits is equal to the base times the sum of its prime factors:

2 × 5 × 6 × 6 × 2 = 720 = 10 × (2 + 3 + 7 + 13 + 47)

Rhonda numbers only exist in bases that are not a prime.

*Rhonda numbers to base 10 **always** contain at least 1 digit 5 and **always** contain at least 1 even digit.*

Task

* For the non-prime bases ***b*** from **2** through **16** , find and display here, on this page, at least the first **10** **Rhonda numbers** to base ***b***. Display the found numbers at least in base **10**.

Stretch

* Extend out to base **36**.

See also

* Wolfram Mathworld - Rhonda numbers * Numbers Aplenty - Rhonda numbers * OEIS:A100968 - Integers n that are Rhonda numbers to base 4 * OEIS:A100969 - Integers n that are Rhonda numbers to base 6 * OEIS:A100970 - Integers n that are Rhonda numbers to base 8 * OEIS:A100973 - Integers n that are Rhonda numbers to base 9 * OEIS:A099542 - Rhonda numbers to base 10 * OEIS:A100971 - Integers n that are Rhonda numbers to base 12 * OEIS:A100972 - Integers n that are Rhonda numbers to base 14 * OEIS:A100974 - Integers n that are Rhonda numbers to base 15 * OEIS:A100975 - Integers n that are Rhonda numbers to base 16

* OEIS:A255735 - Integers n that are Rhonda numbers to base 18 * OEIS:A255732 - Rhonda numbers in vigesimal number system (base 20) * OEIS:A255736 - Integers that are Rhonda numbers to base 30

* Related Task: Smith numbers

[Assistant]
Find and show the first 15 so as to display the namesake Rhonda number 25662.

```
use Prime::Factor;

my @factor-sum;

@factor-sum[1000000] = 42; # Sink a large index to make access thread safe

sub rhonda ($base) {
    (1..∞).hyper.map: { $_ if $base * (@factor-sum[$_] //= .&prime-factors.sum) == [×] .polymod($base xx *) }
}

for (flat 2..16, 17..36).grep: { !.&is-prime }  -> $b {
    put "\nFirst 15 Rhonda numbers to base $b:";
    my @rhonda = rhonda($b)[^15];
    my $ch = @rhonda[*-1].chars max @rhonda[*-1].base($b).chars;
    put "In base 10: " ~ @rhonda».fmt("%{$ch}s").join: ', ';
    put $b.fmt("In base %2d: ") ~ @rhonda».base($b)».fmt("%{$ch}s").join: ', ';
}

```

Output:

```
First 15 Rhonda numbers to base 4:
In base 10:      10206,      11935,      12150,      16031,      45030,      94185,     113022,     114415,     191149,     244713,     259753,     374782,     392121,     503773,     649902
In base  4:    2133132,    2322133,    2331312,    3322133,   22333212,  112333221,  123211332,  123323233,  232222231,  323233221,  333122221, 1123133332, 1133232321, 1322333131, 2132222232

First 15 Rhonda numbers to base 6:
In base 10:     855,    1029,    3813,    5577,    7040,    7304,   15104,   19136,   35350,   36992,   41031,   42009,   60368,   65536,   67821
In base  6:    3543,    4433,   25353,   41453,   52332,   53452,  153532,  224332,  431354,  443132,  513543,  522253, 1143252, 1223224, 1241553

First 15 Rhonda numbers to base 8:
In base 10:   1836,   6318,   6622,  10530,  14500,  14739,  17655,  18550,  25398,  25956,  30562,  39215,  39325,  50875,  51429
In base  8:   3454,  14256,  14736,  24442,  34244,  34623,  42367,  44166,  61466,  62544,  73542, 114457, 114635, 143273, 144345

First 15 Rhonda numbers to base 9:
In base 10:  15540,  21054,  25331,  44360,  44660,  44733,  47652,  50560,  54944,  76857,  77142,  83334,  83694,  96448,  97944
In base  9:  23276,  31783,  37665,  66758,  67232,  67323,  72326,  76317,  83328, 126376, 126733, 136273, 136723, 156264, 158316

First 15 Rhonda numbers to base 10:
In base 10:  1568,  2835,  4752,  5265,  5439,  5664,  5824,  5832,  8526, 12985, 15625, 15698, 19435, 25284, 25662
In base 10:  1568,  2835,  4752,  5265,  5439,  5664,  5824,  5832,  8526, 12985, 15625, 15698, 19435, 25284, 25662

First 15 Rhonda numbers to base 12:
In base 10:   560,   800,  3993,  4425,  4602,  4888,  7315,  8296,  9315, 11849, 12028, 13034, 14828, 15052, 16264
In base 12:   3A8,   568,  2389,  2689,  27B6,  29B4,  4297,  4974,  5483,  6A35,  6B64,  7662,  86B8,  8864,  94B4

First 15 Rhonda numbers to base 14:
In base 10:  11475,  18655,  20565,  29631,  31725,  45387,  58404,  58667,  59950,  63945,  67525,  68904,  91245,  99603, 125543
In base 14:   4279,   6B27,   76CD,   AB27,   B7C1,  1277D,  173DA,  17547,  17BC2,  19437,  1A873,  1B17A,  25377,  28427,  33A75

First 15 Rhonda numbers to base 15:
In base 10:  2392,  2472, 11468, 15873, 17424, 18126, 19152, 20079, 24388, 30758, 31150, 33004, 33550, 37925, 39483
In base 15:   A97,   AEC,  35E8,  4A83,  5269,  5586,  5A1C,  5E39,  735D,  91A8,  936A,  9BA4,  9E1A,  B385,  BA73

First 15 Rhonda numbers to base 16:
In base 10:  1000,  1134,  6776, 15912, 19624, 20043, 20355, 23946, 26296, 29070, 31906, 32292, 34236, 34521, 36465
In base 16:   3E8,   46E,  1A78,  3E28,  4CA8,  4E4B,  4F83,  5D8A,  66B8,  718E,  7CA2,  7E24,  85BC,  86D9,  8E71

First 15 Rhonda numbers to base 18:
In base 10:  1470,  3000,  8918, 17025, 19402, 20650, 21120, 22156, 26522, 36549, 38354, 43281, 46035, 48768, 54229
In base 18:   49C,   94C,  1998,  2G9F,  35FG,  39D4,  3B36,  3E6G,  49F8,  64E9,  6A6E,  77A9,  7G19,  8696,  956D

First 15 Rhonda numbers to base 20:
In base 10:  1815, 11050, 15295, 21165, 22165, 30702, 34510, 34645, 42292, 44165, 52059, 53416, 65945, 78430, 80712
In base 20:   4AF,  17CA,  1I4F,  2CI5,  2F85,  3GF2,  465A,  46C5,  55EC,  5A85,  6A2J,  6DAG,  84H5,  9G1A,  A1FC

First 15 Rhonda numbers to base 21:
In base 10:  1632,  5390,  8512, 12992, 15678, 25038, 29412, 34017, 39552, 48895, 49147, 61376, 85078, 89590, 91798
In base 21:   3EF,   C4E,   J67,  189E,  1EBC,  2EG6,  33EC,  3E2I,  45E9,  55I7,  5697,  6D3E,  93J7,  9E34,  9J37

First 15 Rhonda numbers to base 22:
In base 10:   2695,   4128,   7865,  28800,  31710,  37030,  71875,  74306, 117760, 117895, 121626, 126002, 131427, 175065, 192753
In base 22:    5CB,    8BE,    G5B,   2FB2,   2LB8,   3AB4,   6GB1,   6LBC,   B16G,   B1CJ,   B96A,   BI78,   C7BL,   G9FB,   I25B

First 15 Rhonda numbers to base 24:
In base 10:  2080,  2709,  3976,  5628,  5656,  7144,  8296,  9030, 10094, 17612, 20559, 24616, 26224, 29106, 31458
In base 24:   3EG,   4GL,   6LG,   9IC,   9JG,   C9G,   E9G,   FG6,   HCE,  16DK,  1BGF,  1IHG,  1LCG,  22CI,  26EI

First 15 Rhonda numbers to base 25:
In base 10:   6764,   9633,  13260,  22022,  53382,  57640,  66015,  69006,  97014, 140130, 142880, 144235, 159724, 162565, 165504
In base 25:    AKE,    FA8,    L5A,   1A5M,   3AA7,   3H5F,   45FF,   4AA6,   655E,   8O55,   93F5,   95JA,   A5DO,   AA2F,   AEK4

First 15 Rhonda numbers to base 26:
In base 10:   7788,   9322,   9374,  11160,  22165,  27885,  34905,  44785,  47385,  49257,  62517,  72709,  74217, 108745, 132302
In base 26:    BDE,    DKE,    DME,    GD6,   16KD,   1F6D,   1PGD,   2E6D,   2I2D,   2KMD,   3ECD,   43ED,   45KD,   64MD,   7DIE

First 15 Rhonda numbers to base 27:
In base 10:  4797, 11844, 12078, 13200, 14841, 17750, 24320, 26883, 27477, 46455, 52750, 58581, 61009, 61446, 61500
In base 27:   6FI,   G6I,   GF9,   I2O,   K9I,   O9B,  169K,  19NI,  1AII,  29JF,  2I9J,  2Q9I,  32IG,  337L,  339L

First 15 Rhonda numbers to base 28:
In base 10:  3094,  5808,  5832,  7462, 11160, 13671, 27270, 28194, 28638, 39375, 39550, 49500, 50862, 52338, 52938
In base 28:   3QE,   7BC,   7C8,   9EE,   E6G,   HC7,  16LQ,  17QQ,  18EM,  1M67,  1MCE,  273O,  28OE,  2AL6,  2BEI

First 15 Rhonda numbers to base 30:
In base 10:  3024,  3168,  5115,  5346,  5950,  6762,  7750,  7956,  8470,  9476,  9576,  9849, 10360, 11495, 13035
In base 30:   3AO,   3FI,   5KF,   5S6,   6IA,   7FC,   8IA,   8P6,   9CA,   AFQ,   AJ6,   AS9,   BFA,   CN5,   EEF

First 15 Rhonda numbers to base 32:
In base 10:  1944,  3600, 13520, 15876, 16732, 16849, 25410, 25752, 28951, 47472, 49610, 50968, 61596, 64904, 74005
In base 32:   1SO,   3GG,   D6G,   FG4,   GAS,   GEH,   OQ2,   P4O,   S8N,  1EBG,  1GEA,  1HOO,  1S4S,  1VC8,  288L

First 15 Rhonda numbers to base 33:
In base 10:    756,   7040,   7568,  13826,  24930,  30613,  59345,  63555,  64372, 131427, 227840, 264044, 313709, 336385, 344858
In base 33:     MU,    6FB,    6VB,    CMW,    MTF,    S3M,   1LGB,   1PBU,   1Q3M,   3LML,   6B78,   7BFB,   8O2B,   9BTG,   9JM8

First 15 Rhonda numbers to base 34:
In base 10:   5661,  14161,  15620,  16473,  22185,  37145, 125579, 134692, 135405, 138472, 140369, 177086, 250665, 255552, 295614
In base 34:    4UH,    C8H,    DHE,    E8H,    J6H,    W4H,   36LH,   3EHI,   3F4H,   3HQO,   3JEH,   4H6E,   6CSH,   6H28,   7HOI

First 15 Rhonda numbers to base 35:
In base 10:   8232,   9476,   9633,  18634,  30954,  41905,  52215,  52440,  56889,  61992,  62146,  66339,  98260, 102180, 103305
In base 35:    6P7,    7PQ,    7U8,    F7E,    P9E,    Y7A,   17LU,   17SA,   1BFE,   1FL7,   1FPL,   1J5E,   2A7F,   2DEF,   2EBK

First 15 Rhonda numbers to base 36:
In base 10:  1000,  4800,  5670,  8190, 10998, 12412, 13300, 15750, 16821, 23016, 51612, 52734, 67744, 70929, 75030
In base 36:    RS,   3PC,   4DI,   6BI,   8HI,   9KS,   A9G,   C5I,   CZ9,   HRC,  13TO,  14OU,  1G9S,  1IQ9,  1LW6
```


[User]
**Rice coding** is a variant of Golomb coding where the parameter is a power of two. This makes it easier to encode the remainder of the euclidean division.

Implement Rice coding in your programming language and verify that you can consistently encode and decode a list of examples (for instance numbers from 0 to 10 or something).

Rice coding is initially meant to encode natural numbers, but since relative numbers are countable, it is fairly easy to modify Rice coding to encode them too. You can do that for extra credit.

[Assistant]
```
package Rice {

  our sub encode(Int $n, UInt :$k = 2) {
    my $d = 2**$k;
    my $q = $n div $d;
    my $b = sign(1 + sign($q));
    my $m = abs($q) + $b;
    flat
      $b xx $m, 1 - $b,
      ($n mod $d).polymod(2 xx $k - 1).reverse
  }

  our sub decode(@bits is copy, UInt :$k = 2) {
    my $d = 2**$k;
    my $b = @bits.shift;
    my $m = 1;
    $m++ while @bits and @bits.shift == $b;
    my $q = $b ?? $m - 1 !! -$m;
    $q*$d + @bits.reduce(2 * * + *);
  }

}

CHECK {
  use Test;
  constant N = 100;
  plan 2*N + 1;
  is $_, Rice::decode Rice::encode $_ for -N..N;
}

```


[User]
Riordan numbers show up in several places in set theory. They are closely related to Motzkin numbers, and may be used to derive them.

Riordan numbers comprise the sequence **a** where:

```
   a(0) = 1, a(1) = 0, for subsequent terms, a(n) = (n-1)*(2*a(n-1) + 3*a(n-2))/(n+1)

```

There are other generating functions, and you are free to use one most convenient for your language.

Task

* Find and display the first 32 Riordan numbers.

Stretch

* Find and display the **digit count** of the 1,000th Riordan number.
* Find and display the **digit count** of the 10,000th Riordan number.

See also

* OEIS:A005043 - Riordan numbers

[Assistant]
```
use Lingua::EN::Numbers;

my @riordan = 1, 0, { state $n = 1; (++$n - 1) / ($n + 1) × (3 × $^a + 2 × $^b) } … *;

my $upto = 32;
say "First {$upto.&cardinal} Riordan numbers:\n" ~ @riordan[^$upto]».&comma».fmt("%17s").batch(4).join("\n") ~ "\n";

sub abr ($_) { .chars < 41 ?? $_ !! .substr(0,20) ~ '..' ~ .substr(*-20) ~ " ({.chars} digits)" }

say "The {.Int.&ordinal}: " ~ abr @riordan[$_ - 1] for 1e3, 1e4

```

Output:

```
First thirty-two Riordan numbers:
                1                 0                 1                 1
                3                 6                15                36
               91               232               603             1,585
            4,213            11,298            30,537            83,097
          227,475           625,992         1,730,787         4,805,595
       13,393,689        37,458,330       105,089,229       295,673,994
      834,086,421     2,358,641,376     6,684,761,125    18,985,057,351
   54,022,715,451   154,000,562,758   439,742,222,071 1,257,643,249,140

The one thousandth: 51077756867821111314..79942013897484633052 (472 digits)
The ten thousandth: 19927418577260688844..71395322020211157137 (4765 digits)
```


[User]
**RIPEMD-160** is another hash function; it computes a 160-bit message digest.

There is a RIPEMD-160 home page, with test vectors and pseudocode for RIPEMD-160.
For padding the message, RIPEMD-160 acts like MD4 (RFC 1320).

Find the RIPEMD-160 message digest of a string of octets.
Use the ASCII encoded string “Rosetta Code”.
You may either call an RIPEMD-160 library, or implement RIPEMD-160 in your language.

[Assistant]
(formerly Perl 6)

```
# https://github.com/grondilu/libdigest-raku/blob/master/lib/Digest/RIPEMD.rakumod

say rmd160 "Rosetta Code";

=begin CREDITS
Crypto-JS v2.0.0
http:#code.google.com/p/crypto-js/
Copyright (c) 2009, Jeff Mott. All rights reserved.
=end CREDITS

proto rmd160($) returns Blob is export {*}
multi rmd160(Str $str) { samewith $str.encode }

multi rmd160(Blob $data) {

  sub rotl(uint32 $n, $b) { $n +< $b +| $n +> (32 - $b) }

  blob8.new:
    map |*.polymod(256 xx 3),
    |reduce
      -> blob32 $h, @words {
        blob32.new: [Z+] map {$_[[^5].rotate(++$)]}, $h, |await
          map -> [&f, $r, @K, $s] {
            start {
              reduce -> $A, $j {
                $A[4],
                rotl(
                  ($A[0] + (BEGIN [
                    * +^ * +^ *,
                    { $^x +& $^y +| +^$x +& $^z },
                    (* +| +^*) +^ *,
                    { $^x +& $^z +| $^y +& +^$^z },
                    { $^x +^ ($^y +| +^$^z) }
                  ])[&f($j) div 16](|$A[1..3])
                  + @words[$r[$j]] + @K[$j]) mod 2**32,
                  $s[$j]
                ) + $A[4],
                $A[1],
                rotl($A[2], 10),
                $A[3]
              }, $h, |^80
            }
          },
          BEGIN Array.new:
            map -> [ &a,$b,@c,$d ] {
              [&a,.($b),(flat @c »xx» 16),.($d)] given *.comb».parse-base(16)
            },
            (  +*,
              "0123456789ABCDEF74D1A6F3C0952EB83AE49F812706DB5C19BA08C4D37FE56240597C2AE138B6FD",
              <0x00000000 0x5a827999 0x6ed9eba1 0x8f1bbcdc 0xa953fd4e>,
              "BEFC5879BDEF6798768DB97F7CF9B7DCBD67E9DFE8D65C75BCEFEF989E56865C9F5B68DC5CDEB856"
            ),
            (79-*,
              "5E7092B4D6F81A3C6B370D5AEF8C4912F5137E69B8C2A04D86413BF05C2D97AECFA4158762DE039B",
              <0x50a28be6 0x5c4dd124 0x6d703ef3 0x7a6d76e9 0x00000000>,
              "899BDFF5778BEEC69DF7C89B77C76FDB97FB866ECD5EDD75F58BEE6E69C9C5F885C9C5E68D65FDBB"
            )
          ;
      },
      (BEGIN blob32.new: 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0),
      |blob32.new(
        blob8.new(
          $data.list,
          0x80,
          0 xx (-($data.elems + 1 + 8) % 64),
          |(8 * $data).polymod: 256 xx 7
        ).rotor(4).map: { :256[@^x.reverse] }
      ).rotor(16);
}

```

Output:

```
Buf:0x<b3 be 15 98 60 84 2c eb aa 71 74 c8 ff f0 aa 9e 50 a5 19 9f>
```


[User]
|  |
| --- |
| This page uses content from **Wikipedia**. The original article was at Robots\_(1984\_video\_game). 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) |

The task is to implement a clone of Ken Arnold's turn-based game Robots.

Simple game where its only objective is to escape from a number of robots, which have been programmed to kill the player.

[Assistant]
(formerly Perl 6)
The bots single-mindedly chase you, taking the shortest path, ignoring obstacles. Use arrow keys to navigate your character(╂) around the board. Avoid bots(☗) and hazards(☢). "Kill" bots by causing them to crash into hazards or other bots. A dead bot creates another hazard. If you eliminate all of the bots on the board, another wave will spawn in random positions. If you touch a hazard or are touched by a bot, you die(†).

```
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);

# reset terminal to original settings and clean up on exit
END { $saved.setattr(:NOW);  print "\e[?25h\n" }

print "\e[?25l"; # hide cursor

my %dir = (
   "\e[A" => 'up',
   "\e[B" => 'down',
   "\e[C" => 'right',
   "\e[D" => 'left',
);

my $x = 100; # nominal "board" width
my $y = 40;  # nominal "board" height

my $human = "\e[0;92m╂\e[0m"; # various
my $robot = "\e[0;91m☗\e[0m"; # entity
my $block = "\e[0;93m☢\e[0m"; # sprite
my $dead  = "\e[1;37m†\e[0m"; # characters
my $wall  = "\e[1;96m█\e[0m";
my $blank = ' ';

my $numbots = 10; # number of bots in each round

# blank playing field
my @scr = flat $wall xx $x, ($wall, $blank xx $x - 2, $wall) xx $y - 2, $wall xx $x;

# put player on board
my $me;
loop {
    $me = ($x+2 .. ($x - 1 ) * $y).roll;
    last if @scr[$me] eq $blank;
}
@scr[$me] = $human;

# Put an assortment of hazards on board
for ^20 {
    my $s = (^$x*$y).pick;
    if @scr[$s] eq $blank { @scr[$s] = $block } else { redo }
}

my $info  = 0;
my $score = 0;

newbots(); # populate board with a fresh wave of bots

loop {
    print "\e[H\e[J";
    print "\e[H";
    print join "\n", @scr.rotor($x)».join;
    print "\nSurvived " , $info , ' bots';

    # Read up to 4 bytes from keyboard buffer.
    # Page navigation keys are 3-4 bytes each.
    # Specifically, arrow keys are 3.
    my $key = $*IN.read(4).decode;

    move %dir{$key} if so %dir{$key};
    movebots();
    last if $key eq 'q'; # (q)uit
}

proto sub move (|) {*};

multi move ('up') {
    if @scr[$me - $x] ne $wall {
        expire() if @scr[$me - $x] ne $blank;
        @scr[$me] = $blank;
        $me = $me - $x;
        @scr[$me] = $human;
    }
}
multi move ('down') {
    if @scr[$me + $x] ne $wall {
        expire() if @scr[$me + $x] ne $blank;
        @scr[$me] = $blank;
        $me = $me + $x;
        @scr[$me] = $human;
    }
}
multi move ('left') {
   if @scr[$me - 1] ne $wall {
        expire() if @scr[$me - 1] ne $blank;
        @scr[$me] = $blank;
        $me = $me - 1;
        @scr[$me] = $human;
    }
}

multi move ('right') {
    if @scr[$me + 1] ne $wall {
        expire() if @scr[$me + 1] ne $blank;
        @scr[$me] = $blank;
        $me = $me + 1;
        @scr[$me] = $human;
    }
}

sub newbots {
    for ^$numbots {
        my $s = (^$x*$y).pick;
        if @scr[$s] eq $blank {
            @scr[$s] = $robot;
        } else {
            redo
        }
    }
}

sub movebots {
    my $mx = $me % $x;
    my $my = $me div $x;
    my @bots = @scr.grep: * eq $robot, :k;
    for @bots -> $b {
        my $bx = $b % $x;
        my $by = $b div $x ;
        if ($mx - $bx).abs < ($my - $by).abs {
            $by += ($my - $by) < 0 ?? -1 !! 1;
        } else {
            $bx += ($mx - $bx) < 0 ?? -1 !! 1;
        }
        my $n = $by * $x + $bx;
        if @scr[$n] eq $robot {
            @scr[$b] = @scr[$n] = $block;
        } elsif @scr[$n] eq $block {
            @scr[$b] = $block;
        } elsif $n == $me {
            expire()
        } else {
            @scr[$b] = $blank;
            @scr[$n] = $robot;
        }
    }
    unless +@bots > 0 {
        newbots();
        $score += $numbots;
    }
    $info = $score + $numbots - @scr.grep: * eq $robot;
}

sub expire {
    @scr[$me] = $dead;
    print "\e[H\e[J";
    print "\e[H";
    print join "\n", @scr.rotor($x)».join;
    print "\nSurvived " , $info , ' bots, but succumbed in the end.';
    exit
}

```

Sample game:

```
████████████████████████████████████████████████████████████████████████████████████████████████████
█                                                                                █
█                                               ☗                                                  █
█                                 ☢☢                                                               █
█                             †    ☢       ☢                                  ☢                    █
█          ☢                  ☢☢☢☢☢☢                                                               █
█       ☢☢☢☢☢☢☢                ☢☢☢☢☢☢☢                                                             █
█               ☢☢☢☢           ☢  ☢☢                              ☢☢☢                              █
█             ☢☢☢☢☢               ☢☢                                                               █
█            ☢☢☢☢☢☢☢☢             ☢☢☢                        ☢☢☢                                   █
█             ☢ ☢☢☢☢                ☢                                                              █
█              ☢☢☢                                                                                █
█                                              ☗                                                   █
█               ☢☢☢ ☢                                                                              █
█               ☢☢☢☢☢☢                                                                             █
█                ☢☢☢☢☢☢☢☢                                                                          █
█               ☢☢☢☢☢☢ ☢☢                                                                          █
█               ☢☢☢☢☢☢☢☢                   ☗                                                       █
█               ☢☢☢☢☢☢☢      ☢                                 ☢                                   █
█                 ☢☢ ☢       ☢☢                                                                    █
█                  ☢ ☢       ☢         ☢☢                                                          █
█                 ☢☢                   ☢                                                           █
█           ☢                          ☢                                                           █
█           ☢                                                                                █
█           ☢                                                                                █
█                                                                                █
█                                                                        ☢                      ☢  █
█                                                                                █
█                                                                                █
█                                                                                █
█                                                                                ☢    █
█                                                                             ☢             ☢      █
█                                                        ☢                                         █
█                                                                                █
█                                                                                █
█                                           ☢☢                                                     █
█                                           ☢                                                      █
█                                                                                █
█            ☢☢                                                                                █
████████████████████████████████████████████████████████████████████████████████████████████████████
Survived 117 bots, but succumbed in the end.
```


[User]
Task

Implement the classic children's game Rock-paper-scissors, as well as a simple predictive   **AI**   (artificial intelligence)   player.

Rock Paper Scissors is a two player game.

Each player chooses one of rock, paper or scissors, without knowing the other player's choice.

The winner is decided by a set of rules:

:   :   :   * Rock beats scissors
            * Scissors beat paper
            * Paper beats rock

If both players choose the same thing, there is no winner for that round.

For this task, the computer will be one of the players.

The operator will select Rock, Paper or Scissors and the computer will keep a record of the choice frequency, and use that information to make a weighted random choice in an attempt to defeat its opponent.

Extra credit

Support additional choices   additional weapons.

[Assistant]
(formerly Perl 6)
This is slightly more complicated than it could be; it is a general case framework with input filtering. It weights the computers choices based on your previous choices. Type in at least the first two characters of your choice, or just hit enter to quit. Customize it by supplying your own %vs options/outcomes.

Here is standard Rock-Paper-Scissors.

```
my %vs = (
    options => [<Rock Paper Scissors>],
    ro => {
        ro => [ 2, ''                        ],
        pa => [ 1, 'Paper covers Rock: '     ],
        sc => [ 0, 'Rock smashes Scissors: ' ]
    },
    pa => {
        ro => [ 0, 'Paper covers Rock: '    ],
        pa => [ 2, ''                       ],
        sc => [ 1, 'Scissors cut Paper: '   ]
    },
    sc => {
        ro => [ 1, 'Rock smashes Scissors: '],
        pa => [ 0, 'Scissors cut Paper: '   ],
        sc => [ 2, ''                       ]
    }
);

my %choices = %vs<options>.map({; $_.substr(0,2).lc => $_ });
my $keys    = %choices.keys.join('|');
my $prompt  = %vs<options>.map({$_.subst(/(\w\w)/, -> $/ {"[$0]"})}).join(' ')~"? ";
my %weight  = %choices.keys »=>» 1;

my @stats = 0,0,0;
my $round;

while my $player = (prompt "Round {++$round}: " ~ $prompt).lc {
    $player.=substr(0,2);
    say 'Invalid choice, try again.' and $round-- and next
      unless $player.chars == 2 and $player ~~ /<$keys>/;
    my $computer = (flat %weight.keys.map( { $_ xx %weight{$_} } )).pick;
    %weight{$_.key}++ for %vs{$player}.grep( { $_.value[0] == 1 } );
    my $result = %vs{$player}{$computer}[0];
    @stats[$result]++;
    say "You chose %choices{$player},  Computer chose %choices{$computer}.";
    print %vs{$player}{$computer}[1];
    print ( 'You win!', 'You Lose!','Tie.' )[$result];
    say " - (W:{@stats[0]} L:{@stats[1]} T:{@stats[2]})\n",
};

```

Example output:

```
Round 1: [Ro]ck [Pa]per [Sc]issors? ro
You chose Rock,  Computer chose Paper.
Paper covers Rock: You Lose! - (W:0 L:1 T:0)

Round 2: [Ro]ck [Pa]per [Sc]issors? pa
You chose Paper,  Computer chose Scissors.
Scissors cut Paper: You Lose! - (W:0 L:2 T:0)

Round 3: [Ro]ck [Pa]per [Sc]issors? pa
You chose Paper,  Computer chose Scissors.
Scissors cut Paper: You Lose! - (W:0 L:3 T:0)

Round 4: [Ro]ck [Pa]per [Sc]issors? ro
You chose Rock,  Computer chose Rock.
Tie. - (W:0 L:3 T:1)

Round 5: [Ro]ck [Pa]per [Sc]issors? sc
You chose Scissors,  Computer chose Scissors.
Tie. - (W:0 L:3 T:2)
...
```

Here is example output from the same code only with a different %vs data structure implementing Rock-Paper-Scissors-Lizard-Spock.

```
my %vs = (
    options => [<Rock Paper Scissors Lizard Spock>],
    ro => {
        ro => [ 2, ''                            ],
        pa => [ 1, 'Paper covers Rock: '         ],
        sc => [ 0, 'Rock smashes Scissors: '     ],
        li => [ 0, 'Rock crushes Lizard: '       ],
        sp => [ 1, 'Spock vaporizes Rock: '      ]
    },
    pa => {
        ro => [ 0, 'Paper covers Rock: '         ],
        pa => [ 2, ''                            ],
        sc => [ 1, 'Scissors cut Paper: '        ],
        li => [ 1, 'Lizard eats Paper: '         ],
        sp => [ 0, 'Paper disproves Spock: '     ]
    },
    sc => {
        ro => [ 1, 'Rock smashes Scissors: '     ],
        pa => [ 0, 'Scissors cut Paper: '        ],
        sc => [ 2, ''                            ],
        li => [ 0, 'Scissors decapitate Lizard: '],
        sp => [ 1, 'Spock smashes Scissors: '    ]
    },
    li => {
        ro => [ 1, 'Rock crushes Lizard: '       ],
        pa => [ 0, 'Lizard eats Paper: '         ],
        sc => [ 1, 'Scissors decapitate Lizard: '],
        li => [ 2, ''                            ],
        sp => [ 0, 'Lizard poisons Spock: '      ]
    },
    sp => {
        ro => [ 0, 'Spock vaporizes Rock: '      ],
        pa => [ 1, 'Paper disproves Spock: '     ],
        sc => [ 0, 'Spock smashes Scissors: '    ],
        li => [ 1, 'Lizard poisons Spock: '      ],
        sp => [ 2, ''                            ]
    }
);

```

```
Round 1: [Ro]ck [Pa]per [Sc]issors [Li]zard [Sp]ock? li
You chose Lizard,  Computer chose Scissors.
Scissors decapitate Lizard: You Lose! - (W:0 L:1 T:0)

Round 2: [Ro]ck [Pa]per [Sc]issors [Li]zard [Sp]ock? sp
You chose Spock,  Computer chose Paper.
Paper disproves Spock: You Lose! - (W:0 L:2 T:0)

Round 3: [Ro]ck [Pa]per [Sc]issors [Li]zard [Sp]ock? ro
You chose Rock,  Computer chose Lizard.
Rock crushes Lizard: You Win! - (W:1 L:2 T:0)

Round 4: [Ro]ck [Pa]per [Sc]issors [Li]zard [Sp]ock? ro
You chose Rock,  Computer chose Scissors.
Rock smashes Scissors: You win! - (W:2 L:2 T:0)

Round 5: [Ro]ck [Pa]per [Sc]issors [Li]zard [Sp]ock? li
You chose Lizard,  Computer chose Paper.
Lizard eats Paper: You win! - (W:3 L:2 T:0)
...
```


[User]
Task

Rotate a point about some axis by some angle using Rodrigues' rotation formula.

Reference

* Wikipedia: Rodrigues' rotation formula

[Assistant]
```
sub infix:<⋅> { [+] @^a »×« @^b }
sub norm      (@v) { sqrt @v⋅@v }
sub normalize (@v) { @v X/ @v.&norm }
sub getAngle  (@v1,@v2) { 180/π × acos (@v1⋅@v2) / (@v1.&norm × @v2.&norm) }

sub crossProduct ( @v1, @v2 ) {
    my \a = <1 2 0>; my \b = <2 0 1>;
    (@v1[a] »×« @v2[b]) »-« (@v1[b] »×« @v2[a])
}

sub aRotate ( @p, @v, $a ) {
    my \ca = cos $a/180×π;
    my \sa = sin $a/180×π;
    my \t = 1 - ca;
    my (\x,\y,\z) = @v;
    map { @p⋅$_ },
        [   ca + x×x×t, x×y×t -  z×sa, x×z×t +  y×sa],
        [x×y×t +  z×sa,    ca + y×y×t, y×z×t -  x×sa],
        [z×x×t -  y×sa, z×y×t +  x×sa,    ca + z×z×t]
}

my @v1 = [5,-6,  4];
my @v2 = [8, 5,-30];
say join ' ', aRotate @v1, normalize(crossProduct @v1, @v2), getAngle @v1, @v2;

```

Output:

```
2.232221073308229 1.3951381708176411 -8.370829024905852
```

Alternately, differing mostly in style:

```
sub infix:<•> { sum @^v1 Z× @^v2 } # dot product

sub infix:<❌> (@v1, @v2) {         # cross product
    my \a = <1 2 0>; my \b = <2 0 1>;
    @v1[a] »×« @v2[b] »-« @v1[b] »×« @v2[a]
}

sub norm (*@v) { sqrt @v • @v }

sub normal (*@v) { @v X/ @v.&norm }

sub angle-between (@v1, @v2) { acos( (@v1 • @v2) / (@v1.&norm × @v2.&norm) ) }

sub infix:<> is equiv(&infix:<×>) { $^a × $^b } # invisible times

sub postfix:<°> (\d) { d × τ / 360 } # degrees to radians

sub rodrigues-rotate( @point, @axis, $θ ) {
    my ( \cos𝜃, \sin𝜃 ) = cis($θ).reals;
    my ( \𝑥, \𝑦, \𝑧 )   = @axis;
    my \𝑡 = 1 - cos𝜃;

    map @point • *, [
       [ 𝑥²𝑡 + cos𝜃, 𝑦𝑥𝑡 - 𝑧sin𝜃, 𝑧𝑥𝑡 + 𝑦sin𝜃 ],
       [ 𝑥𝑦𝑡 + 𝑧sin𝜃, 𝑦²𝑡 + cos𝜃, 𝑧𝑦𝑡 - 𝑥sin𝜃 ],
       [ 𝑥𝑧𝑡 - 𝑦sin𝜃, 𝑦𝑧𝑡 + 𝑥sin𝜃, 𝑧²𝑡 + cos𝜃 ]
    ]
}

sub point-vector (@point, @vector) {
    rodrigues-rotate @point, normal(@point ❌ @vector), angle-between @point, @vector
}

put qq:to/TESTING/;
Task example - Point and composite axis / angle:
{ point-vector [5, -6, 4], [8, 5, -30] }

Perhaps more useful, (when calculating a range of motion for a robot appendage,
for example), feeding a point, axis of rotation and rotation angle separately;
since theoretically, the point vector and axis of rotation should be constant:

{
(0, 10, 20 ... 180).map( { # in degrees
    sprintf "Rotated %3d°: %.13f, %.13f, %.13f", $_,
    rodrigues-rotate [5, -6, 4], ([5, -6, 4] ❌ [8, 5, -30]).&normal, .°
}).join: "\n"
}
TESTING

```

Output:

```
Task example - Point and composite axis / angle:
2.232221073308228 1.3951381708176427 -8.370829024905852

Perhaps more useful, (when calculating a range of motion for a robot appendage,
for example), feeding a point, axis of rotation and rotation angle directly;
since theoretically, the point vector and axis of rotation should be constant:

Rotated   0°: 5.0000000000000, -6.0000000000000, 4.0000000000000
Rotated  10°: 5.7240554466526, -6.0975296976939, 2.6561853906284
Rotated  20°: 6.2741883650704, -6.0097890410223, 1.2316639322573
Rotated  30°: 6.6336832449081, -5.7394439854392, -0.2302810114435
Rotated  40°: 6.7916170161550, -5.2947088286573, -1.6852289831393
Rotated  50°: 6.7431909410900, -4.6890966233686, -3.0889721249495
Rotated  60°: 6.4898764214992, -3.9410085899762, -4.3988584118384
Rotated  70°: 6.0393702908772, -3.0731750048240, -5.5750876118134
Rotated  80°: 5.4053609500356, -2.1119645522518, -6.5819205958338
Rotated  90°: 4.6071124519719, -1.0865831254651, -7.3887652531624
Rotated 100°: 3.6688791733663, -0.0281864202486, -7.9711060171693
Rotated 110°: 2.6191688576205, 1.0310667150840, -8.3112487584187
Rotated 120°: 1.4898764214993, 2.0589914100238, -8.3988584118384
Rotated 130°: 0.3153148442246, 3.0243546928699, -8.2312730024418
Rotated 140°: -0.8688274150348, 3.8978244887705, -7.8135845280911
Rotated 150°: -2.0265707929363, 4.6528608599741, -7.1584842417190
Rotated 160°: -3.1227378427887, 5.2665224084086, -6.2858770340300
Rotated 170°: -4.1240220834695, 5.7201633384526, -5.2222766334692
Rotated 180°: -5.0000000000000, 6.0000000000000, -4.0000000000000
```


[User]
Task

Create a function taking a positive integer as its parameter and returning a string containing the Roman numeral representation of that integer. Modern Roman numerals are written by expressing each digit separately, starting with the left most digit and skipping any digit with a value of zero.

In Roman numerals:

* 1990 is rendered: 1000=M, 900=CM, 90=XC; resulting in MCMXC
* 2008 is written as 2000=MM, 8=VIII; or MMVIII
* 1666 uses each Roman symbol in descending order: MDCLXVI

[Assistant]
(formerly Perl 6)

```
my %symbols =
    1 => "I", 5 => "V", 10 => "X", 50 => "L", 100 => "C",
    500 => "D", 1_000 => "M";

my @subtractors =
    1_000, 100,  500, 100,  100, 10,  50, 10,  10, 1,  5, 1,  1, 0;

multi sub roman (0) { '' }
multi sub roman (Int $n) {
    for @subtractors -> $cut, $minus {
        $n >= $cut
            and return %symbols{$cut} ~ roman($n - $cut);
        $n >= $cut - $minus
            and return %symbols{$minus} ~ roman($n + $minus);
     }
}

# Sample usage

for 1 .. 2_010 -> $x {
    say roman($x);
}
```


[User]
Find all eigenvalues of a real 3x3 matrix and estimate their errors.

See Wikipedia Cubic equation. [1]
Example.

a\*x\*\*3 + b\*x\*\*2 + c\*x + d = 0

matrix: [[1,-1,0], [0,1,-1],[0,0,1]]

polynomial: [a,b,c,d] =[1, -3,+3, -1]

roots: [1,1,1]

[Assistant]
```
my \r = 1/sqrt(2);
my Pair @m = [[
      triple       => [[ 1, -1,  0], [ 0,  1, -1], [ 0,  0,  1] ],
      double       => [[ 2,  0,  0], [ 0, -1,  0], [ 0,  0, -1] ],
      distinct     => [[ 2,  0,  0], [ 0,  3,  4], [ 0,  4,  9] ],
      rotation     => [[ 1,  0,  0], [ 0,  r, -r], [ 0,  r,  r] ],
   ]];
for ^@m {
   my Pair $pair = @m[$_];                  print "\n  {1+$_}:  {$pair.key} ";
   my @t = $pair.value.[];                  say 'matrix: 	  ', @t.raku;
   my @poly = polynomial( @t );             say 'polynomial:  ', @poly.raku;
   my @reduction = reduction( |@poly );     say 'reduction :  ', @reduction.raku;
   my ( $s, $e ) = spectrum( @t );          say 'eigenvalues: ', @$s.raku;
                                            say 'errors: 	  ', @$e.raku;
}
sub horner( \x, \a, \b, \c, \d ) {          # cubic polynomial using horner's method
    ((a * x + b) * x + c) * x + d
}
sub polynomial( @t ) {
    my \a = 1;                                  # create characteristic polynomial
    my \b = -(@t[0;0] + @t[1;1] + @t[2;2]);                     # = -trace
    my \c = ( @t[0;0]*@t[1;1] + @t[1;1]*@t[2;2] + @t[2;2]*@t[0;0] )
            -(@t[1;2]*@t[2;1] + @t[2;0]*@t[0;2] + @t[0;1]*@t[1;0] );
    my \d = - @t[0;0] * @t[1;1] * @t[2;2]
            - @t[0;1] * @t[1;2] * @t[2;0]
            - @t[0;2] * @t[1;0] * @t[2;1]
            + @t[0;0] * @t[2;1] * @t[1;2]
            + @t[0;1] * @t[1;0] * @t[2;2]
            + @t[0;2] * @t[1;1] * @t[2;0];                  # = -determinant
    return [ a, b, c, d]>>.narrow;
}
sub reduction( \a, \b, \c, \d ) {
    my \delta = 18 * a * b * c * d - 4 * b **3 * d + b**2 * c**2 - 4 * a * c**3 - 27 * a**2 * d**2;
    my \p = (3 * a * c - b * b) / (3 * a * a);
    my \q = (2 * b ** 3 - 9 * a * b * c + 27 * a ** 2 * d) / (27 * a ** 3);
    my \d0 = b*b - 3 * a * c;
    my \d1 = 2*b**3 - 9*a*b*c + 27 * a**2 * d;
    return [ delta, p, q, d0, d1 ];
}
sub solution( \a, \b, \c, \d, \delta, \p, \q, \d0, \d1 ) {
    my @x;
    if abs(delta) =~= 0 {           # say " multiple real roots ", p.raku ;
        if abs(p) =~= 0 {           # say " triple equal real roots: ";;
            @x[$_] = 0 for ^3;
        }
        else {                      # say ' double real root:';
            @x[0] = 3 * q / p;
            @x[1] = -3 * q /(2 * p);
            @x[2] = @x[1];
        }
    }
    elsif delta > 0 {               # say " three distinct real roots:";
        @x[$_] = 2*sqrt(-p/3) * cos( acos( sqrt( -3 / p ) * 3 * q /( 2 * p ) )/3 - 2*pi * $_/ 3 ) for ^3;
    }
    else {      # delta < 0;        say " one real root and two complex conjugate roots:";
        my $g = do {
            if d0 == 0 and d1 < 0 {
                -(-d1)**⅓;
            }
            elsif d0 < 0 and d1 == 0 {
                -sqrt(-d0);
            }
            else {
                my \s = Complex( d1**2 - 4 * d0**3 ).sqrt;
                my \g1 = (( d1 + s )/2)**⅓;
                my \g2 = (( d1 - s )/2)**⅓;
                g1 == 0 ?? g2 !! g1
            }
        }
        my Complex $z = $g * ( -1 + Complex(-3).sqrt )/2;
        @x[0] = -⅓ * ( $g + d0 / $g );
        @x[1] = -⅓ * ( $z + d0 / $z );
        @x[2] = @x[1].conj;
    }
    @x[$_] -= ⅓ * b / a for ^3;
    return @x;
}
sub spectrum( @mat ) {
    my ( \a, \b, \c, \d )         = polynomial( @mat );
    my (\delta, \p, \q, \d0, \d1) = reduction( a, b, c, d );
    my @s = solution( a, b, c, d, delta, p, q, d0, d1 )>>.narrow;
    my @e = @s.map( { horner( $_, a, b, c, d ) })>>.narrow;
    return ( @s, @e );
}

```

Output:

```
 1:  triple matrix: [[1, -1, 0], [0, 1, -1], [0, 0, 1]]
polynomial:  [1, -3, 3, -1]
reduction :  [0, 0.0, 0.0, 0, 0]
eigenvalues: [1, 1, 1]
errors:      [0, 0, 0]

  2:  double matrix: [[2, 0, 0], [0, -1, 0], [0, 0, -1]]
polynomial:  [1, 0, -3, -2]
reduction :  [0, -3.0, -2.0, 9, -54]
eigenvalues: [2, -1, -1]
errors:      [0, 0, 0]

  3:  distinct matrix: [[2, 0, 0], [0, 3, 4], [0, 4, 9]]
polynomial:  [1, -14, 35, -22]
reduction :  [8100, <-91/3>, <-1672/27>, 91, -1672]
eigenvalues: [11, 2, 0.9999999999999991e0]
errors:      [0, 0, -1.0658141036401503e-14]

  4: rotation matrix: [[1, 0, 0], [0, 0.7071067811865475e0, -0.7071067811865475e0], [0, 0.7071067811865475e0, 0.7071067811865475e0]]
polynomial:  [1, -2.414213562373095e0, 2.414213562373095e0, -0.9999999999999998e0]
reduction :  [-0.6862915010152442e0, 0.4714045207910316e0, -0.0994922778153789e0, -1.414213562373095e0, -2.68629150101523e0]
eigenvalues: [0.9999999999999992e0, <0.7071067811865478-0.7071067811865472i>, <0.7071067811865478+0.7071067811865472i>]
errors:      [0, <-3.3306690738754696e-16-3.885780586188048e-16i>, <-3.3306690738754696e-16+3.885780586188048e-16i>]

```


[User]
Task

Create a program that finds and outputs the roots of a given function, range and (if applicable) step width.

The program should identify whether the root is exact or approximate.

For this task, use:      ƒ(x)   =   x3 - 3x2 + 2x

[Assistant]
(formerly Perl 6)
Uses exact arithmetic.

```
sub f(\x) { x³ - 3*x² + 2*x }

my $start = -1;
my $stop = 3;
my $step = 0.001;

for $start, * + $step ... $stop -> $x {
    state $sign = 0;
    given f($x) {
        my $next = .sign;
        when 0.0 {
            say "Root found at $x";
        }
        when $sign and $next != $sign {
            say "Root found near $x";
        }
        NEXT $sign = $next;
    }
}

```

Output:

```
Root found at 0
Root found at 1
Root found at 2
```


[User]
This task has been clarified. Its programming examples are in need of review to ensure that they still fit the requirements of the task.

Write a program to find the roots of a quadratic equation, i.e., solve the equation

a

x

2
+
b
x
+
c
=
0
{\displaystyle {\displaystyle ax^{2}+bx+c=0}}
.
Your program must correctly handle non-real roots, but it need not check that

a
≠
0
{\displaystyle {\displaystyle a\neq 0}}
.

The problem of solving a quadratic equation is a good example of how dangerous it can be to ignore the peculiarities of floating-point arithmetic.
The obvious way to implement the quadratic formula suffers catastrophic loss of accuracy when one of the roots to be found is much closer to 0 than the other.
In their classic textbook on numeric methods *Computer Methods for Mathematical Computations*, George Forsythe, Michael Malcolm, and Cleve Moler suggest trying the naive algorithm with

a
=
1
{\displaystyle {\displaystyle a=1}}
,

b
=
−

10

5
{\displaystyle {\displaystyle b=-10^{5}}}
, and

c
=
1
{\displaystyle {\displaystyle c=1}}
.
(For double-precision floats, set

b
=
−

10

9
{\displaystyle {\displaystyle b=-10^{9}}}
.)
Consider the following implementation in Ada:

```
with Ada.Text_IO;                        use Ada.Text_IO;
with Ada.Numerics.Elementary_Functions;  use Ada.Numerics.Elementary_Functions;

procedure Quadratic_Equation is
   type Roots is array (1..2) of Float;
   function Solve (A, B, C : Float) return Roots is
      SD : constant Float := sqrt (B**2 - 4.0 * A * C);
      AA : constant Float := 2.0 * A;
   begin
      return ((- B + SD) / AA, (- B - SD) / AA);
   end Solve;

   R : constant Roots := Solve (1.0, -10.0E5, 1.0);
begin
   Put_Line ("X1 =" & Float'Image (R (1)) & " X2 =" & Float'Image (R (2)));
end Quadratic_Equation;

```

Output:

```
X1 = 1.00000E+06 X2 = 0.00000E+00
```

As we can see, the second root has lost all significant figures. The right answer is that `X2` is about

10

−
6
{\displaystyle {\displaystyle 10^{-6}}}
. The naive method is numerically unstable.

Suggested by Middlebrook (D-OA), a better numerical method: to define two parameters

q
=

a
c

/
b
{\displaystyle {\displaystyle q={\sqrt {ac}}/b}}
 and

f
=
1

/
2
+

1
−
4

q

2

/
2
{\displaystyle {\displaystyle f=1/2+{\sqrt {1-4q^{2}}}/2}}

and the two roots of the quardratic are:

−
b
a
f
{\displaystyle {\displaystyle {\frac {-b}{a}}f}}
 and

−
c

b
f
{\displaystyle {\displaystyle {\frac {-c}{bf}}}}

**Task**: do it better. This means that given

a
=
1
{\displaystyle {\displaystyle a=1}}
,

b
=
−

10

9
{\displaystyle {\displaystyle b=-10^{9}}}
, and

c
=
1
{\displaystyle {\displaystyle c=1}}
, both of the roots your program returns should be greater than

10

−
11
{\displaystyle {\displaystyle 10^{-11}}}
. Or, if your language can't do floating-point arithmetic any more precisely than single precision, your program should be able to handle

b
=
−

10

6
{\displaystyle {\displaystyle b=-10^{6}}}
. Either way, show what your program gives as the roots of the quadratic in question. See page 9 of
"What Every Scientist Should Know About Floating-Point Arithmetic" for a possible algorithm.

[Assistant]
(formerly Perl 6)

**Works with**: Rakudo version 2022.12

*Works with previous versions also but will return slightly less precise results.*

Raku has complex number handling built in.

```
for
[1, 2, 1],
[1, 2, 3],
[1, -2, 1],
[1, 0, -4],
[1, -10⁶, 1]
-> @coefficients {
    printf "Roots for %d, %d, %d\t=> (%s, %s)\n",
    |@coefficients, |quadroots(@coefficients);
}

sub quadroots (*[$a, $b, $c]) {
    ( -$b + $_ ) / (2 × $a),
    ( -$b - $_ ) / (2 × $a)
    given
    ($b² - 4 × $a × $c ).Complex.sqrt.narrow
}

```

Output:

```
Roots for 1, 2, 1	=> (-1, -1)
Roots for 1, 2, 3	=> (-1+1.4142135623730951i, -1-1.4142135623730951i)
Roots for 1, -2, 1	=> (1, 1)
Roots for 1, 0, -4	=> (2, -2)
Roots for 1, -1000000, 1	=> (999999.999999, 1.00000761449337e-06)
```


[User]
The purpose of this task is to explore working with   complex numbers.

Task

Given   **n**,   find the   **n**th   roots of unity.

[Assistant]
(formerly Perl 6)
Raku has a built-in function cis which returns a unitary complex number given its phase. Raku also defines the tau = 2\*pi constant. Thus the k-th n-root of unity can simply be written cis(k\*τ/n).

```
constant n = 10;
for ^n -> \k {
    say cis(k*τ/n);
}

```

Output:

```
1+0i
0.809016994374947+0.587785252292473i
0.309016994374947+0.951056516295154i
-0.309016994374947+0.951056516295154i
-0.809016994374947+0.587785252292473i
-1+1.22464679914735e-16i
-0.809016994374948-0.587785252292473i
-0.309016994374948-0.951056516295154i
0.309016994374947-0.951056516295154i
0.809016994374947-0.587785252292473i
```

Alternately, you could use the built-in .roots method to find the nth roots of any number.

```
.say for 1.roots(9)

```

Output:

```
1+0i
0.766044443118978+0.6427876096865393i
0.17364817766693041+0.984807753012208i
-0.4999999999999998+0.8660254037844387i
-0.9396926207859083+0.3420201433256689i
-0.9396926207859084-0.34202014332566866i
-0.5000000000000004-0.8660254037844384i
0.17364817766692997-0.9848077530122081i
0.7660444431189778-0.6427876096865396i
```


[User]
Find the total number of programming examples for each task and the total for all tasks.

Essentially, count the number of occurrences of =={{header| on each task page.

Output:

```
100 doors: 20 examples.
99 Bottles of Beer: 29 examples.
Abstract type: 10 examples.

Total: X examples.
```

For a full output, updated periodically, see Rosetta Code/Count examples/Full list.

You'll need to use the Media Wiki API, which you can find out about locally, here, or in Media Wiki's API documentation at, API:Query

[Assistant]
(formerly Perl 6)

**Works with**: Rakudo version 2018.12

Retrieves counts for both Tasks and Draft Tasks. Save / Display results as a sortable wikitable rather than a static list. Click on a column header to sort on that column. To do a secondary sort, hold down the shift key and click on a second column header. Tasks have a gray (default) background, Draft Tasks have a yellow background.

This example tracks the top 50 languages by number of examples completed but only generates reports in tiers of 10. More than 10 gets too heavy and difficult to navigate.

Feed it parameters to control behaviour:

* :nf or :no-fetch to use saved information to generate the different reports. Recommended for the second, third, fourth, whatever report you are generating at any one time as fetching from the site is *by far* the most time consuming part.
* :t=1 (or :tier=1). :t=2, :t=3, whatever, up to :t=5 to control which tier of results to generate.

Language names with spaces will have underscores inserted to make the results uniform. Some oddball languages (lookin' at you Icon and Unicon) make it very difficult to obtain accurate results. The whole "conglomerate all of the Basic dialects together" movement of a few years ago also complicates things, but this should be pretty close.

For a full output, see Top tier, Second tier, Third tier, Fourth tier

```
use HTTP::UserAgent;
use URI::Escape;
use JSON::Fast;
use Lingua::EN::Numbers :short;

unit sub MAIN ( Bool :nf(:$no-fetch) = False, :t(:$tier) = 1 );

# Friendlier descriptions for task categories
my %cat = (
    'Programming_Tasks' => 'Task',
    'Draft_Programming_Tasks' => 'Draft'
);

my $client = HTTP::UserAgent.new;
$client.timeout = 10;

my $url = 'https://rosettacode.org/w';

my $hashfile  = './RC_Task_count.json';
my $tablefile = "./RC_Task_count-{$tier}.txt";

my %tasks;

my @places = <① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ㉑ ㉒ ㉓ ㉔ ㉕
      ㉖ ㉗ ㉘ ㉙ ㉚ ㉛ ㉜ ㉝ ㉞ ㉟ ㊱ ㊲ ㊳ ㊴ ㊵ ㊶ ㊷ ㊸ ㊹ ㊺ ㊺ ㊻ ㊼ ㊽ ㊾ ㊿>;

# clear screen
run($*DISTRO.is-win ?? 'cls' !! 'clear') unless $no-fetch;

my %counts =
    mediawiki-query(
        $url, 'pages',
        :generator<categorymembers>,
        :gcmtitle<Category:Programming Languages>,
        :gcmlimit<350>,
        :rawcontinue(),
        :prop<categoryinfo>
    )
    .map({ .<title>.subst(/^'Category:'/, '') => .<categoryinfo><pages> || 0 });

my $per-tier = 10;

my $which = (^$per-tier) »+» $per-tier * ($tier - 1);

my @top-n = %counts.sort( {-.value, .key} )[|$which].map: *.key.trans(' ' => '_');

# dump a copy to STDOUT, mostly for debugging purposes
say "<pre>{tc $tier.&ord-n} {$per-tier.&card} programming languages by number of task examples completed:";
say '    ', join ' ', .map( {("{(@places[|$which])[$_]} {@top-n[$_]}").fmt("%-15s")} ) for (^@top-n).batch(5);
say "</pre>\n";

unless $no-fetch {

    note 'Retrieving task information...';

    mkdir('./pages') unless './pages'.IO.e;

    @top-n = %counts.sort( {-.value, .key} )[^@places].map: *.key.trans(' ' => '_');;

    for %cat.keys.sort -> $cat {
        mediawiki-query(
            $url, 'pages',
            :generator<categorymembers>,
            :gcmtitle("Category:$cat"),
            :gcmlimit<350>,
            :rawcontinue(),
            :prop<title>
        ).map({
            my $page;
            my $response;

            loop {
                $response = $client.get("{ $url }/index.php?title={ uri-escape .<title> }&action=raw");
                if $response.is-success {
                    $page = $response.content;
                    last;
                } else {
                    redo;
                }
            }

            "./pages/{ uri-escape .<title>.subst(/' '/, '_', :g) }".IO.spurt($page);
            my $lc = $page.lc.trans(' ' => '_');
            my $count = +$lc.comb(/ ^^'==' <-[\n=]>* '{{header|' <-[}]>+? '}}==' \h* $$ /);
            %tasks{.<title>} = {'cat' => %cat{$cat}, :$count};
            %tasks{.<title>}<top-n> = (^@top-n).map( {
                ($lc.contains("==\{\{header|{@top-n[$_].lc}}}") or
                 # Deal with 3 part headers - {{header|F_Sharp|F#}}, {{header|C_Sharp|C#}}, etc.
                 $lc.contains("==\{\{header|{@top-n[$_].lc}|")  or
                 # Icon and Unicon are their own special flowers
                 $lc.contains("}}_and_\{\{header|{@top-n[$_].lc}}}==") or
                 # Language1 / Language2 for shared entries (e.g. C / C++)
                 $lc.contains(rx/'}}''_'*'/''_'*'{{header|'$(@top-n[$_].lc)'}}=='/)) ??
                (@places[$_]) !!
                 # Check if the task was omitted
                 $lc.contains("\{\{omit_from|{@top-n[$_].lc}") ?? 'O' !!
                 # The task is neither done or omitted
                 ' '
            } ).join;
            print clear, 1 + $++, ' ', %cat{$cat}, ' ', .<title>;
        })
    }

    print clear;

    note "\nTask information saved to local file: {$hashfile.IO.absolute}";
    $hashfile.IO.spurt(%tasks.&to-json);

}

# Load information from local file
%tasks = $hashfile.IO.e ?? $hashfile.IO.slurp.&from-json !! ( );

@top-n = %counts.sort( {-.value, .key} )[|$which].map: *.key.trans(' ' => '_');

# Convert saved task info to a table
note "\nBuilding table...";
my $count    = +%tasks;
my $taskcnt  = +%tasks.grep: *.value.<cat> eq %cat<Programming_Tasks>;
my $draftcnt = $count - $taskcnt;
my $total    = sum %tasks{*}»<count>;

# Dump table to a file
my $out = open($tablefile, :w)  or die "$!\n";

$out.say: "<pre>{tc $tier.&ord-n} {$per-tier.&card} programming languages by number of task examples completed:";
$out.say: '    ', join ' ', .map( {("{(@places[|$which])[$_]} {@top-n[$_]}").fmt("%-15s")} ) for (^@top-n).batch(5);
$out.say: "</pre>\n\n<div style=\"height:40em;overflow:scroll;\">";

# Add table boilerplate and caption
$out.say:
    '{|class="wikitable sortable"', "\n",
    "|+ As of { DateTime.new(time) } :: Tasks: { $taskcnt } ::<span style=\"background-color:#ffd\"> Draft Tasks:",
    "{ $draftcnt } </span>:: Total Tasks: { $count } :: Total Examples: { $total }\n",
    "!Count!!Task!!{(@places[|$which]).join('!!')}"
;

# Sort tasks by count then add row
for %tasks.sort: { [-.value<count>, .key] } -> $task {
    $out.say:
      ( $task.value<cat> eq 'Draft'
        ?? "|- style=\"background-color: #ffc\"\n"
        !! "|-\n"
      ),
      "| { $task.value<count> }\n",
      ( $task.key ~~ /\d/
        ?? "|data-sort-value=\"{ $task.key.&naturally }\"| [[{uri-escape $task.key}|{$task.key}]]\n"
        !! "| [[{uri-escape $task.key}|{$task.key}]]\n"
      ),
      "|{ $task.value<top-n>.comb[|$which].join('||') }"
}

$out.say( "|}\n</div>" );
$out.close;

note "Table file saved as: {$tablefile.IO.absolute}";

sub mediawiki-query ($site, $type, *%query) {
    my $url = "$site/api.php?" ~ uri-query-string(
        :action<query>, :format<json>, :formatversion<2>, |%query);
    my $continue = '';

    gather loop {
        my $response = $client.get("$url&$continue");
        my $data = from-json($response.content);
        take $_ for $data.<query>.{$type}.values;
        $continue = uri-query-string |($data.<query-continue>{*}».hash.hash or last);
    }
}

sub uri-query-string (*%fields) { %fields.map({ "{.key}={uri-escape .value}" }).join("&") }

sub naturally ($a) { $a.lc.subst(/(\d+)/, ->$/ {0~(65+$0.chars).chr~$0},:g) }

sub clear { "\r" ~ ' ' x 116 ~ "\r" }

```

Abridged output:

```
Top ten programming language by number of task examples completed:
① Go
② Perl 6
③ Kotlin
④ Python
⑤ Phix
⑥ Racket
⑦ Perl
⑧ C
⑨ Julia
⑩ Tcl

```

As of 2019-01-21T22:41:28Z :: Tasks: 924 :: Draft Tasks:215 :: Total Tasks: 1139 :: Total Examples: 59984

| Count | Task | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 405 | Hello world/Text | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |
| 283 | 99 Bottles of Beer | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |
| 276 | FizzBuzz | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |
| 273 | 100 doors | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |
| 251 | Fibonacci sequence | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |
| 246 | Comments | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |
| 239 | Factorial | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |
| 223 | Empty program | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |
| 222 | A+B | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |
| 214 | Function definition | ① | ② | ③ | ④ | ⑤ | ⑥ | ⑦ | ⑧ | ⑨ | ⑩ |


[User]
Task

Find all    <lang>    tags without a language specified in the text of a page.

Display counts by language section:

```
Description

<lang>Pseudocode</lang>

=={{header|C}}==
<lang C>printf("Hello world!\n");</lang>

=={{header|Perl}}==
<lang>print "Hello world!\n"</lang>

```

should display something like

```
2 bare language tags.

1 in perl
1 in no language

```

Extra credit

Allow multiple files to be read.   Summarize all results by language:

```
5 bare language tags.

2 in c ([[Foo]], [[Bar]])
1 in perl ([[Foo]])
2 in no language ([[Baz]])

```

Extra extra credit

Use the   Media Wiki API   to test actual RC tasks.

[Assistant]
(formerly Perl 6)

**Translation of**: Perl

The only tricky thing here is the use of the ms form of match, short for m:sigspace. This causes whitespace in the regex to be considered "significant", that is, it matches optional whitespace at those positions, as if you'd put \s\* there. Of course, the regexes themselves are in Raku syntax, which is quite different from Perl 5 regex syntax (and arguably much cleaner). Regex syntax is perhaps the area in which Raku diverges most from Perl 5.

```
my $lang = '(no language)';
my $total = 0;
my %blanks;

for lines() {
  when / '<lang>' / {
    %blanks{$lang}++;
    $total++;
  }
  when ms/ '==' '{{' 'header' '|' ( <-[}]>+? ) '}}' '==' / {
    $lang = $0.lc;
  }
}

say "$total bare language tag{ 's' if $total != 1 }\n";
say .value, ' in ', .key for %blanks.sort;

```

Output:

```
2 bare language tags

1 in (no language)
1 in perl
```


[User]
Task

Given the name of a language on Rosetta Code, find all tasks which are not implemented in that language.

Note: Implementations should allow for fetching more data than can be returned in one request to Rosetta Code.

You'll need to use the Media Wiki API, which you can find out about locally, here, or in Media Wiki's API documentation at, API:Query

[Assistant]
(formerly Perl 6)

**Works with**: Rakudo version 2018.04.1

```
use HTTP::UserAgent;
use URI::Escape;
use JSON::Fast;
use Sort::Naturally;

unit sub MAIN( Str :$lang = 'Raku' );

my $client = HTTP::UserAgent.new;
my $url = 'https://rosettacode.org/w';

my @total;
my @impl;

@total.append: .&get-cat for 'Programming_Tasks', 'Draft_Programming_Tasks';
@impl = get-cat $lang;

say "Unimplemented tasks in $lang:";
my @unimplemented = (@total (-) @impl).keys.sort: *.&naturally;
.say for @unimplemented;
say "{+@unimplemented} unimplemented tasks";

sub get-cat ($category) {
    flat mediawiki-query(
        $url, 'pages',
        :generator<categorymembers>,
        :gcmtitle("Category:$category"),
        :gcmlimit<350>,
        :rawcontinue(),
        :prop<title>
    ).map({ .<title> });
}

sub mediawiki-query ($site, $type, *%query) {
    my $url = "$site/api.php?" ~ uri-query-string(
        :action<query>, :format<json>, :formatversion<2>, |%query);
    my $continue = '';

    gather loop {
        my $response = $client.get("$url&$continue");
        my $data = from-json($response.content);
        take $_ for $data.<query>.{$type}.values;
        $continue = uri-query-string |($data.<query-continue>{*}».hash.hash or last);
    }
}

sub uri-query-string (*%fields) { %fields.map({ "{.key}={uri-escape .value}" }).join("&") }

```

Output:

*As of Sept. 2, 2022*

```
Unimplemented tasks in Raku:
3d turtle graphics
15 puzzle game in 3D
Addition-chain exponentiation
Audio alarm
Audio frequency generator
Audio overlap loop
Binary coded decimal
Black box
Blackjack strategy
Boids
Catmull–Clark subdivision surface
Chess player
CLI-based maze-game
Compare sorting algorithms' performance
Compiler/AST interpreter
Compiler/Preprocessor
Compiler/syntax analyzer
Create an executable for a program in an interpreted language
Cross compilation
Cycles of a permutation
Diophantine linear system solving
Dominoes
Elevator simulation
Execute Computer/Zero
Free polyominoes enumeration
Generalised floating point multiplication
Hexapawn
Honeycombs
IRC gateway
Morpion solitaire
Number triplets game
OLE automation
OpenGL pixel shader
P-Adic square roots
Play recorded sounds
Red black tree sort
Remote agent/Agent interface
Remote agent/Agent logic
Remote agent/Simulation
Simple turtle graphics
Solve a Rubik's cube
Solving coin problems
Sorting algorithms/Tree sort on a linked list
Tamagotchi emulator
Tetris
Ukkonen’s suffix tree construction
Unicode polynomial equation
Uno (card game)
Use a REST API
Waveform analysis/Top and tail
Weather routing
WebGL rotating F
52 unimplemented tasks
```


[User]
This task has been *revised* for the hosting change Rosetta Code has had in August 2022.

See the Python example for a new example to fit the revised task.

Task

Fix Rosetta Code deprecated code tags, with these rules:

```
Change <lang %s> to <syntaxhighlight lang=%s>
Change </lang> to </syntaxhighlight>
Change <lang> to <syntaxhighlight lang=text>

```

Demonstrate the task on these examples

```
<lang AutoHotkey>; usage: > fixtags.ahk input.txt ouput.txt
FileRead, text, %1%
langs = ada,awk,autohotkey,etc
slang = /lang
slang := "<" . slang . "/>"
Loop, Parse, langs, `,
{
  tag1 = <%A_LoopField%>
  tag2 = </%A_LoopField%>
  text := RegExReplace(text, tag1, "<lang " . A_LoopField . ">")
  text := RegExReplace(text, tag2, slang)
  text := RegExReplace(text, "<code (.+?)>(.*?)</code>"
          , "<lang $1>$2" . slang)
}
FileAppend, % text, %2%
</lang>

```

```
<lang perl>my @langs = qw(ada cpp-qt pascal lscript z80 visualprolog
html4strict cil objc asm progress teraterm hq9plus genero tsql
email pic16 tcl apt_sources io apache vhdl avisynth winbatch
vbnet ini scilab ocaml-brief sas actionscript3 qbasic perl bnf
cobol powershell php kixtart visualfoxpro mirc make javascript
cpp sdlbasic cadlisp php-brief rails verilog xml csharp
actionscript nsis bash typoscript freebasic dot applescript
haskell dos oracle8 cfdg glsl lotusscript mpasm latex sql klonec
ruby ocaml smarty python oracle11 caddcl robots groovy smalltalk
diff fortran cfm lua modula3 vb autoit java text scala
lotusformulas pixelbender reg _div whitespace providex asp css
lolcode lisp inno mysql plsql matlab oobas vim delphi xorg_conf
gml prolog bf per scheme mxml d basic4gl m68k gnuplot idl abap
intercal c_mac thinbasic java5 xpp boo klonecpp blitzbasic eiffel
povray c gettext);

my $text = join "", <STDIN>;
my $slang="/lang";
for (@langs) {
    $text =~ s|<$_>|<lang $_>|g;
    $text =~ s|</$_>|<$slang>|g;
}

$text =~ s|<code (.+?)>(.*?)</code>|<lang $1>$2<$slang>|sg;

print $text;</lang>

```

```
<lang>HAI 1.3

I HAS A bottles ITZ 99 I HAS A plural ITZ "Z" I HAS A lyric ITZ "99 BOTTLZ OV BEER"

IM IN YR song

   VISIBLE lyric " ON TEH WALL"
   VISIBLE lyric
   VISIBLE "TAEK 1 DOWN, PAZ IT AROUN"
   bottles R DIFF OF bottles AN 1
   NOT bottles, O RLY?
       YA RLY, VISIBLE "NO MOAR BOTTLZ OV BEER ON TEH WALL", GTFO
   OIC
   BOTH SAEM bottles AN 1, O RLY?
       YA RLY, plural R ""
   OIC
   lyric R SMOOSH bottles " BOTTL" plural " OV BEER" MKAY
   VISIBLE lyric " ON TEH WALL:)"
IM OUTTA YR song

KTHXBYE</lang>

```

[Assistant]
(formerly Perl 6)

```
my @langs = <
    abap actionscript actionscript3 ada apache applescript apt_sources
    asm asp autoit avisynth bash basic4gl bf blitzbasic bnf boo c caddcl
    cadlisp cfdg cfm cil c_mac cobol cpp cpp-qt csharp css d delphi
    diff _div dos dot eiffel email fortran freebasic genero gettext
    glsl gml gnuplot groovy haskell hq9plus html4strict idl ini inno
    intercal io java java5 javascript kixtart klonec klonecpp latex lisp
    lolcode lotusformulas lotusscript lscript lua m68k make matlab mirc
    modula3 mpasm mxml mysql nsis objc ocaml ocaml-brief oobas oracle11
    oracle8 pascal per perl php php-brief pic16 pixelbender plsql povray
    powershell progress prolog providex python qbasic rails reg robots
    ruby sas scala scheme scilab sdlbasic smalltalk smarty sql tcl teraterm
    text thinbasic tsql typoscript vb vbnet verilog vhdl vim visualfoxpro
    visualprolog whitespace winbatch xml xorg_conf xpp z80
>;

$_ = slurp;

for @langs -> $l {
    s:g:i [ '<' 'lang '?  $l '>' ] = "<lang $l>";
    s:g [ '</' $l '>' ] = '</' ~ 'lang>';
}

s:g [ '<code '(.+?) '>' (.*?) '</code>' ] = "<lang $0>{$1}</"~"lang>";

.say;

```

```
use v6;

constant @langs = < abap actionscript actionscript3 ada  … >;

slurp().subst(
    rx:r{
        | '<' <( $<need-add-space>=<?> )> @langs '>'
        | '</' <( @langs )> '>'
        | '<' '/'? <( code )> [<.ws> @langs]? '>'
    },
    'lang' ~ " " x *<need-add-space>.so,
    :g,
).print

```


[User]
In this task, the goal is to compile an authorship list for task descriptions. A pseudocode example (in imperative style) that should accomplish this is as follows:

```
for each task page
  grab page source, discard everything after the first ==section==.
Cache as $previous. Note $author.
  for each revision
    grab page source, discard everything after first ==section==.
Cache as $previous2. Note $author2
    compare $previous2 to $previous. If different, record $author to $list.
    replace $previous with $previous2
    replace $author with $author2
```

The following resources for HTTP interface information for MediaWiki may prove to be useful:

* https://www.mediawiki.org/wiki/Index.php#Raw
* https://www.mediawiki.org/wiki/Index.php#History
* https://www.mediawiki.org/wiki/API:Main\_page

Conversely, some languages have libraries which abstract these interfaces into language-native idioms. Use of these abstractions is perfectly fine.

Please **DO NOT** add a full output for *each* programming language; just show a representative sample. For an full listing, see Rosetta\_Code/List\_authors\_of\_task\_descriptions/Full\_list.

[Assistant]
(formerly Perl 6)

**Works with**: Rakudo version 2018.03

The pseudocode above is no longer really useful as the page format has changed significantly since this task was written. Rather than checking **every** edit to see if it was a change to the task description, we'll just assume the user that created the page is the task author. This isn't 100% accurate; a very few pages got renamed and recreated by someone other than the original author without preserving the history, so they are misreported (15 Puzzle Game for instance,) but is as good as it is likely to get without extensive manual intervention. Subsequent edits to the task description are not credited. As it is, we must still make *thousands* of requests and pound the server pretty hard. Checking **every** edit would make the task several of orders of magnitude more abusive of the server (and my internet connection.)

```
use HTTP::UserAgent;
use URI::Escape;
use JSON::Fast;
use Sort::Naturally;

# Friendlier descriptions for task categories
my %cat = (
    'Programming_Tasks' => 'Task',
    'Draft_Programming_Tasks' => 'Draft'
);

my $client = HTTP::UserAgent.new;

my $url = 'https://rosettacode.org/w';

my $tablefile = './RC_Authors.txt';
my $hashfile  = './RC_Authors.json';

my %tasks;

# clear screen
run($*DISTRO.is-win ?? 'cls' !! 'clear');

%tasks = $hashfile.IO.e ?? $hashfile.IO.slurp.&from-json !! ( );
sleep 1;

#=begin update

note 'Retrieving task information...';

my %filter;
for %cat.keys.sort -> $category {
    mediawiki-query(
        $url, 'pages',
        :generator<categorymembers>,
        :gcmtitle("Category:$category"),
        :gcmlimit<350>,
        :rawcontinue(),
        :prop<title>
    ).map( { %filter{.<title>} = %cat{$category} } )
}

my $delete = %tasks.keys (-) %filter.keys;

%tasks.delete($_) for $delete.keys; #Tasks that have changed names or been removed

my @add;
for %filter.keys -> $title {
    if %tasks{$title}:exists {
        %tasks{$title}<category> = %filter{$title} # update status
    } else {
        @add.push: $title => %filter{$title} # New Tasks
    }
}

if @add {
    .say for 'Adding new tasks:', |@add;
}

for @add -> $task {
    mediawiki-query(
        $url, 'pages',
        :titles($task.key),
        :prop<revisions>,
        :rvprop<user|timestamp>,
        :rvstart<2000-01-01T01:01:01Z>,
        :rvdir<newer>,
        :rvlimit<1>
    ).map: {
        print clear, 1 + $++, ' ', .[0]<title>;
        %tasks{.[0]<title>}<category> = $task.value;
        %tasks{.[0]<title>}<author> = .[0]<revisions>[0]<user>;
        %tasks{.[0]<title>}<date> = .[0]<revisions>[0]<timestamp>.subst(/'T'.+$/, '')
    }
}

print clear;

# Save information to a local file
note "\nTask information saved to local file: {$hashfile.IO.absolute}";
$hashfile.IO.spurt(%tasks.&to-json);

#=end update

# Load information from local file
%tasks = $hashfile.IO.e ?? $hashfile.IO.slurp.&from-json !! ( );

# Convert saved task / author info to a table
note "\nBuilding table...";
my $count    = +%tasks;
my $taskcnt  = +%tasks.grep: *.value.<category> eq %cat<Programming_Tasks>;
my $draftcnt = $count - $taskcnt;

# Open a file handle to dump table in
my $out = open($tablefile, :w)  or die "$!\n";

# Add table boilerplate and header
$out.say:
    "\{|class=\"wikitable sortable\"\n",
    "|+ As of { Date.today } :: Total Tasks: { $count }:: Tasks: { $taskcnt }",
    " ::<span style=\"background-color:#ffd\"> Draft Tasks: { $draftcnt } </span>",
    ":: By {+%tasks{*}».<author>.unique} Authors\n",
    "! Author !! Tasks !! Authored"
;

# Get sorted unique list of task authors
for %tasks{*}».<author>.unique.sort(&naturally) -> $author {

    # Get list of tasks by this author
    my @these = %tasks.grep( { $_.value.<author> eq $author } );
    my $s = +@these == 1 ?? '' !! 's';

    # Add author and contributions link to the first two cells
    $out.say:
    $author ~~ /\d/
      ?? "|- id=\"$author\"\n|data-sort-value=\"{ sort-key $author }\"|[[User:$author|$author]]\n"~
         "|data-sort-value=\"{ +@these }\"|[[Special:Contributions/$author|"~
         "{ +@these } task{ $s }]]"
      !! "|- id=\"$author\"\n|[[User:$author|$author]]\n"~
         "|data-sort-value=\"{ +@these }\"|[[Special:Contributions/$author|"~
         "{ +@these } task{ $s }]]"
    ;

    if +@these > 2 {
        $out.say: "|style=\"padding: 0px;\"|\n",
          "\{|class=\"broadtable sortable\" style=\"width: 100%;\"\n",
          "! Task Name !! Date Added !! Status";
    }
    else {
        $out.say: "|style=\"padding: 0px;\"|\n",
          "\{|class=\"broadtable\" style=\"width: 100%;\"";
   }

    # Tasks by this author, sorted by name
    for @these.sort({.key.&naturally}) -> $task {

        my $color = $task.value.<category> eq 'Draft' ?? '#ffd' !! '#fff';

        # add the task link, date and status to the table in the second cell
        $out.say: "|-\n|style=\"background-color: $color;\"",
          ( $task.key ~~ /\d/
            ?? " data-sort-value=\"{ sort-key $task.key }\"| [[{uri-escape $task.key}|{$task.key}]]\n"
            !! "| [[{uri-escape $task.key}|{$task.key}]]\n"
          ),
          "|style=\"width: 10em; background-color: $color;\"| {$task.value.<date>}\n",
          "|style=\"width: 6em; background-color: $color;\"| {$task.value.<category>}",
    }
     $out.say: '|}'
}
$out.say( "|}\n" );
$out.close;

note "Table file saved as: {$tablefile.IO.absolute}";

sub mediawiki-query ($site, $type, *%query) {
    my $url = "$site/api.php?" ~ uri-query-string(
        :action<query>, :format<json>, :formatversion<2>, |%query);
    my $continue = '';

    gather loop {
        my $response = $client.get("$url&$continue");
        my $data = from-json($response.content);
        take $_ for $data.<query>.{$type}.values;
        $continue = uri-query-string |($data.<query-continue>{*}».hash.hash or last);
    }
}

sub uri-query-string (*%fields) { %fields.map({ "{.key}={uri-escape .value}" }).join("&") }

sub sort-key ($a) { $a.lc.subst(/(\d+)/, ->$/ {0~(65+($0.chars)).chr~$0},:g) }

sub clear { "\r" ~ ' ' x 100 ~ "\r" }

```

Sample output:

See full output at Rosetta\_Code/List\_authors\_of\_task\_descriptions/Full\_list

As of 2018-04-10 :: Total Tasks: 1080:: Tasks: 871 :: Draft Tasks: 209 :: By 251 Authors

| Author | Tasks | Authored |
| --- | --- | --- |
| 2Powers | 2 tasks | |  |  |  | | --- | --- | --- | | Names to numbers | 2013-05-16 | Draft | | Solving coin problems | 2013-05-16 | Draft | |
| 12.175.32.19 | 1 task | |  |  |  | | --- | --- | --- | | Soundex | 2009-11-12 | Task | |
| 12Me21 | 1 task | |  |  |  | | --- | --- | --- | | Draw a rotating cube | 2015-05-04 | Task | |
| many rows omitted... | | |
| Zorro1024 | 2 tasks | |  |  |  | | --- | --- | --- | | Perfect shuffle | 2015-04-16 | Task | | Vector | 2015-03-21 | Draft | |
| Zzo38 | 1 task | |  |  |  | | --- | --- | --- | | Thue-Morse | 2015-09-20 | Task | |
| Русский | 3 tasks | | Task Name | Date Added | Status | | --- | --- | --- | | Main step of GOST 28147-89 | 2012-08-31 | Task | | Old Russian measure of length | 2013-01-09 | Draft | | Transportation problem | 2013-05-24 | Draft | |


[User]
Task

Sort most popular programming languages based on the number of users on Rosetta Code.

Show the languages with at least 100 users.

A method to solve the task

Users of a computer programming language   **X**   are those referenced in the page:

```
 https://rosettacode.org/wiki/Category:X_User,     or preferably:
 https://rosettacode.org/mw/index.php?title=Category:X_User&redirect=no to avoid re-directions.

```

In order to find the list of such categories,   it's possible to first parse the entries of:

```
 http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000.

```

Then download and parse each computer language   *users*   category to find the number of users of that computer language.

Sample output on 18 February 2019:

```
Language             Users
--------------------------
C                      391
Java                   276
C++                    275
Python                 262
JavaScript             238
Perl                   171
PHP                    167
SQL                    138
UNIX Shell             131
BASIC                  120
C sharp                118
Pascal                 116
Haskell                102
```

A Rosetta Code user usually declares using a language with the mylang template. This template is expected to appear on the User page. However, in some cases it appears in a user Talk page. It's not necessary to take this into account. For instance, among the 373 C users in the table above, 3 are actually declared in a Talk page.

[Assistant]
(formerly Perl 6)

**Works with**: Rakudo version 2017.11

Use the mediawiki API rather than web scraping since it is much faster and less resource intensive. Show languages with more than 25 users since that is still a pretty short list and to demonstrate how tied rankings are handled. Change the **$minimum** parameter to adjust what the cut-off point will be.

This is all done in a single pass; ties are not detected until a language has the same count as a previous one, so ties are marked by a **T** next to the count indicating that **this** language has the same count as the **previous**.

```
use HTTP::UserAgent;
use URI::Escape;
use JSON::Fast;

my $client = HTTP::UserAgent.new;

my $url = 'https://rosettacode.org/w';

my $start-time = now;

say "========= Generated: { DateTime.new(time) } =========";

my $lang = 1;
my $rank = 0;
my $last = 0;
my $tie = ' ';
my $minimum = 25;

.say for
    mediawiki-query(
        $url, 'pages',
        :generator<categorymembers>,
        :gcmtitle<Category:Language users>,
        :gcmlimit<350>,
        :rawcontinue(),
        :prop<categoryinfo>
    )

    .map({ %( count => .<categoryinfo><pages> || 0,
              lang  => .<title>.subst(/^'Category:' (.+) ' User'/, ->$/ {$0}) ) })

    .sort( { -.<count>, .<syntaxhighlight lang="text"> } )

    .map( { last if .<count> < $minimum; display(.<count>, .<syntaxhighlight lang="text">) } );

say "========= elapsed: {(now - $start-time).round(.01)} seconds =========";

sub display ($count, $which) {
    if $last != $count { $last = $count; $rank = $lang; $tie = ' ' } else { $tie = 'T' };
    sprintf "#%3d  Rank: %2d %s  with %-4s users:  %s", $lang++, $rank, $tie, $count, $which;
}

sub mediawiki-query ($site, $type, *%query) {
    my $url = "$site/api.php?" ~ uri-query-string(
        :action<query>, :format<json>, :formatversion<2>, |%query);
    my $continue = '';

    gather loop {
        my $response = $client.get("$url&$continue");
        my $data = from-json($response.content);
        take $_ for $data.<query>.{$type}.values;
        $continue = uri-query-string |($data.<query-continue>{*}».hash.hash or last);
    }
}

sub uri-query-string (*%fields) {
    join '&', %fields.map: { "{.key}={uri-escape .value}" }
}

```

Output:

```
========= Generated: 2022-09-02T20:59:20Z =========
#  1  Rank:  1    with 441  users:  C
#  2  Rank:  2    with 321  users:  Java
#  3  Rank:  3    with 319  users:  Python
#  4  Rank:  4    with 314  users:  C++
#  5  Rank:  5    with 291  users:  JavaScript
#  6  Rank:  6    with 190  users:  PHP
#  7  Rank:  7    with 186  users:  Perl
#  8  Rank:  8    with 167  users:  SQL
#  9  Rank:  9    with 151  users:  UNIX Shell
# 10  Rank: 10    with 133  users:  Pascal
# 11  Rank: 11    with 132  users:  BASIC
# 12  Rank: 11 T  with 132  users:  C sharp
# 13  Rank: 13    with 115  users:  Haskell
# 14  Rank: 14    with 107  users:  Ruby
# 15  Rank: 15    with 94   users:  Fortran
# 16  Rank: 16    with 75   users:  Visual Basic
# 17  Rank: 17    with 72   users:  Scheme
# 18  Rank: 18    with 70   users:  Prolog
# 19  Rank: 19    with 68   users:  AWK
# 20  Rank: 19 T  with 68   users:  Lua
# 21  Rank: 21    with 66   users:  Common Lisp
# 22  Rank: 22    with 61   users:  HTML
# 23  Rank: 23    with 55   users:  X86 Assembly
# 24  Rank: 24    with 50   users:  Forth
# 25  Rank: 25    with 49   users:  Batch File
# 26  Rank: 26    with 47   users:  Assembly
# 27  Rank: 27    with 45   users:  Bash
# 28  Rank: 27 T  with 45   users:  MATLAB
# 29  Rank: 29    with 42   users:  Lisp
# 30  Rank: 30    with 41   users:  APL
# 31  Rank: 30 T  with 41   users:  Erlang
# 32  Rank: 32    with 40   users:  Delphi
# 33  Rank: 32 T  with 40   users:  R
# 34  Rank: 34    with 39   users:  J
# 35  Rank: 34 T  with 39   users:  Visual Basic .NET
# 36  Rank: 36    with 38   users:  Go
# 37  Rank: 36 T  with 38   users:  Tcl
# 38  Rank: 38    with 37   users:  COBOL
# 39  Rank: 39    with 36   users:  Smalltalk
# 40  Rank: 40    with 35   users:  Brainf***
# 41  Rank: 40 T  with 35   users:  Objective-C
# 42  Rank: 42    with 34   users:  Clojure
# 43  Rank: 43    with 33   users:  Mathematica
# 44  Rank: 44    with 30   users:  OCaml
# 45  Rank: 45    with 28   users:  LaTeX
# 46  Rank: 46    with 27   users:  AutoHotkey
# 47  Rank: 46 T  with 27   users:  Emacs Lisp
# 48  Rank: 46 T  with 27   users:  PostScript
# 49  Rank: 46 T  with 27   users:  REXX
# 50  Rank: 50    with 26   users:  Perl 6
# 51  Rank: 50 T  with 26   users:  Sed
# 52  Rank: 52    with 25   users:  CSS
# 53  Rank: 52 T  with 25   users:  Scala
# 54  Rank: 52 T  with 25   users:  VBScript
========= elapsed: 1.48 seconds =========

========= elapsed: 1.45 seconds =========
```