Rosetta Code/Find unimplemented tasks: Difference between revisions
(→{{header|AutoHotkey}}: New, working (?) version with GUI) |
|||
Line 7: | Line 7: | ||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
{{incorrect|AutoHotkey|Does not implement fetching more than one page of results.}} |
|||
The GUI overkill version. Most code is encoding/decoding to/from listview. |
|||
<lang AutoHotkey>MsgBox % getUnimplemented("AutoHotkey") |
|||
<lang AutoHotkey> |
|||
MsgBox % getUnimplemented("Python") |
|||
#NoEnv |
|||
#SingleInstance force |
|||
SetBatchLines, -1 |
|||
SetControlDelay, 0 |
|||
AutoExec: |
|||
getUnimplemented(category) |
|||
Gui, Add, DDL, x10 y10 w270 r20 vlngStr |
|||
{ |
|||
Gui, Add, Button, x290 y10 gShowLng, Show Unimplemented |
|||
url := "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:" |
|||
Gui, Add, ListView, x10 y36 w400 h300 vcatLst gOnLV, Unimplemented |
|||
. category . "&cmlimit=500&format=xml" |
|||
Gui, Add, StatusBar, vsbStr, Loading available languages... Please wait. |
|||
url2 := "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml" |
|||
Gui, Show, , RosettaCode unimplemented list |
|||
allLng := getList("lng") |
|||
selectStr = Select language... |
|||
GuiControl, , LngStr, |%selectStr%||%allLng% |
|||
SB_SetIcon("user32.dll", 5) |
|||
SB_SetText("Done loading languages. Select from menu.") |
|||
Return |
|||
ShowLng: |
|||
UrlDownloadToFile, %url%, unimplemented.html |
|||
Gui, Submit, NoHide |
|||
UrlDownloadToFile, %url2%, alltasks.html |
|||
If (lngStr != selectStr) |
|||
FileRead, category2, unimplemented.html |
|||
FileRead, alltasks, alltasks.html |
|||
pos = 1 |
|||
reg = title="[^"]+" ; " |
|||
While (pos := RegexMatch(alltasks, reg, title, pos)) |
|||
{ |
{ |
||
SB_SetIcon("user32.dll", 2) ; exclamation |
|||
StringReplace, title, title, title= |
|||
SB_SetText("Loading unimplemented tasks... Please wait.") |
|||
StringReplace, title, title, `", ,All ; " |
|||
allTsk := getList("tsk") |
|||
If !InStr(category2, title) |
|||
allThis := getList(lngStr) |
|||
todo .= title . "`n" |
|||
Loop, Parse, allTsk, | |
|||
{ |
|||
If !InStr(allThis,A_LoopField) |
|||
notImpl .= A_LoopField . "|" |
|||
allTskCnt := A_Index |
|||
} |
|||
StringTrimRight, notImpl, notImpl, 1 |
|||
LV_Delete() |
|||
GuiControl, -Redraw, catLst |
|||
Loop, Parse, notImpl, | |
|||
{ |
|||
LV_Add("", A_LoopField) |
|||
notImplCnt := A_Index |
|||
} |
|||
GuiControl, +Redraw, catLst |
|||
SB_SetIcon("user32.dll", 5) ; information |
|||
SB_SetText("There are " . notImplCnt . " of " . allTskCnt |
|||
. " tasks unimplemented. Double-click task to open in browser.") |
|||
notImpl = |
|||
notImplCnt = 0 |
|||
} |
} |
||
Return |
|||
}</lang> |
|||
OnLV: |
|||
If (A_GuiEvent = "DoubleClick") |
|||
{ |
|||
LV_GetText(rowTxt, A_EventInfo) |
|||
rowTxt := Enc_Uri(rowTxt) |
|||
StringReplace, rowTxt, rowTxt, `%20, _, All |
|||
Run % "http://rosettacode.org/wiki/" . rowTxt |
|||
} |
|||
Return |
|||
getList(category) |
|||
{ |
|||
fileName = temp.xml |
|||
If (category = "lng") |
|||
{ |
|||
category = Programming_Languages |
|||
fileName = lng.xml |
|||
IfExist, %fileName% |
|||
{ |
|||
FileGetTime, modTime, %fileName% |
|||
EnvSub, modTime, %A_Now%, days |
|||
If (modTime < 3) ; reload on older than 3 days |
|||
Goto, GetFileNoDL |
|||
} |
|||
} |
|||
If (category = "tsk") |
|||
category = Programming_Tasks |
|||
getFile: |
|||
url := "http://www.rosettacode.org/w/api.php?action=query&list=" |
|||
. "categorymembers&cmtitle=Category:" . category |
|||
. "&cmlimit=500&format=xml" . continue |
|||
UrlDownloadToFile, %url%, %fileName% |
|||
getFileNoDL: |
|||
FileRead, data, %fileName% |
|||
pos = 1 |
|||
rxp = title="(.*?)" |
|||
While (pos := RegExMatch(data, rxp, title, pos)) |
|||
{ |
|||
If InStr(title1, "Category:") |
|||
StringTrimLeft, title1, title1, 9 |
|||
StringReplace, title1, title1, |, `|, All |
|||
title1 := Dec_XML(UTF82Ansi(title1)) |
|||
allTitles .= title1 . "|" |
|||
pos++ |
|||
} |
|||
rxp = cmcontinue="(.*?)" |
|||
If RegExMatch(data, rxp, next) |
|||
{ |
|||
continue = &cmcontinue=%next1% |
|||
Goto getFile |
|||
} |
|||
StringTrimRight, allTitles, allTitles, 1 |
|||
Return allTitles |
|||
} |
|||
Dec_XML(str) |
|||
{ |
|||
Loop |
|||
If RegexMatch(str, "S)(&#(\d+);)", dec) |
|||
StringReplace, str, str, %dec1%, % Chr(dec2), All |
|||
Else If RegexMatch(str, "Si)(&#x([\da-f]+);)", hex) |
|||
StringReplace, str, str, %hex1%, % Chr("0x" . hex2), All |
|||
Else |
|||
Break |
|||
StringReplace, str, str, , %A_Space%, All |
|||
StringReplace, str, str, ", ", All |
|||
StringReplace, str, str, ', ', All |
|||
StringReplace, str, str, <, <, All |
|||
StringReplace, str, str, >, >, All |
|||
StringReplace, str, str, &, &, All |
|||
return, str |
|||
} |
|||
Enc_XML(str, chars="") |
|||
{ |
|||
StringReplace, str, str, &, &, All |
|||
StringReplace, str, str, ", ", All |
|||
StringReplace, str, str, ', ', All |
|||
StringReplace, str, str, <, <, All |
|||
StringReplace, str, str, >, >, All |
|||
Loop, Parse, chars |
|||
StringReplace, str, str, %A_LoopField%, % "&#" . Asc(A_LoopField) . "`;", All |
|||
return, str |
|||
} |
|||
Enc_Uri(str) |
|||
{ |
|||
f = %A_FormatInteger% |
|||
SetFormat, Integer, Hex |
|||
If RegExMatch(str, "^\w+:/{0,2}", pr) |
|||
StringTrimLeft, str, str, StrLen(pr) |
|||
StringReplace, str, str, `%, `%25, All |
|||
Loop |
|||
If RegExMatch(str, "i)[^\w\.~%/:]", char) |
|||
StringReplace, str, str, %char%, % "%" . SubStr(Asc(char),3), All |
|||
Else Break |
|||
SetFormat, Integer, %f% |
|||
Return, pr . str |
|||
} |
|||
UTF82Ansi(zString) |
|||
{ |
|||
Ansi2Unicode(zString, wString, 65001) |
|||
Unicode2Ansi(wString, sString, 0) |
|||
Return sString |
|||
} |
|||
Ansi2Unicode(ByRef sString, ByRef wString, CP = 0) |
|||
{ |
|||
nSize := DllCall("MultiByteToWideChar", "Uint", CP |
|||
, "Uint", 0, "Uint", &sString, "int", -1 |
|||
, "Uint", 0, "int", 0) |
|||
VarSetCapacity(wString, nSize * 2) |
|||
DllCall("MultiByteToWideChar" |
|||
, "Uint", CP, "Uint", 0, "Uint", &sString, "int", -1 |
|||
, "Uint", &wString, "int", nSize) |
|||
} |
|||
Unicode2Ansi(ByRef wString, ByRef sString, CP = 0) |
|||
{ |
|||
nSize := DllCall("WideCharToMultiByte" |
|||
, "Uint", CP, "Uint", 0, "Uint", &wString, "int", -1 |
|||
, "Uint", 0, "int", 0, "Uint", 0, "Uint", 0) |
|||
VarSetCapacity(sString, nSize) |
|||
DllCall("WideCharToMultiByte" |
|||
, "Uint", CP, "Uint", 0, "Uint", &wString, "int", -1 |
|||
, "str", sString, "int", nSize, "Uint", 0, "Uint", 0) |
|||
} |
|||
GuiClose: |
|||
ExitApp |
|||
Return |
|||
</lang> |
|||
===Output=== |
|||
Loads a list of all languages. Pick the language you would like to see the unimplemented tasks of, press the button, double click the selected task to launch in default browser. |
|||
[[Image:Ahk_find_unimplemented.png]] |
|||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
Revision as of 18:23, 22 August 2010
You are encouraged to solve this task according to the task description, using any language you may know.
Given the name of a language on Rosetta Code, find all tasks which are not implemented in that language.
Note: Implementations should allow for fetching more data than can be returned in one request to Rosetta Code.
You'll need to use the Media Wiki API, which you can find out about locally, here, or in Media Wiki's API documentation at, API:Query
AutoHotkey
The GUI overkill version. Most code is encoding/decoding to/from listview. <lang AutoHotkey>
- NoEnv
- SingleInstance force
SetBatchLines, -1 SetControlDelay, 0
AutoExec:
Gui, Add, DDL, x10 y10 w270 r20 vlngStr Gui, Add, Button, x290 y10 gShowLng, Show Unimplemented Gui, Add, ListView, x10 y36 w400 h300 vcatLst gOnLV, Unimplemented Gui, Add, StatusBar, vsbStr, Loading available languages... Please wait. Gui, Show, , RosettaCode unimplemented list allLng := getList("lng") selectStr = Select language... GuiControl, , LngStr, |%selectStr%||%allLng% SB_SetIcon("user32.dll", 5) SB_SetText("Done loading languages. Select from menu.")
Return
ShowLng:
Gui, Submit, NoHide If (lngStr != selectStr) { SB_SetIcon("user32.dll", 2) ; exclamation SB_SetText("Loading unimplemented tasks... Please wait.") allTsk := getList("tsk") allThis := getList(lngStr) Loop, Parse, allTsk, | { If !InStr(allThis,A_LoopField) notImpl .= A_LoopField . "|" allTskCnt := A_Index } StringTrimRight, notImpl, notImpl, 1 LV_Delete() GuiControl, -Redraw, catLst Loop, Parse, notImpl, | { LV_Add("", A_LoopField) notImplCnt := A_Index } GuiControl, +Redraw, catLst SB_SetIcon("user32.dll", 5) ; information SB_SetText("There are " . notImplCnt . " of " . allTskCnt . " tasks unimplemented. Double-click task to open in browser.") notImpl = notImplCnt = 0 }
Return
OnLV:
If (A_GuiEvent = "DoubleClick") { LV_GetText(rowTxt, A_EventInfo) rowTxt := Enc_Uri(rowTxt) StringReplace, rowTxt, rowTxt, `%20, _, All Run % "http://rosettacode.org/wiki/" . rowTxt }
Return
getList(category) {
fileName = temp.xml If (category = "lng") { category = Programming_Languages fileName = lng.xml IfExist, %fileName% { FileGetTime, modTime, %fileName% EnvSub, modTime, %A_Now%, days If (modTime < 3) ; reload on older than 3 days Goto, GetFileNoDL } } If (category = "tsk") category = Programming_Tasks
getFile: url := "http://www.rosettacode.org/w/api.php?action=query&list=" . "categorymembers&cmtitle=Category:" . category . "&cmlimit=500&format=xml" . continue UrlDownloadToFile, %url%, %fileName%
getFileNoDL: FileRead, data, %fileName% pos = 1 rxp = title="(.*?)" While (pos := RegExMatch(data, rxp, title, pos)) { If InStr(title1, "Category:") StringTrimLeft, title1, title1, 9 StringReplace, title1, title1, |, `|, All title1 := Dec_XML(UTF82Ansi(title1)) allTitles .= title1 . "|" pos++ } rxp = cmcontinue="(.*?)" If RegExMatch(data, rxp, next) { continue = &cmcontinue=%next1% Goto getFile } StringTrimRight, allTitles, allTitles, 1 Return allTitles
}
Dec_XML(str)
{
Loop If RegexMatch(str, "S)(&#(\d+);)", dec) StringReplace, str, str, %dec1%, % Chr(dec2), All Else If RegexMatch(str, "Si)(&#x([\da-f]+);)", hex) StringReplace, str, str, %hex1%, % Chr("0x" . hex2), All Else Break StringReplace, str, str, , %A_Space%, All StringReplace, str, str, ", ", All StringReplace, str, str, ', ', All StringReplace, str, str, <, <, All StringReplace, str, str, >, >, All StringReplace, str, str, &, &, All return, str
}
Enc_XML(str, chars="") {
StringReplace, str, str, &, &, All StringReplace, str, str, ", ", All StringReplace, str, str, ', ', All StringReplace, str, str, <, <, All StringReplace, str, str, >, >, All Loop, Parse, chars StringReplace, str, str, %A_LoopField%, % "&#" . Asc(A_LoopField) . "`;", All return, str
}
Enc_Uri(str) {
f = %A_FormatInteger% SetFormat, Integer, Hex If RegExMatch(str, "^\w+:/{0,2}", pr) StringTrimLeft, str, str, StrLen(pr) StringReplace, str, str, `%, `%25, All Loop If RegExMatch(str, "i)[^\w\.~%/:]", char) StringReplace, str, str, %char%, % "%" . SubStr(Asc(char),3), All Else Break SetFormat, Integer, %f% Return, pr . str
}
UTF82Ansi(zString) {
Ansi2Unicode(zString, wString, 65001) Unicode2Ansi(wString, sString, 0) Return sString
}
Ansi2Unicode(ByRef sString, ByRef wString, CP = 0) {
nSize := DllCall("MultiByteToWideChar", "Uint", CP , "Uint", 0, "Uint", &sString, "int", -1 , "Uint", 0, "int", 0) VarSetCapacity(wString, nSize * 2) DllCall("MultiByteToWideChar" , "Uint", CP, "Uint", 0, "Uint", &sString, "int", -1 , "Uint", &wString, "int", nSize)
}
Unicode2Ansi(ByRef wString, ByRef sString, CP = 0) {
nSize := DllCall("WideCharToMultiByte" , "Uint", CP, "Uint", 0, "Uint", &wString, "int", -1 , "Uint", 0, "int", 0, "Uint", 0, "Uint", 0) VarSetCapacity(sString, nSize) DllCall("WideCharToMultiByte" , "Uint", CP, "Uint", 0, "Uint", &wString, "int", -1 , "str", sString, "int", nSize, "Uint", 0, "Uint", 0)
}
GuiClose:
ExitApp
Return </lang>
Output
Loads a list of all languages. Pick the language you would like to see the unimplemented tasks of, press the button, double click the selected task to launch in default browser.
C#
Using JSON (not parsed, just Regex.)
To help demonstrate paging, the cmlimit parameter has been omitted from the search query so that 10 rows are returned by default
<lang csharp>using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Net;
class Program {
static List<string> GetTitlesFromCategory(string category) { string searchQueryFormat = "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:{0}&format=json{1}"; List<string> results = new List<string>(); string cmcontinue = string.Empty;
do { string cmContinueKeyValue;
//append continue variable as needed if (cmcontinue.Length > 0) cmContinueKeyValue = String.Format("&cmcontinue={0}", cmcontinue); else cmContinueKeyValue = String.Empty;
//execute query string query = String.Format(searchQueryFormat, category, cmContinueKeyValue); string content = new WebClient().DownloadString(query);
results.AddRange(new Regex("\"title\":\"(.+?)\"").Matches(content).Cast<Match>().Select(x => x.Groups[1].Value));
//detect if more results are available cmcontinue = Regex.Match(content, @"{""cmcontinue"":""([^""]+)""}", RegexOptions.IgnoreCase).Groups["1"].Value; } while (cmcontinue.Length > 0);
return results; }
static string[] GetUnimplementedTasksFromLanguage(string language) { List<string> alltasks = GetTitlesFromCategory("Programming_Tasks"); List<string> lang = GetTitlesFromCategory(language);
return alltasks.Where(x => !lang.Contains(x)).ToArray(); }
static void Main(string[] args) { string[] unimpl = GetUnimplementedTasksFromLanguage(args[0]);
foreach (string i in unimpl) Console.WriteLine(i); }
}</lang>
Clojure
This uses a couple of core libraries, and a Java method for URL encoding. <lang clojure>(require
'[clojure.xml :as xml] '[clojure.set :as set])
(import '[java.net URLEncoder])</lang>
The titles-cont function fetches and parses an XML response, and walks over it extracting titles. It also extracts the cmcontinue value, if present. Returns a pair [titles,cmcontinue]. <lang clojure>(defn titles-cont [url]
(let [docseq (-> url xml/parse xml-seq)] ((juxt #(filter string? %), #(-> (filter map? %) first :cmcontinue)) (for [{:keys [tag attrs content]} docseq :when (#{:cm :query-continue} tag)] (if (= tag :cm) (attrs :title) (-> content first :attrs))))))</lang>
The get-titles function has 1- and 2-argument versions. The former takes the name of a category, composes the appropriate URL query, and calls the 2-argument version. The 2-argument version gets a title list (with possible cmcontinue value), chaining further calls as necessary into the lazy sequence result. <lang clojure>(defn urlencode [s] (URLEncoder/encode s "UTF-8")) (defn param [p v] (str p (urlencode v))) (defn join [sep items] (apply str (interpose sep items)) ; 'join is a core function in Clojure 1.2
(defn get-titles
([category] (let [urlbase "http://www.rosettacode.org/w/api.php" params ["action=query" "list=categorymembers" "format=xml" "cmlimit=200" (param "cmtitle=Category:" category)] url (str urlbase "?" (join "&" params)] (get-titles url nil))) ([url continue-at] (let [continue-param (if continue-at (param "&cmcontinue=" continue-at)) [titles continue] (titles-cont (str url continue-param))] (if continue (lazy-cat titles (get-titles url continue)) titles))))</lang>
The unimplemented function gets a set of all titles and of language-implemented titles and returns the difference. It uses future in order to do the necessary URL requests in parallel. <lang clojure>(defn unimplemented [lang-name]
(let [title-set #(future (apply sorted-set (get-titles %))) all-titles (title-set "Programming_Tasks") lang-titles (title-set lang-name)] (seq (set/difference @all-titles @lang-titles))))
(let [titles (unimplemented "Clojure")]
(doseq [title titles] (println title)) (println "count: " (count titles)))
(shutdown-agents)</lang>
E
Using JSON.
<lang e>#!/usr/bin/env rune
- NOTE: This program will not work in released E, because TermL is an
- imperfect superset of JSON in that version: it does not accept "\/".
- If you build E from the latest source in SVN then it will work.
- Usage: rosettacode-cat-subtract.e [<lang e>]
- Prints a list of tasks which have not been completed in the language.
- If unspecified, the default language is E.
pragma.syntax("0.9") pragma.enable("accumulator")
def termParser := <import:org.quasiliteral.term.makeTermParser> def jURLEncoder := <unsafe:java.net.makeURLEncoder>
def urlEncode(text) {
return jURLEncoder.encode(text, "UTF-8")
}
/** Convert JSON-as-term-tree to the corresponding natural E data structures. */ def jsonTermToData(term) {
switch (term) {
# JSON object to E map match term`{@assocs*}` { return accum [].asMap() for term`@{key :String}: @valueJson` in assocs { _.with(key, jsonTermToData(valueJson)) } }
# JSON array to E list match term`[@elements*]` { return accum [] for elem in elements { _.with(jsonTermToData(elem)) } } # Literals just need to be coerced match lit :any[String, int, float64] { return lit } # Doesn't support true/false/null, but we don't need that for this application. }
}
def fetchCategoryAccum(name, membersSoFar :Set, extraArgs) {
stderr.println(`Fetching Category:$name $extraArgs...`) def categoryAPIResource := <http>[`//rosettacode.org/w/api.php?` + `action=query&list=categorymembers&cmtitle=Category:${urlEncode(name)}&` + `format=json&cmlimit=500&cmprop=title$extraArgs`] def members := when (def responseJSON := categoryAPIResource <- getTwine()) -> { # stderr.println(`Fetched Category:$name $extraArgs, parsing...`) def response := jsonTermToData(termParser(responseJSON))
# stderr.println(`Parsed Category:$name $extraArgs response, extracting data...`) def [ "query" => ["categorymembers" => records], "query-continue" => continueData := null ] := response def members := accum membersSoFar for record in records { _.with(record["title"]) } switch (continueData) { match ==null { stderr.println(`Got all ${members.size()} for Category:$name.`) members } match ["categorymembers" => ["cmcontinue" => continueParam]] { stderr.println(`Fetched ${members.size()} members for Category:$name...`) fetchCategoryAccum(name, members, `&cmcontinue=` + urlEncode(continueParam)) } } } catch p { throw(p) } return members
}
def fetchCategory(name) {
return fetchCategoryAccum(name, [].asSet(), "")
}
- Interpret program arguments
def lang := switch (interp.getArgs()) {
match [lang] { lang } match [] { "E" }
}
- Fetch categories
when (def allTasks := fetchCategory("Programming_Tasks"),
def doneTasks := fetchCategory(lang), def omitTasks := fetchCategory(lang + "/Omit") ) -> { # Compute difference and report def notDoneTasks := allTasks &! (doneTasks | omitTasks) println() println("\n".rjoin(notDoneTasks.getElements().sort()))
} catch p {
# Whoops, something went wrong stderr.println(`$p${p.eStack()}`)
}</lang>
Haskell
from HackageDB
<lang haskell>import Network.Browser import Network.HTTP import Network.URI import Data.List import Data.Maybe import Text.XML.Light import Control.Arrow import Data.Char
getRespons url = do
rsp <- Network.Browser.browse $ do setAllowRedirects True setOutHandler $ const (return ()) -- quiet request $ getRequest url return $ rspBody $ snd rsp
replaceWithSpace c = (\x -> if c==x then ' ' else x)
encl = chr 34
unimpTasks lang = do
allTasks <- getRespons "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml" impl <- getRespons ( "http://rosettacode.org/json/isb/" ++ lang ++ ".json") let langxx = map (map(replaceWithSpace '_')) $ filter (/=",") $ words $ map (replaceWithSpace encl ) $ init $ drop 1 impl xml = onlyElems $ parseXML allTasks allxx = concatMap (map (fromJust.findAttr (unqual "title")). filterElementsName (== unqual "cm")) xml mapM_ putStrLn $ sort $ allxx \\ langxx</lang>
J
Solution: <lang j>require 'strings web/gethttp'
findUnimpTasks=: ('Programming_Tasks' -.&getCategoryMembers ,&'/Omit') ([ #~ -.@e.) getCategoryMembers
getTagContents=: dyad define
'starttag endtag'=. x ('\' -.~ endtag&taketo)&.>@(starttag&E. <@((#starttag)&}.);.1 ]) y
)
NB. RosettaCode Utilities parseTitles=: ('"title":"';'"')&getTagContents parseCMcontinue=:('"cmcontinue":"';'"')&getTagContents getCMcontquery=: ('&cmcontinue=' , urlencode)^:(0 < #)@>@parseCMcontinue
getCategoryMembers=: monad define
buildqry=. 'action=query&list=categorymembers&cmtitle=Category:' , ,&'&cmlimit=500&format=json' url=.'http://www.rosettacode.org/w/api.php' uri=. url ,'?', buildqry urlencode y catmbrs=. qrycont=. whilst. #qrycont=. getCMcontquery jsondat do. jsondat=. gethttp uri , qrycont catmbrs=. catmbrs, parseTitles jsondat end. catmbrs
)</lang>
Example Usage: <lang j> 4{. findUnimpTasks 'J' NB. get first 4 unimplemented tasks for J +-------------+--------------+----------------+------------------------------+ |Active object|Atomic updates|Basic input loop|Call foreign language function| +-------------+--------------+----------------+------------------------------+</lang>
Oz
By parsing XML and using an XPath-like mechanism: <lang oz>declare
[HTTPClient] = {Link ['x-ozlib://mesaros/net/HTTPClient.ozf']} [XMLParser] = {Link ['x-oz://system/xml/Parser.ozf']}
fun {FindUnimplementedTasks Language} AllTasks = {FindCategory "Programming Tasks"} LangTasks = {FindCategory Language} in {ListDiff AllTasks LangTasks} end fun {FindCategory Cat} CatUrl = "http://www.rosettacode.org/mw/api.php?action=query" #"&list=categorymembers" #"&cmtitle=Category:"#{PercentEncode Cat} #"&cmlimit=500&format=xml"
fun {Loop CMContinue} [_ Doc] = {Parse {GetPage CatUrl#CMContinue}} Titles = {XPath Doc [api query categorymembers cm {Attribute title}]} in case {XPath Doc [api 'query-continue' categorymembers {Attribute cmcontinue}]} of nil then Titles [] [NewCMContinueAtom] then NewCMContinue = {PercentEncode {Atom.toString NewCMContinueAtom}} in {Append Titles {Loop "&cmcontinue="#NewCMContinue}} end end in {Loop nil} end
%% XPath emulation fun {XPath Doc Path} P|Pr = Path in Doc.name = P %% assert {FoldL Pr XPathStep [Doc]} end
Nothing = {NewName} fun {NotNothing X} X \= Nothing end fun {XPathStep Elements P} if {Atom.is P} then {FilteredChildren Elements P} elseif {Procedure.is P} then {Filter {Map Elements P} NotNothing} end end %% A flat list of all Type-children of all Elements. fun {FilteredChildren Elements Type} {Flatten {Map Elements fun {$ E} {Filter E.children fun {$ X} case X of element(name:!Type ...) then true else false end end} end}} end fun {Attribute Attr} fun {$ Element} case {Filter Element.attributes fun {$ A} A.name == Attr end} of [A] then A.value else Nothing end end end
%% GetPage Client = {New HTTPClient.urlGET init(inPrms(toFile:false toStrm:true) _)} fun {GetPage RawUrl} Url = {VirtualString.toString RawUrl} OutParams in {Client getService(Url ?OutParams ?_)} OutParams.sOut end fun {PercentEncode Xs} case Xs of nil then nil [] X|Xr then if {Char.isDigit X} orelse {Member X [&- &_ &. &~]} orelse X >= &a andthen X =< &z orelse X >= &z andthen X =< &Z then X|{PercentEncode Xr} else {Append &%|{ToHex2 X} {PercentEncode Xr}} end end end fun {ToHex2 X} [{ToHex1 X div 16} {ToHex1 X mod 16}] end fun {ToHex1 X} if X >= 0 andthen X =< 9 then &0 + X elseif X >= 10 andthen X =< 15 then &A + X - 10 end end
%% Parse local Parser = {New XMLParser.parser init} in fun {Parse Xs} {Parser parseVS(Xs $)} end end
fun {ListDiff Xs Ys} {FoldL Ys List.subtract Xs} end
in
%% show tasks not implemented in Oz {ForAll {FindUnimplementedTasks "Oz"} System.showInfo}</lang>
Perl
Using JSON (not parsed, just Regex.)
<lang perl>use LWP::Simple 'get';
my $fmt = 'http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:%s&cmlimit=500&format=json'; my $lang = shift
or die "No language given.\n";
sub urlencode
{join , map {sprintf '%%%02x', ord} split //, shift}
sub tasks
{my $category = urlencode shift; my @tasks; my $json = get sprintf $fmt, $category; for (;;) {push @tasks, $json =~ /"title":"(.+?)"}/g; $json =~ /"cmcontinue":"(.+?)"}/ or last; $json = get sprintf $fmt . '&cmcontinue=%s', $category, urlencode $1;} return @tasks;}
my @all = tasks 'Programming_Tasks'; my %lang = map {$_, 1} tasks $lang
or die "No such category.\n";
$lang{$_} or print "$_\n"
foreach @all;</lang>
See also: User:ImplSearchBot/Code
Python
Using XML.
<lang python>import xml.dom.minidom import urllib, sys
def findrc(category):
name = "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:%s&cmlimit=500&format=xml" % urllib.quote(category) cmcontinue, titles = , [] while True: u = urllib.urlopen(name + cmcontinue) xmldata = u.read() u.close() x = xml.dom.minidom.parseString(xmldata) titles += [i.getAttribute("title") for i in x.getElementsByTagName("cm")] cmcontinue = filter( None, (urllib.quote(i.getAttribute("cmcontinue")) for i in x.getElementsByTagName("categorymembers")) ) if cmcontinue: cmcontinue = '&cmcontinue=' + cmcontinue[0] else: break return titles
alltasks = findrc("Programming_Tasks") lang = findrc(sys.argv[1])
for i in [i for i in alltasks if i not in lang]:
print i</lang>
R
<lang R>library(XML) find.unimplemented.tasks <- function(lang="R"){ PT <- xmlInternalTreeParse( paste("http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml",sep="") ) PT.nodes <- getNodeSet(PT,"//cm") PT.titles = as.character( sapply(PT.nodes, xmlGetAttr, "title") ) language <- xmlInternalTreeParse( paste("http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:", lang, "&cmlimit=500&format=xml",sep="") ) lang.nodes <- getNodeSet(language,"//cm") lang.titles = as.character( sapply(lang.nodes, xmlGetAttr, "title") ) unimplemented <- setdiff(PT.titles, lang.titles) unimplemented }
- Usage
find.unimplemented.tasks(lang="Python") langs <- c("R","python","perl") sapply(langs, find.unimplemented.tasks) # fetching data for multiple languages</lang>
Ruby
Finds tasks that are either not implemented or omitted. Sorts by task creation time.
Uses the RosettaCode
module from Count programming examples#Ruby
<lang ruby>require 'rosettacode'
require 'time'
module RosettaCode
def self.get_unimplemented(lang) programming_tasks = [] category_members("Programming_Tasks") {|task| programming_tasks << task}
lang_tasks = [] category_members(lang) {|task| lang_tasks << task}
lang_tasks_omit = [] category_members("#{lang}/Omit") {|task| lang_tasks_omit << task}
[programming_tasks - lang_tasks, lang_tasks_omit] end
def self.created_time(title) url = get_api_url({ "action" => "query", "titles" => title, "format" => "xml", "rvlimit" => 500, "prop" => "revisions", "rvprop" => "timestamp" }) doc = REXML::Document.new open(url) REXML::XPath.each(doc, "//rev").collect do |node| Time.parse( node.attribute("timestamp").value ) end.min end
end
puts Time.now lang = ARGV[0] || "Ruby" unimplemented, omitted = RosettaCode.get_unimplemented(lang) unimplemented.collect {|title| [title, RosettaCode.created_time(title)]} .
sort_by {|e| e[1]} . each do |title, date| puts "%s %6s %s" % [ date.strftime("%Y-%m-%d"), omitted.include?(title) ? "[omit]" : "" , title ] end
</lang>
Output for Ruby
2010-04-05 11:08:07 -0500 2007-01-14 Table creation 2007-01-25 [omit] Pointers and references 2007-02-04 SQL-based authentication 2007-02-09 Metered concurrency 2007-02-27 [omit] Address of a variable 2007-02-27 [omit] Variable size/Set 2007-02-27 Variable size/Get 2007-06-08 OpenGL 2007-06-08 HTTPS/Authenticated 2007-11-06 Pattern matching 2007-11-08 [omit] Parametric polymorphism 2007-11-13 Special characters 2007-12-11 Arithmetic evaluation 2007-12-21 [omit] Proof 2007-12-24 Plot coordinate pairs 2007-12-24 Polynomial regression 2007-12-24 Compare sorting algorithms' performance 2008-03-27 Dragon curve 2008-03-28 Formal power series 2008-09-11 RCRPG 2008-11-02 Active object 2008-11-13 Window creation/X11 2008-12-05 [omit] Constrained genericity 2009-02-17 Rendezvous 2009-03-22 Arena storage pool 2009-05-23 Ray-casting algorithm 2009-05-26 [omit] Memory allocation 2009-05-26 Simulate input/Mouse 2009-05-27 Mouse position 2009-05-27 Keyboard macros 2009-05-27 Window management 2009-05-27 Color of a screen pixel 2009-06-01 HTTPS/Client-authenticated 2009-06-02 Simulate input/Keyboard 2009-06-08 [omit] Create an object at a given address 2009-06-10 Events 2009-06-10 Scope modifiers 2009-08-09 Verify distribution uniformity/Chi-squared test 2009-08-11 Call a function from a foreign language 2009-08-12 Safe addition 2009-12-05 Rate counter 2010-01-02 Loading Animated 3D Data 2010-01-06 Catmull–Clark subdivision surface 2010-01-21 Hough transform 2010-01-25 Compile-time calculation 2010-02-14 Knapsack problem/Bounded 2010-02-21 Deconvolution/1D 2010-02-23 Deconvolution/2D+ 2010-02-24 Knapsack problem/Continuous 2010-03-23 Sutherland-Hodgman polygon clipping 2010-03-23 Find Common Directory Path
Tcl
First, find all members of the Programming_Tasks category, then find all members of the $lang
category. The difference is the list of unimplemented tasks.
This uses the json
and struct::set
packages from
<lang tcl>package require Tcl 8.5 package require http package require json package require struct::set
fconfigure stdout -buffering none
- Initialize a cache of lookups
array set cache {} proc log msg {
#puts -nonewline $msg
}
proc get_tasks {category} {
global cache if {[info exists cache($category)]} {
return $cache($category)
} set base_url http://www.rosettacode.org/w/api.php set query {
action query list categorymembers cmtitle Category:%s format json cmlimit 500
} set query [list {*}$query]; # remove excess whitespace set this_query [dict create {*}[split [format $query $category]]] set tasks [list] while {1} { set url [join [list $base_url [http::formatQuery {*}$this_query]] ?] while 1 { set response [http::geturl $url]
# Process redirects
if {[http::ncode $response] == 301} { set newurl [dict get [http::meta $response] Location] if {[string match http://* $newurl]} { set url $newurl } else { set url [regexp -inline {http://[^/]+} $url] append url $newurl } continue }
# Check for oopsies!
if {
[set s [http::status $response]] ne "ok" || [http::ncode $response] != 200 } then {
error "Oops: url=$url\nstatus=$s\nhttp code=[http::code $response]" } break }
# Get the data out of the message
set data [json::json2dict [http::data $response]] http::cleanup $response # add tasks to list foreach task [dict get $data query categorymembers] { lappend tasks [dict get [dict create {*}$task] title] } if {[catch {
dict get $data query-continue categorymembers cmcontinue } continue_task]} then {
# no more continuations, we're done break } dict set this_query cmcontinue $continue_task } return [set cache($category) $tasks]
}
proc get_unimplemented {lang} {
set tasks [get_tasks Programming_Tasks] set collected [get_tasks Collection_Members] set doneTasks [get_tasks $lang] set omittedTasks [get_tasks $lang/Omit]
# Map generic collection task categories to specific ones set tasks [regsub -all {Category:(\S+)} $tasks "\\1/$lang"]
set collectOfLang [struct::set intersect $collected $doneTasks] set ignorable [struct::set union $doneTasks $omittedTasks $collectOfLang] set unimplemented [struct::set difference $tasks $ignorable]
puts "\n$lang has [llength $unimplemented] unimplemented programming tasks:" if {[llength $unimplemented]} {
puts " [join [lsort $unimplemented] "\n "]"
}
}
foreach lang {Perl Python Ruby Tcl} {
get_unimplemented $lang
}</lang>