Rosetta Code/Find unimplemented tasks: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
Line 176: Line 176:
set base_url http://www.rosettacode.org/w/api.php
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 {action query list categorymembers cmtitle Category:%s format json cmlimit 500}
set this_query [dict create {*}[format $query $category]]
set this_query [dict create {*}[split [format $query $category]]]
set tasks [list]
set tasks [list]



Revision as of 12:54, 17 April 2009

Task
Rosetta Code/Find unimplemented tasks
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.

E

Using JSON.

<lang>

  1. !/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 [<language>]
  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)
    ) -> {
   
   # Compute difference and report
   def notDoneTasks := allTasks &! doneTasks
   println()
   println("\n".rjoin(notDoneTasks.getElements().sort()))

} catch p {

   # Whoops, something went wrong
   stderr.println(`$p${p.eStack()}`)

} </lang>

Perl

Using JSON, though we don't bother actually parsing it.

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

Python

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

Details: It does not guarantee that all members of the category are fetched, only the first 500.

Using XML.

<lang python>import xml.dom.minidom import urllib, sys

def do(category):

   x = urllib.urlopen("http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:%s&cmlimit=500&format=xml" % urllib.quote(category)).read()
   x = xml.dom.minidom.parseString(x)
   x = [i.getAttribute("title") for i in x.getElementsByTagName("cm")]    
   return x

alltasks = do("Programming_Tasks") lang = do(sys.argv[1])

for i in [i for i in alltasks if i not in lang]:

   print i</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 tcllib <lang tcl>package require Tcl 8.5 package require http package require json package require struct::set

fconfigure stdout -buffering none

proc get_tasks {category} {

   set start [clock milliseconds]
   puts -nonewline "getting $category members..."
   set base_url http://www.rosettacode.org/w/api.php
   set query {action query list categorymembers cmtitle Category:%s format json cmlimit 500}
   set this_query [dict create {*}[split [format $query $category]]]
   set tasks [list]
   while {1} {
       set url [join [list $base_url [http::formatQuery {*}$this_query]] ?]
       set response [http::geturl $url]
       if {[set s [http::status $response]] ne "ok" || [http::ncode $response] != 200} {
           error "Oops: url=$url\nstatus=$s\nhttp code=[http::code $response]"
       }
       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] != 0} {
           # no more continuations, we're done
           break
       }
       dict set this_query cmcontinue $continue_task
   }
   puts " found [llength $tasks] tasks in [expr {[clock milliseconds] - $start}] milliseconds"
   return $tasks

}

proc get_unimplemented {lang} {

   set unimplemented [struct::set difference [get_tasks Programming_Tasks] [get_tasks $lang]]
   puts "\n$lang has [llength $unimplemented] unimplemented programming tasks:"
   puts [join [lsort $unimplemented] \n]

}

get_unimplemented Tcl</lang>