/*REXX program  encodes  several example text strings  using  the  ROT-13  algorithm.   */
$='foo'                         ; say "simple text=" $;  say 'rot-13 text=' rot13($);  say
$='bar'                         ; say "simple text=" $;  say 'rot-13 text=' rot13($);  say
$="Noyr jnf V, 'rer V fnj Ryon."; say "simple text=" $;  say 'rot-13 text=' rot13($);  say
$='abc?  ABC!'                  ; say "simple text=" $;  say 'rot-13 text=' rot13($);  say
$='abjurer NOWHERE'             ; say "simple text=" $;  say 'rot-13 text=' rot13($);  say
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
rot13: return  translate( arg(1), 'abcdefghijklmABCDEFGHIJKLMnopqrstuvwxyzNOPQRSTUVWXYZ',,
                                  "nopqrstuvwxyzNOPQRSTUVWXYZabcdefghijklmABCDEFGHIJKLM")


f = function(x)
{
  rval = x .^ 3 - 3 * x .^ 2 + 2 * x;
  return rval;
};

>> findroot(f, , [-5,5])
  0


def sign(x)
  x <=> 0
end

def find_roots(f, range, step=0.001)
  sign = sign(f[range.begin])
  range.step(step) do |x|
    value = f[x]
    if value == 0
      puts "Root found at #{x}"
    elsif sign(value) == -sign
      puts "Root found between #{x-step} and #{x}"
    end
    sign = sign(value)
  end
end

f = lambda { |x| x**3 - 3*x**2 + 2*x }
find_roots(f, -1..3)


see "enter a string : " give s
ans = ""
for a = 1 to len(s)
    letter = substr(s, a, 1)
    if letter >= "a" and letter <= "z"
       char = char(ascii(letter) + 13)
       if char > "z" char = chr(asc(char) - 26) ok
    else
       if letter >= "a" and letter <= "z" char = char(ascii(letter) + 13) ok
       if char > "z" char = char(ascii(char) - 26) else  char = letter ok
    ok
    ans = ans + char
next
see ans + nl


# Returns a copy of _s_ with rot13 encoding.
def rot13(s)
  s.tr('A-Za-z', 'N-ZA-Mn-za-m')
end

# Perform rot13 on files from command line, or standard input.
while line = ARGF.gets
  print rot13(line)
end


// 202100315 Rust programming solution

use roots::find_roots_cubic;

fn main() {

   let roots = find_roots_cubic(1f32, -3f32, 2f32, 0f32);

   println!("Result : {:?}", roots);
}


object Roots extends App {
  val poly = (x: Double) => x * x * x - 3 * x * x + 2 * x

  private def printRoots(f: Double => Double,
                         lowerBound: Double,
                         upperBound: Double,
                         step: Double): Unit = {
    val y = f(lowerBound)
    var (ox, oy, os) = (lowerBound, y, math.signum(y))

    for (x <- lowerBound to upperBound by step) {
      val y = f(x)
      val s = math.signum(y)
      if (s == 0) println(x)
      else if (s != os) println(s"~${x - (x - ox) * (y / (y - oy))}")

      ox = x
      oy = y
      os = s
    }
  }

  printRoots(poly, -1.0, 4, 0.002)

}


INPUT "Enter a string: "; s$
ans$ = ""
FOR a = 1 TO LEN(s$)
        letter$ = MID$(s$, a, 1)
        IF letter$ >= "A" AND letter$ <= "Z" THEN
           char$ = CHR$(ASC(letter$) + 13)
           IF char$ > "Z" THEN char$ = CHR$(ASC(char$) - 26)
        else
           if letter$ >= "a" AND letter$ <= "z" THEN   char$ = CHR$(ASC(letter$) + 13)
           IF char$ > "z" THEN  char$ = CHR$(ASC(char$) - 26) ELSE  char$ = letter$
        END IF
        ans$ = ans$ + char$
NEXT a
PRINT ans$


fn rot13(string: &str) -> String {
    string.chars().map(|c| {
        match c {
            'a'..='m' | 'A'..='M' => ((c as u8) + 13) as char,
            'n'..='z' | 'N'..='Z' => ((c as u8) - 13) as char,
            _ => c
        }
    }).collect()
}

fn main () {
    assert_eq!(rot13("abc"), "nop");
}


comment
  Return the rot13 transformation of s, preserving case and
  passing non-alphabetic characters without change
end

function rot13(s = string) = string
  var i, k = integer
  var ch = char
  var normal, rotated = string
  normal  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  rotated = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
  for i = 1 to len(s)
    ch = mid(s,i,1)
    k = instr(1,normal,ch)
    if k <> 0 then ch = mid(rotated,k,1)
    mid(s,i,1) = ch
  next i
end = s

rem - exercise the function

var plain, encoded = string

plain = "The quick brown fox jumps over the lazy red dog."
encoded = rot13(plain)
print "Plain text: "; plain
print "Encoded   : "; encoded
print "Decoded   : "; rot13(encoded)

end


func f(x) {
    x*x*x - 3*x*x + 2*x
}

var step = 0.001
var start = -1
var stop = 3

for x in range(start+step, stop, step) {
    static sign = false
    given (var value = f(x)) {
        when (0) {
            say "Root found at #{x}"
        }
        case (sign && ((value > 0) != sign)) {
            say "Root found near #{x}"
        }
    }
    sign = value>0
}


proc froots {lambda {start -3} {end 3} {step 0.0001}} {
    set res {}
    set lastsign [sgn [apply $lambda $start]]
    for {set x $start} {$x <= $end} {set x [expr {$x + $step}]} {
        set sign [sgn [apply $lambda $x]]
        if {$sign != $lastsign} {
            lappend res [format ~%.11f $x]
        }
        set lastsign $sign
    }
    return $res
}
proc sgn x {expr {($x>0) - ($x<0)}}

puts [froots {x {expr {$x**3 - 3*$x**2 + 2*$x}}}]


variable old = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
variable new = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm";

define rot13(s) {
  s = strtrans(s, old, new);
  return s;
}

define rot13_stream(s) {
  variable ln;
  while (-1 != fgets(&ln, s))
    fputs(rot13(ln), stdout);
}

if (__argc > 1) {
  variable arg, fp;
  foreach arg (__argv[[1:]]) {
    fp = fopen(arg, "r");
    rot13_stream(fp);
  }
}
else
  rot13_stream(stdin);


scala> def rot13(s: String) = s map {
     |   case c if 'a' <= c.toLower && c.toLower <= 'm' => c + 13 toChar
     |   case c if 'n' <= c.toLower && c.toLower <= 'z' => c - 13 toChar
     |   case c => c
     | }
rot13: (s: String)String

scala> rot13("7 Cities of Gold.")
res61: String = 7 Pvgvrf bs Tbyq.

scala> rot13(res61)
res62: String = 7 Cities of Gold.


import "/fmt" for Fmt

var secant = Fn.new { |f, x0, x1|
    var f0 = 0
    var f1 = f.call(x0)
    for (i in 0...100) {
        f0 = f1
        f1 = f.call(x1)
        if (f1 == 0) return [x1, "exact"]
        if ((x1-x0).abs < 1e-6) return [x1, "approximate"]
        var t = x0
        x0 = x1
        x1 = x1-f1*(x1-t)/(f1-f0)
    }
    return [0, ""]
}

var findRoots = Fn.new { |f, lower, upper, step|
    var x0 = lower
    var x1 = lower + step
    while (x0 < upper) {
        x1 = (x1 < upper) ? x1 : upper
        var res = secant.call(f, x0, x1)
        var r = res[0]
        var status = res[1]
        if (status != "" && r >= x0 && r < x1) {
            Fmt.print(" $6.3f $s", r, status)
        }
        x0 = x1
        x1 = x1 + step
    }
}

var example = Fn.new { |x|  x*x*x - 3*x*x + 2*x }
findRoots.call(example, -0.5, 2.6, 1)


(define (rot13 str)
  (define (rot13-char c)
    (integer->char (+ (char->integer c)
                      (cond ((and (char>=? c #\a) (char<? c #\n))
                             13)
                            ((and (char>=? c #\A) (char<? c #\N))
                             13)
                            ((and (char>=? c #\n) (char<=? c #\z))
                             -13)
                            ((and (char>=? c #\N) (char<=? c #\Z))
                             -13)
                            (else
                             0)))))
  (list->string (map rot13-char (string->list str))))


$ include "seed7_05.s7i";

const proc: main is func
  local
    var char: ch is ' ';
  begin
    ch := getc(IN);
    while not eof(IN) do
      if (ch >= 'a' and ch <= 'm') or (ch >= 'A' and ch <= 'M') then
        ch := chr(ord(ch) + 13);
      elsif (ch >= 'n' and ch <= 'z') or (ch >= 'N' and ch <= 'Z') then
        ch := chr(ord(ch) - 13);
      end if;
      write(ch);
      ch := getc(IN);
    end while;
  end func;


# Returns a copy of 's' with rot13 encoding.
func rot13(s) {
    s.tr('A-Za-z', 'N-ZA-Mn-za-m');
}

# Perform rot13 on standard input.
STDIN.each { |line| print rot13(line) }


fcn findRoots(f,start,stop,step,eps){
   [start..stop,step].filter('wrap(x){ f(x).closeTo(0.0,eps) })
}


    TEXT PROCEDURE ROT13(INP); TEXT INP;
    BEGIN

        CHARACTER PROCEDURE ROT13CHAR(C); CHARACTER C;
            ROT13CHAR :=
                CHAR(
                    RANK(C) +
                       (IF C >= 'A' AND C <= 'M' THEN  13 ELSE
                        IF C >= 'a' AND C <= 'm' THEN  13 ELSE
                        IF C >= 'N' AND C <= 'Z' THEN -13 ELSE
                        IF C >= 'n' AND C <= 'z' THEN -13 ELSE 0));

        TEXT OUTP;
        OUTP :- BLANKS(INP.LENGTH);

        INP.SETPOS(1);
        WHILE INP.MORE DO
            OUTP.PUTCHAR(ROT13CHAR(INP.GETCHAR));

        ROT13 :- OUTP;
    END ROT13;


#!/usr/local/bin/slate

[email protected](String Character traits) rot13
[| value |
  upper ::= ch isUppercase.
  value := ch toLowercase as: Integer.
  (value >= 97) /\ [value < 110]
    ifTrue: [value += 13]
    ifFalse: [(value > 109) /\ [value <= 122]
                ifTrue: [value -= 13]].
  upper
    ifTrue: [(value as: String Character) toUppercase]
    ifFalse: [value as: String Character]
].

lobby define: #Rot13Encoder &parents: {Encoder}.

[email protected](Rot13Encoder traits) convert
[
  [c in isAtEnd] whileFalse: [c out nextPut: c in next rot13].
].

(Rot13Encoder newFrom: Console reader to: Console writer) convert.


"1. simple approach"
rot13 := [ :string |
  string collect: [ :each | | index |
    index := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
      indexOf: each ifAbsent: [ 0 ]. "Smalltalk uses 1-based indexing"
        index isZero
          ifTrue: [ each ]
          ifFalse: [ 'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM' at:
            index ] ] ].

(rot13 value: 'Test123') printNl "gives 'Grfg123'"

"2. extending built-in classes"
Character extend [
  + inc [
     (inc isKindOf: Character)
     ifTrue: [
        ^ ( Character value: ((self asInteger) + (inc asInteger)) )
     ] ifFalse: [
       ^ ( Character value: ((self asInteger) + inc) )
     ]
  ]
  - inc [
    ^ ( self + (inc asInteger negated) )
  ]
  trFrom: map1 to: map2 [
     (map1 includes: self) ifTrue: [
        ^ map2 at: (map1 indexOf: self)
     ] ifFalse: [ ^self ]
  ]
].

String extend [
  rot: num [ |s|
    s := String new.
    self do: [ :c |
         ((c asLowercase) between: $a and: $z)
	   ifTrue: [ |c1|
              c1 := ( $a + ((((c asLowercase) - $a + num) asInteger) rem:26)).
              (c isLowercase) ifFalse: [ c1 := c1 asUppercase ].
              s := s, (c1 asString)
           ]
           ifFalse: [
	      s := s, (c asString)
           ]
     ].
     ^s
  ]
].

('abcdefghijklmnopqrstuvwxyz123!' rot: 13) displayNl.
(('abcdefghijklmnopqrstuvwxyz123!' rot: 13) rot: 13) displayNl.

"2. using a 'translation'. Not very idiomatic Smalltalk code"
rotThirteen := [ :s | |m1 m2 r|
  r := String new.
  m1 := OrderedCollection new.
  0 to: 25 do: [ :i | m1 add: ($a + i) ].
  m2 := OrderedCollection new.
  0 to: 25 do: [ :i | m2 add: ($a + ((i+13) rem: 26)) ].
  s do: [ :c |
    (c between: $a and: $z) | (c between: $A and: $Z)
      ifTrue: [ | a |
        a := (c asLowercase) trFrom: m1 to: m2.
        (c isUppercase) ifTrue: [ a := a asUppercase ].
        r := r, (a asString)]
      ifFalse: [ r := r, (c asString) ]
  ].
  r
].

(rotThirteen value: 'abcdefghijklmnopqrstuvwxyz123!') displayNl.


*       # Function using replace( )
        define('rot13(s)u1,u2,l1,l2') :(rot13_end)
rot13   &ucase len(13) . u1 rem . u2
        &lcase len(13) . l1 rem . l2
        rot13 = replace(s,&ucase &lcase,u2 u1 l2 l1) :(return)
rot13_end

*       # Function using pattern
        define('rot13s(s)c')
        alfa = &ucase &ucase &lcase &lcase :(rot13s_end)
rot13s  s len(1) . c = :f(return)
        alfa break(c) len(13) len(1) . c
        rot13s = rot13s c :(rot13s)
rot13s_end

*       # Test and display both
        str = rot13("I abjure the $19.99 trinket!")
        output = str; output = rot13(str)
        str = rot13s("He's a real Nowhere Man.")
        output = str; output = rot13s(str)
end


SELECT translate(
        'The quick brown fox jumps over the lazy dog.',
        'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
        'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'
        )
        FROM dual;


function rot13(s) {
	u = ascii(s)
	i = selectindex(u:>64 :& u:<91)
	if (length(i)>0) u[i] = mod(u[i]:-52, 26):+65
	i = selectindex(u:>96 :& u:<123)
	if (length(i)>0) u[i] = mod(u[i]:-84, 26):+97
	return(char(u))
}

rot13("Shall Not Perish")
  Funyy Abg Crevfu


func rot13char(c: UnicodeScalar) -> UnicodeScalar {
  switch c {
  case "A"..."M", "a"..."m":
    return UnicodeScalar(UInt32(c) + 13)
  case "N"..."Z", "n"..."z":
    return UnicodeScalar(UInt32(c) - 13)
  default:
    return c
  }
}

func rot13(str: String) -> String {
  return String(map(str.unicodeScalars){ c in Character(rot13char(c)) })
}

println(rot13("The quick brown fox jumps over the lazy dog"))


proc rot13 line {
    string map {
        a n b o c p d q e r f s g t h u i v j w k x l y m z
        n a o b p c q d r e s f t g u h v i w j x k y l z m
        A N B O C P D Q E R F S G T H U I V J W K X L Y M Z
        N A O B P C Q D R E S F T G U H V I W J X K Y L Z M
    } $line
}
set tx "Hello, World !"
puts "$tx : [rot13 $tx]"


:"ABCDEFGHIJKLMNOPQRSTUVWXYZ→Str0
:".→Str2
:For(N,1,length(Str1
:If inString(Str0,sub(Str1,N,1
:Then
:inString(Str0,sub(Str1,N,1
:Ans+13-26(Ans>13
:Str2+sub(Str0,Ans,1→Str2
:Else
:Str2+sub(Str1,N,1→Str2
:End
:End
:sub(Str2,2,length(Str2)-1→Str1


function rot13(%string)
{
	%alph = "abcdefghijklmnopqrstuvwxyz";
	%len = strLen(%string);

	for(%a = 0; %a < %len; %a++)
	{
		%char = getSubStr(%string,%a,1);
		%pos = striPos(%alph, %char);

		if(%pos < 0)
			%out = %out @ %char;
		else
		{
			if(strPos(%alph, %char) < 0)
				%out = %out @ strUpr(getSubStr(%alph, (%pos + 13) % 26));
			else
				%out = %out @ getSubStr(%alph, (%pos + 13) % 26);
		}
	}
	return %out;
}


tr \
'NOWHERE AZ clerk IRAQ faber gnat ABJURER NM pyrex VEND snore tang'\
'abjurer nm PYREX vend SNORE TANG nowhere az CLERK iraq FABER GNAT' \
'ABJURER NM pyrex VEND snore tang NOWHERE AZ clerk IRAQ faber gnat'\
'nowhere az CLERK iraq FABER GNAT abjurer nm PYREX vend SNORE TANG'


#import std

#executable (<'parameterized','default-to-stdin'>,<>)

rot = ~command.files; * contents:= ~contents; * * -:~& -- ^p(~&,rep13~&zyC)~~ ~=`A-~ letters


string rot13(string s) {
  const string lcalph = "abcdefghijklmnopqrstuvwxyz";
  const string ucalph = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  string result = "";
  int pos;
  unichar c;

  for (int i = 0; s.get_next_char (ref i, out c);) {
    if ((pos = lcalph.index_of_char(c)) != -1)
      result += lcalph[(pos + 13) % 26].to_string();
    else if ((pos = ucalph.index_of_char(c)) != -1)
      result += ucalph[(pos + 13) % 26].to_string();
    else
      result += c.to_string();
  }

  return result;
}

void main() {
  print(rot13("The Quick Brown Fox Jumped Over the Lazy Dog!"));
}


Function ROT13(ByVal a As String) As String
  Dim i As Long
  Dim n As Integer, e As Integer

  ROT13 = a
  For i = 1 To Len(a)
    n = Asc(Mid$(a, i, 1))
    Select Case n
      Case 65 To 90
        e = 90
        n = n + 13
      Case 97 To 122
        e = 122
        n = n + 13
      Case Else
        e = 255
    End Select

    If n > e Then
      n = n - 26
    End If
    Mid$(ROT13, i, 1) = Chr$(n)
  Next i
End Function


Module Module1

   Private Function rot13(ByVal str As String) As String
       Dim newChars As Char(), i, j As Integer, original, replacement As String

       original = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
       replacement = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"

       newChars = str.ToCharArray()

       For i = 0 To newChars.Length - 1
           For j = 0 To 51
               If newChars(i) = original(j) Then
                   newChars(i) = replacement(j)
                   Exit For
               End If
           Next
       Next

       Return New String(newChars)
   End Function

End Module


option explicit

function rot13(a)
  dim b,n1,n,i
  b=""
  for i=1 to len(a)
    n=asc(mid(a,i,1))
    if n>=65 and n<= 91 then
       n1=(((n-65)+13)mod 26)+65
    elseif n>=97 and n<= 123 then
       n1=(((n-97)+13)mod 26)+97
    else
        n1=n
    end if
    b=b & chr(n1)
  next
  rot13=b
end function

const a="The quick brown fox jumps over the lazy dog."
dim b,c
wscript.echo a
b=rot13(a)
wscript.echo b
c=rot13(b)
wscript.echo c


def (rot13 s)
  (as string
      (map rot13
           (as list s)))

Alphabet <- "abcdefghijklmnopqrstuvwxyz"
def (rot13 c) :case (and string?.c len.c=1)
  if ("a" <= c <= "z")
       let idx (pos c Alphabet)
         Alphabet (idx+13 % 26)
     ("A" <= c <= "Z")
       (downcase.c -> rot13 -> upcase)
     :else
       c


var rot13 = Fn.new { |s|
    var bytes = s.bytes.toList
    for (i in 0...bytes.count) {
        var c = bytes[i]
        if ((c >= 65 && c <= 77) || (c >= 97 && c <= 109)) {
            bytes[i] = c + 13
        } else if ((c >= 78 && c <= 90) || (c >= 110 && c <= 122)) {
            bytes[i] = c - 13
        }
    }
    return bytes.map { |b| String.fromByte(b) }.join()
}

System.print(rot13.call("nowhere ABJURER"))


format 	ELF 	executable 3
entry 	start

segment	readable writeable
buf	rb	1

segment	readable executable
start:	mov	eax, 3		; syscall "read"
	mov	ebx, 0		; stdin
	mov	ecx, buf	; buffer for read byte
	mov	edx, 1		; len (read one byte)
	int	80h

	cmp	eax, 0		; EOF?
	jz	exit

	xor 	eax, eax	; load read char to eax
	mov	al, [buf]
	cmp	eax, "A"	; see if it is in ascii a-z or A-Z
	jl	print
	cmp	eax, "z"
	jg	print
	cmp	eax, "Z"
	jle	rotup
	cmp	eax, "a"
	jge	rotlow
	jmp	print

rotup:	sub	eax, "A"-13	; do rot 13 for A-Z
	cdq
	mov	ebx, 26
	div	ebx
	add	edx, "A"
	jmp	rotend

rotlow:	sub	eax, "a"-13	; do rot 13 for a-z
	cdq
	mov	ebx, 26
	div	ebx
	add	edx, "a"

rotend:	mov	[buf], dl

print: 	mov	eax, 4		; syscall write
	mov	ebx, 1		; stdout
	mov	ecx, buf	; *char
	mov	edx, 1		; string length
	int	80h

	jmp	start

exit: 	mov     eax,1		; syscall exit
	xor     ebx,ebx		; exit code
	int     80h


#include <algorithm>
#include <cassert>
#include <iomanip>
#include <iostream>

int digit_product(int base, int n) {
    int product = 1;
    for (; n != 0; n /= base)
        product *= n % base;
    return product;
}

int prime_factor_sum(int n) {
    int sum = 0;
    for (; (n & 1) == 0; n >>= 1)
        sum += 2;
    for (int p = 3; p * p <= n; p += 2)
        for (; n % p == 0; n /= p)
            sum += p;
    if (n > 1)
        sum += n;
    return sum;
}

bool is_prime(int n) {
    if (n < 2)
        return false;
    if (n % 2 == 0)
        return n == 2;
    if (n % 3 == 0)
        return n == 3;
    for (int p = 5; p * p <= n; p += 4) {
        if (n % p == 0)
            return false;
        p += 2;
        if (n % p == 0)
            return false;
    }
    return true;
}

bool is_rhonda(int base, int n) {
    return digit_product(base, n) == base * prime_factor_sum(n);
}

std::string to_string(int base, int n) {
    assert(base <= 36);
    static constexpr char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    std::string str;
    for (; n != 0; n /= base)
        str += digits[n % base];
    std::reverse(str.begin(), str.end());
    return str;
}

int main() {
    const int limit = 15;
    for (int base = 2; base <= 36; ++base) {
        if (is_prime(base))
            continue;
        std::cout << "First " << limit << " Rhonda numbers to base " << base
                  << ":\n";
        int numbers[limit];
        for (int n = 1, count = 0; count < limit; ++n) {
            if (is_rhonda(base, n))
                numbers[count++] = n;
        }
        std::cout << "In base 10:";
        for (int i = 0; i < limit; ++i)
            std::cout << ' ' << numbers[i];
        std::cout << "\nIn base " << base << ':';
        for (int i = 0; i < limit; ++i)
            std::cout << ' ' << to_string(base, numbers[i]);
        std::cout << "\n\n";
    }
}


code    ChIn=7, ChOut=8;
int     C, CC;
repeat  C:= ChIn(1);  CC:= C&~$20;  \CC handles lowercase too
        ChOut(0, C + (if CC>=^A & CC<=^M then +13
                 else if CC>=^N & CC<=^Z then -13
                 else 0));
until   C = $1A;  \EOF


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" />
  <xsl:variable name="alpha">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz</xsl:variable>
  <xsl:variable name="rot13">NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm</xsl:variable>
  <xsl:template match="body">
    <xsl:apply-templates/>
  </xsl:template>
  <xsl:template match="rot13">
    <xsl:value-of select="translate(.,$alpha,$rot13)"/>
  </xsl:template>
</xsl:stylesheet>


USING: formatting grouping io kernel lists lists.lazy math
math.parser math.primes math.primes.factors prettyprint ranges
sequences sequences.extras ;

: rhonda? ( n base -- ? )
    [ [ >base 1 group ] keep '[ _ base> ] map-product ]
    [ swap factors sum * ] 2bi = ;

: rhonda ( base -- list ) 1 lfrom swap '[ _ rhonda? ] lfilter ;

: list. ( list base -- ) '[ _ >base write bl ] leach nl ;

:: rhonda. ( base -- )
    15 base rhonda ltake :> r
    base "First 15 Rhonda numbers to base %d:\n" printf
    "In base 10: " write r 10 list.
    base "In base %d: " printf r base list. ;

2 36 [a..b] [ prime? not ] filter [ rhonda. nl ] each


package main

import (
    "fmt"
    "rcu"
    "strconv"
)

func contains(a []int, n int) bool {
    for _, e := range a {
        if e == n {
            return true
        }
    }
    return false
}

func main() {
    for b := 2; b <= 36; b++ {
        if rcu.IsPrime(b) {
            continue
        }
        count := 0
        var rhonda []int
        for n := 1; count < 15; n++ {
            digits := rcu.Digits(n, b)
            if !contains(digits, 0) {
                var anyEven = false
                for _, d := range digits {
                    if d%2 == 0 {
                        anyEven = true
                        break
                    }
                }
                if b != 10 || (contains(digits, 5) && anyEven) {
                    calc1 := 1
                    for _, d := range digits {
                        calc1 *= d
                    }
                    calc2 := b * rcu.SumInts(rcu.PrimeFactors(n))
                    if calc1 == calc2 {
                        rhonda = append(rhonda, n)
                        count++
                    }
                }
            }
        }
        if len(rhonda) > 0 {
            fmt.Printf("\nFirst 15 Rhonda numbers in base %d:\n", b)
            rhonda2 := make([]string, len(rhonda))
            counts2 := make([]int, len(rhonda))
            for i, r := range rhonda {
                rhonda2[i] = fmt.Sprintf("%d", r)
                counts2[i] = len(rhonda2[i])
            }
            rhonda3 := make([]string, len(rhonda))
            counts3 := make([]int, len(rhonda))
            for i, r := range rhonda {
                rhonda3[i] = strconv.FormatInt(int64(r), b)
                counts3[i] = len(rhonda3[i])
            }
            maxLen2 := rcu.MaxInts(counts2)
            maxLen3 := rcu.MaxInts(counts3)
            maxLen := maxLen2
            if maxLen3 > maxLen {
                maxLen = maxLen3
            }
            maxLen++
            fmt.Printf("In base 10: %*s\n", maxLen, rhonda2)
            fmt.Printf("In base %-2d: %*s\n", b, maxLen, rhonda3)
        }
    }
}


s$ = "nowhere ABJURER"
print " Cadena original : ", s$
print "  Tras codificar : ", Rot13$(s$)
print "Tras decodificar : ", Rot13$(Rot13$(s$))
end

sub Rot13$ (s$)
    local cad$
    cad$ = ""

    for i = 1 to len(s$)
        temp = asc(mid$(s$, i, 1))

        if temp >= 65 and temp <= 90 then      // A to Z
            temp = (mod((temp - 52), 26)) + 65
        elsif temp >= 97 And temp <= 122 then  // a to z
            temp = (mod((temp - 84), 26)) + 97
        end if
        cad$ = cad$ + chr$(temp)
    next i
    return cad$
end sub


// Warning: modifies the buffer in-place (returns pointer to in)
fn rot13(in: [] u8) []u8 {
    for (in) |*c| {
        var d : u8 = c.*;
        var x : u8 = d;
        x = if (@subWithOverflow(u8, d | 32, 97, &x) ) x else x;
        if (x < 26) {
            x = (x + 13) % 26 + 65 + (d & 32);
            c.* = x;
        }
    }
    return in;
}

const msg: [:0] const u8 =
    \\Lbh xabj vg vf tbvat gb or n onq qnl
    \\ jura gur yrggref va lbhe nycunorg fbhc
    \\ fcryy Q-V-F-N-F-G-R-E.
;

// need to copy the const string to a buffer
// before we can modify it in-place
//https://zig.news/kristoff/what-s-a-string-literal-in-zig-31e9

var buf: [500]u8 = undefined;
fn assignStr(out: []u8, str: [:0]const u8) void {
    for (str) |c, i| {
        out[i] = c;
    }
    out[str.len] = 0;
}

const print = @import("std").debug.print;

pub fn main() void {
    assignStr(&buf, msg);
    print("rot13={s}\n",.{rot13(&buf)});
}


#!/home/craigd/Bin/zkl
fcn rot13(text){
   text.translate("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
   		  "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM");
}
text:=(vm.arglist or File.stdin);  // command line or pipe
text.pump(File.stdout,rot13);      // rotate each word and print it
if(text.isType(List)) File.stdout.writeln();	// command line gets ending newline


tobase=: (a.{~;48 97(+ i.)each 10 26) {~ #.inv
isrhonda=: (*/@:(#.inv) = (* +/@q:))"0

task=: {{
  for_base.(#~ 0=1&p:) }.1+i.36 do.
    k=.i.0
    block=. 1+i.1e4
    while. 15>#k do.
      k=. k, block#~ base isrhonda block
      block=. block+1e4
    end.
    echo ''
    echo 'First 15 Rhondas in',b=.' base ',':',~":base
    echo 'In base 10: ',":15{.k
    echo 'In',;:inv b;base tobase each 15{.k
  end.
}}

   task''


public class RhondaNumbers {
    public static void main(String[] args) {
        final int limit = 15;
        for (int base = 2; base <= 36; ++base) {
            if (isPrime(base))
                continue;
            System.out.printf("First %d Rhonda numbers to base %d:\n", limit, base);
            int numbers[] = new int[limit];
            for (int n = 1, count = 0; count < limit; ++n) {
                if (isRhonda(base, n))
                    numbers[count++] = n;
            }
            System.out.printf("In base 10:");
            for (int i = 0; i < limit; ++i)
                System.out.printf(" %d", numbers[i]);
            System.out.printf("\nIn base %d:", base);
            for (int i = 0; i < limit; ++i)
                System.out.printf(" %s", Integer.toString(numbers[i], base));
            System.out.printf("\n\n");
        }
    }

    private static int digitProduct(int base, int n) {
        int product = 1;
        for (; n != 0; n /= base)
            product *= n % base;
        return product;
    }

    private static int primeFactorSum(int n) {
        int sum = 0;
        for (; (n & 1) == 0; n >>= 1)
            sum += 2;
        for (int p = 3; p * p <= n; p += 2)
            for (; n % p == 0; n /= p)
                sum += p;
        if (n > 1)
            sum += n;
        return sum;
    }

    private static boolean isPrime(int n) {
        if (n < 2)
            return false;
        if (n % 2 == 0)
            return n == 2;
        if (n % 3 == 0)
            return n == 3;
        for (int p = 5; p * p <= n; p += 4) {
            if (n % p == 0)
                return false;
            p += 2;
            if (n % p == 0)
                return false;
        }
        return true;
    }

    private static boolean isRhonda(int base, int n) {
        return digitProduct(base, n) == base * primeFactorSum(n);
    }
}


program: rot13
  case: 1
        input: abc
        output: nop
  case: 2
        input: nop
        output: abc
  case: 3
        input: 'ABC'
        output: 'NOP'
  case: 4
        input: 'NOP'
        output: 'ABC'


10 CLS
20 INPUT "Enter a string: ", s$
30 LET a$ = "": REM a$ is the encoded string
40 FOR l = 1 TO LEN(s$)
50 LET i$ = s$(l): REM i$ is the letter being worked on
60 IF i$ < "A" OR i$ > "Z" THEN GO TO 100
70 LET c$ = CHR$(CODE(i$) + 13): REM c$ is the encoded letter
80 IF c$ > "Z" THEN LET c$ = CHR$(CODE(c$) - 26)
90 GO TO 300
100 IF i$ < "a" OR i$ > "z" THEN GO TO 200
110 LET c$ = CHR$(CODE(i$) + 13)
120 IF c$ > "z" THEN LET c$ = CHR$(CODE(c$) - 26)
130 GO TO 300
200 LET c$ = i$
300 LET a$ = a$ + c$
310 NEXT l
320 PRINT a$


using Primes

isRhonda(n, b) = prod(digits(n, base=b)) == b * sum([prod(pair) for pair in factor(n).pe])

function displayrhondas(low, high, nshow)
    for b in filter(!isprime, low:high)
        n, rhondas = 1, Int[]
        while length(rhondas) < nshow
            isRhonda(n, b) && push!(rhondas, n)
            n += 1
        end
        println("First $nshow Rhondas in base $b:")
        println("In base 10: ", rhondas)
        println("In base $b: ", replace(string([string(i, base=b) for i in rhondas]), "\"" => ""), "\n")
    end
end

displayrhondas(2, 16, 15)


ClearAll[RhondaNumberQ]
RhondaNumberQ[b_Integer][n_Integer] := Module[{l, r},
  l = Times @@ IntegerDigits[n, b];
  r = Total[Catenate[ConstantArray @@@ FactorInteger[n]]];
  l == b r
]
bases = Select[Range[2, 36], PrimeQ/*Not];
Do[
 Print["base ", b, ":", Take[Select[Range[700000], RhondaNumberQ[b]], UpTo[15]]];
 ,
 {b, bases}
]


use strict;
use warnings;
use feature 'say';
use ntheory qw<is_prime factor vecsum vecprod todigitstring todigits>;

sub rhonda {
    my($b, $cnt) = @_;
    my(@r,$n);
    while (++$n) {
        push @r, $n if ($b * vecsum factor($n)) == vecprod todigits($n,$b);
        return @r if $cnt == @r;
    }
}

for my $b (grep { ! is_prime $_ } 2..36) {
    my @Rb = map { todigitstring($_,$b) } my @R = rhonda($b, 15);
    say <<~EOT;
        First 15 Rhonda numbers to base $b:
        In base $b: @Rb
        In base 10: @R
        EOT
}


with javascript_semantics
constant fmt = """
First 15 Rhonda numbers in base %d:
In base 10:  %s
In base %-2d:  %s

"""
function digit(integer d) return d-iff(d<='9'?'0':'a'-10) end function

for base=2 to 36 do
    if not is_prime(base) then
        sequence rhondab = {},  -- (base)
                 rhondad = {}   -- (decimal)
        integer n = 1
        while length(rhondab)<15 do
            string digits = sprintf("%a",{{base,n}})
            if not find('0',digits)
            and (base!=10 or (find('5',digits) and sum(apply(digits,even))!=0)) then
                integer pd = product(apply(digits,digit)),
                        bs = base*sum(prime_factors(n,true,-1))
                if pd==bs then
                    string decdig = sprintf("%d",n)
                    integer l = max(length(decdig),length(digits))
                    rhondab = append(rhondab,pad_head(digits,l))
                    rhondad = append(rhondad,pad_head(decdig,l))
                end if
            end if
            n += 1
        end while
        printf(1,fmt,{base,join(rhondad),base,join(rhondab)})
    end if
end for


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: ', ';
}


// [dependencies]
// radix_fmt = "1.0"

fn digit_product(base: u32, mut n: u32) -> u32 {
    let mut product = 1;
    while n != 0 {
        product *= n % base;
        n /= base;
    }
    product
}

fn prime_factor_sum(mut n: u32) -> u32 {
    let mut sum = 0;
    while (n & 1) == 0 {
        sum += 2;
        n >>= 1;
    }
    let mut p = 3;
    while p * p <= n {
        while n % p == 0 {
            sum += p;
            n /= p;
        }
        p += 2;
    }
    if n > 1 {
        sum += n;
    }
    sum
}

fn is_prime(n: u32) -> bool {
    if n < 2 {
        return false;
    }
    if n % 2 == 0 {
        return n == 2;
    }
    if n % 3 == 0 {
        return n == 3;
    }
    let mut p = 5;
    while p * p <= n {
        if n % p == 0 {
            return false;
        }
        p += 2;
        if n % p == 0 {
            return false;
        }
        p += 4;
    }
    true
}

fn is_rhonda(base: u32, n: u32) -> bool {
    digit_product(base, n) == base * prime_factor_sum(n)
}

fn main() {
    let limit = 15;
    for base in 2..=36 {
        if is_prime(base) {
            continue;
        }
        println!("First {} Rhonda numbers to base {}:", limit, base);
        let numbers: Vec<u32> = (1..).filter(|x| is_rhonda(base, *x)).take(limit).collect();
        print!("In base 10:");
        for n in &numbers {
            print!(" {}", n);
        }
        print!("\nIn base {}:", base);
        for n in &numbers {
            print!(" {}", radix_fmt::radix(*n, base as u8));
        }
        print!("\n\n");
    }
}


func is_rhonda_number(n, base = 10) {
    base.is_composite || return false
    n > 0             || return false
    n.digits(base).prod == base*n.factor.sum
}

for b in (2..16 -> grep { .is_composite }) {
    say ("First 10 Rhonda numbers to base #{b}: ",
        10.by { is_rhonda_number(_, b) })
}


func digitProduct(base: Int, num: Int) -> Int {
    var product = 1
    var n = num
    while n != 0 {
        product *= n % base
        n /= base
    }
    return product
}

func primeFactorSum(_ num: Int) -> Int {
    var sum = 0
    var n = num
    while (n & 1) == 0 {
        sum += 2
        n >>= 1
    }
    var p = 3
    while p * p <= n {
        while n % p == 0 {
            sum += p
            n /= p
        }
        p += 2
    }
    if n > 1 {
        sum += n
    }
    return sum
}

func isPrime(_ n: Int) -> Bool {
    if n < 2 {
        return false
    }
    if n % 2 == 0 {
        return n == 2
    }
    if n % 3 == 0 {
        return n == 3
    }
    var p = 5
    while p * p <= n {
        if n % p == 0 {
            return false
        }
        p += 2
        if n % p == 0 {
            return false
        }
        p += 4
    }
    return true
}

func isRhonda(base: Int, num: Int) -> Bool {
    return digitProduct(base: base, num: num) == base * primeFactorSum(num)
}

let limit = 15
for base in 2...36 {
    if isPrime(base) {
        continue
    }
    print("First \(limit) Rhonda numbers to base \(base):")
    let numbers = Array((1...).lazy.filter{ isRhonda(base: base, num: $0) }.prefix(limit))
    print("In base 10:", terminator: "")
    for n in numbers {
        print(" \(n)", terminator: "")
    }
    print("\nIn base \(base):", terminator: "")
    for n in numbers {
        print(" \(String(n, radix: base))", terminator: "")
    }
    print("\n")
}


import "./math" for Math, Int, Nums
import "./fmt" for Fmt, Conv

for (b in 2..36) {
    if (Int.isPrime(b)) continue
    var count = 0
    var rhonda = []
    var n = 1
    while (count < 15) {
        var digits = Int.digits(n, b)
        if (!digits.contains(0)) {
            if (b != 10 || (digits.contains(5) && digits.any { |d| d % 2 == 0 })) {
                var calc1 = Nums.prod(digits)
                var calc2 = b * Nums.sum(Int.primeFactors(n))
                if (calc1 == calc2) {
                    rhonda.add(n)
                    count = count + 1
                }
            }
        }
        n = n + 1
    }
    if (rhonda.count > 0) {
        System.print("\nFirst 15 Rhonda numbers in base %(b):")
        var rhonda2 = rhonda.map { |r| r.toString }.toList
        var rhonda3 = rhonda.map { |r| Conv.Itoa(r, b) }.toList
        var maxLen2 = Nums.max(rhonda2.map { |r| r.count })
        var maxLen3 = Nums.max(rhonda3.map { |r| r.count })
        var maxLen  = Math.max(maxLen2, maxLen3) + 1
        Fmt.print("In base 10:  $*s", maxLen, rhonda2)
        Fmt.print("In base $-2d:  $*s", b, maxLen, rhonda3)
    }
}


with Ada.Integer_Text_IO;   use Ada.Integer_Text_IO;
with Ada.Strings.Fixed;     use Ada.Strings.Fixed;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO;           use Ada.Text_IO;

with Ada.Containers.Ordered_Sets;
with Ada.Strings.Less_Case_Insensitive;

with AWS.Client;
with AWS.Response;

procedure Test is

   use Ada.Strings;

   function "+" (S : String) return Unbounded_String renames To_Unbounded_String;

   type A_Language_Count is
      record
         Count    : Integer := 0;
         Language : Unbounded_String;
      end record;

   function "=" (L, R : A_Language_Count) return Boolean is
   begin
      return L.Language = R.Language;
   end "=";

   function "<" (L, R : A_Language_Count) return Boolean is
   begin
      -- Sort by 'Count' and then by Language name
      return L.Count < R.Count
        or else (L.Count = R.Count
                 and then Less_Case_Insensitive (Left  => To_String (L.Language),
                                                 Right => To_String (R.Language)));
   end "<";

   package Sets is new Ada.Containers.Ordered_Sets (A_Language_Count);
   use Sets;

   Counts : Set;

   procedure Find_Counts (S : String) is
      Title_Str : constant String  := "title=""Category:";
      End_A_Str : constant String  := "</a> (";

      Title_At   : constant Natural := Index (S, Title_Str);
   begin
      if Title_At /= 0 then
         declare
            Bracket_At : constant Natural := Index (S (Title_At   + Title_Str'Length .. S'Last), ">");
            End_A_At   : constant Natural := Index (S (Bracket_At + 1                .. S'Last), End_A_Str);
            Space_At   : constant Natural := Index (S (End_A_At   + End_A_Str'Length .. S'Last), " ");
            Count      : constant Natural := Natural'Value (S (End_A_At + End_A_Str'Length .. Space_At - 1));
            Language   : constant String  :=                S (Title_At + Title_Str'Length .. Bracket_At - 2);
         begin
            if Bracket_At /= 0 and then End_A_At /= 0 and then Space_At /= 0 then
               begin
                  Counts.Insert (New_Item => (Count, +Language));
               exception
                  when Constraint_Error =>
                     Put_Line (Standard_Error, "Warning: repeated language: " & Language);
                     -- Ignore repeated results.
                     null;
               end;
            end if;
            -- Recursively parse the string for languages and counts
            Find_Counts (S (Space_At + 1 .. S'Last));
         end;
      end if;

   end Find_Counts;

   Place : Natural := 1;

   procedure Display (C : Cursor) is
   begin
      Put (Place, Width => 1);             Put (". ");
      Put (Element (C).Count, Width => 1); Put (" - ");
      Put_Line (To_String (Element (C).Language));
      Place := Place + 1;
   end Display;

   Http_Source : constant AWS.Response.Data :=
     AWS.Client.Get ("http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000");
begin
   Find_Counts (AWS.Response.Message_Body (Http_Source));
   Counts.Reverse_Iterate (Display'Access);
end Test;


PROC good page = (REF STRING page) BOOL:
     IF grep in string("^HTTP/[0-9.]* 200", page, NIL, NIL) = 0
     THEN TRUE
     ELSE IF INT start, end;
              grep in string("^HTTP/[0-9.]* [0-9]+ [a-zA-Z ]*", page,
                             start, end) = 0
          THEN print (page[start : end])
          ELSE print ("unknown error retrieving page")
          FI;
          FALSE
     FI;

MODE LISTOFSTRING = STRUCT(REF LINK first, last, INT upb);
MODE LINK = STRUCT(STRING value, REF LINK next);

PRIO LISTINIT = 1;
OP LISTINIT = (REF LISTOFSTRING new, REF LINK first)REF LISTOFSTRING: (
  new := (first, first, (first IS REF LINK(NIL) | 0 | 1 ));
  new
);

OP +:=  = (REF LISTOFSTRING list, []CHAR item)VOID: (
  HEAP LINK new := (STRING(item), REF LINK(NIL));
  IF first OF list IS REF LINK(NIL) THEN
    first OF list := new
  ELSE
    next OF last OF list := new
  FI;
  last OF list := new;
  upb OF list +:= 1
);

OP UPB = (LISTOFSTRING list)INT: upb OF list;

OP ARRAYOFSTRING = (LISTOFSTRING list)[]STRING:(
  [UPB list]STRING out;
  REF LINK this := first OF list;
  FOR i TO UPB list DO out[i] := value OF this; this := next OF this OD;
  out
);

INT match=0, no match=1, out of memory error=2, other error=3;

PROC re split = (STRING re split, REF STRING beetles)[]STRING:(
    LISTOFSTRING out := (NIL, NIL, 0); # LISTINIT REF LINK NIL; #
    INT start := 1, pos, end;
    WHILE grep in string(re split, beetles[start:], pos, end) = match DO
      out +:= beetles[start:start+pos-2];
      out +:= beetles[start+pos-1:start+end-1];
      start +:= end
    OD;
    IF start > UPB beetles THEN
      out +:= beetles[start:]
    FI;
    ARRAYOFSTRING(out)
  );

IF STRING reply;
   INT rc =
      http content (reply, "www.rosettacode.org", "http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=500", 0);
   rc /= 0 OR NOT good page (reply)
THEN print (("Error:",strerror (rc)))
ELSE
  STRING  # hack: HTML should be parsed by an official HTML parsing library #
    re html tag = "<[^>]*>",
    re a href category = "^<a href=""/wiki/Category:.*"" title=",
    re members = "([1-9][0-9]* members)";

  MODE STATISTIC = STRUCT(INT members, STRING category);
  FLEX[0]STATISTIC stats;

  OP +:=  = (REF FLEX[]STATISTIC in out, STATISTIC item)VOID:(
      [LWB in out: UPB in out+1]STATISTIC new;
      new[LWB in out: UPB in out]:=in out;
      new[UPB new]:=item;
      in out := new
    );

# hack: needs to be manually maintained #
  STRING re ignore ="Programming Tasks|WikiStubs|Maintenance/OmitCategoriesCreated|"+
                    "Unimplemented tasks by language|Programming Languages|"+
                    "Solutions by Programming Language|Implementations|"+
                    "Solutions by Library|Encyclopedia|Language users|"+
                    "Solutions by Programming Task|Basic language learning|"+
                    "RCTemplates|Language Implementations";

  FORMAT category fmt = $"<a href=""/wiki/Category:"g""" title=""Category:"g""""$;
  STRING encoded category, category;
  FORMAT members fmt = $" ("g" members)"$;
  INT members;

  FLEX[0]STRING tokens := re split(re html tag, reply);
  FOR token index TO UPB tokens DO
    STRING token := tokens[token index];
    FILE file;
    IF grep in string(re a href category, token, NIL, NIL) = match THEN
      associate(file, token);
      make term(file,"""");
      getf(file, (category fmt, encoded category, category));
      close(file)
    ELIF grep in string(re members, token, NIL, NIL) = match THEN
      IF grep in string(re ignore, category, NIL, NIL) /= match THEN
        associate(file, token);
        getf(file, (members fmt, members));
        stats +:= STATISTIC(members, category);
        close(file)
      FI
    FI
  OD;

  OP < = (STATISTIC a,b)BOOL:
    members OF a < members OF b;

  MODE SORTSTRUCT = STATISTIC;
  PR READ "prelude/sort.a68" PR;

  stats := in place shell sort reverse(stats);

  INT max = 10;
  FOR i TO (UPB stats > max | max | UPB stats) DO
    printf(($g(-0)". "g(-0)" - "gl$,i,stats[i]))
  OD
FI


MembsUrl = http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000
ValidUrl = http://rosettacode.org/wiki/Category:Programming_Languages
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")

; Get the webpages
WebRequest.Open("GET", MembsUrl),WebRequest.Send()
MembsPage := WebRequest.ResponseText
WebRequest.Open("GET", ValidUrl),WebRequest.Send()
ValidPage := WebRequest.ResponseText

; Replace special characters
StringReplace, MembsPage, MembsPage, ΜC++, µC++, All
StringReplace, MembsPage, MembsPage, МК-61/52, MK-61/52, All
StringReplace, ValidPage, ValidPage, ΜC++, µC++, All
StringReplace, ValidPage, ValidPage, МК-61/52, MK-61/52, All

ValidREx := "s)href=""([^""]+)"" title=""Category:([^""]+)"">(?=.*</table>)"
MembsREx := "title=""Category:(.+?)"">.+?\((\d+) members?\)"

; Iterate through all matches for valid languages
ValidLangs := [], FoundPos := 0
While FoundPos := RegExMatch(ValidPage, ValidREx, Match, FoundPos+1)
	ValidLangs[Match2] := Match1

; Iterate through all matches for categories with members
MembsLangs := [], Dupes := [], Detected := 0, FoundPos := 0
While FoundPos := RegExMatch(MembsPage, MembsREx, Match, FoundPos+1)
{
	; If it isn't a valid language or is a duplicate, skip it
	if !ValidLangs.HasKey(Match1) || Dupes.HasKey(Match1)
		continue

	Dupes.Insert(Match1, true)
	Detected++

	; Initialize this member count
	if !IsObject(MembsLangs[Match2])
		MembsLangs[Match2] := [Match1]
	else
		MembsLangs[Match2].Insert(Match1)
}

; Sort the languages with the highest member count first
Sorted := []
for Members, Languages in MembsLangs
	Sorted.Insert(1, [Members, Languages])

; Initialize the GUI
Gui, New, HwndGuiHwnd
Gui, Add, Text, w300 Center, %Detected% languages detected
Gui, Add, Edit, w300 vSearchText gSearch, Filter languages
Gui, Add, ListView, w300 r20 Grid gOpen vMyListView, Rank|Members|Category

; Populate the list view
LV_ModifyCol(1, "Integer"), LV_ModifyCol(2, "Integer"), LV_ModifyCol(3, 186)
for Rank, Languages in Sorted
	for Key, Language in Languages[2]
		LV_Add("", Rank, Languages[1], Language)

Gui, Show,, Rosetta Code
return

Open:
if (A_GuiEvent == "DoubleClick")
{
	LV_GetText(Language, A_EventInfo, 3)
	Run, % "http://rosettacode.org" ValidLangs[Language]
}
return

Search:
GuiControlGet, SearchText
GuiControl, -Redraw, MyListView

LV_Delete()
for Rank, Languages in Sorted
	for Key, Language in Languages[2]
		if InStr(Language, SearchText)
			LV_Add("", Rank, Languages[1], Language)

GuiControl, +Redraw, MyListView
return

GuiClose:
ExitApp
return


function join(array, start, end, sep,    result, i) {
        result = array[start]
        for (i = start + 1; i <= end; i++)
            result = result sep array[i]
        return result
}

function trim(str) {
        gsub(/^[[:blank:]]+|[[:blank:]\n]+$/, "", str)
        return str
}

function http2var(      site,path,server,j,output) {

        RS = ORS = "\r\n"

        site = "rosettacode.org"
        path = "/mw/api.php" \
            "?action=query" \
            "&generator=categorymembers" \
            "&gcmtitle=Category:Programming%20Languages" \
            "&gcmlimit=500" \
            (gcmcontinue "" ? "&gcmcontinue=" gcmcontinue : "") \
            "&prop=categoryinfo" \
            "&format=txt"

        server = "/inet/tcp/0/" site "/80"
        print "GET " path " HTTP/1.0" |& server
        print "Host: " site |& server
        print "" |& server
        while ((server |& getline) > 0) {
            if($0 != 0) {
                j++
                output[j] = $0
            }
        }
        close(server)
        if(length(output) == 0)
            return -1
        else
            return join(output, 1, j, "\n")
}

function parse(webpage  ,c,a,i,b,e,pages) {

       # Check for API continue code ie. a new page of results available
        match(webpage, "gcmcontinue[]] =>[^)]+[^)]", a)
        if(a[0] != "") {
            split(a[0], b, ">")
            gcmcontinue = trim(b[2])
        } else gcmcontinue = ""

        c = split(webpage, a, "[[][0-9]{1,7}[]]")

        while(i++ < c) {
            if(match(a[i], /[pages]/)) {
                match(a[i], "pages[]] =>[^[]+[^[]", b)
                split(b[0], e, ">")
                pages = trim(e[2]) + 0
            } else pages = 0
            if(match(a[i], /[title]/)) {
                match(a[i], "title[]] =>[^[]+[^[]", b)
                split(b[0], e, ":")
                e[2] = trim(e[2])
                if ( substr(e[2], length(e[2]), 1) == ")" )
                    e[2] = trim( substr(e[2], 1, length(e[2]) - 1) )
                if(length(e[2]) > 0)
                    G[e[2]] = pages
            }
        }
}

BEGIN {

        parse( http2var() )     # First 500
        while ( gcmcontinue != "" )
            parse( http2var() ) # Next 500, etc

        # https://www.gnu.org/software/gawk/manual/html_node/Controlling-Scanning.html
        PROCINFO["sorted_in"] = "@val_type_desc"
        for ( language in G )
            print ++i ". " language " - " G[language]

}


INSTALL @lib$+"SORTLIB"
      SortUp% = FN_sortinit(0,0)   : REM Ascending
      SortDown% = FN_sortinit(1,0) : REM Descending

      VDU 23,22,640;512;8,16,16,128+8 : REM Enable UTF-8 support
      DIM lang$(1000), tasks%(1000)
      NORM_IGNORECASE = 1

      SYS "LoadLibrary", "URLMON.DLL" TO urlmon%
      SYS "GetProcAddress", urlmon%, "URLDownloadToFileA" TO UDTF

      PRINT "Downloading languages list..."
      url$ = "http://rosettacode.org/wiki/Category:Programming_Languages"
      file$ = @tmp$ + "languages.htm"
      SYS UDTF, 0, url$, file$, 0, 0 TO fail%
      IF fail% ERROR 100, "File download failed (languages)"

      file% = OPENIN(file$)
      index% = 0
      WHILE NOT EOF#file%
        REPEAT
          a$ = GET$#file%
          IF INSTR(a$, "<a href=""/wiki/Category") = 0 EXIT REPEAT
          i% = INSTR(a$, "")
          IF i% = 0 EXIT REPEAT
          j% = i%
          REPEAT i% -= 1 : UNTIL MID$(a$,i%,1) = ">" OR i% = 0
          IF i% = 0 EXIT REPEAT
          lang$(index%) = MID$(a$, i%+1, j%-i%-1)
          IF lang$(index%) <> "Languages" index% += 1
        UNTIL TRUE
      ENDWHILE
      CLOSE #file%

      C% = index%
      CALL SortUp%, lang$(0)

      PRINT "Downloading categories list..."
      url$ = "http://www.rosettacode.org/w/index.php"
      url$ += "?title=Special:Categories&limit=5000"
      file$ = @tmp$ + "categories.htm"
      SYS UDTF, 0, url$, file$, 0, 0 TO fail%
      IF fail% ERROR 100, "File download failed (categories)"

      file% = OPENIN(file$)
      WHILE NOT EOF#file%
        REPEAT
          a$ = GET$#file%
          i% = INSTR(a$, "member")
          IF i% = 0 EXIT REPEAT
          REPEAT i% -= 1 : UNTIL MID$(a$,i%,1) = "(" OR i% = 0
          IF i% = 0 EXIT REPEAT
          tasks% = VAL(MID$(a$, i%+1))
          IF tasks% = 0 EXIT REPEAT
          REPEAT i% -= 1 : UNTIL MID$(a$,i%,1) = "<" OR i% = 0
          IF i% = 0 EXIT REPEAT
          j% = i%
          REPEAT i% -= 1 : UNTIL MID$(a$,i%,1) = ">" OR i% = 0
          IF i% = 0 EXIT REPEAT
          k% = FNwhere(lang$(), MID$(a$, i%+1, j%-i%-1), index%-1)
          IF k% <> -1 tasks%(k%) += tasks%
        UNTIL TRUE
      ENDWHILE
      CLOSE #file%

      CALL SortDown%, tasks%(0), lang$(0)

      VDU 14
      @% = 3 : REM Column width
      PRINT "List of languages as of " TIME$
      FOR i% = 0 TO index%-1
        IF tasks%(i%) = 0 EXIT FOR
        PRINT  i%+1 ". " tasks%(i%) " - " lang$(i%)
      NEXT
      END

      DEF FNwhere(a$(), S$, T%)
      LOCAL B%, C%, H%
      H% = 2
      WHILE H%<T% H% *= 2:ENDWHILE
      H% /= 2
      REPEAT
        IF (B%+H%)<=T% THEN
          SYS "CompareString", 0, NORM_IGNORECASE, S$, -1, a$(B%+H%), -1 TO C%
          IF C% >= 2 B% += H%
        ENDIF
        H% /= 2
      UNTIL H%=0
      SYS "CompareString", 0, NORM_IGNORECASE, S$, -1, a$(B%), -1 TO C%
      IF C% = 2 THEN = B% ELSE = -1


  ( get-page
  =   url type
    .   !arg:(?url.?type)
      & sys$(str$("wget -q -O wget.out \"" !url \"))
      & get$("wget.out",!type)                     { Type can be JSN, X ML, HT ML or just ML. }
  )
& ( get-langs
  =   arr lang
    .   :?arr
      & !arg:? (.h2.) ?arg (h2.?) ?      { Only analyse part of page between the h2 elements. }
      &   whl
        ' ( !arg
          :   ?
              ( a
              .   ?
                  ( title
                  .   @(?:"Category:" ?):?lang
                    & !lang !arr:?arr
                  )
                  ?
              )
              ?arg
          )
      & !arr
  )
& ( get-cats
  =   page langs list count pat li A Z
    .   !arg:(?page.?langs)
      & 0:?list
      &   whl
        ' ( !langs:%?lang ?langs
          &                                { Use macro substitution to create a fast pattern. }
              ' ( ?
                  (a.? (title.$lang) ?)           { $lang is replaced by the actual language. }
                  ?
                  (.a.)
                  @(?:? #?count " " ?)
                )
            : (=?pat)
          &       (       !page
                        :   ?A
                            ( (li.) ?li (.li.) ?Z
                            & !li:!pat
                            )
                      & !A !Z:?page     { Remove found item from page. (Not necessary at all.)}
                      & !count
                    | 0                                       { The language has no examples. }
                  .
                  )
                \L !lang             { Bracmat normalizes a\Lx+b\Ly+a\Lz to a\L(x*z)+b\Ly, so }
              + !list                { it's easy to collect categories with the same count.   }
            : ?list
          )
      & !list
  )
&     get-cats
    $ (   get-page
        $ ( "http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000"
          . HT,ML
          )
      .   get-langs
        $ ( get-page
          $ ( "http://rosettacode.org/wiki/Category:Programming_Languages"
            . HT ML
            )
          )
      )
  : ?cats
& :?list
&   whl
  ' ( !cats:(?count.)\L?tiedcats+?cats
    & :?ties
    &   whl
      ' ( !tiedcats:@(?:"Category:" ?name)*?tiedcats
        & !ties !name:?ties
        )
    & (!count.!ties) !list:?list
    )
& 1:?rank
&   whl
  ' ( !rank:?tiedRank
    & !list:(?count.?ties) ?list
    &   whl
      ' ( !ties:%?name ?ties
        & @(!tiedRank:? [?len)                  { We want some padding for the highest ranks. }
        & @("   ":? [!len ?sp)                  { Skip blanks up to the length of the rank.   }
        & out$(str$(!sp !tiedRank ". " !count " - " !name))
        & 1+!rank:?rank
        )
    )
& ;


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char * lang_url = "http://www.rosettacode.org/w/api.php?action=query&"
		"list=categorymembers&cmtitle=Category:Programming_Languages&"
		"cmlimit=500&format=json";
const char * cat_url = "http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000";

#define BLOCK 1024
char *get_page(const char *url)
{
	char cmd[1024];
	char *ptr, *buf;
	int bytes_read = 1, len = 0;
	sprintf(cmd, "wget -q \"%s\" -O -", url);
	FILE *fp = popen(cmd, "r");
	if (!fp) return 0;
	for (ptr = buf = 0; bytes_read > 0; ) {
		buf = realloc(buf, 1 + (len += BLOCK));
		if (!ptr) ptr = buf;
		bytes_read = fread(ptr, 1, BLOCK, fp);
		if (bytes_read <= 0) break;
		ptr += bytes_read;
	}
	*++ptr = '\0';
	return buf;
}

char ** get_langs(char *buf, int *l)
{
	char **arr = 0;
	for (*l = 0; (buf = strstr(buf, "Category:")) && (buf += 9); ++*l)
		for (	(*l)[arr = realloc(arr, sizeof(char*)*(1 + *l))] = buf;
			*buf != '"' || (*buf++ = 0);
			buf++);

	return arr;
}

typedef struct { const char *name; int count; } cnt_t;
cnt_t * get_cats(char *buf, char ** langs, int len, int *ret_len)
{
	char str[1024], *found;
	cnt_t *list = 0;
	int i, llen = 0;
	for (i = 0; i < len; i++) {
		sprintf(str, "/wiki/Category:%s", langs[i]);
		if (!(found = strstr(buf, str))) continue;
		buf = found + strlen(str);

		if (!(found = strstr(buf, "</a> ("))) continue;
		list = realloc(list, sizeof(cnt_t) * ++llen);
		list[llen - 1].name = langs[i];
		list[llen - 1].count = strtol(found + 6, 0, 10);
	}
	*ret_len = llen;
	return list;
}

int _scmp(const void *a, const void *b)
{
	int x = ((const cnt_t*)a)->count, y = ((const cnt_t*)b)->count;
	return x < y ? -1 : x > y;
}

int main()
{
	int len, clen;
	char ** langs = get_langs(get_page(lang_url), &len);
	cnt_t *cats = get_cats(get_page(cat_url), langs, len, &clen);
	qsort(cats, clen, sizeof(cnt_t), _scmp);
	while (--clen >= 0)
		printf("%4d %s\n", cats[clen].count, cats[clen].name);

	return 0;
}


using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;

class Program
{
    static void Main(string[] args)
    {
        string get1 = new WebClient().DownloadString("http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Languages&cmlimit=500&format=json");
        string get2 = new WebClient().DownloadString("http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000");

        ArrayList langs = new ArrayList();
        Dictionary<string, int> qtdmbr = new Dictionary<string, int>();

        MatchCollection match1 = new Regex("\"title\":\"Category:(.+?)\"").Matches(get1);
        MatchCollection match2 = new Regex("title=\"Category:(.+?)\">.+?</a>[^(]*\\((\\d+) members\\)").Matches(get2);

        foreach (Match lang in match1) langs.Add(lang.Groups[1].Value);

        foreach (Match match in match2)
        {
            if (langs.Contains(match.Groups[1].Value))
            {
                qtdmbr.Add(match.Groups[1].Value, Int32.Parse(match.Groups[2].Value));
            }
        }

        string[] test = qtdmbr.OrderByDescending(x => x.Value).Select(x => String.Format("{0,3} - {1}", x.Value, x.Key)).ToArray();

        int count = 1;

        foreach (string i in test)
        {
            Console.WriteLine("{0,3}. {1}", count, i);
            count++;
        }
    }
}


#include <string>
#include <boost/regex.hpp>
#include <boost/asio.hpp>
#include <vector>
#include <utility>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <algorithm>
#include <iomanip>

struct Sort { //sorting programming languages according to frequency
   bool operator( ) ( const std::pair<std::string,int> & a , const std::pair<std::string,int> & b )
      const {
	 return a.second > b.second ;
      }
} ;

int main( ) {
   try {
      //setting up an io service , with templated subelements for resolver and query
      boost::asio::io_service io_service ;
      boost::asio::ip::tcp::resolver resolver ( io_service ) ;
      boost::asio::ip::tcp::resolver::query query ( "rosettacode.org" , "http" ) ;
      boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve( query ) ;
      boost::asio::ip::tcp::resolver::iterator end ;
      boost::asio::ip::tcp::socket socket( io_service ) ;
      boost::system::error_code error = boost::asio::error::host_not_found ;
      //looking for an endpoint the socket will be able to connect to
      while ( error && endpoint_iterator != end ) {
	 socket.close( ) ;
	 socket.connect( *endpoint_iterator++ , error ) ;
      }
      if ( error )
	 throw boost::system::system_error ( error ) ;
      //we send a request
      boost::asio::streambuf request ;
      std::ostream request_stream( &request ) ;
      request_stream << "GET " << "/mw/index.php?title=Special:Categories&limit=5000" << " HTTP/1.0\r\n" ;
      request_stream << "Host: " << "rosettacode.org" << "\r\n" ;
      request_stream << "Accept: */*\r\n" ;
      request_stream << "Connection: close\r\n\r\n" ;
      //send the request
      boost::asio::write( socket , request ) ;
      //we receive the response analyzing every line and storing the programming language
      boost::asio::streambuf response ;
      std::istream response_stream ( &response ) ;
      boost::asio::read_until( socket , response , "\r\n\r\n" ) ;
      boost::regex e( "
<a href=\"[^<>]+?\">([a-zA-Z\\+#1-9]+?)\\s?\\((\\d+) members\\)
" ) ;
      //using the wrong regex produces incorrect sorting!!
      std::ostringstream line ;
      std::vector<std::pair<std::string , int> > languages ; //holds language and number of examples
      boost::smatch matches ;
      while ( boost::asio::read( socket , response , boost::asio::transfer_at_least( 1 ) , error ) ) {
	 line << &response ;
	 if ( boost::regex_search( line.str( ) , matches , e ) ) {
	    std::string lang( matches[2].first , matches[2].second ) ;
	    int zahl = atoi ( lang.c_str( ) ) ;
	    languages.push_back( std::make_pair( matches[ 1 ] , zahl ) ) ;
	 }
	 line.str( "") ;//we have to erase the string buffer for the next read
      }
      if ( error != boost::asio::error::eof )
	 throw boost::system::system_error( error ) ;
      //we sort the vector entries , see the struct above
      std::sort( languages.begin( ) , languages.end( ) , Sort( ) ) ;
      int n = 1 ;
      for ( std::vector<std::pair<std::string , int> >::const_iterator spi = languages.begin( ) ;
	    spi != languages.end( ) ; ++spi ) {
	 std::cout << std::setw( 3 ) << std::right << n << '.' << std::setw( 4 ) << std::right <<
	 spi->second   << " - " << spi->first << '\n' ;
	 n++ ;
      }
   } catch ( std::exception &ex ) {
      std::cout << "Exception: " << ex.what( ) << '\n' ;
   }
   return 0 ;
}


Class Utils.Net.RosettaCode [ Abstract ]
{

ClassMethod GetTopLanguages(pHost As %String = "", pPath As %String = "", pTop As %Integer = 10) As %Status
{
	// check input parameters
	If $Match(pHost, "^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$")=0 {
		Quit $$$ERROR($$$GeneralError, "Invalid host name.")
	}

	// create http request and get page
	Set req=##class(%Net.HttpRequest).%New()
	Set req.Server=pHost
	Do req.Get(pPath)

	// create xml stream with doc type
	Set xml=##class(%Stream.GlobalCharacter).%New()
	Set sc=xml.WriteLine("<!DOCTYPE doc_type [")
	Set sc=xml.WriteLine($Char(9)_"<!ENTITY nbsp ' '>")
	Set sc=xml.WriteLine($Char(9)_"<!ENTITY amp '&'>")
	Set sc=xml.WriteLine("]>")

	// copy xhtml stream to xml stream
	Set xhtml=req.HttpResponse.Data
	Set xhtml.LineTerminator=$Char(10)
	While 'xhtml.AtEnd {
		Set line=xhtml.ReadLine()
		If line["!DOCTYPE" Continue
		If line["<g:plusone></g:plusone>" {
			Continue
			Set line="<g:plusone xmlns:g='http://base.google.com/ns/1.0'></g:plusone>"
		}
		Set sc=xml.WriteLine(line)
	}

	// create an instance of an %XML.XPATH.Document
	Set sc=##class(%XML.XPATH.Document).CreateFromStream(xml, .xdoc)
	If $$$ISERR(sc) Quit sc

	// evaluate following 'XPath' expression
	Set sc=xdoc.EvaluateExpression("//div[@id='bodyContent']//li", "a[contains(@href, '/Category:')]/ancestor::li", .res)

	// iterate through list elements
	Set array=##class(%ArrayOfDataTypes).%New()
	Do {
		Set dom=res.GetNext(.key)
		If '$IsObject(dom) Quit

		// get language name and members
		Set lang=""
		While dom.Read() {
			If 'dom.HasValue Continue
			If lang="" {
				If $Locate(dom.Value, "User|Tasks|Omit|attention|operations|Solutions by") Quit
				Set lang=dom.Value Continue
			}
			If dom.Value["members" {
				Set members=+$ZStrip(dom.Value, "<>P")
				Set list=array.GetAt(members)
				Set $List(list, $ListLength(list)+1)=lang
				Set sc=array.SetAt(list, members)
				Quit
			}
		}
	} While key'=""
	If array.Count()=0 Quit $$$ERROR($$$GeneralError, "No languages found.")

	// show top entries
	Write "Top "_pTop_" Languages (as at "_$ZDate($HoroLog, 2)_"):", !
	For count=1:1:pTop {
		Set members=array.GetPrevious(.key)
		If key="" Quit
		Write $Justify(count, 3), ". ", key, " - ", $ListToString(members, ", "), !
	}

	// finished
	Quit $$$OK
}

}


void main() {
    import std.stdio, std.algorithm, std.conv, std.array, std.regex,
           std.typecons, std.net.curl;

    immutable r1 = `"title":"Category:([^"]+)"`;
    const languages = get("www.rosettacode.org/w/api.php?action=query"~
                          "&list=categorymembers&cmtitle=Category:Pro"~
                          "gramming_Languages&cmlimit=500&format=json")
                      .matchAll(r1).map!q{ a[1].dup }.array;

    auto pairs = get("www.rosettacode.org/w/index.php?" ~
                      "title=Special:Categories&limit=5000")
                  .matchAll(`title="Category:([^"]+)">[^<]+` ~
                            `</a>[^(]+\((\d+) members\)`)
                  .filter!(m => languages.canFind(m[1]))
                  .map!(m => tuple(m[2].to!uint, m[1].dup));

    foreach (i, res; pairs.array.sort!q{a > b}.release)
        writefln("%3d. %3d - %s", i + 1, res[]);
}


program Rank_languages_by_popularity;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.Classes,
  IdHttp,
  IdBaseComponent,
  IdComponent,
  IdIOHandler,
  IdIOHandlerSocket,
  IdIOHandlerStack,
  IdSSL,
  IdSSLOpenSSL,
  System.RegularExpressions,
  System.Generics.Collections,
  System.Generics.Defaults;

const
  AURL = 'https://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000';
  UserAgent =
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36';

type
  TPair = record
    Language: string;
    Users: Integer;
    constructor Create(lang, user: string);
  end;

  TPairs = TList<TPair>;

  { TPair }

constructor TPair.Create(lang, user: string);
begin
  Language := lang;
  Users := StrToIntDef(user, 0);
end;

function GetFullCode: string;
begin
  with TIdHttp.create(nil) do
  begin
    HandleRedirects := True;
    Request.UserAgent := UserAgent;
    IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    Result := Get(AURL);
    IOHandler.Free;
    Free;
  end;
end;

function GetList(const Code: string): TPairs;
var
  RegularExpression: TRegEx;
  Match: TMatch;
  language, users: string;
begin
  Result := TPairs.Create;

  RegularExpression.Create('>(?<LANG>[^<,;]*)<\/a>.. \((?<USERS>[,\d]*)');
  Match := RegularExpression.Match(Code);

  while Match.Success do
  begin
    users := Match.Groups.Item['USERS'].Value.Replace(',', '');
    language := Match.Groups.Item['LANG'].Value;

    Result.Add(TPair.Create(language, users));
    Match := Match.NextMatch;
  end;
end;

procedure Sort(List: TPairs);
begin
  List.Sort(TComparer<TPair>.Construct(
    function(const Left, Right: TPair): Integer
    begin
      result := Right.Users - Left.Users;
      if result = 0 then
        result := CompareText(Left.Language, Right.Language);
    end));
end;

function SumUsers(List: TPairs): Cardinal;
var
  p: TPair;
begin
  Result := 0;
  for p in List do
  begin
    Inc(Result, p.Users);
  end;
end;

var
  Data: TStringList;
  Code, line: string;
  List: TPairs;
  i: Integer;

begin
  Data := TStringList.Create;
  Writeln('Downloading code...');

  Code := GetFullCode;
  data.Clear;

  List := GetList(Code);

  Sort(List);

  Writeln('Total languages: ', List.Count);
  Writeln('Total Users: ', SumUsers(List));
  Writeln('Top 10:'#10);

  for i := 0 to List.Count - 1 do
  begin
    line := Format('%5dth %5d %s', [i + 1, List[i].users, List[i].language]);
    Data.Add(line);
    if i < 10 then
      Writeln(line);
  end;

  Data.SaveToFile('Rank.txt');
  List.Free;
  Data.Free;

  Readln;
end.


-module( rank_languages_by_popularity ).

-export( [task/0] ).

-record( print_fold, {place=0, place_step=1, previous_count=0} ).

task() ->
	ok = find_unimplemented_tasks:init(),
	Category_programming_languages = find_unimplemented_tasks:rosetta_code_list_of( "Programming_Languages" ),
	Programming_languages = [X || "Category:" ++ X <- Category_programming_languages],
	{ok, {{_HTTP,200,"OK"}, _Headers, Body}} = httpc:request( "http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000" ),
	Count_categories = lists:sort( [{Y, X} || {X, Y} <- category_counts(Body, []), lists:member(X, Programming_languages)] ),
	lists:foldr( fun place_count_category_write/2, #print_fold{}, Count_categories ).

category_counts( "", [[] | Acc] ) -> Acc;
category_counts( String, Acc ) ->
	{Begin, End} = category_count_begin_end( String ),
	{Category_count, String_continuation} = category_count_extract( String, Begin, End ),
	category_counts( String_continuation, [Category_count | Acc] ).

category_count_begin_end( String ) ->
	Begin = string:str( String, "/wiki/Category:" ),
	End = string:str( string:substr(String, Begin), " member" ),
	category_count_begin_end( Begin, End, erlang:length(" member") ).

category_count_begin_end( _Begin, 0, _End_length ) -> {0, 0};
category_count_begin_end( Begin, End, End_length ) ->
	{Begin, Begin + End + End_length}.

category_count_extract( _String, 0, _End ) -> {[], ""};
category_count_extract( String, Begin, End ) ->
	Category_count = category_count_extract( string:substr(String, Begin, End - Begin) ),
	{Category_count, string:substr( String, End + 1 )}.

category_count_extract( "/wiki/Category:" ++ T ) ->
	Category_member = string:tokens( T, " " ),
	Category = category_count_extract_category( Category_member ),
	Member = category_count_extract_count( lists:reverse(Category_member) ),
	{Category, Member}.

category_count_extract_category( [Category | _T] ) ->
	lists:map( fun category_count_extract_category_map/1, string:strip(Category, right, $") ).

category_count_extract_category_map( $_ ) -> $\s;
category_count_extract_category_map( Character ) -> Character.

category_count_extract_count( ["member" ++ _, "(" ++ N | _T] ) -> erlang:list_to_integer( N );
category_count_extract_count( _T ) -> 0.

place_count_category_write( {Count, Category}, Acc ) ->
	Print_fold = place_count_category_write( Count, Acc ),
	io:fwrite("~p. ~p - ~p~n", [Print_fold#print_fold.place, Count, Category] ),
	Print_fold;

place_count_category_write( Count, #print_fold{place_step=Place_step, previous_count=Count}=Print_fold ) ->
	Print_fold#print_fold{place_step=Place_step + 1};
place_count_category_write( Count, #print_fold{place=Place, place_step=Place_step} ) ->
	#print_fold{place=Place + Place_step, previous_count=Count}.


open System
open System.Text.RegularExpressions

[<EntryPoint>]
let main argv =
    let rosettacodeSpecialCategoriesAddress =
        "http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000"
    let rosettacodeProgrammingLaguagesAddress =
        "http://rosettacode.org/wiki/Category:Programming_Languages"

    let getWebContent (url :string)  =
        using (new System.Net.WebClient()) (fun x -> x.DownloadString url)

    let regexForTitleCategoryFollowedOptionallyByMembercount =
        new Regex("""
            title="Category: (?<Name> [^"]* ) ">    # capture the name of the category
            (                   # group begin for optional part
                [^(]*           # ignore up to next open paren (on this line)
                \(              # verbatim open paren
                    (?<Number>
                        \d+     # a number (= some digits)
                    )
                    \s+         # whitespace
                    member(s?)  # verbatim text members (maybe singular)
                \)              # verbatim closing paren
            )?                  # end of optional part
            """, // " <- Make syntax highlighting happy
            RegexOptions.IgnorePatternWhitespace ||| RegexOptions.ExplicitCapture)
    let matchesForTitleCategoryFollowedOptionallyByMembercount str =
        regexForTitleCategoryFollowedOptionallyByMembercount.Matches(str)

    let languages =
        matchesForTitleCategoryFollowedOptionallyByMembercount
            (getWebContent rosettacodeProgrammingLaguagesAddress)
        |> Seq.cast
        |> Seq.map (fun (m: Match) -> (m.Groups.Item("Name").Value, true))
        |> Map.ofSeq

    let entriesWithCount =
        let parse str = match Int32.TryParse(str) with | (true, n) -> n | (false, _) -> -1
        matchesForTitleCategoryFollowedOptionallyByMembercount
            (getWebContent rosettacodeSpecialCategoriesAddress)
        |> Seq.cast
        |> Seq.map (fun (m: Match) ->
            (m.Groups.Item("Name").Value, parse (m.Groups.Item("Number").Value)))
        |> Seq.filter (fun p -> (snd p) > 0 &&  Map.containsKey (fst p) languages)
        |> Seq.sortBy (fun x -> -(snd x))

    Seq.iter2 (fun i x -> printfn "%4d. %s" i x)
        (seq { 1 .. 20 })
        (entriesWithCount |> Seq.map (fun x -> sprintf "%3d - %s" (snd x) (fst x)))
    0


package main

import (
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"regexp"
	"sort"
	"strconv"
	"strings"
)

var baseQuery = "http://rosettacode.org/mw/api.php?action=query" +
	"&format=xml&list=categorymembers&cmlimit=500"

func req(u string, foundCm func(string)) string {
	resp, err := http.Get(u)
	if err != nil {
		log.Fatal(err) // connection or request fail
	}
	defer resp.Body.Close()
	for p := xml.NewDecoder(resp.Body); ; {
		t, err := p.RawToken()
		switch s, ok := t.(xml.StartElement); {
		case err == io.EOF:
			return ""
		case err != nil:
			log.Fatal(err)
		case !ok:
			continue
		case s.Name.Local == "cm":
			for _, a := range s.Attr {
				if a.Name.Local == "title" {
					foundCm(a.Value)
				}
			}
		case s.Name.Local == "categorymembers" && len(s.Attr) > 0 &&
			s.Attr[0].Name.Local == "cmcontinue":
			return url.QueryEscape(s.Attr[0].Value)
		}
	}
	return ""
}

// satisfy sort interface (reverse sorting)
type pop struct {
	string
	int
}
type popList []pop

func (pl popList) Len() int      { return len(pl) }
func (pl popList) Swap(i, j int) { pl[i], pl[j] = pl[j], pl[i] }
func (pl popList) Less(i, j int) bool {
	switch d := pl[i].int - pl[j].int; {
	case d > 0:
		return true
	case d < 0:
		return false
	}
	return pl[i].string < pl[j].string
}

func main() {
	// get languages, store in a map
	langMap := make(map[string]bool)
	storeLang := func(cm string) {
		if strings.HasPrefix(cm, "Category:") {
			cm = cm[9:]
		}
		langMap[cm] = true
	}
	languageQuery := baseQuery + "&cmtitle=Category:Programming_Languages"
	continueAt := req(languageQuery, storeLang)
	for continueAt != "" {
		continueAt = req(languageQuery+"&cmcontinue="+continueAt, storeLang)
	}
	// allocate slice for sorting
	s := make(popList, 0, len(langMap))

	// get big list of categories
	resp, err := http.Get("http://rosettacode.org/mw/index.php" +
		"?title=Special:Categories&limit=5000")
	if err != nil {
		log.Fatal(err)
	}
	page, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	// split out fields of interest and populate sortable slice
	rx := regexp.MustCompile("
(.*).*[(]([0-9]+) member")
	for _, sm := range rx.FindAllSubmatch(page, -1) {
		ls := string(sm[1])
		if langMap[ls] {
			if n, err := strconv.Atoi(string(sm[2])); err == nil {
				s = append(s, pop{ls, n})
			}
		}
	}

	// output
	sort.Sort(s)
	lastCnt, lastIdx := -1, 1
	for i, lang := range s {
		if lang.int != lastCnt {
			lastCnt = lang.int
			lastIdx = i + 1
		}
		fmt.Printf("%3d. %3d - %s\n", lastIdx, lang.int, lang.string)
	}
}


def html = new URL('http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000').getText([
        connectTimeout:500,
        readTimeout:15000,
        requestProperties: [ 'User-Agent': 'Firefox/2.0.0.4']])
def count = [:]
(html =~ '
]+>([^<]+)[^(]*[(](\\d+) member[s]*[)]
').each { match, language, members ->
    count[language] = (members as int)
}
count.sort { v1, v2 -> v2.value <=> v1.value }.eachWithIndex { value, index -> println "${index + 1} $value" }


{-# LANGUAGE OverloadedStrings #-}

import Data.Aeson
import Network.HTTP.Base (urlEncode)
import Network.HTTP.Conduit (simpleHttp)
import Data.List (sortBy, groupBy)
import Data.Function (on)
import Data.Map (Map, toList)

-- Record representing a single language.
data Language =
    Language {
        name      :: String,
        quantity  :: Int
    } deriving (Show)

-- Make Language an instance of FromJSON for parsing of query response.
instance FromJSON Language where
    parseJSON (Object p) = do
        categoryInfo <- p .:? "categoryinfo"

        let quantity = case categoryInfo of
                           Just ob -> ob .: "size"
                           Nothing -> return 0

            name = p .: "title"

        Language <$> name <*> quantity

-- Record representing entire response to query.
-- Contains collection of languages and optional continuation string.
data Report =
    Report {
        continue    :: Maybe String,
        languages   :: Map String Language
    } deriving (Show)

-- Make Report an instance of FromJSON for parsing of query response.
instance FromJSON Report where
    parseJSON (Object p) = do
        querycontinue <- p .:? "query-continue"

        let continue
                = case querycontinue of
                      Just ob -> fmap Just $
                                     (ob .: "categorymembers") >>=
                                     (   .: "gcmcontinue")
                      Nothing -> return Nothing

            languages = (p .: "query") >>= (.: "pages")

        Report <$> continue <*> languages

-- Pretty print a single language
showLanguage :: Int -> Bool -> Language -> IO ()
showLanguage rank tie (Language languageName languageQuantity) =
    let rankStr = show rank
    in putStrLn $ rankStr ++ "." ++
                      replicate (4 - length rankStr) ' ' ++
                      (if tie then " (tie)" else "      ") ++
                      " " ++ drop 9 languageName ++
                      " - " ++ show languageQuantity

-- Pretty print languages with common rank
showRanking :: (Int,  [Language]) -> IO ()
showRanking (ranking, languages) =
    mapM_ (showLanguage ranking $ length languages > 1) languages

-- Sort and group languages by rank, then pretty print them.
showLanguages :: [Language] -> IO ()
showLanguages allLanguages =
    mapM_ showRanking $
          zip [1..] $
          groupBy ((==) `on` quantity) $
          sortBy (flip compare `on` quantity) allLanguages

-- Mediawiki api style query to send to rosettacode.org
queryStr = "http://rosettacode.org/mw/api.php?" ++
           "format=json" ++
           "&action=query" ++
           "&generator=categorymembers" ++
           "&gcmtitle=Category:Programming%20Languages" ++
           "&gcmlimit=100" ++
           "&prop=categoryinfo"

-- Issue query to get a list of Language descriptions
runQuery :: [Language] -> String -> IO ()
runQuery ls query = do
    Just (Report continue langs) <- decode <$> simpleHttp query
    let accLanguages = ls ++ map snd (toList langs)

    case continue of
        -- If there is no continue string we are done so display the accumulated languages.
        Nothing -> showLanguages accLanguages

        -- If there is a continue string, recursively continue the query.
        Just continueStr -> do
            let continueQueryStr = queryStr ++ "&gcmcontinue=" ++ urlEncode continueStr
            runQuery accLanguages continueQueryStr

main :: IO ()
main = runQuery [] queryStr


CHARACTER cats*50000, catlist*50000, sortedCat*50000, sample*100
DIMENSION RankNr(1)

  READ(ClipBoard) cats
  catlist = ' '
  pos = 1 ! find language entries like    * 100 doors (2 members)
  nr = 0
  ! after next '*' find next "name" = '100 doors' and next "(...)" = '(2 members)' :
1 EDIT(Text=cats, SetPos=pos, Right='*', R, Mark1, R='(', Left, M2, Parse=name, R=2, P=members, GetPos=pos)
  IF(pos > 0) THEN
      READ(Text=members) count
      IF(count > 0) THEN
          nr = nr + 1
          WRITE(Text=catlist, Format='i4, 1x, 2a', APPend) count, name, ';'
      ENDIF
      GOTO 1 ! no WHILE in HicEst
  ENDIF      ! catlist is now = "   1  ... User ;   2  100 doors ;   3  3D ;   8  4D ; ..."

  ALLOCATE(RankNr, nr)
  EDIT(Text=catlist, SePaRators=';', Option=1+4, SorTtoIndex=RankNr) ! case (1) and back (4)

  sortedCat = ' ' ! get the sorted list in the sequence of RankNr:
  ok = 0
  DO i = 1, nr
    EDIT(Text=catlist, SePaRators=';', ITeM=RankNr(i), CoPyto=sample)
    discard = EDIT(Text=sample, LeXicon='user,attention,solutions,tasks,program,language,implementation,')
    IF(discard == 0) THEN ! removes many of the non-language entries
        ok = ok + 1
        WRITE(Text=sortedCat, APPend, Format='F5.0, 2A') ok, TRIM(sample), $CRLF
    ENDIF
  ENDDO
  DLG(Text=sortedCat, Format=$CRLF)
END


$define RCLANGS "http://rosettacode.org/mw/api.php?format=xml&action=query&generator=categorymembers&gcmtitle=Category:Programming%20Languages&gcmlimit=500&prop=categoryinfo"
$define RCUA    "User-Agent: Unicon Rosetta 0.1"
$define RCXUA   "X-Unicon: http://unicon.org/"

link strings
link hexcvt

procedure main()
    cnt := create seq()
    last := -1
    every pair := !reverse(sort(langs := tallyPages(),2)) do {
        n := if last ~=:= pair[2] then @cnt else (@cnt,"")
        write(right(n,4),": ",left(pair[1],30,". "),right(pair[2],10,". "))
        }
    write(*langs, " languages")
end

# Generate page counts for each language
procedure tallyPages(url)
    /url := RCLANGS
    counts := table()
    continue := ""
    while \(txt := ReadURL(url||continue)) do {
        txt ? {
            if tab(find("gcmcontinue=")) then {
                continue := "&"||tab(upto('"'))
                move(1)
                continue ||:= tab(upto('"'))
                }
            else continue := ""
            while tab(find("<page ") & find(s := "title=\"Category:")+*s) do {
                lang := tab(upto('"'))
                tab(find(s := "pages=\"")+*s)
                counts[lang] := numeric(tab(upto('"')))
                }
            if continue == "" then return counts
            }
        }
end

procedure ReadURL(url)                 #: read URL into string
    page := open(url,"m",RCUA,RCXUA) | stop("Unable to open ",url)
    text := ""
    if page["Status-Code"] < 300 then while text ||:= reads(page,-1)
    else write(&errout,image(url),": ",
                       page["Status-Code"]," ",page["Reason-Phrase"])
    close(page)
    return text
end


require 'web/gethttp xml/sax/x2j regex'

x2jclass 'rcPopLang'

rx         =:  (<0 1) {:: (2#a:) ,~ rxmatches rxfrom ]

'Popular Languages' x2jDefn
   /                             :=  langs  : langs =: 0 2 $ a:
   html/body/div/div/div/ul/li   :=  langs =: langs ,^:(a:~:{[email protected][)~ lang ;  ' \((\d+) members?\)' rx y
   html/body/div/div/div/ul/li/a :=  lang  =: '^\s*((?:.(?!User|Tasks|Omit|attention|operations|by))+)\s*$' rx y
)

cocurrent'base'

sortTab    =.  \: __ ". [: ;:^:_1: {:"1
formatTab  =:  [: ;:^:_1: [: (20 A. (<'-') , |. , [: ('.' <"1@:,.~ ":) 1 + 1 [email protected],~ 1{$)&.|: sortTab f.

rcPopLangs =:  [email protected]:[email protected]:gethttp


import  java.net.URL;
import  java.net.URLConnection;
import  java.io.*;
import  java.util.*;

public class GetRCLanguages
{
    // Custom sort Comparator for sorting the language list
    // assumes the first character is the page count and the rest is the language name
    private static class LanguageComparator implements Comparator<String>
    {
        public int compare( String a, String b )
        {
            // as we "know" we will be comparaing languages, we will assume the Strings have the appropriate format
            int result = ( b.charAt( 0 ) - a.charAt( 0 ) );
            if( result == 0 )
            {
                // the counts are the same - compare the names
                result = a.compareTo( b );
            } // if result == 0
        return result;
        } // compare
    } // LanguageComparator

    // get the string following marker in text
    private static String after( String text, int marker )
    {
        String result = "";
        int    pos    = text.indexOf( marker );
        if( pos >= 0 )
        {
            // the marker is in the string
            result = text.substring( pos + 1 );
        } // if pos >= 0
    return result;
    } // after

    // read and parse the content of path
    // results returned in gcmcontinue and languageList
    public static void parseContent( String path
                                   , String[] gcmcontinue
                                   , ArrayList<String> languageList
                                   )
    {
        try
        {

            URL            url = new URL( path );
            URLConnection  rc  = url.openConnection();
            // Rosetta Code objects to the default Java user agant so use a blank one
            rc.setRequestProperty( "User-Agent", "" );
            BufferedReader bfr = new BufferedReader( new InputStreamReader( rc.getInputStream() ) );

            gcmcontinue[0]      = "";
            String languageName = "?";
            String line         = bfr.readLine();
            while( line != null )
            {
                line = line.trim();
                if     ( line.startsWith( "[title]" ) )
                {
                    // have a programming language - should look like "[title] => Category:languageName"
                    languageName = after( line, ':' ).trim();
                }
                else if( line.startsWith( "[pages]" ) )
                {
                    // number of pages the language has (probably)
                    String pageCount = after( line, '>' ).trim();
                    if( pageCount.compareTo( "Array" ) != 0 )
                    {
                        // haven't got "[pages] => Array" - must be a number of pages
                        languageList.add( ( (char) Integer.parseInt( pageCount ) ) + languageName );
                        languageName = "?";
                    } // if [pageCount.compareTo( "Array" ) != 0
                }
                else if( line.startsWith( "[gcmcontinue]" ) )
                {
                    // have an indication of wether there is more data or not
                    gcmcontinue[0] = after( line, '>' ).trim();
                } // if various line starts
                line = bfr.readLine();
            } // while line != null
            bfr.close();
        }
        catch( Exception e )
        {
            e.printStackTrace();
        } // try-catch
    } // parseContent

    public static void main( String[] args )
    {
        // get the languages
        ArrayList<String> languageList = new ArrayList<String>( 1000 );
        String[]          gcmcontinue  = new String[1];
        gcmcontinue[0]                 = "";
        do
        {
            String path = ( "http://www.rosettacode.org/mw/api.php?action=query"
                          + "&generator=categorymembers"
                          + "&gcmtitle=Category:Programming%20Languages"
                          + "&gcmlimit=500"
                          + ( gcmcontinue[0].compareTo( "" ) == 0 ? "" : ( "&gcmcontinue=" + gcmcontinue[0] ) )
                          + "&prop=categoryinfo"
                          + "&format=txt"
                          );
            parseContent( path, gcmcontinue, languageList );
        }
        while( gcmcontinue[0].compareTo( "" ) != 0 );
        // sort the languages
        String[] languages = languageList.toArray(new String[]{});
        Arrays.sort( languages, new LanguageComparator() );
        // print the languages
        int    lastTie    = -1;
        int    lastCount  = -1;
        for( int lPos = 0; lPos < languages.length; lPos ++ )
        {
            int    count = (int) ( languages[ lPos ].charAt( 0 ) );
            System.out.format( "%4d: %4d: %s\n"
                             , 1 + ( count == lastCount ? lastTie : lPos )
                             , count
                             , languages[ lPos ].substring( 1 )
                             );
            if( count != lastCount )
            {
                lastTie   = lPos;
                lastCount = count;
            } // if count != lastCount
        } // for lPos
    } // main
} // GetRCLanguages


#!/bin/bash

# produce lines of the form: [ "language", n ]
function categories {
  curl -Ss 'http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000' |\
    grep "/wiki/Category:" | grep member | grep -v '(.*(' |\
    grep -v ' User' |\
    sed -e 's/.*title="Category://' -e 's/member.*//'  |\
    sed 's:^\([^"]*\)"[^(]*(\(.*\):["\1", \2]:'
}

# produce lines of the form: "language"
function languages {
  curl -Ss 'http://rosettacode.org/wiki/Category:Programming_Languages' |\
    sed '/Pages in category "Programming Languages"/,$d' |\
    grep '
<a href="/wiki/Category:' | fgrep title= |\
    sed 's/.*Category:\([^"]*\)".*/"\1"/'
}

categories |\
  /usr/local/bin/jq --argfile languages <(languages) -s -r '

  # input: array of [score, _] sorted by score
  # output: array of [ranking, score, _]
  def ranking:
    reduce .[] as $x
      ([];   # array of [count, rank, score, _]
       if length == 0 then [[1, 1] + $x]
       else .[length - 1] as $previous
       | if $x[0] == $previous[2]
         then . + [ [$previous[0] + 1, $previous[1]] + $x ]
         else . + [ [$previous[0] + 1, $previous[0] + 1] + $x ]
         end
       end)
    | [ .[] | .[1:] ];

    # Every language page has three category pages that should be excluded
    (reduce .[] as $pair
      ({};
       ($pair[1] as $n | if $n > 3 then . + {($pair[0]): ($n - 3)} else . end ))) as $freq
  | [ $languages[] | select($freq[.] != null) |  [$freq[.], .]]
  | sort
  | reverse
  | ranking[]
  | "\(.[0]).  \(.[1]) - \(.[2])" '


using HTTP

try
    response = HTTP.request("GET", "http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000")
    langcount = Dict{String, Int}()
    for mat in eachmatch(r"
]+>([^\<]+)[^1-9]+(\d+)[^\w]+member.?.?
", String(response.body))
        if match(r"^Programming", mat.captures[1]) == nothing
            langcount[mat.captures[1]] = parse(Int, mat.captures[2])
        end
    end
    langs = sort(collect(keys(langcount)), lt=(x, y)->langcount[x]<langcount[y], rev=true)
    for (i, lang) in enumerate(langs)
        println("Language $lang can be ranked #$i at $(langcount[lang]).")
    end
catch y
    println("HTTP request failed: $y.")
    exit()
end


import java.net.URL
import java.io.*

object Popularity {
    /** Gets language data. */
    fun ofLanguages(): List<String> {
        val languages = mutableListOf<String>()
        var gcm = ""
        do {
            val path = url + (if (gcm == "") "" else "&gcmcontinue=" + gcm) + "&prop=categoryinfo" + "&format=txt"
            try {
                val rc = URL(path).openConnection() // URL completed, connection opened
                // Rosetta Code objects to the default Java user agent so use a blank one
                rc.setRequestProperty("User-Agent", "")
                val bfr = BufferedReader(InputStreamReader(rc.inputStream))
                try {
                    gcm = ""
                    var languageName = "?"
                    var line: String? = bfr.readLine()
                    while (line != null) {
                        line = line.trim { it <= ' ' }
                        if (line.startsWith("[title]")) {
                            // have a programming language - should look like "[title] => Category:languageName"
                            languageName = line[':']
                        } else if (line.startsWith("[pages]")) {
                            // number of pages the language has (probably)
                            val pageCount = line['>']
                            if (pageCount != "Array") {
                                // haven't got "[pages] => Array" - must be a number of pages
                                languages += pageCount.toInt().toChar() + languageName
                                languageName = "?"
                            }
                        } else if (line.startsWith("[gcmcontinue]"))
                            gcm = line['>']  // have an indication of whether there is more data or not
                        line = bfr.readLine()
                    }
                } finally {
                    bfr.close()
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        } while (gcm != "")

        return languages.sortedWith(LanguageComparator)
    }

    /** Custom sort Comparator for sorting the language list.
     * Assumes the first character is the page count and the rest is the language name. */
    internal object LanguageComparator : java.util.Comparator<String> {
        override fun compare(a: String, b: String): Int {
            // as we "know" we will be comparing languages, we will assume the Strings have the appropriate format
            var r = b.first() - a.first()
            return if (r == 0) a.compareTo(b) else r
            // r == 0: the counts are the same - compare the names
        }
    }

    /** Gets the string following marker in text. */
    private operator fun String.get(c: Char) = substringAfter(c).trim { it <= ' ' }

    private val url = "http://www.rosettacode.org/mw/api.php?action=query" +
            "&generator=categorymembers" + "&gcmtitle=Category:Programming%20Languages" +
            "&gcmlimit=500"
}

fun main(args: Array<String>) {
    // read/sort/print the languages (CSV format):
    var lastTie = -1
    var lastCount = -1
    Popularity.ofLanguages().forEachIndexed { i, lang ->
        val count = lang.first().toInt()
        if (count == lastCount)
            println("%12s%s".format("", lang.substring(1)))
        else {
            println("%4d, %4d, %s".format(1 + if (count == lastCount) lastTie else i, count, lang.substring(1)))
            lastTie = i
            lastCount = count
        }
    }
}


[
sys_listtraits !>> 'xml_tree_trait' ? include('xml_tree.lasso')
local(lang = array)
local(f = curl('http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000')->result->asString)
local(ff) = xml_tree(#f)
local(lis = #ff->body->div(3)->div(3)->div(3)->div->ul->getnodes)
with li in #lis do => {
	local(title = #li->a->attribute('title'))
	#title->removeLeading('Category:')
	local(num = #li->asString->split('(')->last)
	#num->removeTrailing(')')
	#num->removeTrailing('members')
	#num->removeTrailing('member')
	#num->trim
	#num = integer(#num)
	#lang->insert(#title = #num)
}
local(c = 1)
with l in #lang
order by #l->second descending
do => {^
	#c++
	'. '+#l->second + '  - ' + #l->first+'\r'
^}
]


Module RankLanguages {
      Const Part1$="{
            Declare htmldoc "Msxml2.ServerXMLHTTP"
            With htmldoc , "readyState" as ready
            Report "Download:"+url$
            Method htmldoc "open","get", url$, True
            Method htmldoc "send"
            Profiler
            While Ready<>4 {
                  Wait 20
                  Print Over format$("Wait: {0:3} sec", timecount/1000)
                  If timecount>timeout then Exit
            }
            If ready=4 Then  With  htmldoc, "responseText" as ready$ : =ready$
            Declare htmldoc Nothing
            print
      }

      languages$=httpGet$(langHttp$, 30000)
      If Doc.Len(languages$)=0 then  Error "File download failed (languages)"

      Inventory Lang

      m=Paragraph(languages$, 0)
      If Forward(languages$,m) then {
            While m {
                  job$=Paragraph$(languages$,(m))
                  If Instr(job$, part1$) Else Continue
                  i = Instr(job$, "")
                  If i Else Continue   ' same as If i=0 Then Continue
                  j = i
                   i=Rinstr(job$, ">", -i)
                  If i Else Continue
                  LastLang$=MID$(job$, i+1, j-i-1)
                  if Instr(job$, "Category:"+lastlang$) then Append lang, lastlang$:=0  :  Print Over format$("Languages: {0}", len(lang))
            }
      }
      Print
      Document categories$=httpGet$(categoriesHttp$, 30000)
      If Doc.Len(categories$)=0 then  Error "File download failed (categories)"
      limit=Doc.Par(categories$)
      If limit<Len(Lang) then Error "Invalid data"
      Refresh
      set slow
      m=Paragraph(categories$, 0)
      counter=0
      If Forward(categories$,m) then {
            While m {
                  job$=Paragraph$(categories$,(m))
                  counter++
                  Print Over format$("{0:2:-6}%", counter/limit*100)
                  i=Instr(job$, part2$)
                  If  i Else Continue
                  i=Rinstr(job$, "(", -i)
                  If  i Else Continue
                  tasks=Val(Filter$(Mid$(job$, i+1),","))
                  If tasks Else Continue
                  i=Rinstr(job$, "<", -i)
                  If i Else Continue
                  j = i
                  i=Rinstr(job$, ">", -i)
                  If i Else Continue
                  LastLang$=MID$(job$, i+1, j-i-1)
                  If Exist(Lang, LastLang$) Then {
                         Return Lang, LastLang$:=Lang(LastLang$)+tasks
                  }
            }
      }
      Print
      \\ this type of inventory can get same keys
      \\ also has stable sort
      Report "Make Inventory list by Task"
      Inventory queue ByTask
      t1=Len(Lang)
      T=Each(Lang)
      While T {
            Append ByTask, Eval(T):=Eval$(T!)
            Print Over format$("Complete: {0} of {1}", T^+1, t1 )
      }
      Print
      Report "Sort by task (stable sort, sort keys as numbers)"
      Sort descending ByTask as number
      Report "Make List"
      T=Each(ByTask)
      final$="Sample output on "+Date$(Today, 1033, "long date")+{:

      }
      While T {
            final$=format$("rank:{0::-4}. {1:-5} entries - {2}", T^+1, Eval$(T!), Eval$(T))+{
            }
      }
      Report "Copy to Clipboard"
      clipboard final$
      \\ present to console with 3/4 fill lines then stop for space bar or mouse click to continue
      Report final$
}
RankLanguages


count_sizes := proc(arr_name,arr_pop,i,lst)
	local index := i;
	local language;
	for language in lst do
		language := language[1]:
		arr_name(index) := txt["query"]["pages"][language]["title"][10..]:
		if(assigned(txt["query"]["pages"][language]["categoryinfo"]["size"])) then
			arr_pop(index) := txt["query"]["pages"][language]["categoryinfo"]["size"]:
		else:
			arr_pop(index) := 0:
		end if:
		index++:
	end do:
	return index:
end proc:

txt := JSON:-ParseFile("http://rosettacode.org/mw/api.php?action=query&generator=categorymembers&gcmtitle=Category:Programming%20Languages&gcmlimit=350&prop=categoryinfo&format=json"):
arr_name := Array():
arr_pop := Array():
i := count_sizes(arr_name, arr_pop, 1, [indices(txt["query"]["pages"])]):
while (assigned(txt["continue"]["gcmcontinue"])) do
	continue := txt["continue"]["gcmcontinue"]:
	txt := JSON:-ParseFile(cat("http://rosettacode.org/mw/api.php?action=query&generator=categorymembers&gcmtitle=Category:Programming%20Languages&gcmlimit=350&prop=categoryinfo&format=json", "&continue=", txt["continue"]["continue"], "&gcmcontinue=", txt["continue"]["gcmcontinue"])):
	i:=count_sizes(arr_name,arr_pop,i,[indices(txt["query"]["pages"])]):
end do:
arr_name:= arr_name[sort(arr_pop,output=permutation)]:
arr_pop := sort(arr_pop, output=sorted):
i := i-1:
for x from i to 1 by -1 do
	printf("rank %d    %d examples    %s\n", i-x+1, arr_pop[x], arr_name[x]):
end do:


Languages = Flatten[Import["http://rosettacode.org/wiki/Category:Programming_Languages","Data"][[1,1]]];
Languages = [email protected][Languages, {" " -> "_", "+" -> "%2B"}];
b = {#, If[#  ===  {}, 0, #[[1]]]&@( StringCases[Import["http://rosettacode.org/wiki/Category:"<>#,"Plaintext"],
   "category, out of " ~~ x:NumberString ~~ " total" ->x])} &/@ Languages;
For[i = 1, i < [email protected] , i++ , Print[i, ". ", #[[2]], " - ", #[[1]] ]&@ Part[[email protected][b, Last], i]]