Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
|
|
@ -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
|
||||
27
Task/Rosetta-Code-Rank-languages-by-popularity/00-TASK.txt
Normal file
27
Task/Rosetta-Code-Rank-languages-by-popularity/00-TASK.txt
Normal 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:
|
||||
* 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 '''813''' languages (from the REXX example) is included here ──► [[RC_POP.OUT|output from the REXX program]].
|
||||
<br><br>
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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]
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
)
|
||||
)
|
||||
& ;
|
||||
|
|
@ -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 ;
|
||||
}
|
||||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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[]);
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
@ -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}.
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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" }
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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])" '
|
||||
|
|
@ -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
|
||||
|
|
@ -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, :])
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
|
@ -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]]
|
||||
|
|
@ -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}"
|
||||
|
|
@ -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(" ", " "));
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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'};
|
||||
}
|
||||
|
|
@ -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;">`"`</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;">`'`</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;">`<div class="printfooter">`</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;">"<h2>Subcategories</h2>"</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">Phix</a>?? (997 members)</li>
|
||||
-- but obviously only when we have found that language in the phase above.
|
||||
-- (note there is / ignore some wierd uncode-like stuff after the </a>...)</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;">"</a>"</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;">"(<"</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;">'<'</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)<"</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>
|
||||
<!--
|
||||
|
|
@ -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)) )
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -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))
|
||||
|
|
@ -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
|
||||
|
|
@ -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,]
|
||||
|
|
@ -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= 'D├⌐j├á' ; 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
|
||||
|
|
@ -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))
|
||||
|
|
@ -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}" }
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
]
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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>"
|
||||
|
|
@ -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
|
||||
|
|
@ -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])
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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})
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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 |
|
||||
+-----------------------+
|
||||
|
|
@ -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
|
||||
|
|
@ -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]
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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}'
|
||||
|
|
@ -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)
|
||||
|
|
@ -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])
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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())) }
|
||||
Loading…
Add table
Add a link
Reference in a new issue