Rosetta Code/Tasks without examples: Difference between revisions
Content added Content deleted
(Added Wren) |
|||
Line 970: | Line 970: | ||
End Function |
End Function |
||
</lang> |
</lang> |
||
=={{header|Wren}}== |
|||
{{libheader|libcurl}} |
|||
{{libheader|Wren-pattern}} |
|||
An embedded program so we can use the libcurl library. |
|||
<lang ecmascript>/* rc_tasks_without_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 unescs = [ |
|||
["_", " "], |
|||
["\%2B", "+"], |
|||
["\%27", "'"], |
|||
["\%C3\%A9", "é"], |
|||
["\%E2\%80\%93", "–"], |
|||
["\%22", "\""], |
|||
["\%C3\%B6", "ö"], |
|||
["\%E2\%80\%99", "’"], |
|||
["\%C3\%A8", "è"], |
|||
["\%C5\%91", "ő"], |
|||
] |
|||
var unescape = Fn.new { |text| |
|||
for (u in unescs) text = text.replace(u[0], u[1]) |
|||
return text |
|||
} |
|||
var url = "http://rosettacode.org/wiki/Category:Programming_Tasks" |
|||
var content = getContent.call(url) |
|||
var p1 = Pattern.new("<li><a href/=\"//wiki//[+1^\"]\"") |
|||
var p2 = Pattern.new("<~//+0^>>") |
|||
var matches = p1.findAll(content) |
|||
var tasks = matches.map { |m| m.capsText[0] }.toList |
|||
for (task in tasks.take(3)) { // just show the first 3 say |
|||
var taskUrl = "http://rosettacode.org/wiki/" + task |
|||
var html = getContent.call(taskUrl) |
|||
var text = "using any language you may know.</div>" |
|||
var start = html.indexOf(text) |
|||
var end = html.indexOf("<div id=\"toc\"") |
|||
html = html[start + text.count...end] |
|||
text = p2.replaceAll(html, "").replace(" ", "").trim() |
|||
var title = unescape.call(task) |
|||
System.print("\n****** %(title) ******\n") |
|||
System.print(text) |
|||
}</lang> |
|||
<br> |
|||
which we embed in the following C program, build and run. |
|||
<lang c>/* gcc rc_tasks_without_examples.c -o rc_tasks_without_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 = "rc_tasks_without_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; |
|||
}</lang> |
|||
{{out}} |
|||
Just showing the first 3 tasks. |
|||
<pre> |
|||
****** 100 doors ****** |
|||
There are 100 doors in a row that are all initially closed. |
|||
You make 100 passes by the doors. |
|||
The first time through, visit every door and toggle the door (if the door is closed, open it; if it is open, close it). |
|||
The second time, only visit every 2nd door (door #2, #4, #6, ...), and toggle it. |
|||
The third time, visit every 3rd door (door #3, #6, #9, ...), etc, until you only visit the 100th door. |
|||
Task |
|||
Answer the question: what state are the doors in after the last pass? Which are open, which are closed? |
|||
Alternate: |
|||
As noted in this page's discussion page, the only doors that remain open are those whose numbers are perfect squares. |
|||
Opening only those doors is an optimization that may also be expressed; |
|||
however, as should be obvious, this defeats the intent of comparing implementations across programming languages. |
|||
****** 100 prisoners ****** |
|||
The Problem |
|||
100 prisoners are individually numbered 1 to 100 |
|||
A room having a cupboard of 100 opaque drawers numbered 1 to 100, that cannot be seen from outside. |
|||
Cards numbered 1 to 100 are placed randomly, one to a drawer, and the drawers all closed; at the start. |
|||
Prisoners start outside the room |
|||
They can decide some strategy before any enter the room. |
|||
Prisoners enter the room one by one, can open a drawer, inspect the card number in the drawer, then close the drawer. |
|||
A prisoner can open no more than 50 drawers. |
|||
A prisoner tries to find his own number. |
|||
A prisoner finding his own number is then held apart from the others. |
|||
If all 100 prisoners find their own numbers then they will all be pardoned. If any don't then all sentences stand. |
|||
The task |
|||
Simulate several thousand instances of the game where the prisoners randomly open drawers |
|||
Simulate several thousand instances of the game where the prisoners use the optimal strategy mentioned in the Wikipedia article, of: |
|||
First opening the drawer whose outside number is his prisoner number. |
|||
If the card within has his number then he succeeds otherwise he opens the drawer with the same number as that of the revealed card. (until he opens his maximum). |
|||
Show and compare the computed probabilities of success for the two strategies, here, on this page. |
|||
References |
|||
The unbelievable solution to the 100 prisoner puzzle standupmaths (Video). |
|||
wp:100 prisoners problem |
|||
100 Prisoners Escape Puzzle DataGenetics. |
|||
Random permutation statistics#One hundred prisoners on Wikipedia. |
|||
****** 15 puzzle game ****** |
|||
Task |
|||
Implement the Fifteen Puzzle Game. |
|||
The 15-puzzle is also known as: |
|||
Fifteen Puzzle |
|||
Gem Puzzle |
|||
Boss Puzzle |
|||
Game of Fifteen |
|||
Mystic Square |
|||
14-15 Puzzle |
|||
and some others. |
|||
Related Tasks |
|||
15 Puzzle Solver |
|||
16 Puzzle Game |
|||
</pre> |
|||
=={{header|zkl}}== |
=={{header|zkl}}== |