Rosetta Code/Find unimplemented tasks

From Rosetta Code

(Redirected from Find unimplemented tasks)
Jump to: navigation, search
Rosetta Code/Find unimplemented tasks is a programming task. Visitors like you are encouraged to solve it according to the task description, using any language they may happen to know.
Add to BlogMarksAdd to del.icio.usAdd to diggAdd to NewsvineAdd to redditAdd to Slashdot

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.

Contents

[edit] AutoHotkey

This example is incorrect. Does not implement fetching more than one page of results. Please fix the code and remove this message.


MsgBox % getUnimplemented("AutoHotkey")
MsgBox % getUnimplemented("Python")
 
getUnimplemented(category)
{
url := "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:"
. category . "&cmlimit=500&format=xml"
url2 := "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml"
 
UrlDownloadToFile, %url%, unimplemented.html
UrlDownloadToFile, %url2%, alltasks.html
FileRead, category2, unimplemented.html
FileRead, alltasks, alltasks.html
pos = 1
reg = title="[^"]+"  ; "
While (pos := RegexMatch(alltasks, reg, title, pos))
{
StringReplace, title, title, title=
StringReplace, title, title, `", ,All ; "
If !InStr(category2, title)
todo .= title . "`n"
pos += 1
}
Return todo
}

[edit] C#

This example is incorrect. Does not implement fetching more than one page of results. Please fix the code and remove this message.

Using JSON (not parsed, just Regex.)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Net;
 
class Program {
static string[] GetTitlesFromCategory(string category) {
string content = new WebClient().DownloadString(
String.Format("http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:{0}&cmlimit=500&format=json", category)
);
 
return new Regex("\"title\":\"(.+?)\"").Matches(content).Cast<Match>().Select(x => x.Groups[1].Value).ToArray();
}
 
static string[] GetUnimplementedTasksFromLanguage(string language) {
List<string> alltasks = GetTitlesFromCategory("Programming_Tasks").ToList();
List<string> lang = GetTitlesFromCategory(language).ToList();
 
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);
}
}

[edit] E

Using JSON.

#!/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()}`)
}

[edit] Haskell

Library: HTTP XML from HackageDB

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

[edit] J

Solution:

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
)

Example Usage:

   4{. findUnimpTasks 'J'     NB. get first 4 unimplemented tasks for J
+-------------+--------------+----------------+------------------------------+
|Active object|Atomic updates|Basic input loop|Call foreign language function|
+-------------+--------------+----------------+------------------------------+

[edit] Oz

Library: OzHttpClient

By parsing XML and using an XPath-like mechanism:

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}

[edit] Perl

Using JSON (not parsed, just Regex.)

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;

See also: User:ImplSearchBot/Code

[edit] Python

Using XML.

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

[edit] R

Library: XML (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

[edit] Ruby

Uses the RosettaCode module from Count programming examples#Ruby

require 'rosettacode'
 
module RosettaCode
def RosettaCode.rc_unimplemented(lang)
programming_tasks = []
rc_tasks("Programming_Tasks") {|task| programming_tasks << task}
lang_tasks = []
rc_tasks(lang) {|task| lang_tasks << task}
programming_tasks - lang_tasks
end
end
 
lang = "Ruby"
unimplemented = RosettaCode.rc_unimplemented(lang)
puts "#{lang} has #{unimplemented.length} unimplemented tasks:"
puts unimplemented.join("\n")

[edit] 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 Library: tcllib

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
}
Personal tools
Google AdSense