     libraryDependencies ++= Seq(
     "org.json4s"%%"json4s-native"%"3.6.0",
     "com.softwaremill.sttp"%%"core"%"1.5.11",
     "com.softwaremill.sttp"%%"json4s"%"1.5.11")


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/mw/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  "]"
    }
}

catch {console show}
catch {wm withdraw .}
foreach lang {Perl Python Ruby Tcl} {
    get_unimplemented $lang
}


/* rc_find_unimplemented_tasks.wren */

import "./pattern" for Pattern

var CURLOPT_URL = 10002
var CURLOPT_FOLLOWLOCATION = 52
var CURLOPT_WRITEFUNCTION = 20011
var CURLOPT_WRITEDATA = 10001

foreign class Buffer {
    construct new() {}  // C will allocate buffer of a suitable size

    foreign value       // returns buffer contents as a string
}

foreign class Curl {
    construct easyInit() {}

    foreign easySetOpt(opt, param)

    foreign easyPerform()

    foreign easyCleanup()
}

var curl = Curl.easyInit()

var getContent = Fn.new { |url|
    var buffer = Buffer.new()
    curl.easySetOpt(CURLOPT_URL, url)
    curl.easySetOpt(CURLOPT_FOLLOWLOCATION, 1)
    curl.easySetOpt(CURLOPT_WRITEFUNCTION, 0)  // write function to be supplied by C
    curl.easySetOpt(CURLOPT_WRITEDATA, buffer)
    curl.easyPerform()
    return buffer.value
}

var p1 = Pattern.new("title/=\"[+1^\"]\"")
var p2 = Pattern.new("cmcontinue/=\"[+1^\"]\"")

var findTasks = Fn.new { |category|
    var url = "https://www.rosettacode.org/mw/api.php?action=query&list=categorymembers&cmtitle=Category:%(category)&cmlimit=500&format=xml"
    var cmcontinue = ""
    var tasks = []
    while (true) {
        var content = getContent.call(url + cmcontinue)
        var matches1 = p1.findAll(content)
        for (m in matches1) {
            var title = m.capsText[0].replace("'", "'").replace(""", "\"")
            tasks.add(title)
        }
        var m2 = p2.find(content)
        if (m2) cmcontinue = "&cmcontinue=%(m2.capsText[0])" else break
    }
    return tasks
}

var tasks1 = findTasks.call("Programming_Tasks") // 'full' tasks only
var tasks2 = findTasks.call("Draft_Programming_Tasks")
var lang = "Wren"
var langTasks = findTasks.call(lang) // includes draft tasks
curl.easyCleanup()
System.print("Unimplemented 'full' tasks in %(lang):")
for (task in tasks1) {
    if (!langTasks.contains(task)) System.print("  " + task)
}
System.print("\nUnimplemented 'draft' tasks in %(lang):")
for (task in tasks2) {
    if (!langTasks.contains(task)) System.print("  " + task)
}


var [const] YAJL=Import("zklYAJL")[0], CURL=Import("zklCurl");

fcn getTasks(language){
   continueValue,tasks:="",Data(0,String);  // "nm\0nm\0...."
   do{
      page:=CURL().get(("http://rosettacode.org/mw/api.php?"
         "action=query&cmlimit=500"
	 "&format=json"
	 "&list=categorymembers"
	 "&cmtitle=Category:%s"
	 "&cmcontinue=%s").fmt(language,continueValue));
      page=page[0].del(0,page[1]);  // get rid of HTML header
      json:=YAJL().write(page).close();
      json["query"]["categorymembers"].pump(tasks,T("get","title"));
      continueValue=json.find("continue") //continue:-||,cmcontinue:page|954|19)
          .toList().apply("concat","=").concat("&");
   }while(continueValue);
   tasks
}

allTasks:=getTasks.future("Programming_Tasks");  // thread


task =
(
Description

<lang>Pseudocode</lang>

=={{header|C}}==
<lang C>printf("Hello world!\n");</lang>

=={{header|Perl}}==
<lang>print "Hello world!\n"</lang>
)
lang := "no language", out := Object(lang, 0), total := 0
Loop Parse, task, `r`n
	If RegExMatch(A_LoopField, "==\s*{{\s*header\s*\|\s*([^\s\}]+)\s*}}\s*==", $)
		lang := $1, out[lang] := 0
	else if InStr(A_LoopField, "<lang>")
		out[lang]++
For lang, num in Out
	If num
		total++, str .= "`n" num " in " lang
MsgBox % clipboard := total " bare lang tags.`n" . str


-module( find_bare_lang_tags ).

-export( [task/0] ).

task() ->
	{ok, Binary} = file:read_file( "priv/find_bare_lang_tags_1" ),
	Lines = string:tokens( erlang:binary_to_list(Binary), "\n" ),
	{_Lang, Dict} = lists:foldl( fun count_empty_lang/2, {"no language", dict:new()}, Lines ),
	Count_langs = [{dict:fetch(X, Dict), X} || X <- dict:fetch_keys(Dict)],
	io:fwrite( "~p bare language tags.~n", [lists:sum([X || {X, _Y} <- Count_langs])] ),
	[io:fwrite( "~p in ~p~n", [X, Y] ) || {X, Y} <- Count_langs].

count_empty_lang( Line, {Lang, Dict} ) ->
	Empty_lang = string:str( Line, "<lang>" ),
	New_dict = dict_update_counter( Empty_lang, Lang, Dict ),
	New_lang = new_lang( string:str( Line,"=={{header|" ), Line, Lang ),
	{New_lang, New_dict}.

dict_update_counter( 0, _Lang, Dict ) -> Dict;
dict_update_counter( _Start, Lang, Dict ) -> dict:update_counter( Lang, 1, Dict ).

new_lang( 0, _Line, Lang ) -> Lang;
new_lang( _Start, Line, _Lang ) ->
	Start = string:str( Line, "|" ),
	Stop = string:rstr( Line, "}}==" ),
	string:sub_string( Line, Start+1, Stop-1 ).


package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "regexp"
    "strings"
)

type header struct {
    start, end int
    lang       string
}

type data struct {
    count int
    names *[]string
}

func newData(count int, name string) *data {
    return &data{count, &[]string{name}}
}

var bmap = make(map[string]*data)

func add2bmap(lang, name string) {
    pd := bmap[lang]
    if pd != nil {
        pd.count++
        *pd.names = append(*pd.names, name)
    } else {
        bmap[lang] = newData(1, name)
    }
}

func check(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

func main() {
    expr := `==\s*{{\s*header\s*\|\s*([^\s\}]+)\s*}}\s*==`
    expr2 := fmt.Sprintf("<%s>.*?</%s>", "lang", "lang")
    r := regexp.MustCompile(expr)
    r2 := regexp.MustCompile(expr2)
    fileNames := []string{"example.txt", "example2.txt", "example3.txt"}
    for _, fileName := range fileNames {
        f, err := os.Open(fileName)
        check(err)
        b, err := ioutil.ReadAll(f)
        check(err)
        f.Close()
        text := string(b)
        fmt.Printf("Contents of %s:\n\n%s\n\n", fileName, text)
        m := r.FindAllStringIndex(text, -1)
        headers := make([]header, len(m))
        if len(m) > 0 {
            for i, p := range m {
                headers[i] = header{p[0], p[1] - 1, ""}
            }
            m2 := r.FindAllStringSubmatch(text, -1)
            for i, s := range m2 {
                headers[i].lang = strings.ToLower(s[1])
            }
        }
        last := len(headers) - 1
        if last == -1 { // if there are no headers in the file add a dummy one
            headers = append(headers, header{-1, -1, "no language"})
            last = 0
        }
        m3 := r2.FindAllStringIndex(text, -1)
        for _, p := range m3 {
            if p[1] < headers[0].start {
                add2bmap("no language", fileName)
            } else if p[0] > headers[last].end {
                add2bmap(headers[last].lang, fileName)
            } else {
                for i := 0; i < last; i++ {
                    if p[0] > headers[i].end && p[0] < headers[i+1].start {
                        add2bmap(headers[i].lang, fileName)
                        break
                    }
                }
            }
        }
    }
    fmt.Println("Results:\n")
    count := 0
    for _, v := range bmap {
        count += v.count
    }
    fmt.Printf(" %d bare language tags.\n\n", count)
    for k, v := range bmap {
        fmt.Printf("  %d in %-11s %v\n", v.count, k, *v.names)
    }
}


import java.util.function.Predicate
import java.util.regex.Matcher
import java.util.regex.Pattern

class FindBareTags {
    private static final Pattern TITLE_PATTERN = Pattern.compile("\"title\": \"([^\"]+)\"")
    private static final Pattern HEADER_PATTERN = Pattern.compile("==\\{\\{header\\|([^}]+)}}==")
    private static final Predicate<String> BARE_PREDICATE = Pattern.compile("<lang>").asPredicate()

    static String download(URL target) {
        URLConnection connection = target.openConnection()
        connection.setRequestProperty("User-Agent", "Firefox/2.0.0.4")

        InputStream is = connection.getInputStream()
        return is.getText("UTF-8")
    }

    static void main(String[] args) {
        URI titleUri = URI.create("http://rosettacode.org/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks")
        String titleText = download(titleUri.toURL())
        if (titleText != null) {
            Matcher titleMatcher = TITLE_PATTERN.matcher(titleText)

            Map<String, Integer> countMap = new HashMap<>()
            while (titleMatcher.find()) {
                String title = titleMatcher.group(1)

                URI pageUri = new URI("http", null, "//rosettacode.org/wiki", "action=raw&title=$title", null)
                String pageText = download(pageUri.toURL())
                if (pageText != null) {
                    String language = "no language"
                    for (String line : pageText.readLines()) {
                        Matcher headerMatcher = HEADER_PATTERN.matcher(line)
                        if (headerMatcher.matches()) {
                            language = headerMatcher.group(1)
                            continue
                        }

                        if (BARE_PREDICATE.test(line)) {
                            int count = countMap.get(language, 0) + 1
                            countMap.put(language, count)
                        }
                    }
                } else {
                    println("Got an error reading the task page")
                }
            }

            for (Map.Entry<String, Integer> entry : countMap.entrySet()) {
                println("$entry.value in $entry.key")
            }
        } else {
            println("Got an error reading the title page")
        }
    }
}


import System.Environment
import Network.HTTP
import Text.Printf
import Text.Regex.TDFA
import Data.List
import Data.Array
import qualified Data.Map as Map

{-| Takes a string and cuts out the text matched in the MatchText array.  -}
splitByMatches :: String -> [MatchText String] -> [String]
splitByMatches str matches  =  foldr splitHead [str] matches
    where splitHead match acc  =  before:after:(tail acc)
            where before  =  take (matchOffset).head$ acc
                  after  =  drop (matchOffset + matchLen).head$ acc
                  matchOffset  =  fst.snd.(!0)$ match
                  matchLen  =  snd.snd.(!0)$ match

{-| Takes a string and counts the number of time a valid, but bare, lang tag
    appears.  It does not attempt to ignore valid tags inside lang blocks.  -}
countBareLangTags :: String -> Int
countBareLangTags  =  matchCount (makeRegex "<lang[[:space:]]*>" :: Regex)

{-| Takes a string and counts the number of bare lang tags per section of the
    text.  All tags before the first section are put into the key "".  -}
countByLanguage :: String -> Map.Map String Int
countByLanguage str  =  Map.fromList.filter ((>0).snd)$ zip langs counts
    where counts  =  map countBareLangTags.splitByMatches str$ allMatches
          langs  =  "":(map (fst.(!1)) allMatches)
          allMatches  =  matchAllText (makeRegex headerRegex :: Regex) str
          headerRegex  =  "==[[:space:]]*{{[[:space:]]*header[[:space:]]*\\|[[:space:]]*([^ }]*)[[:space:]]*}}[^=]*=="

main = do
    args <- getArgs
    (contents, files) <- if length args == 0 then do
        -- If there aren't arguments, read from stdin
            content  <-  getContents
            return ([content],[""])
        else if length args == 1 then do
        -- If there's only one argument, read the file, but don't display
        -- the filename in the results.
            content  <-  readFile (head args)
            return ([content],[""])
        else if (args !! 0) == "-w" then do
        -- If there's more than one argument and the first one is the -w option,
        -- use the rest of the arguments as page titles and load them from the wiki.
            contents  <-  mapM getPageContent.tail$ args
            return (contents, if length args > 2 then tail args else [""])
        else do
        -- Otherwise, read all the files and display their file names.
            contents  <-  mapM readFile args
            return (contents, args)
    let tagsPerLang  =  map countByLanguage contents
    let tagsWithFiles  =  zipWith addFileToTags files tagsPerLang
    let combinedFiles  =  Map.unionsWith combine tagsWithFiles
    printBareTags combinedFiles
        where addFileToTags file  =  Map.map (flip (,) [file])
              combine cur next  =  (fst cur + fst next, snd cur ++ snd next)

printBareTags :: Map.Map String (Int,[String]) -> IO ()
printBareTags tags  =  do
    let numBare  =  Map.foldr ((+).fst) 0 tags
    printf "%d bare language tags:\n\n" numBare
    mapM_ (\(lang,(count,files)) ->
        printf "%d in %s%s\n" count
                              (if lang == "" then "no language" else lang)
                              (filesString files)
        ) (Map.toAscList tags)

filesString :: [String] -> String
filesString []  =  ""
filesString ("":rest)  =  filesString rest
filesString files  =  " ("++listString files++")"
    where listString [file]  =  "[["++file++"]]"
          listString (file:files)  =  "[["++file++"]], "++listString files

getPageContent :: String -> IO String
getPageContent title  =  do
    response  <-  simpleHTTP.getRequest$ url
    getResponseBody response
        where url  =  "http://rosettacode.org/mw/index.php?action=raw&title="++title


import Utils		# To get the FindFirst class

procedure main()
    keys := ["{{header|","<lang>"]
    lang := "No language"
    tags := table(0)
    total := 0

    ff := FindFirst(keys)
    f := reads(&input, -1)

    f ? while tab(ff.locate()) do {
        if "{{header|" == 1(ff.getMatch(), ff.moveMatch()) then lang := map(tab(upto("}}")))
        else (tags[lang] +:= 1, total +:= 1)
        }

    write(total," bare language tags:\n")
    every pair := !sort(tags) do write(pair[2]," in ",pair[1])
end


import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class FindBareTags {
    private static final String BASE = "http://rosettacode.org";

    private static final Pattern TITLE_PATTERN = Pattern.compile("\"title\": \"([^\"]+)\"");
    private static final Pattern HEADER_PATTERN = Pattern.compile("==\\{\\{header\\|([^}]+)}}==");
    private static final Predicate<String> BARE_PREDICATE = Pattern.compile("<lang>").asPredicate();

    public static void main(String[] args) throws Exception {
        var client = HttpClient.newBuilder().build();

        URI titleUri = URI.create(BASE + "/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks");
        var titleRequest = HttpRequest.newBuilder(titleUri).GET().build();

        var titleResponse = client.send(titleRequest, HttpResponse.BodyHandlers.ofString());
        if (titleResponse.statusCode() == 200) {
            var titleBody = titleResponse.body();

            var titleMatcher = TITLE_PATTERN.matcher(titleBody);
            var titleList = titleMatcher.results().map(mr -> mr.group(1)).collect(Collectors.toList());

            var countMap = new HashMap<String, Integer>();
            for (String title : titleList) {
                var pageUri = new URI("http", null, "//rosettacode.org/wiki", "action=raw&title=" + title, null);
                var pageRequest = HttpRequest.newBuilder(pageUri).GET().build();
                var pageResponse = client.send(pageRequest, HttpResponse.BodyHandlers.ofString());
                if (pageResponse.statusCode() == 200) {
                    var pageBody = pageResponse.body();

                    AtomicReference<String> language = new AtomicReference<>("no language");
                    pageBody.lines().forEach(line -> {
                        var headerMatcher = HEADER_PATTERN.matcher(line);
                        if (headerMatcher.matches()) {
                            language.set(headerMatcher.group(1));
                        } else if (BARE_PREDICATE.test(line)) {
                            int count = countMap.getOrDefault(language.get(), 0) + 1;
                            countMap.put(language.get(), count);
                        }
                    });
                } else {
                    System.out.printf("Got a %d status code%n", pageResponse.statusCode());
                }
            }

            for (Map.Entry<String, Integer> entry : countMap.entrySet()) {
                System.out.printf("%d in %s%n", entry.getValue(), entry.getKey());
            }
        } else {
            System.out.printf("Got a %d status code%n", titleResponse.statusCode());
        }
    }
}


using Gumbo, AbstractTrees, HTTP, JSON, Dates

rosorg = "http://rosettacode.org"
qURI = "/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=json"
qdURI = "/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Draft_Programming_Tasks&cmlimit=500&format=json"
sqURI = "http://www.rosettacode.org/mw/index.php?title="

function topages(js, v)
    for d in js["query"]["categorymembers"]
        push!(v, sqURI * HTTP.Strings.escapehtml(replace(d["title"], " " => "_")) * "&action=raw")
    end
end

function getpages(uri)
    wikipages = Vector{String}()
    response = HTTP.request("GET", rosorg * uri)
    if response.status == 200
        fromjson = JSON.parse(String(response.body))
        topages(fromjson, wikipages)
        while haskey(fromjson, "continue")
            cmcont, cont = fromjson["continue"]["cmcontinue"], fromjson["continue"]["continue"]
            response = HTTP.request("GET", rosorg * uri * "&cmcontinue=$cmcont&continue=$cont")
            fromjson = JSON.parse(String(response.body))
            topages(fromjson, wikipages)
        end
    end
    wikipages
end

function processtaskpages(wpages, verbose=false)
    totalcount = 0
    langcount = Dict{String, Int}()
    for pag in wpages
        count = 0
        checked = 0
        try
            response = HTTP.request("GET", pag)
            if response.status == 200
                doc = parsehtml(String(response.body))
                lasttext = ""
                for elem in StatelessBFS(doc.root)
                    if typeof(elem) != HTMLText
                        if tag(elem) == :lang
                            if isempty(attrs(elem))
                                count += 1
                                if lasttext != ""
                                    if verbose
                                        println("Missing lang attibute for lang $lasttext")
                                    end
                                    if !haskey(langcount, lasttext)
                                        langcount[lasttext] = 1
                                    else
                                        langcount[lasttext] += 1
                                    end
                                end
                            else
                                checked += 1
                            end
                        end
                    else
                        m = match(r"header\|(.+)}}==", text(elem))
                        lasttext = (m == nothing) ? "" : m.captures[1]
                    end
                end
            end
        catch y
            if verbose
                println("Page $pag is not loaded or found: $y.")
            end
            continue
        end
        if count > 0 && verbose
            println("Page $pag had $count bare lang tags.")
        end
        totalcount += count
    end
    println("Total bare tags: $totalcount.")
    for k in sort(collect(keys(langcount)))
        println("Total bare <lang> for language $k: $(langcount[k])")
    end
end

println("Programming examples at $(DateTime(now())):")
qURI |> getpages |> processtaskpages

println("\nDraft programming tasks:")
qdURI |> getpages |> processtaskpages


import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.util.regex.Pattern
import java.util.stream.Collectors

const val BASE = "http://rosettacode.org"

fun main() {
    val client = HttpClient.newBuilder().build()

    val titleUri = URI.create("$BASE/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks")
    val titleRequest = HttpRequest.newBuilder(titleUri).GET().build()

    val titleResponse = client.send(titleRequest, HttpResponse.BodyHandlers.ofString())
    if (titleResponse.statusCode() == 200) {
        val titleBody = titleResponse.body()

        val titlePattern = Pattern.compile("\"title\": \"([^\"]+)\"")
        val titleMatcher = titlePattern.matcher(titleBody)
        val titleList = titleMatcher.results().map { it.group(1) }.collect(Collectors.toList())

        val headerPattern = Pattern.compile("==\\{\\{header\\|([^}]+)}}==")
        val barePredicate = Pattern.compile("<lang>").asPredicate()

        val countMap = mutableMapOf<String, Int>()
        for (title in titleList) {
            val pageUri = URI("http", null, "//rosettacode.org/wiki", "action=raw&title=$title", null)
            val pageRequest = HttpRequest.newBuilder(pageUri).GET().build()
            val pageResponse = client.send(pageRequest, HttpResponse.BodyHandlers.ofString())
            if (pageResponse.statusCode() == 200) {
                val pageBody = pageResponse.body()

                //println("Title is $title")
                var language = "no language"
                for (line in pageBody.lineSequence()) {
                    val headerMatcher = headerPattern.matcher(line)
                    if (headerMatcher.matches()) {
                        language = headerMatcher.group(1)
                        continue
                    }

                    if (barePredicate.test(line)) {
                        countMap[language] = countMap.getOrDefault(language, 0) + 1
                    }
                }
            } else {
                println("Got a ${titleResponse.statusCode()} status code")
            }
        }

        for (entry in countMap.entries) {
            println("${entry.value} in ${entry.key}")
        }
    } else {
        println("Got a ${titleResponse.statusCode()} status code")
    }
}


#Did not count the tasks where languages tasks are properly closed
add_lan := proc(language, n, existence, languages, pos)
	if (assigned(existence[language])) then
		existence[language] += n:
		return pos;
	else
		existence[language] := n:
		languages(pos) := language:
		return pos+1;
	end if;
end proc:
count_tags := proc(tasks, pos)
	local task, url, txt, header_tags, close_tags, close_len, header_len, occurence, i, pos_copy;
	pos_copy := pos:
	for task in tasks do
		url := cat("http://www.rosettacode.org/mw/index.php?title=", StringTools:-Encode(StringTools:-SubstituteAll(task["title"], " ", "_"), 'percent'), "&action=raw"):
		txt := URL:-Get(url):
		header_tags := [StringTools:-SearchAll("=={{header|", txt)]:
		close_tags := [StringTools:-SearchAll("}}==",txt)]:
		close_len := numelems(close_tags):
		header_len := numelems(header_tags):
		if header_len = 0 then
			break;
		end if;
		if (not header_len = close_len) then
			printf("%s is not counted since some language tags are not properly closed.\n", task["title"]);
			break;
		end if;
		occurence := numelems([StringTools:-SearchAll("<lang>", txt[1..header_tags[1]])]):
		if occurence > 0 then
			pos_copy := add_lan("no languages", occurence, existence, languages, pos_copy):
		end if:
		if close_len > 1 then
			for i from 2 to close_len do
				occurence := numelems([StringTools:-SearchAll("<lang>", txt[header_tags[i-1]..header_tags[i]])]):
				if occurence > 0 then
					pos_copy := add_lan(txt[header_tags[i-1]+11..close_tags[i-1]-1], occurence, existence, languages, pos_copy):
				end if:
			end do:
			occurence := numelems([StringTools:-SearchAll("<lang>", txt[header_tags[-1]..])]):
			if occurence > 0 then
				pos_copy := add_lan(txt[header_tags[-1]+11..close_tags[-1]-1], occurence, existence, languages, pos_copy):
			end if:
		end if:
	end do:
	return pos_copy:
end proc:

existence := table():
languages := Array():
pos := 1:
#go through every task
x := JSON:-ParseFile("http://rosettacode.org/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=10&format=json"):
pos := count_tags(x["query"]["categorymembers"], pos):
while(assigned(x["continue"]["cmcontinue"])) do
	continue := x["continue"]["cmcontinue"]:
	more_tasks:= cat("http://rosettacode.org/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=10&format=json", "&continue=", x["continue"]["continue"], "&cmcontinue=", x["continue"]["cmcontinue"]):
	x := JSON:-ParseFile(more_tasks):
	pos := count_tags(x["query"]["categorymembers"], pos):
end do:
#Prints out the table
total := 0:
for lan in languages do
	total += existence[lan]:
	printf("There are %d bare lang tags in %s\n", existence[lan], lan);
end do:
printf("Total number %d", total);


tasks[page_: ""] :=
  Module[{res =
     Import["http://rosettacode.org/mw/api.php?format=xml&action=\
query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=\
500" <> page, "XML"]},
   If[MemberQ[res[[2, 3]], XMLElement["query-continue", __]],
    Join[res[[2, 3, 1, 3, 1, 3, All, 2, 3, 2]],
     tasks["&cmcontinue=" <> res[[2, 3, 2, 3, 1, 2, 1, 2]]]],
    res[[2, 3, 1, 3, 1, 3, All, 2, 3, 2]]]];
bareTags = # -> (# -> StringCount[#2, "<lang>"] &) @@@
      Partition[
       Prepend[StringSplit[
          Import["http://rosettacode.org/wiki?action=raw&title=" <>
            URLEncode[#], "Text"],
          Shortest["=={{header|" ~~ x__ ~~ "}}=="] :> x],
         "no language"] //. {a___,
          multi_String?StringContainsQ["}}" ~~ ___ ~~ "{{header|"],
          bare_Integer, b___} :> {a, StringSplit[multi, "}"][[1]],
          bare, StringSplit[multi, "|"][[-1]], bare, b}, 2] & /@
   tasks[];
Print[IntegerString[Total[Flatten[bareTags[[All, 2, All, 2]]]]] <>
   " bare language tags.\n"];
langCounts =
  Normal[Total /@
    GroupBy[Flatten[bareTags[[All, 2]]], Keys -> Values]];
Print[IntegerString[#2] <> " in " <> # <> " ([[" <>
     StringRiffle[
      Keys[Select[bareTags,
        Function[task, MemberQ[task[[2]], # -> _Integer?Positive]]]],
      "]], [["] <> "]])"] & @@@
  Select[SortBy[langCounts, Keys], #[[2]] > 0 &];


import algorithm, htmlparser, httpclient, json
import sequtils, strformat, strscans, tables, times, xmltree
import strutils except escape

const

  Rosorg = "http://rosettacode.org"
  QUri = "/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=json"
  QdUri = "/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Draft_Programming_Tasks&cmlimit=500&format=json"
  SqUri = "http://www.rosettacode.org/mw/index.php?title="

proc addPages(pages: var seq[string], fromJson: JsonNode) =
  for d in fromJson{"query", "categorymembers"}:
    pages.add SqUri & d["title"].getStr().replace(" ", "_").escape() & "&action=raw"

proc getPages(client: var HttpClient; uri: string): seq[string] =
  let response = client.get(Rosorg & uri)
  if response.status == $Http200:
    var fromJson = response.body.parseJson()
    result.addPages(fromJson)
    while fromJson.hasKey("continue"):
      let cmcont = fromJson{"continue", "cmcontinue"}.getStr()
      let cont = fromJson{"continue", "continue"}.getStr()
      let response = client.get(Rosorg & uri & fmt"&cmcontinue={cmcont}&continue={cont}")
      fromJson = response.body.parseJson()
      result.addPages(fromJson)

proc processTaskPages(client: var HttpClient; pages: seq[string]; verbose = false) =
  var totalCount = 0
  var langCount: CountTable[string]

  for page in pages:
    var count, checked = 0
    try:
      let response = client.get(page)
      if response.status == $Http200:
        let doc = response.body.parseHtml()
        if doc.kind != xnElement: continue
        var lastText = ""
        for elem in doc:
          if elem.kind == xnElement and elem.tag == "lang":
            if elem.attrs.isNil:
              inc count
              if lastText.len != 0:
                if verbose:
                  echo "Missing lang attribute for lang ", lastText
                langCount.inc lastText
            else:
              inc checked
          elif elem.kind == xnText:
            discard elem.text.scanf("=={{header|$+}}", lastText):
    except CatchableError:
      if verbose:
        echo &"Page {page} is not loaded or found: {getCurrentExceptionMsg()}"
      continue

    if count > 0 and verbose:
      echo &"Page {page} had {count} bare lang tags."
    inc totalCount, count

  echo &"Total bare tags: {totalCount}."
  for k in sorted(toSeq(langCount.keys)):
    echo &"Total bare <lang> for language {k}: ({langcount[k]})"

echo "Programming examples at ", now()
var client = newHttpClient()
client.processTaskPages(client.getPages(QUri))

echo "\nDraft programming tasks:"
client.processTaskPages(client.getPages(QdUri))


use Web.HTTP;
use Query.RegEx;
use Collection.Generic;

class Program {
  function : Main(args : String[]) ~ Nil {
    master_tasks := ProcessTasks(["100_doors", "99_bottles_of_beer", "Filter", "Array_length", "Greatest_common_divisor", "Greatest_element_of_a_list", "Greatest_subsequential_sum"]);
    "---"->PrintLine();
    PrintTasks(master_tasks);
  }

  function : ProcessTasks(tasks : String[]) ~ MultiMap<String, String> {
    master_tasks := MultiMap->New()<String, String>;

    each(i : tasks) {
      task := tasks[i];
      "Processing '{$task}'..."->PrintLine();
      matches := ProcessTask(task);
      langs := matches->GetKeys()<String>;
      each(j : langs) {
        master_tasks->Insert(langs->Get(j), task);
      };
    };

    return master_tasks;
  }

  function : ProcessTask(task : String) ~ Set<String> {
    langs := Set->New()<String>;

    header_regex := RegEx->New("==\\{\\{header\\|(\\w|/|-|_)+\\}\\}==");
    lang_regex := RegEx->New("<(\\s)*lang(\\s)*>");

    url := "http://rosettacode.org/mw/index.php?action=raw&title={$task}";
    lines := HttpClient->New()->GetAll(url)->Split("\n");

    last_header : String;
    each(i : lines) {
      line := lines[i];

      # get header
      header := header_regex->FindFirst(line);
      if(<>header->IsEmpty()) {
        last_header := HeaderName(header);
      };

      # get language
      lang := lang_regex->FindFirst(line);
      if(lang->Size() > 0) {
        if(last_header <> Nil) {
          langs->Insert("{$last_header}");
        }
        else {
          langs->Insert("no language");
        };
      };
    };

    return langs;
  }

  function : HeaderName(lang_str : String) ~ String {
    start := lang_str->Find('|');
    if(start > -1) {
      start += 1;
      end := lang_str->Find(start, '}');
      return lang_str->SubString(start, end - start);
    };

    return "";
  }

  function : PrintTasks(tasks : MultiMap<String, String>) ~ Nil {
    keys := tasks->GetKeys()<String>;
    each(i : keys) {
      buffer := "";

      key := keys->Get(i);
      values := tasks->Find(key)<String>;
      count := values->Size();
      buffer += "{$count} in {$key} (";
      each(j : values) {
        value := values->Get(j);
        buffer += "[[{$value}]]";
        if(j + 1 < values->Size()) {
          buffer += ", ";
        };
      };
      buffer += ")";

      buffer->PrintLine();
    };
  }
}


my $lang = 'no language';
my $total = 0;
my %blanks = ();
while (<>) {
  if (m/<lang>/) {
    if (exists $blanks{lc $lang}) {
      $blanks{lc $lang}++
    } else {
      $blanks{lc $lang} = 1
    }
    $total++
  } elsif (m/==\s*\{\{\s*header\s*\|\s*([^\s\}]+)\s*\}\}\s*==/) {
    $lang = lc $1
  }
}

if ($total) {
	print "$total bare language tag" . ($total > 1 ? 's' : '') . ".\n\n";
	while ( my ($k, $v) = each(%blanks) ) {
		print "$k in $v\n"
	}
}


--
-- demo\rosetta\Find_bare_lang_tags.exw
-- ====================================
--
--  (Uses '&' instead of/as well as 'a', for everyone's sanity..)
--  Finds/counts no of "<l&ng>" as opposed to eg "<l&ng Phix>" tags.
--  Since downloading all the pages can be very slow, this uses a cache.
--
without js -- (fairly obviously this will never ever run in a browser!)
constant include_drafts = true,
         sort_by_task = true,
         sort_by_lang = not sort_by_task    -- (one or t'other)

include rosettacode_cache.e -- see Rosetta_Code/Count_examples#Phix

constant {utf8,ansi} = columnize({{x"E28093","-"},
                                  {x"E28099","'"},
                                  {x"C3A8","e"},
                                  {x"C3A9","e"},
                                  {x"D09A","K"},
                                  {x"D09C","M"}})

function utf8_clean(string s)
    return substitute_all(s,utf8,ansi)
end function

function multi_lang(sequence s)
-- Convert eg {"Algol","Algol","C","C","C"} to "Algol[2],C[3]"
    integer i = 1, j = 2
    while i<length(s) do
        if s[i]=s[j] then
            while j<length(s) and s[i]=s[j+1] do j+=1 end while
            s[i..j] = {sprintf("%s[%d]",{s[i],j-i+1})}
        end if
        i += 1
        j = i+1
    end while
    return join(s,",")
end function

function multi_task(sequence s, tasks)
-- Similar to multi_lang() but with task[indexes]
    integer i = 1, j = 2
    while i<=length(s) do
        integer si = s[i]
        string tsi = html_clean(tasks[si])
        if j<=length(s) and si=s[j] then
            while j<length(s) and si=s[j+1] do j+=1 end while
            s[i..j] = {sprintf("%s[%d]",{tsi,j-i+1})}
        else
            s[i] = tsi
        end if
        i += 1
        j = i+1
    end while
    if length(s)>8 then s[4..-4] = {"..."} end if
    return join(s,",")
end function

bool first = true

function find_bare_lang_tags()
    if get_file_type("rc_cache")!=FILETYPE_DIRECTORY then
        if not create_directory("rc_cache") then
            crash("cannot create rc_cache directory")
        end if
    end if
    -- note this lot use web scraping (as cribbed from a similar task) ...
    sequence tasks = dewiki(open_category("Programming_Tasks"))
    if include_drafts then
        tasks &= dewiki(open_category("Draft_Programming_Tasks"))
        tasks = sort(tasks)
    end if
    integer blt = find("Rosetta_Code/Find_bare_lang_tags",tasks) -- not this one!
    tasks[blt..blt] = {}

    -- ... whereas the individual tasks use the web api instead (3x smaller/faster)
    integer total_count = 0,
            lt = length(tasks),
            kept = 0
    progress("%d tasks found\n",{lt})
    sequence task_langs = {},
             task_counts = iff(sort_by_task?repeat(0,lt):{}),
             task_things = iff(sort_by_task?repeat({},lt):{})
    for i=1 to length(tasks) do
        string ti = tasks[i],
               url = sprintf("http://rosettacode.org/mw/index.php?title=%s&action=raw",{ti}),
               contents = open_download(ti&".raw",url),
               curr
        integer count = 0, start = 1, header
        while true do
            start = match(`<l`&`ang>`,contents,start)
            if start=0 then exit end if
            -- look backward for the nearest header
            header = rmatch(`{`&`{he`&`ader|`,contents,start)
            if header=0 then
                curr = "no language"
            else
                header += length(`{`&`{he`&`ader|`)
                curr = utf8_clean(contents[header..match(`}}`,contents,header)-1])
            end if
            if sort_by_lang then
                integer k = find(curr,task_langs)
                if k=0 then
                    task_langs = append(task_langs,curr)
                    task_things = append(task_things,{i})
                    task_counts = append(task_counts,1)
                else
                    task_things[k] = append(task_things[k],i)
                    task_counts[k] += 1
                end if
            else
                task_things[i] = append(task_things[i],curr)
            end if
            count += 1
            start += length(`<l`&`ang>`)
        end while
        if count!=0 then
            if sort_by_task then
                task_counts[i] = count
            end if
            kept += 1
        end if
        progress("%d tasks kept, %d to go\r",{kept,lt-i})
        total_count += count
        if get_key()=#1B then progress("escape keyed\n") exit end if
    end for
    curl_cleanup()
    progress("%d tasks with bare lang tags\n",{kept})
    sequence tags = custom_sort(task_counts,tagset(length(task_counts)))
    for i=length(tags) to 1 by -1 do
        integer ti = tags[i],
                tc = task_counts[ti]
        if tc=0 then exit end if
        if sort_by_task then
            progress("%s %d (%s)\n",{html_clean(tasks[ti]),tc,multi_lang(task_things[ti])})
        else -- (sort_by_count)
            progress("%s %d (%s)\n",{task_langs[ti],tc,multi_task(task_things[ti],tasks)})
        end if
    end for
    return total_count
end function

progress("Total: %d\n",{find_bare_lang_tags()})

?"done"
{} = wait_key()


"""Count bare `lang` tags in wiki markup. Requires Python >=3.6.

Uses the Python standard library `urllib` to make MediaWiki API requests.
"""

from __future__ import annotations

import functools
import gzip
import json
import logging
import platform
import re

from collections import Counter
from collections import defaultdict

from typing import Any
from typing import Iterator
from typing import Iterable
from typing import List
from typing import Mapping
from typing import NamedTuple
from typing import Optional
from typing import Tuple

from urllib.parse import urlencode
from urllib.parse import urlunparse
from urllib.parse import quote_plus

import urllib.error
import urllib.request

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# Parse wiki markup with these regular expression patterns. Any headings and
# `lang` tags found inside `nowiki`, `pre` or other `lang` tags (bare or not)
# should not count as "bare".
#
# NOTE: The order of these patterns is significant.
RE_SPEC = [
    ("NOWIKI", r"<\s*nowiki\s*>.*?</\s*nowiki\s*>"),
    ("PRE", r"<\s*pre\s*>.*?</\s*pre\s*>"),
    ("LANG", r"<\s*lang\s+.+?>.*?</\s*lang\s*>"),
    ("HEAD", r"==\{\{\s*header\s*\|\s*(?P<header>.+?)\s*}}=="),
    ("BARE", r"<\s*lang\s*>.*?</\s*lang\s*>"),
]

RE_BARE_LANG = re.compile(
    "|".join(rf"(?P<{name}>{pattern})" for name, pattern in RE_SPEC),
    re.DOTALL | re.IGNORECASE,
)

# Some wiki headings look like this "=={{header|Some}} / {{header|Other}}==".
# We'll use this regular expression to strip out the markup.
RE_MULTI_HEADER = re.compile(r"(}|(\{\{\s*header\s*\|\s*))", re.IGNORECASE)

def find_bare_lang_section_headers(wiki_text: str) -> Iterator[str]:
    """Generate a sequence of wiki section headings that contain bare
    'lang' tags.

    If there are multiple bare lang tags in a section, that section
    heading will appear multiple times in the sequence.
    """
    current_heading = "no language"

    for match in RE_BARE_LANG.finditer(wiki_text):
        kind = match.lastgroup

        if kind == "HEAD":
            current_heading = RE_MULTI_HEADER.sub("", match.group("header"))
        elif kind == "BARE":
            yield current_heading

class Error(Exception):
    """Exception raised when we get an unexpected response from the MediaWiki API."""

class TagCounter:
    """Count bare `lang` tags in wiki markup. Group them by heading and
    remember what page they're in."""

    def __init__(self):
        self.counter = Counter()
        self.pages = defaultdict(set)
        self.total = 0

    def __len__(self):
        return len(self.counter)

    @classmethod
    def from_section_headers(
        cls, page_title: str, section_headers: Iterable[str]
    ) -> TagCounter:
        """Return a new `TagCounter` initialized with the given section
        headings."""
        counter = cls()

        for heading in section_headers:
            counter.add(page_title, heading)

        return counter

    @classmethod
    def from_wiki_text(cls, page_title: str, wiki_text: str) -> TagCounter:
        """Return a new `TagCounter` initialized with bare lang tags from the
        given wiki text."""
        return cls.from_section_headers(
            page_title,
            find_bare_lang_section_headers(wiki_text),
        )

    def add(self, page_title: str, section_heading: str):
        """Increment the counter by one for the given section heading an
        page."""
        self.counter[section_heading] += 1
        self.pages[section_heading].add(page_title)
        self.total += 1

    def update(self, other):
        """Union this counter with `other`, another counter."""
        assert isinstance(other, TagCounter)

        self.counter.update(other.counter)

        for section_heading, pages in other.pages.items():
            self.pages[section_heading].update(pages)

        self.total += other.total

    def most_common(self, n=None) -> str:
        """Return a formatted string of the most common wiki sections to have
        bare lang tags."""
        buf = [f"{sum(self.counter.values())} bare lang tags.\n"]

        for section_heading, count in self.counter.most_common(n=n):
            pages = list(self.pages[section_heading])
            buf.append(f"{count} in {section_heading} {pages}")

        return "\n".join(buf)

def quote_underscore(string, safe="", encoding=None, errors=None):
    """Like urllib.parse.quote but replaces spaces with underscores."""
    string = quote_plus(string, safe, encoding, errors)
    return string.replace("+", "_")

class URL(NamedTuple):
    """A `urllib.parse.urlunparse` compatible Tuple with some helper methods.
    We'll use this to build and pass around our MediaWiki API URLs.
    """

    scheme: str
    netloc: str
    path: str
    params: str
    query: str
    fragment: str

    def __str__(self):
        return urlunparse(self)

    def with_query(self, query: Mapping[str, Any]) -> URL:
        query_string = urlencode(query, safe=":", quote_via=quote_underscore)
        return self._replace(query=query_string)

API_BASE_URL = URL(
    scheme="http",
    netloc="rosettacode.org",
    path="/mw/api.php",
    params="",
    query="",
    fragment="",
)

UGLY_RAW_URL = URL(
    scheme="http",
    netloc="rosettacode.org",
    path="/mw/index.php",
    params="",
    query="",
    fragment="",
)

# NOTE: Cloudflare was blocking requests with the default user agent.
DEFAULT_HEADERS = {
    "User-agent": f"python/{platform.python_version()}",
    "Accept-encoding": "gzip, deflate",
    "Accept": "*/*",
    "Connection": "keep-alive",
}

class Response(NamedTuple):
    headers: Mapping[str, str]
    body: bytes

def get(url: URL, headers=DEFAULT_HEADERS) -> Response:
    """Make an HTTP GET request to the given URL."""
    logger.debug(f"GET {url}")
    request = urllib.request.Request(str(url), headers=headers)

    try:
        with urllib.request.urlopen(request) as response:
            return Response(
                headers=dict(response.getheaders()),
                body=response.read(),
            )
    except urllib.error.HTTPError as e:
        logging.debug(e.code)
        logging.debug(gzip.decompress(e.read()))
        raise

def raise_for_header(headers: Mapping[str, str], header: str, expect: str):
    got = headers.get(header)
    if got != expect:
        raise Error(f"expected '{expect}', got '{got}'")

raise_for_content_type = functools.partial(raise_for_header, header="Content-Type")

class CMContinue(NamedTuple):
    continue_: str
    cmcontinue: str

Pages = Tuple[List[str], Optional[CMContinue]]

def get_wiki_page_titles(chunk_size: int = 500, continue_: CMContinue = None) -> Pages:
    """Return a list of wiki page titles and any continuation information."""
    query = {
        "action": "query",
        "list": "categorymembers",
        "cmtitle": "Category:Programming_Tasks",
        "cmlimit": chunk_size,
        "format": "json",
        "continue": "",
    }

    if continue_:
        query["continue"] = continue_.continue_
        query["cmcontinue"] = continue_.cmcontinue

    response = get(API_BASE_URL.with_query(query))

    # Fail early if the response is not what we are expecting.
    raise_for_content_type(response.headers, expect="application/json; charset=utf-8")
    raise_for_header(response.headers, "Content-Encoding", "gzip")

    data = json.loads(gzip.decompress(response.body))
    page_titles = [p["title"] for p in data["query"]["categorymembers"]]

    if data.get("continue", {}).get("cmcontinue"):
        _continue = CMContinue(
            data["continue"]["continue"],
            data["continue"]["cmcontinue"],
        )
    else:
        _continue = None

    return (page_titles, _continue)

def get_wiki_page_markup(page_title: str) -> str:
    """Return raw MediaWiki markup from the page `page_title`."""
    query = {"action": "raw", "title": page_title}
    response = get(UGLY_RAW_URL.with_query(query))

    # Fail early if the response is not what we are expecting.
    raise_for_content_type(response.headers, expect="text/x-wiki; charset=UTF-8")

    return response.body.decode()

def example(limit=30):
    # Get the first chunk of wiki page titles from the MediaWiki API
    page_titles, continue_ = get_wiki_page_titles()

    # Get more chunks if there are any.
    while continue_ is not None:
        more_page_titles, continue_ = get_wiki_page_titles(continue_=continue_)
        page_titles.extend(more_page_titles)

    # Aggregate counts from all pages.
    counter = TagCounter()

    for i, page_title in enumerate(page_titles):
        if i > limit:
            break

        # Read and parse raw wiki page markup.
        wiki_text = get_wiki_page_markup(page_title)
        counts = TagCounter.from_wiki_text(page_title, wiki_text)
        counter.update(counts)

    # Dump the results to stdout.
    print(counter.most_common())

if __name__ == "__main__":
    logging.basicConfig(format="%(asctime)s %(message)s", level=logging.DEBUG)
    example()


#lang racket

(require net/url net/uri-codec json)

(define (get-text page)
  (define ((get k) x) (dict-ref x k))
  ((compose1 (get '*) car (get 'revisions) cdar hash->list (get 'pages)
             (get 'query) read-json get-pure-port string->url format)
   "http://rosettacode.org/mw/api.php?~a"
   (alist->form-urlencoded
    `([titles . ,page] [prop . "revisions"] [rvprop . "content"]
      [format . "json"] [action . "query"]))))

(define (find-bare-tags page)
  (define in (open-input-string (get-text page)))
  (define rx
    ((compose1 pregexp string-append)
     "<\\s*lang\\s*>|"
     "==\\s*\\{\\{\\s*header\\s*\\|\\s*([^{}]*?)\\s*\\}\\}\\s*=="))
  (let loop ([lang "no language"] [bare '()])
    (match (regexp-match rx in)
      [(list _ #f) (loop lang (dict-update bare lang add1 0))]
      [(list _ lang) (loop lang bare)]
      [#f (if (null? bare) (printf "no bare language tags\n")
              (begin (printf "~a bare language tags\n" (apply + (map cdr bare)))
                     (for ([b bare]) (printf "  ~a in ~a\n" (cdr b) (car b)))))])))

(find-bare-tags "Rosetta Code/Find bare lang tags")


my $lang = '(no language)';
my $total = 0;
my %blanks;

for lines() {
  when / '<lang>' / {
    %blanks{$lang}++;
    $total++;
  }
  when ms/ '==' '{{' 'header' '|' ( <-[}]>+? ) '}}' '==' / {
    $lang = $0.lc;
  }
}

say "$total bare language tag{ 's' if $total != 1 }\n";
say .value, ' in ', .key for %blanks.sort;


/*REXX pgm finds and displays bare language (<lang>) tags without a language specified. */
parse arg iFID .                                 /*obtain optional argument from the CL.*/
if iFID=='' | iFID=","  then iFID= 'BARELANG.HTM'  /*Not specified?  Then assume default*/
call lineout iFID                                /*close the file, just in case its open*/
call linein  ifid,1,0                            /*point to the first record.           */
noLa= 0;  bare= 0;  header=;  heads=             /*initialize various REXX variables.   */
!.= 0                                            /*sparse array to hold language headers*/
            do recs=0  while lines(iFID)\==0     /*read all lines in the input file.    */
            $= linein(iFID)                      /*read a line (record) from the input. */
            $= space($)                          /*elide superfluous blanks from record.*/
            if $==''  then iterate               /*if a blank line, then skip any tests.*/
            call testHead                        /*process possible  ==((header|ααα}}== */
            call testLang                        /*   "        "    <lang ααα> or <lang>*/
            end   /*recs*/

call lineout iFID                                /*close the file, just in case its open*/
say recs  ' records read from file: '  iFID; say /*show number of records read from file*/
if bare==0  then bare= 'no';    say right(bare, 9)   " bare language tags.";           say

   do #=1  for words(head);   _= word(head, #)   /*maybe show  <lang>  for language ααα */
   if !._\==0  then say right(!._, 9)  ' in'  _  /*show the count for a particular lang.*/
   end   /*#*/

if noLa==0  then noLa= 'no';    say right(noLa, 9)   " in no specified language."
exit 0
/*──────────────────────────────────────────────────────────────────────────────────────*/
testHead: @head= '=={{header|';      @foot= "}}=="               /*define two literals. */
          hh= pos(@head, $     );    if hh==0  then return       /*get start of literal.*/
          or= hh + length(@head) - 1                             /*get position of  |   */
          hb= pos(@foot, $, or);     if hb==0  then return       /*get position of foot.*/
          head= substr($, or+1, hb-or-1)                         /*get the language name*/
          if head\==''  then header= head                        /*Header?  Then use it.*/
          if wordpos(head, heads)==0  then heads= heads head     /*Is lang?  Add──► list*/
          return
/*──────────────────────────────────────────────────────────────────────────────────────*/
testLang: @lang= '<lang';            @back= ">"                  /*define two literals. */
          s1= pos(@lang, $      );   if s1==0  then return       /*get start of literal.*/
          gt= pos(@back, $, s1+1)                                /*get position of  <   */
          lang= strip( substr($, gt-2, gt-length(@lang) -1 ) )   /*get the language name*/
          if lang==''  then bare= bare + 1                       /*No lang?  Bump bares.*/
                       else @lang= lang                          /*Is lang?  Set lang.  */
          if @lang\==''  &  header==''   then noLa= noLa + 1     /*bump  noLang counter.*/
          if @lang\==''  &  header\==''  then !.head= !.head + 1 /*bump  a lang    "    */
          return


require "open-uri"
require "cgi"

tasks  = ["Greatest_common_divisor", "Greatest_element_of_a_list", "Greatest_subsequential_sum"]
part_uri  = "http://rosettacode.org/wiki?action=raw&title="
Report = Struct.new(:count, :tasks)
result = Hash.new{|h,k| h[k] = Report.new(0, [])}

tasks.each do |task|
  puts "processing #{task}"
  current_lang = "no language"
  open(part_uri + CGI.escape(task)).each_line do |line|
    current_lang = Regexp.last_match["lang"] if /==\{\{header\|(?<lang>.+)\}\}==/ =~ line
    num_no_langs = line.scan(/<lang\s*>/).size
    if num_no_langs > 0 then
      result[current_lang].count += num_no_langs
      result[current_lang].tasks << task
    end
  end
end

puts "\n#{result.values.map(&:count).inject(&:+)} bare language tags.\n\n"
result.each{|k,v| puts "#{v.count} in #{k} (#{v.tasks})"}


extern crate regex;

use std::io;
use std::io::prelude::*;

use regex::Regex;

fn find_bare_lang_tags(input: &str) -> Vec<(Option<String>, i32)> {
    let mut language_pairs = vec![];
    let mut language = None;
    let mut counter = 0_i32;

    let header_re = Regex::new(r"==\{\{header\|(?P<lang>[[:alpha:]]+)\}\}==").unwrap();

    for line in input.lines() {
        if let Some(captures) = header_re.captures(line) {
            if let Some(header_lang) = captures.name("lang") {
                language_pairs.push((language, counter));
                language = Some(header_lang.as_str().to_owned());
                counter = 0;
            }
        }

        if line.contains("<lang>") {
            counter += 1;
        }
    }

    language_pairs.push((language, counter));
    language_pairs
}

fn main() {
    let stdin = io::stdin();
    let mut buf = String::new();
    stdin.lock().read_to_string(&mut buf).unwrap();
    let results = find_bare_lang_tags(&buf);
    let total_bare = results.iter().map(|r| r.1).sum::<i32>();

    println!("{} bare language tags.\n", total_bare);
    for result in &results {
        let num_bare = result.1;

        if num_bare > 0 {
            println!(
                "{} in {}",
                result.1,
                result
                    .0
                    .to_owned()
                    .unwrap_or_else(|| String::from("no language"))
            );
        }
    }
}


// Map lines to a list of Option(heading -> task) for each bare lang tag found.
val headerFormat = "==[{]+header[|]([^}]*)[}]+==".r
val langFormat = "<lang([^>]*)>".r
def mapped(lines: Seq[String], taskName: String = "") = {
  var heading = ""
  for (line <- lines;
     head = headerFormat.findFirstMatchIn(line).map(_ group 1);
     lang = langFormat.findFirstMatchIn(line).map(_ group 1)) yield {
    if (head.isDefined) heading = head.get
    lang.map(_.trim).filter(_ == "").map(_ => heading -> taskName)
  }
}
// Group results as a Map(heading -> task1, task2, ...)
def reduced(results: Seq[Option[(String,String)]]) =
  results.flatten.groupBy(_._1).mapValues(_.unzip._2)

// Format each heading as "tasklist.size in heading (tasklist)"
def format(results: Map[String,Seq[String]]) = results.map{case (heading, tasks) =>
  val h = if (heading.length > 0) heading else "no langauge"
  val hmsg = s"${tasks.size} in $h"
  val t = tasks.filterNot(_ == "")
  val tmsg = if (t.isEmpty) "" else t.distinct.mkString(" (", ",", ")")
  hmsg + tmsg
}
def count(results: Map[String,Seq[String]]) = results.values.map(_.size).sum

// Single and multi-source support
case class BareLangFinder(source: scala.io.Source, taskName: String = "") {
  def map = mapped(source.getLines.toSeq, taskName)
  def mapReduce = reduced(map)
  def summary = format(mapReduce) mkString "\n"
}
def mapReduce(inputs: Seq[BareLangFinder]) = reduced(inputs.flatMap(_.map))


package require Tcl 8.5
package require http
package require json
package require textutil::split
package require uri

proc getUrlWithRedirect {base args} {
    set url $base?[http::formatQuery {*}$args]
    while 1 {
	set t [http::geturl $url]
	if {[http::status $t] ne "ok"} {
	    error "Oops: url=$url\nstatus=$s\nhttp code=[http::code $token]"
	}
	if {[string match 2?? [http::ncode $t]]} {
	    return $t
	}
	# OK, but not 200? Must be a redirect...
	set url [uri::resolve $url [dict get [http::meta $t] Location]]
	http::cleanup $t
    }
}

proc get_tasks {category} {
    global cache
    if {[info exists cache($category)]} {
	return $cache($category)
    }
    set query [dict create cmtitle Category:$category]
    set tasks [list]

    while {1} {
	set response [getUrlWithRedirect http://rosettacode.org/mw/api.php \
		action query list categorymembers format json cmlimit 500 {*}$query]

	# 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 query cmcontinue $continue_task
    }
    return [set cache($category) $tasks]
}
proc getTaskContent task {
    set token [getUrlWithRedirect http://rosettacode.org/mw/index.php \
	    title $task action raw]
    set content [http::data $token]
    http::cleanup $token
    return $content
}

proc init {} {
    global total count found
    set total 0
    array set count {}
    array set found {}
}
proc findBareTags {pageName pageContent} {
    global total count found
    set t {{}}
    lappend t {*}[textutil::split::splitx $pageContent \
	    {==\s*\{\{\s*header\s*\|\s*([^{}]+?)\s*\}\}\s*==}]
    foreach {sectionName sectionText} $t {
	set n [regexp -all {<lang>} $sectionText]
	if {!$n} continue
	incr count($sectionName) $n
	lappend found($sectionName) $pageName
	incr total $n
    }
}
proc printResults {} {
    global total count found
    puts "$total bare language tags."
    if {$total} {
	puts ""
	if {[info exists found()]} {
	    puts "$count() in task descriptions\
		    (\[\[[join $found() {]], [[}]\]\])"
	    unset found()
	}
	foreach sectionName [lsort -dictionary [array names found]] {
	    puts "$count($sectionName) in $sectionName\
		    (\[\[[join $found($sectionName) {]], [[}]\]\])"
	}
    }
}

init
set tasks [get_tasks Programming_Tasks]
#puts stderr "querying over [llength $tasks] tasks..."
foreach task [get_tasks Programming_Tasks] {
    #puts stderr "$task..."
    findBareTags $task [getTaskContent $task]
}
printResults


import "/ioutil" for FileUtil
import "/pattern" for Pattern
import "/set" for Set
import "/sort" for Sort
import "/fmt" for Fmt

var p = Pattern.new("/=/={{header/|[+0/y]}}/=/=", Pattern.start)
var bareCount = 0
var bareLang = {}
for (fileName in ["example.txt", "example2.txt", "example3.txt"]) {
    var lines = FileUtil.readLines(fileName)
    var lastHeader = "No language"
    for (line in lines) {
        line = line.trimStart()
        if (line == "") continue
        var m = p.find(line)
        if (m) {
            lastHeader = m.capsText[0]
            continue
        }
        if (line.startsWith("<lang>")) {
            bareCount = bareCount + 1
            var value = bareLang[lastHeader]
            if (value) {
                value[0] = value[0] + 1
                value[1].add(fileName)
            } else {
                bareLang[lastHeader] = [1, Set.new([fileName])]
            }
        }
    }
}
System.print("%(bareCount) bare language tags:")
for (me in bareLang) {
    var lang  = me.key
    var count = me.value[0]
    var names = me.value[1].toList
    Sort.insertion(names)
    Fmt.print(" $2d in $-11s $n", count, lang, names)
}


var [const] CURL=Import("zklCurl"),
   partURI="http://rosettacode.org/wiki?action=raw&title=%s",
   langRE=RegExp(0'!\s*==\s*{{\s*header\s*\|(.+)}}!),  // == {{ header | zkl }}
   emptyRE=RegExp(0'!<lang\s*>!);

fcn findEmptyTags(a,b,c,etc){  // -->[lang:(task,task...)]
   results:=Dictionary();
   foreach task in (vm.arglist){
      println("processing ",task);
      currentLang:="";
      page:=CURL().get(partURI.fmt(CURL.urlEncode(task)));
      foreach line in (page[0]){
	 if(langRE.search(line,True)){
	    lang:=langRE.matched[1].strip();
	    if(lang) currentLang=lang;
	 }
	 if(emptyRE.matches(line,True)) results.appendV(currentLang,task);
      }
   }
   results
}


with Aws.Client, Aws.Messages, Aws.Response, Aws.Resources, Aws.Url;
with Dom.Readers, Dom.Core, Dom.Core.Documents, Dom.Core.Nodes, Dom.Core.Attrs;
with Input_Sources.Strings, Unicode, Unicode.Ces.Utf8;
with Ada.Strings.Unbounded, Ada.Strings.Fixed, Ada.Text_IO, Ada.Command_Line;
with Ada.Containers.Vectors;

use  Aws.Client, Aws.Messages, Aws.Response, Aws.Resources, Aws.Url;
use Dom.Readers, Dom.Core, Dom.Core.Documents, Dom.Core.Nodes, Dom.Core.Attrs;
use Aws, Ada.Strings.Unbounded, Ada.Strings.Fixed, Input_Sources.Strings;
use Ada.Text_IO, Ada.Command_Line;

procedure Count_Examples is

   package Members_Vectors is new Ada.Containers.Vectors (
      Index_Type => Positive,
      Element_Type => Unbounded_String);
   use Members_Vectors;

   Exemples      : Vector;
   Nbr_Lg, Total : Natural := 0;

   procedure Get_Vector (Category : in String; Mbr_Vector : in out Vector) is
      Reader  : Tree_Reader;
      Doc     : Document;
      List    : Node_List;
      N       : Node;
      A       : Attr;
      Page    : Aws.Response.Data;
      Uri_Xml : constant String :=
         "http://rosettacode.org/mw/api.php?action=query&list=categorymembers"
         &
         "&format=xml&cmlimit=500&cmtitle=Category:";
   begin
      Page := Client.Get (Uri_Xml & Category);
      if Response.Status_Code (Page) not  in Messages.Success then
         raise Client.Connection_Error;
      end if;
      declare
         Xml    : constant String := Message_Body (Page);
         Source : String_Input;
      begin
         Open
           (Xml'Unrestricted_Access,
            Unicode.Ces.Utf8.Utf8_Encoding,
            Source);
         Parse (Reader, Source);
         Close (Source);
      end;
      Doc  := Get_Tree (Reader);
      List := Get_Elements_By_Tag_Name (Doc, "cm");
      for Index in 1 .. Length (List) loop
         N := Item (List, Index - 1);
         A := Get_Named_Item (Attributes (N), "title");
         Append (Mbr_Vector, To_Unbounded_String (Value (A)));
      end loop;
      Free (List);
      Free (Reader);
   end Get_Vector;

   function Scan_Page (Title : String) return Natural is
      Page                      : Aws.Response.Data;
      File                      : Aws.Resources.File_Type;
      Buffer                    : String (1 .. 1024);
      Languages, Position, Last : Natural := 0;
   begin
      Page :=
         Client.Get
           ("http://rosettacode.org/mw/index.php?title=" &
            Aws.Url.Encode (Title) &
            "&action=raw");
      Response.Message_Body (Page, File);
      while not End_Of_File (File) loop
         Resources.Get_Line (File, Buffer, Last);
         Position :=
            Index
              (Source  => Buffer (Buffer'First .. Last),
               Pattern => "=={{header|");
         if Position > 0 then
            Languages := Languages + 1;
         end if;
      end loop;
      Close (File);
      return Languages;
   end Scan_Page;

begin
   Get_Vector ("Programming_Tasks", Exemples);

   for I in First_Index (Exemples) .. Last_Index (Exemples) loop
      declare
         Title : constant String :=
            To_String (Members_Vectors.Element (Exemples, I));
      begin
         Nbr_Lg := Scan_Page (Title);
         Total  := Total + Nbr_Lg;
         Put_Line (Title & " :" & Integer'Image (Nbr_Lg) & " exemples.");
      end;
   end loop;

   Put_Line ("Total :" & Integer'Image (Total) & " exemples.");
end Count_Examples;


UrlDownloadToFile
  , http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml
  , tasks.xml
FileRead, tasks, tasks.xml
pos = 0
quote = "  ; "
regtitle := "<cm.*?title=" . quote . "(.*?)" . quote
While, pos := RegExMatch(tasks, regtitle, title, pos + 1)
{
  UrlDownloadToFile
    , % "http://www.rosettacode.org/w/index.php?title=" . title1 . "&action=raw"
    , task.xml
  FileRead, task, task.xml
  RegExReplace(task, "\{\{header\|", "", count)
  current :=  title1 . ": " . count . " examples.`n"
  output .= current
  TrayTip, current, % current
}
MsgBox % output
Return


      VDU 23,22,640;512;8,16,16,128+8 : REM Enable UTF-8 support

      SYS "LoadLibrary", "URLMON.DLL" TO urlmon%
      SYS "GetProcAddress", urlmon%, "URLDownloadToFileA" TO UDTF
      special$ = "+()'"

      url$ = "http://www.rosettacode.org/w/api.php?action=query" + \
      \      "&list=categorymembers&cmtitle=Category:Programming_Tasks" + \
      \      "&cmlimit=500&format=xml"
      file$ = @tmp$ + "tasks.xml"
      SYS UDTF, 0, url$, file$, 0, 0 TO fail%
      IF fail% ERROR 100, "File download failed (tasks)"

      Total% = 0
      file% = OPENIN(file$)
      WHILE NOT EOF#file%
        a$ = GET$#file%
        i% = 0
        REPEAT
          i% = INSTR(a$, "title=", i%+1)
          IF i% THEN
            j% = INSTR(a$, ">", i%)
            title$ = MID$(a$, i%+7, j%-i%-10)
            REM Replace HTML codes:
            REPEAT
              k% = INSTR(title$, "&")
              IF k% THEN
                l% = INSTR(title$, ";", k%)
                title$ = LEFT$(title$,k%-1) + \
                \        FNhtml(MID$(title$,k%,l%-k%+1)) + MID$(title$,l%+1)
              ENDIF
            UNTIL k% = 0
            t$ = title$
            REM Substitute characters not allowed in a URL:
            FOR s% = 1 TO LEN(special$)
              REPEAT
                s$ = MID$(special$, s%, 1)
                k% = INSTR(t$, s$)
                IF k% t$ = LEFT$(t$,k%-1) + "%" + STR$~ASCs$ + MID$(t$,k%+1)
              UNTIL k% = 0
            NEXT
            url$ = "http://www.rosettacode.org/w/index.php?title=" + t$ + \
            \      "&action=raw"
            file$ = @tmp$ + "title.htm"
            SYS UDTF, 0, url$, file$, 0, 0 TO fail%
            IF fail% ERROR 100, "File download failed " + t$
            examples% = 0
            task% = OPENIN(file$)
            WHILE NOT EOF#task%
              IF INSTR(GET$#task%, "=={{header|") examples% += 1
            ENDWHILE
            CLOSE #task%
            Total% += examples%
            PRINT title$ ": " ; examples% " examples."
          ENDIF
        UNTIL i% = 0
        i% = INSTR(a$, "cmcontinue=")
        IF i% THEN
          CLOSE #file%
          j% = INSTR(a$, """", i%+1)
          k% = INSTR(a$, """", j%+1)
          url$ = "http://www.rosettacode.org/w/api.php?action=query" + \
          \      "&list=categorymembers&cmtitle=Category:Programming_Tasks" + \
          \      "&cmlimit=500&format=xml&cmcontinue=" + MID$(a$,j%+1,k%-j%)
          REPEAT
            i% = INSTR(url$, "|")
            IF i% url$ = LEFT$(url$,i%-1) + "%7C" + MID$(url$,i%+1)
          UNTIL i% = 0
          file$ = @tmp$ + "tasks.xml"
          SYS UDTF, 0, url$, file$, 0, 0 TO fail%
          IF fail% ERROR 100, "File download failed (continue)"
          file% = OPENIN(file$)
        ENDIF
      ENDWHILE
      CLOSE #file%
      PRINT ' "Total: " ; Total% " examples."
      END

      DEF FNhtml(h$)
      IF LEFT$(h$,2) = "&#" THEN = CHR$(VALMID$(h$,3))
      CASE h$ OF
        WHEN """: = """"
      ENDCASE
      = h$


( ( get-page
  =
    .   sys$(str$("wget -q -O wget.out \"" !arg \"))
      & get$("wget.out",HT ML)
  )
&   get-page$"http://rosettacode.org/wiki/Category:Programming_Tasks"
  : ? (table.?) ?tasklist (.table.) ?
& 0:?list
&   whl
  ' ( !tasklist
    :   ?
        ( a
        .   ([email protected](?:"/wiki/" ?href)) (title.?title)
          &   get-page$(str$("http://rosettacode.org/wiki/" !href))
            : ?task
          & 0:?cnt
          &   whl
            ' (   !task
                :   ?
                    (   (span.(class.mw-headline) (id.?))
                        ?span
                        (.span.)
                        ?task
                    &   !span
                      :   ?
                          ( a
                          .   ([email protected](?:"/wiki/Category:" ?))
                              ([email protected](?:"Category:" ?))
                          )
                          @
                          (.a.)
                          ?
                    )
              & 1+!cnt:?cnt
              )
          & (!cnt.!title)+!list:?list
        )
        ?tasklist
    )
& lst$(list,taskfreq,NEW)
)


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Net;

class Task {
    private string _task;
    private int _examples;

    public Task(string task, int examples) {
        _task = task;
        _examples = examples;
    }

    public string Name {
        get { return _task; }
    }

    public int Examples {
        get { return _examples; }
    }

    public override string ToString() {
        return String.Format("{0}: {1} examples.", this._task, this._examples);
    }
}

class Program {
    static List<string> GetTitlesFromCategory(string category, WebClient wc) {
        string content = wc.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.Replace("\\/", "/")).ToList();
    }

    static string GetSourceCodeFromPage(string page, WebClient wc) {
        return wc.DownloadString(
            String.Format("http://www.rosettacode.org/w/index.php?title={0}&action=raw", page)
        );
    }

    static void Main(string[] args) {
        WebClient wc = new WebClient();
        List<Task> tasks = new List<Task>();
        List<string> tasknames = GetTitlesFromCategory("Programming_Tasks", wc);

        foreach (string task in tasknames) {
            string content = GetSourceCodeFromPage(task, wc);
            int count = new Regex("=={{header", RegexOptions.IgnoreCase).Matches(content).Count;
            Task t = new Task(task, count);

            Console.WriteLine(t);
            tasks.Add(t);
        }

        Console.WriteLine("\nTotal: {0} examples.", tasks.Select(x => x.Examples).Sum());
    }
}


(ns count-examples
  (:import [java.net URLEncoder])
  (:use [clojure.contrib.http.agent :only (http-agent string)]
        [clojure.contrib.json :only (read-json)]
        [clojure.contrib.string :only (join)]))

(defn url-encode [v] (URLEncoder/encode (str v) "utf-8"))

(defn rosettacode-get [path params]
  (let [param-string (join "&" (for [[n v] params] (str (name n) "=" (url-encode v))))]
    (string (http-agent (format "http://www.rosettacode.org/w/%s?%s" path param-string)))))

(defn rosettacode-query [params]
  (read-json (rosettacode-get "api.php" (merge {:action "query" :format "json"} params))))

(defn list-cm
  ([params] (list-cm params nil))
  ([params continue]
     (let [cm-params (merge {:list "categorymembers"} params (or continue {}))
           result (rosettacode-query cm-params)]
       (concat (-> result (:query) (:categorymembers))
               (if-let [cmcontinue (-> result (:query-continue) (:categorymembers))]
                 (list-cm params cmcontinue))))))

(defn programming-tasks []
  (let [result (list-cm {:cmtitle "Category:Programming_Tasks" :cmlimit 50})]
    (map #(:title %) result)))

(defn task-count [task]
  [task (count
         (re-seq #"==\{\{header"
                 (rosettacode-get "index.php" {:action "raw" :title task})))])

(defn print-result []
  (let [task-counts (map task-count (programming-tasks))]
    (doseq [[task count] task-counts]
      (println (str task ":") count)
      (flush))
    (println "Total: " (reduce #(+ %1 (second %2)) 0 task-counts))))


import tango.io.Stdout;
import tango.net.http.HttpClient;
import tango.net.http.HttpHeaders;
import tango.text.xml.Document;
import tango.text.Util;

alias HttpHeader.ContentLength CL;

auto url = "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml";
void main()
{
    auto client = new HttpClient (HttpClient.Get, url);
    client.open();
    char[] mainData, tmp;
    int total, i;

    void cat(void[] content) { tmp ~= cast(char[]) content; }

    if (client.isResponseOK) {
        client.read(&cat, client.getResponseHeaders.getInt(CL));
        mainData = tmp;
        tmp = null;

        auto doc = new Document!(char);
        doc.parse(mainData);
        foreach (n; doc.query.descendant("cm").attribute("title")) {
            auto subClient = new HttpClient(HttpClient.Get,
                    "http://www.rosettacode.org/w/index.php?title=" ~
                    replace(n.value.dup, ' ', '_') ~ "&action=raw");
            subClient.open();
            if (! subClient.isResponseOK) {
                Stderr (client.getResponse);
                 break;
            }
            subClient.read(&cat, subClient.getResponseHeaders.getInt(CL));
            foreach (segment; patterns(cast(char[])tmp, "=={{header|")) i++;
            --i;
            if (i) --i;
            Stdout.formatln ("{0,-40} - {}", n.value, i);
            total += i;
            tmp = null;
            i = 0;
        }
        Stdout("total examples: ", total).newline;
    } else {
        Stderr (client.getResponse);
    }
}


package com.eglexamples.client;

import org.eclipse.edt.rui.widgets.*;

handler RosettaCodeHandler type RUIhandler{initialUI =[ui], title = "Rosetta Code Tasks and Counts"}

    ui GridLayout{columns = 3, rows = 4, cellPadding = 4, children = [ b1, dg1, l1, l2, l3, l4 ]};

    b1 Button{ layoutData = new GridLayoutData{ row = 1, column = 1 }, text = "Go!", onClick ::= b1_onClick };
    l1 TextLabel{ layoutData = new GridLayoutData{ row = 1, column = 2 }, text = "Total Tasks:" };
    l2 TextLabel{ layoutData = new GridLayoutData{ row = 1, column = 3 }, text = "0" };

    l3 TextLabel{ layoutData = new GridLayoutData{ row = 2, column = 2 }, text = "Total Implementations:" };
    l4 TextLabel{ layoutData = new GridLayoutData{ row = 2, column = 3 }, text = "0" };

    dg1 DataGrid{ layoutData = new GridLayoutData{ row = 3, column = 1, horizontalSpan = 3 },
    	pageSize = 10, showScrollbar = true,
	columns = [ new DataGridColumn{name = "title", displayName = "Task", width=220},
		    new DataGridColumn{name = "count", displayName = "Count", width=100} ] };

    cmcontinue string?;
    title string?;
    allTasks Task[];

    restBindingTasks IHttp? = new HttpRest{
        restType = eglx.rest.ServiceType.TrueRest,
   	request.uri = "http://rosettacode.org/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=1&format=json"};

    restBindingPageDetail IHttp? = new HttpRest{
        restType = eglx.rest.ServiceType.TrueRest,
   	request.uri = "http://rosettacode.org/mw/index.php"};

    function b1_onClick(event Event in)
	call ProxyFunctions.listTasks("") using restBindingTasks
    	    returning to listTasksCallBack onException exceptionHandler;
    end

    function listTasksCallBack(retResult RosettaCodeJSON in)
	title = retResult.query.categorymembers[1].title;
	cmcontinue = retResult.queryContinue.categorymembers.cmcontinue;

	call ProxyFunctions.fetchPageDetail(title) using restBindingPageDetail
 	    returning to pageDetailCallBack onException exceptionHandler;
    end

    function pageDetailCallBack(pageResults string in)
   	count int = countSubstring("=={{header", pageResults);
   	allTasks.appendElement(new Task { title = title, count = count });
	l2.text = l2.text as int + 1;
	l4.text = l4.text as int + count;

   	if(cmcontinue != null)
	    call ProxyFunctions.listTasks(cmcontinue) using restBindingTasks
		returning to listTasksCallBack onException exceptionHandler;
	else
	    dg1.data = allTasks as any[];
	end
    end

    function countSubstring(substr string in, str string in) returns(int)
	if(str.length() > 0 and substr.length() > 0)
	    return (str.length() - str.replaceStr(subStr, "").length()) / subStr.length();
	else
	    return 0;
	end
    end

   function exceptionHandler(exp AnyException in)
   end

end

record Task
	title string;
	count int;
end


-module(rosseta_examples).
-include_lib("xmerl/include/xmerl.hrl").

-export([main/0]).

main() ->
   application:start(inets),
   Titles = read_titles(empty),
   Result = lists:foldl(fun(Title,Acc) -> Acc + calculate_one(Title) end, 0, Titles),
   io:format("Total: ~p examples.\n",[Result]),
   application:stop(inets).

read_titles(CurrentContinue) ->
   URL0 = "http://rosettacode.org/mw/api.php?" ++
         "action=query&list=categorymembers&cmtitle=Category:Programming_Tasks" ++
         "&cmlimit=500&format=xml",
   URL =
      case CurrentContinue of
         empty -> URL0;
         _ -> URL0 ++ "&cmcontinue=" ++ CurrentContinue
      end,
   {ok,Answer} = httpc:request(URL),
   {Document,_} = xmerl_scan:string(lists:last(tuple_to_list(Answer))),
   Continue =
      [Value || #xmlAttribute{value = Value} <- xmerl_xpath:string("//@cmcontinue", Document)],
   Titles =
     [Value || #xmlAttribute{value = Value} <- xmerl_xpath:string("//@title", Document)],
   case Continue of
      []->
         Titles;
      [ContValue | _] ->
         Titles ++ read_titles(ContValue)
   end.

calculate_one(Title0) ->
   Title = replace_chars(Title0),
   URL = "http://www.rosettacode.org/w/index.php?title=" ++
         Title ++ "&action=raw",
   case httpc:request(URL) of
      {ok,Result} ->
            {match,Found} =
               re:run(lists:last(tuple_to_list(Result)), "\n=={{header(|)", [global]),
            io:format("~ts: ~p examples.\n",[Title0,length(Found)]),
            length(Found);
      {error,socket_closed_remotely} ->
         io:format("Socket closed remotely. Retry.\n"),
         calculate_one(Title0)
   end.

replace_chars(String) ->
   replace_chars(String,[]).

replace_chars([$ | T],Acc) ->
   replace_chars(T, [$_| Acc]);
replace_chars([$+| T],Acc) ->
   replace_chars(T, lists:reverse("%2B") ++ Acc);
replace_chars([8211| T],Acc) ->
   replace_chars(T, lists:reverse("%E2%80%93") ++ Acc);
replace_chars([Other| T],Acc) ->
   replace_chars(T, [Other| Acc]);
replace_chars([],Acc) ->
   lists:reverse(Acc).


#r "System.Xml.Linq.dll"

let uri1 = "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml"
let uri2 task = sprintf "http://www.rosettacode.org/w/index.php?title=%s&action=raw" task

[|for xml in (System.Xml.Linq.XDocument.Load uri1).Root.Descendants() do
    for attrib in xml.Attributes() do
      if attrib.Name.LocalName = "title" then
        yield async {
          let uri = uri2 (attrib.Value.Replace(" ", "_") |> System.Web.HttpUtility.UrlEncode)
          use client = new System.Net.WebClient()
          let! html = client.AsyncDownloadString(System.Uri uri)
          let sols' = html.Split([|"{{header|"|], System.StringSplitOptions.None).Length - 1
          lock stdout (fun () -> printfn "%s: %d examples" attrib.Value sols')
          return sols' }|]
|> Async.Parallel
|> Async.RunSynchronously
|> fun xs -> printfn "Total: %d examples" (Seq.sum xs)


USING: arrays assocs concurrency.combinators
concurrency.semaphores formatting hashtables http.client io
json.reader kernel math math.parser sequences splitting
urls.encoding ;
IN: rosetta-code.count-examples

CONSTANT: list-url "http://rosettacode.org/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&cmprop=title&format=json"

: titles ( query -- titles )
  "query" of "categorymembers" of [ "title" of ] map ;
: continued-url ( query -- url/f )
  "query-continue" of "categorymembers" of
  [ assoc>query list-url swap "&" glue ] [ f ] if* ;

: (all-programming-titles) ( titles url -- titles' url' )
  http-get nip json> [ titles append ] [ continued-url ] bi
  [ (all-programming-titles) ] [ f ] if* ;
: all-programming-titles ( -- titles ) { } list-url (all-programming-titles) drop ;

CONSTANT: content-base-url "http://rosettacode.org/mw/index.php?title=&action=raw"
: content-url ( title -- url )
  " " "_" replace
  "title" associate assoc>query
  content-base-url swap "&" glue ;

: occurences ( seq subseq -- n ) split-subseq length 1 - ;
: count-examples ( title -- n )
  content-url http-get nip "=={{header|" occurences ;

: print-task ( title n -- ) "%s: %d examples.\n" printf ;
: print-total ( assoc -- ) values sum "Total: %d examples.\n" printf ;
: fetch-counts ( titles -- assoc )
  10 <semaphore> [
    [ dup count-examples 2array ] with-semaphore
  ] curry parallel-map ;

: print-counts ( titles -- )
  [ [ print-task ] assoc-each nl ] [ print-total ] bi ;
: rosetta-examples ( -- )
  all-programming-titles fetch-counts print-counts ;

MAIN: rosetta-examples


package main

import (
    "bytes"
    "encoding/xml"
    "fmt"
    "io"
    "io/ioutil"
    "net/http"
    "net/url"
    "strings"
)

func req(u string, foundCm func(string)) string {
    resp, err := http.Get(u)
    if err != nil {
        fmt.Println(err) // connection or request fail
        return ""
    }
    defer resp.Body.Close()
    for p := xml.NewDecoder(resp.Body); ; {
        t, err := p.RawToken()
        switch s, ok := t.(xml.StartElement); {
        case err == io.EOF:
            return ""
        case err != nil:
            fmt.Println(err)
            return ""
        case !ok:
            continue
        case s.Name.Local == "cm":
            for _, a := range s.Attr {
                if a.Name.Local == "title" {
                    foundCm(a.Value)
                }
            }
        case s.Name.Local == "categorymembers" && len(s.Attr) > 0 &&
            s.Attr[0].Name.Local == "cmcontinue":
            return url.QueryEscape(s.Attr[0].Value)
        }
    }
    return ""
}

func main() {
    taskQuery := "http://rosettacode.org/mw/api.php?action=query" +
        "&format=xml&list=categorymembers&cmlimit=500" +
        "&cmtitle=Category:Programming_Tasks"
    continueAt := req(taskQuery, count)
    for continueAt > "" {
        continueAt = req(taskQuery+"&cmcontinue="+continueAt, count)
    }
    fmt.Printf("Total: %d examples.\n", total)
}

var marker = []byte("=={{header|")
var total int

func count(cm string) {
    taskFmt := "http://rosettacode.org/mw/index.php?title=%s&action=raw"
    taskEsc := url.QueryEscape(strings.Replace(cm, " ", "_", -1))
    resp, err := http.Get(fmt.Sprintf(taskFmt, taskEsc))
    var page []byte
    if err == nil {
        page, err = ioutil.ReadAll(resp.Body)
        resp.Body.Close()
    }
    if err != nil {
        fmt.Println(err)
        return
    }
    examples := bytes.Count(page, marker)
    fmt.Printf("%s: %d\n", cm, examples)
    total += examples
}


import Network.Browser
import Network.HTTP
import Network.URI
import Data.List
import Data.Maybe
import Text.XML.Light
import Control.Arrow

justifyR w = foldl ((.return).(++).tail) (replicate w ' ')
showFormatted t n = t ++ ": " ++ justifyR 4 (show n)

getRespons url = do
    rsp <- Network.Browser.browse $ do
      setAllowRedirects True
      setOutHandler $ const (return ())     -- quiet
      request $ getRequest url
    return $ rspBody $ snd rsp

getNumbOfExampels p = do
  let pg = intercalate "_" $ words p
  rsp <- getRespons $ "http://www.rosettacode.org/w/index.php?title=" ++ pg ++ "&action=raw"
  let taskPage = rsp
      countEx = length $ filter (=="=={{header|") $ takeWhile(not.null) $ unfoldr (Just. (take 11 &&& drop 1)) taskPage
  return countEx

progTaskExamples = do
  rsp <- getRespons "http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml"

  let xmls = onlyElems $ parseXML $ rsp
      tasks = concatMap (map (fromJust.findAttr (unqual "title")). filterElementsName (== unqual "cm")) xmls

  taskxx <- mapM getNumbOfExampels tasks
  let ns = taskxx
      tot = sum ns

  mapM_ putStrLn $ zipWith showFormatted tasks ns
  putStrLn $ ("Total: " ++) $ show tot


$define RCINDEX "http://rosettacode.org/mw/api.php?format=xml&action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500"
$define RCTASK  "http://rosettacode.org/mw/index.php?action=raw&title="
$define RCUA    "User-Agent: Unicon Rosetta 0.1"
$define RCXUA   "X-Unicon: http://unicon.org/"
$define TASKTOT "* Total Tasks *"
$define TOTTOT  "* Total Headers*"

link strings
link hexcvt

procedure main(A)   # simple single threaded read all at once implementation
    Tasks := table(0)
    every task := taskNames() do {
       Tasks[TASKTOT] +:= 1                            # count tasks
       every lang := languages(task) do {              # count languages
          Tasks[task] +:= 1
          Tasks[TOTTOT] +:= 1
          }
       }
    every insert(O := set(),key(Tasks))                # extract & sort keys
    O := put(sort(O--set(TOTTOT,TASKTOT)),TASKTOT,TOTTOT)  # move totals to end
    every write(k := !O, " : ", Tasks[k]," examples.") # report
end

# Generate task names
procedure taskNames()
    continue := ""
    while \(txt := ReadURL(RCINDEX||continue)) do {
        txt ? {
            while tab(find("<cm ") & find(s :="title=\"")+*s) do
                suspend tab(find("\""))\1
            if tab(find("cmcontinue=")) then {
                continue := "&"||tab(upto(' \t'))
                }
            else break
            }
        }
end

# Generate language headers in a task
procedure languages(task)
    static WS
    initial WS := ' \t'
    page := ReadURL(RCTASK||CleanURI(task))
    page ? while (tab(find("\n==")),tab(many(WS))|"",tab(find("{{"))) do {
               header := tab(find("=="))
               header ? {
                   while tab(find("{{header|")) do {
                       suspend 2(="{{header|",tab(find("}}")))\1
                       }
                   }
               }
end

procedure CleanURI(u)                  #: clean up a URI
    static tr,dxml                     # xml & http translation
    initial {
       tr := table()
       every c := !string(~(&digits++&letters++'-_.!~*()/\'`')) do
          tr[c] := "%"||hexstring(ord(c),2)
       every /tr[c := !string(&cset)] := c
       tr[" "] := "_"                                      # wiki convention
       every push(dxml := [],"&#"||right(ord(c := !"&<>'\""),3,"0")||";",c)
       }

    dxml[1] := u                       # insert URI as 1st arg
    u := replacem!dxml                 # de-xml it
    every (c := "") ||:= tr[!u]        # reencode everything
    c := replace(c,"%3E","'")          # Hack to put single quotes back in
    c := replace(c,"%26quot%3B","\"")  # Hack to put double quotes back in
    return c
end

procedure ReadURL(url)                 #: read URL into string
    page := open(url,"m",RCUA,RCXUA) | stop("Unable to open ",url)
    text := ""
    if page["Status-Code"] < 300 then while text ||:= reads(page,-1)
    else write(&errout,image(url),": ",
                       page["Status-Code"]," ",page["Reason-Phrase"])
    close(page)
    return text
end


require 'web/gethttp'

getAllTaskSolnCounts=: monad define
  tasks=.  getCategoryMembers 'Programming_Tasks'
  counts=. getTaskSolnCounts &> tasks
  tasks;counts
)

getTaskSolnCounts=: monad define
  makeuri=. 'http://www.rosettacode.org/w/index.php?title=' , ,&'&action=raw'
  wikidata=. gethttp makeuri urlencode y
  ([: +/ '{{header|'&E.) wikidata
)

formatSolnCounts=: monad define
  'tasks counts'=. y
  tasks=. tasks , &.>':'
  res=. ;:^:_1 tasks ,. (8!:0 counts) ,. <'examples.'
  res , 'Total examples: ' , ": +/counts
)


import java.util.ArrayList;
import ScreenScrape;

public class CountProgramExamples {
    private static final String baseURL = "http://rosettacode.org/wiki/";
    private static final String rootURL = "http://www.rosettacode.org/w/"
        + "api.php?action=query&list=categorymembers"
        + "&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml";
    private static final String taskBegin = "title=\"";
    private static final String taskEnd = "\"";
    private static final String exmplBegin = "";
    private static final String exmplEnd = "";
    private static final String editBegin = "";

    /**
     * @param args
     */
    public static void main(String[] args) {
        int exTotal = 0;
        try {
            // Get root query results
            ArrayList<String> tasks = new ArrayList<String>();
            ScreenScrape ss = new ScreenScrape();
            String rootPage = ss.read(rootURL);
            while (rootPage.contains(taskBegin)) {
                rootPage = rootPage.substring(rootPage.indexOf(taskBegin)
                    + taskBegin.length());
                String title = rootPage.substring(0, rootPage.indexOf(taskEnd));
                if (!title.contains("Category:")) {
                    tasks.add(title);
                }
                rootPage = rootPage.substring(rootPage.indexOf(taskEnd));
            }
            // Loop through each task and print count
            for (String task : tasks) {
                String title = task.replaceAll("'", "'");
                String taskPage = ss.read(baseURL + title.replaceAll(" ", "_"));
                int exSubTot;
                if (taskPage.contains(exmplBegin)) {
                    int startPos = taskPage.lastIndexOf(exmplBegin)
                        + exmplBegin.length();
                    String countStr = taskPage.substring(startPos,
                        taskPage.indexOf(exmplEnd, startPos));
                    exSubTot = Integer
                        .parseInt(countStr.contains(".") ? countStr
                            .substring(0, countStr.indexOf("."))
                            : countStr);
                } else {
                    exSubTot = 0;
                    while (taskPage.contains(editBegin)) {
                        taskPage = taskPage.substring(taskPage
                            .indexOf(editBegin) + editBegin.length());
                        exSubTot++;
                    }
                }
                exTotal += exSubTot;
                System.out.println(title + ": " + exSubTot + " examples.");
            }
            // Print total
            System.out.println("\nTotal: " + exTotal + " examples.");
        } catch (Exception e) {
            System.out.println(title);
            System.out.println(startPos + ":"
                + taskPage.indexOf(exmplEnd, startPos));
            System.out.println(taskPage);
            e.printStackTrace(System.out);
        }
    }
}


#!/bin/bash

# Produce lines of the form: URI TITLE
function titles {
    local uri="http://www.rosettacode.org/mw/api.php?action=query&list=categorymembers"
    uri+="&cmtitle=Category:Programming_Tasks&cmlimit=5000&format=json"
    curl -Ss "$uri" |
      jq -r '.query.categorymembers[] | .title | "\(@uri) \(.)"'
}

# Syntax: count URI
function count {
    local uri="$1"
    curl -Ss "http://rosettacode.org/mw/index.php?title=${uri}&action=raw" |
      jq -R -n 'reduce (inputs|select(test("=={{header\\|"))) as $x(0; .+1)'
}

local n=0 i
while read uri title
do
    i=$(count "$uri")
    echo "$title: $i examples."
    n=$((n + i))
done < <(titles)
echo Total: $n examples.


using HTTP, JSON, Dates

rosorg = "http://rosettacode.org"
qURI = "/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=json"
qdURI = "/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Draft_Programming_Tasks&cmlimit=500&format=json"
sqURI = rosorg * "/wiki/"
topages(js, v) = for d in js["query"]["categorymembers"] push!(v, sqURI * replace(d["title"], " " => "_")) end

function getpages(uri)
    wikipages = Vector{String}()
    response = HTTP.request("GET", rosorg * uri)
    if response.status == 200
        fromjson = JSON.parse(String(response.body))
        topages(fromjson, wikipages)
        while haskey(fromjson, "continue")
            cmcont, cont = fromjson["continue"]["cmcontinue"], fromjson["continue"]["continue"]
            response = HTTP.request("GET", rosorg * uri * "&cmcontinue=$cmcont&continue=$cont")
            fromjson = JSON.parse(String(response.body))
            topages(fromjson, wikipages)
        end
    end
    wikipages
end

function processtaskpages(wpages, verbose=false)
    totalexamples = 0
    for pag in wpages
        response = HTTP.request("GET", pag)
        if response.status == 200
            n = length(collect(eachmatch(r"span class=\"mw-headline\"", String(response.body))))
            if verbose
                println("Wiki page $pag => $n examples.")
            end
            totalexamples += n
        end
    end
    println("Total of $totalexamples on $(length(wpages)) task pages.\n")
end

println("Programming examples at $(DateTime(now())):")
qURI |> getpages |> processtaskpages

println("Draft programming tasks:")
qdURI |> getpages |> processtaskpages


local(root = json_deserialize(curl('http://rosettacode.org/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=10&format=json')->result))
local(tasks = array, title = string, urltitle = string, thiscount = 0, totalex = 0)
with i in #root->find('query')->find('categorymembers') do => {^
	#thiscount = 0
	#title = #i->find('title')
	#urltitle = #i->find('title')
	#urltitle->replace(' ','_')

	#title+': '
	local(src = curl('http://rosettacode.org/mw/index.php?title='+#urltitle->asBytes->encodeurl+'&action=raw')->result->asString)
	#thiscount = (#src->split('=={{header|'))->size - 1
	#thiscount < 0 ? #thiscount = 0
	#thiscount + ' examples.'
	#totalex += #thiscount
	'\r'
^}
'Total: '+#totalex+' examples.'


on mouseUp
    put empty into fld "taskurls"
    put URL "http://rosettacode.org/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=10&format=xml" into  apixml
    put revXMLCreateTree(apixml,true,true,false) into pDocID
    put "/api/query/categorymembers/cm" into pXPathExpression
    repeat for each line xmlnode in revXMLEvaluateXPath(pDocID, pXPathExpression)
        put revXMLAttribute(pDocID,xmlnode,"title") into pgTitle
        put revXMLAttribute(pDocID,xmlnode,"pageid") into pageId
        put "http://www.rosettacode.org/w/index.php?title=" & urlEncode(pgTitle) & "&action=raw" into taskURL
        put URL taskURL into taskPage
        filter lines of taskPage with "=={{header|*"
        put the number of lines of taskPage into taskTotal
        put pgTitle & comma & taskTotal & cr after fld "tasks"
        add taskTotal to allTaskTotal
    end repeat
    put "Total" & comma & allTaskTotal after fld "tasks"
end mouseUp


ConvertUTF8 := proc( str )
        local i, tempstring, uniindex;
       try
           tempstring := str;
           uniindex := [StringTools:-SearchAll("\u",str)];
           if uniindex <> [] then
               for i in uniindex  do
                   tempstring := StringTools:-Substitute(tempstring, str[i..i+5], UTF8:-unicode(str[i+2..i+5]));
               end do:
           end if;
           return tempstring;
       catch:
           return str;
       end try;
   end proc:
print_examples := proc(lst)
	local task, count, url, headers, item;
	for task in lst do
		count := 0:
		url := cat("http://www.rosettacode.org/mw/index.php?title=", StringTools:-Encode(StringTools:-SubstituteAll(task["title"], " ", "_"), 'percent'), "&action=raw"):
		headers := [StringTools:-SearchAll("=={{header|",URL:-Get(url))]:
		for item in headers do
			count++:
		end do:
		printf("%s has %d examples\n",ConvertUTF8(task["title"]), count);
	end do:
end proc:

x := JSON:-ParseFile("http://rosettacode.org/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=20&format=json"):
print_examples(x["query"]["categorymembers"]);
while(assigned(x["continue"]["cmcontinue"])) do
	continue := x["continue"]["cmcontinue"]:
	more_tasks:= cat("http://rosettacode.org/mw/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=20&format=json", "&continue=", x["continue"]["continue"], "&cmcontinue=", x["continue"]["cmcontinue"]):
	x := JSON:-ParseFile(more_tasks):
	print_examples(x["query"]["categorymembers"]);
end do:


TaskList = Flatten[
   Import["http://rosettacode.org/wiki/Category:Programming_Tasks", "Data"][[1, 1]]];
Print["Task \"", StringReplace[#, "_" -> " "], "\" has ",
  [email protected][Import["http://rosettacode.org/wiki/" <> #, "Data"][[1,2]],
  StringFreeQ[#, __ ~~ "Programming Task" | __ ~~ "Omit"]& ], " example(s)"]&
  ~Map~ StringReplace[TaskList, " " -> "_"]


function c = count_examples(url)
    c = 0;
    [s, success] = urlread (url);
    if ~success, return; end;
    c = length(strfind(s,'
<span class='));
  end;

  % script
  s   = urlread ('http://rosettacode.org/wiki/Category:Programming_Tasks');
  pat = '
<a href="/wiki/';
  ix  = strfind(s,pat)+length(pat)-6;
  for k = 1:length(ix);
     % look through all tasks
     e = find(s(ix(k):end)==34,1)-2;
     t = s(ix(k)+[0:e]);    % task
     c = count_examples(['http://rosettacode.org',t]);
     printf('Task "%s" has %i examples.\n',t(7:end), c);
  end;