Rosetta Code/Find unimplemented tasks

Revision as of 00:48, 29 January 2010 by Tikkanz (talk | contribs) (→‎{{header|J}}: still need strings script)

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.

Task
Rosetta Code/Find unimplemented tasks
You are encouraged to solve this task according to the task description, using any language you may know.

AutoHotkey

This example is incorrect. Please fix the code and remove this message.

Details: Does not implement fetching more than one page of results.

<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#

This example is incorrect. Please fix the code and remove this message.

Details: Does not implement fetching more than one page of results.

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

  1. NOTE: This program will not work in released E, because TermL is an
  2. imperfect superset of JSON in that version: it does not accept "\/".
  3. If you build E from the latest source in SVN then it will work.
  4. Usage: rosettacode-cat-subtract.e [<lang e>]
  5. Prints a list of tasks which have not been completed in the language.
  6. 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(), "")

}

  1. Interpret program arguments

def lang := switch (interp.getArgs()) {

 match [lang] { lang }
 match [] { "E" }

}

  1. 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

Library: HTTP XML

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' /:~@([ #~ -.@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

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

  1. 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

Library: tcllib

<lang tcl>package require Tcl 8.5 package require http package require json package require struct::set

fconfigure stdout -buffering none

  1. 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>