Rosetta Code/Find unimplemented tasks: Difference between revisions
(added Haskell) |
(→{{header|J}}: update to use web/http addon) |
||
Line 206: | Line 206: | ||
=={{header|J}}== |
=={{header|J}}== |
||
'''Solution:''' |
|||
Use <code>getHTTP</code> from [[Web Scraping#J|Web Scraping]] |
|||
<lang j>require 'web/gethttp' |
|||
findUnimpTasks=: 'Programming_Tasks' /:~@([ #~ -.@e.)&getTasks ] |
|||
NB. Utility verbs |
|||
require 'strings' |
|||
safe=. (33}.127{.a.)-.'=&%+' |
|||
encode=: [: toupper ('%',(I.'6'=,3!:3'f') {&, 3!:3) |
|||
urlencode=: [: ; encode^:(safe -.@e.~ ])&.> |
|||
NB. RosettaCode Utilities |
NB. RosettaCode Utilities |
||
Line 222: | Line 217: | ||
makeuri=. 'http://rosettacode.org/json/isb/', ,&'.json' |
makeuri=. 'http://rosettacode.org/json/isb/', ,&'.json' |
||
uri=. makeuri urlencode y |
uri=. makeuri urlencode y |
||
parseTaskNames |
parseTaskNames gethttp uri |
||
)</lang> |
)</lang> |
||
Example Usage: |
'''Example Usage:''' |
||
<lang j> 4{. findUnimpTasks 'J' NB. get first 4 unimplemented tasks for J |
<lang j> 4{. findUnimpTasks 'J' NB. get first 4 unimplemented tasks for J |
||
+-------------+--------------+---------------+----------------+ |
+-------------+--------------+----------------+------------------------------+ |
||
|Active object|Atomic updates|Basic input loop|Call foreign language function| |
|||
|Active_object|Atomic_updates|Basic_Animation|Basic_input_loop| |
|||
+-------------+--------------+---------------+----------------+</lang> |
+-------------+--------------+----------------+------------------------------+</lang> |
||
=={{header|Perl}}== |
=={{header|Perl}}== |
Revision as of 00:45, 29 January 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. Use these JSON files as source information.
AutoHotkey
<lang AutoHotkey>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
}</lang>
C#
Using JSON (not parsed, just Regex.)
<lang csharp>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); }
}</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 'web/gethttp'
findUnimpTasks=: 'Programming_Tasks' /:~@([ #~ -.@e.)&getTasks ]
NB. RosettaCode Utilities parseTaskNames=: '","' splitstring _2 }. 2 }. ]
getTasks=: monad define
makeuri=. 'http://rosettacode.org/json/isb/', ,&'.json' uri=. makeuri urlencode y parseTaskNames gethttp uri
)</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>
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
Uses the RosettaCode
module from Count programming examples#Ruby
<lang 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")</lang>
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>