⚠️ Warning: This is a draft ⚠️
This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.
If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.
[[Category:Networking and Web Interaction]] [[Category:Sorting]] [[Category:Rosetta Code related]]
{{task|Text processing}}
;Task: Sort the most popular computer programming languages based in number of members in Rosetta Code categories.
Sample output on 9 October 2019 at 15:31 +02:
Rank: 1 (1,183 entries) Go
Rank: 2 (1,121 entries) Phix
Rank: 3 (1,111 entries) Perl 6
Rank: 4 (1,108 entries) Julia
Rank: 5 (1,093 entries) Python
Rank: 6 (1,062 entries) Perl
Rank: 7 (1,057 entries) Kotlin
Rank: 8 (1,046 entries) Racket
Rank: 9 (971 entries) C
Rank: 10 (964 entries) Zkl
...
;Notes:
- Each language typically demonstrates one or two methods of accessing the data: :::* with web scraping (via http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000) :::* with the API method (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).
- The scraping and API solutions can be separate subsections, see the [[Rosetta Code/Rank languages by popularity#Tcl|Tcl example]].
- Filtering wrong results is optional. 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''.
- A complete ranked listing of all '''727''' languages (from the REXX example) is included here ──► [[RC_POP.OUT]].
Ada
{{libheader|AWS}}
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Ordered_Sets;
with Ada.Strings.Less_Case_Insensitive;
with AWS.Client;
with AWS.Response;
procedure Test is
use Ada.Strings;
function "+" (S : String) return Unbounded_String renames To_Unbounded_String;
type A_Language_Count is
record
Count : Integer := 0;
Language : Unbounded_String;
end record;
function "=" (L, R : A_Language_Count) return Boolean is
begin
return L.Language = R.Language;
end "=";
function "<" (L, R : A_Language_Count) return Boolean is
begin
-- Sort by 'Count' and then by Language name
return L.Count < R.Count
or else (L.Count = R.Count
and then Less_Case_Insensitive (Left => To_String (L.Language),
Right => To_String (R.Language)));
end "<";
package Sets is new Ada.Containers.Ordered_Sets (A_Language_Count);
use Sets;
Counts : Set;
procedure Find_Counts (S : String) is
Title_Str : constant String := "title=""Category:";
End_A_Str : constant String := "</a> (";
Title_At : constant Natural := Index (S, Title_Str);
begin
if Title_At /= 0 then
declare
Bracket_At : constant Natural := Index (S (Title_At + Title_Str'Length .. S'Last), ">");
End_A_At : constant Natural := Index (S (Bracket_At + 1 .. S'Last), End_A_Str);
Space_At : constant Natural := Index (S (End_A_At + End_A_Str'Length .. S'Last), " ");
Count : constant Natural := Natural'Value (S (End_A_At + End_A_Str'Length .. Space_At - 1));
Language : constant String := S (Title_At + Title_Str'Length .. Bracket_At - 2);
begin
if Bracket_At /= 0 and then End_A_At /= 0 and then Space_At /= 0 then
begin
Counts.Insert (New_Item => (Count, +Language));
exception
when Constraint_Error =>
Put_Line (Standard_Error, "Warning: repeated language: " & Language);
-- Ignore repeated results.
null;
end;
end if;
-- Recursively parse the string for languages and counts
Find_Counts (S (Space_At + 1 .. S'Last));
end;
end if;
end Find_Counts;
Place : Natural := 1;
procedure Display (C : Cursor) is
begin
Put (Place, Width => 1); Put (". ");
Put (Element (C).Count, Width => 1); Put (" - ");
Put_Line (To_String (Element (C).Language));
Place := Place + 1;
end Display;
Http_Source : constant AWS.Response.Data :=
AWS.Client.Get ("http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000");
begin
Find_Counts (AWS.Response.Message_Body (Http_Source));
Counts.Reverse_Iterate (Display'Access);
end Test;
ALGOL 68
ALGOL68: using web scraping
{{works with|ALGOL 68G|mk8+ for Unix and Linux - tested with release mk15-0.8b.fc9.i386 - uses non-standard library routines ''http content'' and'' grep in string''.}}
Note: the routine ''http content'' is currently not available on Win32 systems.
{{incorrect|ALGOL 68| ---among others, Tcl (the top dog) is missing. }}
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
{{out|Sample output}}
1. 233 - Python
2. 222 - Ada
3. 203 - OCaml
4. 203 - C
5. 201 - Perl
6. 193 - Haskell
7. 182 - Java
8. 179 - D
9. 178 - ALGOL 68
10. 160 - Ruby
ALGOL 68:using the API
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
{{out|Sample output top 10}}
572 languages
rank: 1 (883 entries) Tcl
rank: 2 (875 entries) Racket
rank: 3 (837 entries) Python
rank: 4 (800 entries) J
rank: 5 (772 entries) Ruby
rank: 6 (763 entries) Perl 6
rank: 7 (756 entries) C
rank: 8 (742 entries) Go
rank: 9 (737 entries) D
rank: 10 (707 entries) Perl
AutoHotkey
MembsUrl = http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000
ValidUrl = http://rosettacode.org/wiki/Category:Programming_Languages
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
; Get the webpages
WebRequest.Open("GET", MembsUrl),WebRequest.Send()
MembsPage := WebRequest.ResponseText
WebRequest.Open("GET", ValidUrl),WebRequest.Send()
ValidPage := WebRequest.ResponseText
; Replace special characters
StringReplace, MembsPage, MembsPage, ΜC++, µC++, All
StringReplace, MembsPage, MembsPage, MK-61/52, MK-61/52, All
StringReplace, ValidPage, ValidPage, ΜC++, µC++, All
StringReplace, ValidPage, ValidPage, MK-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
AWK
{{works with|Gawk}}
By using the API
This is the third solution. The [http://rosettacode.org/mw/index.php?title=Rosetta_Code/Rank_languages_by_popularity&oldid=102962#AWK first solution] used web scraping with an external program '''ns''' for networking. The [http://rosettacode.org/mw/index.php?title=Rosetta_Code/Rank_languages_by_popularity&oldid=204081 second solution] used the Rosetta Code API instead of web scraping, but continued use of '''ns''' which for unknown reasons didn't work correctly. This solution uses native gawk networking to connect to the API at 500 items per request ("gmcontinue").
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]
}
{{out|Output from 26 May 2015}}
1. Tcl - 867
2. Racket - 863
3. Python - 828
4. J - 777
5. Ruby - 769
6. Perl 6 - 755
7. C - 751
...
570. NQP - 0
571. AspectC++ - 0
572. Cilk - 0
573. PL/M - 0
574. Agda2 - 0
BBC BASIC
{{works with|BBC BASIC for Windows}} Note that language names differing only in their case are merged.
INSTALL @lib$+"SORTLIB"
SortUp% = FN_sortinit(0,0) : REM Ascending
SortDown% = FN_sortinit(1,0) : REM Descending
VDU 23,22,640;512;8,16,16,128+8 : REM Enable UTF-8 support
DIM lang$(1000), tasks%(1000)
NORM_IGNORECASE = 1
SYS "LoadLibrary", "URLMON.DLL" TO urlmon%
SYS "GetProcAddress", urlmon%, "URLDownloadToFileA" TO UDTF
PRINT "Downloading languages list..."
url$ = "http://rosettacode.org/wiki/Category:Programming_Languages"
file$ = @tmp$ + "languages.htm"
SYS UDTF, 0, url$, file$, 0, 0 TO fail%
IF fail% ERROR 100, "File download failed (languages)"
file% = OPENIN(file$)
index% = 0
WHILE NOT EOF#file%
REPEAT
a$ = GET$#file%
IF INSTR(a$, "<a href=""/wiki/Category") = 0 EXIT REPEAT
i% = INSTR(a$, "</a>")
IF i% = 0 EXIT REPEAT
j% = i%
REPEAT i% -= 1 : UNTIL MID$(a$,i%,1) = ">" OR i% = 0
IF i% = 0 EXIT REPEAT
lang$(index%) = MID$(a$, i%+1, j%-i%-1)
IF lang$(index%) <> "Languages" index% += 1
UNTIL TRUE
ENDWHILE
CLOSE #file%
C% = index%
CALL SortUp%, lang$(0)
PRINT "Downloading categories list..."
url$ = "http://www.rosettacode.org/w/index.php"
url$ += "?title=Special:Categories&limit=5000"
file$ = @tmp$ + "categories.htm"
SYS UDTF, 0, url$, file$, 0, 0 TO fail%
IF fail% ERROR 100, "File download failed (categories)"
file% = OPENIN(file$)
WHILE NOT EOF#file%
REPEAT
a$ = GET$#file%
i% = INSTR(a$, "member")
IF i% = 0 EXIT REPEAT
REPEAT i% -= 1 : UNTIL MID$(a$,i%,1) = "(" OR i% = 0
IF i% = 0 EXIT REPEAT
tasks% = VAL(MID$(a$, i%+1))
IF tasks% = 0 EXIT REPEAT
REPEAT i% -= 1 : UNTIL MID$(a$,i%,1) = "<" OR i% = 0
IF i% = 0 EXIT REPEAT
j% = i%
REPEAT i% -= 1 : UNTIL MID$(a$,i%,1) = ">" OR i% = 0
IF i% = 0 EXIT REPEAT
k% = FNwhere(lang$(), MID$(a$, i%+1, j%-i%-1), index%-1)
IF k% <> -1 tasks%(k%) += tasks%
UNTIL TRUE
ENDWHILE
CLOSE #file%
CALL SortDown%, tasks%(0), lang$(0)
VDU 14
@% = 3 : REM Column width
PRINT "List of languages as of " TIME$
FOR i% = 0 TO index%-1
IF tasks%(i%) = 0 EXIT FOR
PRINT i%+1 ". " tasks%(i%) " - " lang$(i%)
NEXT
END
DEF FNwhere(a$(), S$, T%)
LOCAL B%, C%, H%
H% = 2
WHILE H%<T% H% *= 2:ENDWHILE
H% /= 2
REPEAT
IF (B%+H%)<=T% THEN
SYS "CompareString", 0, NORM_IGNORECASE, S$, -1, a$(B%+H%), -1 TO C%
IF C% >= 2 B% += H%
ENDIF
H% /= 2
UNTIL H%=0
SYS "CompareString", 0, NORM_IGNORECASE, S$, -1, a$(B%), -1 TO C%
IF C% = 2 THEN = B% ELSE = -1
'''Output:'''
Downloading languages list...
Downloading categories list...
List of languages as of Sat.17 Nov 2012,00:21:11
1. 682 - Tcl
2. 638 - Python
3. 626 - PicoLisp
4. 622 - C
5. 592 - J
6. 581 - Go
7. 570 - Ruby
8. 553 - Ada
9. 515 - Perl
10. 514 - D
11. 507 - Haskell
12. 490 - Perl 6
13. 489 - BBC BASIC
14. 477 - Java
15. 473 - Mathematica
16. 469 - PureBasic
17. 469 - OCaml
18. 459 - Unicon
19. 438 - REXX
20. 428 - Icon
......
461. 1 - ScriptBasic
462. 1 - Qore
463. 1 - Opa
464. 1 - Nickle
465. 1 - Neko
466. 1 - Neat
467. 1 - MEL
468. 1 - MAPPER
469. 1 - Kotlin
470. 1 - Chapel
Bracmat
( get-page
= url type
. !arg:(?url.?type)
& sys$(str$("wget -q -O wget.out \"" !url \"))
& get$("wget.out",!type) { Type can be JSN, X ML, HT ML or just ML. }
)
& ( get-langs
= arr lang
. :?arr
& !arg:? (.h2.) ?arg (h2.?) ? { Only analyse part of page between the h2 elements. }
& whl
' ( !arg
: ?
( a
. ?
( title
. @(?:"Category:" ?):?lang
& !lang !arr:?arr
)
?
)
?arg
)
& !arr
)
& ( get-cats
= page langs list count pat li A Z
. !arg:(?page.?langs)
& 0:?list
& whl
' ( !langs:%?lang ?langs
& { Use macro substitution to create a fast pattern. }
' ( ?
(a.? (title.$lang) ?) { $lang is replaced by the actual language. }
?
(.a.)
@(?:? #?count " " ?)
)
: (=?pat)
& ( !page
: ?A
( (li.) ?li (.li.) ?Z
& !li:!pat
)
& !A !Z:?page { Remove found item from page. (Not necessary at all.)}
& !count
| 0 { The language has no examples. }
.
)
\L !lang { Bracmat normalizes a\Lx+b\Ly+a\Lz to a\L(x*z)+b\Ly, so }
+ !list { it's easy to collect categories with the same count. }
: ?list
)
& !list
)
& get-cats
$ ( get-page
$ ( "http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000"
. HT,ML
)
. get-langs
$ ( get-page
$ ( "http://rosettacode.org/wiki/Category:Programming_Languages"
. HT ML
)
)
)
: ?cats
& :?list
& whl
' ( !cats:(?count.)\L?tiedcats+?cats
& :?ties
& whl
' ( !tiedcats:@(?:"Category:" ?name)*?tiedcats
& !ties !name:?ties
)
& (!count.!ties) !list:?list
)
& 1:?rank
& whl
' ( !rank:?tiedRank
& !list:(?count.?ties) ?list
& whl
' ( !ties:%?name ?ties
& @(!tiedRank:? [?len) { We want some padding for the highest ranks. }
& @(" ":? [!len ?sp) { Skip blanks up to the length of the rank. }
& out$(str$(!sp !tiedRank ". " !count " - " !name))
& 1+!rank:?rank
)
)
& ;
Output:
1. 816 - Tcl
2. 771 - Racket
3. 760 - Python
4. 708 - C
5. 705 - Perl 6
6. 700 - J
7. 695 - Ruby
8. 690 - D
9. 656 - Go
10. 643 - PicoLisp
11. 639 - Perl
12. 622 - REXX
13. 602 - Ada
14. 591 - Mathematica
15. 588 - Haskell
16. 574 - AutoHotkey
17. 559 - Unicon
18. 543 - Java
19. 526 - BBC BASIC
20. 510 - Icon
21. 500 - C++
...
498. 1 - Vox
498. 1 - XPath 2.0
498. 1 - Xanadu
523. 0 - Clarion
523. 0 - EhBASIC
523. 0 - Epigram
523. 0 - FLORA-2
523. 0 - Florid
523. 0 - Jcon
523. 0 - LLP
523. 0 - Lolli
523. 0 - Lygon
523. 0 - Monte
523. 0 - ObjectIcon
523. 0 - RPGIV
523. 0 - Rubylog
523. 0 - Star
523. 0 - True BASIC
523. 0 - X10
523. 0 - XS
523. 0 - Ya
C
{{incorrect|C|Compiles without error but "Segmentation fault" when run. Tested on Cygwin, SuSE Linux and Arch Linux (Manjaro)}}
{{improve|C|This solution uses an external program '''wget''' for networking, but it could use '''Library: libcurl''' (see [[Web scraping#C]]) for example. Also this solution scrapes Special:Categories &limit 5000 which will break if the HTML style changes or the number of languages exceeds 5000. It could use the MediWiki API to get the language names and pages in a single call, in blocks of 500 until complete with no upper limit. See the Awk example. If you make an API-based version please retain the web-scrapping version in its own sub-section (following the lead of [[Rosetta_Code/Rank_languages_by_popularity#Tcl|TCL on this page]]). }}
Ghetto parser
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char * lang_url = "http://www.rosettacode.org/w/api.php?action=query&"
"list=categorymembers&cmtitle=Category:Programming_Languages&"
"cmlimit=500&format=json";
const char * cat_url = "http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000";
#define BLOCK 1024
char *get_page(const char *url)
{
char cmd[1024];
char *ptr, *buf;
int bytes_read = 1, len = 0;
sprintf(cmd, "wget -q \"%s\" -O -", url);
FILE *fp = popen(cmd, "r");
if (!fp) return 0;
for (ptr = buf = 0; bytes_read > 0; ) {
buf = realloc(buf, 1 + (len += BLOCK));
if (!ptr) ptr = buf;
bytes_read = fread(ptr, 1, BLOCK, fp);
if (bytes_read <= 0) break;
ptr += bytes_read;
}
*++ptr = '\0';
return buf;
}
char ** get_langs(char *buf, int *l)
{
char **arr = 0;
for (*l = 0; (buf = strstr(buf, "Category:")) && (buf += 9); ++*l)
for ( (*l)[arr = realloc(arr, sizeof(char*)*(1 + *l))] = buf;
*buf != '"' || (*buf++ = 0);
buf++);
return arr;
}
typedef struct { const char *name; int count; } cnt_t;
cnt_t * get_cats(char *buf, char ** langs, int len, int *ret_len)
{
char str[1024], *found;
cnt_t *list = 0;
int i, llen = 0;
for (i = 0; i < len; i++) {
sprintf(str, "/wiki/Category:%s", langs[i]);
if (!(found = strstr(buf, str))) continue;
buf = found + strlen(str);
if (!(found = strstr(buf, "</a> ("))) continue;
list = realloc(list, sizeof(cnt_t) * ++llen);
list[llen - 1].name = langs[i];
list[llen - 1].count = strtol(found + 6, 0, 10);
}
*ret_len = llen;
return list;
}
int _scmp(const void *a, const void *b)
{
int x = ((const cnt_t*)a)->count, y = ((const cnt_t*)b)->count;
return x < y ? -1 : x > y;
}
int main()
{
int len, clen;
char ** langs = get_langs(get_page(lang_url), &len);
cnt_t *cats = get_cats(get_page(cat_url), langs, len, &clen);
qsort(cats, clen, sizeof(cnt_t), _scmp);
while (--clen >= 0)
printf("%4d %s\n", cats[clen].count, cats[clen].name);
return 0;
}
{{out}}
563 Tcl
529 PicoLisp
522 Python
504 C
500 J
442 Go
440 Ruby
435 Ada
430 PureBasic
427 Perl
...
{{libheader|libcurl}} Using cJSON.
Compiled with gcc -lcurl -lm cJSON.c lang_rank.c
Usage: rank [number]
Outputs the first [number] languages in the list, default to 10. Use -1 to display all the languages.
#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);
}
{{out}}
1. Racket: 907 tasks
2. Tcl: 899 tasks
3. Python: 872 tasks
4. J: 848 tasks
5. Perl 6: 813 tasks
6. Ruby: 796 tasks
7. C: 777 tasks
8. Java: 764 tasks
9. Go: 759 tasks
10. D: 749 tasks
C#
Sorting only programming languages.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
class Program
{
static void Main(string[] args)
{
string get1 = new WebClient().DownloadString("http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Languages&cmlimit=500&format=json");
string get2 = new WebClient().DownloadString("http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000");
ArrayList langs = new ArrayList();
Dictionary<string, int> qtdmbr = new Dictionary<string, int>();
MatchCollection match1 = new Regex("\"title\":\"Category:(.+?)\"").Matches(get1);
MatchCollection match2 = new Regex("title=\"Category:(.+?)\">.+?</a>[^(]*\\((\\d+) members\\)").Matches(get2);
foreach (Match lang in match1) langs.Add(lang.Groups[1].Value);
foreach (Match match in match2)
{
if (langs.Contains(match.Groups[1].Value))
{
qtdmbr.Add(match.Groups[1].Value, Int32.Parse(match.Groups[2].Value));
}
}
string[] test = qtdmbr.OrderByDescending(x => x.Value).Select(x => String.Format("{0,3} - {1}", x.Value, x.Key)).ToArray();
int count = 1;
foreach (string i in test)
{
Console.WriteLine("{0,3}. {1}", count, i);
count++;
}
}
}
{{out|Output (as of May 30, 2010)}}
- 397 - Tcl
- 368 - Python
- 350 - Ruby
- 333 - J
- 332 - C
- 322 - Haskell
- 322 - OCaml
- 302 - Perl
- 290 - Common Lisp
- 289 - AutoHotkey . . . ===Object-oriented solution===
using System;
using System.Net;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections.Generic;
class Category {
private string _title;
private int _members;
public Category(string title, int members) {
_title = title;
_members = members;
}
public string Title {
get {
return _title;
}
}
public int Members {
get {
return _members;
}
}
}
class Program {
static void Main(string[] args) {
string get1 = new WebClient().DownloadString("http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Languages&cmlimit=500&format=json");
string get2 = new WebClient().DownloadString("http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000");
MatchCollection match1 = new Regex("\"title\":\"Category:(.+?)\"").Matches(get1);
MatchCollection match2 = new Regex("title=\"Category:(.+?)\">.+?</a>[^(]*\\((\\d+) members\\)").Matches(get2);
string[] valids = match1.Cast<Match>().Select(x => x.Groups[1].Value).ToArray();
List<Category> langs = new List<Category>();
foreach (Match match in match2) {
string category = match.Groups[1].Value;
int members = Int32.Parse(match.Groups[2].Value);
if (valids.Contains(category)) langs.Add(new Category(category, members));
}
langs = langs.OrderByDescending(x => x.Members).ToList();
int count = 1;
foreach (Category i in langs) {
Console.WriteLine("{0,3}. {1,3} - {2}", count, i.Members, i.Title);
count++;
}
}
}
C++
{{libheader|Boost}} using g++ under Linux with g++ -lboost_thread -lboost_system -lboost_regex:
#include <string>
#include <boost/regex.hpp>
#include <boost/asio.hpp>
#include <vector>
#include <utility>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <algorithm>
#include <iomanip>
struct Sort { //sorting programming languages according to frequency
bool operator( ) ( const std::pair<std::string,int> & a , const std::pair<std::string,int> & b )
const {
return a.second > b.second ;
}
} ;
int main( ) {
try {
//setting up an io service , with templated subelements for resolver and query
boost::asio::io_service io_service ;
boost::asio::ip::tcp::resolver resolver ( io_service ) ;
boost::asio::ip::tcp::resolver::query query ( "rosettacode.org" , "http" ) ;
boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve( query ) ;
boost::asio::ip::tcp::resolver::iterator end ;
boost::asio::ip::tcp::socket socket( io_service ) ;
boost::system::error_code error = boost::asio::error::host_not_found ;
//looking for an endpoint the socket will be able to connect to
while ( error && endpoint_iterator != end ) {
socket.close( ) ;
socket.connect( *endpoint_iterator++ , error ) ;
}
if ( error )
throw boost::system::system_error ( error ) ;
//we send a request
boost::asio::streambuf request ;
std::ostream request_stream( &request ) ;
request_stream << "GET " << "/mw/index.php?title=Special:Categories&limit=5000" << " HTTP/1.0\r\n" ;
request_stream << "Host: " << "rosettacode.org" << "\r\n" ;
request_stream << "Accept: */*\r\n" ;
request_stream << "Connection: close\r\n\r\n" ;
//send the request
boost::asio::write( socket , request ) ;
//we receive the response analyzing every line and storing the programming language
boost::asio::streambuf response ;
std::istream response_stream ( &response ) ;
boost::asio::read_until( socket , response , "\r\n\r\n" ) ;
boost::regex e( "<li><a href=\"[^<>]+?\">([a-zA-Z\\+#1-9]+?)</a>\\s?\\((\\d+) members\\)</li>" ) ;
//using the wrong regex produces incorrect sorting!!
std::ostringstream line ;
std::vector<std::pair<std::string , int> > languages ; //holds language and number of examples
boost::smatch matches ;
while ( boost::asio::read( socket , response , boost::asio::transfer_at_least( 1 ) , error ) ) {
line << &response ;
if ( boost::regex_search( line.str( ) , matches , e ) ) {
std::string lang( matches[2].first , matches[2].second ) ;
int zahl = atoi ( lang.c_str( ) ) ;
languages.push_back( std::make_pair( matches[ 1 ] , zahl ) ) ;
}
line.str( "") ;//we have to erase the string buffer for the next read
}
if ( error != boost::asio::error::eof )
throw boost::system::system_error( error ) ;
//we sort the vector entries , see the struct above
std::sort( languages.begin( ) , languages.end( ) , Sort( ) ) ;
int n = 1 ;
for ( std::vector<std::pair<std::string , int> >::const_iterator spi = languages.begin( ) ;
spi != languages.end( ) ; ++spi ) {
std::cout << std::setw( 3 ) << std::right << n << '.' << std::setw( 4 ) << std::right <<
spi->second << " - " << spi->first << '\n' ;
n++ ;
}
} catch ( std::exception &ex ) {
std::cout << "Exception: " << ex.what( ) << '\n' ;
}
return 0 ;
}
{{out|Sample output (just the "top ten")}}
- 367 - Tcl
- 334 - Python
- 319 - Ruby
- 286 - C
- 277 - Perl
- 272 - OCaml
- 264 - Ada
- 241 - E
- 239 - AutoHotkey
- 193 - Forth
=={{header|Caché ObjectScript}}==
Class Utils.Net.RosettaCode [ Abstract ]
{
ClassMethod GetTopLanguages(pHost As %String = "", pPath As %String = "", pTop As %Integer = 10) As %Status
{
// check input parameters
If $Match(pHost, "^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$")=0 {
Quit $$$ERROR($$$GeneralError, "Invalid host name.")
}
// create http request and get page
Set req=##class(%Net.HttpRequest).%New()
Set req.Server=pHost
Do req.Get(pPath)
// create xml stream with doc type
Set xml=##class(%Stream.GlobalCharacter).%New()
Set sc=xml.WriteLine("<!DOCTYPE doc_type [")
Set sc=xml.WriteLine($Char(9)_"<!ENTITY nbsp ' '>")
Set sc=xml.WriteLine($Char(9)_"<!ENTITY amp '&'>")
Set sc=xml.WriteLine("]>")
// copy xhtml stream to xml stream
Set xhtml=req.HttpResponse.Data
Set xhtml.LineTerminator=$Char(10)
While 'xhtml.AtEnd {
Set line=xhtml.ReadLine()
If line["!DOCTYPE" Continue
If line["<g:plusone></g:plusone>" {
Continue
Set line="<g:plusone xmlns:g='http://base.google.com/ns/1.0'></g:plusone>"
}
Set sc=xml.WriteLine(line)
}
// create an instance of an %XML.XPATH.Document
Set sc=##class(%XML.XPATH.Document).CreateFromStream(xml, .xdoc)
If $$$ISERR(sc) Quit sc
// evaluate following 'XPath' expression
Set sc=xdoc.EvaluateExpression("//div[@id='bodyContent']//li", "a[contains(@href, '/Category:')]/ancestor::li", .res)
// iterate through list elements
Set array=##class(%ArrayOfDataTypes).%New()
Do {
Set dom=res.GetNext(.key)
If '$IsObject(dom) Quit
// get language name and members
Set lang=""
While dom.Read() {
If 'dom.HasValue Continue
If lang="" {
If $Locate(dom.Value, "User|Tasks|Omit|attention|operations|Solutions by") Quit
Set lang=dom.Value Continue
}
If dom.Value["members" {
Set members=+$ZStrip(dom.Value, "<>P")
Set list=array.GetAt(members)
Set $List(list, $ListLength(list)+1)=lang
Set sc=array.SetAt(list, members)
Quit
}
}
} While key'=""
If array.Count()=0 Quit $$$ERROR($$$GeneralError, "No languages found.")
// show top entries
Write "Top "_pTop_" Languages (as at "_$ZDate($HoroLog, 2)_"):", !
For count=1:1:pTop {
Set members=array.GetPrevious(.key)
If key="" Quit
Write $Justify(count, 3), ". ", key, " - ", $ListToString(members, ", "), !
}
// finished
Quit $$$OK
}
}
{{out|Example}}
USER>Do ##class(Utils.Net.RosettaCode).GetTopLanguages("www.rosettacode.org", "/mw/index.php?title=Special:Categories&limit=5000")
Top 10 Languages (as at 21 Apr 2013):
1. 728 - Tcl
2. 668 - Python
3. 654 - C
4. 630 - J
5. 626 - PicoLisp
6. 595 - D
7. 590 - Ruby
8. 589 - Go
9. 576 - Perl 6
10. 567 - Ada
D
With dmd you need compile like "dmd rosetta_popularity.d -L-lphobos2 -L-lcurl".
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[]);
}
{{out|Sample output (top twenty as of 2013-01-24)}}
1. 717 - Tcl
2. 663 - Python
3. 643 - C
4. 626 - PicoLisp
5. 622 - J
6. 587 - Go
7. 587 - Ruby
8. 585 - D
9. 568 - Perl 6
10. 564 - Ada
11. 554 - Mathematica
12. 535 - Perl
13. 532 - Haskell
14. 514 - BBC BASIC
15. 505 - REXX
16. 491 - Java
17. 478 - OCaml
18. 469 - PureBasic
19. 462 - Unicon
20. 430 - AutoHotkey
Erlang
-module( rank_languages_by_popularity ).
-export( [task/0] ).
-record( print_fold, {place=0, place_step=1, previous_count=0} ).
task() ->
ok = find_unimplemented_tasks:init(),
Category_programming_languages = find_unimplemented_tasks:rosetta_code_list_of( "Programming_Languages" ),
Programming_languages = [X || "Category:" ++ X <- Category_programming_languages],
{ok, {{_HTTP,200,"OK"}, _Headers, Body}} = httpc:request( "http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000" ),
Count_categories = lists:sort( [{Y, X} || {X, Y} <- category_counts(Body, []), lists:member(X, Programming_languages)] ),
lists:foldr( fun place_count_category_write/2, #print_fold{}, Count_categories ).
category_counts( "", [[] | Acc] ) -> Acc;
category_counts( String, Acc ) ->
{Begin, End} = category_count_begin_end( String ),
{Category_count, String_continuation} = category_count_extract( String, Begin, End ),
category_counts( String_continuation, [Category_count | Acc] ).
category_count_begin_end( String ) ->
Begin = string:str( String, "/wiki/Category:" ),
End = string:str( string:substr(String, Begin), " member" ),
category_count_begin_end( Begin, End, erlang:length(" member") ).
category_count_begin_end( _Begin, 0, _End_length ) -> {0, 0};
category_count_begin_end( Begin, End, End_length ) ->
{Begin, Begin + End + End_length}.
category_count_extract( _String, 0, _End ) -> {[], ""};
category_count_extract( String, Begin, End ) ->
Category_count = category_count_extract( string:substr(String, Begin, End - Begin) ),
{Category_count, string:substr( String, End + 1 )}.
category_count_extract( "/wiki/Category:" ++ T ) ->
Category_member = string:tokens( T, " " ),
Category = category_count_extract_category( Category_member ),
Member = category_count_extract_count( lists:reverse(Category_member) ),
{Category, Member}.
category_count_extract_category( [Category | _T] ) ->
lists:map( fun category_count_extract_category_map/1, string:strip(Category, right, $") ).
category_count_extract_category_map( $_ ) -> $\s;
category_count_extract_category_map( Character ) -> Character.
category_count_extract_count( ["member" ++ _, "(" ++ N | _T] ) -> erlang:list_to_integer( N );
category_count_extract_count( _T ) -> 0.
place_count_category_write( {Count, Category}, Acc ) ->
Print_fold = place_count_category_write( Count, Acc ),
io:fwrite("~p. ~p - ~p~n", [Print_fold#print_fold.place, Count, Category] ),
Print_fold;
place_count_category_write( Count, #print_fold{place_step=Place_step, previous_count=Count}=Print_fold ) ->
Print_fold#print_fold{place_step=Place_step + 1};
place_count_category_write( Count, #print_fold{place=Place, place_step=Place_step} ) ->
#print_fold{place=Place + Place_step, previous_count=Count}.
{{out|Sample output (top/last ten as of 2013-05-27)}}
1. 741 - "Tcl"
2. 676 - "Python"
3. 660 - "C"
4. 638 - "J"
5. 627 - "PicoLisp"
6. 609 - "Perl 6"
6. 609 - "D"
8. 607 - "Racket"
9. 592 - "Ruby"
10. 589 - "Go"
...
454. 1 - "Opa"
454. 1 - "Nickle"
454. 1 - "NewtonScript"
454. 1 - "Neko"
454. 1 - "Neat"
454. 1 - "MEL"
454. 1 - "MAPPER"
454. 1 - "LiveScript"
454. 1 - "Kotlin"
454. 1 - "Jacquard Loom"
=={{header|F_Sharp|F#}}==
open System
open System.Text.RegularExpressions
[<EntryPoint>]
let main argv =
let rosettacodeSpecialCategoriesAddress =
"http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000"
let rosettacodeProgrammingLaguagesAddress =
"http://rosettacode.org/wiki/Category:Programming_Languages"
let getWebContent (url :string) =
using (new System.Net.WebClient()) (fun x -> x.DownloadString url)
let regexForTitleCategoryFollowedOptionallyByMembercount =
new Regex("""
title="Category: (?<Name> [^"]* ) "> # capture the name of the category
( # group begin for optional part
[^(]* # ignore up to next open paren (on this line)
\( # verbatim open paren
(?<Number>
\d+ # a number (= some digits)
)
\s+ # whitespace
member(s?) # verbatim text members (maybe singular)
\) # verbatim closing paren
)? # end of optional part
""", // " <- Make syntax highlighting happy
RegexOptions.IgnorePatternWhitespace ||| RegexOptions.ExplicitCapture)
let matchesForTitleCategoryFollowedOptionallyByMembercount str =
regexForTitleCategoryFollowedOptionallyByMembercount.Matches(str)
let languages =
matchesForTitleCategoryFollowedOptionallyByMembercount
(getWebContent rosettacodeProgrammingLaguagesAddress)
|> Seq.cast
|> Seq.map (fun (m: Match) -> (m.Groups.Item("Name").Value, true))
|> Map.ofSeq
let entriesWithCount =
let parse str = match Int32.TryParse(str) with | (true, n) -> n | (false, _) -> -1
matchesForTitleCategoryFollowedOptionallyByMembercount
(getWebContent rosettacodeSpecialCategoriesAddress)
|> Seq.cast
|> Seq.map (fun (m: Match) ->
(m.Groups.Item("Name").Value, parse (m.Groups.Item("Number").Value)))
|> Seq.filter (fun p -> (snd p) > 0 && Map.containsKey (fst p) languages)
|> Seq.sortBy (fun x -> -(snd x))
Seq.iter2 (fun i x -> printfn "%4d. %s" i x)
(seq { 1 .. 20 })
(entriesWithCount |> Seq.map (fun x -> sprintf "%3d - %s" (snd x) (fst x)))
0
Showing top 20 as of 2013-04-02
1. 721 - Tcl
2. 665 - Python
3. 647 - C
4. 626 - PicoLisp
5. 622 - J
6. 588 - Go
7. 588 - Ruby
8. 585 - D
9. 569 - Perl 6
10. 565 - Ada
11. 555 - Mathematica
12. 535 - Perl
13. 533 - Haskell
14. 514 - BBC BASIC
15. 505 - REXX
16. 491 - Java
17. 480 - OCaml
18. 469 - PureBasic
19. 462 - Unicon
20. 430 - AutoHotkey
Go
package main
import (
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"net/url"
"regexp"
"sort"
"strconv"
"strings"
)
var baseQuery = "http://rosettacode.org/mw/api.php?action=query" +
"&format=xml&list=categorymembers&cmlimit=500"
func req(u string, foundCm func(string)) string {
resp, err := http.Get(u)
if err != nil {
log.Fatal(err) // connection or request fail
}
defer resp.Body.Close()
for p := xml.NewDecoder(resp.Body); ; {
t, err := p.RawToken()
switch s, ok := t.(xml.StartElement); {
case err == io.EOF:
return ""
case err != nil:
log.Fatal(err)
case !ok:
continue
case s.Name.Local == "cm":
for _, a := range s.Attr {
if a.Name.Local == "title" {
foundCm(a.Value)
}
}
case s.Name.Local == "categorymembers" && len(s.Attr) > 0 &&
s.Attr[0].Name.Local == "cmcontinue":
return url.QueryEscape(s.Attr[0].Value)
}
}
return ""
}
// satisfy sort interface (reverse sorting)
type pop struct {
string
int
}
type popList []pop
func (pl popList) Len() int { return len(pl) }
func (pl popList) Swap(i, j int) { pl[i], pl[j] = pl[j], pl[i] }
func (pl popList) Less(i, j int) bool {
switch d := pl[i].int - pl[j].int; {
case d > 0:
return true
case d < 0:
return false
}
return pl[i].string < pl[j].string
}
func main() {
// get languages, store in a map
langMap := make(map[string]bool)
storeLang := func(cm string) {
if strings.HasPrefix(cm, "Category:") {
cm = cm[9:]
}
langMap[cm] = true
}
languageQuery := baseQuery + "&cmtitle=Category:Programming_Languages"
continueAt := req(languageQuery, storeLang)
for continueAt != "" {
continueAt = req(languageQuery+"&cmcontinue="+continueAt, storeLang)
}
// allocate slice for sorting
s := make(popList, 0, len(langMap))
// get big list of categories
resp, err := http.Get("http://rosettacode.org/mw/index.php" +
"?title=Special:Categories&limit=5000")
if err != nil {
log.Fatal(err)
}
page, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
// split out fields of interest and populate sortable slice
rx := regexp.MustCompile("<li><a.*>(.*)</a>.*[(]([0-9]+) member")
for _, sm := range rx.FindAllSubmatch(page, -1) {
ls := string(sm[1])
if langMap[ls] {
if n, err := strconv.Atoi(string(sm[2])); err == nil {
s = append(s, pop{ls, n})
}
}
}
// output
sort.Sort(s)
lastCnt, lastIdx := -1, 1
for i, lang := range s {
if lang.int != lastCnt {
lastCnt = lang.int
lastIdx = i + 1
}
fmt.Printf("%3d. %3d - %s\n", lastIdx, lang.int, lang.string)
}
}
{{out|Output on 11 Aug 2014}}
1. 832 - Tcl
2. 783 - Racket
3. 774 - Python
4. 733 - Perl 6
5. 729 - J
…
506. 1 - Supernova
506. 1 - TestML
506. 1 - Vox
506. 1 - XPath 2.0
506. 1 - Xanadu
(All the final entries are tied for spot 506, there are 530 lines.)
Groovy
def html = new URL('http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000').getText([
connectTimeout:500,
readTimeout:15000,
requestProperties: [ 'User-Agent': 'Firefox/2.0.0.4']])
def count = [:]
(html =~ '<li><a[^>]+>([^<]+)</a>[^(]*[(](\\d+) member[s]*[)]</li>').each { match, language, members ->
count[language] = (members as int)
}
count.sort { v1, v2 -> v2.value <=> v1.value }.eachWithIndex { value, index -> println "${index + 1} $value" }
Output:
1 Tcl=766
2 Racket=726
3 Python=712
4 Programming Tasks=695
5 C=681
6 Perl 6=649
...
48 Groovy=323
Haskell
Haskell: Using the API
{-# 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
{{out}} (As of 2015-07-29.) Here we show only the top 30.
1. Tcl - 887
2. Racket - 877
3. Python - 853
4. J - 795
5. Ruby - 775
6. Perl 6 - 766
7. C - 757
8. Go - 746
9. D - 740
10. Perl - 710
11. REXX - 697
12. PicoLisp - 692
13. Haskell - 682
14. Mathematica - 675
15. Java - 652
16. Zkl - 634
17. Ada - 623
18. AutoHotkey - 591
19. Unicon - 581
20. C++ - 562
21. Common Lisp - 551
22. Scala - 548
23. BBC BASIC - 532
24. Icon - 523
25. C sharp - 516
26. OCaml - 508
27. Nim - 502
28. (tie) Clojure - 485
28. (tie) PureBasic - 485
29. Erlang - 455
30. PARI/GP - 441
Haskell: Using web scraping
Scraping the languages and categories pages.
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
{{out|First 20}}
*Main> mostPopLang
1. 421 Tcl
2. 392 Python
3. 365 PicoLisp
4. 363 J
5. 360 Ruby
6. 354 C
7. 344 Haskell
8. 337 OCaml
9. 316 Perl
10. 308 PureBasic
11. 302 AutoHotkey
12. 299 Common Lisp
13. 295 D
14. 295 Java
15. 293 Ada
16. 278 Oz
17. 260 R
18. 259 C sharp
19. 257 C++
20. 255 ALGOL 68
HicEst
CHARACTER cats*50000, catlist*50000, sortedCat*50000, sample*100
DIMENSION RankNr(1)
READ(ClipBoard) cats
catlist = ' '
pos = 1 ! find language entries like * 100 doors (2 members)
nr = 0
! after next '*' find next "name" = '100 doors' and next "(...)" = '(2 members)' :
1 EDIT(Text=cats, SetPos=pos, Right='*', R, Mark1, R='(', Left, M2, Parse=name, R=2, P=members, GetPos=pos)
IF(pos > 0) THEN
READ(Text=members) count
IF(count > 0) THEN
nr = nr + 1
WRITE(Text=catlist, Format='i4, 1x, 2a', APPend) count, name, ';'
ENDIF
GOTO 1 ! no WHILE in HicEst
ENDIF ! catlist is now = " 1 ... User ; 2 100 doors ; 3 3D ; 8 4D ; ..."
ALLOCATE(RankNr, nr)
EDIT(Text=catlist, SePaRators=';', Option=1+4, SorTtoIndex=RankNr) ! case (1) and back (4)
sortedCat = ' ' ! get the sorted list in the sequence of RankNr:
ok = 0
DO i = 1, nr
EDIT(Text=catlist, SePaRators=';', ITeM=RankNr(i), CoPyto=sample)
discard = EDIT(Text=sample, LeXicon='user,attention,solutions,tasks,program,language,implementation,')
IF(discard == 0) THEN ! removes many of the non-language entries
ok = ok + 1
WRITE(Text=sortedCat, APPend, Format='F5.0, 2A') ok, TRIM(sample), $CRLF
ENDIF
ENDDO
DLG(Text=sortedCat, Format=$CRLF)
END
2010-04-24 18:31
Top 10 entries (not all are languages)
1. 394 Tcl
2. 363 Python
3. 346 Ruby
4. 328 J
5. 319 C
6. 317 OCaml
7. 315 Haskell
8. 298 Perl
9. 288 WikiStubs
10. 281 Common Lisp
=={{header|Icon}} and {{header|Unicon}}==
By using the API
The following solution only works in Unicon.
$define RCLANGS "http://rosettacode.org/mw/api.php?format=xml&action=query&generator=categorymembers&gcmtitle=Category:Programming%20Languages&gcmlimit=500&prop=categoryinfo"
$define RCUA "User-Agent: Unicon Rosetta 0.1"
$define RCXUA "X-Unicon: http://unicon.org/"
link strings
link hexcvt
procedure main()
cnt := create seq()
last := -1
every pair := !reverse(sort(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
Abridged output (top 26 languages as of July 30, 2016):
1: Racket. . . . . . . . . . . . . . . .904
2: Tcl . . . . . . . . . . . . . . . . .894
3: Python. . . . . . . . . . . . . . . .867
4: J . . . . . . . . . . . . . . . . . .852
5: Perl 6. . . . . . . . . . . . . . . .824
6: Ruby. . . . . . . . . . . . . . . . .796
7: C . . . . . . . . . . . . . . . . . .777
8: Go. . . . . . . . . . . . . . . . . .769
9: Java. . . . . . . . . . . . . . . . .764
10: D . . . . . . . . . . . . . . . . . .747
11: REXX. . . . . . . . . . . . . . . . .743
12: Perl. . . . . . . . . . . . . . . . .736
13: Haskell . . . . . . . . . . . . . . .712
: Zkl . . . . . . . . . . . . . . . . .712
15: PicoLisp. . . . . . . . . . . . . . .695
16: Mathematica . . . . . . . . . . . . .686
17: Sidef . . . . . . . . . . . . . . . .632
18: Ada . . . . . . . . . . . . . . . . .626
19: C++ . . . . . . . . . . . . . . . . .619
20: AutoHotkey. . . . . . . . . . . . . .603
21: Unicon. . . . . . . . . . . . . . . .578
22: Common Lisp . . . . . . . . . . . . .577
23: Scala . . . . . . . . . . . . . . . .561
24: BBC BASIC . . . . . . . . . . . . . .535
25: C sharp . . . . . . . . . . . . . . .529
26: Icon. . . . . . . . . . . . . . . . .520
...
604 languages
== {{header|J}} == {{works with|J|6.02 (32 bit only)}} '''Solution''':
require 'web/gethttp xml/sax/x2j regex'
x2jclass 'rcPopLang'
rx =: (<0 1) {:: (2#a:) ,~ rxmatches rxfrom ]
'Popular Languages' x2jDefn
/ := langs : langs =: 0 2 $ a:
html/body/div/div/div/ul/li := langs =: langs ,^:(a:~:{.@[)~ lang ; ' \((\d+) members?\)' rx y
html/body/div/div/div/ul/li/a := lang =: '^\s*((?:.(?!User|Tasks|Omit|attention|operations|by))+)\s*$' rx y
)
cocurrent'base'
sortTab =. \: __ ". [: ;:^:_1: {:"1
formatTab =: [: ;:^:_1: [: (20 A. (<'-') , |. , [: ('.' <"1@:,.~ ":) 1 + 1 i.@,~ 1{$)&.|: sortTab f.
rcPopLangs =: formatTab@:process_rcPopLang_@:gethttp
'''Example''':
10 {. rcPopLangs 'http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=2000'
1. 687 - Tcl
2. 646 - Python
3. 637 - C
4. 626 - PicoLisp
5. 612 - J
6. 587 - Go
7. 556 - Ada
8. 550 - D
9. 549 - Mathematica
10. 526 - Perl
'''Notes''': See some [[Talk:Sort most popular programming languages#J|notes on the J solution]].
== {{header|Java}} == Tested with Java 1.7. Uses the api.
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
{{out}} Top 10 languages as at 27th August 2015
1: 883: Tcl
2: 875: Racket
3: 837: Python
4: 799: J
5: 772: Ruby
6: 763: Perl 6
7: 756: C
8: 742: Go
9: 737: D
10: 707: Perl
...
== {{header|jq}} == {{works with|jq|1.4}} The following solution matches the languages listed on the Category:Programming_Languages page with the statistics given on the Special:Categories page, making an adjustment for the number of irrelevant subcategories.
jq 1.4 cannot retrieve documents over the web and has no support for regular expressions, but is intended to work seamlessly with other command line tools, so the following solution is presented in the form of a bash script that uses curl for retrieval, and grep and sed for screen scraping.
#!/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])" '
{{out}}
# 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
Julia
using HTTP
try
response = HTTP.request("GET", "http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000")
langcount = Dict{String, Int}()
for mat in eachmatch(r"<li><a href[^\>]+>([^\<]+)</a>[^1-9]+(\d+)[^\w]+member.?.?</li>", String(response.body))
if match(r"^Programming", mat.captures[1]) == nothing
langcount[mat.captures[1]] = parse(Int, mat.captures[2])
end
end
langs = sort(collect(keys(langcount)), lt=(x, y)->langcount[x]<langcount[y], rev=true)
for (i, lang) in enumerate(langs)
println("Language $lang can be ranked #$i at $(langcount[lang]).")
end
catch y
println("HTTP request failed: $y.")
exit()
end
{{out}
Language Phix can be ranked #1 at 995.
Language Racket can be ranked #2 at 989.
Language Perl can be ranked #3 at 969.
Language Julia can be ranked #4 at 968.
Language C can be ranked #5 at 944.
Language Tcl can be ranked #6 at 930.
Language Zkl can be ranked #7 at 919.
Language J can be ranked #8 at 905.
Language Java can be ranked #9 at 900.
Language REXX can be ranked #10 at 892.
Language D can be ranked #11 at 874.
Language Ruby can be ranked #12 at 869.
Language Haskell can be ranked #13 at 853.
Language Scala can be ranked #14 at 792.
Language Sidef can be ranked #15 at 788.
Language PicoLisp can be ranked #16 at 775.
Language C sharp can be ranked #17 at 763.
Language Mathematica can be ranked #18 at 743.
Language C++ can be ranked #19 at 738.
Language Common Lisp can be ranked #20 at 667.
Language Ada can be ranked #21 at 656.
Language AutoHotkey can be ranked #22 at 628.
Language JavaScript can be ranked #23 at 619.
Language Lua can be ranked #24 at 618.
Language WikiStubs can be ranked #25 at 614.
...
Julia: Using web scraping
{{trans|Python}}
using HTTP, Dates
response = HTTP.request("GET", "http://rosettacode.org/wiki/Category:Programming_Languages")
languages = Set(m.captures[1] for m in eachmatch(r"title=\"Category:(.*?)\">",String(response.body)))
response = HTTP.request("GET", "http://rosettacode.org/mw/index.php?title=Special:Categories&limit=5000")
response = replace(String(response.body),"," => "")
reg = r"<li><a[^>]+>([^<]+)</a>[^(]*[\(](\d+) member[s]?[)]</li>"
ms = eachmatch(reg,response)
members = [[1,parse(Int,m.captures[2]),m.captures[1]] for m in ms]
filter!(x -> x[3] in languages, members)
sort!(members, by = x -> (-x[2],x[3]))
for i in 2:length(members)
if members[i-1][2] == members[i][2]
members[i][1] = members[i-1][1]
else
members[i][1] = i
end
end
println("Sample output on ", Dates.day(now()), " ", Dates.monthname(now()), " ", Dates.year(now()), ":\n")
for (rank,entries,name) in members[1:10]
println("Rank: ", lpad(rank,4), lpad(" ($entries entries) ",16), name)
end
{{out}}
Sample output on 22 July 2019:
Rank: 1 (1154 entries) Go
Rank: 2 (1089 entries) Perl 6
Rank: 3 (1070 entries) Julia
Rank: 4 (1066 entries) Python
Rank: 5 (1062 entries) Phix
Rank: 6 (1045 entries) Kotlin
Rank: 7 (1026 entries) Perl
Rank: 8 (991 entries) Racket
Rank: 9 (952 entries) C
Rank: 10 (945 entries) J
Kotlin
{{trans|Java}}
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
}
}
}
{{out}}
1, 901, Racket
2, 893, Tcl
3, 851, Python
4, 826, J
5, 796, Perl 6
...
135, 70, Kotlin
...
Lasso
```txt
<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>
{{out}}
```txt
1. 759 - Tcl
2. 724 - Racket
3. 707 - Python
4. 692 - Programming Tasks
5. 672 - C
6. 643 - J
7. 635 - Perl 6
8. 632 - D
9. 627 - PicoLisp
10. 617 - Ruby
...
M2000 Interpreter
Based on BBC BASIC idea, and using M2000 Rinstr() and objects as Inventories, Document, and Microsoft.XMLHTTP for downloading (async use). Results also copy to Clipboard. We can use Msxml2.ServerXMLHTTP (code is the same, only name of object change).
Update: Numbers above 999 get a comma (,) so we have to drop this using Filter$()
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
{{out}}
Sample output on Saturday, June 22, 2019: rank: 1. 1149 entries - Go rank: 2. 1084 entries - Perl 6 rank: 3. 1061 entries - Python rank: 4. 1045 entries - Kotlin rank: 5. 1044 entries - Julia rank: 6. 1033 entries - Phix rank: 7. 1026 entries - Perl rank: 8. 991 entries - Racket rank: 9. 951 entries - C rank: 10. 944 entries - J rank: 11. 938 entries - Zkl rank: 12. 930 entries - Tcl rank: 13. 910 entries - REXX rank: 14. 909 entries - Java rank: 15. 883 entries - Ruby rank: 16. 881 entries - D rank: 17. 869 entries - Haskell rank: 18. 814 entries - Sidef rank: 19. 801 entries - Scala rank: 20. 779 entries - C sharp rank: 21. 775 entries - PicoLisp rank: 22. 772 entries - C++ rank: 23. 748 entries - Mathematica rank: 24. 678 entries - Common Lisp rank: 25. 668 entries - Ada rank: 26. 639 entries - JavaScript rank: 27. 633 entries - Lua rank: 28. 628 entries - AutoHotkey rank: 29. 611 entries - Ring rank: 30. 595 entries - Factor rank: 31. 594 entries - Clojure rank: 32. 590 entries - Unicon rank: 33. 566 entries - ALGOL 68 rank: 34. 563 entries - Nim rank: 35. 563 entries - PureBasic rank: 36. 560 entries - BBC BASIC rank: 37. 559 entries - Fortran rank: 38. 556 entries - OCaml rank: 39. 540 entries - PARI/GP rank: 40. 538 entries - F Sharp rank: 41. 532 entries - Icon rank: 42. 517 entries - Elixir rank: 43. 497 entries - FreeBASIC rank: 44. 495 entries - Erlang rank: 45. 485 entries - Rust rank: 46. 473 entries - PowerShell rank: 47. 462 entries - Jq rank: 48. 456 entries - Pascal rank: 49. 453 entries - AWK rank: 50. 450 entries - Forth rank: 51. 448 entries - Seed7 rank: 52. 435 entries - R rank: 53. 414 entries - Groovy rank: 54. 403 entries - PL/I rank: 55. 401 entries - PHP rank: 56. 383 entries - VBA rank: 57. 361 entries - Scheme rank: 58. 359 entries - MATLAB rank: 59. 353 entries - Swift rank: 60. 346 entries - M2000 Interpreter rank: 61. 343 entries - Maple rank: 62. 337 entries - Liberty BASIC rank: 63. 314 entries - Run BASIC rank: 64. 309 entries - Prolog .......... rank: 685. 1 entries - Jacquard Loom rank: 686. 1 entries - Kamailio Script rank: 687. 1 entries - Lambda Prolog rank: 688. 1 entries - LibreOffice Basic rank: 689. 1 entries - MAPPER rank: 690. 1 entries - MEL rank: 691. 1 entries - MiniZinc rank: 692. 1 entries - Mond rank: 693. 1 entries - Monkey rank: 694. 1 entries - NASL rank: 695. 1 entries - Neat rank: 696. 1 entries - NewtonScript rank: 697. 1 entries - Nickle rank: 698. 1 entries - Nix rank: 699. 1 entries - Opa rank: 700. 1 entries - Pare rank: 701. 1 entries - Qore rank: 702. 1 entries - Rapira rank: 703. 1 entries - RPGIV rank: 704. 1 entries - Setl4 rank: 705. 1 entries - Soar rank: 706. 1 entries - SoneKing Assembly rank: 707. 1 entries - Supernova rank: 708. 1 entries - SuperTalk rank: 709. 1 entries - Terra rank: 710. 1 entries - TestML rank: 711. 1 entries - WebAssembly rank: 712. 1 entries - Wollok rank: 713. 1 entries - Xanadu rank: 714. 1 entries - Ya rank: 715. 1 entries - МiniZinc rank: 716. 0 entries - AngelScript rank: 717. 0 entries - Binary Lambda Calculus rank: 718. 0 entries - EhBASIC rank: 719. 0 entries - Epigram rank: 720. 0 entries - FLORA-2 rank: 721. 0 entries - Florid rank: 722. 0 entries - Gerbil rank: 723. 0 entries - LC2200 Assembly rank: 724. 0 entries - Leon rank: 725. 0 entries - Livecode rank: 726. 0 entries - LLP rank: 727. 0 entries - Loglan82 rank: 728. 0 entries - Lolli rank: 729. 0 entries - Lygon rank: 730. 0 entries - ObjectIcon rank: 731. 0 entries - PL/B rank: 732. 0 entries - Plan rank: 733. 0 entries - Reduce rank: 734. 0 entries - Rubylog rank: 735. 0 entries - S BASIC rank: 736. 0 entries - SimpleLang rank: 737. 0 entries - Star rank: 738. 0 entries - X10 rank: 739. 0 entries - XS## Maple ```Maple 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: ``` {{Out|Output}} ```txt #10:30 AM 10/05/2018 rank 1 1002 examples Kotlin rank 2 977 examples Racket rank 3 977 examples Python rank 4 949 examples Perl 6 rank 5 918 examples Tcl rank 6 898 examples C rank 7 891 examples J rank 8 879 examples Zkl rank 9 870 examples Java rank 10 860 examples D ... rank 680 0 examples Epigram rank 681 0 examples LLP rank 682 0 examples Lolli rank 683 0 examples Leon rank 684 0 examples Florid rank 685 0 examples Loglan82 ``` ## Mathematica ```Mathematica Languages = Flatten[Import["http://rosettacode.org/wiki/Category:Programming_Languages","Data"][[1,1]]]; Languages = Most@StringReplace[Languages, {" " -> "_", "+" -> "%2B"}]; b = {#, If[# === {}, 0, #[[1]]]&@( StringCases[Import["http://rosettacode.org/wiki/Category:"<>#,"Plaintext"], "category, out of " ~~ x:NumberString ~~ " total" ->x])} &/@ Languages; For[i = 1, i < Length@b , i++ , Print[i, ". ", #[[2]], " - ", #[[1]] ]&@ Part[Reverse@SortBy[b, Last], i]] ``` {{out|Output : As of 29 February 2012}} ```txt 1. 637 - Tcl 2. 576 - C 3. 558 - J 4. 538 - Go 5. 485 - Ada 6. 456 - D 7. 450 - Haskell 8. 441 - Mathematica 9. 432 - Java 10. 425 - Icon ... ``` ## Nim ```nim import httpclient, json, re, strutils, algorithm const langSite = "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Languages&cmlimit=500&format=json" catSize = "http://www.rosettacode.org/w/index.php?title=Special:Categories&limit=5000" let regex = re"title=""Category:(.*?)"">.+?.*\((.*) members\)" var langs: seq[string] = @[] for l in parseJson(getContent(langSite))["query"]["categorymembers"]: langs.add(l["title"].str.split("Category:")[1]) var ranks: seq[tuple[lang: string, count: int]] = @[] for line in getContent(catSize).findAll(regex): let lang = line.replacef(regex, "$1") if lang in langs: let count = parseInt(line.replacef(regex, "$2").strip()) ranks.add((lang, count)) ranks.sort(proc (x, y): int = cmp[int](y.count, x.count)) for i, l in ranks: echo align($(i+1), 3), align($l.count, 5), " - ", l.lang ``` Output: ```txt 1 833 - Tcl 2 781 - Racket 3 770 - Python 4 730 - Perl 6 5 725 - J 6 712 - C 7 708 - Ruby 8 698 - D 9 674 - Go 10 656 - Perl ... ``` ## Objeck ```objeck 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(" ", " ")); }; }; }; 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("