Rosetta Code/Count examples: Difference between revisions

m
→‎{{header|Wren}}: Minor changes (though see Talk Page re encoding of '+')
(→‎{{header|Raku}}: Marked omitted tasks; count shared entries (C / C++))
m (→‎{{header|Wren}}: Minor changes (though see Talk Page re encoding of '+'))
 
(13 intermediate revisions by 8 users not shown)
Line 18:
{{libheader|AWS}}
Parsing XML file with XMLAda from AdaCore
<langsyntaxhighlight Adalang="ada">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;
Line 119:
Put_Line ("Total :" & Integer'Image (Total) & " exemples.");
end Count_Examples;
</syntaxhighlight>
</lang>
Output :
<pre>
Line 130:
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">UrlDownloadToFile
, http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml
, tasks.xml
Line 149:
}
MsgBox % output
Return</langsyntaxhighlight>
 
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> VDU 23,22,640;512;8,16,16,128+8 : REM Enable UTF-8 support
SYS "LoadLibrary", "URLMON.DLL" TO urlmon%
Line 236:
WHEN "&quot;": = """"
ENDCASE
= h$</langsyntaxhighlight>
'''Sample output:'''
<pre>
Line 265:
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat">( ( get-page
=
. sys$(str$("wget -q -O wget.out \"" !arg \"))
Line 305:
)
& lst$(list,taskfreq,NEW)
)</langsyntaxhighlight>
Output (in file <code>tasqfreq</code>):
<pre>list=
Line 353:
Object-oriented solution.
 
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 402:
 
foreach (string task in tasknames) {
stringtry content = GetSourceCodeFromPage(task, wc);{
string content = GetSourceCodeFromPage(WebUtility.UrlEncode(task), wc);
int count = new Regex("=={{header", RegexOptions.IgnoreCase).Matches(content).Count;
Task t int count = new TaskRegex(task"=={{header", countRegexOptions.IgnoreCase).Matches(content).Count;
Task t = new Task(task, count);
 
Console.WriteLine(t);
tasks.Add(t);
}
catch (Exception ex) {
Console.WriteLine("**** Unable to get task \"" + task + "\": " + ex.Message);
}
}
 
Console.WriteLine("\nTotal: {0} examples.", tasks.Select(x => x.Examples).Sum());
}
}</langsyntaxhighlight>
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">(ns count-examples
(:import [java.net URLEncoder])
(:use [clojure.contrib.http.agent :only (http-agent string)]
Line 454 ⟶ 459:
(flush))
(println "Total: " (reduce #(+ %1 (second %2)) 0 task-counts))))
</syntaxhighlight>
</lang>
<langsyntaxhighlight lang="clojure">count-examples> (print-result)
100 doors: 73
24 game: 18
Line 471 ⟶ 476:
Total: 11216
nil
</syntaxhighlight>
</lang>
 
=={{header|D}}==
{{works with|Tango}}
<syntaxhighlight lang="d">
<lang D>
import tango.io.Stdout;
import tango.net.http.HttpClient;
Line 524 ⟶ 529:
}
}
</syntaxhighlight>
</lang>
 
=={{header|EGL}}==
Line 532 ⟶ 537:
 
User Interface: RosettaCodeHandler.egl
<langsyntaxhighlight EGLlang="egl">package com.eglexamples.client;
 
import org.eclipse.edt.rui.widgets.*;
Line 607 ⟶ 612:
title string;
count int;
end</langsyntaxhighlight>
 
Service Interface: ProxyFunctions.egl
<langsyntaxhighlight EGLlang="egl">package com.eglexamples.client;
 
library ProxyFunctions
Line 646 ⟶ 651:
record QueryContinue
categorymembers Categorymembers;
end</langsyntaxhighlight>
 
=={{header|Erlang}}==
Line 652 ⟶ 657:
{{libheader|xmerl}}
 
<langsyntaxhighlight lang="erlang">
-module(rosseta_examples).
-include_lib("xmerl/include/xmerl.hrl").
Line 715 ⟶ 720:
replace_chars([],Acc) ->
lists:reverse(Acc).
</syntaxhighlight>
</lang>
 
 
Line 735 ⟶ 740:
Using asynchronous workflows to perform downloads concurrently:
 
<langsyntaxhighlight lang="fsharp">#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"
Line 752 ⟶ 757:
|> Async.Parallel
|> Async.RunSynchronously
|> fun xs -> printfn "Total: %d examples" (Seq.sum xs)</langsyntaxhighlight>
 
This is 21&#215; faster than the python thanks to the concurrency.
Line 759 ⟶ 764:
Runs in about a minute. The number of threads is limited to 10 avoid cloudfare's protection mechanism.
 
<langsyntaxhighlight lang="factor">USING: arrays assocs concurrency.combinators
concurrency.semaphores formatting hashtables http.client io
json.reader kernel math math.parser sequences splitting
Line 800 ⟶ 805:
all-programming-titles fetch-counts print-counts ;
 
MAIN: rosetta-examples</langsyntaxhighlight>
Outputs:
 
Line 812 ⟶ 817:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 886 ⟶ 891:
fmt.Printf("%s: %d\n", cm, examples)
total += examples
}</langsyntaxhighlight>
{{out|Output: (May 25, 2011)}}
<pre>
Line 900 ⟶ 905:
{{libheader|HTTP XML}} from [http://hackage.haskell.org/packages/hackage.html HackageDB]
 
<langsyntaxhighlight lang="haskell">import Network.Browser
import Network.HTTP
import Network.URI
Line 936 ⟶ 941:
 
mapM_ putStrLn $ zipWith showFormatted tasks ns
putStrLn $ ("Total: " ++) $ show tot</langsyntaxhighlight>
some output:
<langsyntaxhighlight lang="haskell">*Main> progTaskExamples
100 doors: 56
24 game: 11
Line 947 ⟶ 952:
Active object: 9
...
Total: 9156</langsyntaxhighlight>
 
==Icon and {{header|Unicon}}==
The following code uses features exclusive to Unicon. This version handles all tasks, not just the first 500.
 
<langsyntaxhighlight Uniconlang="unicon">$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"
Line 1,033 ⟶ 1,038:
close(page)
return text
end</langsyntaxhighlight>
 
{{libheader|Icon Programming Library}}
Line 1,065 ⟶ 1,070:
'''Solution:'''<br>
Using <code>getCategoryMembers</code> from [[Find unimplemented tasks#J|Find unimplemented tasks]].
<langsyntaxhighlight lang="j">require 'web/gethttp'
 
getAllTaskSolnCounts=: monad define
Line 1,084 ⟶ 1,089:
res=. ;:^:_1 tasks ,. (8!:0 counts) ,. <'examples.'
res , 'Total examples: ' , ": +/counts
)</langsyntaxhighlight>
 
'''Example Usage:'''
<langsyntaxhighlight lang="j"> formatSolnCounts getAllTaskSolnCounts ''
100 doors: 61 examples.
24 game: 15 examples.
24 game Player: 11 examples.
99 Bottles of Beer: 76 examples.
...</langsyntaxhighlight>
 
=={{header|Java}}==
{{works with|Java|1.5+}}
<langsyntaxhighlight lang="java5">
import java.util.ArrayList;
import ScreenScrape;
Line 1,166 ⟶ 1,171:
}
}
</syntaxhighlight>
</lang>
[[Count programming examples/Java/ScreenScrape|ScreenScrape class]]
 
Line 1,174 ⟶ 1,179:
`@uri` filter in the bash function `titles`.
 
<langsyntaxhighlight lang="bash">#!/bin/bash
 
# Produce lines of the form: URI TITLE
Line 1,198 ⟶ 1,203:
n=$((n + i))
done < <(titles)
echo Total: $n examples.</langsyntaxhighlight>
 
{{out}}
Line 1,214 ⟶ 1,219:
=={{header|Julia}}==
Output by page is too long, so summaries only output shown.
<langsyntaxhighlight lang="julia">using HTTP, JSON, Dates
 
rosorg = "http://rosettacode.org"
qURI = "/mww/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=json"
qdURI = "/mww/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
Line 1,259 ⟶ 1,264:
println("Draft programming tasks:")
qdURI |> getpages |> processtaskpages
</langsyntaxhighlight>{{out}}
<pre>
Programming examples at 2019-02-16T21:04:15.583:
Line 1,269 ⟶ 1,274:
 
=={{header|Lasso}}==
<langsyntaxhighlight Lassolang="lasso">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 => {^
Line 1,285 ⟶ 1,290:
'\r'
^}
'Total: '+#totalex+' examples.'</langsyntaxhighlight>
 
{{out}}
Line 1,307 ⟶ 1,312:
2. Add a text field called "tasks"
 
n.b. The list of tasks is limited to 10 for demo purposes<langsyntaxhighlight LiveCodelang="livecode">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
Line 1,323 ⟶ 1,328:
end repeat
put "Total" & comma & allTaskTotal after fld "tasks"
end mouseUp</langsyntaxhighlight>
 
=={{header|Maple}}==
<langsyntaxhighlight Maplelang="maple">ConvertUTF8 := proc( str )
local i, tempstring, uniindex;
try
Line 1,363 ⟶ 1,368:
print_examples(x["query"]["categorymembers"]);
end do:
</syntaxhighlight>
</lang>
{{Out|Output}}
<pre>
Line 1,478 ⟶ 1,483:
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">TaskList = Flatten[
Import["http://rosettacode.org/wiki/Category:Programming_Tasks", "Data"][[1, 1]]];
 
Print["Task \"", StringReplace[#, "_" -> " "], "\" has ",
Length@Select[Import["http://rosettacode.org/wiki/" <> #, "Data"][[1,2]],
StringFreeQ[#, __ ~~ "Programming Task" | __ ~~ "Omit"]& ], " example(s)"]&
~Map~ StringReplace[TaskList, " " -> "_"]</langsyntaxhighlight>
returns:
<pre>Task "100 doors" has 143 example(s)
Line 1,495 ⟶ 1,499:
 
The function count_examples() need to be saved in a file count_examples.m and its directory need to be included in the path.
<langsyntaxhighlight MATLABlang="matlab"> function c = count_examples(url)
c = 0;
[s, success] = urlread (url);
Line 1,512 ⟶ 1,516:
c = count_examples(['http://rosettacode.org',t]);
printf('Task "%s" has %i examples.\n',t(7:end), c);
end; </langsyntaxhighlight>
 
Output:
Line 1,524 ⟶ 1,528:
 
=={{header|Nim}}==
<langsyntaxhighlight lang="nim">import httpclient, strutils, xmltree, xmlparser, cgi
 
proc count(s, sub: string): int =
Line 1,546 ⟶ 1,550:
inc sum, c
 
echo "\nTotal: ", sum, " examples."</langsyntaxhighlight>
 
{{out}}
Line 1,574 ⟶ 1,578:
 
=={{header|Objeck}}==
<langsyntaxhighlight lang="objeck">use HTTP;
use XML;
 
Line 1,611 ⟶ 1,615:
return xml;
}
}</langsyntaxhighlight>
 
Output:<pre>Amb: 28
Line 1,644 ⟶ 1,648:
ocamlfind opt -linkpkg -package str,unix,xml-light,netclient countex.ml -o countex.opt
 
<langsyntaxhighlight lang="ocaml">open Http_client.Convenience
 
Line 1,705 ⟶ 1,709:
let catmb = get_child "categorymembers" query in
List.iter f catmb
| _ -> ()</langsyntaxhighlight>
 
outputs:
Line 1,732 ⟶ 1,736:
{{libheader|OzHttpClient}}
 
<langsyntaxhighlight lang="oz">declare
[HTTPClient] = {Module.link ['x-ozlib://mesaros/net/HTTPClient.ozf']}
[XMLParser] = {Module.link ['x-oz://system/xml/Parser.ozf']}
Line 1,816 ⟶ 1,820:
end
in
{Main}</langsyntaxhighlight>
 
Example output:
Line 1,834 ⟶ 1,838:
 
=={{header|Perl}}==
<syntaxhighlight lang="perl">use HTTP::Tiny;
{{libheader|HTTP:Tiny}}
<lang Perl>use HTTP::Tiny;
 
my $site = "http://rosettacode.org";
my $list_url = "/mww/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml";
 
my $response = HTTP::Tiny->new->get("$site$list_url");
Line 1,846 ⟶ 1,849:
my $count = () = $response->{content} =~ /toclevel-1/g;
print "$_: $count examples\n";
}</langsyntaxhighlight>
 
{{libheader|Mojolicious}}
<syntaxhighlight lang="perl">use Mojo::UserAgent;
<lang Perl>use v5.10;
use Mojo::UserAgent;
 
my $site = "http://rosettacode.org";
Line 1,860 ⟶ 1,862:
my $count = $ua->get("$site/wiki/$slug")->res->dom->find("#toc .toclevel-1")->size;
say "$_->{title}: $count examples";
});</langsyntaxhighlight>
 
=={{header|Phix}}==
First, some common code used by several tasks:
Counts no of "{{header|" (nb not "=={{header|") via web api (but gets tasks via scraping).<br>
<!--<syntaxhighlight lang="phix">(notonline)-->
Since downloading all the pages can be very slow, this uses a cache.<br>
<span style="color: #000080;font-style:italic;">--
Limiting (notdone) by "Phix" fairly obviously speeds it up tenfold :-)
<lang Phix> -- demo\rosetta\Count_examplesrosettacode_cache.exwe
-- ================================
constant include_drafts = true,
--
sort_by_count = false,
-- Common routines for handling rc_cache etc.
-- notlang = "Phix" -- or "" (ie a zero length string) for all
--</span>
notlang = ""
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (libcurl, file i/o, peek, progress..)</span>
 
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #004080;">timedate</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
integer lp = 0
<span style="color: #008080;">constant</span> <span style="color: #000000;">day</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">timedelta</span><span style="color: #0000FF;">(</span><span style="color: #000000;">days</span><span style="color: #0000FF;">:=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
procedure progress(string msg, sequence args = {})
<span style="color: #004080;">integer</span> <span style="color: #000000;">refresh_cache</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">21</span><span style="color: #0000FF;">*</span><span style="color: #000000;">day</span> <span style="color: #000080;font-style:italic;">-- 0 for always [NB refresh_cache += timedelta(days:=1) below]</span>
if length(args) then msg = sprintf(msg,args) end if
integer lm = length(msg)
<span style="color: #008080;">function</span> <span style="color: #000000;">days</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">delta</span><span style="color: #0000FF;">)</span>
if lm<lp then msg[$..$] = repeat(' ',lp-lm)&msg[$] end if
<span style="color: #004080;">integer</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">ceil</span><span style="color: #0000FF;">(</span><span style="color: #000000;">delta</span><span style="color: #0000FF;">/</span><span style="color: #000000;">day</span><span style="color: #0000FF;">)</span>
puts(1,msg)
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d day%s"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?</span><span style="color: #008000;">""</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"s"</span><span style="color: #0000FF;">)})</span>
lp = iff(msg[$]='\r'?lm:0)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
end procedure
 
<span style="color: #008080;">constant</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">hex</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ascii</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">({{</span><span style="color: #008000;">"%22"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`"`</span><span style="color: #0000FF;">},</span>
include builtins\timedate.e
<span style="color: #0000FF;">{</span><span style="color: #008000;">"%27"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"'"</span><span style="color: #0000FF;">},</span>
integer refresh_cache = timedelta(days:=365) -- 0 for always
<span style="color: #0000FF;">{</span><span style="color: #008000;">"%2A"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"*"</span><span style="color: #0000FF;">},</span>
--integer refresh_cache = timedelta(days:=1) -- 0 for always
<span style="color: #0000FF;">{</span><span style="color: #008000;">"%2B"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"+"</span><span style="color: #0000FF;">},</span>
 
<span style="color: #0000FF;">{</span><span style="color: #008000;">"%3A"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">":"</span><span style="color: #0000FF;">},</span>
include builtins\libcurl.e
<span style="color: #0000FF;">{</span><span style="color: #008000;">"%5E"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`^`</span><span style="color: #0000FF;">},</span>
atom curl = NULL
<span style="color: #0000FF;">{</span><span style="color: #008000;">"%E2%80%93"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"-"</span><span style="color: #0000FF;">},</span>
atom pErrorBuffer
<span style="color: #0000FF;">{</span><span style="color: #008000;">"%E2%80%99"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"'"</span><span style="color: #0000FF;">},</span>
 
<span style="color: #0000FF;">{</span><span style="color: #008000;">"%C3%A8"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"e"</span><span style="color: #0000FF;">},</span>
function write_callback(atom pData, integer size, integer nmemb, integer fn)
<span style="color: #0000FF;">{</span><span style="color: #008000;">"%C3%A9"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"e"</span><span style="color: #0000FF;">},</span>
integer bytes_written = size * nmemb
<span style="color: #0000FF;">{</span><span style="color: #008000;">"%C3%B6"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"o"</span><span style="color: #0000FF;">},</span>
puts(fn,peek({pData,bytes_written}))
<span style="color: #0000FF;">{</span><span style="color: #008000;">"%C5%91"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"o"</span><span style="color: #0000FF;">},</span>
return bytes_written
<span style="color: #0000FF;">{</span><span style="color: #008000;">"&quot;"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`"`</span><span style="color: #0000FF;">},</span>
end function
<span style="color: #0000FF;">{</span><span style="color: #008000;">"&#039;"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"'"</span><span style="color: #0000FF;">},</span>
constant write_cb = call_back({'+', routine_id("write_callback")})
<span style="color: #0000FF;">{</span><span style="color: #008000;">"_"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">}})</span>
 
function open_download(string filename, url)
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">html_clean</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
bool refetch = true
<span style="color: #008080;">return</span> <span style="color: #7060A8;">substitute_all</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hex</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ascii</span><span style="color: #0000FF;">)</span>
if get_file_type("rc_cache")!=FILETYPE_DIRECTORY then
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
if not create_directory("rc_cache") then
crash("cannot create rc_cache directory")
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">libcurl</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
end if
<span style="color: #004080;">atom</span> <span style="color: #000000;">curl</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pErrorBuffer</span>
end if
filename = join_path({"rc_cache",filename})
<span style="color: #008080;">function</span> <span style="color: #000000;">write_callback</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">pData</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">size</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nmemb</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
if file_exists(filename) then
<span style="color: #004080;">integer</span> <span style="color: #000000;">bytes_written</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">size</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">nmemb</span>
-- use existing file if <= refresh_cache (365 days) old
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">peek</span><span style="color: #0000FF;">({</span><span style="color: #000000;">pData</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bytes_written</span><span style="color: #0000FF;">}))</span>
sequence last_mod = get_file_date(filename) -- (0.8.1+)
<span style="color: #008080;">return</span> <span style="color: #000000;">bytes_written</span>
atom delta = timedate_diff(last_mod,date())
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
refetch = (delta>refresh_cache) or get_file_size(filename)=0
<span style="color: #008080;">constant</span> <span style="color: #000000;">write_cb</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">call_back</span><span style="color: #0000FF;">({</span><span style="color: #008000;">'+'</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">write_callback</span><span style="color: #0000FF;">})</span>
else
string directory = get_file_path(filename)
<span style="color: #008080;">global</span> <span style="color: #004080;">string</span> <span style="color: #000000;">wastitle</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> <span style="color: #000080;font-style:italic;">-- don't clobber "NEED EDITING"/Downloading messages</span>
if get_file_type(directory)!=FILETYPE_DIRECTORY then
<span style="color: #008080;">global</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">show_title</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">progress</span>
if not create_directory(directory,make_parent:=true) then
crash("cannot create %s directory",{directory})
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">open_download</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">url</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #004080;">object</span> <span style="color: #000000;">text</span>
end if
<span style="color: #004080;">bool</span> <span style="color: #000000;">refetch</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
end if
<span style="color: #004080;">string</span> <span style="color: #000000;">why</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"not found"</span>
object text
<span style="color: #000000;">filename</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">join_path</span><span style="color: #0000FF;">({</span><span style="color: #008000;">"rc_cache"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">})</span>
if not refetch then
<span style="color: #008080;">if</span> <span style="color: #7060A8;">file_exists</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
text = trim(get_text(filename))
<span style="color: #000080;font-style:italic;">-- use existing file if &lt;= refresh_cache days old</span>
refetch = (not sequence(text)) or (length(text)<10)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">last_mod</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_file_date</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #004080;">atom</span> <span style="color: #000000;">delta</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">timedate_diff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">last_mod</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">date</span><span style="color: #0000FF;">())</span>
if refetch then
<span style="color: #000000;">refetch</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
progress("Downloading %s...\r",{filename})
<span style="color: #008080;">if</span> <span style="color: #000000;">delta</span><span style="color: #0000FF;">></span><span style="color: #000000;">refresh_cache</span>
if curl=NULL then
<span style="color: #008080;">and</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #008000;">".hist"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
curl_global_init()
<span style="color: #000000;">why</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">days</span><span style="color: #0000FF;">(</span><span style="color: #000000;">delta</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">" &gt; "</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">days</span><span style="color: #0000FF;">(</span><span style="color: #000000;">refresh_cache</span><span style="color: #0000FF;">)</span>
curl = curl_easy_init()
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">get_file_size</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
pErrorBuffer = allocate(CURL_ERROR_SIZE)
<span style="color: #000000;">why</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"filesize of 0"</span>
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, pErrorBuffer)
<span style="color: #008080;">else</span>
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb)
<span style="color: #000000;">text</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">get_text</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">))</span>
end if
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
url = substitute(url,"%3A",":")
<span style="color: #000000;">why</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"no text"</span>
url = substitute(url,"%2A","*")
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">text</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">10</span> <span style="color: #008080;">then</span>
curl_easy_setopt(curl, CURLOPT_URL, url)
<span style="color: #000000;">why</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"&lt;10 bytes"</span>
integer fn = open(filename,"wb")
<span style="color: #008080;">else</span>
if fn=-1 then ?9/0 end if
<span style="color: #000000;">refetch</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fn)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
while true do
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
CURLcode res = curl_easy_perform(curl)
<span style="color: #008080;">else</span>
if res=CURLE_OK then exit end if
<span style="color: #000000;">refetch</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
string error = sprintf("%d",res)
<span style="color: #004080;">string</span> <span style="color: #000000;">directory</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_file_path</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span>
if res=CURLE_COULDNT_RESOLVE_HOST then
<span style="color: #008080;">if</span> <span style="color: #7060A8;">get_file_type</span><span style="color: #0000FF;">(</span><span style="color: #000000;">directory</span><span style="color: #0000FF;">)!=</span><span style="color: #004600;">FILETYPE_DIRECTORY</span> <span style="color: #008080;">then</span>
error &= " [CURLE_COULDNT_RESOLVE_HOST]"
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">create_directory</span><span style="color: #0000FF;">(</span><span style="color: #000000;">directory</span><span style="color: #0000FF;">,</span><span style="color: #000000;">make_parent</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
end if
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"cannot create %s directory"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">directory</span><span style="color: #0000FF;">})</span>
progress("Error %s downloading file, retry?(Y/N):",{error})
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if lower(wait_key())!='y' then abort(0) end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
printf(1,"Y\n")
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end while
<span style="color: #008080;">if</span> <span style="color: #000000;">refetch</span> <span style="color: #008080;">then</span>
close(fn)
<span style="color: #000000;">wastitle</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"x"</span> <span style="color: #000080;font-style:italic;">-- don't clobber</span>
refresh_cache += timedelta(days:=1) -- did I mention it is slow?
<span style="color: #004080;">string</span> <span style="color: #000000;">nofn</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">?</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"(%d/%d, %.1f%%) "</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">/</span><span style="color: #000000;">n</span><span style="color: #0000FF;">*</span><span style="color: #000000;">100</span><span style="color: #0000FF;">}):</span><span style="color: #008000;">""</span><span style="color: #0000FF;">),</span>
text = get_text(filename)
<span style="color: #000000;">title</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Downloading %s%s (%s)..."</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">nofn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">html_clean</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">),</span><span style="color: #000000;">why</span><span style="color: #0000FF;">})</span>
end if
<span style="color: #000000;">show_title</span><span style="color: #0000FF;">(</span><span style="color: #000000;">title</span><span style="color: #0000FF;">)</span>
return text
<span style="color: #008080;">if</span> <span style="color: #000000;">curl</span><span style="color: #0000FF;">=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span>
end function
<span style="color: #7060A8;">curl_global_init</span><span style="color: #0000FF;">()</span>
 
<span style="color: #000000;">curl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">curl_easy_init</span><span style="color: #0000FF;">()</span>
function open_category(string filename)
<span style="color: #000000;">pErrorBuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">CURL_ERROR_SIZE</span><span style="color: #0000FF;">)</span>
return open_download(filename&".htm","http://rosettacode.org/wiki/Category:"&filename)
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">CURLOPT_ERRORBUFFER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pErrorBuffer</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CURLOPT_WRITEFUNCTION</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">write_cb</span><span style="color: #0000FF;">)</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
function dewiki(string s)
<span style="color: #000000;">url</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">url</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%3A"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">":"</span><span style="color: #0000FF;">)</span>
-- extract tasks from eg `<li><a href="/wiki/100_doors"`
<span style="color: #000000;">url</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">url</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%2A"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"*"</span><span style="color: #0000FF;">)</span>
sequence tasks = {}
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CURLOPT_URL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">url</span><span style="color: #0000FF;">)</span>
integer start = 1, finish = match(`<div class="printfooter">`,s)
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"wb"</span><span style="color: #0000FF;">)</span>
s = s[1..finish-1]
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"cannot open "</span><span style="color: #0000FF;">&</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span>
while true do
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">CURLOPT_WRITEDATA</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
start = match("<li><a href=\"/wiki/",s,start)
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
if start=0 then exit end if
<span style="color: #004080;">CURLcode</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curl_easy_perform</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">)</span>
start += length("<li><a href=\"/wiki/")
<span style="color: #008080;">if</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">=</span><span style="color: #004600;">CURLE_OK</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
finish = find('"',s,start)
<span style="color: #004080;">string</span> <span style="color: #000000;">error</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
string task = s[start..finish-1]
<span style="color: #008080;">if</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">=</span><span style="color: #000000;">CURLE_COULDNT_RESOLVE_HOST</span> <span style="color: #008080;">then</span>
task = substitute_all(task,{"*",":"},{"%2A","%3A"})
<span style="color: #000000;">error</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">" [CURLE_COULDNT_RESOLVE_HOST]"</span>
tasks = append(tasks,task)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
start = finish+1
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Error %s downloading file, retry?(Y/N):"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">error</span><span style="color: #0000FF;">})</span>
end while
<span style="color: #008080;">if</span> <span style="color: #7060A8;">lower</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">())!=</span><span style="color: #008000;">'y'</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">abort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return tasks
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Y\n"</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
 
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
constant {hex,ascii} = columnize({{"%2A","*"},
<span style="color: #000000;">refresh_cache</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">timedelta</span><span style="color: #0000FF;">(</span><span style="color: #000000;">days</span><span style="color: #0000FF;">:=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- did I mention it is slow?</span>
{"%3A",":"},
<span style="color: #000000;">text</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_text</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span>
{"%27","'"},
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
{"%2B","+"},
<span style="color: #008080;">return</span> <span style="color: #000000;">text</span>
{"%22","\""},
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
{"%E2%80%93","-"},
{"%E2%80%99","'"},
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">open_category</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
{"%C3%A8","e"},
<span style="color: #008080;">return</span> <span style="color: #000000;">open_download</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">&</span><span style="color: #008000;">".htm"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"http://rosettacode.org/wiki/Category:"</span><span style="color: #0000FF;">&</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
{"%C3%A9","e"}})
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
 
function html_clean(string s)
<span style="color: #008080;">global</span> <span style="color: #008080;">function</span> <span style="color: #000000;">dewiki</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">exclude</span><span style="color: #0000FF;">={})</span>
return substitute_all(s,hex,ascii)
<span style="color: #000080;font-style:italic;">-- extract tasks from eg `&lt;li&gt;&lt;a href="/wiki/100_doors"`</span>
end function
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tasks</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
 
<span style="color: #004080;">integer</span> <span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">finish</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`&lt;div class="printfooter"&gt;`</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
function count_tasks()
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">finish</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
-- note this lot use web scraping (as cribbed from a similar task) ...
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
sequence tasks = dewiki(open_category("Programming_Tasks"))
<span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`&lt;li&gt;&lt;a href="/wiki/`</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">start</span><span style="color: #0000FF;">)</span>
if include_drafts then
<span style="color: #008080;">if</span> <span style="color: #000000;">start</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
tasks &= dewiki(open_category("Draft_Programming_Tasks"))
<span style="color: #000000;">start</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`&lt;li&gt;&lt;a href="/wiki/`</span><span style="color: #0000FF;">)</span>
tasks = sort(tasks)
<span style="color: #000000;">finish</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'"'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">start</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #004080;">string</span> <span style="color: #000000;">task</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">start</span><span style="color: #0000FF;">..</span><span style="color: #000000;">finish</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
if length(notlang) then
<span style="color: #000000;">task</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute_all</span><span style="color: #0000FF;">(</span><span style="color: #000000;">task</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"*"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">":"</span><span style="color: #0000FF;">},{</span><span style="color: #008000;">"%2A"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%3A"</span><span style="color: #0000FF;">})</span>
-- filter already done in specified language
<span style="color: #000000;">tasks</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tasks</span><span style="color: #0000FF;">,</span><span style="color: #000000;">task</span><span style="color: #0000FF;">)</span>
string langurl = "http://rosettacode.org/wiki/Category:"&notlang
<span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">finish</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span>
sequence done = dewiki(open_download(notlang&".htm",langurl))
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
integer k = 0
<span style="color: #008080;">return</span> <span style="color: #000000;">tasks</span>
for i=1 to length(tasks) do
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
if not find(tasks[i],done) then
k += 1
<span style="color: #008080;">global</span> <span style="color: #008080;">procedure</span> <span style="color: #000000;">curl_cleanup</span><span style="color: #0000FF;">()</span>
tasks[k] = tasks[i]
<span style="color: #008080;">if</span> <span style="color: #000000;">curl</span><span style="color: #0000FF;">!=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span>
end if
<span style="color: #7060A8;">curl_easy_cleanup</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">)</span>
end for
<span style="color: #7060A8;">free</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pErrorBuffer</span><span style="color: #0000FF;">)</span>
tasks = tasks[1..k]
<span style="color: #000000;">curl</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">NULL</span>
done = {}
<span style="color: #000000;">pErrorBuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">NULL</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
progress("%d tasks found\n",{length(tasks)})
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
-- ... whereas the individual tasks use the web api instead (3x smaller/faster)
<!--</syntaxhighlight>-->
integer total_count = 0
The task itself:
sequence task_counts = repeat(0,length(tasks))
<!--<syntaxhighlight lang="phix">(notonline)-->
for i=1 to length(tasks) do
<span style="color: #000080;font-style:italic;">--
string ti = tasks[i],
-- demo\rosetta\Count_examples.exw
url = sprintf("http://rosettacode.org/mw/index.php?title=%s&action=raw",{ti}),
-- ===============================
contents = open_download(ti&".raw",url),
--
prev = "", this
-- (This uses a few '&' instead of/as well as 'a', fairly obviously for everyone's sanity..)
integer count = 0, start = 1
-- Counts no of "<nowiki>{{</nowiki>he&der|" (nb not "==<nowiki>{{</nowiki>he&der|") via web api (but gets tasks via scraping).
while true do
-- Since downloading all the pages can be very slow, this uses a cache.
start = match(`{{header|`,contents,start)
-- Limiting (notdone) by "Phix" fairly obviously speeds it up tenfold :-)
if start=0 then exit end if
--</span>
--
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (fairly obviously this will never ever run in a browser!)</span>
-- skip duplicates/we also have to cope with eg
<span style="color: #008080;">constant</span> <span style="color: #000000;">include_drafts</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span><span style="color: #0000FF;">,</span>
-- =={{header|Python}}== \
<span style="color: #000000;">sort_by_count</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">,</span>
-- ==={{header|Python}} Original=== } count
<span style="color: #000080;font-style:italic;">-- notlang = "Phix" -- or "" (ie a zero length string) for all</span>
-- ==={{header|Python}} Succinct=== } once
<span style="color: #000000;">notlang</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
-- ==={{header|Python}} Recursive === /
-- =={{header|Mathematica}} / {{header|Wolfram Language}}== \
<span style="color: #008080;">include</span> <span style="color: #000000;">rosettacode_cache</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
-- =={{header|Icon}} and {{header|Unicon}}== } count
-- == {{header|Icon}} and {{header|Unicon}} == / both
<span style="color: #008080;">function</span> <span style="color: #000000;">count_tasks</span><span style="color: #0000FF;">()</span>
-- == {{header|Java}}==
<span style="color: #008080;">if</span> <span style="color: #7060A8;">get_file_type</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"rc_cache"</span><span style="color: #0000FF;">)!=</span><span style="color: #004600;">FILETYPE_DIRECTORY</span> <span style="color: #008080;">then</span>
-- etc. Note however that this /does/ count eg
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">create_directory</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"rc_cache"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
-- ==={{header|Applesoft BASIC}}=== \
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"cannot create rc_cache directory"</span><span style="color: #0000FF;">)</span>
-- ==={{header|BASIC256}}=== } count
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
-- ==={{header|Commodore BASIC}}=== } 'em
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
-- ==={{header|IS-BASIC}}=== } all
<span style="color: #000080;font-style:italic;">-- note this lot use web scraping (as cribbed from a similar task) ...</span>
-- ==={{header|Sinclair ZX81 BASIC}}=== /
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tasks</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dewiki</span><span style="color: #0000FF;">(</span><span style="color: #000000;">open_category</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Programming_Tasks"</span><span style="color: #0000FF;">))</span>
--
<span style="color: #008080;">if</span> <span style="color: #000000;">include_drafts</span> <span style="color: #008080;">then</span>
this = contents[start..match(`}}`,contents,start+1)]
<span style="color: #000000;">tasks</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">dewiki</span><span style="color: #0000FF;">(</span><span style="color: #000000;">open_category</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Draft_Programming_Tasks"</span><span style="color: #0000FF;">))</span>
if this!=prev then
<span style="color: #000000;">tasks</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tasks</span><span style="color: #0000FF;">)</span>
count += 1
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">notlang</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
prev = this
<span style="color: #000080;font-style:italic;">-- filter already done in specified language</span>
start += length(`{{header|`)
<span style="color: #004080;">string</span> <span style="color: #000000;">langurl</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"http://rosettacode.org/wiki/Category:"</span><span style="color: #0000FF;">&</span><span style="color: #000000;">notlang</span>
end while
<span style="color: #004080;">sequence</span> <span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dewiki</span><span style="color: #0000FF;">(</span><span style="color: #000000;">open_download</span><span style="color: #0000FF;">(</span><span style="color: #000000;">notlang</span><span style="color: #0000FF;">&</span><span style="color: #008000;">".htm"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">langurl</span><span style="color: #0000FF;">))</span>
if sort_by_count then
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
task_counts[i] = count
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tasks</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
elsif length(notlang) or i<=2 or i>=length(tasks)-1 or mod(i,200)=0 then
<span style="color: #004080;">string</span> <span style="color: #000000;">ti</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tasks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
progress("%s %d\n",{html_clean(ti),count})
<span style="color: #004080;">integer</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">,</span><span style="color: #000000;">done</span><span style="color: #0000FF;">)</span>
end if
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">d</span> <span style="color: #008080;">then</span>
total_count += count
<span style="color: #000000;">k</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
if get_key()=#1B then progress("escape keyed\n") exit end if
<span style="color: #000000;">tasks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ti</span>
end for
<span style="color: #008080;">else</span>
if curl!=NULL then
<span style="color: #000000;">done</span><span style="color: #0000FF;">[</span><span style="color: #000000;">d</span><span style="color: #0000FF;">..</span><span style="color: #000000;">d</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
curl_easy_cleanup(curl)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
free(pErrorBuffer)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
curl = NULL
<span style="color: #000000;">tasks</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tasks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
pErrorBuffer = NULL
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if sort_by_count then
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d tasks found\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tasks</span><span style="color: #0000FF;">)})</span>
sequence tags = custom_sort(task_counts,tagset(length(tasks)))
<span style="color: #000080;font-style:italic;">-- ... whereas the individual tasks use the web api instead (3x smaller/faster)</span>
for i=length(tags) to 1 by -1 do
<span style="color: #004080;">integer</span> <span style="color: #000000;">total_count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
integer ti = tags[i]
<span style="color: #004080;">sequence</span> <span style="color: #000000;">task_counts</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tasks</span><span style="color: #0000FF;">))</span>
progress("%s %d\n",{html_clean(tasks[ti]),task_counts[ti]})
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tasks</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end for
<span style="color: #004080;">string</span> <span style="color: #000000;">ti</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tasks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span>
end if
<span style="color: #000000;">url</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"http://rosettacode.org/mw/index.php?title=%s&action=raw"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">}),</span>
return total_count
<span style="color: #000000;">contents</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">open_download</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">&</span><span style="color: #008000;">".raw"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">url</span><span style="color: #0000FF;">),</span>
end function
<span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">curr</span>
 
<span style="color: #004080;">integer</span> <span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
progress("Total: %d\n",{count_tasks()})</lang>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
{{out}} (as of 24/7/19, showing first two, every 200th, and last two)
<span style="color: #000000;">start</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`<nowiki>{{</nowiki>hea`</span><span style="color: #0000FF;">&</span><span style="color: #008000;">`der|`</span><span style="color: #0000FF;">,</span><span style="color: #000000;">contents</span><span style="color: #0000FF;">,</span><span style="color: #000000;">start</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">start</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000080;font-style:italic;">--
-- skip duplicates/we also have to cope with eg
-- ==<nowiki>{{</nowiki>he&der|Python<nowiki>}}</nowiki>== \
-- ===<nowiki>{{</nowiki>he&der|Python<nowiki>}}</nowiki> Original=== } count
-- ===<nowiki>{{</nowiki>he&der|Python<nowiki>}}</nowiki> Succinct=== } once
-- ===<nowiki>{{</nowiki>he&der|Python<nowiki>}}</nowiki> Recursive === /
-- ==<nowiki>{{</nowiki>he&der|Mathematica<nowiki>}}</nowiki> / <nowiki>{{</nowiki>he&der|Wolfram Language<nowiki>}}</nowiki>== \
-- ==<nowiki>{{</nowiki>he&der|Icon<nowiki>}}</nowiki> and <nowiki>{{</nowiki>he&der|Unicon<nowiki>}}</nowiki>== } count
-- == <nowiki>{{</nowiki>he&der|Icon<nowiki>}}</nowiki> and <nowiki>{{</nowiki>he&der|Unicon<nowiki>}}</nowiki> == / both
-- == <nowiki>{{</nowiki>he&der|Java<nowiki>}}</nowiki>==
-- etc. Note however that this /does/ count eg
-- ===<nowiki>{{</nowiki>he&der|Applesoft BASIC<nowiki>}}</nowiki>=== \
-- ===<nowiki>{{</nowiki>he&der|BASIC256<nowiki>}}</nowiki>=== } count
-- ===<nowiki>{{</nowiki>he&der|Commodore BASIC<nowiki>}}</nowiki>=== } 'em
-- ===<nowiki>{{</nowiki>he&der|IS-BASIC<nowiki>}}</nowiki>=== } all
-- ===<nowiki>{{</nowiki>he&der|Sinclair ZX81 BASIC<nowiki>}}</nowiki>=== /
--</span>
<span style="color: #000000;">curr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">contents</span><span style="color: #0000FF;">[</span><span style="color: #000000;">start</span><span style="color: #0000FF;">..</span><span style="color: #7060A8;">match</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`<nowiki>}}</nowiki>`</span><span style="color: #0000FF;">,</span><span style="color: #000000;">contents</span><span style="color: #0000FF;">,</span><span style="color: #000000;">start</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">prev</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curr</span>
<span style="color: #000000;">start</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`<nowiki>{{</nowiki>hea`</span><span style="color: #0000FF;">&</span><span style="color: #008000;">`der|`</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">sort_by_count</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">task_counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">count</span>
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">notlang</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #000000;">i</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">2</span> <span style="color: #008080;">or</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">>=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tasks</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">200</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%s: %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">html_clean</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">),</span><span style="color: #000000;">count</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">total_count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">count</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">get_key</span><span style="color: #0000FF;">()=</span><span style="color: #000000;">#1B</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"escape keyed\n"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">curl_cleanup</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">sort_by_count</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tags</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">custom_sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">task_counts</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tasks</span><span style="color: #0000FF;">)))</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tags</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ti</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%s: %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">html_clean</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tasks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">]),</span><span style="color: #000000;">task_counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">]})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">total_count</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Total: %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">count_tasks</span><span style="color: #0000FF;">()})</span>
<!--</syntaxhighlight>-->
{{out}} (as of 30/2/22, showing first two, every 200th, and last two)
<pre>
11751523 tasks found
10001th prime: 33
100_doors 294
100 doors: 337
15_Puzzle_Game 55
Chowla numbers: 46
Compiler/virtual_machine_interpreter 14
Exactly three adjacent 3 in lists: 27
General_FizzBuzz 51
Imaginary base numbers: 21
Maximum_triangle_path_sum 46
Monte Carlo methods: 87
Random_number_generator_(included) 89
Prime numbers which contain 123: 23
String_concatenation 155
Smallest number k such that k+2^m is composite for all m less than k: 5
Zhang-Suen_thinning_algorithm 29
Trabb Pardo-Knuth algorithm: 83
Zig-zag_matrix 99
Zig-zag matrix: 113
Total: 64405
Zumkeller numbers: 36
Total: 88455
</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/http.l")
 
(client "rosettacode.org" 80
Line 2,101 ⟶ 2,153:
(unless (sub? "." (till "<" T))
(inc 'Cnt) ) )
(out NIL (prinl (ht:Pack Task) ": " Cnt)) ) ) ) ) )</langsyntaxhighlight>
Output (05may10):
<pre>100 doors: 79
Line 2,112 ⟶ 2,164:
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">Procedure handleError(value, msg.s)
If value = 0
MessageRequester("Error", msg)
Line 2,175 ⟶ 2,227:
Input()
CloseConsole()
EndIf</langsyntaxhighlight>
Sample output:
<pre>100 doors: 224 examples
Line 2,193 ⟶ 2,245:
=={{header|Python}}==
 
<langsyntaxhighlight lang="python">from urllib.request import urlopen, Request
import xml.dom.minidom
 
Line 2,211 ⟶ 2,263:
 
print(f'\nTotal: {sum(tasks)} examples.')
</syntaxhighlight>
</lang>
 
===Using Semantic MediaWiki===
{{libheader|Requests}}
Here we use the [https://www.semantic-mediawiki.org/wiki/Help:API:ask ask] API provided by the [https://www.semantic-mediawiki.org/wiki/Semantic_MediaWiki Semantic MediaWiki extension] to query page [https://www.semantic-mediawiki.org/wiki/Help:Properties_and_types properties] rather than parse page content, producing subtly different counts to some other solutions. Maybe too different for this task.
 
We only count task examples that have a corresponding category page AND that page has the "Is Language" property set to True. In other words, <code>Implemented In</code> + <code>Not Implemented In</code> + <code>Omitted From</code> is always equal to the total number of languages.
 
<syntaxhighlight lang="python">"""Count Rosetta Code tasks implementations using the Semantic MediaWiki API.
Works with Python >= 3.7."""
import json
import logging
 
from dataclasses import dataclass
from dataclasses import field
 
from datetime import datetime
 
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from typing import Set
from typing import Tuple
 
import requests
from requests.adapters import HTTPAdapter
from requests.adapters import Retry
 
logging.basicConfig(level=logging.WARN)
 
# See https://www.semantic-mediawiki.org/wiki/Help:API:ask
_SM_ASK: Dict[str, str] = {
"action": "ask",
"format": "json",
"formatversion": "2",
"api_version": "3",
}
 
_SM_ASK_REQUEST_BLOCK_SIZE = 500
 
 
@dataclass(frozen=True)
class Page:
# fulltext is the page's title, not the page content.
fulltext: str
fullurl: str
namespace: int
exists: str
displaytitle: str
 
 
@dataclass(frozen=True, eq=False)
class Lang(Page):
def __eq__(self, other: object) -> bool:
if isinstance(other, Lang):
return self.fullurl == other.fullurl
elif isinstance(other, str):
return self.fullurl == other
return False
 
def __hash__(self) -> int:
return hash(self.fullurl)
 
def unimplemented(self, tasks: Set["Task"]) -> Set["Task"]:
return {task for task in tasks if self.fullurl not in task.exclude}
 
def omitted_from(self, tasks: Set["Task"]) -> Set["Task"]:
return {task for task in tasks if self.fullurl in task.omitted_from}
 
 
@dataclass(frozen=True)
class Task(Page):
title: str
implemented_in: Set[Lang] = field(repr=False, compare=False)
omitted_from: Set[Lang] = field(repr=False, compare=False)
exclude: Set[Lang] = field(repr=False, compare=False)
 
def not_implemented_in(self, langs: Set[Lang]) -> Set[Lang]:
return langs.difference(self.exclude)
 
 
@dataclass
class TaskResponseBlock:
tasks: List[Task]
continue_offset: Optional[int] = None
 
 
@dataclass
class LanguageResponseBlock:
langs: List[Lang]
continue_offset: Optional[int] = None
 
 
def sm_ask_category(
session: requests.Session,
url: str,
category: str,
limit: int,
offset: int,
known_langs: Set[Lang],
) -> TaskResponseBlock:
query_params = {
**_SM_ASK,
"query": (
f"[[Category:{category}]]"
"|?Implemented in language"
"|?Omitted from language"
f"|limit={limit}"
f"|offset={offset}"
),
}
 
# Display some progress
log(f"ask [[Category:{category}]] offset={offset}")
 
response = session.get(url, params=query_params)
response.raise_for_status()
data = response.json()
handle_warnings_and_errors(data)
return _transform_implemented_in_response_data(data, known_langs)
 
 
def sm_ask_tasks(
session: requests.Session,
url: str,
limit: int,
offset: int,
known_langs: Set[Lang],
):
return sm_ask_category(
session, url, "Programming Tasks", limit, offset, known_langs
)
 
 
def sm_ask_drafts(
session: requests.Session,
url: str,
limit: int,
offset: int,
known_langs: Set[Lang],
):
return sm_ask_category(
session, url, "Draft Programming Tasks", limit, offset, known_langs
)
 
 
def sm_ask_languages(
session: requests.Session,
url: str,
limit: int,
offset: int,
) -> LanguageResponseBlock:
query_params = {
**_SM_ASK,
"query": (
"[[Is language::+]]"
"|?Implemented in language"
"|?Omitted from language"
f"|limit={limit}"
f"|offset={offset}"
),
}
 
# Display some progress
log(f"ask [[Is language::+]] offset={offset}")
 
response = session.get(url, params=query_params)
response.raise_for_status()
data = response.json()
handle_warnings_and_errors(data)
return _transform_language_response_data(data)
 
 
def sm_ask_all_tasks(
session: requests.Session, url: str, known_langs: Set[Lang]
) -> List[Task]:
block = sm_ask_tasks(
session,
url,
limit=_SM_ASK_REQUEST_BLOCK_SIZE,
offset=0,
known_langs=known_langs,
)
tasks = block.tasks
 
while block.continue_offset:
block = sm_ask_tasks(
session,
url,
limit=_SM_ASK_REQUEST_BLOCK_SIZE,
offset=block.continue_offset,
known_langs=known_langs,
)
tasks.extend(block.tasks)
 
return tasks
 
 
def sm_ask_all_drafts(
session: requests.Session, url: str, known_langs: Set[Lang]
) -> List[Task]:
block = sm_ask_drafts(
session,
url,
limit=_SM_ASK_REQUEST_BLOCK_SIZE,
offset=0,
known_langs=known_langs,
)
tasks = block.tasks
 
while block.continue_offset:
block = sm_ask_drafts(
session,
url,
limit=_SM_ASK_REQUEST_BLOCK_SIZE,
offset=block.continue_offset,
known_langs=known_langs,
)
tasks.extend(block.tasks)
 
return tasks
 
 
def sm_ask_all_languages(session: requests.Session, url: str) -> List[Lang]:
block = sm_ask_languages(
session,
url,
limit=_SM_ASK_REQUEST_BLOCK_SIZE,
offset=0,
)
langs = block.langs
 
while block.continue_offset:
block = sm_ask_languages(
session,
url,
limit=_SM_ASK_REQUEST_BLOCK_SIZE,
offset=block.continue_offset,
)
langs.extend(block.langs)
 
return langs
 
 
def _transform_implemented_in_response_data(
data: Any, known_langs: Set[Lang]
) -> TaskResponseBlock:
tasks: List[Task] = []
for result in data["query"]["results"]:
for task_title, task_page in result.items():
# We're excluding implementations that don't have a corresponding
# category page with an "Is Language" property.
implemented_in = {
Lang(**lang)
for lang in task_page["printouts"]["Implemented in language"]
}.intersection(known_langs)
 
omitted_from = (
{
Lang(**lang)
for lang in task_page["printouts"]["Omitted from language"]
}
.intersection(known_langs)
.difference(implemented_in)
)
 
tasks.append(
Task(
title=task_title,
implemented_in=implemented_in,
omitted_from=omitted_from,
fulltext=task_page["fulltext"],
fullurl=task_page["fullurl"],
namespace=task_page["namespace"],
exists=task_page["exists"],
displaytitle=task_page["displaytitle"],
exclude=implemented_in.union(omitted_from),
)
)
 
return TaskResponseBlock(
tasks=tasks, continue_offset=data.get("query-continue-offset", None)
)
 
 
def _transform_language_response_data(data: Any) -> LanguageResponseBlock:
langs: List[Lang] = []
for result in data["query"]["results"]:
for _, task_page in result.items():
langs.append(
Lang(
fulltext=task_page["fulltext"],
fullurl=task_page["fullurl"],
namespace=task_page["namespace"],
exists=task_page["exists"],
displaytitle=task_page["displaytitle"],
)
)
 
return LanguageResponseBlock(
langs=langs, continue_offset=data.get("query-continue-offset", None)
)
 
 
def get_session() -> requests.Session:
"""Setup a requests.Session with retries."""
retry_strategy = Retry(
total=5,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["HEAD", "GET", "OPTIONS"],
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session = requests.Session()
session.mount("https://", adapter)
session.mount("http://", adapter)
return session
 
 
def log(msg: str) -> None:
print(f"{datetime.now().isoformat(' ', 'seconds')}: {msg}")
 
 
def handle_warnings_and_errors(data: Any) -> None:
if data.get("errors"):
for error in data["errors"]:
logging.error(json.dumps(error))
# legacy format
if data.get("error"):
logging.error(json.dumps(data["error"]))
if data.get("warnings"):
for warning in data["warnings"]:
logging.warning(json.dumps(warning))
 
 
def count_examples(url: str, n: int = 30) -> None:
"""Print a table to stdout containing implementation counts for the first
`n` tasks, sorted by number implementations (most to least)."""
session = get_session()
langs = set(sm_ask_all_languages(session, url))
tasks = sm_ask_all_tasks(session, url, langs)
drafts = sm_ask_all_drafts(session, url, langs)
all_tasks = [*tasks, *drafts]
 
# Map of task to (implemented in, not implemented in, omitted from)
counts: Dict[Task, Tuple[int, int, int]] = {}
 
# Running total of examples for all tasks. Where a language has multiple examples
# for a single tasks, we only count one example.
total: int = 0
 
for task in all_tasks:
total += len(task.implemented_in)
counts[task] = (
len(task.implemented_in),
len(task.not_implemented_in(langs)),
len(task.omitted_from),
)
 
# Pretty print
top = sorted(counts.items(), key=lambda it: it[1][0], reverse=True)[:n]
pad = max([len(task.fulltext) for task, _ in top])
 
print("\nKnown languages:", len(langs))
print("Total tasks:", len(all_tasks))
print("Total examples:", total)
print(f"{'Task':>{pad}} | Implemented In | Not Implemented In | Omitted From")
print("-" * (pad + 1), "+", "-" * 16, "+", "-" * 20, "+", "-" * 13, sep="")
 
for task, _counts in top:
implemented_in, not_implemented_in, omitted_from = _counts
print(
f"{task.fulltext:>{pad}} |"
f"{implemented_in:>15} |"
f"{not_implemented_in:>19} |"
f"{omitted_from:>13}"
)
 
 
if __name__ == "__main__":
import argparse
 
URL = "https://rosettacode.org/w/api.php"
parser = argparse.ArgumentParser(description="Count tasks on Rosetta Code.")
 
parser.add_argument(
"--rows",
"-n",
type=int,
default=30,
dest="n",
help="number of rows to display in the output table (default: 30)",
)
 
parser.add_argument(
"--url",
default=URL,
help=f"target MediaWiki URL (default: {URL})",
)
 
args = parser.parse_args()
count_examples(args.url, args.n)</syntaxhighlight>
 
{{out}}
<pre>
2023-02-11 11:09:34: ask [[Is language::+]] offset=0
2023-02-11 11:09:35: ask [[Is language::+]] offset=500
2023-02-11 11:09:36: ask [[Category:Programming Tasks]] offset=0
2023-02-11 11:09:47: ask [[Category:Programming Tasks]] offset=500
2023-02-11 11:10:04: ask [[Category:Programming Tasks]] offset=1000
2023-02-11 11:10:12: ask [[Category:Draft Programming Tasks]] offset=0
 
Known languages: 890
Total tasks: 1602
Total examples: 91075
Task | Implemented In | Not Implemented In | Omitted From
--------------------------------+----------------+--------------------+-------------
Hello world/Text | 498 | 392 | 0
99 bottles of beer | 371 | 519 | 0
100 doors | 334 | 555 | 1
FizzBuzz | 325 | 565 | 0
Fibonacci sequence | 308 | 582 | 0
Factorial | 302 | 588 | 0
Comments | 297 | 592 | 1
A+B | 293 | 597 | 0
Empty program | 274 | 616 | 0
Function definition | 254 | 634 | 2
Loops/Infinite | 254 | 635 | 1
Loops/For | 248 | 641 | 1
Loops/While | 244 | 645 | 1
Arrays | 237 | 652 | 1
Ackermann function | 234 | 653 | 3
Reverse a string | 231 | 657 | 2
Conditional structures | 223 | 666 | 1
Arithmetic/Integer | 213 | 677 | 0
Greatest common divisor | 213 | 677 | 0
Array concatenation | 208 | 682 | 0
Greatest element of a list | 208 | 682 | 0
Even or odd | 207 | 683 | 0
Loops/Downward for | 207 | 683 | 0
Sieve of Eratosthenes | 203 | 687 | 0
Increment a numerical string | 202 | 688 | 0
Integer comparison | 202 | 688 | 0
Repeat a string | 199 | 691 | 0
Boolean values | 198 | 691 | 1
Loops/For with a specified step | 198 | 691 | 1
Copy a string | 196 | 693 | 1
</pre>
 
=={{header|R}}==
Line 2,217 ⟶ 2,716:
 
{{libheader|RCurl}}
<syntaxhighlight lang="r">
<lang R>
library(XML)
library(RCurl)
Line 2,232 ⟶ 2,731:
}
cat("Total: ", length(unlist(counts)), "examples\n")
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
 
<langsyntaxhighlight lang="racket">
#lang racket
 
Line 2,262 ⟶ 2,761:
(printf "~a: ~a\n" task s)
s))
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
Line 2,278 ⟶ 2,777:
 
For a full output, see [[Rosetta_Code/Count_examples/Full_list|Top tier]], [[Rosetta_Code/Count_examples/Full_list/Tier_2|Second tier]], [[Rosetta_Code/Count_examples/Full_list/Tier_3|Third tier]], [[Rosetta_Code/Count_examples/Full_list/Tier_4|Fourth tier]]
<syntaxhighlight lang="raku" perl6line>use HTTP::UserAgent;
use URI::Escape;
use JSON::Fast;
Line 2,294 ⟶ 2,793:
$client.timeout = 10;
 
my $url = 'httphttps://rosettacode.org/mww';
 
my $hashfile = './RC_Task_count.json';
Line 2,452 ⟶ 2,951:
sub naturally ($a) { $a.lc.subst(/(\d+)/, ->$/ {0~(65+$0.chars).chr~$0},:g) }
 
sub clear { "\r" ~ ' ' x 116 ~ "\r" }</langsyntaxhighlight>
 
{{out|Abridged output}}
Line 2,516 ⟶ 3,015:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project: Rosetta Code/Count examples
 
Line 2,572 ⟶ 3,071:
end
return sum
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,603 ⟶ 3,102:
{{libheader|REXML}}
First, a RosettaCode module, saved as <tt>rosettacode.rb</tt>:
<langsyntaxhighlight lang="ruby">require 'open-uri'
require 'rexml/document'
 
Line 2,653 ⟶ 3,152:
end
 
end</langsyntaxhighlight>
 
Then, we implement the task with:
<langsyntaxhighlight lang="ruby">require 'rosettacode'
 
total_examples = 0
Line 2,668 ⟶ 3,167:
 
puts
puts "Total: #{total_examples}"</langsyntaxhighlight>
 
=={{header|Run BASIC}}==
<langsyntaxhighlight lang="runbasic">html "<table border=1><tr bgcolor=wheat align=center><td>Num</td><td>Task</td><td>Examples</td></tr>"
 
a$ = httpGet$("http://rosettacode.org/wiki/Category:Programming_Tasks")
Line 2,702 ⟶ 3,201:
wend
html "<tr bgcolor=wheat><td>**</td><td>** Total **</td><td align=right>";totExamp;"</td></tr></table>"
end</langsyntaxhighlight>
<table border=1><tr bgcolor=wheat align=center><td>Num</td><td>Task</td><td>Examples</td></tr>
<tr><td align=right>1</td><td>100 doors</td><td align=right>165</td></tr>
Line 2,726 ⟶ 3,225:
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">extern crate reqwest;
extern crate url;
extern crate rustc_serialize;
Line 2,837 ⟶ 3,336:
let json: Json = query_api(query).unwrap();
count_number_examples(&json, task.page_id).unwrap()
}</langsyntaxhighlight>
 
The function is then run using the following:
<langsyntaxhighlight lang="rust">
extern crate count_examples;
fn main() {
Line 2,848 ⟶ 3,347:
println!("Task: {} has {} examples", task.title, count);
}
}</langsyntaxhighlight>
 
=={{header|Scala}}==
{{libheader|Scala}}<langsyntaxhighlight Scalalang="scala">import scala.language.postfixOps
 
object TaskCount extends App {
Line 2,875 ⟶ 3,374:
counts map (_.apply) map Function.tupled("%s: %d examples." format (_, _)) foreach println
println("\nTotal: %d examples." format (counts map (_.apply._2) sum))
}</langsyntaxhighlight>
 
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby">var lwp = require('LWP::UserAgent').new(agent => 'Mozilla/5.0');
 
var site = 'http://rosettacode.org';
Line 2,891 ⟶ 3,390:
var count = lwp.get("#{site}/wiki/#{slug}").decoded_content.count(/toclevel-1/g);
say "#{m[0]}: #{count} examples";
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,909 ⟶ 3,408:
=={{header|Tcl}}==
{{tcllib|json}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
package require http
package require json
Line 2,973 ⟶ 3,472:
}
 
puts "\nTotal: $total examples"</langsyntaxhighlight>
 
=={{header|TUSCRIPT}}==
<langsyntaxhighlight lang="tuscript">$$ MODE TUSCRIPT
url="http://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml"
data=REQUEST (url)
Line 3,015 ⟶ 3,514:
 
FILE "tasks" = line
</syntaxhighlight>
</lang>
Output in file "tasks":
<pre style='height:30ex;overflow:scroll'>
Line 3,041 ⟶ 3,540:
Requires the <tt>curl</tt> and <tt>jq</tt> command-line utilities.
 
<langsyntaxhighlight lang="sh">#!/usr/bin/env bash
SITE=https://www.rosettacode.org
API=$SITE/mw/api.php
Line 3,060 ⟶ 3,559:
| jq -r '.query.categorymembers[].title')
 
printf '\nTotal: %d examples.\n' "$total"</langsyntaxhighlight>
 
=={{header|Wren}}==
{{libheader|libcurl}}
{{libheader|Wren-pattern}}
An embedded program so we can use the libcurl library.
<syntaxhighlight lang="wren">/* Rosetta_Code_Count_examples.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 url = "https://www.rosettacode.org/w/api.php?action=query&list=categorymembers&cmtitle=Category:Programming_Tasks&cmlimit=500&format=xml"
var content = getContent.call(url)
var p = Pattern.new("title/=\"[+1^\"]\"")
var matches = p.findAll(content)
for (m in matches) {
var title = m.capsText[0].replace("&#039;", "'").replace("&quot;", "\"")
var title2 = title.replace(" ", "_").replace("+", "\%252B")
var taskUrl = "https://www.rosettacode.org/w/index.php?title=%(title2)&action=raw"
var taskContent = getContent.call(taskUrl)
var lines = taskContent.split("\n")
var count = lines.count { |line| line.trim().startsWith("=={{header|") }
System.print("%(title) : %(count) examples")
}
 
curl.easyCleanup()</syntaxhighlight>
<br>
which we now embed in the following C program, build and run.
<syntaxhighlight lang="c">/* gcc Rosetta_Code_Count_examples.c -o Rosetta_Code_Count_examples -lcurl -lwren -lm */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include "wren.h"
 
struct MemoryStruct {
char *memory;
size_t size;
};
 
/* C <=> Wren interface functions */
 
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
char *ptr = realloc(mem->memory, mem->size + realsize + 1);
if(!ptr) {
/* out of memory! */
printf("not enough memory (realloc returned NULL)\n");
return 0;
}
 
mem->memory = ptr;
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
 
void C_bufferAllocate(WrenVM* vm) {
struct MemoryStruct *ms = (struct MemoryStruct *)wrenSetSlotNewForeign(vm, 0, 0, sizeof(struct MemoryStruct));
ms->memory = malloc(1);
ms->size = 0;
}
 
void C_bufferFinalize(void* data) {
struct MemoryStruct *ms = (struct MemoryStruct *)data;
free(ms->memory);
}
 
void C_curlAllocate(WrenVM* vm) {
CURL** pcurl = (CURL**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(CURL*));
*pcurl = curl_easy_init();
}
 
void C_value(WrenVM* vm) {
struct MemoryStruct *ms = (struct MemoryStruct *)wrenGetSlotForeign(vm, 0);
wrenSetSlotString(vm, 0, ms->memory);
}
 
void C_easyPerform(WrenVM* vm) {
CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
curl_easy_perform(curl);
}
 
void C_easyCleanup(WrenVM* vm) {
CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
curl_easy_cleanup(curl);
}
 
void C_easySetOpt(WrenVM* vm) {
CURL* curl = *(CURL**)wrenGetSlotForeign(vm, 0);
CURLoption opt = (CURLoption)wrenGetSlotDouble(vm, 1);
if (opt < 10000) {
long lparam = (long)wrenGetSlotDouble(vm, 2);
curl_easy_setopt(curl, opt, lparam);
} else if (opt < 20000) {
if (opt == CURLOPT_WRITEDATA) {
struct MemoryStruct *ms = (struct MemoryStruct *)wrenGetSlotForeign(vm, 2);
curl_easy_setopt(curl, opt, (void *)ms);
} else if (opt == CURLOPT_URL) {
const char *url = wrenGetSlotString(vm, 2);
curl_easy_setopt(curl, opt, url);
}
} else if (opt < 30000) {
if (opt == CURLOPT_WRITEFUNCTION) {
curl_easy_setopt(curl, opt, &WriteMemoryCallback);
}
}
}
 
WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {
WrenForeignClassMethods methods;
methods.allocate = NULL;
methods.finalize = NULL;
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Buffer") == 0) {
methods.allocate = C_bufferAllocate;
methods.finalize = C_bufferFinalize;
} else if (strcmp(className, "Curl") == 0) {
methods.allocate = C_curlAllocate;
}
}
return methods;
}
 
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Buffer") == 0) {
if (!isStatic && strcmp(signature, "value") == 0) return C_value;
} else if (strcmp(className, "Curl") == 0) {
if (!isStatic && strcmp(signature, "easySetOpt(_,_)") == 0) return C_easySetOpt;
if (!isStatic && strcmp(signature, "easyPerform()") == 0) return C_easyPerform;
if (!isStatic && strcmp(signature, "easyCleanup()") == 0) return C_easyCleanup;
}
}
return NULL;
}
 
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
 
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
 
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}
 
static void loadModuleComplete(WrenVM* vm, const char* module, WrenLoadModuleResult result) {
if( result.source) free((void*)result.source);
}
 
WrenLoadModuleResult loadModule(WrenVM* vm, const char* name) {
WrenLoadModuleResult result = {0};
if (strcmp(name, "random") != 0 && strcmp(name, "meta") != 0) {
result.onComplete = loadModuleComplete;
char fullName[strlen(name) + 6];
strcpy(fullName, name);
strcat(fullName, ".wren");
result.source = readFile(fullName);
}
return result;
}
 
int main(int argc, char **argv) {
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignClassFn = &bindForeignClass;
config.bindForeignMethodFn = &bindForeignMethod;
config.loadModuleFn = &loadModule;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "Rosetta_Code_Count_examples.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}</syntaxhighlight>
 
{{out}}
Just showing the first 25 'full' tasks:
<pre>
100 doors : 355 examples
100 prisoners : 85 examples
15 puzzle game : 86 examples
15 puzzle solver : 27 examples
2048 : 65 examples
21 game : 52 examples
24 game : 107 examples
24 game/Solve : 64 examples
4-rings or 4-squares puzzle : 74 examples
9 billion names of God the integer : 66 examples
99 bottles of beer : 376 examples
A+B : 296 examples
Abbreviations, automatic : 58 examples
Abbreviations, easy : 50 examples
Abbreviations, simple : 46 examples
ABC problem : 150 examples
Abelian sandpile model : 40 examples
Abelian sandpile model/Identity : 28 examples
Abstract type : 93 examples
Abundant odd numbers : 72 examples
Abundant, deficient and perfect number classifications : 110 examples
Accumulator factory : 115 examples
Achilles numbers : 25 examples
Ackermann function : 243 examples
Active Directory/Connect : 29 examples
....
</pre>
 
=={{header|zkl}}==
Uses shared libraries YAJL and cURL and handles "continue" responses.
<langsyntaxhighlight lang="zkl">var [const] YAJL=Import("zklYAJL")[0], CURL=Import("zklCurl");
 
fcn getTasks(language){
Line 3,091 ⟶ 3,871:
cnt,n:=0,0; while(re.search(page,True,n)){ cnt+=1; n=re.matched[0].sum(0); }
"%4d: %s".fmt(cnt,task).println();
}</langsyntaxhighlight>
{{out}}
<pre>
9,476

edits