Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,7 @@
---
category:
- Networking and Web Interaction
- Sorting
- Rosetta Code related
from: http://rosettacode.org/wiki/Rosetta_Code/Rank_languages_by_popularity
note: Text processing

View file

@ -0,0 +1,27 @@
;Task:
Sort the most popular computer programming languages based in number of members in Rosetta Code categories.
Sample output on 02 August 2022 at 09:50 +02
<pre>Rank: 1 (1,565 entries) Phix
Rank: 2 (1,558 entries) Wren
Rank: 3 (1,531 entries) Julia
Rank: 4 (1,507 entries) Raku
Rank: 5 (1,500 entries) Go
Rank: 6 (1,466 entries) Perl
Rank: 7 (1,409 entries) Python
Rank: 8 (1,402 entries) Nim
Rank: 9 (1,254 entries) J
Rank: 10 (1,211 entries) C
...</pre>
;Notes:
* &nbsp; Each language typically demonstrates one or two methods of accessing the data:
:::* &nbsp; with web scraping &nbsp; (via http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000)
:::* &nbsp; with the API method &nbsp; (examples below for [[Rosetta Code/Rank languages by popularity#AWK|Awk]], [[Rosetta Code/Rank languages by popularity#Perl|Perl]], [[Rosetta Code/Rank languages by popularity#Ruby|Ruby]], [[Rosetta Code/Rank languages by popularity#Tcl|Tcl]], etc).
* &nbsp; The scraping and API solutions can be separate subsections, see the [[Rosetta Code/Rank languages by popularity#Tcl|Tcl example]].
* &nbsp; Filtering wrong results is optional. &nbsp; You can check against [[Special:MostLinkedCategories]] (if using web scraping)
::If you use the API, and do elect to filter, you may check your results against [[Rosetta_Code/Rank_languages_by_popularity/Full_list|this complete, accurate, sortable, wikitable listing]] of all '''{{PAGESINCAT:Programming Languages}}''' [[:Category:Programming Languages|programming languages]], updated periodically, ''typically weekly''.
* &nbsp; A complete ranked listing of all &nbsp; '''813''' &nbsp; languages (from the REXX example) is included here &nbsp; ──► &nbsp; [[RC_POP.OUT|output from the REXX program]].
<br><br>

View file

@ -0,0 +1,124 @@
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

View file

@ -0,0 +1,157 @@
CHAR line feed = REPR 10, carriage return = REPR 13;
STRING crlf = carriage return + line feed;
STRING domain = "rosettacode.org",
page = "/mw/api.php?format=xml&action=query&generator=categorymembers&gcmtitle=Category:Programming%20Languages&gcmlimit=500&prop=categoryinfo";
# concatenate tuples #
OP + = ([]STRING a, b) []STRING:
BEGIN
[⌈a + ⌈b] STRING c;
c[:⌈a] := a;
c[⌈a+1:] := b;
c
END;
# count occurrances of string in string #
PROC count = (STRING sub, str) INT :
BEGIN
INT count := 0;
IF UPB str ≥ UPB sub AND UPB str ≥ 1 THEN
INT p := 1; INT p0;
WHILE p + UPB sub - 1 <= UPB str ANDF (p0 := p; string in string (sub, p, str[p0:])) DO
count +:= 1;
p +:= p0 + UPB sub - 1
OD
FI;
count
END;
# split string into tuple #
PROC split = (STRING str, sep) FLEX[]STRING :
BEGIN
INT seplen = UPB sep, strlen = UPB str;
INT cnt := 0, start := 1;
INT p;
[count (sep, str) + 1] STRING list;
WHILE start ≤ strlen - (seplen - 1)
ANDF string in string (sep, p, str[start:]) DO
p +:= start - 1;
list[cnt +:= 1] := str[start:p-1];
start := p + seplen
OD;
IF cnt = 0 THEN list[cnt +:= 1] := str
ELIF start ≤ strlen THEN list[cnt +:= 1] := str[start:]
ELIF start = strlen + 1 AND seplen ≥ 1 THEN list[cnt +:= 1] := ""
FI;
list
END;
# reverse strings in a TUPLE #
OP REVERSE = ([]STRING org) []STRING :
BEGIN
[UPB org]STRING new;
FOR i TO UPB org DO
new[UPB org - (i - 1)] := org[i]
OD;
new
END;
# convert unsigned number to INT #
OP TOINT = (STRING str) INT:
BEGIN
INT p := 1, len := UPB str;
WHILE p ≤ len ANDF is space (str[p]) DO p +:= 1 OD;
IF str[1] = "-" OR str[1] = "+" THEN
p +:= 1
FI;
INT n := 0;
WHILE p ≤ len ANDF is space (str[p]) DO p +:= 1 OD;
FOR i FROM p TO len WHILE is digit (str[i]) DO
n := n × 10 + ABS str[i] - ABS "0"
OD;
n
END;
# pad to fixed width #
PROC field = (UNION (STRING,INT) x, INT w) STRING:
BEGIN
STRING s = (x | (INT i): whole (i,0), (STRING t): t);
(w >= UPB s | " " * (w - UPB s)) + s
END;
PROC get web page = (STRING host, path) STRING:
BEGIN
STRING reply;
INT rc;
# 'http content' sometimes fails with interrupted system call, so we loop until succeeding #
WHILE
# 'http content' makes requests that are not accepted by rosettacode.org, so therefore the hack #
STRING hack = " HTTP/1.0" + crlf +
"Host: rosettacode.org" + crlf +
"User-Agent: rank_languages_by_popularity";
rc := http content (reply, host, path + hack, 0);
rc = 4
DO SKIP
OD;
IF rc = 0 AND grep in string ("^HTTP/[0-9.]+ 200", reply, NIL, NIL) = 0 THEN
INT p;
IF string in string (crlf + crlf, p, reply) THEN
STRING headers = reply[:p],
body = reply[p+4:];
body
ELSE
""
FI
ELSE
print (strerror (rc)); ""
FI
END;
# the main program rank languages by popularity starts here #
STRING gcmcontinue;
FLEX[0]STRING lines;
# get through API in chunks of 500 #
WHILE
STRING body = get web page (domain, page + (gcmcontinue /= "" | "&gcmcontinue=" + gcmcontinue));
INT b, e;
gcmcontinue := (grep in string ("gcmcontinue=""([^""]+)", body, b, e) = 0 | body[b+13:e-1] | "");
# split the XML into lines on </page> #
lines := lines + split (body, "</page>");
gcmcontinue /= "" DO SKIP
OD;
# Each line is one language,
go through them and rewrite them to something we can sort #
FOR i TO UPB lines DO
STRING line = lines[i];
STRING title;
INT pages := 0;
INT b, e;
# the two fields we are intrested in are title="Category:xxx", and pages="999" #
IF grep in string ("title=""Category:[^""]+""", line, b, e) = 0 THEN
title := line[b+16:e-1]
FI;
IF grep in string ("pages=""[0-9]+""", line, b, e) = 0 THEN
pages := TOINT line[b+7:e-1]
FI;
lines[i] := field (pages, 6) + " " + title
OD;
lines := REVERSE SORT lines;
INT rank := 1;
BOOL tied := FALSE, lasttied := FALSE;
print ((new line, whole (UPB lines, 0), " languages", new line, new line));
FOR i TO UPB lines DO
INT entries = TOINT lines[i][:6];
STRING lang = lines[i][8:];
IF entries > 0 THEN
tied := i < UPB lines ANDF lines[i][:6] = lines[i+1][:6];
print (("rank: ", field (rank,3), " ", (tied OR lasttied | "[tied]" | " "*6),
field ("(" + whole (entries,0) + " " + (entries = 1 | "entry)" | "entries)"), 20),
" ", lang, new line));
IF NOT tied THEN rank +:= 1 FI;
lasttied := tied
FI
OD

View file

@ -0,0 +1,84 @@
function join(array, start, end, sep, result, i) {
result = array[start]
for (i = start + 1; i <= end; i++)
result = result sep array[i]
return result
}
function trim(str) {
gsub(/^[[:blank:]]+|[[:blank:]\n]+$/, "", str)
return str
}
function http2var( site,path,server,j,output) {
RS = ORS = "\r\n"
site = "rosettacode.org"
path = "/mw/api.php" \
"?action=query" \
"&generator=categorymembers" \
"&gcmtitle=Category:Programming%20Languages" \
"&gcmlimit=500" \
(gcmcontinue "" ? "&gcmcontinue=" gcmcontinue : "") \
"&prop=categoryinfo" \
"&format=txt"
server = "/inet/tcp/0/" site "/80"
print "GET " path " HTTP/1.0" |& server
print "Host: " site |& server
print "" |& server
while ((server |& getline) > 0) {
if($0 != 0) {
j++
output[j] = $0
}
}
close(server)
if(length(output) == 0)
return -1
else
return join(output, 1, j, "\n")
}
function parse(webpage ,c,a,i,b,e,pages) {
# Check for API continue code ie. a new page of results available
match(webpage, "gcmcontinue[]] =>[^)]+[^)]", a)
if(a[0] != "") {
split(a[0], b, ">")
gcmcontinue = trim(b[2])
} else gcmcontinue = ""
c = split(webpage, a, "[[][0-9]{1,7}[]]")
while(i++ < c) {
if(match(a[i], /[pages]/)) {
match(a[i], "pages[]] =>[^[]+[^[]", b)
split(b[0], e, ">")
pages = trim(e[2]) + 0
} else pages = 0
if(match(a[i], /[title]/)) {
match(a[i], "title[]] =>[^[]+[^[]", b)
split(b[0], e, ":")
e[2] = trim(e[2])
if ( substr(e[2], length(e[2]), 1) == ")" )
e[2] = trim( substr(e[2], 1, length(e[2]) - 1) )
if(length(e[2]) > 0)
G[e[2]] = pages
}
}
}
BEGIN {
parse( http2var() ) # First 500
while ( gcmcontinue != "" )
parse( http2var() ) # Next 500, etc
# https://www.gnu.org/software/gawk/manual/html_node/Controlling-Scanning.html
PROCINFO["sorted_in"] = "@val_type_desc"
for ( language in G )
print ++i ". " language " - " G[language]
}

View file

@ -0,0 +1,89 @@
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;

View file

@ -0,0 +1,86 @@
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

View file

@ -0,0 +1,90 @@
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

View file

@ -0,0 +1,91 @@
( 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
)
)
& ;

View file

@ -0,0 +1,78 @@
#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 ;
}

View file

@ -0,0 +1,41 @@
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++;
}
}
}

View file

@ -0,0 +1,55 @@
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++;
}
}
}

View file

@ -0,0 +1,77 @@
#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;
}

View file

@ -0,0 +1,147 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include "cJSON.h"
char *URL_BASE = "http://www.rosettacode.org/mw/api.php?format=json&action=query&generator=categorymembers&gcmtitle=Category:Programming%20Languages&gcmlimit=500&prop=categoryinfo&rawcontinue";
char *URL_BASE_CONT = "http://www.rosettacode.org/mw/api.php?format=json&action=query&generator=categorymembers&gcmtitle=Category:Programming%20Languages&gcmlimit=500&prop=categoryinfo&gcmcontinue=";
typedef struct mem {
char *text;
size_t size;
} mem;
typedef struct page {
char *name;
int num;
} page;
size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata);
void curl_request(CURL *curl, char *url, mem *response);
char *build_url(char *cont);
char *get_cont(cJSON *json);
void sort_arrays(page *pages, int *s);
cJSON *parse_json(cJSON *json);
page *fill_arrays(page *pages, int *s, cJSON *json);
int main(int argc, char *argv[]) {
curl_global_init(CURL_GLOBAL_ALL);
CURL *curl = curl_easy_init();
char *cont = NULL;
page *pages = malloc(1);
int till = 10;
int *npag = malloc(sizeof(int));
*npag = 0;
if (argc>1) till = atoi(argv[1]);
do {
mem *response = calloc(1, sizeof(mem));
char *url = build_url(cont);
if (cont) free(cont);
curl_request(curl, url, response);
cJSON *json = cJSON_Parse(response->text);
cont = get_cont(json);
cJSON *json_pages = parse_json(json);
pages = fill_arrays(pages, npag, json_pages);
cJSON_Delete(json);
free(url);
free(response->text);
free(response);
} while (cont);
sort_arrays(pages, npag);
if (till>*npag||till<-1) till=10;
if (till==-1) till=*npag;
for (int i = 0;i<till;i++) {
printf("#%d: %s, %d tasks\n", i+1, pages[i].name, pages[i].num);
}
for (int i = 0;i<*npag;i++) {
free(pages[i].name);
}
free(pages);
free(npag);
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata) {
mem *response = userdata;
response->text = realloc(response->text, response->size+size*nmemb+1);
memcpy(&(response->text[response->size]), ptr, size*nmemb);
response->size += size*nmemb;
response->text[response->size] = '\0';
return size*nmemb;
}
void curl_request(CURL *curl, char *url, mem *response) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, response);
curl_easy_perform(curl);
}
char *build_url(char *cont) {
char *url;
if (cont) {
int size = strlen(URL_BASE_CONT)+strlen(cont)+1;
url = calloc(1, size);
strncpy(url, URL_BASE_CONT, strlen(URL_BASE_CONT));
strcat(url, cont);
} else {
url = malloc(strlen(URL_BASE)+1);
strcpy(url, URL_BASE);
}
return url;
}
cJSON *parse_json(cJSON *json) {
cJSON *pages;
if (json) {
pages = cJSON_GetObjectItem(json, "query");
pages = cJSON_GetObjectItem(pages, "pages");
pages = pages->child;
}
return pages;
}
char *get_cont(cJSON *json) {
cJSON *jcont = cJSON_GetObjectItem(json, "query-continue");
if (jcont && jcont->child->child) {
char *cont = malloc(strlen(jcont->child->child->valuestring)+1);
strcpy(cont, jcont->child->child->valuestring);
return cont;
} else {
return NULL;
}
}
page *fill_arrays(page *pag, int *i, cJSON *json) {
cJSON *cur_page = json;
page *pages = pag;
do {
pages = realloc(pages, *i*sizeof(page)+sizeof(page));
if (json->child) {
int size = strlen(cur_page->child->next->next->valuestring)-9;
char *lang = malloc(size+1);
strcpy(lang, cur_page->child->next->next->valuestring+9);
pages[*i].name = lang;
} else {
pages[*i].name = "no name";
}
int task = cur_page->child->next->next->next?cur_page->child->next->next->next->child->valueint:0;
pages[*i].num = task;
*i = *i+1;
cur_page = cur_page->next;
} while (cur_page->next);
return pages;
}
void sort_arrays(page *pages, int *size) {
int sorted = 0;
do {
sorted = 1;
for (int i = 0;i<*size-1;i++) {
if (pages[i].num<pages[i+1].num) {
sorted = 0;
int a = pages[i+1].num;
pages[i+1].num = pages[i].num;
pages[i].num = a;
char *s = pages[i+1].name;
pages[i+1].name = pages[i].name;
pages[i].name = s;
}
}
} while (sorted!=1);
}

View file

@ -0,0 +1,20 @@
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[]);
}

View file

@ -0,0 +1,135 @@
program Rank_languages_by_popularity;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Classes,
IdHttp,
IdBaseComponent,
IdComponent,
IdIOHandler,
IdIOHandlerSocket,
IdIOHandlerStack,
IdSSL,
IdSSLOpenSSL,
System.RegularExpressions,
System.Generics.Collections,
System.Generics.Defaults;
const
AURL = 'https://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000';
UserAgent =
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36';
type
TPair = record
Language: string;
Users: Integer;
constructor Create(lang, user: string);
end;
TPairs = TList<TPair>;
{ TPair }
constructor TPair.Create(lang, user: string);
begin
Language := lang;
Users := StrToIntDef(user, 0);
end;
function GetFullCode: string;
begin
with TIdHttp.create(nil) do
begin
HandleRedirects := True;
Request.UserAgent := UserAgent;
IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
Result := Get(AURL);
IOHandler.Free;
Free;
end;
end;
function GetList(const Code: string): TPairs;
var
RegularExpression: TRegEx;
Match: TMatch;
language, users: string;
begin
Result := TPairs.Create;
RegularExpression.Create('>(?<LANG>[^<,;]*)<\/a>.. \((?<USERS>[,\d]*)');
Match := RegularExpression.Match(Code);
while Match.Success do
begin
users := Match.Groups.Item['USERS'].Value.Replace(',', '');
language := Match.Groups.Item['LANG'].Value;
Result.Add(TPair.Create(language, users));
Match := Match.NextMatch;
end;
end;
procedure Sort(List: TPairs);
begin
List.Sort(TComparer<TPair>.Construct(
function(const Left, Right: TPair): Integer
begin
result := Right.Users - Left.Users;
if result = 0 then
result := CompareText(Left.Language, Right.Language);
end));
end;
function SumUsers(List: TPairs): Cardinal;
var
p: TPair;
begin
Result := 0;
for p in List do
begin
Inc(Result, p.Users);
end;
end;
var
Data: TStringList;
Code, line: string;
List: TPairs;
i: Integer;
begin
Data := TStringList.Create;
Writeln('Downloading code...');
Code := GetFullCode;
data.Clear;
List := GetList(Code);
Sort(List);
Writeln('Total languages: ', List.Count);
Writeln('Total Users: ', SumUsers(List));
Writeln('Top 10:'#10);
for i := 0 to List.Count - 1 do
begin
line := Format('%5dth %5d %s', [i + 1, List[i].users, List[i].language]);
Data.Add(line);
if i < 10 then
Writeln(line);
end;
Data.SaveToFile('Rank.txt');
List.Free;
Data.Free;
Readln;
end.

View file

@ -0,0 +1,60 @@
-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}.

View file

@ -0,0 +1,53 @@
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

View file

@ -0,0 +1,115 @@
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)
}
}

View file

@ -0,0 +1,9 @@
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" }

View file

@ -0,0 +1,102 @@
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import Network.HTTP.Base (urlEncode)
import Network.HTTP.Conduit (simpleHttp)
import Data.List (sortBy, groupBy)
import Data.Function (on)
import Data.Map (Map, toList)
-- Record representing a single language.
data Language =
Language {
name :: String,
quantity :: Int
} deriving (Show)
-- Make Language an instance of FromJSON for parsing of query response.
instance FromJSON Language where
parseJSON (Object p) = do
categoryInfo <- p .:? "categoryinfo"
let quantity = case categoryInfo of
Just ob -> ob .: "size"
Nothing -> return 0
name = p .: "title"
Language <$> name <*> quantity
-- Record representing entire response to query.
-- Contains collection of languages and optional continuation string.
data Report =
Report {
continue :: Maybe String,
languages :: Map String Language
} deriving (Show)
-- Make Report an instance of FromJSON for parsing of query response.
instance FromJSON Report where
parseJSON (Object p) = do
querycontinue <- p .:? "query-continue"
let continue
= case querycontinue of
Just ob -> fmap Just $
(ob .: "categorymembers") >>=
( .: "gcmcontinue")
Nothing -> return Nothing
languages = (p .: "query") >>= (.: "pages")
Report <$> continue <*> languages
-- Pretty print a single language
showLanguage :: Int -> Bool -> Language -> IO ()
showLanguage rank tie (Language languageName languageQuantity) =
let rankStr = show rank
in putStrLn $ rankStr ++ "." ++
replicate (4 - length rankStr) ' ' ++
(if tie then " (tie)" else " ") ++
" " ++ drop 9 languageName ++
" - " ++ show languageQuantity
-- Pretty print languages with common rank
showRanking :: (Int, [Language]) -> IO ()
showRanking (ranking, languages) =
mapM_ (showLanguage ranking $ length languages > 1) languages
-- Sort and group languages by rank, then pretty print them.
showLanguages :: [Language] -> IO ()
showLanguages allLanguages =
mapM_ showRanking $
zip [1..] $
groupBy ((==) `on` quantity) $
sortBy (flip compare `on` quantity) allLanguages
-- Mediawiki api style query to send to rosettacode.org
queryStr = "http://rosettacode.org/mw/api.php?" ++
"format=json" ++
"&action=query" ++
"&generator=categorymembers" ++
"&gcmtitle=Category:Programming%20Languages" ++
"&gcmlimit=100" ++
"&prop=categoryinfo"
-- Issue query to get a list of Language descriptions
runQuery :: [Language] -> String -> IO ()
runQuery ls query = do
Just (Report continue langs) <- decode <$> simpleHttp query
let accLanguages = ls ++ map snd (toList langs)
case continue of
-- If there is no continue string we are done so display the accumulated languages.
Nothing -> showLanguages accLanguages
-- If there is a continue string, recursively continue the query.
Just continueStr -> do
let continueQueryStr = queryStr ++ "&gcmcontinue=" ++ urlEncode continueStr
runQuery accLanguages continueQueryStr
main :: IO ()
main = runQuery [] queryStr

View file

@ -0,0 +1,35 @@
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

View file

@ -0,0 +1,33 @@
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

View file

@ -0,0 +1,12 @@
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

View file

@ -0,0 +1,49 @@
$define RCLANGS "http://rosettacode.org/mw/api.php?format=xml&action=query&generator=categorymembers&gcmtitle=Category:Programming%20Languages&gcmlimit=500&prop=categoryinfo"
$define RCUA "User-Agent: Unicon Rosetta 0.1"
$define RCXUA "X-Unicon: http://unicon.org/"
link strings
link hexcvt
procedure main()
cnt := create seq()
last := -1
every pair := !reverse(sort(langs := tallyPages(),2)) do {
n := if last ~=:= pair[2] then @cnt else (@cnt,"")
write(right(n,4),": ",left(pair[1],30,". "),right(pair[2],10,". "))
}
write(*langs, " languages")
end
# Generate page counts for each language
procedure tallyPages(url)
/url := RCLANGS
counts := table()
continue := ""
while \(txt := ReadURL(url||continue)) do {
txt ? {
if tab(find("gcmcontinue=")) then {
continue := "&"||tab(upto('"'))
move(1)
continue ||:= tab(upto('"'))
}
else continue := ""
while tab(find("<page ") & find(s := "title=\"Category:")+*s) do {
lang := tab(upto('"'))
tab(find(s := "pages=\"")+*s)
counts[lang] := numeric(tab(upto('"')))
}
if continue == "" then return counts
}
}
end
procedure ReadURL(url) #: read URL into string
page := open(url,"m",RCUA,RCXUA) | stop("Unable to open ",url)
text := ""
if page["Status-Code"] < 300 then while text ||:= reads(page,-1)
else write(&errout,image(url),": ",
page["Status-Code"]," ",page["Reason-Phrase"])
close(page)
return text
end

View file

@ -0,0 +1,18 @@
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

View file

@ -0,0 +1,11 @@
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

View file

@ -0,0 +1,131 @@
import java.net.URL;
import java.net.URLConnection;
import java.io.*;
import java.util.*;
public class GetRCLanguages
{
// Custom sort Comparator for sorting the language list
// assumes the first character is the page count and the rest is the language name
private static class LanguageComparator implements Comparator<String>
{
public int compare( String a, String b )
{
// as we "know" we will be comparaing languages, we will assume the Strings have the appropriate format
int result = ( b.charAt( 0 ) - a.charAt( 0 ) );
if( result == 0 )
{
// the counts are the same - compare the names
result = a.compareTo( b );
} // if result == 0
return result;
} // compare
} // LanguageComparator
// get the string following marker in text
private static String after( String text, int marker )
{
String result = "";
int pos = text.indexOf( marker );
if( pos >= 0 )
{
// the marker is in the string
result = text.substring( pos + 1 );
} // if pos >= 0
return result;
} // after
// read and parse the content of path
// results returned in gcmcontinue and languageList
public static void parseContent( String path
, String[] gcmcontinue
, ArrayList<String> languageList
)
{
try
{
URL url = new URL( path );
URLConnection rc = url.openConnection();
// Rosetta Code objects to the default Java user agant so use a blank one
rc.setRequestProperty( "User-Agent", "" );
BufferedReader bfr = new BufferedReader( new InputStreamReader( rc.getInputStream() ) );
gcmcontinue[0] = "";
String languageName = "?";
String line = bfr.readLine();
while( line != null )
{
line = line.trim();
if ( line.startsWith( "[title]" ) )
{
// have a programming language - should look like "[title] => Category:languageName"
languageName = after( line, ':' ).trim();
}
else if( line.startsWith( "[pages]" ) )
{
// number of pages the language has (probably)
String pageCount = after( line, '>' ).trim();
if( pageCount.compareTo( "Array" ) != 0 )
{
// haven't got "[pages] => Array" - must be a number of pages
languageList.add( ( (char) Integer.parseInt( pageCount ) ) + languageName );
languageName = "?";
} // if [pageCount.compareTo( "Array" ) != 0
}
else if( line.startsWith( "[gcmcontinue]" ) )
{
// have an indication of wether there is more data or not
gcmcontinue[0] = after( line, '>' ).trim();
} // if various line starts
line = bfr.readLine();
} // while line != null
bfr.close();
}
catch( Exception e )
{
e.printStackTrace();
} // try-catch
} // parseContent
public static void main( String[] args )
{
// get the languages
ArrayList<String> languageList = new ArrayList<String>( 1000 );
String[] gcmcontinue = new String[1];
gcmcontinue[0] = "";
do
{
String path = ( "http://www.rosettacode.org/mw/api.php?action=query"
+ "&generator=categorymembers"
+ "&gcmtitle=Category:Programming%20Languages"
+ "&gcmlimit=500"
+ ( gcmcontinue[0].compareTo( "" ) == 0 ? "" : ( "&gcmcontinue=" + gcmcontinue[0] ) )
+ "&prop=categoryinfo"
+ "&format=txt"
);
parseContent( path, gcmcontinue, languageList );
}
while( gcmcontinue[0].compareTo( "" ) != 0 );
// sort the languages
String[] languages = languageList.toArray(new String[]{});
Arrays.sort( languages, new LanguageComparator() );
// print the languages
int lastTie = -1;
int lastCount = -1;
for( int lPos = 0; lPos < languages.length; lPos ++ )
{
int count = (int) ( languages[ lPos ].charAt( 0 ) );
System.out.format( "%4d: %4d: %s\n"
, 1 + ( count == lastCount ? lastTie : lPos )
, count
, languages[ lPos ].substring( 1 )
);
if( count != lastCount )
{
lastTie = lPos;
lastCount = count;
} // if count != lastCount
} // for lPos
} // main
} // GetRCLanguages

View file

@ -0,0 +1,45 @@
#!/bin/bash
# produce lines of the form: [ "language", n ]
function categories {
curl -Ss 'http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000' |\
grep "/wiki/Category:" | grep member | grep -v '(.*(' |\
grep -v ' User</a>' |\
sed -e 's/.*title="Category://' -e 's/member.*//' |\
sed 's:^\([^"]*\)"[^(]*(\(.*\):["\1", \2]:'
}
# produce lines of the form: "language"
function languages {
curl -Ss 'http://rosettacode.org/wiki/Category:Programming_Languages' |\
sed '/Pages in category "Programming Languages"/,$d' |\
grep '<li><a href="/wiki/Category:' | fgrep title= |\
sed 's/.*Category:\([^"]*\)".*/"\1"/'
}
categories |\
/usr/local/bin/jq --argfile languages <(languages) -s -r '
# input: array of [score, _] sorted by score
# output: array of [ranking, score, _]
def ranking:
reduce .[] as $x
([]; # array of [count, rank, score, _]
if length == 0 then [[1, 1] + $x]
else .[length - 1] as $previous
| if $x[0] == $previous[2]
then . + [ [$previous[0] + 1, $previous[1]] + $x ]
else . + [ [$previous[0] + 1, $previous[0] + 1] + $x ]
end
end)
| [ .[] | .[1:] ];
# Every language page has three category pages that should be excluded
(reduce .[] as $pair
({};
($pair[1] as $n | if $n > 3 then . + {($pair[0]): ($n - 3)} else . end ))) as $freq
| [ $languages[] | select($freq[.] != null) | [$freq[.], .]]
| sort
| reverse
| ranking[]
| "\(.[0]). \(.[1]) - \(.[2])" '

View file

@ -0,0 +1,23 @@
# First ten and last ten lines as of May 27, 2015
$ pop.sh
1. 868 - Tcl
2. 863 - Racket
3. 842 - Python
4. 778 - J
5. 769 - Ruby
6. 756 - Perl 6
7. 752 - C
8. 736 - D
9. 735 - Go
10. 700 - Perl
...
386. 1 - FP
386. 1 - ElastiC
386. 1 - ESQL
386. 1 - Clipper/XBase++
386. 1 - Bori
386. 1 - Biferno
386. 1 - AspectJ
386. 1 - Algae
386. 1 - 80386 Assembly
386. 1 - 68000 Assembly

View file

@ -0,0 +1,37 @@
""" Rosetta code task rosettacode.org/wiki/Rosetta_Code/Rank_languages_by_popularity """
using Dates
using DataFrames
using HTTP
using JSON3
""" Get listing of all tasks and draft tasks with authors and dates created, with the counts as popularity """
function rosetta_code_language_example_counts(verbose = false)
URL = "https://rosettacode.org/w/api.php?"
LANGPARAMS = ["action" => "query", "format" => "json", "formatversion" => "2", "generator" => "categorymembers",
"gcmtitle" => "Category:Programming_Languages", "gcmlimit" => "500", "rawcontinue" => "", "prop" => "title"]
queryparams = copy(LANGPARAMS)
df = empty!(DataFrame([[""], [0]], ["ProgrammingLanguage", "ExampleCount"]))
while true # get all the languages listed, with curid, eg rosettacode.org/w/index.php?curid=196 for C
resp = HTTP.get(URL * join(map(p -> p[1] * (p[2] == "" ? "" : ("=" * p[2])), queryparams), "&"))
json = JSON3.read(String(resp.body))
pages = json.query.pages
reg = r"The following \d+ pages are in this category, out of ([\d\,]+) total"
for p in pages
lang = replace(p.title, "Category:" => "")
langpage = String(HTTP.get("https://rosettacode.org/w/index.php?curid=" * string(p.pageid)).body)
if !((m = match(reg, langpage)) isa Nothing)
push!(df, [lang, parse(Int, replace(m.captures[1], "," => ""))])
verbose && println("Language: $lang, count: ", m.captures[1])
end
end
!haskey(json, "query-continue") && break # break if no more pages, else continue to next pages
queryparams = vcat(LANGPARAMS, "gcmcontinue" => json["query-continue"]["categorymembers"]["gcmcontinue"])
end
return sort!(df, :ExampleCount, rev = true)
end
println("Top 20 Programming Languages on Rosetta Code by Number of Examples, As of: ", now())
println(rosetta_code_language_example_counts()[begin:begin+19, :])

View file

@ -0,0 +1,81 @@
import java.net.URL
import java.io.*
object Popularity {
/** Gets language data. */
fun ofLanguages(): List<String> {
val languages = mutableListOf<String>()
var gcm = ""
do {
val path = url + (if (gcm == "") "" else "&gcmcontinue=" + gcm) + "&prop=categoryinfo" + "&format=txt"
try {
val rc = URL(path).openConnection() // URL completed, connection opened
// Rosetta Code objects to the default Java user agent so use a blank one
rc.setRequestProperty("User-Agent", "")
val bfr = BufferedReader(InputStreamReader(rc.inputStream))
try {
gcm = ""
var languageName = "?"
var line: String? = bfr.readLine()
while (line != null) {
line = line.trim { it <= ' ' }
if (line.startsWith("[title]")) {
// have a programming language - should look like "[title] => Category:languageName"
languageName = line[':']
} else if (line.startsWith("[pages]")) {
// number of pages the language has (probably)
val pageCount = line['>']
if (pageCount != "Array") {
// haven't got "[pages] => Array" - must be a number of pages
languages += pageCount.toInt().toChar() + languageName
languageName = "?"
}
} else if (line.startsWith("[gcmcontinue]"))
gcm = line['>'] // have an indication of whether there is more data or not
line = bfr.readLine()
}
} finally {
bfr.close()
}
} catch (e: Exception) {
e.printStackTrace()
}
} while (gcm != "")
return languages.sortedWith(LanguageComparator)
}
/** Custom sort Comparator for sorting the language list.
* Assumes the first character is the page count and the rest is the language name. */
internal object LanguageComparator : java.util.Comparator<String> {
override fun compare(a: String, b: String): Int {
// as we "know" we will be comparing languages, we will assume the Strings have the appropriate format
var r = b.first() - a.first()
return if (r == 0) a.compareTo(b) else r
// r == 0: the counts are the same - compare the names
}
}
/** Gets the string following marker in text. */
private operator fun String.get(c: Char) = substringAfter(c).trim { it <= ' ' }
private val url = "http://www.rosettacode.org/mw/api.php?action=query" +
"&generator=categorymembers" + "&gcmtitle=Category:Programming%20Languages" +
"&gcmlimit=500"
}
fun main(args: Array<String>) {
// read/sort/print the languages (CSV format):
var lastTie = -1
var lastCount = -1
Popularity.ofLanguages().forEachIndexed { i, lang ->
val count = lang.first().toInt()
if (count == lastCount)
println("%12s%s".format("", lang.substring(1)))
else {
println("%4d, %4d, %s".format(1 + if (count == lastCount) lastTie else i, count, lang.substring(1)))
lastTie = i
lastCount = count
}
}
}

View file

@ -0,0 +1,25 @@
<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>

View file

@ -0,0 +1,104 @@
Module RankLanguages {
Const Part1$="<a href="+""""+ "/wiki/Category", Part2$="member"
Const langHttp$="http://rosettacode.org/wiki/Category:Programming_Languages"
Const categoriesHttp$="http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000"
Def long m, i,j, tasks, counter, limit, T, t1
Def string LastLang$, job$
Document final$, languages$, categories$
httpGet$=lambda$ (url$, timeout=1000)->{
Declare htmldoc "Msxml2.ServerXMLHTTP"
With htmldoc , "readyState" as ready
Report "Download:"+url$
Method htmldoc "open","get", url$, True
Method htmldoc "send"
Profiler
While Ready<>4 {
Wait 20
Print Over format$("Wait: {0:3} sec", timecount/1000)
If timecount>timeout then Exit
}
If ready=4 Then With htmldoc, "responseText" as ready$ : =ready$
Declare htmldoc Nothing
print
}
languages$=httpGet$(langHttp$, 30000)
If Doc.Len(languages$)=0 then Error "File download failed (languages)"
Inventory Lang
m=Paragraph(languages$, 0)
If Forward(languages$,m) then {
While m {
job$=Paragraph$(languages$,(m))
If Instr(job$, part1$) Else Continue
i = Instr(job$, "</a>")
If i Else Continue ' same as If i=0 Then Continue
j = i
i=Rinstr(job$, ">", -i)
If i Else Continue
LastLang$=MID$(job$, i+1, j-i-1)
if Instr(job$, "Category:"+lastlang$) then Append lang, lastlang$:=0 : Print Over format$("Languages: {0}", len(lang))
}
}
Print
Document categories$=httpGet$(categoriesHttp$, 30000)
If Doc.Len(categories$)=0 then Error "File download failed (categories)"
limit=Doc.Par(categories$)
If limit<Len(Lang) then Error "Invalid data"
Refresh
set slow
m=Paragraph(categories$, 0)
counter=0
If Forward(categories$,m) then {
While m {
job$=Paragraph$(categories$,(m))
counter++
Print Over format$("{0:2:-6}%", counter/limit*100)
i=Instr(job$, part2$)
If i Else Continue
i=Rinstr(job$, "(", -i)
If i Else Continue
tasks=Val(Filter$(Mid$(job$, i+1),","))
If tasks Else Continue
i=Rinstr(job$, "<", -i)
If i Else Continue
j = i
i=Rinstr(job$, ">", -i)
If i Else Continue
LastLang$=MID$(job$, i+1, j-i-1)
If Exist(Lang, LastLang$) Then {
Return Lang, LastLang$:=Lang(LastLang$)+tasks
}
}
}
Print
\\ this type of inventory can get same keys
\\ also has stable sort
Report "Make Inventory list by Task"
Inventory queue ByTask
t1=Len(Lang)
T=Each(Lang)
While T {
Append ByTask, Eval(T):=Eval$(T!)
Print Over format$("Complete: {0} of {1}", T^+1, t1 )
}
Print
Report "Sort by task (stable sort, sort keys as numbers)"
Sort descending ByTask as number
Report "Make List"
T=Each(ByTask)
final$="Sample output on "+Date$(Today, 1033, "long date")+{:
}
While T {
final$=format$("rank:{0::-4}. {1:-5} entries - {2}", T^+1, Eval$(T!), Eval$(T))+{
}
}
Report "Copy to Clipboard"
clipboard final$
\\ present to console with 3/4 fill lines then stop for space bar or mouse click to continue
Report final$
}
RankLanguages

View file

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

View file

@ -0,0 +1,5 @@
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]]

View file

@ -0,0 +1,42 @@
import std/[Algorithm, httpclient, json, re, strformat, strutils]
const
LangSite = "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Languages&cmlimit=500&format=json"
CatSite = "http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000"
let regex = re"title=""Category:(.*?)"">.+?</a>.*\((.*) members\)"
type Rank = tuple[lang: string, count: int]
proc cmp(a, b: Rank): int =
result = cmp(b.count, a.count)
if result == 0: result = cmp(a.lang, b.lang)
proc add(langs: var seq[string]; fromJson: JsonNode) =
for entry in fromJson{"query", "categorymembers"}:
let title = entry["title"].getStr()
if title.startsWith("Category:"):
langs.add title[9..^1]
var client = newHttpClient()
var langs: seq[string]
var url = LangSite
while true:
let response = client.get(url)
if response.status != $Http200: break
let fromJson = response.body.parseJson()
langs.add fromJson
if "continue" notin fromJson: break
let cmcont = fromJson{"continue", "cmcontinue"}.getStr
let cont = fromJson{"continue", "continue"}.getStr
url = LangSite & fmt"&cmcontinue={cmcont}&continue={cont}"
var ranks: seq[Rank]
for line in client.getContent(CatSite).findAll(regex):
let lang = line.replacef(regex, "$1")
if lang in langs:
let count = parseInt(line.replacef(regex, "$2").replace(",", "").strip())
ranks.add (lang, count)
ranks.sort(cmp)
for i, rank in ranks:
echo &"{i + 1:3} {rank.count:4} - {rank.lang}"

View file

@ -0,0 +1,80 @@
use HTTP;
use RegEx;
use XML;
use Collection;
class RosettaRank {
function : Main(args : String[]) ~ Nil {
langs_xml := "";
client := HttpClient->New();
in := client->Get("http://rosettacode.org/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Languages&cmlimit=5000&format=xml");
each(i : in) {
langs_xml += in->Get(i)->As(String);
};
langs := StringSet->New();
parser := XmlParser->New(langs_xml);
if(parser->Parse()) {
# get first item
results := parser->FindElements("/api/query/categorymembers/cm");
each(i : results) {
element := results->Get(i)->As(XmlElement);
name := element->GetAttribute("title")->GetValue();
offset := name->Find(':');
if(offset > -1) {
lang := name->SubString(offset + 1, name->Size() - offset - 1);
langs->Insert(lang->ReplaceAll("&#x20;", " "));
};
};
};
langs_counts := IntMap->New();
client := HttpClient->New();
html := client->Get("http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000");
each(i : html) {
lines := html->Get(i)->As(String);
html_elements := lines->Split("\n");
each(j : html_elements) {
element := html_elements[j];
name : String; count : String;
regex := RegEx->New("<li><a href=\"(\\w|\\s|/|\\?|\\&|;|:|#)+\"\\stitle=\"Category:(\\w|\\s|#)+\">");
found := regex->FindFirst(element);
if(found <> Nil) {
group1 := found->Size();
regex := RegEx->New("(\\w|\\s)+");
found := regex->Match(element, group1);
if(found <> Nil & found->Size() > 0) {
name := found;
# skip over some junk characters
group2 := group1 + found->Size() + 10;
regex := RegEx->New("\\s\\(");
found := regex->Match(element, group2);
if(found <> Nil) {
group3 := group2 + found->Size();
regex := RegEx->New("\\d+");
found := regex->Match(element, group3);
if(found <> Nil & found->Size() > 0) {
count := found;
};
};
};
};
if(name <> Nil & count <> Nil) {
if(langs->Has(name)) {
langs_counts->Insert(count->ToInt(), name);
};
name := Nil; count := Nil;
};
};
};
keys := langs_counts->GetKeys();
count := 1;
for(i := keys->Size() - 1; i >= 0; i -=1;) {
key := keys->Get(i);
IO.Console->Print(count)->Print(". ")->Print(key)->Print(" - ")->PrintLine(langs_counts->Find(key)->As(String));
count += 1;
};
}
}

View file

@ -0,0 +1,333 @@
/* 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)
*--------------------------------------------------------------------*/
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 pos(',', mems)\==0 then
mems=changestr(",", mems, '') /* remove commas. */
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>â<EFBFBD>⎠(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

View file

@ -0,0 +1,40 @@
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

View file

@ -0,0 +1,39 @@
use 5.010;
use MediaWiki::API;
my $api =
MediaWiki::API->new( { api_url => 'http://rosettacode.org/w/api.php' } );
my @languages;
my $gcmcontinue;
while (1) {
my $apih = $api->api(
{
action => 'query',
generator => 'categorymembers',
gcmtitle => 'Category:Programming Languages',
gcmlimit => 250,
prop => 'categoryinfo',
gcmcontinue => $gcmcontinue
}
);
push @languages, values %{ $apih->{'query'}{'pages'} };
last if not $gcmcontinue = $apih->{'continue'}{'gcmcontinue'};
}
for (@languages) {
$_->{'title'} =~ s/Category://;
$_->{'categoryinfo'}{'size'} //= 0;
}
my @sorted_languages =
reverse sort { $a->{'categoryinfo'}{'size'} <=> $b->{'categoryinfo'}{'size'} }
@languages;
binmode STDOUT, ':encoding(utf8)';
my $n = 1;
for (@sorted_languages) {
printf "%3d. %20s - %3d\n", $n++, $_->{'title'},
$_->{'categoryinfo'}{'size'};
}

View file

@ -0,0 +1,130 @@
(phixonline)-->
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Rank_Languages.exw</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">output_users</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">limit</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">20</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- 0 to list all</span>
<span style="color: #000000;">languages</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"http://rosettacode.org/wiki/Category:Programming_Languages"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">categories</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000"</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">rosettacode_cache</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- see [[Rosetta_Code/Count_examples#Phix]]</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">correct_name</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">ri</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`&quot;`</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`"`</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`&#039;`</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`'`</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\xE2\x80\x99"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"'"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\xC3\xB6"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"o"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%3A"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">":"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%E2%80%93"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"-"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%E2%80%99"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"'"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%27"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"'"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%2B"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"+"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%C3%A8"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"e"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%C3%A9"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"e"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%C3%B6"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"o"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%C5%91"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"o"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%22"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`"`</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%2A"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"*"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\xC2\xB5"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"u"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\xC3\xA0"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"a"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\xC3\xA6"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"a"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\xC3\xA9"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"e"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\xC3\xB4"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"o"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\xC5\x8D"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"o"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\xCE\x9C"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"u"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\xD0\x9C\xD0\x9A"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"MK"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\xE0\xAE\x89\xE0\xAE\xAF\xE0\xAE\xBF\xE0\xAE\xB0\xE0\xAF\x8D/"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"APEX"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Apex"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"uC++ "</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"UC++"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`CASIO BASIC`</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`Casio BASIC`</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`Visual BASIC`</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`Visual Basic`</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`INTERCAL`</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`Intercal`</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`SETL4`</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`Setl4`</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`QBASIC`</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`QBasic`</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`RED`</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`Red`</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`OCTAVE`</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`Octave`</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ri</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ri</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`OoREXX`</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`OoRexx`</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">ri</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">/</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">cat_title</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">`title="Category:`</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">extract_names</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">results</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- {rank,count,name}</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">get_file_type</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"rc_cache"</span><span style="color: #0000FF;">)!=</span><span style="color: #004600;">FILETYPE_DIRECTORY</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">create_directory</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"rc_cache"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"cannot create rc_cache directory"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000080;font-style:italic;">-- 1) extract languages from eg title="Category:Phix"</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">language_names</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">langs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_download</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"languages.htm"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">languages</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">language_name</span>
<span style="color: #000000;">langs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">langs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`&lt;div class="printfooter"&gt;`</span><span style="color: #0000FF;">,</span><span style="color: #000000;">langs</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"&lt;h2&gt;Subcategories&lt;/h2&gt;"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">langs</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">k</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cat_title</span><span style="color: #0000FF;">,</span><span style="color: #000000;">langs</span><span style="color: #0000FF;">,</span><span style="color: #000000;">start</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">k</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cat_title</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'"'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">langs</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">language_name</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">correct_name</span><span style="color: #0000FF;">(</span><span style="color: #000000;">langs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">..</span><span style="color: #000000;">start</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">language_names</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">language_names</span><span style="color: #0000FF;">,</span><span style="color: #000000;">language_name</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000080;font-style:italic;">-- 2) extract results from eg title="Category:Phix"&gt;Phix&lt;/a&gt;?? (997 members)&lt;/li&gt;
-- but obviously only when we have found that language in the phase above.
-- (note there is / ignore some wierd uncode-like stuff after the &lt;/a&gt;...)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">cats</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_download</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"categories.htm"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">categories</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cat_title</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cats</span><span style="color: #0000FF;">,</span><span style="color: #000000;">start</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">k</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cat_title</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'"'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cats</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">language_name</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">correct_name</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">..</span><span style="color: #000000;">start</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"&lt;/a&gt;"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cats</span><span style="color: #0000FF;">,</span><span style="color: #000000;">start</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">4</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">output_users</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">language_name</span><span style="color: #0000FF;">)></span><span style="color: #000000;">5</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">language_name</span><span style="color: #0000FF;">[-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">" User"</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">language_name</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">correct_name</span><span style="color: #0000FF;">(</span><span style="color: #000000;">language_name</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">language_name</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">language_name</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">and</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">language_name</span><span style="color: #0000FF;">,</span><span style="color: #000000;">language_names</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">start</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"(&lt;"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> <span style="color: #000000;">start</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">while</span> <span style="color: #000080;font-style:italic;">-- (ignore)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">members</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cats</span><span style="color: #0000FF;">[</span><span style="color: #000000;">start</span><span style="color: #0000FF;">..</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'&lt;'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cats</span><span style="color: #0000FF;">,</span><span style="color: #000000;">start</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)]</span>
<span style="color: #000000;">members</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">members</span><span style="color: #0000FF;">,</span><span style="color: #008000;">","</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">scanf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">members</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"(%d member%s)&lt;"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">results</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">results</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">language_name</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">results</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort_columns</span><span style="color: #0000FF;">(</span><span style="color: #000000;">results</span><span style="color: #0000FF;">,{-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">})</span> <span style="color: #000080;font-style:italic;">-- (descending 2nd column, then asc 3rd)
--3) assign rank</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rank</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">results</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">results</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">=</span><span style="color: #000000;">prev</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">results</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"="</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">rank</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #000000;">results</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rank</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">count</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">results</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">show</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">results</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">limit</span><span style="color: #0000FF;">?</span><span style="color: #000000;">limit</span><span style="color: #0000FF;">:</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">results</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%3s: %,d - %s\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">results</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">show</span><span style="color: #0000FF;">(</span><span style="color: #000000;">extract_names</span><span style="color: #0000FF;">())</span>
<!--

View file

@ -0,0 +1,14 @@
(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)) )

View file

@ -0,0 +1,27 @@
$get1 = (New-Object Net.WebClient).DownloadString("http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Languages&cmlimit=700&format=json")
$get2 = (New-Object Net.WebClient).DownloadString("http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000")
$match1 = [regex]::matches($get1, "`"title`":`"Category:(.+?)`"")
$match2 = [regex]::matches($get2, "title=`"Category:([^`"]+?)`">[^<]+?</a>[^\(]*\((\d+) members\)")
$r = 1
$langs = $match1 | foreach { $_.Groups[1].Value.Replace("\","") }
$res = $match2 | sort -Descending {[Int]$($_.Groups[2].Value)} | foreach {
if ($langs.Contains($_.Groups[1].Value))
{
[pscustomobject]@{
Rank = "$r"
Members = "$($_.Groups[2].Value)"
Language = "$($_.Groups[1].Value)"
}
$r++
}
}
1..30 | foreach{
[pscustomobject]@{
"Rank 1..30" = "$($_)"
"Members 1..30" = "$($res[$_-1].Members)"
"Language 1..30" = "$($res[$_-1].Language)"
"Rank 31..60" = "$($_+30)"
"Members 31..60" = "$($res[$_+30].Members)"
"Language 31..60" = "$($res[$_+30].Language)"
}
}| Format-Table -AutoSize

View file

@ -0,0 +1,20 @@
$response = (New-Object Net.WebClient).DownloadString("http://rosettacode.org/wiki/Category:Programming_Languages")
$languages = [regex]::matches($response,'title="Category:(.*?)">') | foreach {$_.Groups[1].Value}
$response = [Net.WebClient]::new().DownloadString("http://rosettacode.org/w/index.php?title=Special:Categories&limit=5000")
$response = [regex]::Replace($response,'(\d+),(\d+)','$1$2')
$members = [regex]::matches($response,'<li><a[^>]+>([^<]+)</a>[^(]*[(](\d+) member[s]?[)]</li>') | foreach { [pscustomobject]@{
Members = [Int]($_.Groups[2].Value)
Language = [String]($_.Groups[1].Value)
}} | where {$languages.Contains($_.Language)} | sort -Descending Members
Get-Date -UFormat "Sample output on %d %B %Y at %R %Z"
$members | Select-Object -First 10 | foreach -Begin {$r, $rank, $count = 0, 0,-1} {
$r++
if ($count -ne $_.Members) {$rank = $r}
$count = $_.Members
$x = $_.Members.ToString("N0",[System.Globalization.CultureInfo]::CreateSpecificCulture('en-US'))
$entry = "($x entries)"
[String]::Format("Rank: {0,2} {1,15} {2}",$rank,$entry,$_.Language)
}

View file

@ -0,0 +1,40 @@
$languages = @{}
$Body = @{
format = 'json'
action = 'query'
generator = 'categorymembers'
gcmtitle = 'Category:Programming Languages'
gcmlimit = '200'
gcmcontinue = ''
continue = ''
prop = 'categoryinfo'
}
$params = @{
Method = 'Get'
Uri = 'http://rosettacode.org/mw/api.php'
Body = $Body
}
while ($true) {
$response = Invoke-RestMethod @params
$response.query.pages.PSObject.Properties | ForEach-Object {
if (($_.value.PSObject.Properties.Name -Contains 'title') -and ($_.value.PSObject.Properties.Name -Contains 'categoryinfo')) {
$languages[$_.value.title.replace('Category:', '')] = $_.value.categoryinfo.size
}
}
if ($response.PSObject.Properties.Name -Contains 'continue') {
$gcmcontinue = $response.continue.gcmcontinue
$params.Body.gcmcontinue = $gcmcontinue
} else {
break
}
}
$members = $languages.GetEnumerator() | sort -Descending value
Get-Date -UFormat "Sample output on %d %B %Y at %R %Z"
$members | Select-Object -First 10 | foreach -Begin {$r, $rank, $count = 0, 0,-1} {
$r++
if ($count -ne $_.Members) {$rank = $r}
$count = $_.Value
$x = $_.Value.ToString("N0",[System.Globalization.CultureInfo]::CreateSpecificCulture('en-US'))
$entry = "($x entries)"
[String]::Format("Rank: {0,2} {1,15} {2}",$rank, $entry, $_.Name)
}

View file

@ -0,0 +1,128 @@
Procedure handleError(value, msg.s)
If value = 0
MessageRequester("Error", msg)
End
EndIf
EndProcedure
Structure languageInfo
name.s
pageCount.i
EndStructure
#JSON_web_data = 0 ;ID# for our parsed JSON web data object
Define NewList languages.languageInfo()
Define blah.s, object_val, allPages_mem, title_mem, page_mem, categoryInfo_mem, continue_mem
Define url$, title$, currentPage$, language$, langPageCount, gcmcontinue$, *bufferPtr
handleError(InitNetwork(), "Unable to initialize network functions.")
Repeat
url$ = "http://www.rosettacode.org/mw/api.php?action=query" +
"&generator=categorymembers&gcmtitle=Category:Programming%20Languages" +
"&gcmlimit=500" + "&gcmcontinue=" + gcmcontinue$ +
"&prop=categoryinfo&format=json"
*bufferPtr = ReceiveHTTPMemory(url$)
handleError(*bufferPtr, "Unable to receive web page data.")
If CatchJSON(#JSON_web_data, *bufferPtr, MemorySize(*bufferPtr)) = 0
MessageRequester("Error", JSONErrorMessage() + " at position " +
JSONErrorPosition() + " in line " +
JSONErrorLine() + " of JSON web Data")
End
EndIf
FreeMemory(*bufferPtr)
object_val = JSONValue(#JSON_web_data)
allPages_mem = GetJSONMember(GetJSONMember(object_val, "query"), "pages")
If ExamineJSONMembers(allPages_mem)
While NextJSONMember(allPages_mem)
page_mem = JSONMemberValue(allPages_mem)
title_mem = GetJSONMember(page_mem, "title")
If title_mem
title$ = GetJSONString(title_mem)
If Left(title$, 9) = "Category:"
language$ = Mid(title$, 10)
categoryInfo_mem = GetJSONMember(page_mem, "categoryinfo")
If categoryInfo_mem
langPageCount = GetJSONInteger(GetJSONMember(categoryInfo_mem, "pages"))
Else
langPageCount = 0
EndIf
AddElement(languages())
languages()\name = language$
languages()\pageCount = langPageCount
EndIf
EndIf
Wend
EndIf
;check for continue
continue_mem = GetJSONMember(object_val, "continue")
If continue_mem
gcmcontinue$ = GetJSONString(GetJSONMember(continue_mem, "gcmcontinue"))
Else
gcmcontinue$ = ""
EndIf
FreeJSON(#JSON_web_data)
Until gcmcontinue$ = ""
;all data has been aquired, now process and display it
SortStructuredList(languages(), #PB_Sort_Descending, OffsetOf(languageInfo\pageCount), #PB_Integer)
If OpenConsole()
If ListSize(languages())
Define i, *startOfGroupPtr.languageInfo, *lastElementPtr, groupSize, rank
Define outputSize = 100, outputLine
PrintN(Str(ListSize(languages())) + " languages." + #CRLF$)
LastElement(languages())
*lastElementPtr = @languages() ;pointer to last element
FirstElement(languages())
*startOfGroupPtr = @languages() ;pointer to first element
groupSize = 1
rank = 1
While NextElement(languages())
If languages()\pageCount <> *startOfGroupPtr\pageCount Or *lastElementPtr = @languages()
;display a group of languages at the same rank
ChangeCurrentElement(languages(), *startOfGroupPtr)
For i = 1 To groupSize
;display output in groups to allow viewing of all entries
If outputLine = 0
PrintN(" Rank Tasks Language")
PrintN(" ------ ----- --------")
EndIf
PrintN(RSet(Str(rank), 6) + ". " +
RSet(Str(languages()\pageCount), 4) + " " +
languages()\name)
outputLine + 1
If outputLine >= outputSize
Print(#CRLF$ + #CRLF$ + "Press ENTER to continue" + #CRLF$): Input()
outputLine = 0
EndIf
NextElement(languages())
Next
rank + groupSize
groupSize = 1
*startOfGroupPtr = @languages()
Else
groupSize + 1
EndIf
Wend
Else
PrintN("No language categories found.")
EndIf
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()
EndIf

View file

@ -0,0 +1,56 @@
;Uses a web scraping method.
;It is limited to only retrieving 5000 language categories and the counts contain
;some slight inaccuracies.
Structure Language
count.i
Name.s
EndStructure
Dim Row.Language(5000)
Procedure handleError(value, msg.s)
If value = 0
MessageRequester("Error", msg)
End
EndIf
EndProcedure
handleError(InitNetwork(), "Unable to initialize network functions.")
; Lines have been split to fit RC's 80 char preferences
ignore$ = "Basic language learning Encyclopedia Implementations " +
"Language Implementations Language users " +
"Maintenance/OmitCategoriesCreated Programming Languages " +
"Programming Tasks RCTemplates Solutions by Library Solutions by " +
"Programming Language Solutions by Programming Task Unimplemented " +
"tasks by language WikiStubs Examples needing attention " +
"Impl needed"
url$ = "http://www.rosettacode.org/mw/index.php?" +
"title=Special:Categories&limit=5000"
ReceiveHTTPFile(url$, "special.htm")
ReadFile(0, "special.htm", #PB_UTF8)
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_Integer)
OpenConsole()
For i = 0 To 29
PrintN( Str(i + 1) + ". " + Str(Row(i)\count) + " - " + Row(i)\Name)
Next
Input()

View file

@ -0,0 +1,13 @@
import requests
import re
response = requests.get("http://rosettacode.org/wiki/Category:Programming_Languages").text
languages = re.findall('title="Category:(.*?)">',response)[:-3] # strip last 3
response = requests.get("http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000").text
response = re.sub('(\d+),(\d+)',r'\1'+r'\2',response) # strip ',' from popular languages above 999 members
members = re.findall('<li><a[^>]+>([^<]+)</a>[^(]*[(](\\d+) member[s]*[)]</li>',response) # find language and members
for cnt, (language, members) in enumerate(sorted(members, key=lambda x: -int(x[1]))[:15]): # show only top 15 languages
if language in languages:
print("{:4d} {:4d} - {}".format(cnt+1, int(members), language))

View file

@ -0,0 +1,33 @@
import requests
import operator
import re
api_url = 'http://rosettacode.org/mw/api.php'
languages = {}
parameters = {
'format': 'json',
'action': 'query',
'generator': 'categorymembers',
'gcmtitle': 'Category:Programming Languages',
'gcmlimit': '200',
'gcmcontinue': '',
'continue': '',
'prop': 'categoryinfo'
}
while(True):
response = requests.get(api_url, params=parameters).json()
for k,v in response['query']['pages'].items():
if 'title' in v and 'categoryinfo' in v:
languages[v['title']]=v['categoryinfo']['size']
if 'continue' in response:
gcmcontinue = response['continue']['gcmcontinue']
# print(gcmcontinue)
parameters.update({'gcmcontinue': gcmcontinue})
else:
break
# report top 15 languages
for i, (language, size) in enumerate(sorted(languages.items(), key=operator.itemgetter(1), reverse=True)[:15]):
print("{:4d} {:4d} - {}".format(i+1, size, re.sub('Category:','',language))) # strip Category: from language

View file

@ -0,0 +1,21 @@
library(rvest)
library(dplyr)
options(stringsAsFactors=FALSE)
# getting the required table from the rosetta website
langUrl <- "https://rosettacode.org/wiki/Rosetta_Code/Rank_languages_by_popularity/Full_list"
langs <- read_html(langUrl) %>%
html_nodes(xpath='/html/body/div/div/div[1]/div[3]/main/div[2]/div[3]/div[1]/table') %>%
html_table() %>%
data.frame() %>%
select(c("Rank","TaskEntries","Language"))
# changing the columns to required format
langs$Rank = paste("Rank: ",langs$Rank)
langs$TaskEntries = paste0("(", format(langs$TaskEntries, big.mark = ",")
," entries", ")")
names(langs) <- NULL
langs[1:10,]

View file

@ -0,0 +1,112 @@
/*REXX program reads two files and displays a ranked list of Rosetta Code languages.*/
parse arg catFID lanFID outFID . /*obtain optional arguments from the CL*/
call init /*initialize some REXX variables. */
call get /*obtain data from two separate files. */
call eSort #,0 /*sort languages along with members. */
call tSort /* " " that are tied in rank.*/
call eSort #,1 /* " " along with members. */
call out /*create the RC_POP.OUT (output) file.*/
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
commas: parse arg _; do jc=length(_)-3 to 1 by -3; _= insert(",",_,jc); end; return _
s: if arg(1)==1 then return arg(3); return word(arg(2) 's',1) /*pluralizer.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
eSort: procedure expose #. @. !tr.; arg N,p2; h= N /*sort: number of members*/
do while h>1; h= h % 2 /*halve number of records*/
do i=1 for N-h; j= i; k= h + i /*sort this part of list.*/
if p2 then do while !tR.k==!tR.j & @.k>@.j /*this uses a 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 /*this uses a hard swap ↓*/
@= @.j; #= #.j; @.j= @.k; #.j= #.k; @.k= @; #.k= #
if h>=j then leave; j= j - h; k= k - h
end /*while #.k<···*/
end /*i*/ /*hard swaps needed for embedded blanks.*/
end /*while h>1*/; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
get: langs= 0; call rdr 'languages' /*assign languages ───► L.ααα */
call rdr 'categories' /*append categories ───► catHeap */
#= 0
do j=1 until catHeap=='' /*process the heap of categories. */
parse var catHeap cat.j (sep) catHeap /*get a category from the catHeap. */
parse var cat.j cat.j '<' "(" mems . /*untangle the strange─looking string. */
cat.j= space(cat.j); ?=cat.j; upper ? /*remove any superfluous blanks. */
if ?=='' | \L.? then iterate /*it's blank or it's not a language. */
if pos(',', mems)\==0 then mems= space(translate(mems,,","), 0) /*¬commas.*/
if \datatype(mems, 'W') then iterate /*is the "members" number not numeric? */
#.0= #.0 + mems /*bump the number of members found. */
if u.?\==0 then do; do f=1 for # until ?==@u.f
end /*f*/
#.f= #.f + mems; iterate j /*languages in different cases.*/
end /* [↑] handle any possible duplicates.*/
u.?= u.? + 1; #= # + 1 /*bump a couple of counters. */
#.#= #.# + mems; @.#= cat.j; @u.#=? /*bump the counter; assign it (upper).*/
end /*j*/
!.=; @tno= '(total) number of' /*array holds indication of TIED langs.*/
call tell right(commas(#), 9) @tno 'languages detected in the category file'
call tell right(commas(langs),9) ' " " " " " " " language "
call tell right(commas(#.0), 9) @tno 'entries (solutions) detected', , 1; term= 0
return /*don't show any more msgs──►term. [↑] */
/*──────────────────────────────────────────────────────────────────────────────────────*/
init: sep= ''; L.=0; #.=0; u.=#.; catHeap=; term=1; old.= /*assign some REXX vars*/
if catFID=='' then catFID= "RC_POP.CAT" /*Not specified? Then use the default.*/
if lanFID=='' then lanFID= "RC_POP.LAN" /* " " " " " " */
if outFID=='' then outFID= "RC_POP.OUT" /* " " " " " " */
call tell center('timestamp: ' date() time("Civil"),79,''), 2, 1; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
out: w= length( commas(#) ); rank= 0 /* [↓] show by ascending rank of lang.*/
do t=# by -1 for #; rank= rank + 1 /*bump rank of a programming language. */
call tell right('rank:' right(commas(!tR.t), w), 20-1) right(!.t, 7),
right('('commas(#.t) left("entr"s(#.t, 'ies', "y")')', 9), 20) @.t
end /*#*/ /* [↑] S(···) pluralizes a word. */
call tell left('', 27) "☼ end─of─list. ☼", 1, 2; return /*bottom title.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
rdr: arg which 2; igAst= 1 /*ARG uppers WHICH, obtain the 1st char*/
if which=='L' then inFID= lanFID /*use this fileID for the languages. */
if which=='C' then inFID= catFID /* " " " " " categories. */
Uyir= 'α«ëα«»α«α«α»ì/Uyir' /*Unicode (in text) name for Uyir */
old.0= '£C++' ; new.0= "µC++" /*Unicode ╬£C++ ───► ASCII─8: µC++ */
old.1= 'UC++' ; new.1= "µC++" /*old UC++ ───► ASCII─8: µC++ */
old.2= '£Ü-' ; new.2= "MK-" /*Unicode ╨£╨Ü─ ───► ASCII-8: MK- */
old.3= 'Djá' ; new.3= "Déjà" /*Unicode ├⌐j├á ───► ASCII─8: Déjà */
old.4= 'Cach' ; new.4= "Caché" /*Unicode Cach├⌐ ───► ASCII─8: Caché */
old.5= '??-61/52' ; new.5= "MK-61/52" /*somewhere past, a mis─translated: MK-*/
old.6= 'Fìrmulª' ; new.6= 'Fôrmulæ' /*Unicode ───► ASCII─8: Fôrmulæ */
old.7= '£iniZinc' ; new.7= 'MiniZinc' /*Unicode ───► ASCII─8: MiniZinc*/
old.8= Uyir ; new.8= 'Uyir' /*Unicode ───► ASCII─8: Uyir */
old.9= 'Perl 6' ; new.9= 'Raku' /* (old name) ───► (new name) */
do recs=0 while lines(inFID) \== 0 /*read a file, a single line at a time.*/
$= translate( linein(inFID), , '9'x) /*handle any stray TAB ('09'x) chars.*/
$$= space($); if $$=='' then iterate /*ignore all blank lines in the file(s)*/
do v=0 while old.v \== '' /*translate Unicode variations of langs*/
if pos(old.v, $$) \==0 then $$= changestr(old.v, $$, new.v)
end /*v*/ /* [↑] handle different lang spellings*/
if igAst then do; igAst= pos(' * ', $)==0; if igAst then iterate; end
if pos('RETRIEVED FROM', translate($$))\==0 then leave /*pseudo End─Of─Data?.*/
if which=='L' then do; if left($$, 1)\=="*" then iterate /*lang ¬legitimate?*/
parse upper var $$ '*' $$ "<"; $$= space($$)
if $$=='' then iterate; L.$$= 1
langs= langs + 1 /*bump number of languages found. */
iterate
end /* [↓] extract computer language name.*/
if left($$, 1)=='*' then $$= sep || space( substr($$, 2) )
catHeap= catHeap $$ /*append to the catHeap (CATegory) heap*/
end /*recs*/
call tell right( commas(recs), 9) 'records read from file: ' inFID
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
tell: do '0'arg(2); call lineout outFID," " ; if term then say ; end
call lineout outFID,arg(1) ; if term then say arg(1)
do '0'arg(3); call lineout outFID," " ; if term then say ; end
return /*show BEFORE blank lines (if any), message, show AFTER blank lines.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
tSort: tied=; r= 0 /*add true rank (tR) ───► the entries. */
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 when language 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*/; return

View file

@ -0,0 +1,43 @@
#lang racket
(require racket/hash
net/url
json)
(define limit 15)
(define (replacer cat) (regexp-replace #rx"^Category:(.*?)$" cat "\\1"))
(define category "Category:Programming Languages")
(define entries "entries")
(define api-url (string->url "http://rosettacode.org/mw/api.php"))
(define (make-complete-url gcmcontinue)
(struct-copy url api-url
[query `([format . "json"]
[action . "query"]
[generator . "categorymembers"]
[gcmtitle . ,category]
[gcmlimit . "200"]
[gcmcontinue . ,gcmcontinue]
[continue . ""]
[prop . "categoryinfo"])]))
(define @ hash-ref)
(define table (make-hash))
(let loop ([gcmcontinue ""])
(define resp (read-json (get-pure-port (make-complete-url gcmcontinue))))
(hash-union! table
(for/hash ([(k v) (in-hash (@ (@ resp 'query) 'pages))])
(values (@ v 'title #f) (@ (@ v 'categoryinfo (hash)) 'size 0))))
(cond [(@ resp 'continue #f) => (λ (c) (loop (@ c 'gcmcontinue)))]))
(for/fold ([prev #f] [rank #f] #:result (void))
([item (in-list (sort (hash->list table) > #:key cdr))] [i (in-range limit)])
(match-define (cons cat size) item)
(define this-rank (if (equal? prev size) rank (add1 i)))
(printf "Rank: ~a ~a ~a\n"
(~a this-rank #:align 'right #:min-width 2)
(~a (format "(~a ~a)" size entries) #:align 'right #:min-width 14)
(replacer cat))
(values size this-rank))

View file

@ -0,0 +1,99 @@
use HTTP::UserAgent;
use URI::Escape;
use JSON::Fast;
use Sort::Naturally;
my $client = HTTP::UserAgent.new;
my $url = 'https://rosettacode.org/w';
my $tablefile = './RC_Popularity.txt';
my %cat = (
'Programming_Tasks' => 'Task',
'Draft_Programming_Tasks' => 'Draft'
);
my %tasks;
for %cat.keys.sort -> $cat {
mediawiki-query(
$url, 'pages',
:generator<categorymembers>,
:gcmtitle("Category:$cat"),
:gcmlimit<350>,
:rawcontinue(),
:prop<title>
).map({ %tasks{%cat{$cat}}++ });
}
my %counts =
mediawiki-query(
$url, 'pages',
:generator<categorymembers>,
:gcmtitle<Category:Programming Languages>,
:gcmlimit<350>,
:rawcontinue(),
:prop<categoryinfo>
)
.map({
my $title = .<title>.subst(/^'Category:'/, '');
my $tasks = (.<categoryinfo><pages> || 0);
my $categories = (.<categoryinfo><subcats> || 0);
my $total = (.<categoryinfo><size> || 0);
$title => [$tasks ,$categories, $total]
});
my $out = open($tablefile, :w) or die "$!\n";
# Add table boilerplate and header
$out.say:
"\{|class=\"wikitable sortable\"\n",
"|+ As of { Date.today } :: {+%counts} Languages\n",
'!Rank!!Language!!Task<br>Entries!!Tasks<br>done %!!Non-task<br>Subcate-<br>gories!!Total<br>Categories'
;
my @bg = <#fff; #ccc;>;
my $ff = 0;
my $rank = 1;
my $ties = 0;
# Get sorted unique task counts
for %counts.values»[0].unique.sort: -* -> $count {
$ff++;
# Get list of tasks with this count
my @these = %counts.grep( *.value[0] == $count )».keys.sort: *.&naturally;
for @these {
$ties++;
$out.say:
"|- style=\"background-color: { @bg[$ff % 2] }\"\n"~
"|$rank\n"~
"|[[:Category:$_|]]\n"~
"|$count\n"~
"|{(100 * $count/%tasks<Draft Task>.sum).round(.01)} %\n"~
"|{%counts{$_}[1]}\n"~
"|{%counts{$_}[2]}"
}
$rank += $ties;
$ties = 0;
}
$out.say( "|}" );
$out.say('=' x 5, " query, download & processing: {(now - INIT now).round(.01)} seconds ", '=' x 5);
$out.close;
sub mediawiki-query ($site, $type, *%query) {
my $url = "$site/api.php?" ~ uri-query-string(
:action<query>, :format<json>, :formatversion<2>, |%query);
my $continue = '';
gather loop {
my $response = $client.get("$url&$continue");
my $data = from-json($response.content);
take $_ for $data.<query>.{$type}.values;
$continue = uri-query-string |($data.<query-continue>{*}».hash.hash or last);
}
}
sub uri-query-string (*%fields) {
join '&', %fields.map: { "{.key}={uri-escape .value}" }
}

View file

@ -0,0 +1,22 @@
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.subst(',', ''), ~$0] if
/ '<li><a href="/wiki/Category:' .*? '" title="Category:' .*? '">'
(.*?) <?{ ~$0 languages }>
'</a>' .*? '(' (<[, 0..9]>+) ' member' /;
}
for @results.kv -> $i, @l {
printf "%d:\t%4d - %s\n", $i+1, |@l;
}

View file

@ -0,0 +1,51 @@
Red []
data: read http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000
lb: make block! 500
;;data: read %data.html ;; for testing save html and use flat file
arr: split data newline
k: "Category:"
;; exclude list:
exrule: [thru ["programming"
| "users"
| "Implementations"
| "Solutions by "
| "Members"
| "WikipediaSourced"
| "Typing/Strong"
| "Impl needed"
]
to end
]
foreach line arr [
unless find line k [continue]
parse line [ thru k thru ">" copy lang to "<" to end ] ;; extract/parse language
if 20 < length? lang [continue]
if parse lang [exrule] [continue] ;; exclude invalid
cnt: 0
;; parse number of entries
parse line [thru "</a>" thru "(" copy cnt to " member" (cnt: to-integer cnt ) to end]
if cnt > 25 [ append lb reduce [to-string lang cnt] ] ;; only process lang with > 25 entries
]
lb: sort/skip/compare lb 2 2 ;; sort series by entries
print reduce [ "Rank Entries Language" ] ;; header
last: 0
rank: 0
lb: tail lb ;; process the series backwards
until [
lb: skip lb -2
cnt: second lb
if cnt <> last [
rank: rank + 1
]
print rejoin [ pad/left rank 4 "." pad/left cnt 5 " - " first lb ]
last: cnt
head? lb ;; until head reached
]

View file

@ -0,0 +1,86 @@
# Project: Rosetta Code/Rank languages by popularity
load "stdlib.ring"
ros= download("http://rosettacode.org/wiki/Category:Programming_Languages")
pos = 1
totalros = 0
rosname = ""
rosnameold = ""
rostitle = ""
roslist = []
for n = 1 to len(ros)
nr = searchstring(ros,'<li><a href="/wiki/',pos)
if nr = 0
exit
else
pos = nr + 1
ok
nr = searchname(nr)
nr = searchtitle(nr)
next
roslist = sortfirst(roslist)
roslist = reverse(roslist)
see nl
for n = 1 to len(roslist)
see "rank: " + n + " (" + roslist[n][1] + " entries) " + roslist[n][2] + nl
next
func searchstring(str,substr,n)
newstr=right(str,len(str)-n+1)
nr = substr(newstr, substr)
if nr = 0
return 0
else
return n + nr -1
ok
func count(cstring,dstring)
sum = 0
while substr(cstring,dstring) > 0
sum = sum + 1
cstring = substr(cstring,substr(cstring,dstring)+len(string(sum)))
end
return sum
func searchname(sn)
nr2 = searchstring(ros,"/wiki/Category:",sn)
nr3 = searchstring(ros,"title=",sn)
nr4 = searchstring(ros,'">',sn)
nr5 = searchstring(ros,"</a></li>",sn)
rosname = substr(ros,nr2+15,nr3-nr2-17)
rosnameold = substr(ros,nr4+2,nr5-nr4-2)
return sn
func searchtitle(sn)
rostitle = "rosettacode.org/wiki/Category:" + rosname
rostitle = download(rostitle)
nr2 = 0
roscount = count(rostitle,"The following")
if roscount > 0
rp = 1
for rc = 1 to roscount
nr2 = searchstring(rostitle,"The following",rp)
rp = nr2 + 1
next
ok
nr3 = searchstring(rostitle,"pages are in this category",nr2)
if nr2 > 0 and nr3 > 0
rosnr = substr(rostitle,nr2+14,nr3-nr2-15)
rosnr = substr(rosnr,",","")
add(roslist,[rosnr,rosnameold])
ok
return sn
func sortfirst(alist)
for n = 1 to len(alist) - 1
for m = n + 1 to len(alist)
if alist[m][1] < alist[n][1]
swap(alist,m,n)
ok
if alist[m][1] = alist[n][1] and strcmp(alist[m][2],alist[n][2]) > 0
swap(alist,m,n)
ok
next
next
return alist

View file

@ -0,0 +1,30 @@
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

View file

@ -0,0 +1,28 @@
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>"

View file

@ -0,0 +1,30 @@
-include "url.sno"
http.recl = "K,32767" ;* Read next 32767 characters
;* of very long lines.
rclangs = "http://rosettacode.org/mw/api.php?"
+ "format=xml&action=query&generator=categorymembers&"
+ "gcmtitle=Category:Programming%20Languages&"
+ "gcmlimit=500&prop=categoryinfo"
languagepat = arb "<page" arb 'title="Category:'
+ break('"') . lang arb 'pages="' break('"') . count
langtable = table(500, 20)
url.open(.fin, rclangs, http.recl) :s(read)
output = "Cannot open rosettacode site." :(end)
read line = line fin :f(done)
get line languagepat = :f(read)
langtable<syntaxhighlight lang="text"> = langtable<syntaxhighlight lang="text"> + count :(get)
done langarray = rsort(langtable,2) :s(write)
output = "No languages found." :(end)
write n = n + 1
output = lpad(n ". ", 5) lpad(langarray<n, 2>, 4)
+ " - " langarray<n,1> :s(write)
url.close(.fin)
end

View file

@ -0,0 +1,145 @@
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...")
def getLangs(first: Boolean = true, continue: String = ""): TreeSet[String] = (first, continue) match {
case (false, "") => TreeSet[String]()
case _ => {
val xml = XML.load(convertPathArgsToURL(endPoint, Map(
"action" -> "query",
"list" -> "categorymembers",
"cmtitle" -> (prefix + "Programming_Languages"),
"cmlimit" -> "500",
"rawcontinue" -> "",
"format" -> "xml",
"cmcontinue" -> continue)))
getLangs(false, (xml \\ "query-continue" \ "categorymembers" \ "@cmcontinue").text) ++ (xml \\ "categorymembers" \ "cm").map(c => (c \ "@title").text)
}
}
val languages = getLangs()
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.contains(cato._1)
} yield (cato._1.drop(prefix.length), 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, langs), rank) =>
println(f"${rank + 1}%2d. $score%3d - ${langs.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
}
} // object Concurrent
trait AppCommons {
val execStart = 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])
}

View file

@ -0,0 +1,58 @@
$ 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;

View file

@ -0,0 +1,37 @@
require('MediaWiki::API')
var api = %O<MediaWiki::API>.new(
Hash(api_url => 'http://rosettacode.org/mw/api.php')
)
var languages = []
var gcmcontinue
loop {
var apih = api.api(
Hash(
action => 'query',
generator => 'categorymembers',
gcmtitle => 'Category:Programming Languages',
gcmlimit => 250,
prop => 'categoryinfo',
gcmcontinue => gcmcontinue,
)
)
languages.append(apih{:query}{:pages}.values...)
gcmcontinue = apih{:continue}{:gcmcontinue}
gcmcontinue || break
}
languages.each { |lang|
lang{:title} -= /^Category:/
lang{:categoryinfo}{:size} := 0
}
var sorted_languages = languages.sort_by { |lang|
-lang{:categoryinfo}{:size}
}
sorted_languages.each_kv { |i, lang|
printf("%3d. %20s - %3d\n", i+1, lang{:title}, lang{:categoryinfo}{:size})
}

View file

@ -0,0 +1,35 @@
copy "http://rosettacode.org/wiki/Category:Programming_Languages" lang.html, replace
import delimited lang.html, delim("@") enc("utf-8") clear
keep if ustrpos(v1,"/wiki/Category:")
gen i = ustrpos(v1,"title=")
gen j = ustrpos(v1,char(34),i+1)
gen k = ustrpos(v1,char(34),j+1)
gen s = usubstr(v1,j,k-j+1)
keep if usubstr(s,2,9)=="Category:"
gen lang=usubstr(s,11,ustrlen(s)-11)
keep lang
save lang, replace
copy "http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000" categ.html, replace
import delimited categ.html, delim("@") enc("utf-8") clear
keep if ustrpos(v1,"/wiki/Category:") & ustrpos(v1,"member")
gen i = ustrpos(v1,"title=")
gen j = ustrpos(v1,char(34),i+1)
gen k = ustrpos(v1,char(34),j+1)
gen s = usubstr(v1,j,k-j+1)
keep if usubstr(s,2,9)=="Category:"
gen lang=usubstr(s,11,ustrlen(s)-11)
drop i j k s
gen i = ustrrpos(v1,"(")
gen j = ustrrpos(v1,")")
gen s = usubstr(v1,i,j-i+1)
gen k = ustrpos(s," ")
gen t = usubstr(s,2,k-1)
destring t, gen(count)
drop v1 i j k s t
merge 1:1 lang using lang, keep(2 3) nogen
replace count=0 if missing(count)
gsort -count lang
gen rank=1
replace rank=rank[_n-1]+(count[_n]!=count[_n-1]) in 2/l
save tasks, replace

View file

@ -0,0 +1,31 @@
* Total number of entries
qui sum n
di r(sum)
57211
* Number of languages
count
671
* Number of languages with at least one entry
count if count
650
* First 10 languages
list in 1/10, noobs
+-----------------------+
| lang count rank |
|-----------------------|
| Racket 961 1 |
| Python 958 2 |
| Perl 6 925 3 |
| Tcl 918 4 |
| J 883 5 |
|-----------------------|
| C 874 6 |
| Kotlin 868 7 |
| Zkl 857 8 |
| Ruby 845 9 |
| Go 828 10 |
+-----------------------+

View file

@ -0,0 +1,49 @@
$$ 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

View file

@ -0,0 +1,40 @@
package require Tcl 8.5
package require http
set response [http::geturl http://rosettacode.org/mw/index.php?title=Special:Categories&limit=8000]
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
}
# need substring filter
proc filterLang {n} {
return [expr {[string first "User" $n] > 0}]
}
# (sorry the 1 double quote in the regexp kills highlighting)
foreach line [split [http::data $response] \n] {
if {[regexp {title..Category:([^"]+).* \((\d+) members\)} $line -> lang num]} {
if {![info exists ignore($lang)] && ![filterLang $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]
}

View file

@ -0,0 +1,110 @@
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 20} { ;# limit fetch to 20 at a time
dict set query titles [join [lrange $cats $n $n+19] |]
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 "Programming Languages" lang {
lappend langs $lang
}
puts stderr "" ;# Because of the progress dots...
puts "There are [llength $langs] languages"
# Get the count of solutions for each, stripping "Category:" prefix
rc count $langs l c {
dict set langcounts [regsub {^Category:} $l {}] $c
}
puts stderr "" ;# Because of the progress dots...
# Print the output
puts "Here are the top fifteen:"
set langcounts [lsort -stride 2 -index 1 -integer -decreasing $langcounts]
set i 0
foreach {lang count} $langcounts {
puts [format "%1\$3d. %3\$3d - %2\$s" [incr n] $lang $count]
if {[incr i]>=15} break
}
# --- generate a full report, similar in format to REXX example
proc popreport {langcounts} {
set bycount {}
foreach {lang count} $langcounts {
dict lappend bycount $count $lang
}
set bycount [lsort -stride 2 -integer -decreasing $bycount]
set rank 1
foreach {count langs} $bycount {
set tied [expr {[llength $langs] > 1 ? "\[tied\]" : ""}]
foreach lang $langs {
puts [format {%15s:%4d %-12s %12s %s} rank $rank $tied "($count entries)" $lang]
}
incr rank [llength $langs]
}
}
popreport $langcounts

View file

@ -0,0 +1,3 @@
curl 'http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000' |
sed -nre 's/^<li.*title="Category:([^"(]+)".*\(([0-9]+) members\).*/\2 - \1/p' |
sort -nr | awk '{printf "%2d. %s\n",NR,$0}'

View file

@ -0,0 +1,118 @@
'''''''''''''''''''''''''''''''''''''''''''''
' Rosetta Code/Rank Languages by Popularity '
' VBScript Implementation '
'...........................................'
'API Links (From C Code)
URL1 = "http://www.rosettacode.org/mw/api.php?format=json&action=query&generator=categorymembers&gcmtitle=Category:Programming%20Languages&gcmlimit=500&prop=categoryinfo&rawcontinue"
URL2 = "http://www.rosettacode.org/mw/api.php?format=json&action=query&generator=categorymembers&gcmtitle=Category:Programming%20Languages&gcmlimit=500&prop=categoryinfo&gcmcontinue="
'Get Contents of the API from the Web...
Function ScrapeGoat(link)
On Error Resume Next
ScrapeGoat = ""
Err.Clear
Set objHttp = CreateObject("Msxml2.ServerXMLHTTP")
objHttp.Open "GET", link, False
objHttp.Send
If objHttp.Status = 200 And Err = 0 Then ScrapeGoat = objHttp.ResponseText
Set objHttp = Nothing
End Function
'HACK: Setup HTML for help of my partner/competitor that is better than me, JavaScript...
Set HTML = CreateObject("HtmlFile")
Set HTMLWindow = HTML.ParentWindow
''''''''''''''''''''
' Main code begins '
'..................'
On Error Resume Next
isComplete = 0 ' 1 -> Complete Already
cntLoop = 0 ' Counts Number of Loops Done
Set outputData = CreateObject("Scripting.Dictionary")
Do
'Scrape Data From API
If cntLoop = 0 Then strData = ScrapeGoat(URL1) Else strData = ScrapeGoat(URL2 & gcmCont)
If Len(strData) = 0 Then
Set HTML = Nothing
WScript.StdErr.WriteLine "Processing of data stopped because API query failed."
WScript.Quit(1)
End If
'Parse JSON HACK
HTMLWindow.ExecScript "var json = " & strData, "JavaScript"
Set ObjJS = HTMLWindow.json
Err.Clear 'Test if Query is Complete Already
batchCompl = ObjJS.BatchComplete
If Err.Number = 438 Then
'Query not yet complete. Get gcmContinue instead.
gcmCont = ObjJS.[Query-Continue].CategoryMembers.gcmContinue
Else
isComplete = 1 'Yes!
End If
'HACK #2: Put all language page ids into a JS array to be accessed by VBScript
HTMLWindow.ExecScript "var langs=new Array(); for(var lang in json.query.pages){langs.push(lang);}" & _
"var nums=langs.length;", "JavaScript"
Set arrLangs = HTMLWindow.langs
arrLength = HTMLWindow.nums
For i = 0 to arrLength - 1
BuffStr = "ObjJS.Query.Pages.[" & Eval("arrLangs.[" & i & "]") & "]"
EachStr = Eval(BuffStr & ".title")
Err.Clear
CntLang = Eval(BuffStr & ".CategoryInfo.Pages")
If InStr(EachStr, "Category:") = 1 And Err.Number = 0 Then
outputData.Add Replace(EachStr, "Category:", "", 1, 1), CntLang
End If
Next
cntLoop = cntLoop + 1
Loop While isComplete = 0
'The outputData now contains the data we need. We should now sort and print it!
'Make a 2D array with copy of outputData
arrRelease = Array()
ReDim arrRelease(UBound(outputData.Keys), 1)
outKeys = outputData.Keys
outItem = outputData.Items
For i = 0 To UBound(outKeys)
arrRelease(i, 0) = outKeys(i)
arrRelease(i, 1) = outItem(i)
Next
'Bubble Sort (Greatest to Least Number of Examples)
For i = 0 to UBound(arrRelease, 1)
For j = 0 to UBound(arrRelease, 1) - 1
If arrRelease(j, 1) < arrRelease(j + 1, 1) Then
temp1 = arrRelease(j + 1, 0)
temp2 = arrRelease(j + 1, 1)
arrRelease(j + 1, 0) = arrRelease(j, 0)
arrRelease(j + 1, 1) = arrRelease(j, 1)
arrRelease(j, 0) = temp1
arrRelease(j, 1) = temp2
End If
Next
Next
'Save contents to file instead to support Unicode Names
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set txtOut = objFSO.CreateTextFile(".\OutVBRC.txt", True, True)
txtOut.WriteLine "As of " & Now & ", RC has " & UBound(arrRelease) + 1 & " languages."
txtOut.WriteLine ""
For i = 0 to UBound(arrRelease)
txtOut.WriteLine arrRelease(i, 1) & " Examples - " & arrRelease(i, 0)
Next
'Successfully Done :)
Set HTML = Nothing
Set objFSO = Nothing
WScript.Quit(0)

View file

@ -0,0 +1,78 @@
/* rc_rank_languages_by_popularity.wren */
import "./pattern" for Pattern
import "./fmt" for Fmt
var CURLOPT_URL = 10002
var CURLOPT_FOLLOWLOCATION = 52
var CURLOPT_WRITEFUNCTION = 20011
var CURLOPT_WRITEDATA = 10001
foreign class Buffer {
construct new() {} // C will allocate buffer of a suitable size
foreign value // returns buffer contents as a string
}
foreign class Curl {
construct easyInit() {}
foreign easySetOpt(opt, param)
foreign easyPerform()
foreign easyCleanup()
}
var curl = Curl.easyInit()
var getContent = Fn.new { |url|
var buffer = Buffer.new()
curl.easySetOpt(CURLOPT_URL, url)
curl.easySetOpt(CURLOPT_FOLLOWLOCATION, 1)
curl.easySetOpt(CURLOPT_WRITEFUNCTION, 0) // write function to be supplied by C
curl.easySetOpt(CURLOPT_WRITEDATA, buffer)
curl.easyPerform()
return buffer.value
}
var p1 = Pattern.new("> <a href/=\"//wiki//Category:+1^\"\" title/=\"Category:[+1^\"]\">+1^,, [+1^ ] page")
var p2 = Pattern.new("subcatfrom/=[+1^#/#mw-subcategories]\"")
var findLangs = Fn.new {
var url = "https://rosettacode.org/w/index.php?title=Category:Programming_Languages"
var subcatfrom = ""
var langs = []
while (true) {
var content = getContent.call(url + subcatfrom)
var matches1 = p1.findAll(content)
for (m in matches1) {
var name = m.capsText[0]
var tasks = Num.fromString(m.capsText[1].replace(",", ""))
langs.add([name, tasks])
}
var m2 = p2.find(content)
if (m2) subcatfrom = "&subcatfrom=%(m2.capsText[0])" else break
}
return langs
}
var langs = findLangs.call()
langs.sort { |a, b| a[1] > b[1] }
System.print("Languages with most examples as at 11 September, 2022:")
var rank = 0
var lastScore = 0
var lastRank = 0
for (i in 0...langs.count) {
var pair = langs[i]
var eq = " "
rank = i + 1
if (lastScore == pair[1]) {
eq = "="
rank = lastRank
} else {
lastScore = pair[1]
lastRank = rank
}
Fmt.print("$-3d$s $-20s $,5d", rank, eq, pair[0], pair[1])
}

View file

@ -0,0 +1,191 @@
/* gcc rc_rank_languages_by_popularity.c -o rc_rank_languages_by_popularity -lcurl -lwren -lm */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include "wren.h"
struct MemoryStruct {
char *memory;
size_t size;
};
/* C <=> Wren interface functions */
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
char *ptr = realloc(mem->memory, mem->size + realsize + 1);
if(!ptr) {
/* out of memory! */
printf("not enough memory (realloc returned NULL)\n");
return 0;
}
mem->memory = ptr;
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
void C_bufferAllocate(WrenVM* vm) {
struct MemoryStruct *ms = (struct MemoryStruct *)wrenSetSlotNewForeign(vm, 0, 0, sizeof(struct MemoryStruct));
ms->memory = malloc(1);
ms->size = 0;
}
void C_bufferFinalize(void* data) {
struct MemoryStruct *ms = (struct MemoryStruct *)data;
free(ms->memory);
}
void C_curlAllocate(WrenVM* vm) {
CURL** pcurl = (CURL**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(CURL*));
*pcurl = curl_easy_init();
}
void C_value(WrenVM* vm) {
struct MemoryStruct *ms = (struct MemoryStruct *)wrenGetSlotForeign(vm, 0);
wrenSetSlotString(vm, 0, ms->memory);
}
void C_easyPerform(WrenVM* vm) {
CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
curl_easy_perform(curl);
}
void C_easyCleanup(WrenVM* vm) {
CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
curl_easy_cleanup(curl);
}
void C_easySetOpt(WrenVM* vm) {
CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
CURLoption opt = (CURLoption)wrenGetSlotDouble(vm, 1);
if (opt < 10000) {
long lparam = (long)wrenGetSlotDouble(vm, 2);
curl_easy_setopt(curl, opt, lparam);
} else if (opt < 20000) {
if (opt == CURLOPT_WRITEDATA) {
struct MemoryStruct *ms = (struct MemoryStruct *)wrenGetSlotForeign(vm, 2);
curl_easy_setopt(curl, opt, (void *)ms);
} else if (opt == CURLOPT_URL) {
const char *url = wrenGetSlotString(vm, 2);
curl_easy_setopt(curl, opt, url);
}
} else if (opt < 30000) {
if (opt == CURLOPT_WRITEFUNCTION) {
curl_easy_setopt(curl, opt, &WriteMemoryCallback);
}
}
}
WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {
WrenForeignClassMethods methods;
methods.allocate = NULL;
methods.finalize = NULL;
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Buffer") == 0) {
methods.allocate = C_bufferAllocate;
methods.finalize = C_bufferFinalize;
} else if (strcmp(className, "Curl") == 0) {
methods.allocate = C_curlAllocate;
}
}
return methods;
}
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Buffer") == 0) {
if (!isStatic && strcmp(signature, "value") == 0) return C_value;
} else if (strcmp(className, "Curl") == 0) {
if (!isStatic && strcmp(signature, "easySetOpt(_,_)") == 0) return C_easySetOpt;
if (!isStatic && strcmp(signature, "easyPerform()") == 0) return C_easyPerform;
if (!isStatic && strcmp(signature, "easyCleanup()") == 0) return C_easyCleanup;
}
}
return NULL;
}
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}
static void loadModuleComplete(WrenVM* vm, const char* module, WrenLoadModuleResult result) {
if( result.source) free((void*)result.source);
}
WrenLoadModuleResult loadModule(WrenVM* vm, const char* name) {
WrenLoadModuleResult result = {0};
if (strcmp(name, "random") != 0 && strcmp(name, "meta") != 0) {
result.onComplete = loadModuleComplete;
char fullName[strlen(name) + 6];
strcpy(fullName, name);
strcat(fullName, ".wren");
result.source = readFile(fullName);
}
return result;
}
int main(int argc, char **argv) {
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignClassFn = &bindForeignClass;
config.bindForeignMethodFn = &bindForeignMethod;
config.loadModuleFn = &loadModule;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "rc_rank_languages_by_popularity.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}

View file

@ -0,0 +1,38 @@
var [const] CURL=Import("zklCurl"), YAJL=Import("zklYAJL")[0];
fcn getLangCounts(language){ // -->( (count,lang), ...)
continueValue,tasks,curl := "",List(), CURL(); // "nm\0nm\0...."
do{ // eg 5 times
page:=curl.get(("http://rosettacode.org/mw/api.php?"
"format=json"
"&action=query"
"&generator=categorymembers"
"&gcmtitle=Category:Programming%%20Languages"
"&gcmlimit=500"
"&prop=categoryinfo"
"&rawcontinue" // remove warning
"&gcmcontinue=%s")
.fmt(continueValue));
page=page[0].del(0,page[1]); // get rid of HTML header
json:=YAJL().write(page).close();
json["query"]["pages"].howza(9).pump(tasks,fcn(d){ #dictionary values,only
// { title:Category:AWK,categoryinfo:{ pages:398,size:401,... },... }
// Gotta take care of no categoryinfo case
count:=d.find("categoryinfo",Dictionary).find("size",0); // or pages?
if(count<300) return(Void.Skip); // prune
T(count,d["title"].del(0,9)); // "Category:RPL" --> "RPL"
});
if(continueValue=json.find("query-continue"))
// subcat|524558580a52455858|4331 or void
continueValue=continueValue["categorymembers"]["gcmcontinue"];
}while(continueValue);
tasks
}
langCounts:=getLangCounts() .sort(fcn(a,b){ a[0]>b[0] }); // reverse sort
println("Most popular Rosetta Code languages as of ",Time.Date.prettyDay());
foreach n,name in ([1..15].zip(langCounts))
{ println("%2d: %3d %s".fmt(n,name.xplode())) }