Rosetta Code/Rank languages by popularity

From Rosetta Code
Jump to: navigation, search
Task
Rosetta Code/Rank languages by popularity
You are encouraged to solve this task according to the task description, using any language you may know.

Sort most popular programming languages based in number of members in Rosetta Code categories
(from http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000)

Sample output on March 30 2014:

  1. 797 - Tcl
  2. 756 - Racket
  3. 750 - Python
  4. 719 - C
  5. 692 - Perl 6
  6. 678 - D
  7. 677 - J
  8. 668 - Ruby
  9. 638 - Go
 10. 636 - PicoLisp
 11. 630 - Perl
 12. 615 - REXX
 13. 585 - Ada
 14. 578 - Haskell
 15. 567 - Mathematica
 16. 561 - AutoHotkey
 17. 541 - Unicon
 18. 539 - Java
 19. 525 - BBC BASIC
 20. 495 - Icon
 21. 492 - OCaml
 22. 487 - C++
 23. 473 - Common Lisp
 24. 469 - PureBasic
 25. 446 - C sharp
 26. 444 - Erlang
 27. 411 - Scala
 28. 387 - JavaScript
 29. 385 - Clojure
 30. 359 - Seed7
 31. 347 - Lua
 32. 341 - Groovy
 33. 340 - R
 34. 340 - F Sharp
 35. 337 - Forth
 36. 335 - PHP
 37. 329 - ALGOL 68
 38. 328 - Fortran
 39. 319 - Pascal
 40. 307 - Liberty BASIC
...

A complete ranked listing of all 535 languages (from the REXX example) is included here ──► RC_POP.OUT.

Filtering wrong results is optional. You can check against Special:MostLinkedCategories

Contents

[edit] Ada

Library: AWS
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;
 

[edit] ALGOL 68

Works with: ALGOL 68G version mk8+ for Unix and Linux - tested with release mk15-0.8b.fc9.i386 - uses non-standard library routines http content and grep in string.

Note: the routine http content is currently not available on Win32 systems.

This example is incorrect. ---among others, Tcl (the top dog) is missing. Please fix the code and remove this message.
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
Sample output:
1. 233 - Python
2. 222 - Ada
3. 203 - OCaml
4. 203 - C
5. 201 - Perl
6. 193 - Haskell
7. 182 - Java
8. 179 - D
9. 178 - ALGOL 68
10. 160 - Ruby

[edit] AutoHotkey

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

[edit] AWK

This example is incorrect. Broken because nc may close the connection too soon. It sends the HTTP request but then quits before getting the response. So the program gets an empty list of languages. Please fix the code and remove this message.


Works with: Gawk version 3.1.8

The solution for Awk now goes through the API at http://rosettacode.org/mw/api.php, so it only ranks programming languages. This solution replaces an older solution for Awk that tried to scrape the HTML.

This solution needs help from the nc command to make a TCP connection.

Translation of: Perl
Library: nc
BEGIN {
for (i = 0; i <= 255; i++)
ord[sprintf("%c", i)] = i
}
 
# Encode string with application/x-www-form-urlencoded escapes.
function escape(str, c, len, res) {
len = length(str)
res = ""
for (i = 1; i <= len; i++) {
c = substr(str, i, 1);
if (c ~ /[-._*0-9A-Za-z]/)
res = res c
else if (c == " ")
res = res "+"
else
res = res "%" sprintf("%02X", ord[c])
}
return res
}
 
function nc_open(gcmcontinue, host, path) {
host = "rosettacode.org"
path = "/mw/api.php" \
"?action=query" \
"&generator=categorymembers" \
"&gcmtitle=Category:Programming%20Languages" \
"&gcmlimit=500" \
(gcmcontinue "" ? "&gcmcontinue=" escape(gcmcontinue) : "") \
"&prop=categoryinfo" \
"&format=txt"
 
nc = "printf 'GET %s HTTP/1.1\r\nHost: %s\r\n\r\n' '" \
path "' '" host "' | nc '" host "' 80"
}
 
function nc_next(out) {
# Read each line of the HTTP response.
while (nc | getline > 0) {
# Ignore all lines except
# [gcmcontinue], [title] and [pages].
if (index($0, "[gcmcontinue]")) {
# " [gcmcontinue] => BEFUNGE|"
sub(/^.*=> */, "")
out["gcmcontinue"] = $0
} else if (index($0, "[title]")) {
# " [title] => Category:AWK"
sub(/^.*Category:/, "")
out["title"] = $0
} else if(index($0, "[pages]")) {
# " [pages] => 129"
sub(/^.*=> */, "")
# Ignore " [pages] => Array".
if ($0 !~ /^[0-9]+/)
continue
 
# Force conversion to number, so AWK will do
# numeric comparisons, not string comparisons.
out["pages"] = $0 + 0
 
# Return now; [pages] came after [title].
return 1
}
}
 
if ("gcmcontinue" in out) {
close(nc)
nc_open(out["gcmcontinue"])
delete out["gcmcontinue"]
return nc_next(out)
} else
return 0
}
 
BEGIN {
nc_open()
while (nc_next(language)) {
title = language["title"] # "AWK"
pages = language["pages"] # 129
 
# Insert "129 - AWK" into rank[].
i = 1
while (i <= count && (rank[i] + 0) >= pages)
i++
for (j = count; j >= i; j--)
rank[j + 1] = rank[j]
rank[i] = pages " - " title
count++
}
 
for (i = 1; i <= count; i++)
print i ". " rank[i]
}
Output from 1 April 2010:
1. 492 - Tcl
2. 458 - Python
3. 454 - PicoLisp
4. 436 - J
5. 407 - C
...
49. 129 - AWK
...

[edit] BBC BASIC

Note that language names differing only in their case are merged.

      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$, "</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

Output:

Downloading languages list...
Downloading categories list...
List of languages as of Sat.17 Nov 2012,00:21:11
  1. 682 - Tcl
  2. 638 - Python
  3. 626 - PicoLisp
  4. 622 - C
  5. 592 - J
  6. 581 - Go
  7. 570 - Ruby
  8. 553 - Ada
  9. 515 - Perl
 10. 514 - D
 11. 507 - Haskell
 12. 490 - Perl 6
 13. 489 - BBC BASIC
 14. 477 - Java
 15. 473 - Mathematica
 16. 469 - PureBasic
 17. 469 - OCaml
 18. 459 - Unicon
 19. 438 - REXX
 20. 428 - Icon
......
461.   1 - ScriptBasic
462.   1 - Qore
463.   1 - Opa
464.   1 - Nickle
465.   1 - Neko
466.   1 - Neat
467.   1 - MEL
468.   1 - MAPPER
469.   1 - Kotlin
470.   1 - Chapel

[edit] Bracmat

  ( 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
)
)
& ;

Output:

  1. 816 - Tcl
  2. 771 - Racket
  3. 760 - Python
  4. 708 - C
  5. 705 - Perl 6
  6. 700 - J
  7. 695 - Ruby
  8. 690 - D
  9. 656 - Go
 10. 643 - PicoLisp
 11. 639 - Perl
 12. 622 - REXX
 13. 602 - Ada
 14. 591 - Mathematica
 15. 588 - Haskell
 16. 574 - AutoHotkey
 17. 559 - Unicon
 18. 543 - Java
 19. 526 - BBC BASIC
 20. 510 - Icon
 21. 500 - C++
...
498. 1 - Vox
498. 1 - XPath 2.0
498. 1 - Xanadu
523. 0 - Clarion
523. 0 - EhBASIC
523. 0 - Epigram
523. 0 - FLORA-2
523. 0 - Florid
523. 0 - Jcon
523. 0 - LLP
523. 0 - Lolli
523. 0 - Lygon
523. 0 - Monte
523. 0 - ObjectIcon
523. 0 - RPGIV
523. 0 - Rubylog
523. 0 - Star
523. 0 - True BASIC
523. 0 - X10
523. 0 - XS
523. 0 - Ya

[edit] C

Ghetto parser
#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;
}
Output:
 563 Tcl
 529 PicoLisp
 522 Python
 504 C
 500 J
 442 Go
 440 Ruby
 435 Ada
 430 PureBasic
 427 Perl
...

[edit] C#

Sorting only programming languages.

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++;
}
}
}
Output (as of May 30, 2010):
 1. 397 - Tcl
 2. 368 - Python
 3. 350 - Ruby
 4. 333 - J
 5. 332 - C
 6. 322 - Haskell
 7. 322 - OCaml
 8. 302 - Perl
 9. 290 - Common Lisp
10. 289 - AutoHotkey
    . . .

[edit] Object-oriented solution

using System;
using System.Net;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections.Generic;
 
class Category {
private string _title;
private int _members;
 
public Category(string title, int members) {
_title = title;
_members = members;
}
 
public string Title {
get {
return _title;
}
}
 
public int Members {
get {
return _members;
}
}
}
 
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");
 
MatchCollection match1 = new Regex("\"title\":\"Category:(.+?)\"").Matches(get1);
MatchCollection match2 = new Regex("title=\"Category:(.+?)\">.+?</a>[^(]*\\((\\d+) members\\)").Matches(get2);
 
string[] valids = match1.Cast<Match>().Select(x => x.Groups[1].Value).ToArray();
List<Category> langs = new List<Category>();
 
foreach (Match match in match2) {
string category = match.Groups[1].Value;
int members = Int32.Parse(match.Groups[2].Value);
 
if (valids.Contains(category)) langs.Add(new Category(category, members));
}
 
langs = langs.OrderByDescending(x => x.Members).ToList();
int count = 1;
 
foreach (Category i in langs) {
Console.WriteLine("{0,3}. {1,3} - {2}", count, i.Members, i.Title);
count++;
}
}
}

[edit] C++

Library: Boost

using g++ under Linux with g++ -lboost_thread -lboost_system -lboost_regex:

#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( "<li><a href=\"[^<>]+?\">([a-zA-Z\\+#1-9]+?)</a>\\s?\\((\\d+) members\\)</li>" ) ;
//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 ;
}
Sample output (just the "top ten"):
 1. 367 - Tcl
 2. 334 - Python
 3. 319 - Ruby
 4. 286 - C
 5. 277 - Perl
 6. 272 - OCaml
 7. 264 - Ada
 8. 241 - E
 9. 239 - AutoHotkey
10. 193 - Forth

[edit] Caché ObjectScript

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 '&#160;'>")
Set sc=xml.WriteLine($Char(9)_"<!ENTITY amp '&#38;'>")
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
}
 
}
Example:
USER>Do ##class(Utils.Net.RosettaCode).GetTopLanguages("www.rosettacode.org", "/mw/index.php?title=Special:Categories&limit=5000")
Top 10 Languages (as at 21 Apr 2013):
  1. 728 - Tcl
  2. 668 - Python
  3. 654 - C
  4. 630 - J
  5. 626 - PicoLisp
  6. 595 - D
  7. 590 - Ruby
  8. 589 - Go
  9. 576 - Perl 6
 10. 567 - Ada

[edit] D

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[]);
}
Sample output (top twenty as of 2013-01-24):
  1. 717 - Tcl
  2. 663 - Python
  3. 643 - C
  4. 626 - PicoLisp
  5. 622 - J
  6. 587 - Go
  7. 587 - Ruby
  8. 585 - D
  9. 568 - Perl 6
 10. 564 - Ada
 11. 554 - Mathematica
 12. 535 - Perl
 13. 532 - Haskell
 14. 514 - BBC BASIC
 15. 505 - REXX
 16. 491 - Java
 17. 478 - OCaml
 18. 469 - PureBasic
 19. 462 - Unicon
 20. 430 - AutoHotkey

[edit] Erlang

 
-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}.
Sample output (top/last ten as of 2013-05-27):
1. 741 - "Tcl"
2. 676 - "Python"
3. 660 - "C"
4. 638 - "J"
5. 627 - "PicoLisp"
6. 609 - "Perl 6"
6. 609 - "D"
8. 607 - "Racket"
9. 592 - "Ruby"
10. 589 - "Go"
...
454. 1 - "Opa"
454. 1 - "Nickle"
454. 1 - "NewtonScript"
454. 1 - "Neko"
454. 1 - "Neat"
454. 1 - "MEL"
454. 1 - "MAPPER"
454. 1 - "LiveScript"
454. 1 - "Kotlin"
454. 1 - "Jacquard Loom"

[edit] F#

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

Showing top 20 as of 2013-04-02

   1. 721 - Tcl
   2. 665 - Python
   3. 647 - C
   4. 626 - PicoLisp
   5. 622 - J
   6. 588 - Go
   7. 588 - Ruby
   8. 585 - D
   9. 569 - Perl 6
  10. 565 - Ada
  11. 555 - Mathematica
  12. 535 - Perl
  13. 533 - Haskell
  14. 514 - BBC BASIC
  15. 505 - REXX
  16. 491 - Java
  17. 480 - OCaml
  18. 469 - PureBasic
  19. 462 - Unicon
  20. 430 - AutoHotkey

[edit] Go

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("<li><a.*>(.*)</a>.*[(]([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)
}
}
Output on 11 Aug 2014:
  1. 832 - Tcl
  2. 783 - Racket
  3. 774 - Python
  4. 733 - Perl 6
  5. 729 - J
…
506.   1 - Supernova
506.   1 - TestML
506.   1 - Vox
506.   1 - XPath 2.0
506.   1 - Xanadu

(All the final entries are tied for spot 506, there are 530 lines.)

[edit] Groovy

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 =~ '<li><a[^>]+>([^<]+)</a>[^(]*[(](\\d+) member[s]*[)]</li>').each { match, language, members ->
count[language] = (members as int)
}
count.sort { v1, v2 -> v2.value <=> v1.value }.eachWithIndex { value, index -> println "${index + 1} $value" }

Output:

1 Tcl=766
2 Racket=726
3 Python=712
4 Programming Tasks=695
5 C=681
6 Perl 6=649
...
48 Groovy=323

[edit] Haskell

import Network.Browser
import Network.HTTP
import Network.URI
import Data.List
import Data.Maybe
import Text.XML.Light
import Control.Arrow
import Data.Ord
 
getRespons url = do
rsp <- Network.Browser.browse $ do
setAllowRedirects True
setOutHandler $ const (return ()) -- quiet
request $ getRequest url
return $ rspBody $ snd rsp
 
 
mostPopLang = do
rsp <-getRespons $ "http://www.rosettacode.org/w/api.php?action=query&list=" ++
"categorymembers&cmtitle=Category:Programming_Languages&cmlimit=500&format=xml"
mbrs <- getRespons "http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000"
let xmls = onlyElems $ parseXML rsp
langs = concatMap (map ((\\"Category:"). fromJust.findAttr (unqual "title")). filterElementsName (== unqual "cm")) xmls
 
let catMbr = second (read.takeWhile(/=' '). drop 6). break (=='<'). drop 1. dropWhile(/='>') . drop 5
catNmbs :: [(String, Int)]
catNmbs = map catMbr $ filter (isPrefixOf "<li>") $ lines mbrs
printFmt (n,(l,m)) = putStrLn $ take 6 (show n ++ ". ") ++ (show m) ++ " " ++ l
toMaybe (a,b) =
case b of
Just x -> Just (a,x)
_ -> Nothing
 
mapM_ printFmt $ zip [1..] $ sortBy (flip (comparing snd))
$ mapMaybe (toMaybe. (id &&& flip lookup catNmbs)) langs
First 20:
*Main> mostPopLang
1.    421  Tcl
2.    392  Python
3.    365  PicoLisp
4.    363  J
5.    360  Ruby
6.    354  C
7.    344  Haskell
8.    337  OCaml
9.    316  Perl
10.   308  PureBasic
11.   302  AutoHotkey
12.   299  Common Lisp
13.   295  D
14.   295  Java
15.   293  Ada
16.   278  Oz
17.   260  R
18.   259  C sharp
19.   257  C++
20.   255  ALGOL 68

[edit] HicEst

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
2010-04-24 18:31
Top 10 entries (not all are languages)
1. 394 Tcl
2. 363 Python
3. 346 Ruby
4. 328 J
5. 319 C
6. 317 OCaml
7. 315 Haskell
8. 298 Perl
9. 288 WikiStubs
10. 281 Common Lisp

[edit] Icon and Unicon

The following solution only works in Unicon.

$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(tallyPages(),2)) do {
n := if last ~=:= pair[2] then @cnt else (@cnt,"")
write(right(n,4),": ",left(pair[1],30,". "),right(pair[2],10,". "))
}
end
 
# Generate page counts for each language
procedure tallyPages(url)
/url := RCLANGS
counts := table()
continue := ""
while \(txt := ReadURL(url||continue)) do {
txt ? {
while tab(find("<page ") & find(s := "title=\"Category:")+*s) do {
lang := tab(upto('"'))
tab(find(s := "pages=\"")+*s)
counts[lang] := numeric(tab(upto('"')))
}
if tab(find("cmcontinue=")) then {
continue := "&"||tab(upto(' \t'))
}
else 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

Abridged output (top 25 languages as of June 7, 2013):

   1: Tcl . . . . . . . . . . . . . . . . .743
   2: Racket. . . . . . . . . . . . . . . .696
   3: Python. . . . . . . . . . . . . . . .679
   4: C . . . . . . . . . . . . . . . . . .663
   5: J . . . . . . . . . . . . . . . . . .635
   6: PicoLisp. . . . . . . . . . . . . . .624
   7: Perl 6. . . . . . . . . . . . . . . .617
   8: D . . . . . . . . . . . . . . . . . .608
   9: Ruby. . . . . . . . . . . . . . . . .590
  10: Go. . . . . . . . . . . . . . . . . .586
  11: Ada . . . . . . . . . . . . . . . . .569
  12: Mathematica . . . . . . . . . . . . .559
  13: Perl. . . . . . . . . . . . . . . . .548
  14: Haskell . . . . . . . . . . . . . . .540
  15: REXX. . . . . . . . . . . . . . . . .531
  16: BBC BASIC . . . . . . . . . . . . . .513
  17: Java. . . . . . . . . . . . . . . . .508
  18: Unicon. . . . . . . . . . . . . . . .478
    : OCaml . . . . . . . . . . . . . . . .478
  20: PureBasic . . . . . . . . . . . . . .467
  21: C++ . . . . . . . . . . . . . . . . .452
  22: Icon. . . . . . . . . . . . . . . . .445
  23: AutoHotkey. . . . . . . . . . . . . .427
    : Common Lisp . . . . . . . . . . . . .427
  25: C sharp . . . . . . . . . . . . . . .421

[edit] J

Solution:
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:~:{.@[)~ 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 i.@,~ 1{$)&.|: sortTab f.
 
rcPopLangs =: formatTab@:process_rcPopLang_@:gethttp
Example:
   10 {. rcPopLangs 'http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=2000'
1. 687 - Tcl
2. 646 - Python
3. 637 - C
4. 626 - PicoLisp
5. 612 - J
6. 587 - Go
7. 556 - Ada
8. 550 - D
9. 549 - Mathematica
10. 526 - Perl

Notes: See some notes on the J solution.

[edit] Lasso

<pre><code>[
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'
^}
]</code></pre>
Output:
1. 759  - Tcl
2. 724  - Racket
3. 707  - Python
4. 692  - Programming Tasks
5. 672  - C
6. 643  - J
7. 635  - Perl 6
8. 632  - D
9. 627  - PicoLisp
10. 617  - Ruby
...

[edit] Mathematica

Languages = Flatten[Import["http://rosettacode.org/wiki/Category:Programming_Languages","Data"][[1,1]]];
Languages = Most@StringReplace[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 < Length@b , i++ , Print[i, ". ", #[[2]], " - ", #[[1]] ]&@ Part[Reverse@SortBy[b, Last], i]]
Output 
As of 29 February 2012:
1. 637 - Tcl
2. 576 - C
3. 558 - J
4. 538 - Go
5. 485 - Ada
6. 456 - D
7. 450 - Haskell
8. 441 - Mathematica
9. 432 - Java
10. 425 - Icon
...

[edit] Nimrod

import httpclient, json, re, strutils, algorithm
 
const
langSite = "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Languages&cmlimit=500&format=json"
catSize = "http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000"
let regex = re"title=""Category:(.*?)"">.+?</a>.*\((.*) members\)"
 
var langs: seq[string] = @[]
for l in parseJson(getContent(langSite))["query"]["categorymembers"]:
langs.add(l["title"].str.split("Category:")[1])
 
var ranks: seq[tuple[lang: string, count: int]] = @[]
for line in getContent(catSize).findAll(regex):
let lang = line.replacef(regex, "$1")
if lang in langs:
let count = parseInt(line.replacef(regex, "$2").strip())
ranks.add((lang, count))
 
ranks.sort(proc (x, y): int = cmp[int](y.count, x.count))
for i, l in ranks:
echo align($(i+1), 3), align($l.count, 5), " - ", l.lang

Output:

  1  833 - Tcl
  2  781 - Racket
  3  770 - Python
  4  730 - Perl 6
  5  725 - J
  6  712 - C
  7  708 - Ruby
  8  698 - D
  9  674 - Go
 10  656 - Perl
...

[edit] ooRexx

/* REXX ---------------------------------------------------------------
* Create a list of Rosetta Code languages showing the number of tasks
* This program's logic is basically that of the REXX program
* rearranged to my taste and utilizing the array class of ooRexx
* which offers a neat way of sorting as desired, see :CLASS mycmp below
* For the input to this program open these links:
* http://rosettacode.org/wiki/Category:Programming_Languages
* http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000
* and save the pages as LAN.txt and CAT.txt, respectively
* Output: RC_POP.txt list of languages sorted by popularity
* If test=1, additionally:
* RC_LNG.txt list of languages alphabetically sorted
* RC_TRN.txt list language name translations (debug)
* 24.11.2013 Walter Pachl
*--------------------------------------------------------------------*/

test=1
name.='??'
l.=0
safe=''
x00='00'x
linfid='RC_LAN.txt'
linfid='LAN.txt' /* language file */
cinfid='CAT.txt' /* category file */
oid='RC_POP.txt'; 'erase' oid
If test Then Do
tid='RC.TRN.txt'; 'erase' tid
tia='RC_LNG.txt'; 'erase' tia
End
Call init
 
call read_lang /* process language file */
 
Call read_cat /* process category file */
 
Call ot words(lang_list) 'possible languages'
Call ot words(lang_listr) 'relevant languages'
llrn=words(lang_listr)
 
If test Then
Call no_member
 
a=.array~new /* create array object */
cnt.=0
Do i=1 By 1 While lang_listr<>''
Parse Var lang_listr ddu0 lang_listr
ddu=translate(ddu0,' ',x00)
a[i]=right(mem.ddu,3) name.ddu /* fill array element */
z=mem.ddu /* number of members */
cnt.z=cnt.z+1 /* number of such languages */
End
n=i-1 /* number of output lines */
 
a~sortWith(.mycmp~new) /* sort the array elements */
/* see :CLASS mycmp below */
/*---------------------------------------------------------------------
* and now create the output
*--------------------------------------------------------------------*/

Call o ' '
Call o center('timestamp: ' date() time('Civil'),79,'-')
Call o ' '
Call o right(lrecs,9) 'records read from file: ' linfid
Call o right(crecs,9) 'records read from file: ' cinfid
Call o right(llrn,9) 'relevant languages'
Call o ' '
 
rank=0
rank.=0
Do i=1 To n
rank=rank+1
Parse Value a[i] With o . 6 lang
ol=' rank: 'right(rank,3)' '||,
'('right(o,3) 'entries) 'lang
If cnt.o>1 Then Do
If rank.o=0 Then
rank.o=rank
ol=overlay(right(rank.o,3),ol,17)
ol=overlay('[tied]',ol,22)
End
Call o ol
End
 
Call o ' '
Call o center('+ end of list +',72)
Say 'Output in' oid
 
If test Then Do
b=.array~new /* create array object */
cnt.=0
Do i=1 By 1 While lang_list<>''
Parse Var lang_list ddu0 lang_list
ddu=translate(ddu0,' ',x00)
b[i]=right(mem.ddu,3) name.ddu /* fill array element */
End
n=i-1 /* number of output lines */
 
b~sortWith(.alpha~new) /* sort the array elements */
Call oa n 'languages'
Do i=1 To n
Call oa b[i]
End
Say 'Sorted list of languages in' tia
End
Exit
 
o:
Return lineout(oid,arg(1))
ot:
If test Then Call lineout tid,arg(1)
Return
oa:
If test Then Call lineout tia,arg(1)
Return
 
read_lang:
/*---------------------------------------------------------------------
* Read the language page to determine the list of possible languages
* Output: l.lang>0 for all languages found
* name.lang original name of uppercased language name
* lang_list list of uppercased language names
* lrecs number of records read from language file
*--------------------------------------------------------------------*/

l.=0
name.='??'
lang_list=''
Do lrecs=0 While lines(linfid)\==0
l=linein(linfid) /* read from language file */
l=translate(l,' ','9'x) /* turn tabs to blanks */
dd=space(l) /* remove extra blanks */
ddu=translate(dd)
If pos('AUTOMATED ADMINISTRATION',ddu)>0 Then /* ignore this */
Iterate
If pos('RETRIEVED FROM',ddu)\==0 Then /* this indicates the end */
Leave
If dd=='' Then /* ignore all blank lines. */
Iterate
If left(dd,1)\=='*' Then /* ignore lines w/o * */
Iterate
ddo=fix_lang(dd) /* replace odd language names */
If ddo<>dd Then Do /* show those that we found */
Call ot ' ' dd
Call ot '>' ddo
dd=ddo
End
Parse Var dd '*' dd "<" /* extract the language name */
ddu=strip(translate(dd)) /* translate to uppercase */
If name.ddu='??' Then
name.ddu=dd /* remember 1st original name */
l.ddu=l.ddu+1
ddu_=translate(ddu,x00,' ')
If wordpos(ddu_,lang_list)=0 Then
lang_list=lang_list ddu_
End
Return
 
read_cat:
/*---------------------------------------------------------------------
* Read the category page to get language names and number of members
* Output: mem.ddu number of members for (uppercase) Language ddu
* lang_listr the list of relevant languages
*--------------------------------------------------------------------*/

mem.=0
lang_listr=''
Do crecs=0 While lines(cinfid)\==0
l=get_cat(cinfid) /* read from category file */
l=translate(l,' ','9'x) /* turn tabs to blanks */
dd=space(l) /* remove extra blanks */
If dd=='' Then /* ignore all blank lines. */
Iterate
ddu=translate(dd)
ddo=fix_lang(dd) /* replace odd language names */
If ddo<>dd Then Do /* show those that we found */
Call ot ' ' dd
Call ot '>' ddo
dd=ddo
End
du=translate(dd) /* get an uppercase version. */
If pos('RETRIEVED FROM',du)\==0 Then /* this indicates the end */
Leave
Parse Var dd dd '<' "(" mems . /* extract the language name */
/* and the number of members */
dd=space(substr(dd,3))
_=translate(dd)
If \l._ Then /* not a known language */
Iterate /* ignore */
If\datatype(mems,'W') Then /* not a number of members */
Iterate /* ignore */
ddu=space(translate(dd))
mem.ddu=mem.ddu+mems /* set o add number of members*/
Call memory ddu /* list of relevant languages */
End
Return
 
get_cat:
/*---------------------------------------------------------------------
* get a (logical) line from the category file
* These two lines
* * Lotus 123 Macro Scripting
* </wiki/Category:Lotus_123_Macro_Scripting>‏‎ (3 members)
* are returned as one line:
*-> * Lotus 123 Macro Scripting </wiki/Cate ... (3 members)
* we need language name and number of members in one line
*--------------------------------------------------------------------*/

Parse Arg fid
If safe<>'' Then
ol=safe
Else Do
If lines(fid)=0 Then
Return ''
ol=linein(fid)
safe=''
End
If left(ol,3)=' *' Then Do
Do Until left(r,3)==' *' | lines(fid)=0
r=linein(fid)
If left(r,3)==' *' Then Do
safe=r
Return ol
End
Else
ol=ol r
End
End
Return ol
 
memory:
ddu0=translate(ddu,x00,' ')
If wordpos(ddu0,lang_listr)=0 Then
lang_listr=lang_listr ddu0
Return
 
fix_lang: Procedure Expose old. new.
Parse Arg s
Do k=1 While old.k\=='' /* translate Unicode variations. */
If pos(old.k,s)\==0 Then
s=changestr(old.k,s,new.k)
End
Return s
 
init:
old.=''
old.1='UC++' /* '55432B2B'X */
new.1="µC++" /* old UC++ --?ASCII-8: µC++ */
old.2='МК-61/52' /* 'D09CD09A2D36312F3532'X */
new.2='MK-61/52' /* somewhere a mistranslated: MK- */
old.3='Déjà Vu' /* '44C3A96AC3A0205675'X */
new.3='Déjà Vu' /* Unicode +¬j+á --?ASCII-8: Déjá */
old.4='Caché' /* '43616368C3A9'X */
new.4='Caché' /* Unicode ach+¬ --?ASCII-8: Caché */
old.5='ÎœC++' /* 'CE9C432B2B'X */
new.5="MC++" /* Unicode +£C++ --?ASCII-8: µC++ */
/*-----------------------------------------------------------------*/
Call ot 'Language replacements:'
Do ii=1 To 5
Call ot ' ' left(old.ii,10) left(c2x(old.ii),20) '->' new.ii
End
Call ot ' '
Return
 
no_member: Procedure Expose lang_list lang_listr tid x00 test
/*---------------------------------------------------------------------
* show languages found in language file that are not referred to
* in the category file
*--------------------------------------------------------------------*/

ll =wordsort(lang_list ) /* languages in language file */
llr=wordsort(lang_listr) /* languages in category file */
Parse Var ll l1 ll
Parse Var llr l2 llr
nn.=0
Do Forever
Select
When l1=l2 Then Do
If l1='' Then /* both lists empty */
Leave
Parse Var ll l1 ll /* get the next language */
Parse Var llr l2 llr /* -"- */
End
When l1<l2 Then Do /* in language file */
/* and not in category file */
z=nn.0+1
nn.z=' 'translate(l1,' ',x00) /* show in test output */
nn.0=z
Parse Var ll l1 ll /* next from language file */
End
Otherwise Do
Call ot '?? 'translate(l2,' ',x00) /* show in test output */
Say 'In category file but not in language file:'
Say '?? 'translate(l2,' ',x00)
Say 'Hit enter to proceed'
Pull .
Parse Var llr l2 llr /* next from category file */
End
End
End
Call ot nn.0 'Languages without members:' /* heading */
Do ii=1 To nn.0
Call ot nn.ii
End
Return
 
::CLASS mycmp MIXINCLASS Comparator
::METHOD compare
/**********************************************************************
* smaller number is considered higher
* numbers equal: higher language considered higher
* otherwise return lower
**********************************************************************/

Parse Upper Arg a,b
Parse Var a na +4 ta
Parse Var b nb +4 tb
Select
When na<<nb THEN res=1
When na==nb Then Do
If ta<<tb Then res=-1
Else res=1
End
Otherwise res=-1
End
Return res
 
 
::CLASS alpha MIXINCLASS Comparator
::METHOD compare
/**********************************************************************
* higher language considered higher
* otherwise return lower
**********************************************************************/

Parse Upper Arg a,b
Parse Var a na +4 ta
Parse Var b nb +4 tb
If ta<<tb Then res=-1
Else res=1
Return res

Output (the beginning):

------------------------timestamp:  24 Nov 2013 9:48am-------------------------

      706 records read from file:  LAN.txt
     2204 records read from file:  CAT.txt
      502 relevant languages

          rank:   1               (760 entries)  Tcl
          rank:   2               (724 entries)  Racket
          rank:   3               (708 entries)  Python
          rank:   4               (681 entries)  C

Note: If MC++ and µC++ are the same, they should/could be added together to get 501 languages.

[edit] Oz

Library: OzHttpClient

Using web scraping. Does not filter non-language categories.

declare
[HTTPClient] = {Module.link ['x-ozlib://mesaros/net/HTTPClient.ozf']}
[Regex] = {Module.link ['x-oz://contrib/regex']}
 
fun {GetPage RawUrl}
Client = {New HTTPClient.urlGET init(inPrms(toFile:false toStrm:true) _)}
Url = {VirtualString.toString RawUrl}
OutParams
HttpResponseParams
in
{Client getService(Url ?OutParams ?HttpResponseParams)}
{Client closeAll(true)}
OutParams.sOut
end
 
fun {GetCategories Doc}
{Map {Regex.allMatches "<li><a[^>]+>([^<]+)</a> \\(([0-9]+) member" Doc}
fun {$ Match}
Category = {Regex.group 1 Match Doc}
Count = {String.toInt {ByteString.toString {Regex.group 2 Match Doc}}}
in
Category#Count
end
}
end
 
Url = "http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000"
 
{System.showInfo "Retrieving..."}
Doc = {GetPage Url}
 
{System.showInfo "Parsing..."}
Cs = {GetCategories Doc}
in
for
Cat#Count in {Sort Cs fun {$ _#C1 _#C2} C1 > C2 end}
I in 1..20
do
{System.showInfo I#". "#Count#" - "#Cat}
end
Output:
1. 371 - Tcl
2. 369 - Programming Tasks
3. 338 - Python
4. 324 - Ruby
5. 306 - Haskell
...
17. 225 - Oz
18. 214 - C++
19. 209 - JavaScript
20. 208 - ALGOL 68

[edit] Perl

Sorting only programming languages.

use MediaWiki::API;
my $api = new MediaWiki::API({api_url => 'http://rosettacode.org/mw/api.php'});
 
my @pairs =
sort {$b->[1] <=> $a->[1] or $a->[0] cmp $b->[0]}
map {$_->{title} =~ s/\ACategory://;
[$_->{title}, $_->{categoryinfo}{size} || 0];}
values %{$api->api
({action => 'query',
generator => 'categorymembers',
gcmtitle => 'Category:Programming Languages',
gcmlimit => 'max',
prop => 'categoryinfo'})->{query}{pages}};
 
for (my $n = 1 ; @pairs ; ++$n)
{my ($lang, $tasks) = @{shift @pairs};
printf "%3d. %3d - %s\n", $n, $tasks, $lang;}

[edit] Perl 6

Scraping the languages and categories pages. Perl 6 automatically handles Unicode names correctly.

my $languages =  qx{wget -O - 'http://rosettacode.org/wiki/Category:Programming_Languages'};
my $categories = qx{wget -O - 'http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000'};
 
my @lines = $languages.lines;
shift @lines until @lines[0] ~~ / '<h2>Subcategories</h2>' /;
my \languages = set gather for @lines {
last if / '/bodycontent' /;
take ~$0 if
/ '<li><a href="/wiki/Category:' .*? '" title="Category:' .*? '">' (.*?) '</a></li>' /;
}
 
@lines = $categories.lines;
my @results = sort -*.[0], gather for @lines {
take [+$1, ~$0] if
/ '<li><a href="/wiki/Category:' .*? '" title="Category:' .*? '">'
(.*?) <?{ ~$0 ∈ languages }>
'</a>' .*? '(' (\d+) ' member' /;
}
 
for @results.kv -> $i, @l {
printf "%d:\t%3d - %s\n", $i+1, |@l;
}
Output:

(As of 2014-07-11.) Here we show only the top 10.

1:	833 - Tcl
2:	781 - Racket
3:	770 - Python
4:	730 - Perl 6
5:	725 - J
6:	712 - C
7:	708 - Ruby
8:	698 - D
9:	674 - Go
10:	656 - Perl

[edit] PicoLisp

(load "@lib/http.l")
 
(for (I . X)
(flip
(sort
(make
(client "rosettacode.org" 80
"mw/index.php?title=Special:Categories&limit=5000"
(while (from "<li><a href=\"/wiki/Category:")
(let Cat (till "\"")
(from "(")
(when (format (till " " T))
(link (cons @ (ht:Pack Cat))) ) ) ) ) ) ) )
(prinl (align 3 I) ". " (car X) " - " (cdr X)) )
Output (07apr10):
  1. 390 - Tcl
  2. 389 - Programming_Tasks
  3. 359 - Python
  4. 344 - Ruby
  5. 326 - J
  6. 316 - OCaml
  7. 315 - C
  8. 312 - Haskell
  9. 296 - Perl
 10. 281 - Common_Lisp
...

[edit] PureBasic

Structure Language
count.i
Name.s
EndStructure
 
Dim Row.Language(2000)
 
; Lines has been split to fit RC's 80 char preferences
ignore$ = "Basic language learning Encyclopedia Implementations "
ignore$ + "Language Implementations Language users "
ignore$ + "Maintenance/OmitCategoriesCreated Programming Languages "
ignore$ + "Programming Tasks RCTemplates Solutions by Library Solutions by "
ignore$ + "Programming Language Solutions by Programming Task Unimplemented "
ignore$ + "tasks by language WikiStubs Examples needing attention "
ignore$ + "Impl needed"
 
URL$="http://www.rosettacode.org/w/index.php?"
URL$+"title=Special:Categories&limit=5000"
 
URLDownloadToFile_( #Null, URL$, "special.htm", 0, #Null)
ReadFile(0, "special.htm")
While Not Eof(0)
i + 1
x1$ = ReadString(0)
x2$ = Mid(x1$, FindString(x1$, "member", 1) - 4 , 3)
Row(i)\count = Val(Trim(RemoveString(x2$, "(")))
 
x3$ = Mid(x1$, FindString(x1$, Chr(34) + ">", 1) + 2, 30)
Row(i)\Name = Left(x3$, FindString(x3$, "<", 1) - 1)
If FindString(ignore$, Row(i)\Name, 1) Or Row(i)\Name = ""
Row(i)\count = 0
EndIf
Wend
offset=OffsetOf(Language\count)
SortStructuredArray(Row(), #PB_Sort_Descending, offset, #PB_Sort_Integer)
OpenConsole()
For i = 0 To 20
PrintN( Str(i + 1) + ". " + Str(Row(i)\count) + " - " + Row(i)\Name)
Next
Input()

[edit] Python

Works with: Python version 2.6

This uses MediaWiki's JSON API to query the members of Category:Programming Languages and then scrapes Special:Categories for the number of pages in each language's category.

import urllib, re
 
key1 = lambda x: int(x[1])
 
get1 = urllib.urlopen("http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Languages&cmlimit=500&format=json").read()
get2 = urllib.urlopen("http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000").read()
 
langs = re.findall("\"title\":\"Category:(.+?)\"",get1)
qtdmbr = re.findall("title=\"Category:(.+?)\">.+?</a> \((\d+) members\)",get2)
 
result = [(x,int(y)) for x,y in qtdmbr if x in langs]
 
for n, i in enumerate(sorted(result,key=key1,reverse=True)):
print "%3d. %3d - %s" % (n+1, i[1], i[0])
Output (as of Sep 11, 2010):
 1. 423 - Tcl
 2. 394 - Python
 3. 368 - J
 4. 365 - PicoLisp
 5. 362 - Ruby
 6. 355 - C
 7. 351 - Haskell
 8. 339 - OCaml
 9. 316 - Perl
10. 315 - PureBasic
11. 306 - D
12. 302 - AutoHotkey
13. 300 - Common Lisp
14. 295 - Java
15. 293 - Ada
16. 278 - Oz
17. 260 - C++
18. 260 - C sharp
    . . .

[edit] R

library(RJSONIO)
langUrl <- "http://rosettacode.org/mw/api.php?action=query&format=json&cmtitle=Category:Solutions_by_Programming_Language&list=categorymembers&cmlimit=500"
 
languages <- fromJSON(langUrl)$query$categorymembers
languages <- sapply(languages, function(x) sub("Category:", "", x$title))
 
# fails if there are more than 500 users per language
user <- function (lang) {
userBaseUrl <- "http://rosettacode.org/mw/api.php?action=query&format=json&list=categorymembers&cmlimit=500&cmtitle=Category:"
userUrl <- paste(userBaseUrl, URLencode(paste(lang, " User", sep="")),sep="")
length(fromJSON(userUrl)$query$categorymembers)
}
 
users <- sapply(languages, user)
head(sort(users, decreasing=TRUE),15)
Output (as of March, 13, 2010):
         C        C++       Java     Python JavaScript       Perl UNIX Shell 
        55         55         37         32         27         27         22 
    Pascal      BASIC        PHP        SQL    Haskell        AWK    C sharp 
        20         19         19         18         17         16         16 
      Ruby 
        14 

[edit] Racket

#lang racket
 
(require net/url)
(require json)
 
(define proglangs_url "http://rosettacode.org/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Languages&cmlimit=500&format=json")
(define categories_url "http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000")
 
(define (fetch-json urlstring)
(read-json (get-pure-port (string->url urlstring))))
 
(define programming-languages
(for/set ([h (in-list
(hash-ref (hash-ref (fetch-json proglangs_url) 'query)
'categorymembers))])
(substring (hash-ref h 'title) 9)))
 
(define result '())
(for ([l (in-port read-line (get-pure-port (string->url categories_url)))])
(let ([res (regexp-match #px"title=\"Category:(.+?)\".+\\((\\d+) member" l)])
(when (and res (set-member? programming-languages (cadr res)))
(set! result (cons (cons (cadr res)
(string->number (caddr res)))
result)))))
 
(printf "Place\tCount\tName~n")
(for ([lang (in-list (sort result > #:key cdr))]
[place (in-naturals 1)])
(printf "~a\t~a\t~a~n" place (cdr lang) (car lang)))
 

Output, 2013-5-25:

Place	Count	Name
1	737	Tcl
2	676	Python
3	660	C
4	638	J
5	626	PicoLisp
6	609	Perl 6
7	609	D
8	601	Racket
9	592	Ruby
10	589	Go
...

Recent, occasionally updated output also available at: http://www.timb.net/popular-languages.html

[edit] REXX

(Native) REXX doesn't support web-page reading, so the mentioned Rosetta Code categories and
Rosetta Code Languages were downloaded to local files.

This program reads the Languages file and uses the contents of that file for a validation of
the categories file.   This essentially is a perfect filter for the Rosetta Code categories file.
The   catHeap   variable in the REXX program is just a long string of all the records in the web-file of the
Rosetta Code categories, with a special character (sep) that separates each language entry (name).
The mechanism is to use a (sparse) stemmed array which holds only the names of languages which
(for most REXXes) uses a hashing algorithm to locate the entry   (which is very fast).

Programming note:   (REXX doesn't handle Unicode characters)   some special cases that are translated:

  •   ╬£C++           translated into   µC++   [Greek micro]
  •   ╨£╨Ü-61/52   translated into   MK-61/52   [Cyrillic   МК-61/52])
  •   ??-61/52         translated into   MK-61/52   [Cyrillic   МК-61/52])
  •   D├⌐j├á Vu     translated into   Déjá Vu
  •   D├½j├á Vu     translated into   Déjá Vu
  •   Cach├⌐         translated into   Caché
  •   ??-61/52

(The 3rd entry is most likely caused by the inability to render unsupported glyphs when it was first used to add that language.)
Note that this REXX example properly ranks tied languages.
This version now sorts the tied languages by language name (thanks to Walter Pachl).

[edit] REXX program

/*REXX pgm reads 2 files, shows a ranked list of Rosetta Code languages.*/
sep='█'; L.=0; #.=0; u.=0; catHeap=; old.= /*assign variable defaults. */
parse arg cutoff CinFID LinFID outFID . /*obtain specified options. */
if cutoff==',' | cutoff=='' then cutoff=0 /*assume no cutoff default. */
if CinFID=='' then CinFID = 'RC_POP.CAT' /*Not specified? Use default.*/
if LinFID=='' then LinFID = 'RC_POP.LAN' /* " " " " */
if outFID=='' then outFID = 'RC_POP.OUT' /* " " " " */
call tell center('timestamp: ' date() time('Civil'),79,'═'), 2, 1
call reader 'lang' /*assign to L.ααα */
call reader 'cat' /*append to the catHeap*/
#=0 /*number of categories.*/
do j=1 until catHeap=='' /*process heap of cats.*/
parse var catHeap cat.j (sep) catHeap /*pick off a category. */
parse var cat.j cat.j '<' "(" mems . /*untangle the string. */
cat.j=space(cat.j); _=cat.j; upper _ /*remove excess blanks.*/
if _=='' | \L._ then iterate /*blank or ¬ a language*/
if \datatype(mems,'W') then iterate /*"members" ¬ numeric.*/
#.0=#.0+mems /*bump #members found. */
if u._\==0 then do /*[↓] handle duplicates*/
do f=1 for # until _==@u.f
end /*f*/
#.f=#.f+mems; iterate j
end /* [↑] languages that are in different cases.*/
u._=u._+1
#=#+1; #.#=#.#+mems; @.#=cat.j; @u.#=_ /*bump counter, assign.*/
end /*j=1 until ···*/
!.= /*array holds indication of TIED.*/
call tell right(comma(#) ,9) '(total) number of languages detected.'
call tell right(comma(#.0),9) '(total) number of entries detected.', , 1
call eSort #,0 /*sort the languages along with #*/
r=0 /*add true rank (tR) ──► entries.*/
tied=; do j=# by -1 for #; r=r+1; tR=r;  !tR.j=r; jp=j+1; jm=j-1
if tied=='' then pR=r; tied= /*handle if the rank is untied.*/
if #.j==#.jp | #.j==#.jm then do; !.j='[tied]'; tied=!.j; end
if #.j==#.jp then do; tR=pR; !tR.j=pR; end
else pR=r
end /*j=# by ···*/
 
call eSort #,1 /*sort the languages along with @*/
listed=0; w=length(#); rank=0 /* [↓] show by ascending rank. */
 
do t=# by -1 for # while #.t>=cutoff; listed=listed+1; rank=rank+1
call tell right('rank:' right(!tR.t,w),20-1) right(!.t,7),
right('('#.t left("entr"s(#.t,'ies',"y")')', 9),20) @.t
end /*t=# by ···*/ /* [↑] s(···) pluralizes a word*/
 
call tell left('',27) '☼ end-of-list. ☼', 1, 2
if cutoff==0 then exit /*was there a CUTOFF specified?*/
call tell ' Listing stopped due to a cutoff of' comma(cutoff)".", 1
call tell listed 'language's(listed) "found with number of entries ≥" cutoff,1,1
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────ESORT subroutine────────────────────*/
eSort: procedure expose #. @. !tr.; arg N,p2; h=N /*sort by # entries*/
do while h>1; h=h%2 /*sort kinda halved*/
do i=1 for N-h; j=i; k=h+i /*sort this part. */
if p2 then do while !tR.k==!tR.j & @.k>@.j /*using hard swap ↓*/
@=@.j; #=!tR.j; @.j=@.k;  !tR.j=!tR.k; @.k=@;  !tR.k=#
if h>=j then leave; j=j-h; k=k-h
end /*while !tR·k==···*/
else do while #.k<#.j /*using hard swap ↓*/
@=@.j; #=#.j; @.j=@.k; #.j=#.k; @.k=@; #.k=#
if h>=j then leave; j=j-h; k=k-h
end /*while #.k<#.j*/
end /*i*/
end /*while h>1*/
return
/*──────────────────────────────────READER subroutine───────────────────*/
reader: arg which 2; ig_ast=1 /*ARG uppers WHICH, gets 1st char*/
if which=='L' then inFID=Linfid /*use this fileID for languages. */
if which=='C' then inFID=Cinfid /* " " " " categories.*/
old.1='╬£C++'  ; new.1= "µC++" /*Unicode ╬£C++ ──►ASCII-8: µC++ */
old.2='UC++'  ; new.2= "µC++" /*old UC++ ──►ASCII-8: µC++ */
old.3='╨£╨Ü-'  ; new.3= "MK-" /*Unicode ╨£╨Ü- ──►ASCII-8: MK- */
old.4='D├⌐j├á'  ; new.4= 'Déjá' /*Unicode ├⌐j├á ──►ASCII-8: Déjá */
old.5='D├⌐j├á'  ; new.4= 'Dëjá' /*Unicode ├½j├á ──►ASCII-8: Dëjá */
old.6='Cach├⌐'  ; new.5= 'Caché' /*Unicode ach├⌐ ──►ASCII-8: Caché*/
old.7='??-61/52' ; new.6= 'MK-61/52' /*somewhere a mistranslated: MK- */
 
do recs=0 while lines(inFID)\==0 /*read a file, 1 line at a time.*/
$=translate(linein(inFID),,'9'x) /*handle any stray tab characters*/
$$=space($); if $$=='' then iterate /*ignore all blank lines. */
do v=1 while old.v\=='' /*translate Unicode variations. */
if pos(old.v, $$) \==0 then $$=changestr(old.v, $$, new.v)
end /*v*/ /* [↑] handle different spellings*/
if ig_ast then do; ig_ast=pos(' * ',$)==0; if ig_ast then iterate; end
$u=$$; upper $u /*get an uppercase version. */
if pos('RETRIEVED FROM',$u)\==0 then leave /*a pseudo End-Of-Data.*/
if which=='L' then do
if left($$,1)\=='*' then iterate /*legimate?*/
parse upper var $$ '*' $$ "<"; $$=space($$)
L.$$=1 /*languages are stored uppercase.*/
iterate /*iterates the DO WHILE LINES(···*/
end /*(above) pick off language name.*/
if left($$,1)=='*' then $$=sep || space(substr($$,2))
catHeap=catHeap $$ /*append to the (CATegory) heap. */
end /*while lines···*/
 
call tell right(comma(recs),9) 'records read from file: ' inFID
return
/*──────────────────────────────────TELL subroutine─────────────────────*/
tell: do '0'arg(2); call lineout outFID,' '  ; say  ; end
call lineout outFID,arg(1)  ; say arg(1)
do '0'arg(3); call lineout outFID,' '  ; say  ; end
return /*show before blanks lines (if any), MSG, show after blank lines*/
/*──────────────────────────────────one─liner subroutines───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────*/
comma: procedure; parse arg _,c,p,t; c=pickBlank(c,","); o=p(p 3); p=abs(o); t=p(t 999999999); if \isInt(p) | \isInt(t) | p==0 | arg()>4 then return _; n=_'.9'; #=123456789; k=0; return comma_()
comma_: if o<0 then do; b=verify(_,' '); if b==0 then return _; e=length(_)-verify(reverse(_),' ')+1; end; else do; b=verify(n,#,"M"); e=verify(n,#'0',,verify(n,#"0.",'M'))-p-1; end; do j=e to b by -p while k<t; _=insert(c,_,j); k=k+1;end;return _
isInt: return datatype(arg(1),'W')
p: return word(arg(1),1)
pickBlank: procedure; parse arg x,y; arg xu; if xu=='BLANK' then return ' '; return p(x y)
s: if arg(1)==1 then return arg(3); return word(arg(2) 's',1) /*plural*/

Some older REXXes don't have a   changestr   BIF, so one is included here ───►   CHANGESTR.REX.

[edit] all ranked 535 languages

The output for this REXX (RC_POP.REX) program is included here ──►   RC_POP.OUT.

(See the talk page about some programming languages using different cases (lower/upper/mixed) for the language names).

[Note: the timestamp reflects the local time which is USA   CST or CDT   (Central Standard Time   or   Central Daylight Time).

[edit] Ruby

Works with: Ruby version 1.8.7

Now that there are more than 500 categories, the URL given in the task description is insufficient. I use the RC API to grab the categories, and then count the members of each category.

Uses the RosettaCode module from Count programming examples#Ruby

require 'rosettacode'
 
langs = []
RosettaCode.category_members("Programming Languages") {|lang| langs << lang}
 
# API has trouble with long titles= values.
# To prevent skipping languages, use short slices of 20 titles.
langcount = {}
langs.each_slice(20) do |sublist|
url = RosettaCode.get_api_url({
"action" => "query",
"prop" => "categoryinfo",
"format" => "xml",
"titles" => sublist.join("|"),
})
 
doc = REXML::Document.new open(url)
REXML::XPath.each(doc, "//page") do |page|
lang = page.attribute("title").value
info = REXML::XPath.first(page, "categoryinfo")
langcount[lang] = info.nil? ? 0 : info.attribute("pages").value.to_i
end
end
 
puts Time.now
puts "There are #{langcount.length} languages"
puts "the top 25:"
langcount.sort_by {|key,val| val}.reverse[0,25].each_with_index do |(lang, count), i|
puts "#{i+1}. #{count} - #{lang.sub(/Category:/, '')}"
end
Results:
2010-07-08 14:52:46 -0500
There are 306 languages
the top 25:
1. 399 - Tcl
2. 370 - Python
3. 352 - Ruby
4. 338 - J
5. 337 - C
6. 333 - PicoLisp
7. 322 - OCaml
8. 322 - Haskell
9. 299 - Perl
10. 299 - AutoHotkey
11. 288 - Common Lisp
12. 280 - Java
13. 275 - Ada
14. 270 - D
15. 267 - Oz
16. 253 - R
17. 252 - PureBasic
18. 245 - E
19. 243 - C++
20. 241 - C sharp
21. 239 - ALGOL 68
22. 236 - JavaScript
23. 221 - Forth
24. 207 - Clojure
25. 201 - Fortran

[edit] Run BASIC

sqliteconnect #mem, ":memory:"  ' make memory DB
#mem execute("CREATE TABLE stats(lang,cnt)")
a$ = httpGet$("http://rosettacode.org/wiki/Category:Programming_Languages")
aa$ = httpGet$("http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000")
i = instr(a$,"/wiki/Category:")
while i > 0 and lang$ <> "Languages"
j = instr(a$,"""",i)
lang$ = mid$(a$,i+15,j - i-15)
ii = instr(aa$,"Category:";lang$;"""")
jj = instr(aa$,"(",ii)
kk = instr(aa$," ",jj+1)
if ii = 0 then cnt = 0 else cnt = val(mid$(aa$,jj+1,kk-jj))
k = instr(lang$,"%") ' convert hex values to characters
while k > 0
lang$ = left$(lang$,k-1) + chr$(hexdec(mid$(lang$,k+1,2))) + mid$(lang$,k+3)
k = instr(lang$,"%")
wend
#mem execute("insert into stats values ('";lang$;"',";cnt;")")
i = instr(a$,"/wiki/Category:",i+10)
wend
html "<table border=2>"
#mem execute("SELECT * FROM stats ORDER BY cnt desc") ' order list by count descending
WHILE #mem hasanswer()
#row = #mem #nextrow()
rank = rank + 1
html "<TR><TD align=right>";rank;"</td><td>";#row lang$();"</td><td align=right>";#row cnt();"</td></tr>"
WEND
html "</table>"
1Tcl687
2Python650
3C638
4PicoLisp626
5J619
6Go587
7Ruby581
8D571
9Ada559
10Mathematica551
11Perl528
12Perl_6528
13Haskell526
14BBC_BASIC513
15REXX491
16Java488
17OCaml477
18PureBasic469
19Unicon462
20AutoHotkey430
21Icon429
22Common_Lisp424
23C_sharp416
24C++400
25JavaScript359
26Scala339
27PARI/GP338
28Clojure335
29R322
n......

[edit] Scala

[edit] Parallel internet querying

Entry point @ object GhettoParserPar

import akka.actor.{ Actor, ActorSystem, Props }
import scala.collection.immutable.TreeSet
import scala.xml.XML
 
// Reports a list with all languages recorded in the Wiki
 
private object Acquisition {
val (endPoint, prefix) = ("http://rosettacode.org/mw/api.php", "Category:")
val (maxPlaces, correction) = (50, 2)
 
def convertPathArgsToURL(endPoint: String, pathArgs: Map[String, String]) = {
pathArgs.map(argPair => argPair._1 + "=" + argPair._2)
.mkString(endPoint + (if (pathArgs.nonEmpty) "?" else ""), "&", "")
}
 
/* The categories include a page for the language and a count of the pages
* linked therein, this count is the data we need to scrape.
* Reports a list with language, count pair recorded in the Wiki
* All strings starts with the prefixes "Category:"
*/

def mineCatos = {
val endPoint = "http://rosettacode.org/mw/index.php"
Concurrent.logInfo("Acquisition of categories started.")
val categories =
(XML.load(convertPathArgsToURL(endPoint,
Map("title" -> "Special:Categories", "limit" -> "5000"))) \\ "ul" \ "li")
.withFilter(p => (p \ "a" \ "@title").text.startsWith(prefix))
.map // Create a tuple pair, eg. ("Category:Erlang", 195)
{ cat =>
((cat \ "a" \ "@title").text, // Takes the sibling of "a" and extracts the number
("[0-9]+".r.findFirstIn((cat.child.drop(1)).text).getOrElse("0").toInt))
}
Concurrent.logInfo(s"Got ${categories.size} categories..")
categories
}
 
// The languages
// All strings starts with the prefixes "Category:"
def mineLangs = {
Concurrent.logInfo("Acquisition of languages started...")
val languages = (
TreeSet[String]() ++ (XML.load(convertPathArgsToURL(endPoint, Map("action" -> "query",
"list" -> "categorymembers",
"cmtitle" -> (prefix + "Programming_Languages"),
"cmlimit" -> "505", "format" -> "xml"))) \\
"categorymembers" \ "cm").map(c => (c \ "@title").text))
Concurrent.logInfo(s"Got ${languages.size} languages..")
languages
}
 
def joinRosettaCodeWithLanguage(catos: Seq[(String, Int)],
langs: TreeSet[String]) =
for {
cato <- catos //Clean up the tuple pairs, eg ("Category:Erlang", 195) becomes ("Erlang", 192)
if langs.exists(_ == cato._1)
} yield (cato._1.drop(prefix.size), cato._2 - correction max 0) // Correct count
 
def printScrape(languages: TreeSet[String], category: Seq[(String, Int)]) {
 
val join = joinRosettaCodeWithLanguage(category, languages)
val total = join.foldLeft(0)(_ + _._2)
 
Concurrent.logInfo("Data processed")
 
println(f"\nTop$maxPlaces%3d Rosetta Code Languages by Popularity as ${new java.util.Date}%tF:\n")
(join.groupBy(_._2).toSeq.sortBy(-_._1).take(maxPlaces) :+ (0, Seq(("...", 0))))
.zipWithIndex // Group the ex aequo
.foreach {
case ((score, languages), rank) =>
println(f"${rank + 1}%2d. $score%3d - ${languages.map(_._1).mkString(", ")}")
}
 
println(s"\nCross section yields ${join.size} languages, total of $total solutions")
println(s"Resulting average is ${total / join.size} solutions per language")
}
 
def printScrape(): Unit = printScrape(mineLangs, mineCatos)
} // object Acquisition
 
private object Concurrent extends AppCommons {
var (category: Option[Seq[(String, Int)]], language: Option[TreeSet[String]]) = (None, None)
 
class Worker extends Actor {
def receive = {
case 'Catalogue => sender ! Acquisition.mineCatos
case 'Language => sender ! Acquisition.mineLangs
}
}
 
class Listener extends Actor { // Create and signal the worker actors
context.actorOf(Props[Worker], "worker0") ! 'Catalogue
context.actorOf(Props[Worker], "worker1") ! 'Language
 
def printCompleteScape() =
if (category.isDefined && language.isDefined) {
Acquisition.printScrape(language.get, category.get)
context.system.shutdown
appEnd()
}
 
def receive = {
case content: TreeSet[String] => {
language = Some(content)
printCompleteScape()
}
case content: Seq[(String, Int)] => {
category = Some(content)
printCompleteScape()
}
case whatever => logInfo(whatever.toString)
} // def receive
} // class Listener
} // object Concurrent
 
trait AppCommons {
val execStart: Long = System.currentTimeMillis()
System.setProperty("http.agent", "*")
 
def logInfo(info: String) {
println(f"[Info][${System.currentTimeMillis() - execStart}%5d ms]" + info)
}
 
def appEnd() { logInfo("Run succesfully completed") }
}
 
// Main entry for sequential version (slower)
object GhettoParserSeq extends App with AppCommons {
Concurrent.logInfo("Sequential version started")
Acquisition.printScrape()
appEnd()
}
 
// Entry for parallel version (faster)
object GhettoParserPar extends App {
Concurrent.logInfo("Parallel version started")
ActorSystem("Main").actorOf(Props[Concurrent.Listener])
}

[edit] Sequential internet querying

The same code above but as entry point object GhettoParserSeq

Output for both solutions:
but parallel run chosen. Notice the synchronous start time.
[Info][   81 ms]Parallel version started
[Info][ 1316 ms]Acquisition of languages started...
[Info][ 1316 ms]Acquisition of categories started.
[Info][ 2395 ms]Got 500 languages..
[Info][12450 ms]Got 2187 categories..
[Info][12587 ms]Data processed

Top 50 Rosetta Code Languages by Popularity as 2013-11-09:

 1. 758 - Tcl
 2. 722 - Racket
 3. 706 - Python
 4. 679 - C
 5. 641 - J
 6. 634 - Perl 6
 7. 630 - D
 8. 627 - PicoLisp
 9. 619 - Ruby
10. 608 - Go
11. 582 - Perl
12. 572 - Ada
13. 564 - Mathematica
14. 555 - Haskell
15. 547 - REXX
16. 522 - Java
17. 519 - BBC BASIC
18. 510 - Unicon
19. 486 - OCaml
20. 469 - C++, Icon
21. 468 - PureBasic
22. 443 - Common Lisp
23. 434 - C sharp
24. 428 - AutoHotkey
25. 411 - Erlang
26. 386 - Scala
27. 378 - JavaScript
28. 368 - Clojure
29. 356 - PARI/GP
30. 335 - R
31. 333 - Lua
32. 328 - Seed7
33. 326 - ALGOL 68, PHP
34. 324 - F Sharp
35. 323 - Forth
36. 319 - Fortran
37. 313 - PL/I
38. 310 - Pascal
39. 308 - Groovy
40. 297 - MATLAB
41. 291 - Liberty BASIC
42. 284 - Octave
43. 280 - AWK
44. 276 - Oz
45. 272 - Factor
46. 270 - E
47. 265 - NetRexx
48. 263 - Run BASIC
49. 255 - Scheme
50. 225 - Delphi
51.   0 - ...

Cross section yields 483 languages, total of 33603 solutions
Resulting average is 69 solutions per language
[Info][12647 ms]Run succesfully completed

[edit] Seed7

$ include "seed7_05.s7i";
include "gethttp.s7i";
include "scanstri.s7i";
 
const type: popularityHash is hash [string] integer;
const type: rankingHash is hash [integer] array string;
 
const func array string: getLangs (in string: buffer) is func
result
var array string: langs is 0 times "";
local
var integer: pos is 0;
begin
pos := pos(buffer, "Category:");
while pos <> 0 do
pos +:= 9;
langs &:= buffer[pos .. pred(pos(buffer, '"', pos))];
pos := pos(buffer, "Category:", pos);
end while;
end func;
 
const proc: main is func
local
var string: categories is "";
var popularityHash: popularity is popularityHash.value;
var rankingHash: ranking is rankingHash.value;
var array integer: numList is 0 times 0;
var string: lang is "";
var integer: pos is 0;
var string: numStri is "";
var integer: listIdx is 0;
var integer: index is 0;
var integer: place is 1;
begin
categories := getHttp("www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000");
for lang range getLangs(getHttp("rosettacode.org/mw/api.php?action=query&list=categorymembers&\
\cmtitle=Category:Programming_Languages&cmlimit=500&format=json")) do
pos := pos(categories, "title=\"Category:" & lang);
if pos <> 0 then
pos := pos(categories, "</a>", succ(pos));
if pos <> 0 then
pos := pos(categories, "(", succ(pos));
if pos <> 0 then
numStri := categories[succ(pos) len 10];
popularity @:= [lang] integer parse getDigits(numStri);
end if;
end if;
end if;
end for;
ranking := flip(popularity);
numList := sort(keys(ranking));
for listIdx range maxIdx(numList) downto minIdx(numList) do
for key index range ranking[numList[listIdx]] do
writeln(place lpad 3 <& ". " <& numList[listIdx] <& " - " <& ranking[numList[listIdx]][index]);
end for;
place +:= length(ranking[numList[listIdx]]);
end for;
end func;

List of languages as of 2014-01-15:

  1. 772 - Tcl
  2. 733 - Racket
  3. 718 - Python
  4. 685 - C
  5. 657 - Perl 6
  6. 654 - J
  7. 645 - D
  8. 643 - Ruby
  9. 636 - PicoLisp
 10. 624 - Go
 11. 610 - Perl
 12. 579 - REXX
 13. 578 - Ada
 14. 567 - Mathematica
 14. 567 - Haskell
 16. 532 - Unicon
 17. 526 - Java
 18. 523 - BBC BASIC
 19. 489 - OCaml
 20. 487 - Icon
 21. 477 - C++
 22. 470 - PureBasic
 23. 448 - Common Lisp
 24. 439 - Erlang
 24. 439 - C sharp
 26. 437 - AutoHotkey
 27. 406 - Scala
 28. 382 - JavaScript
 29. 375 - Clojure
 30. 356 - Seed7
...

[edit] Tcl

[edit] By web scraping

package require Tcl 8.5
package require http
 
set response [http::geturl http://rosettacode.org/mw/index.php?title=Special:Categories&limit=1000]
 
array set ignore {
"Basic language learning" 1
"Encyclopedia" 1
"Implementations" 1
"Language Implementations" 1
"Language users" 1
"Maintenance/OmitCategoriesCreated" 1
"Programming Languages" 1
"Programming Tasks" 1
"RCTemplates" 1
"Solutions by Library" 1
"Solutions by Programming Language" 1
"Solutions by Programming Task" 1
"Unimplemented tasks by language" 1
"WikiStubs" 1
"Examples needing attention" 1
"Impl needed" 1
}
 
foreach line [split [http::data $response] \n] {
if {[regexp {>([^<]+)</a> \((\d+) member} $line -> lang num]} {
if {![info exists ignore($lang)]} {
lappend langs [list $num $lang]
}
}
}
 
foreach entry [lsort -integer -index 0 -decreasing $langs] {
lassign $entry num lang
puts [format "%d. %d - %s" [incr i] $num $lang]
}
Output on 31 July 2009 (top 15 entries only):
1. 329 - Tcl
2. 292 - Python
3. 270 - Ruby
4. 250 - C
5. 247 - Ada
6. 238 - Perl
7. 223 - E
8. 221 - Java
9. 220 - AutoHotkey
10. 219 - OCaml
11. 210 - Haskell
12. 197 - ALGOL 68
13. 188 - D
14. 179 - C++
15. 175 - Forth
……

[edit] By using the API

Translation of: Ruby
Works with: Tcl version 8.5
Library: tDOM
package require Tcl 8.5
package require http
package require tdom
 
namespace eval rc {
### Utility function that handles the low-level querying ###
proc rcq {q xp vn b} {
upvar 1 $vn v
dict set q action "query"
# Loop to pick up all results out of a category query
while 1 {
set url "http://rosettacode.org/mw/api.php?[http::formatQuery {*}$q]"
puts -nonewline stderr . ;# Indicate query progress...
set token [http::geturl $url]
set doc [dom parse [http::data $token]]
http::cleanup $token
 
# Spoon out the DOM nodes that the caller wanted
foreach v [$doc selectNodes $xp] {
uplevel 1 $b
}
 
# See if we want to go round the loop again
set next [$doc selectNodes "//query-continue/categorymembers"]
if {![llength $next]} break
dict set q cmcontinue [[lindex $next 0] getAttribute "cmcontinue"]
}
}
 
### API function: Iterate over the members of a category ###
proc members {page varName script} {
upvar 1 $varName var
set query [dict create cmtitle "Category:$page" {*}{
list "categorymembers"
format "xml"
cmlimit "500"
}]
rcq $query "//cm" item {
# Tell the caller's script about the item
set var [$item getAttribute "title"]
uplevel 1 $script
}
}
 
### API function: Count the members of a list of categories ###
proc count {cats catVar countVar script} {
upvar 1 $catVar cat $countVar count
set query [dict create prop "categoryinfo" format "xml"]
for {set n 0} {$n<[llength $cats]} {incr n 40} {
dict set query titles [join [lrange $cats $n $n+39] |]
rcq $query "//page" item {
# Get title and count
set cat [$item getAttribute "title"]
set info [$item getElementsByTagName "categoryinfo"]
if {[llength $info]} {
set count [[lindex $info 0] getAttribute "pages"]
} else {
set count 0
}
# Let the caller's script figure out what to do with them
uplevel 1 $script
}
}
}
 
### Assemble the bits into a whole API ###
namespace export members count
namespace ensemble create
}
 
# Get the list of programming languages
rc members "Solutions by Programming Language" lang {
lappend langs $lang
}
# Get the count of solutions for each, stripping "Category:" prefix
rc count $langs l c {
lappend count [list [regsub {^Category:} $l {}] $c]
}
puts stderr "" ;# Because of the progress dots...
# Print the output
puts "There are [llength $count] languages"
puts "Here are the top fifteen:"
set count [lsort -index 1 -integer -decreasing $count]
foreach item [lrange $count 0 14] {
puts [format "%1\$3d. %3\$3d - %2\$s" [incr n] {*}$item]
}

[edit] TUSCRIPT

$$ MODE TUSCRIPT
remotedata = REQUEST ("http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000")
allmembers=allnames=""
COMPILE
LOOP d=remotedata
IF (d.sw."<li>") THEN
name=EXTRACT (d,":<<a<><%>>:"|,":<</a>>:")
IF (name.eq."Language users") CYCLE
IF (name.sw."Unimplemented tasks") CYCLE
IF (name.sw."Programming") CYCLE
IF (name.sw."Solutions") CYCLE
IF (name.sw."Garbage") CYCLE
IF (name.sw."Typing") CYCLE
IF (name.sw."BASIC LANG") CYCLE
IF (name.ew."USER") CYCLE
IF (name.ew."tasks") CYCLE
IF (name.ew."attention") CYCLE
IF (name.ew."related") CYCLE
IF (name.ct."*omit*") CYCLE
IF (name.ct.":*Categor*:") CYCLE
IF (name.ct.":WikiSTUBS:") CYCLE
IF (name.ct.":Impl needed:") CYCLE
IF (name.ct.":Implementations:") CYCLE
IF (name.ct.":':") name = EXCHANGE (name,":'::")
members = STRINGS (d,":><1<>>/><<> member:")
IF (members!="") THEN
allmembers=APPEND (allmembers,members)
allnames =APPEND (allnames,name)
ENDIF
ENDIF
ENDLOOP
index = DIGIT_INDEX (allmembers)
index = REVERSE (index)
allmembers = INDEX_SORT (allmembers,index)
allnames = INDEX_SORT (allnames, index)
ERROR/STOP CREATE ("list",SEQ-E,-std-)
time=time(),balt=nalt=""
FILE "list" = time
LOOP n, a=allnames,b=allmembers
IF (b==balt) THEN
nr=nalt
ELSE
nalt=nr=n
ENDIF
content=concat (nr,". ",a," --- ",b)
FILE "list" = CONTENT
balt=b
ENDLOOP
ENDCOMPILE
Output:
2011-01-24 14:05:27
1. Tcl --- 472 member
2. PicoLisp --- 441 member
3. Python --- 432 member
4. J --- 414 member
5. C --- 394 member
6. Ruby --- 385 member
7. PureBasic --- 371 member
8. Haskell --- 369 member
9. Ada --- 364 member
10. OCaml --- 352 member
11. Perl --- 339 member
11. D --- 339 member
13. Java --- 325 member
14. AutoHotkey --- 308 member
15. Common Lisp --- 305 membe
16. C sharp --- 301 member
17. C++ --- 285 member
18. Oz --- 278 member
19. Clojure --- 272 member
20. R --- 266 member
21. ALGOL 68 --- 262 member
22. Perl 6 --- 258 member
23. JavaScript --- 257 member
24. E --- 254 member
25. REXX --- 253 member
26. Fortran --- 251 member
27. Forth --- 248 member
28. Lua --- 238 member
29. PHP --- 215 member
30. Unicon --- 211 member
31. Icon --- 210 member
32. Factor --- 207 member
33. Scala --- 197 member
34. PL/I --- 193 member
34. Go --- 193 member
36. Scheme --- 186 member 

[edit] UnixPipes

Library: curl
curl 'http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000' |
sed -n -e 's|^<li><a href="/wiki/Category:\([^"]*\).* (\([0-9][0-9]*\) members*)<.*|\2 \1|p' |
sort -rn

[edit] zkl

host:="rosettacode.org"; port:=80; 
dir:="/mw/index.php?title=Special:Categories&limit=5000";
get:="GET %s HTTP/1.0\r\nHost: %s:%s\r\n\r\n".fmt(dir,host,port);
server:=Network.TCPClientSocket.connectTo(host,port);
server.write(get); // send request to web serer
data:=server.read(True); // read data from web server
data.println(); // size of response
 
data=data.filter(fcn(s){(not s.find("Omit")) and s.find("members") });
data.println(); // size after a quick prune
 
re:=RegExp(0'|.+title="Category:([^"]+).+\((\d+) members|);
r:=data.pump(List,'wrap(s){ if(not re.search(s)) return(Void.Skip);
m:=re.matched; T(m[1],m[2].toInt());
}); //-->( (name,#members) ...)
r.len().println(); // number of entries
r.sort(fcn(a,b){a[1]>b[1]})[0,20] // sort, gimmie 20 and print
.pump(Console.println,fcn([(nm,n)],ref){
ref.inc(); "%3d w/%4d: %s".fmt(ref.value,n,nm) }.fp1(Ref(0)));
Output:
Data(322,865)
Data(149,815)
1263
  1 w/ 784: Tcl
  2 w/ 749: Racket
  3 w/ 731: Python
  4 w/ 709: Programming Tasks
  5 w/ 702: C
  6 w/ 677: Perl 6
  7 w/ 669: J
  8 w/ 664: D
  9 w/ 658: Ruby
 10 w/ 636: PicoLisp
 11 w/ 629: Go
 12 w/ 624: Perl
 13 w/ 599: REXX
 14 w/ 583: Ada
 15 w/ 574: Haskell
 16 w/ 567: Examples needing attention
 17 w/ 567: Mathematica
 18 w/ 548: AutoHotkey
 19 w/ 547: WikiStubs
 20 w/ 537: Unicon

The optional part: Also read the programming languages from http://rosettacode.org/wiki/Category:Programming_Languages and use those to filter the data from http://rosettacode.org/mw/index.php?title=Special:Categories.

Here the fun part is the "optional" data is read in a thread so we have two web queries occurring at the same time. When the data is referenced, it forces the thread to complete but is very likely that the thread will finished by that time.

const HOST="rosettacode.org", PORT=80;
 
cats:=fcn{ // read language names into a Dictionary in a thread
dir:="/wiki/Category:Programming_Languages";
get:="GET %s HTTP/1.0\r\nHost: %s:%s\r\n\r\n".fmt(dir,HOST,PORT);
server:=Network.TCPClientSocket.connectTo(HOST,PORT);
server.write(get); // send request to web serer
cats:=server.read(True); // read data from web server
 
cats.del(0,cats.find("</head>"));
cats=cats.filter("find",0'|title="Category:|);
re:=RegExp(0'|.+title="Category:([^"]+)|);
cats.pump(Void,fcn(s,re,d){ if(not re.search(s)) return(Void.Skip);
m:=re.matched; d.add(m[1],True);}.fp1(re,D()));
// the result of the pump is a Dictionary and
// is the function return value, ie the future value
}.future(); // doesn't need to finish until cats is referenced, way below
 
dir:="/mw/index.php?title=Special:Categories&limit=5000";
get:="GET %s HTTP/1.0\r\nHost: %s:%s\r\n\r\n".fmt(dir,HOST,PORT);
server:=Network.TCPClientSocket.connectTo(HOST,PORT);
server.write(get); // send request to web serer
data:=server.read(True); // read data from web server
 
data.println(); // size of response
data = data.filter(fcn(s){(not s.find("Omit")) and s.find("members") });
data.println(); // size after a quick prune
 
re:=RegExp(0'|.+title="Category:([^"]+).+\((\d+) members|);
r:=data.pump(List,fcn(s,re,cats){ if(not re.search(s)) return(Void.Skip);
m:=re.matched; if (not cats.find(m[1])) return(Void.Skip);
T(m[1],m[2].toInt());
}.fp1(re,cats)); //-->( (name,#members) ...)
r.len().println();
 
println("Most popular Rosetta Code languages as of ",Time.Date.prettyDay());
r.sort(fcn(a,b){a[1]>b[1]})[0,20] // sort, gimmie 20 and print
.pump(Console.println,fcn([(nm,n)],ref){
ref.inc(); "%3d w/%4d: %s".fmt(ref.value,n,nm) }.fp1(Ref(0)));
Output:
Data(322,865)
Data(149,815)
493
Most popular Rosetta Code languages as of Wednesday, the 12th of March 2014
  1 w/ 784: Tcl
  2 w/ 749: Racket
  3 w/ 732: Python
  4 w/ 702: C
  5 w/ 677: Perl 6
  6 w/ 669: J
  7 w/ 664: D
  8 w/ 658: Ruby
  9 w/ 636: PicoLisp
 10 w/ 630: Go
 11 w/ 624: Perl
 12 w/ 599: REXX
 13 w/ 583: Ada
 14 w/ 574: Haskell
 15 w/ 567: Mathematica
 16 w/ 548: AutoHotkey
 17 w/ 537: Unicon
 18 w/ 531: Java
 19 w/ 525: BBC BASIC
 20 w/ 491: Icon
Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox