Rosetta Code/Find unimplemented tasks

From Rosetta Code
Revision as of 05:12, 14 September 2009 by Tikkanz (talk | contribs) (→‎{{header|J}}: Update to new task specification)
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. Use these JSON files as source information.

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 [<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),
     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>

J

Use getHTTP from Web Scraping

<lang j> 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 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_Animation|Basic_input_loop| +-------------+--------------+---------------+----------------+ </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

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>