Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Amb/00-META.yaml
Normal file
2
Task/Amb/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Amb
|
||||
47
Task/Amb/00-TASK.txt
Normal file
47
Task/Amb/00-TASK.txt
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
Define and give an example of the Amb operator.
|
||||
|
||||
The Amb operator (short for "ambiguous") expresses nondeterminism. This doesn't refer to randomness (as in "nondeterministic universe") but is closely related to the term as it is used in automata theory ("non-deterministic finite automaton").
|
||||
|
||||
The Amb operator takes a variable number of expressions (or values if that's simpler in the language) and yields a correct one which will satisfy a constraint in some future computation, thereby avoiding failure.
|
||||
|
||||
Problems whose solution the Amb operator naturally expresses can be approached with other tools, such as explicit nested iterations over data sets, or with pattern matching. By contrast, the Amb operator appears integrated into the language. Invocations of Amb are not wrapped in any visible loops or other search patterns; they appear to be independent.
|
||||
|
||||
Essentially Amb(x, y, z) splits the computation into three possible futures: a future in which the value x is yielded, a future in which the value y is yielded and a future in which the value z is yielded. The future which leads to a successful subsequent computation is chosen. The other "parallel universes" somehow go away. Amb called with no arguments fails.
|
||||
|
||||
For simplicity, one of the domain values usable with Amb may denote failure, if that is convenient. For instance, it is convenient if a Boolean false denotes failure, so that Amb(false) fails, and thus constraints can be expressed using Boolean expressions like Amb(x * y == 8) which unless x and y add to four.
|
||||
|
||||
A pseudo-code program which satisfies this constraint might look like:
|
||||
|
||||
<pre>let x = Amb(1, 2, 3)
|
||||
let y = Amb(7, 6, 4, 5)
|
||||
Amb(x * y = 8)
|
||||
print x, y</pre>
|
||||
|
||||
The output is <code>2 4</code> because <code>Amb(1, 2, 3)</code> correctly chooses the future in which <code>x</code> has value <code>2</code>, <code>Amb(7, 6, 4, 5)</code> chooses <code>4</code> and consequently <code>Amb(x * y = 8)</code> produces a success.
|
||||
|
||||
Alternatively, failure could be represented using strictly <code>Amb()</code>:
|
||||
|
||||
<pre>unless x * y = 8 do Amb()</pre>
|
||||
|
||||
Or else Amb could take the form of two operators or functions: one for producing values and one for enforcing constraints:
|
||||
|
||||
<pre>let x = Ambsel(1, 2, 3)
|
||||
let y = Ambsel(4, 5, 6)
|
||||
Ambassert(x * y = 8)
|
||||
print x, y</pre>
|
||||
|
||||
where <code>Ambassert</code> behaves like <code>Amb()</code> if the Boolean expression is false, otherwise it allows the future computation to take place, without yielding any value.
|
||||
|
||||
The task is to somehow implement Amb, and demonstrate it with a program which chooses one word from each of the following four sets of character strings to generate a four-word sentence:
|
||||
|
||||
#<code>"the" "that" "a"</code>
|
||||
#<code>"frog" "elephant" "thing"</code>
|
||||
#<code>"walked" "treaded" "grows"</code>
|
||||
#<code>"slowly" "quickly"</code>
|
||||
|
||||
The constraint to be satisfied is that the last character of each word (other than the last) is the same as the first character of its successor.
|
||||
|
||||
The only successful sentence is <code>"that thing grows slowly"</code>; other combinations do not satisfy the constraint and thus fail.
|
||||
|
||||
The goal of this task isn't to simply process the four lists of words with explicit, deterministic program flow such as nested iteration, to trivially demonstrate the correct output. The goal is to implement the Amb operator, or a facsimile thereof that is possible within the language limitations.
|
||||
|
||||
29
Task/Amb/11l/amb.11l
Normal file
29
Task/Amb/11l/amb.11l
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
F amb(comp, options, prev = ‘’) -> Array[String]
|
||||
I options.empty
|
||||
R []
|
||||
|
||||
L(opt) options[0]
|
||||
// If this is the base call, prev is empty and we need to continue.
|
||||
I prev != ‘’ & !comp(prev, opt)
|
||||
L.continue
|
||||
|
||||
// Take care of the case where we have no options left.
|
||||
I options.len == 1
|
||||
R [opt]
|
||||
|
||||
// Traverse into the tree.
|
||||
V res = amb(comp, options[1..], opt)
|
||||
|
||||
// If it was a failure, try the next one.
|
||||
if !res.empty
|
||||
R opt [+] res // We have a match
|
||||
|
||||
R []
|
||||
|
||||
V sets = [[‘the’, ‘that’, ‘a’],
|
||||
[‘frog’, ‘elephant’, ‘thing’],
|
||||
[‘walked’, ‘treaded’, ‘grows’],
|
||||
[‘slowly’, ‘quickly’]]
|
||||
|
||||
V result = amb((s, t) -> s.last == t[0], sets)
|
||||
print(result.join(‘ ’))
|
||||
38
Task/Amb/ALGOL-68/amb.alg
Normal file
38
Task/Amb/ALGOL-68/amb.alg
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
MODE PAGE = FLEX[0]STRING;
|
||||
MODE YIELDPAGE = PROC(PAGE)VOID;
|
||||
MODE ITERPAGE = PROC(YIELDPAGE)VOID;
|
||||
|
||||
OP INITITERPAGE = (PAGE self)ITERPAGE:
|
||||
(YIELDPAGE yield)VOID: # scope violation #
|
||||
FOR i TO UPB self DO
|
||||
yield(self[i])
|
||||
OD;
|
||||
|
||||
OP + = (ITERPAGE for strings, PAGE b)ITERPAGE:
|
||||
(YIELDPAGE yield)VOID: # scope violation #
|
||||
for strings((PAGE amb)VOID:(
|
||||
[UPB amb + 1]STRING joined;
|
||||
joined[:UPB amb] := amb;
|
||||
STRING last string := amb[UPB amb];
|
||||
CHAR last char := last string[UPB last string];
|
||||
FOR i TO UPB b DO
|
||||
IF last char = b[i][1] THEN
|
||||
joined[UPB joined] := b[i];
|
||||
yield(joined)
|
||||
FI
|
||||
OD
|
||||
));
|
||||
|
||||
OP + = (PAGE a, PAGE b)ITERPAGE: INITITERPAGE a + b;
|
||||
|
||||
ITERPAGE gen amb :=
|
||||
PAGE("the", "that", "a") +
|
||||
PAGE("frog", "elephant", "thing") +
|
||||
PAGE("walked", "treaded", "grows") +
|
||||
PAGE("slowly", "quickly");
|
||||
|
||||
PAGE sep;
|
||||
#FOR PAGE amb IN # gen amb( # ) DO #
|
||||
## (PAGE amb)VOID:
|
||||
print((amb[1]+" "+amb[2]+" "+amb[3]+" "+amb[4], new line))
|
||||
#OD# )
|
||||
124
Task/Amb/ATS/amb.ats
Normal file
124
Task/Amb/ATS/amb.ats
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
(* ****** ****** *)
|
||||
//
|
||||
#include
|
||||
"share/atspre_staload.hats"
|
||||
#include
|
||||
"share/HATS/atspre_staload_libats_ML.hats"
|
||||
//
|
||||
(* ****** ****** *)
|
||||
//
|
||||
staload "libats/ML/SATS/monad_list.sats"
|
||||
staload _ = "libats/ML/DATS/monad_list.dats"
|
||||
//
|
||||
(* ****** ****** *)
|
||||
//
|
||||
datatype
|
||||
words =
|
||||
| Sing of stringGt(0)
|
||||
| Comb of (words, words)
|
||||
//
|
||||
(* ****** ****** *)
|
||||
//
|
||||
extern
|
||||
fun words_get_beg(words): char
|
||||
extern
|
||||
fun words_get_end(words): char
|
||||
//
|
||||
(* ****** ****** *)
|
||||
//
|
||||
implement
|
||||
words_get_beg(w0) =
|
||||
(
|
||||
case+ w0 of
|
||||
| Sing(cs) => cs[0]
|
||||
| Comb(w1, w2) => words_get_beg(w1)
|
||||
)
|
||||
//
|
||||
implement
|
||||
words_get_end(w0) =
|
||||
(
|
||||
case+ w0 of
|
||||
| Sing(cs) => cs[pred(length(cs))]
|
||||
| Comb(w1, w2) => words_get_end(w2)
|
||||
)
|
||||
//
|
||||
(* ****** ****** *)
|
||||
//
|
||||
fun
|
||||
words_comb
|
||||
(
|
||||
w1: words, w2: words
|
||||
) : list0(words) =
|
||||
if (words_get_end(w1)=words_get_beg(w2))
|
||||
then list0_sing(Comb(w1, w2)) else list0_nil()
|
||||
//
|
||||
(* ****** ****** *)
|
||||
//
|
||||
extern
|
||||
fun
|
||||
fprint_words: fprint_type(words)
|
||||
//
|
||||
overload fprint with fprint_words
|
||||
//
|
||||
implement
|
||||
fprint_words(out, ws) =
|
||||
(
|
||||
case+ ws of
|
||||
| Sing(w) => fprint(out, w)
|
||||
| Comb(w1, w2) => fprint!(out, w1, ' ', w2)
|
||||
)
|
||||
//
|
||||
implement fprint_val<words> = fprint_words
|
||||
//
|
||||
(* ****** ****** *)
|
||||
//
|
||||
typedef
|
||||
a = stringGt(0) and b = words
|
||||
//
|
||||
val ws1 =
|
||||
$list{a}("this", "that", "a")
|
||||
val ws1 =
|
||||
list_map_fun<a><b>(ws1, lam(x) => Sing(x))
|
||||
val ws1 = monad_list_list(list0_of_list_vt(ws1))
|
||||
//
|
||||
val ws2 =
|
||||
$list{a}("frog", "elephant", "thing")
|
||||
val ws2 =
|
||||
list_map_fun<a><b>(ws2, lam(x) => Sing(x))
|
||||
val ws2 = monad_list_list(list0_of_list_vt(ws2))
|
||||
//
|
||||
val ws3 =
|
||||
$list{a}("walked", "treaded", "grows")
|
||||
val ws3 =
|
||||
list_map_fun<a><b>(ws3, lam(x) => Sing(x))
|
||||
val ws3 = monad_list_list(list0_of_list_vt(ws3))
|
||||
//
|
||||
val ws4 =
|
||||
$list{a}("slowly", "quickly")
|
||||
val ws4 =
|
||||
list_map_fun<a><b>(ws4, lam(x) => Sing(x))
|
||||
val ws4 = monad_list_list(list0_of_list_vt(ws4))
|
||||
//
|
||||
(* ****** ****** *)
|
||||
//
|
||||
val
|
||||
ws12 =
|
||||
monad_bind2<b,b><b>
|
||||
(ws1, ws2, lam (w1, w2) => monad_list_list(words_comb(w1, w2)))
|
||||
val
|
||||
ws123 =
|
||||
monad_bind2<b,b><b>
|
||||
(ws12, ws3, lam (w12, w3) => monad_list_list(words_comb(w12, w3)))
|
||||
val
|
||||
ws1234 =
|
||||
monad_bind2<b,b><b>
|
||||
(ws123, ws4, lam (w123, w4) => monad_list_list(words_comb(w123, w4)))
|
||||
//
|
||||
(* ****** ****** *)
|
||||
|
||||
implement main0 () =
|
||||
{
|
||||
val () = fprintln! (stdout_ref, "ws1234 = ", ws1234)
|
||||
}
|
||||
|
||||
(* ****** ****** *)
|
||||
70
Task/Amb/Ada/amb.ada
Normal file
70
Task/Amb/Ada/amb.ada
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||
with Ada.Text_IO; use Ada.Text_IO;
|
||||
|
||||
procedure Test_Amb is
|
||||
type Alternatives is array (Positive range <>) of Unbounded_String;
|
||||
|
||||
type Amb (Count : Positive) is record
|
||||
This : Positive := 1;
|
||||
Left : access Amb;
|
||||
List : Alternatives (1..Count);
|
||||
end record;
|
||||
|
||||
function Image (L : Amb) return String is
|
||||
begin
|
||||
return To_String (L.List (L.This));
|
||||
end Image;
|
||||
|
||||
function "/" (L, R : String) return Amb is
|
||||
Result : Amb (2);
|
||||
begin
|
||||
Append (Result.List (1), L);
|
||||
Append (Result.List (2), R);
|
||||
return Result;
|
||||
end "/";
|
||||
|
||||
function "/" (L : Amb; R : String) return Amb is
|
||||
Result : Amb (L.Count + 1);
|
||||
begin
|
||||
Result.List (1..L.Count) := L.List ;
|
||||
Append (Result.List (Result.Count), R);
|
||||
return Result;
|
||||
end "/";
|
||||
|
||||
function "=" (L, R : Amb) return Boolean is
|
||||
Left : Unbounded_String renames L.List (L.This);
|
||||
begin
|
||||
return Element (Left, Length (Left)) = Element (R.List (R.This), 1);
|
||||
end "=";
|
||||
|
||||
procedure Failure (L : in out Amb) is
|
||||
begin
|
||||
loop
|
||||
if L.This < L.Count then
|
||||
L.This := L.This + 1;
|
||||
else
|
||||
L.This := 1;
|
||||
Failure (L.Left.all);
|
||||
end if;
|
||||
exit when L.Left = null or else L.Left.all = L;
|
||||
end loop;
|
||||
end Failure;
|
||||
|
||||
procedure Join (L : access Amb; R : in out Amb) is
|
||||
begin
|
||||
R.Left := L;
|
||||
while L.all /= R loop
|
||||
Failure (R);
|
||||
end loop;
|
||||
end Join;
|
||||
|
||||
W_1 : aliased Amb := "the" / "that" / "a";
|
||||
W_2 : aliased Amb := "frog" / "elephant" / "thing";
|
||||
W_3 : aliased Amb := "walked" / "treaded" / "grows";
|
||||
W_4 : aliased Amb := "slowly" / "quickly";
|
||||
begin
|
||||
Join (W_1'Access, W_2);
|
||||
Join (W_2'Access, W_3);
|
||||
Join (W_3'Access, W_4);
|
||||
Put_Line (Image (W_1) & ' ' & Image (W_2) & ' ' & Image (W_3) & ' ' & Image (W_4));
|
||||
end Test_Amb;
|
||||
16
Task/Amb/AutoHotkey/amb.ahk
Normal file
16
Task/Amb/AutoHotkey/amb.ahk
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
set1 := "the that a"
|
||||
set2 := "frog elephant thing"
|
||||
set3 := "walked treaded grows"
|
||||
set4 := "slowly quickly"
|
||||
|
||||
MsgBox % amb( "", set1, set2, set3, set4 )
|
||||
; this takes a total of 17 iterations to complete
|
||||
|
||||
amb( char = "", set1 = "", set2 = "", set3 = "", set4 = "" )
|
||||
{ ; original call to amb must leave char param blank
|
||||
Loop, Parse, set1, %A_Space%
|
||||
If (char = (idxchar := SubStr(A_LoopField, 1, 1)) && set2 = ""
|
||||
|| (char = idxchar || char = "") && ((retval:= amb(SubStr(A_LoopField, 0, 1), set2, set3, set4)) != ""))
|
||||
Return A_LoopField " " retval
|
||||
Return ""
|
||||
}
|
||||
42
Task/Amb/BaCon/amb.bacon
Normal file
42
Task/Amb/BaCon/amb.bacon
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
DECLARE (*ambassert)() TYPE NUMBER
|
||||
|
||||
FUNCTION amb_recurse$(text$[], nr, total, result$)
|
||||
|
||||
LOCAL ctr
|
||||
LOCAL str$, test$
|
||||
|
||||
FOR ctr = 1 TO AMOUNT(text$[nr])
|
||||
str$ = APPEND$(result$, 0, TOKEN$(text$[nr], ctr))
|
||||
IF nr = total-1 THEN
|
||||
IF ambassert(str$) THEN RETURN str$
|
||||
ELSE
|
||||
test$ = amb_recurse$(text$, nr+1, total, str$)
|
||||
IF AMOUNT(test$) = total THEN RETURN test$
|
||||
ENDIF
|
||||
NEXT
|
||||
|
||||
RETURN ""
|
||||
|
||||
ENDFUNC
|
||||
|
||||
FUNCTION ambsel$(VAR data$ SIZE dim)
|
||||
|
||||
RETURN IIF$(dim < 2, "ambsel$ needs more than 1 argument", amb_recurse$(data$, 0, dim, ""))
|
||||
|
||||
ENDFUNC
|
||||
|
||||
FUNCTION this_is_some_constraint(var$)
|
||||
|
||||
DOTIMES AMOUNT(var$)-1
|
||||
IF RIGHT$(TOKEN$(var$, _), 1) != LEFT$(TOKEN$(var$, _+1), 1) THEN RETURN FALSE
|
||||
DONE
|
||||
|
||||
RETURN TRUE
|
||||
|
||||
ENDFUNC
|
||||
|
||||
' AMBASSERT: pointing to a constraint function
|
||||
ambassert = this_is_some_constraint
|
||||
|
||||
' AMBSEL$: generate result from arguments in delimited string format
|
||||
PRINT ambsel$("the that a", "frog elephant thing", "walked treaded grows", "slowly quickly")
|
||||
23
Task/Amb/Bracmat/amb.bracmat
Normal file
23
Task/Amb/Bracmat/amb.bracmat
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
( ( Amb
|
||||
= first last list words word solution
|
||||
. !arg:(?first.?list)
|
||||
& ( !list:
|
||||
| !list:(.?words) ?list
|
||||
& !words
|
||||
: ?
|
||||
%( @(?word:!first ? @?last)
|
||||
& Amb$(!last.!list):?solution
|
||||
& !word !solution:?solution
|
||||
)
|
||||
?
|
||||
& !solution
|
||||
)
|
||||
)
|
||||
& Amb
|
||||
$ (
|
||||
. (.the that a)
|
||||
(.frog elephant thing)
|
||||
(.walked treaded grows)
|
||||
(.slowly quickly)
|
||||
)
|
||||
)
|
||||
80
Task/Amb/C++/amb.cpp
Normal file
80
Task/Amb/C++/amb.cpp
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
#include <iostream>
|
||||
#include <string_view>
|
||||
#include <boost/hana.hpp>
|
||||
#include <boost/hana/experimental/printable.hpp>
|
||||
|
||||
using namespace std;
|
||||
namespace hana = boost::hana;
|
||||
|
||||
// Define the Amb function. The first parameter is the constraint to be
|
||||
// enforced followed by the potential values.
|
||||
constexpr auto Amb(auto constraint, auto&& ...params)
|
||||
{
|
||||
// create the set of all possible solutions
|
||||
auto possibleSolutions = hana::cartesian_product(hana::tuple(params...));
|
||||
|
||||
// find one that matches the constraint
|
||||
auto foldOperation = [constraint](auto a, auto b)
|
||||
{
|
||||
bool meetsConstraint = constraint(a);
|
||||
return meetsConstraint ? a : b;
|
||||
};
|
||||
|
||||
return hana::fold_right(possibleSolutions, foldOperation);
|
||||
}
|
||||
|
||||
void AlgebraExample()
|
||||
{
|
||||
// use a tuple to hold the possible values of each variable
|
||||
constexpr hana::tuple x{1, 2, 3};
|
||||
constexpr hana::tuple y{7, 6, 4, 5};
|
||||
|
||||
// the constraint enforcing x * y == 8
|
||||
constexpr auto constraint = [](auto t)
|
||||
{
|
||||
return t[hana::size_c<0>] * t[hana::size_c<1>] == 8;
|
||||
};
|
||||
|
||||
// find the solution using the Amb function
|
||||
auto result = Amb(constraint, x, y);
|
||||
|
||||
cout << "\nx = " << hana::experimental::print(x);
|
||||
cout << "\ny = " << hana::experimental::print(y);
|
||||
cout << "\nx * y == 8: " << hana::experimental::print(result);
|
||||
}
|
||||
|
||||
void StringExample()
|
||||
{
|
||||
// the word lists to choose from
|
||||
constexpr hana::tuple words1 {"the"sv, "that"sv, "a"sv};
|
||||
constexpr hana::tuple words2 {"frog"sv, "elephant"sv, "thing"sv};
|
||||
constexpr hana::tuple words3 {"walked"sv, "treaded"sv, "grows"sv};
|
||||
constexpr hana::tuple words4 {"slowly"sv, "quickly"sv};
|
||||
|
||||
// the constraint that the first letter of a word is the same as the last
|
||||
// letter of the previous word
|
||||
constexpr auto constraint = [](const auto t)
|
||||
{
|
||||
auto adjacent = hana::zip(hana::drop_back(t), hana::drop_front(t));
|
||||
return hana::all_of(adjacent, [](auto t)
|
||||
{
|
||||
return t[hana::size_c<0>].back() == t[hana::size_c<1>].front();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// find the solution using the Amb function
|
||||
auto wordResult = Amb(constraint, words1, words2, words3, words4);
|
||||
|
||||
cout << "\n\nWords 1: " << hana::experimental::print(words1);
|
||||
cout << "\nWords 2: " << hana::experimental::print(words2);
|
||||
cout << "\nWords 3: " << hana::experimental::print(words3);
|
||||
cout << "\nWords 4: " << hana::experimental::print(words4);
|
||||
cout << "\nSolution: " << hana::experimental::print(wordResult) << "\n";
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
AlgebraExample();
|
||||
StringExample();
|
||||
}
|
||||
152
Task/Amb/C-sharp/amb-1.cs
Normal file
152
Task/Amb/C-sharp/amb-1.cs
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class Amb : IDisposable
|
||||
{
|
||||
List<IValueSet> streams = new List<IValueSet>();
|
||||
List<IAssertOrAction> assertsOrActions = new List<IAssertOrAction>();
|
||||
volatile bool stopped = false;
|
||||
|
||||
public IAmbValue<T> DefineValues<T>(params T[] values)
|
||||
{
|
||||
return DefineValueSet(values);
|
||||
}
|
||||
|
||||
public IAmbValue<T> DefineValueSet<T>(IEnumerable<T> values)
|
||||
{
|
||||
ValueSet<T> stream = new ValueSet<T>();
|
||||
stream.Enumerable = values;
|
||||
streams.Add(stream);
|
||||
return stream;
|
||||
}
|
||||
|
||||
public Amb Assert(Func<bool> function)
|
||||
{
|
||||
assertsOrActions.Add(new AmbAssert()
|
||||
{
|
||||
Level = streams.Count,
|
||||
IsValidFunction = function
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public Amb Perform(Action action)
|
||||
{
|
||||
assertsOrActions.Add(new AmbAction()
|
||||
{
|
||||
Level = streams.Count,
|
||||
Action = action
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
RunLevel(0, 0);
|
||||
if (!stopped)
|
||||
{
|
||||
throw new AmbException();
|
||||
}
|
||||
}
|
||||
|
||||
void RunLevel(int level, int actionIndex)
|
||||
{
|
||||
while (actionIndex < assertsOrActions.Count && assertsOrActions[actionIndex].Level <= level)
|
||||
{
|
||||
if (!assertsOrActions[actionIndex].Invoke() || stopped)
|
||||
return;
|
||||
actionIndex++;
|
||||
}
|
||||
if (level < streams.Count)
|
||||
{
|
||||
using (IValueSetIterator iterator = streams[level].CreateIterator())
|
||||
{
|
||||
while (iterator.MoveNext())
|
||||
{
|
||||
RunLevel(level + 1, actionIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface IValueSet
|
||||
{
|
||||
IValueSetIterator CreateIterator();
|
||||
}
|
||||
|
||||
interface IValueSetIterator : IDisposable
|
||||
{
|
||||
bool MoveNext();
|
||||
}
|
||||
|
||||
interface IAssertOrAction
|
||||
{
|
||||
int Level { get; }
|
||||
bool Invoke();
|
||||
}
|
||||
|
||||
class AmbAssert : IAssertOrAction
|
||||
{
|
||||
internal int Level;
|
||||
internal Func<bool> IsValidFunction;
|
||||
|
||||
int IAssertOrAction.Level { get { return Level; } }
|
||||
|
||||
bool IAssertOrAction.Invoke()
|
||||
{
|
||||
return IsValidFunction();
|
||||
}
|
||||
}
|
||||
|
||||
class AmbAction : IAssertOrAction
|
||||
{
|
||||
internal int Level;
|
||||
internal Action Action;
|
||||
|
||||
int IAssertOrAction.Level { get { return Level; } }
|
||||
|
||||
bool IAssertOrAction.Invoke()
|
||||
{
|
||||
Action(); return true;
|
||||
}
|
||||
}
|
||||
|
||||
class ValueSet<T> : IValueSet, IAmbValue<T>, IValueSetIterator
|
||||
{
|
||||
internal IEnumerable<T> Enumerable;
|
||||
private IEnumerator<T> enumerator;
|
||||
|
||||
public T Value { get { return enumerator.Current; } }
|
||||
|
||||
public IValueSetIterator CreateIterator()
|
||||
{
|
||||
enumerator = Enumerable.GetEnumerator();
|
||||
return this;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
return enumerator.MoveNext();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
enumerator.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IAmbValue<T>
|
||||
{
|
||||
T Value { get; }
|
||||
}
|
||||
|
||||
public class AmbException : Exception
|
||||
{
|
||||
public AmbException() : base("AMB is angry") { }
|
||||
}
|
||||
30
Task/Amb/C-sharp/amb-2.cs
Normal file
30
Task/Amb/C-sharp/amb-2.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// original problem
|
||||
using (Amb amb = new Amb())
|
||||
{
|
||||
var set1 = amb.DefineValues("the", "that", "a");
|
||||
var set2 = amb.DefineValues("frog", "elephant", "thing");
|
||||
var set3 = amb.DefineValues("walked", "treaded", "grows");
|
||||
var set4 = amb.DefineValues("slowly", "quickly");
|
||||
|
||||
amb.Assert(() => IsJoinable(set1.Value, set2.Value));
|
||||
amb.Assert(() => IsJoinable(set2.Value, set3.Value));
|
||||
amb.Assert(() => IsJoinable(set3.Value, set4.Value));
|
||||
|
||||
amb.Perform(() =>
|
||||
{
|
||||
System.Console.WriteLine("{0} {1} {2} {3}", set1.Value, set2.Value, set3.Value, set4.Value);
|
||||
amb.Stop();
|
||||
});
|
||||
}
|
||||
// problem from http://www.randomhacks.net/articles/2005/10/11/amb-operator
|
||||
using (Amb amb = new Amb())
|
||||
{
|
||||
IAmbValue<int> x = amb.DefineValues(1, 2, 3);
|
||||
IAmbValue<int> y = amb.DefineValues(4, 5, 6);
|
||||
amb.Assert(() => x.Value * y.Value == 8);
|
||||
amb.Perform(() =>
|
||||
{
|
||||
System.Console.WriteLine("{0} {1}", x.Value, y.Value);
|
||||
amb.Stop();
|
||||
});
|
||||
}
|
||||
73
Task/Amb/C-sharp/amb-3.cs
Normal file
73
Task/Amb/C-sharp/amb-3.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Amb {
|
||||
public interface IValue<T> {
|
||||
T Value { get; }
|
||||
string ToString();
|
||||
}
|
||||
|
||||
public sealed class Amb {
|
||||
public IValue<T> Choose<T>(params T[] choices) {
|
||||
var array = new ChoiceArray<T> { Values = choices };
|
||||
_choices.Add(array);
|
||||
return array;
|
||||
}
|
||||
|
||||
public void Require(Func<bool> predicate) =>
|
||||
_constraints.Add(new Constraint { Predicate = predicate, AppliesForItems = _choices.Count });
|
||||
|
||||
public bool Disambiguate() => Disambiguate(0, 0);
|
||||
|
||||
interface IChoices {
|
||||
int Length { get; }
|
||||
int Index { get; set; }
|
||||
}
|
||||
|
||||
interface IConstraint {
|
||||
int AppliesForItems { get; }
|
||||
bool Invoke();
|
||||
}
|
||||
|
||||
readonly List<IChoices> _choices = new();
|
||||
readonly List<IConstraint> _constraints = new();
|
||||
|
||||
bool Disambiguate(int choicesTracked, int constraintIdx) {
|
||||
while (constraintIdx < _constraints.Count && _constraints[constraintIdx].AppliesForItems <= choicesTracked) {
|
||||
if (!_constraints[constraintIdx].Invoke())
|
||||
return false;
|
||||
constraintIdx++;
|
||||
}
|
||||
|
||||
if (choicesTracked == _choices.Count)
|
||||
return true;
|
||||
|
||||
for (var i = 0; i < _choices[choicesTracked].Length; i++) {
|
||||
_choices[choicesTracked].Index = i;
|
||||
if (Disambiguate(choicesTracked + 1, constraintIdx))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class Constraint : IConstraint {
|
||||
internal Func<bool> Predicate;
|
||||
|
||||
public int AppliesForItems { get; set; }
|
||||
|
||||
public bool Invoke() => Predicate?.Invoke() ?? default;
|
||||
}
|
||||
|
||||
class ChoiceArray<T> : IChoices, IValue<T> {
|
||||
internal T[] Values;
|
||||
|
||||
public int Index { get; set; }
|
||||
|
||||
public T Value => Values[Index];
|
||||
|
||||
public int Length => Values.Length;
|
||||
|
||||
public override string ToString() => Value.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Task/Amb/C-sharp/amb-4.cs
Normal file
32
Task/Amb/C-sharp/amb-4.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
using System.Linq;
|
||||
using static System.Console;
|
||||
|
||||
namespace Amb {
|
||||
class Program {
|
||||
static void Main(string[] args) {
|
||||
|
||||
var amb = new Amb();
|
||||
|
||||
var set1 = amb.Choose("the", "that", "a");
|
||||
var set2 = amb.Choose("frog", "elephant", "thing");
|
||||
amb.Require(() => set1.Value.Last() == set2.Value[0]);
|
||||
var set3 = amb.Choose("walked", "treaded", "grows");
|
||||
amb.Require(() => set2.Value.Last() == set3.Value[0]);
|
||||
var set4 = amb.Choose("slowly", "quickly");
|
||||
amb.Require(() => set3.Value.Last() == set4.Value[0]);
|
||||
|
||||
WriteLine(amb.Disambiguate()? $"{set1} {set2} {set3} {set4}" : "Amb failed");
|
||||
Read();
|
||||
|
||||
// problem from http://www.randomhacks.net/articles/2005/10/11/amb-operator
|
||||
amb = new Amb();
|
||||
|
||||
var x = amb.Choose(1, 2, 3);
|
||||
var y = amb.Choose(4, 5, 6);
|
||||
amb.Require(() => x.Value * y.Value == 8);
|
||||
|
||||
WriteLine(amb.Disambiguate() ? $"{x} * {y} = 8" : "Amb failed");
|
||||
Read();
|
||||
}
|
||||
}
|
||||
}
|
||||
22
Task/Amb/C-sharp/amb-5.cs
Normal file
22
Task/Amb/C-sharp/amb-5.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
using static System.Console;
|
||||
using System.Linq;
|
||||
|
||||
string[] w1 = { "the", "that", "a" };
|
||||
string[] w2 = { "frog", "elephant", "thing" };
|
||||
string[] w3 = { "walked", "treaded", "grows" };
|
||||
string[] w4 = { "slowly", "quickly" };
|
||||
|
||||
var result = from a in w1
|
||||
join b in w2 on a?.LastOrDefault() equals b?.FirstOrDefault()
|
||||
join c in w3 on b?.LastOrDefault() equals c?.FirstOrDefault()
|
||||
join d in w4 on c?.LastOrDefault() equals d?.FirstOrDefault()
|
||||
select new [] {a, b, c, d};
|
||||
WriteLine(string.Join(" ", result.SelectMany(x => x)));
|
||||
|
||||
double[] x = { 1, 2, 3 };
|
||||
double[] y = { 7, 6, 4, 5 };
|
||||
|
||||
var result2 = from a in x
|
||||
join b in y on a equals 8 / b
|
||||
select new[] { a, b };
|
||||
WriteLine(string.Join(" ", result2.SelectMany(x => x)));
|
||||
41
Task/Amb/C/amb.c
Normal file
41
Task/Amb/C/amb.c
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
typedef const char * amb_t;
|
||||
|
||||
amb_t amb(size_t argc, ...)
|
||||
{
|
||||
amb_t *choices;
|
||||
va_list ap;
|
||||
int i;
|
||||
|
||||
if(argc) {
|
||||
choices = malloc(argc*sizeof(amb_t));
|
||||
va_start(ap, argc);
|
||||
i = 0;
|
||||
do { choices[i] = va_arg(ap, amb_t); } while(++i < argc);
|
||||
va_end(ap);
|
||||
|
||||
i = 0;
|
||||
do { TRY(choices[i]); } while(++i < argc);
|
||||
free(choices);
|
||||
}
|
||||
|
||||
FAIL;
|
||||
}
|
||||
|
||||
int joins(const char *left, const char *right) { return left[strlen(left)-1] == right[0]; }
|
||||
|
||||
int _main() {
|
||||
const char *w1,*w2,*w3,*w4;
|
||||
|
||||
w1 = amb(3, "the", "that", "a");
|
||||
w2 = amb(3, "frog", "elephant", "thing");
|
||||
w3 = amb(3, "walked", "treaded", "grows");
|
||||
w4 = amb(2, "slowly", "quickly");
|
||||
|
||||
if(!joins(w1, w2)) amb(0);
|
||||
if(!joins(w2, w3)) amb(0);
|
||||
if(!joins(w3, w4)) amb(0);
|
||||
|
||||
printf("%s %s %s %s\n", w1, w2, w3, w4);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
12
Task/Amb/Clojure/amb.clj
Normal file
12
Task/Amb/Clojure/amb.clj
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
(ns amb
|
||||
(:use clojure.contrib.monads))
|
||||
|
||||
(defn amb [wss]
|
||||
(let [valid-word (fn [w1 w2]
|
||||
(if (and w1 (= (last w1) (first w2)))
|
||||
(str w1 " " w2)))]
|
||||
(filter #(reduce valid-word %)
|
||||
(with-monad sequence-m (m-seq wss)))))
|
||||
|
||||
amb> (amb '(("the" "that" "a") ("frog" "elephant" "thing") ("walked" "treaded" "grows") ("slowly" "quickly")))
|
||||
(("that" "thing" "grows" "slowly"))
|
||||
35
Task/Amb/Common-Lisp/amb-1.lisp
Normal file
35
Task/Amb/Common-Lisp/amb-1.lisp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
(define-condition amb-failure () ()
|
||||
(:report "No amb alternative succeeded."))
|
||||
|
||||
(defun invoke-ambiguously (function thunks)
|
||||
"Call function with successive values produced by successive
|
||||
functions in thunks until some invocation of function does not signal
|
||||
an amb-failure."
|
||||
(do ((thunks thunks (rest thunks)))
|
||||
((endp thunks) (error 'amb-failure))
|
||||
(let ((argument (funcall (first thunks))))
|
||||
(handler-case (return (funcall function argument))
|
||||
(amb-failure ())))))
|
||||
|
||||
(defmacro amblet1 ((var form) &body body)
|
||||
"If form is of the form (amb {form}*) then amblet1 is a convenient
|
||||
syntax for invoke-ambiguously, by which body is evaluated with var
|
||||
bound the results of each form until some evaluation of body does not
|
||||
signal an amb-failure. For any other form, amblet binds var the result
|
||||
of form, and evaluates body."
|
||||
(if (and (listp form) (eq (first form) 'amb))
|
||||
`(invoke-ambiguously
|
||||
#'(lambda (,var) ,@body)
|
||||
(list ,@(loop for amb-form in (rest form)
|
||||
collecting `#'(lambda () ,amb-form))))
|
||||
`(let ((,var ,form))
|
||||
,@body)))
|
||||
|
||||
(defmacro amblet (bindings &body body)
|
||||
"Like let, except that if an init-form is of the form (amb {form}*),
|
||||
then the corresponding var is bound with amblet1."
|
||||
(if (endp bindings)
|
||||
`(progn ,@body)
|
||||
`(amblet1 ,(first bindings)
|
||||
(amblet ,(rest bindings)
|
||||
,@body))))
|
||||
50
Task/Amb/Common-Lisp/amb-2.lisp
Normal file
50
Task/Amb/Common-Lisp/amb-2.lisp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
(defparameter *amb-ops* nil)
|
||||
(defparameter *amb-hist* nil)
|
||||
|
||||
(setf *random-state* (make-random-state t))
|
||||
(defun shuffle (items)
|
||||
(loop for i from 0 with r = items with l = (length r) while (< i l) do
|
||||
(rotatef (elt r i) (elt r (+ i (random (- l i)))))
|
||||
finally (return r)))
|
||||
|
||||
;;; (assert '(mess in, mess out))
|
||||
(defmacro amb (a &rest rest)
|
||||
(let ((f (first rest))
|
||||
(rest (rest rest)))
|
||||
(if (not f)
|
||||
`(let ((items (shuffle ,a)))
|
||||
(let ((y (car (last *amb-hist*)))
|
||||
(o (car (last *amb-ops*))))
|
||||
(loop for x in items do
|
||||
(if (or (not *amb-ops*)
|
||||
(funcall o y x))
|
||||
(return (append *amb-hist* (list x))))
|
||||
(elt items (random (length items))))))
|
||||
|
||||
`(let ((items (shuffle ,a)))
|
||||
(let ((y (car (last *amb-hist*)))
|
||||
(o (car (last *amb-ops*))))
|
||||
(loop for x in items do
|
||||
(if (or (not *amb-ops*)
|
||||
(funcall o y x))
|
||||
(let ((*amb-hist* (append *amb-hist* (list x)))
|
||||
(*amb-ops* (append *amb-ops* (list ,f))))
|
||||
(let ((r ,@rest))
|
||||
(if r (return r)))))))))))
|
||||
|
||||
;; test cases
|
||||
(defun joins (a b)
|
||||
(char= (char a (1- (length a))) (char b 0)))
|
||||
|
||||
(defun w34()
|
||||
(amb '("walked" "treaded" "grows") #'joins
|
||||
(amb '("slowly" "quickly"))))
|
||||
|
||||
(print
|
||||
(amb '("the" "that" "a") #'joins
|
||||
(amb '("frog" "elephant" "thing") #'joins
|
||||
(w34))))
|
||||
|
||||
(print (amb '(1 2 5) #'<
|
||||
(amb '(2 3 4) #'=
|
||||
(amb '(3 4 5))))) ; 1 4 4, 2 3 3, etc
|
||||
26
Task/Amb/Common-Lisp/amb-3.lisp
Normal file
26
Task/Amb/Common-Lisp/amb-3.lisp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
;; 22.11.18 Ajout macro
|
||||
|
||||
(defvar *stack* nil)
|
||||
(defvar *assert* t)
|
||||
|
||||
(defun ambnew ()
|
||||
(setf *stack* nil)
|
||||
(setf *assert* t))
|
||||
|
||||
(defmacro ambsel (name domain)
|
||||
`(progn (defparameter ,name (first ,domain))
|
||||
(pushnew ',name *stack*)
|
||||
(setf (get ',name 'domain) ,domain)))
|
||||
|
||||
(defun ambassert (assert)
|
||||
(setf *assert* (list 'and assert *assert*))
|
||||
(if (eval *assert*)
|
||||
t
|
||||
(labels ((probe (&optional (stack *stack*))
|
||||
(let* ((name (first stack))
|
||||
(domain (get name 'domain)))
|
||||
(dolist (value domain)
|
||||
(set name value)
|
||||
(cond ((eval *assert*) (return t))
|
||||
((probe (rest stack)) (return t)))))))
|
||||
(probe))))
|
||||
2
Task/Amb/Common-Lisp/amb-4.lisp
Normal file
2
Task/Amb/Common-Lisp/amb-4.lisp
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(defun match (a b)
|
||||
(equal (elt (reverse a) 0) (elt b 0)))
|
||||
10
Task/Amb/Common-Lisp/amb-5.lisp
Normal file
10
Task/Amb/Common-Lisp/amb-5.lisp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
(defun magic-square (a b c d e f g h i)
|
||||
(and (/= a b c d e f g h i)
|
||||
(= (+ a b c)
|
||||
(+ d e f)
|
||||
(+ g h i)
|
||||
(+ a d g)
|
||||
(+ b e h)
|
||||
(+ c f i)
|
||||
(+ a e i)
|
||||
(+ c e g))))
|
||||
47
Task/Amb/D/amb.d
Normal file
47
Task/Amb/D/amb.d
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import std.stdio, std.array;
|
||||
|
||||
/** This amb function takes a comparison function and
|
||||
the possibilities that need to be checked.*/
|
||||
//string[] amb(in bool function(in string, in string) pure comp,
|
||||
const(string)[] amb(in bool function(in string, in string) pure comp,
|
||||
in string[][] options,
|
||||
in string prev = null) pure {
|
||||
if (options.empty)
|
||||
return null;
|
||||
|
||||
foreach (immutable opt; options.front) {
|
||||
// If this is the base call, prev is null and we need to
|
||||
// continue.
|
||||
if (!prev.empty && !comp(prev, opt))
|
||||
continue;
|
||||
|
||||
// Take care of the case where we have no options left.
|
||||
if (options.length == 1)
|
||||
return [opt];
|
||||
|
||||
// Traverse into the tree.
|
||||
const res = amb(comp, options[1 .. $], opt);
|
||||
|
||||
// If it was a failure, try the next one.
|
||||
if (!res.empty)
|
||||
return opt ~ res; // We have a match!
|
||||
}
|
||||
|
||||
return null; // No matches.
|
||||
}
|
||||
|
||||
void main() {
|
||||
immutable sets = [["the", "that", "a"],
|
||||
["frog", "elephant", "thing"],
|
||||
["walked", "treaded", "grows"],
|
||||
["slowly", "quickly"]];
|
||||
|
||||
// Pass in the comparator and the available sets.
|
||||
// (The comparator is not nothrow because of UTF.)
|
||||
const result = amb((s, t) => s.back == t.front, sets);
|
||||
|
||||
if (result.empty)
|
||||
writeln("No matches found!");
|
||||
else
|
||||
writefln("%-(%s %)", result);
|
||||
}
|
||||
81
Task/Amb/E/amb-1.e
Normal file
81
Task/Amb/E/amb-1.e
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
pragma.enable("accumulator")
|
||||
|
||||
def [amb, unamb] := { # block hides internals
|
||||
|
||||
def Choice := Tuple[any, Map]
|
||||
|
||||
def [ambS, ambU] := <elib:sealing.makeBrand>("amb")
|
||||
var counter := 0 # Used just for printing ambs
|
||||
|
||||
/** Check whether two sets of decisions are consistent */
|
||||
def consistent(decA, decB) {
|
||||
def overlap := decA.domain() & decB.domain()
|
||||
for ambObj in overlap {
|
||||
if (decA[ambObj] != decB[ambObj]) { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/** From an amb object, extract the possible choices */
|
||||
def getChoices(obj, decisions) :List[Choice] {
|
||||
if (decisions.maps(obj)) {
|
||||
return [[decisions[obj], decisions]]
|
||||
} else if (ambU.amplify(obj) =~ [[choices, _]]) {
|
||||
return accum [] for [chosen, dec] ? (consistent(decisions, dec)) in choices { _ + getChoices(chosen, (decisions | dec).with(obj, chosen)) }
|
||||
} else {
|
||||
return [[obj, decisions]]
|
||||
}
|
||||
}
|
||||
|
||||
/** Construct an amb object with remembered decisions */
|
||||
def ambDec(choices :List[Choice]) {
|
||||
def serial := (counter += 1)
|
||||
def ambObj {
|
||||
to __printOn(out) {
|
||||
out.print("<amb(", serial, ")")
|
||||
for [chosen, decisions] in choices {
|
||||
out.print(" ", chosen)
|
||||
for k => v in decisions {
|
||||
out.print(";", ambU.amplify(k)[0][1], "=", v)
|
||||
}
|
||||
}
|
||||
out.print(">")
|
||||
}
|
||||
to __optSealedDispatch(brand) {
|
||||
if (brand == ambS.getBrand()) {
|
||||
return ambS.seal([choices, serial])
|
||||
}
|
||||
}
|
||||
match [verb, args] {
|
||||
var results := []
|
||||
for [rec, rdec] in getChoices(ambObj, [].asMap()) {
|
||||
def expandArgs(dec, prefix, choosing) {
|
||||
switch (choosing) {
|
||||
match [] { results with= [E.call(rec, verb, prefix), dec] }
|
||||
match [argAmb] + moreArgs {
|
||||
for [arg, adec] in getChoices(argAmb, dec) {
|
||||
expandArgs(adec, prefix.with(arg), moreArgs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
expandArgs(rdec, [], args)
|
||||
}
|
||||
ambDec(results)
|
||||
}
|
||||
}
|
||||
return ambObj
|
||||
}
|
||||
|
||||
/** Construct an amb object with no remembered decisions. (public interface) */
|
||||
def amb(choices) {
|
||||
return ambDec(accum [] for c in choices { _.with([c, [].asMap()]) })
|
||||
}
|
||||
|
||||
/** Get the possible results from an amb object, discarding decision info. (public interface) */
|
||||
def unamb(ambObj) {
|
||||
return accum [] for [c,_] in getChoices(ambObj, [].asMap()) { _.with(c) }
|
||||
}
|
||||
|
||||
[amb, unamb]
|
||||
}
|
||||
18
Task/Amb/E/amb-2.e
Normal file
18
Task/Amb/E/amb-2.e
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
def join(a, b) {
|
||||
# This must not use the builtin if, since it coerces to boolean rather than passing messages.
|
||||
# false.pick(x, y) returns y and true.pick(x, y) returns x; we protect the amb([]) from causing
|
||||
# unconditional failure by putting both options in functions.
|
||||
# <=> is the comparison operator that happens to be message-based.
|
||||
return (a.last() <=> b[0]).pick(fn {
|
||||
a + " " + b
|
||||
}, fn {
|
||||
amb([])
|
||||
})()
|
||||
}
|
||||
|
||||
def w1 := amb(["the", "that", "a" ])
|
||||
def w2 := amb(["frog", "elephant", "thing" ])
|
||||
def w3 := amb(["walked", "treaded", "grows" ])
|
||||
def w4 := amb(["slowly", "quickly" ])
|
||||
|
||||
unamb(join(join(join(w1, w2), w3), w4))
|
||||
50
Task/Amb/ERRE/amb.erre
Normal file
50
Task/Amb/ERRE/amb.erre
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
PROGRAM AMB
|
||||
|
||||
!
|
||||
! for rosettacode.org
|
||||
!
|
||||
|
||||
!$KEY
|
||||
|
||||
DIM SET1$[2],SET2$[2],SET3$[2],SET4$[2]
|
||||
|
||||
FUNCTION WORDS_OK(STRING1$,STRING2$)
|
||||
WORDS_OK=(RIGHT$(STRING1$,1)=LEFT$(STRING2$,1))
|
||||
END FUNCTION
|
||||
|
||||
PROCEDURE AMB(SET1$[],SET2$[],SET3$[],SET4$[]->RESULT$)
|
||||
RESULT$="" ! Empty string, e.g. fail
|
||||
FOR A=0 TO 2 DO
|
||||
FOR B=0 TO 2 DO
|
||||
FOR C=0 TO 2 DO
|
||||
FOR D=0 TO 2 DO
|
||||
IF WORDS_OK(SET1$[A],SET2$[B]) AND WORDS_OK(SET2$[B],SET3$[C]) AND WORDS_OK(SET3$[C],SET4$[D]) THEN
|
||||
RESULT$=SET1$[A]+" "+SET2$[B]+" "+SET3$[C]+" "+SET4$[D]
|
||||
EXIT PROCEDURE
|
||||
END IF
|
||||
END FOR
|
||||
END FOR
|
||||
END FOR
|
||||
END FOR
|
||||
END PROCEDURE
|
||||
|
||||
BEGIN
|
||||
PRINT(CHR$(12);) ! CLS
|
||||
SET1$[0]="the" SET1$[1]="that" SET1$[2]="a"
|
||||
SET2$[0]="frog" SET2$[1]="elephant" SET2$[2]="thing"
|
||||
SET3$[0]="walked" SET3$[1]="treaded" SET3$[2]="grows"
|
||||
SET4$[0]="slowly" SET4$[1]="quickly" SET4$[2]=""
|
||||
|
||||
AMB(SET1$[],SET2$[],SET3$[],SET4$[]->TEXT$)
|
||||
IF TEXT$<>"" THEN
|
||||
PRINT("Correct sentence would be:")
|
||||
PRINT(TEXT$)
|
||||
ELSE
|
||||
PRINT("Failed to fine a correct sentence.")
|
||||
END IF
|
||||
PRINT
|
||||
PRINT("Press any key to exit.")
|
||||
REPEAT
|
||||
GET(Z$)
|
||||
UNTIL LEN(Z$)<>0
|
||||
END PROGRAM
|
||||
7
Task/Amb/Egison/amb-1.egison
Normal file
7
Task/Amb/Egison/amb-1.egison
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
; We don't need 'amb' in the code since pattern-matching of Egison automatically do backtracking.
|
||||
(match-all {{"the" "that" "a"} {"frog" "elephant" "thing"} {"walked" "treaded" "grows"} {"slowly" "quickly"}} (list (multiset string))
|
||||
[<cons <cons (& <snoc $c_1 _> $w_1) _>
|
||||
(loop $i [2 $n]
|
||||
<cons <cons (& <cons ,c_(- i 1) <snoc $c_i _>> $w_i) _> ...>
|
||||
<nil>)>
|
||||
(map (lambda [$i] w_i) (between 1 n))])
|
||||
1
Task/Amb/Egison/amb-2.egison
Normal file
1
Task/Amb/Egison/amb-2.egison
Normal file
|
|
@ -0,0 +1 @@
|
|||
{{"that" "thing" "grows" "slowly"}}
|
||||
15
Task/Amb/Ela/amb-1.ela
Normal file
15
Task/Amb/Ela/amb-1.ela
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
open list core
|
||||
|
||||
amb xs = x where
|
||||
(Some x) = & join xs ""
|
||||
join (x::xs) = amb' x (join xs)
|
||||
join [] = \_ -> Some ""
|
||||
eq' [] x = true
|
||||
eq' w x = last w == head x
|
||||
amb' [] _ _ = None
|
||||
amb' (x::xs) n w
|
||||
| eq' w x =
|
||||
match n x with
|
||||
Some v = Some (x ++ " " ++ v)
|
||||
_ = amb' xs n w
|
||||
| else = amb' xs n w
|
||||
6
Task/Amb/Ela/amb-2.ela
Normal file
6
Task/Amb/Ela/amb-2.ela
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
amb [
|
||||
["the","that","a"]
|
||||
,["frog","elephant","thing"]
|
||||
,["walked","treaded","grows"]
|
||||
,["slowly","quickly"]
|
||||
]
|
||||
85
Task/Amb/Elena/amb.elena
Normal file
85
Task/Amb/Elena/amb.elena
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
import system'routines;
|
||||
import extensions;
|
||||
import extensions'routines;
|
||||
|
||||
joinable(former,later) = (former[former.Length - 1] == later[0]);
|
||||
|
||||
dispatcher = new
|
||||
{
|
||||
eval(object a, Func2 f)
|
||||
{
|
||||
^ f(a[0],a[1])
|
||||
}
|
||||
|
||||
eval(object a, Func3 f)
|
||||
{
|
||||
^ f(a[0], a[1],a[2])
|
||||
}
|
||||
|
||||
eval(object a, Func4 f)
|
||||
{
|
||||
^ f(a[0],a[1],a[2],a[3])
|
||||
}
|
||||
|
||||
eval(object a, Func5 f)
|
||||
{
|
||||
^ f(a[0],a[1],a[2],a[3],a[4])
|
||||
}
|
||||
};
|
||||
|
||||
class AmbValueCollection
|
||||
{
|
||||
object theCombinator;
|
||||
|
||||
constructor new(params object[] args)
|
||||
{
|
||||
theCombinator := SequentialEnumerator.new(params args)
|
||||
}
|
||||
|
||||
seek(cond)
|
||||
{
|
||||
theCombinator.reset();
|
||||
|
||||
theCombinator.seekEach:(v => dispatcher.eval(v,cond))
|
||||
}
|
||||
|
||||
do(f)
|
||||
{
|
||||
var result := theCombinator.get();
|
||||
if (nil != result)
|
||||
{
|
||||
dispatcher.eval(result,f)
|
||||
}
|
||||
else
|
||||
{
|
||||
InvalidArgumentException.raise()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
singleton ambOperator
|
||||
{
|
||||
for(params object[] args)
|
||||
= AmbValueCollection.new(params args);
|
||||
}
|
||||
|
||||
public program()
|
||||
{
|
||||
try
|
||||
{
|
||||
ambOperator
|
||||
.for(
|
||||
new object[]{"the","that","a"},
|
||||
new object[]{"frog", "elephant", "thing"},
|
||||
new object[]{"walked", "treaded", "grows"},
|
||||
new object[]{"slowly", "quickly"})
|
||||
.seek:(a,b,c,d => joinable(a,b) && joinable(b,c) && joinable(c,d) )
|
||||
.do:(a,b,c,d) { console.printLine(a," ",b," ",c," ",d) }
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
console.printLine:"AMB is angry"
|
||||
};
|
||||
|
||||
console.readChar()
|
||||
}
|
||||
28
Task/Amb/F-Sharp/amb.fs
Normal file
28
Task/Amb/F-Sharp/amb.fs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// define the List "workflow" (monad)
|
||||
type ListBuilder() =
|
||||
member o.Bind( lst, f ) = List.concat( List.map (fun x -> f x) lst )
|
||||
member o.Return( x ) = [x]
|
||||
member o.Zero() = []
|
||||
|
||||
let list = ListBuilder()
|
||||
|
||||
let amb = id
|
||||
|
||||
// last element of a sequence
|
||||
let last s = Seq.nth ((Seq.length s) - 1) s
|
||||
|
||||
// is the last element of left the same as the first element of right?
|
||||
let joins left right = last left = Seq.head right
|
||||
|
||||
let example = list { let! w1 = amb ["the"; "that"; "a"]
|
||||
let! w2 = amb ["frog"; "elephant"; "thing"]
|
||||
let! w3 = amb ["walked"; "treaded"; "grows"]
|
||||
let! w4 = amb ["slowly"; "quickly"]
|
||||
if joins w1 w2 &&
|
||||
joins w2 w3 &&
|
||||
joins w3 w4
|
||||
then
|
||||
return String.concat " " [w1; w2; w3; w4]
|
||||
}
|
||||
|
||||
printfn "%s" (List.head example)
|
||||
20
Task/Amb/Factor/amb.factor
Normal file
20
Task/Amb/Factor/amb.factor
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
USING: backtrack continuations kernel prettyprint sequences ;
|
||||
IN: amb
|
||||
|
||||
CONSTANT: words {
|
||||
{ "the" "that" "a" }
|
||||
{ "frog" "elephant" "thing" }
|
||||
{ "walked" "treaded" "grows" }
|
||||
{ "slowly" "quickly" }
|
||||
}
|
||||
|
||||
: letters-match? ( str1 str2 -- ? ) [ last ] [ first ] bi* = ;
|
||||
|
||||
: sentence-match? ( seq -- ? ) dup rest [ letters-match? ] 2all? ;
|
||||
|
||||
: select ( seq -- seq' ) [ amb-lazy ] map ;
|
||||
|
||||
: search ( -- )
|
||||
words select dup sentence-match? [ " " join ] [ fail ] if . ;
|
||||
|
||||
MAIN: search
|
||||
37
Task/Amb/FreeBASIC/amb.basic
Normal file
37
Task/Amb/FreeBASIC/amb.basic
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
Function wordsOK(string1 As String, string2 As String) As boolean
|
||||
If Mid(string1, Len(string1), 1) = Mid(string2, 1, 1) Then
|
||||
Return True
|
||||
End If
|
||||
Return False
|
||||
End Function
|
||||
|
||||
Function Amb(A() As String, B() As String, C() As String, D() As String) As String
|
||||
Dim As Integer a2, b2, c2, d2
|
||||
For a2 = 0 To Ubound(A)
|
||||
For b2 = 0 To Ubound(B)
|
||||
For c2 = 0 To Ubound(C)
|
||||
For d2 = 0 To Ubound(D)
|
||||
If wordsOK(A(a2),B(b2)) And wordsOK(B(b2),C(c2)) And wordsOK(C(c2),D(d2)) Then
|
||||
Return A(a2) + " " + B(b2) + " " + C(c2) + " " + D(d2)
|
||||
End If
|
||||
Next d2
|
||||
Next c2
|
||||
Next b2
|
||||
Next a2
|
||||
Return "" 'Cadena vacía, por ejemplo, falla
|
||||
End Function
|
||||
|
||||
Dim As String set1(2), set2(2), set3(2), set4(1)
|
||||
set1(0) = "the" : set1(1) = "that" : set1(2) = "a"
|
||||
set2(0) = "frog" : set2(1) = "elephant" : set2(2) = "thing"
|
||||
set3(0) = "walked" : set3(1) = "treaded" : set3(2) = "grows"
|
||||
set4(0) = "slowly" : set4(1) = "quickly"
|
||||
|
||||
Dim As String text = Amb(set1(), set2(), set3(), set4())
|
||||
|
||||
If text <> "" Then
|
||||
Print !"Correct sentence would be:\n" + text
|
||||
Else
|
||||
Print "Failed to fine a correct sentence."
|
||||
End If
|
||||
Sleep
|
||||
49
Task/Amb/Go/amb-1.go
Normal file
49
Task/Amb/Go/amb-1.go
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func ambStrings(ss []string) chan []string {
|
||||
c := make(chan []string)
|
||||
go func() {
|
||||
for _, s := range ss {
|
||||
c <- []string{s}
|
||||
}
|
||||
close(c)
|
||||
}()
|
||||
return c
|
||||
}
|
||||
|
||||
func ambChain(ss []string, cIn chan []string) chan []string {
|
||||
cOut := make(chan []string)
|
||||
go func() {
|
||||
var w sync.WaitGroup
|
||||
for chain := range cIn {
|
||||
w.Add(1)
|
||||
go func(chain []string) {
|
||||
for s1 := range ambStrings(ss) {
|
||||
if s1[0][len(s1[0])-1] == chain[0][0] {
|
||||
cOut <- append(s1, chain...)
|
||||
}
|
||||
}
|
||||
w.Done()
|
||||
}(chain)
|
||||
}
|
||||
w.Wait()
|
||||
close(cOut)
|
||||
}()
|
||||
return cOut
|
||||
}
|
||||
|
||||
func main() {
|
||||
s1 := []string{"the", "that", "a"}
|
||||
s2 := []string{"frog", "elephant", "thing"}
|
||||
s3 := []string{"walked", "treaded", "grows"}
|
||||
s4 := []string{"slowly", "quickly"}
|
||||
c := ambChain(s1, ambChain(s2, ambChain(s3, ambStrings(s4))))
|
||||
for s := range c {
|
||||
fmt.Println(s)
|
||||
}
|
||||
}
|
||||
39
Task/Amb/Go/amb-2.go
Normal file
39
Task/Amb/Go/amb-2.go
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package main
|
||||
import "fmt"
|
||||
|
||||
func amb(wordsets [][]string, res []string) bool {
|
||||
if len(wordsets) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
var s string
|
||||
|
||||
l := len(res)
|
||||
if l > 0 { s = res[l - 1] }
|
||||
|
||||
res = res[0:len(res) + 1]
|
||||
|
||||
for _, res[l] = range(wordsets[0]) {
|
||||
if l > 0 && s[len(s) - 1] != res[l][0] { continue }
|
||||
|
||||
if amb(wordsets[1:len(wordsets)], res) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func main() {
|
||||
wordset := [][]string { { "the", "that", "a" },
|
||||
{ "frog", "elephant", "thing" },
|
||||
{ "walked", "treaded", "grows" },
|
||||
{ "slowly", "quickly" } }
|
||||
res := make([]string, len(wordset))
|
||||
|
||||
if amb(wordset, res[0:0]) {
|
||||
fmt.Println(res)
|
||||
} else {
|
||||
fmt.Println("No amb found")
|
||||
}
|
||||
}
|
||||
15
Task/Amb/Haskell/amb-1.hs
Normal file
15
Task/Amb/Haskell/amb-1.hs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import Control.Monad
|
||||
|
||||
amb = id
|
||||
|
||||
joins left right = last left == head right
|
||||
|
||||
example = do
|
||||
w1 <- amb ["the", "that", "a"]
|
||||
w2 <- amb ["frog", "elephant", "thing"]
|
||||
w3 <- amb ["walked", "treaded", "grows"]
|
||||
w4 <- amb ["slowly", "quickly"]
|
||||
guard (w1 `joins` w2)
|
||||
guard (w2 `joins` w3)
|
||||
guard (w3 `joins` w4)
|
||||
pure $ unwords [w1, w2, w3, w4]
|
||||
53
Task/Amb/Haskell/amb-2.hs
Normal file
53
Task/Amb/Haskell/amb-2.hs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
joins :: String -> String -> Bool
|
||||
joins left right = last left == head right
|
||||
|
||||
-- First desugaring (dropping the do notation)
|
||||
-- in terms of the bind operator (>>=) for the list monad
|
||||
|
||||
exampleBind :: String
|
||||
exampleBind =
|
||||
["the", "that", "a"] >>=
|
||||
(\w1 ->
|
||||
["frog", "elephant", "thing"] >>=
|
||||
\w2 ->
|
||||
["walked", "treaded", "grows"] >>=
|
||||
\w3 ->
|
||||
["slowly", "quickly"] >>=
|
||||
(\w4 ->
|
||||
if joins w1 w2
|
||||
then (if joins w2 w3
|
||||
then (if joins w3 w4
|
||||
then unwords [w1, w2, w3, w4]
|
||||
else [])
|
||||
else [])
|
||||
else []))
|
||||
|
||||
-- Second desugaring (still dropping the do notation)
|
||||
-- in terms of the concatMap, which is >>= with its arguments flipped
|
||||
|
||||
exampleConcatMap :: String
|
||||
exampleConcatMap =
|
||||
concatMap
|
||||
(\w1 ->
|
||||
concatMap
|
||||
(\w2 ->
|
||||
concatMap
|
||||
(\w3 ->
|
||||
concatMap
|
||||
(\w4 ->
|
||||
if joins w1 w2
|
||||
then (if joins w2 w3
|
||||
then (if joins w3 w4
|
||||
then unwords [w1, w2, w3, w4]
|
||||
else [])
|
||||
else [])
|
||||
else [])
|
||||
["slowly", "quickly"])
|
||||
["walked", "treaded", "grows"])
|
||||
["frog", "elephant", "thing"])
|
||||
["the", "that", "a"]
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
print exampleBind
|
||||
print exampleConcatMap
|
||||
22
Task/Amb/Haskell/amb-3.hs
Normal file
22
Task/Amb/Haskell/amb-3.hs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
example :: [String]
|
||||
example =
|
||||
["the", "that", "a"] >>=
|
||||
\w1 ->
|
||||
when True ["frog", "elephant", "thing"] >>=
|
||||
\w2 ->
|
||||
when (joins w1 w2) ["walked", "treaded", "grows"] >>=
|
||||
\w3 ->
|
||||
when (joins w2 w3) ["slowly", "quickly"] >>=
|
||||
\w4 -> when (joins w3 w4) [w1, w2, w3, w4]
|
||||
|
||||
joins :: String -> String -> Bool
|
||||
joins left right = last left == head right
|
||||
|
||||
when :: Bool -> [a] -> [a]
|
||||
when p xs =
|
||||
if p
|
||||
then xs
|
||||
else []
|
||||
|
||||
main :: IO ()
|
||||
main = print $ unwords example
|
||||
17
Task/Amb/Haskell/amb-4.hs
Normal file
17
Task/Amb/Haskell/amb-4.hs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
joins :: String -> String -> Bool
|
||||
joins left right = last left == head right
|
||||
|
||||
example :: [String]
|
||||
example =
|
||||
[ unwords [w1, w2, w3, w4]
|
||||
| w1 <- ["the", "that", "a"],
|
||||
w2 <- ["frog", "elephant", "thing"],
|
||||
joins w1 w2,
|
||||
w3 <- ["walked", "treaded", "grows"],
|
||||
joins w2 w3,
|
||||
w4 <- ["slowly", "quickly"],
|
||||
joins w3 w4
|
||||
]
|
||||
|
||||
main :: IO ()
|
||||
main = print example
|
||||
73
Task/Amb/Haxe/amb.haxe
Normal file
73
Task/Amb/Haxe/amb.haxe
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
class RosettaDemo
|
||||
{
|
||||
static var setA = ['the', 'that', 'a'];
|
||||
static var setB = ['frog', 'elephant', 'thing'];
|
||||
static var setC = ['walked', 'treaded', 'grows'];
|
||||
static var setD = ['slowly', 'quickly'];
|
||||
|
||||
static public function main()
|
||||
{
|
||||
Sys.print(ambParse([ setA, setB, setC, setD ]).toString());
|
||||
}
|
||||
|
||||
static function ambParse(sets : Array<Array<String>>)
|
||||
{
|
||||
var ambData : Dynamic = amb(sets);
|
||||
|
||||
for (data in 0...ambData.length)
|
||||
{
|
||||
var tmpData = parseIt(ambData[data]);
|
||||
var tmpArray = tmpData.split(' ');
|
||||
tmpArray.pop();
|
||||
if (tmpArray.length == sets.length)
|
||||
{
|
||||
return tmpData;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
static function amb(startingWith : String = '', sets : Array<Array<String>>) : Dynamic
|
||||
{
|
||||
if (sets.length == 0 || sets[0].length == 0) return;
|
||||
|
||||
var match : Dynamic = [];
|
||||
for (reference in sets[0])
|
||||
{
|
||||
if (startingWith == '' || startingWith == reference.charAt(0))
|
||||
{
|
||||
var lastChar = reference.charAt(reference.length-1);
|
||||
if (Std.is(amb(lastChar, sets.slice(1)), Array))
|
||||
{
|
||||
match.push([ reference, amb(lastChar, sets.slice(1))]);
|
||||
}
|
||||
else
|
||||
{
|
||||
match.push([ reference ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
static function parseIt(data : Dynamic)
|
||||
{
|
||||
var retData = '';
|
||||
if (Std.is(data, Array))
|
||||
{
|
||||
for (elements in 0...data.length)
|
||||
{
|
||||
if (Std.is(data[elements], Array))
|
||||
{
|
||||
retData = retData + parseIt(data[elements]);
|
||||
}
|
||||
else
|
||||
{
|
||||
retData = retData + data[elements] + ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
return retData;
|
||||
}
|
||||
}
|
||||
18
Task/Amb/Icon/amb.icon
Normal file
18
Task/Amb/Icon/amb.icon
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
procedure main()
|
||||
s1 := ["the","that","a"]
|
||||
s2 := ["frog","elephant","thing"]
|
||||
s3 := ["walked","treaded","grows"]
|
||||
s4 := ["slowly","quickly"]
|
||||
|
||||
write(amb(!s1,!s2,!s3,!s4))
|
||||
end
|
||||
|
||||
procedure amb(exprs[])
|
||||
s := ""
|
||||
every e := !exprs do {
|
||||
if \c ~== e[1] then fail
|
||||
c := e[-1]
|
||||
s ||:= e || " "
|
||||
}
|
||||
return s
|
||||
end
|
||||
13
Task/Amb/J/amb-1.j
Normal file
13
Task/Amb/J/amb-1.j
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
ambsel=: <^:99@,
|
||||
|
||||
ambassert=: {{
|
||||
anames=. (#~ 99<:{{L.do y}}@>) (#~ 0=nc)/:~~.;:m
|
||||
limit=. */alimits=. #@> avalues=. {{>^:98 do y}}every anames
|
||||
j=. 0 while. do.
|
||||
(anames)=. test=. (alimits#:j) {each avalues
|
||||
try. do m
|
||||
anames {{(x)=:y}}&> test break.
|
||||
catch. end.
|
||||
if. limit<:j=.j+1 do. assert.'no valid solution' end.
|
||||
end. EMPTY
|
||||
}}
|
||||
10
Task/Amb/J/amb-2.j
Normal file
10
Task/Amb/J/amb-2.j
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
s1=: ambsel;:'the that a'
|
||||
s2=: ambsel;:'frog elephant thing'
|
||||
s3=: ambsel;:'walked treaded grows'
|
||||
s4=: ambsel;:'slowly quickly'
|
||||
edgematch=: {{ x,y assert. ({:;x)={.;y }}
|
||||
{{)n edgematch/ s1,s2,s3,s4 }} ambassert
|
||||
echo s1,s2,s3,s4
|
||||
┌────┬─────┬─────┬──────┐
|
||||
│that│thing│grows│slowly│
|
||||
└────┴─────┴─────┴──────┘
|
||||
53
Task/Amb/JavaScript/amb-1.js
Normal file
53
Task/Amb/JavaScript/amb-1.js
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
function ambRun(func) {
|
||||
var choices = [];
|
||||
var index;
|
||||
|
||||
function amb(values) {
|
||||
if (values.length == 0) {
|
||||
fail();
|
||||
}
|
||||
if (index == choices.length) {
|
||||
choices.push({i: 0,
|
||||
count: values.length});
|
||||
}
|
||||
var choice = choices[index++];
|
||||
return values[choice.i];
|
||||
}
|
||||
|
||||
function fail() { throw fail; }
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
index = 0;
|
||||
return func(amb, fail);
|
||||
} catch (e) {
|
||||
if (e != fail) {
|
||||
throw e;
|
||||
}
|
||||
var choice;
|
||||
while ((choice = choices.pop()) && ++choice.i == choice.count) {}
|
||||
if (choice == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
choices.push(choice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ambRun(function(amb, fail) {
|
||||
function linked(s1, s2) {
|
||||
return s1.slice(-1) == s2.slice(0, 1);
|
||||
}
|
||||
|
||||
var w1 = amb(["the", "that", "a"]);
|
||||
var w2 = amb(["frog", "elephant", "thing"]);
|
||||
if (!linked(w1, w2)) fail();
|
||||
|
||||
var w3 = amb(["walked", "treaded", "grows"]);
|
||||
if (!linked(w2, w3)) fail();
|
||||
|
||||
var w4 = amb(["slowly", "quickly"]);
|
||||
if (!linked(w3, w4)) fail();
|
||||
|
||||
return [w1, w2, w3, w4].join(' ');
|
||||
}); // "that thing grows slowly"
|
||||
55
Task/Amb/JavaScript/amb-2.js
Normal file
55
Task/Amb/JavaScript/amb-2.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
|
||||
// amb :: [a] -> (a -> [b]) -> [b]
|
||||
const amb = xs => f =>
|
||||
xs.reduce((a, x) => a.concat(f(x)), []);
|
||||
|
||||
// when :: Bool -> [a] -> [a]
|
||||
const when = p =>
|
||||
xs => p ? (
|
||||
xs
|
||||
) : [];
|
||||
|
||||
|
||||
// TEST -----------------------------------------------
|
||||
const main = () => {
|
||||
|
||||
// joins :: String -> String -> Bool
|
||||
const joins = (a, b) =>
|
||||
b[0] === last(a);
|
||||
|
||||
console.log(
|
||||
amb(['the', 'that', 'a'])
|
||||
(w1 => when(true)(
|
||||
|
||||
amb(['frog', 'elephant', 'thing'])
|
||||
(w2 => when(joins(w1, w2))(
|
||||
|
||||
amb(['walked', 'treaded', 'grows'])
|
||||
(w3 => when(joins(w2, w3))(
|
||||
|
||||
amb(['slowly', 'quickly'])
|
||||
(w4 => when(joins(w3, w4))(
|
||||
|
||||
unwords([w1, w2, w3, w4])
|
||||
|
||||
))
|
||||
))
|
||||
))
|
||||
))
|
||||
);
|
||||
};
|
||||
|
||||
// GENERIC FUNCTIONS ----------------------------------
|
||||
|
||||
// last :: [a] -> a
|
||||
const last = xs =>
|
||||
0 < xs.length ? xs.slice(-1)[0] : undefined;
|
||||
|
||||
// unwords :: [String] -> String
|
||||
const unwords = xs => xs.join(' ');
|
||||
|
||||
// MAIN ---
|
||||
return main();
|
||||
})();
|
||||
6
Task/Amb/Jq/amb-1.jq
Normal file
6
Task/Amb/Jq/amb-1.jq
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
def amb: .[];
|
||||
|
||||
def joins:
|
||||
(.[0][-1:]) as $left
|
||||
| (.[1][0:1]) as $right
|
||||
| if $left == $right then true else empty end;
|
||||
8
Task/Amb/Jq/amb-2.jq
Normal file
8
Task/Amb/Jq/amb-2.jq
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
(["the","that","a"] | amb) as $word1
|
||||
| (["frog","elephant","thing"] | amb) as $word2
|
||||
| [$word1, $word2] | joins
|
||||
| (["walked","treaded","grows"] | amb) as $word3
|
||||
| [$word2, $word3] | joins
|
||||
| (["slowly","quickly"] | amb) as $word4
|
||||
| [$word3, $word4] | joins
|
||||
| [$word1, $word2, $word3, $word4]
|
||||
7
Task/Amb/Jq/amb-3.jq
Normal file
7
Task/Amb/Jq/amb-3.jq
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
jq -n -f amb.jq
|
||||
[
|
||||
"that",
|
||||
"thing",
|
||||
"grows",
|
||||
"slowly"
|
||||
]
|
||||
6
Task/Amb/Jq/amb-4.jq
Normal file
6
Task/Amb/Jq/amb-4.jq
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
def amb(condition): .[] | select(condition);
|
||||
|
||||
def joins:
|
||||
(.[0][-1:]) as $left
|
||||
| (.[1][0:1]) as $right
|
||||
| $left == $right ;
|
||||
5
Task/Amb/Jq/amb-5.jq
Normal file
5
Task/Amb/Jq/amb-5.jq
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
(["the","that","a"] | amb(true)) as $word1
|
||||
| (["frog","elephant","thing"] | amb( [$word1, .] | joins)) as $word2
|
||||
| (["walked","treaded","grows"] | amb( [$word2, .] | joins)) as $word3
|
||||
| (["slowly","quickly"] | amb( [$word3, .] | joins)) as $word4
|
||||
| [$word1, $word2,$word3, $word4]
|
||||
56
Task/Amb/Julia/amb-1.julia
Normal file
56
Task/Amb/Julia/amb-1.julia
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# This is a general purpose AMB function that takes a two-argument failure function and
|
||||
# arbitrary number of iterable objects and returns the first solution found as an array
|
||||
# this function is in essence an iterative backtracking solver
|
||||
|
||||
function amb(failure, itrs...)
|
||||
n = length(itrs)
|
||||
if n == 1 return end
|
||||
states = Vector(n)
|
||||
values = Vector(n)
|
||||
# starting point, we put down the first value from the first iterable object
|
||||
states[1] = start(itrs[1])
|
||||
values[1], states[1] = next(itrs[1], states[1])
|
||||
i = 1
|
||||
# main solver loop
|
||||
while true
|
||||
# test for failure
|
||||
if i > 1 && failure(values[i-1], values[i])
|
||||
# loop for generating a new value upon failure
|
||||
# in fact this would be way more readable using goto, but Julia doesn't seem to have that :(
|
||||
while true
|
||||
# if we failed, we must generate a new value, but first we must check whether there is any
|
||||
if done(itrs[i], states[i])
|
||||
# backtracking step with sanity check in case we ran out of values from the current generator
|
||||
if i == 1
|
||||
return
|
||||
else
|
||||
i -= 1
|
||||
continue
|
||||
end
|
||||
else
|
||||
# if there is indeed a new value, generate it
|
||||
values[i], states[i] = next(itrs[i], states[i])
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
# no failure branch
|
||||
# if solution is ready (i.e. all generators are used) just return it
|
||||
if i == n return values end
|
||||
# else start up the next generator
|
||||
i += 1
|
||||
states[i] = start(itrs[i])
|
||||
values[i], states[i] = next(itrs[i], states[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Call our generic AMB function according to the task description and
|
||||
# form the solution sentence from the returned array of words
|
||||
amb((s1,s2) -> s1[end] != s2[1], # failure function
|
||||
["the", "that", "a"],
|
||||
["frog", "elephant", "thing"],
|
||||
["walked", "treaded", "grows"],
|
||||
["slowly", "quickly"]) |>
|
||||
x -> join(x, " ") |>
|
||||
println
|
||||
2
Task/Amb/Julia/amb-2.julia
Normal file
2
Task/Amb/Julia/amb-2.julia
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
iter = Iterators.product(["the", "that", "a"], ["frog", "elephant", "thing"], ["walked", "treaded", "grows"], ["slowly", "quickly"])
|
||||
@show [join(c, " ") for c in iter if all(i -> c[i][end] == c[i + 1][begin], 1:length(c)-1)] # ["that thing grows slowly"]
|
||||
104
Task/Amb/Kotlin/amb.kotlin
Normal file
104
Task/Amb/Kotlin/amb.kotlin
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// version 1.2.41
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun main(args: Array<String>) = amb {
|
||||
val a = amb("the", "that", "a")
|
||||
val b = amb("frog", "elephant", "thing")
|
||||
val c = amb("walked", "treaded", "grows")
|
||||
val d = amb("slowly", "quickly")
|
||||
|
||||
if (a[a.lastIndex] != b[0]) amb()
|
||||
if (b[b.lastIndex] != c[0]) amb()
|
||||
if (c[c.lastIndex] != d[0]) amb()
|
||||
|
||||
println(listOf(a, b, c, d))
|
||||
|
||||
|
||||
val x = amb(1, 2, 3)
|
||||
val y = amb(7, 6, 4, 5)
|
||||
if (x * y != 8) amb()
|
||||
println(listOf(x, y))
|
||||
}
|
||||
|
||||
|
||||
class AmbException(): Exception("Refusing to execute")
|
||||
data class AmbPair<T>(val cont: Continuation<T>, val valuesLeft: MutableList<T>)
|
||||
|
||||
@RestrictsSuspension
|
||||
class AmbEnvironment {
|
||||
val ambList = mutableListOf<AmbPair<*>>()
|
||||
|
||||
suspend fun <T> amb(value: T, vararg rest: T): T = suspendCoroutineOrReturn { cont ->
|
||||
if (rest.size > 0) {
|
||||
ambList.add(AmbPair(clone(cont), mutableListOf(*rest)))
|
||||
}
|
||||
|
||||
value
|
||||
}
|
||||
|
||||
suspend fun amb(): Nothing = suspendCoroutine<Nothing> { }
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <R> amb(block: suspend AmbEnvironment.() -> R): R {
|
||||
var result: R? = null
|
||||
var toThrow: Throwable? = null
|
||||
|
||||
val dist = AmbEnvironment()
|
||||
block.startCoroutine(receiver = dist, completion = object : Continuation<R> {
|
||||
override val context: CoroutineContext get() = EmptyCoroutineContext
|
||||
override fun resume(value: R) { result = value }
|
||||
override fun resumeWithException(exception: Throwable) { toThrow = exception }
|
||||
})
|
||||
|
||||
while (result == null && toThrow == null && !dist.ambList.isEmpty()) {
|
||||
val last = dist.ambList.run { this[lastIndex] }
|
||||
|
||||
if (last.valuesLeft.size == 1) {
|
||||
dist.ambList.removeAt(dist.ambList.lastIndex)
|
||||
last.apply {
|
||||
(cont as Continuation<Any?>).resume(valuesLeft[0])
|
||||
}
|
||||
} else {
|
||||
val value = last.valuesLeft.removeAt(last.valuesLeft.lastIndex)
|
||||
(clone(last.cont) as Continuation<Any?>).resume(value)
|
||||
}
|
||||
}
|
||||
|
||||
if (toThrow != null)
|
||||
{
|
||||
throw toThrow!!
|
||||
}
|
||||
else if (result != null)
|
||||
{
|
||||
return result!!
|
||||
}
|
||||
else
|
||||
{
|
||||
throw AmbException()
|
||||
}
|
||||
}
|
||||
|
||||
val UNSAFE = Class.forName("sun.misc.Unsafe")
|
||||
.getDeclaredField("theUnsafe")
|
||||
.apply { isAccessible = true }
|
||||
.get(null) as sun.misc.Unsafe
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T: Any> clone(obj: T): T {
|
||||
val clazz = obj::class.java
|
||||
val copy = UNSAFE.allocateInstance(clazz) as T
|
||||
copyDeclaredFields(obj, copy, clazz)
|
||||
return copy
|
||||
}
|
||||
|
||||
tailrec fun <T> copyDeclaredFields(obj: T, copy: T, clazz: Class<out T>) {
|
||||
for (field in clazz.declaredFields) {
|
||||
field.isAccessible = true
|
||||
val v = field.get(obj)
|
||||
field.set(copy, if (v === obj) copy else v)
|
||||
}
|
||||
val superclass = clazz.superclass
|
||||
if (superclass != null) copyDeclaredFields(obj, copy, superclass)
|
||||
}
|
||||
15
Task/Amb/Langur/amb.langur
Normal file
15
Task/Amb/Langur/amb.langur
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
val .wordsets = [
|
||||
w/the that a/,
|
||||
w/frog elephant thing/,
|
||||
w/walked treaded grows/,
|
||||
w/slowly quickly/,
|
||||
]
|
||||
|
||||
val .alljoin = f(.words) for[=true] .i of len(.words)-1 {
|
||||
if last(.words[.i]) != first(.words[.i+1]): break = false
|
||||
}
|
||||
|
||||
# .amb expects 2 or more arguments
|
||||
val .amb = f(...[2 .. -1] .words) if(.alljoin(.words): join " ", .words)
|
||||
|
||||
writeln join "\n", filter(mapX(.amb, .wordsets...))
|
||||
83
Task/Amb/Latitude/amb-1.latitude
Normal file
83
Task/Amb/Latitude/amb-1.latitude
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
;; This is the exception that will be thrown if an amb expression is
|
||||
;; unsatisfiable.
|
||||
AmbError ::= Exception clone tap {
|
||||
|
||||
self message := "Amb expression failed".
|
||||
|
||||
AmbError := self.
|
||||
|
||||
}.
|
||||
|
||||
;; The Amb object itself is primarily for internal use. It stores the
|
||||
;; "next" backtracking point if an amb expression outright fails or
|
||||
;; exhausts its possibilities at some point.
|
||||
Amb ::= Object clone tap {
|
||||
|
||||
;; The default "next" point is to throw an exception. This will be
|
||||
;; overridden in many cases, if there is an actual next handler to
|
||||
;; jump to.
|
||||
self nextHandler := { AmbError clone throw. }.
|
||||
|
||||
Amb := self.
|
||||
|
||||
}.
|
||||
|
||||
callAmb := {
|
||||
;; We need an object which will be accessible from inside the
|
||||
;; continuations that will store the next backtracking point which
|
||||
;; will be called.
|
||||
backtracker := Amb clone.
|
||||
;; We define the dynamically-scoped method $amb which will try each
|
||||
;; possibility that it is given. If all of those possibilities fail,
|
||||
;; it will call the next handler.
|
||||
$amb := {
|
||||
takes '[cases].
|
||||
;; This is the return point. We're going to try each element of
|
||||
;; the cases variable (probably an array, but it could feasibly be
|
||||
;; any collection type). For each element, we'll jump to this
|
||||
;; point (which will wind up being the end of the $amb method). If
|
||||
;; it ends up failing, the backtrack point will get called and
|
||||
;; we'll try the next one.
|
||||
callCC {
|
||||
escapable.
|
||||
;; Get the current backtrack point from the toplevel object and
|
||||
;; store it within this continuation. The backtrack object's
|
||||
;; current backtrack point will change as we make new attempts,
|
||||
;; but this prevHandler variable is stored locally in this scope
|
||||
;; and will not change, so we can always use it later.
|
||||
prevHandler := #'(backtracker nextHandler).
|
||||
;; We iterate over the collection to try each element.
|
||||
cases visit {
|
||||
takes '[curr].
|
||||
callCC {
|
||||
;; This inner continuation will be our new backtrack point.
|
||||
;; We store the continuation object itself in the backtrack
|
||||
;; object so that future $amb calls know to return to this
|
||||
;; point if something goes wrong.
|
||||
nextExit := #'$1.
|
||||
backtracker nextHandler := { nextExit call (Nil). }.
|
||||
;; Now we actually try the value by jumping to the end of
|
||||
;; the $amb method and returning control to the caller.
|
||||
return (curr).
|
||||
}.
|
||||
}.
|
||||
;; If we exhaust each possibility, then that means every value
|
||||
;; in the cases variable has been tried and has failed. So we
|
||||
;; set the backtrack point back to what it was before we tried
|
||||
;; all of these values, and then we jump back to that previous
|
||||
;; backtrack point.
|
||||
backtracker nextHandler := #'(prevHandler).
|
||||
prevHandler.
|
||||
;; prevHandler will always either perform a continuation jump
|
||||
;; (if there is a new backtrack point to try) or throw an
|
||||
;; exception (if we've exhausted all possibilities), so this
|
||||
;; continuation block will never exit normally.
|
||||
}.
|
||||
}.
|
||||
;; An instant failure at a point in an amb expression is equivalent
|
||||
;; to an $amb call on an empty collection.
|
||||
$fail := { $amb (Nil). }.
|
||||
;; Now that the dynamic variables are in place, let's call the
|
||||
;; block.
|
||||
#'($1) call.
|
||||
}.
|
||||
6
Task/Amb/Latitude/amb-2.latitude
Normal file
6
Task/Amb/Latitude/amb-2.latitude
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
callAmb {
|
||||
x := $amb [1, 2, 3, 4].
|
||||
y := $amb [7, 6, 4, 5].
|
||||
(x * y == 8 ) ifFalse { $fail. }. ;; Note: $fail is equivalent to $amb [].
|
||||
println [x, y]. ;; [2, 4]
|
||||
}.
|
||||
21
Task/Amb/Lua/amb-1.lua
Normal file
21
Task/Amb/Lua/amb-1.lua
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
function amb (set)
|
||||
local workset = {}
|
||||
if (#set == 0) or (type(set) ~= 'table') then return end
|
||||
if #set == 1 then return set end
|
||||
if #set > 2 then
|
||||
local first = table.remove(set,1)
|
||||
set = amb(set)
|
||||
for i,v in next,first do
|
||||
for j,u in next,set do
|
||||
if v:byte(#v) == u[1]:byte(1) then table.insert(workset, {v,unpack(u)}) end
|
||||
end
|
||||
end
|
||||
return workset
|
||||
end
|
||||
for i,v in next,set[1] do
|
||||
for j,u in next,set[2] do
|
||||
if v:byte(#v) == u:byte(1) then table.insert(workset,{v,u}) end
|
||||
end
|
||||
end
|
||||
return workset
|
||||
end
|
||||
8
Task/Amb/Lua/amb-2.lua
Normal file
8
Task/Amb/Lua/amb-2.lua
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
result = amb({{'the','that','a'},{'frog','elephant','thing'},{'walked','treaded','grows'},{'slowly','quickly'}})
|
||||
for i,v in next,result do
|
||||
io.write (i,':\t')
|
||||
for j,u in next,v do
|
||||
io.write (u,' ')
|
||||
end
|
||||
io.write ('\n')
|
||||
end
|
||||
21
Task/Amb/Lua/amb-3.lua
Normal file
21
Task/Amb/Lua/amb-3.lua
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
function T(t) return setmetatable(t, {__index=table}) end
|
||||
table.each = function(t,f) for i=1,#t do f(t[i]) end return t end
|
||||
table.map = function(t,f) local s=T{} for i=1,#t do s[i]=f(t[i]) end return s end
|
||||
table.clone = function(t) local s=T{} for k,v in ipairs(t) do s[k]=v end return s end
|
||||
table.filter = function(t,f) local s=T{} for i=1,#t do if f(t[i]) then s[#s+1]=t[i] end end return s end
|
||||
|
||||
function Amb(f, ...)
|
||||
local function cartprod(...)
|
||||
local sets, temp, prod = {...}, T{}, T{}
|
||||
local function descend(depth)
|
||||
for k,v in pairs(sets[depth]) do
|
||||
temp[depth] = v
|
||||
if (depth==#sets) then prod[#prod+1] = temp:clone() else descend(depth+1) end
|
||||
temp[depth] = nil
|
||||
end
|
||||
end
|
||||
descend(1)
|
||||
return prod
|
||||
end
|
||||
return type(f)=='function' and cartprod(...):filter(f) or {f,...}
|
||||
end
|
||||
69
Task/Amb/Lua/amb-4.lua
Normal file
69
Task/Amb/Lua/amb-4.lua
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
print("Per task requirements:")
|
||||
w1 = Amb('the','that','a')
|
||||
w2 = Amb('frog','elephant','thing')
|
||||
w3 = Amb('walked','treaded','grows')
|
||||
w4 = Amb('slowly','quickly')
|
||||
function rule(t) local a,b,c,d = unpack(t) return a:byte(#a)==b:byte(1) and b:byte(#b)==c:byte(1) and c:byte(#c)==d:byte(1) end
|
||||
answers = Amb(rule, w1, w2, w3, w4)
|
||||
answers:map(function(t) return t:concat(" ") end):each(print)
|
||||
|
||||
print()
|
||||
|
||||
print("Modified task, seek equal length of words:")
|
||||
w1 = Amb('the','that','a','which')
|
||||
w2 = Amb('red','green','blue','yellow')
|
||||
w3 = Amb('frog','elephant','cow','thing')
|
||||
w4 = Amb('walked','treaded','grew','shrunk')
|
||||
w5 = Amb('slow','quick','moderately')
|
||||
function rule(t) local a,b,c,d,e = unpack(t) return #a==#b and #b==#c and #c==#d and #d==#e end
|
||||
answers = Amb(rule, w1, w2, w3, w4, w5)
|
||||
answers:map(function(t) return t:concat(" ") end):each(print)
|
||||
|
||||
print()
|
||||
|
||||
print("Modified example, seek product of 12:")
|
||||
x = Amb(1,2,3)
|
||||
y = Amb(4,5,6)
|
||||
function rule(t) local x,y = unpack(t) return x*y==12 end
|
||||
answers = Amb(rule, x, y)
|
||||
answers:map(function(t) return t:concat(" ") end):each(print)
|
||||
|
||||
print()
|
||||
|
||||
print("Pythagorean triples:")
|
||||
x = Amb(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
|
||||
y = Amb(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
|
||||
z = Amb(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
|
||||
function rule(t) local x,y,z = unpack(t) return x^2 + y^2 == z^2 end
|
||||
answers = Amb(rule, x, y, z)
|
||||
answers:map(function(t) return t:concat(" ") end):each(print)
|
||||
|
||||
print()
|
||||
|
||||
print("When there is no solution:")
|
||||
x = Amb(1,2,3)
|
||||
y = Amb(4,5,6)
|
||||
function rule(t) local x,y = unpack(t) return x*y==7 end
|
||||
answers = Amb(rule, x, y, z)
|
||||
print("#answers = " .. #answers)
|
||||
|
||||
print()
|
||||
|
||||
print("send + more = money:")
|
||||
-- intuitive simplification applied: m must be 1 ==> others may not be 1 (reduces complexity from 10^8 to 9^7)
|
||||
-- ("m is allowed to be leading zero" solutions exist, e.g. 2 8 1 7 0 3 6 5, and this could find them, but why?)
|
||||
s = Amb(0,2,3,4,5,6,7,8,9)
|
||||
e = Amb(0,2,3,4,5,6,7,8,9)
|
||||
n = Amb(0,2,3,4,5,6,7,8,9)
|
||||
d = Amb(0,2,3,4,5,6,7,8,9)
|
||||
m = Amb(1)
|
||||
o = Amb(0,2,3,4,5,6,7,8,9)
|
||||
r = Amb(0,2,3,4,5,6,7,8,9)
|
||||
y = Amb(0,2,3,4,5,6,7,8,9)
|
||||
function rule(t)
|
||||
for i=1,#t do for j=i+1,#t do if t[i]==t[j] then return false end end end
|
||||
local s,e,n,d,m,o,r,y = unpack(t)
|
||||
return s*1000 + e*100 + 10*n + d + m*1000 + o*100 + r*10 + e == m*10000 + o*1000 + n*100 + e*10 + y
|
||||
end
|
||||
answers = Amb(rule, s, e, n, d, m, o, r, y)
|
||||
answers:map(function(t) return t:concat(" ") end):each(print)
|
||||
77
Task/Amb/M2000-Interpreter/amb-1.m2000
Normal file
77
Task/Amb/M2000-Interpreter/amb-1.m2000
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
Module AmbFunction {
|
||||
Function Amb (failure) {
|
||||
// get an array of s items, return an array of 1 item
|
||||
// we do this so we forget the type of element
|
||||
getitem=lambda (n, c) -> {
|
||||
dim z(1) :link c to c()
|
||||
stock c(n) keep 1, z(0) // copy from c(n) to z(0) one item
|
||||
=z()
|
||||
}
|
||||
read a
|
||||
c1=lambda a, getitem (i, &any, &ret) ->{
|
||||
any=getitem(i, a)
|
||||
ret=any
|
||||
=true
|
||||
}
|
||||
m=stack.size
|
||||
if m=0 then Error "At least two arrays needed"
|
||||
c=c1
|
||||
while m>1 {
|
||||
read b
|
||||
c1=lambda c2=c, j=0, m=len(a), b, failure, getitem (i, &any, &ret) ->{
|
||||
any=getitem(i, b)
|
||||
ret=(,) : ok=false : anyother=(,)
|
||||
do
|
||||
if c2(j, &anyother, &ret) then
|
||||
if not failure(any, anyother) then
|
||||
ok=true
|
||||
ret=cons(ret, any)
|
||||
end if
|
||||
end if
|
||||
j++
|
||||
until ok or j=m
|
||||
if j=m then j=0
|
||||
=ok
|
||||
}
|
||||
c=c1 : a=b : m--
|
||||
}
|
||||
read b
|
||||
amb1=lambda c2=c, j=0, m=len(a), b, failure, getitem (&ret) ->{
|
||||
ret=(,) : ok=false: anyother=(,)
|
||||
k=each(b)
|
||||
while k
|
||||
any=getitem(k^, b)
|
||||
do
|
||||
if c2(j, &anyother, &ret) then
|
||||
if not failure(any, anyother) then
|
||||
ok=true
|
||||
ret=cons(ret, any)
|
||||
end if
|
||||
end if
|
||||
j++
|
||||
until ok or j=m
|
||||
if j=m then j=0
|
||||
if ok then exit
|
||||
end while
|
||||
=ok
|
||||
}
|
||||
ret=(,)
|
||||
if amb1(&ret) then =ret else =(,) ' default return value
|
||||
}
|
||||
|
||||
a=(1, 2, 3)
|
||||
b=(7, 6, 4, 5)
|
||||
failure=lambda (a,b)->{
|
||||
=a#val(0)*b#val(0)<>8
|
||||
}
|
||||
Print amb(failure, a, b)#str$()
|
||||
a=("the", "that", "a")
|
||||
b=("frog", "elephant", "thing")
|
||||
c=("walked", "treaded", "grows")
|
||||
d=("slowly", "quickly")
|
||||
failure=lambda (a,b)->{
|
||||
=left$(a#val$(0),1)<>right$(b#val$(0),1)
|
||||
}
|
||||
Print amb(failure, a, b, c, d)#str$()
|
||||
}
|
||||
AmbFunction
|
||||
102
Task/Amb/M2000-Interpreter/amb-2.m2000
Normal file
102
Task/Amb/M2000-Interpreter/amb-2.m2000
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
Module AmbFunction {
|
||||
Enum Solution {First, Any=-1}
|
||||
Function Amb(way as Solution, failure) {
|
||||
// get an array of s items, return an array of 1 item
|
||||
// we do this so we forget the type of element
|
||||
getitem=lambda (n, c) -> {
|
||||
dim z(1) :link c to c()
|
||||
stock c(n) keep 1, z(0) // copy from c(n) to z(0) one item
|
||||
=z()
|
||||
}
|
||||
read a
|
||||
c1=lambda i=0, a, getitem (&any, &ret) ->{
|
||||
any=getitem(i, a)
|
||||
ret=any
|
||||
i++
|
||||
ok=i=len(a)
|
||||
if ok then i=0
|
||||
=ok
|
||||
}
|
||||
m=stack.size
|
||||
if m=0 then Error "At least two arrays needed"
|
||||
c=c1
|
||||
while m>0 {
|
||||
read a
|
||||
c1=lambda c2=c, i=0, a, getitem (&any, &ret) ->{
|
||||
any=getitem(i, a)
|
||||
ret=(,) : ok=false : anyother=(,)
|
||||
ok=c2(&anyother, &ret)
|
||||
ret=cons(ret, any)
|
||||
if ok then i++
|
||||
ok=i=len(a)
|
||||
if ok then i=0
|
||||
=ok
|
||||
}
|
||||
c=c1 : m--
|
||||
}
|
||||
ok=false
|
||||
any=(,)
|
||||
flush
|
||||
while not ok
|
||||
ret=(,)
|
||||
ok=c(&any, &ret)
|
||||
s=stack(ret)
|
||||
if not failure(! s) then data ret : if way>0 then ok=true
|
||||
End While
|
||||
if empty then
|
||||
ret=(("",),)
|
||||
else
|
||||
ret=array([])
|
||||
end if
|
||||
=ret
|
||||
}
|
||||
|
||||
a=(1, 2, 3)
|
||||
b=(7, 6, 4, 5)
|
||||
failure=lambda (a,b)->{
|
||||
=a*b<>8
|
||||
}
|
||||
Print Amb(First, failure, a, b)#val(0)#str$()
|
||||
a=("the", "that", "a")
|
||||
b=("frog", "elephant", "thing")
|
||||
c=("walked", "treaded", "grows")
|
||||
d=("slowly", "quickly")
|
||||
failure=lambda (a$, b$, c$, d$)->{
|
||||
def amb(x$, y$)=right$(x$,1)<>left$(y$,1)
|
||||
=amb(a$,b$) or amb(b$,c$) or amb(c$, d$)
|
||||
}
|
||||
Print amb(First, failure, a, b, c, d)#Val(0)#str$()
|
||||
Range=lambda (a, f) ->{
|
||||
for i=a to f-1: data i: next
|
||||
=array([])
|
||||
}
|
||||
Print "Small Pythagorean triples problem:"
|
||||
a=range(1,11)
|
||||
failure=lambda (a, b, z)->{
|
||||
=not (a^2+b^2=z^2 and b>a)
|
||||
}
|
||||
all=amb(Any,failure, a, a, a)
|
||||
k=each(all)
|
||||
while k
|
||||
z=array(k)
|
||||
Print z#str$()
|
||||
end while
|
||||
a=range(1,6)
|
||||
c=range(0,6)
|
||||
N=9
|
||||
failure=lambda N (a, b, c, d, e)->{
|
||||
=not (a+b+c+d+e=N and a>=b and b>=c and c>=d and d>=e)
|
||||
}
|
||||
all=amb(Any,failure, a, a, c, c, c)
|
||||
k=each(all)
|
||||
document ret$
|
||||
while k
|
||||
z=array(k)
|
||||
ret$=replace$("+0", " ", z#str$("+"))+" ="+str$(N)+{
|
||||
}
|
||||
end while
|
||||
Sort descending ret$
|
||||
Print #-2, ret$
|
||||
clipboard ret$
|
||||
}
|
||||
AmbFunction
|
||||
3
Task/Amb/Mathematica/amb-1.math
Normal file
3
Task/Amb/Mathematica/amb-1.math
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
CheckValid[i_List]:=If[Length[i]<=1,True,And@@(StringTake[#[[1]],-1]==StringTake[#[[2]],1]&/@Partition[i,2,1])]
|
||||
sets={{"the","that","a"},{"frog","elephant","thing"},{"walked","treaded","grows"},{"slowly","quickly"}};
|
||||
Select[Tuples[sets],CheckValid]
|
||||
1
Task/Amb/Mathematica/amb-2.math
Normal file
1
Task/Amb/Mathematica/amb-2.math
Normal file
|
|
@ -0,0 +1 @@
|
|||
{{"that", "thing", "grows", "slowly"}}
|
||||
1
Task/Amb/Mathematica/amb-3.math
Normal file
1
Task/Amb/Mathematica/amb-3.math
Normal file
|
|
@ -0,0 +1 @@
|
|||
CheckValid2[i_List] := StringFreeQ[StringJoin[Riffle[i, ","]], a_ ~~ "," ~~ b_ /; a =!= b]
|
||||
25
Task/Amb/Mercury/amb-1.mercury
Normal file
25
Task/Amb/Mercury/amb-1.mercury
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
:- module amb.
|
||||
:- interface.
|
||||
:- import_module io.
|
||||
:- pred main(io::di, io::uo) is cc_multi.
|
||||
:- implementation.
|
||||
:- import_module list, string, char, int.
|
||||
|
||||
main(!IO) :-
|
||||
( solution(S) -> io.write_string(S, !IO), io.nl(!IO)
|
||||
; io.write_string("No solutions found :-(\n", !IO) ).
|
||||
|
||||
:- pred solution(string::out) is nondet.
|
||||
solution(S) :-
|
||||
member(A, ["the", "that", "a"]),
|
||||
member(N, ["frog", "elephant", "thing"]),
|
||||
member(V, ["walked", "treaded", "grows"]),
|
||||
member(E, ["slowly", "quickly"]),
|
||||
S = join_list(" ", [A, N, V, E]),
|
||||
rule1(A, N), rule1(N, V), rule1(V, E).
|
||||
|
||||
:- pred rule1(string::in, string::in) is semidet.
|
||||
rule1(A, B) :- last_char(A) = C, first_char(B, C, _).
|
||||
|
||||
:- func last_char(string::in) = (char::out) is semidet.
|
||||
last_char(S) = C :- index(S, length(S) - 1, C).
|
||||
6
Task/Amb/Mercury/amb-2.mercury
Normal file
6
Task/Amb/Mercury/amb-2.mercury
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
:- pred noun(string).
|
||||
:- mode noun(out) is multi. % provide any one noun.
|
||||
:- mode noun(in) is semidet. % fail if given string isn't a known noun.
|
||||
noun("frog").
|
||||
noun("elephant").
|
||||
noun("thing").
|
||||
71
Task/Amb/NetRexx/amb.netrexx
Normal file
71
Task/Amb/NetRexx/amb.netrexx
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* REXX **************************************************************
|
||||
* 25.08.2013 Walter Pachl derived from REXX version 2
|
||||
*********************************************************************/
|
||||
w=''
|
||||
l=0
|
||||
mm=0
|
||||
mkset(1,'the that a if',w,mm,l)
|
||||
mkset(2,'frog elephant thing',w,mm,l)
|
||||
mkset(3,'walked treaded grows trots',w,mm,l)
|
||||
mkset(4,'slowly quickly',w,mm,l)
|
||||
show(w,mm,l)
|
||||
|
||||
Loop i=1 to 3 /* loop over sets */
|
||||
k=i+1 /* the following set */
|
||||
Loop ii=1 To 10 /* loop over elements in set k*/
|
||||
If w[i,ii].words=i Then Do /* a sentence part found */
|
||||
Loop jj=1 To 10 /* loop over following words */
|
||||
If w[i,ii].right(1)=w[k,jj].left(1) Then Do /* fitting */
|
||||
ns=w[i,ii]' 'w[k,jj] /* build new sentence (part) */
|
||||
If ns.words=k Then /* 'complete' part */
|
||||
add(w,k,ns) /* add to set k */
|
||||
End
|
||||
End
|
||||
End
|
||||
End
|
||||
End
|
||||
Say 'Results:'
|
||||
Loop jj=1 To 10 /* show the results */
|
||||
If w[4,jj].words=4 Then
|
||||
Say '-->' w[4,jj]
|
||||
End
|
||||
|
||||
method add(w,k,s) public static
|
||||
/*********************************************************************
|
||||
* add a fitting sentence (part) s to set w[k,*]
|
||||
*********************************************************************/
|
||||
Loop i=1 To 10 While w[k,i]>'' /* look for an empty slot */
|
||||
End
|
||||
w[k,i]=s /* add the sentence (part) */
|
||||
Return
|
||||
|
||||
method mkset(n,arg,smp,mm,l) public static
|
||||
/*********************************************************************
|
||||
* create set smp[n,*] from data in arg
|
||||
* mm[0] maximum number of elements in any set
|
||||
* l[n] maximum word length in set n
|
||||
*********************************************************************/
|
||||
loop i = 1 to arg.words
|
||||
smp[n,i] = arg.word(i)
|
||||
If smp[n,i].length>l[n] Then
|
||||
l[n]=smp[n,i].length
|
||||
end
|
||||
if i-1>mm[0] Then Do
|
||||
mm[0]=i-1
|
||||
End
|
||||
return
|
||||
|
||||
method show(w,mm,l) public static
|
||||
/*********************************************************************
|
||||
* show the input
|
||||
*********************************************************************/
|
||||
Say 'Input:'
|
||||
Loop j=1 To mm[0] /* output lines */
|
||||
ol=''
|
||||
Loop i=1 To 4
|
||||
ol=ol w[i,j].left(l[i])
|
||||
End
|
||||
Say ol.strip
|
||||
End;
|
||||
say ''
|
||||
Return
|
||||
33
Task/Amb/Nim/amb.nim
Normal file
33
Task/Amb/Nim/amb.nim
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import sugar, strutils
|
||||
|
||||
proc amb(comp: proc(a, b: string): bool,
|
||||
options: seq[seq[string]],
|
||||
prev: string = ""): seq[string] =
|
||||
|
||||
if options.len == 0: return @[]
|
||||
|
||||
for opt in options[0]:
|
||||
# If this is the base call, prev is nil and we need to continue.
|
||||
if prev.len != 0 and not comp(prev, opt): continue
|
||||
|
||||
# Take care of the case where we have no options left.
|
||||
if options.len == 1: return @[opt]
|
||||
|
||||
# Traverse into the tree.
|
||||
let res = amb(comp, options[1..options.high], opt)
|
||||
|
||||
# If it was a failure, try the next one.
|
||||
if res.len > 0: return opt & res # We have a match.
|
||||
|
||||
return @[]
|
||||
|
||||
const sets = @[@["the", "that", "a"],
|
||||
@["frog", "elephant", "thing"],
|
||||
@["walked", "treaded", "grows"],
|
||||
@["slowly", "quickly"]]
|
||||
|
||||
let result = amb((s, t: string) => (s[s.high] == t[0]), sets)
|
||||
if result.len == 0:
|
||||
echo "No matches found!"
|
||||
else:
|
||||
echo result.join " "
|
||||
36
Task/Amb/OCaml/amb-1.ocaml
Normal file
36
Task/Amb/OCaml/amb-1.ocaml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
let set_1 = ["the"; "that"; "a"]
|
||||
let set_2 = ["frog"; "elephant"; "thing"]
|
||||
let set_3 = ["walked"; "treaded"; "grows"]
|
||||
let set_4 = ["slowly"; "quickly"]
|
||||
|
||||
let combs ll =
|
||||
let rec aux acc = function
|
||||
| [] -> (List.map List.rev acc)
|
||||
| hd::tl ->
|
||||
let acc =
|
||||
List.fold_left
|
||||
(fun _ac l ->
|
||||
List.fold_left (fun _ac v -> (v::l)::_ac) _ac hd
|
||||
) [] acc
|
||||
in
|
||||
aux acc tl
|
||||
in
|
||||
aux [[]] ll
|
||||
|
||||
let last s = s.[pred(String.length s)]
|
||||
let joined a b = (last a = b.[0])
|
||||
|
||||
let rec test = function
|
||||
| a::b::tl -> (joined a b) && (test (b::tl))
|
||||
| _ -> true
|
||||
|
||||
let print_set set =
|
||||
List.iter (Printf.printf " %s") set;
|
||||
print_newline();
|
||||
;;
|
||||
|
||||
let () =
|
||||
let sets = combs [set_1; set_2; set_3; set_4] in
|
||||
let sets = List.filter test sets in
|
||||
List.iter print_set sets;
|
||||
;;
|
||||
51
Task/Amb/OCaml/amb-2.ocaml
Normal file
51
Task/Amb/OCaml/amb-2.ocaml
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
let set_1 = [| "the"; "that"; "a" |]
|
||||
let set_2 = [| "frog"; "elephant"; "thing" |]
|
||||
let set_3 = [| "walked"; "treaded"; "grows" |]
|
||||
let set_4 = [| "slowly"; "quickly" |]
|
||||
|
||||
let comb_search p aa =
|
||||
let nx = Array.make (Array.length aa) 0 in
|
||||
let lx = Array.map Array.length aa in
|
||||
let la = Array.length aa in
|
||||
let rec loop() =
|
||||
let res = Array.mapi (fun i j -> aa.(i).(j)) nx in
|
||||
if p res then (res)
|
||||
else
|
||||
( nx.(0) <- nx.(0) + 1;
|
||||
if nx.(0) < lx.(0)
|
||||
then loop()
|
||||
else
|
||||
( nx.(0) <- 0;
|
||||
let rec roll n =
|
||||
if n >= la then raise Not_found
|
||||
else
|
||||
( nx.(n) <- nx.(n) + 1;
|
||||
if nx.(n) >= lx.(n)
|
||||
then ( nx.(n) <- 0; roll (n+1) )
|
||||
else loop()
|
||||
)
|
||||
in
|
||||
roll 1
|
||||
)
|
||||
)
|
||||
in
|
||||
loop()
|
||||
|
||||
let last s = s.[pred(String.length s)]
|
||||
let joined a b = (last a = b.[0])
|
||||
|
||||
let rec test = function
|
||||
| a::b::tl -> (joined a b) && (test (b::tl))
|
||||
| _ -> true
|
||||
|
||||
let test r = test(Array.to_list r)
|
||||
|
||||
let print_set set =
|
||||
Array.iter (Printf.printf " %s") set;
|
||||
print_newline();
|
||||
;;
|
||||
|
||||
let () =
|
||||
let result = comb_search test [| set_1; set_2; set_3; set_4 |] in
|
||||
print_set result;
|
||||
;;
|
||||
36
Task/Amb/OpenEdge-Progress/amb.openedge
Normal file
36
Task/Amb/OpenEdge-Progress/amb.openedge
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
DEF VAR cset AS CHAR EXTENT 4 INIT [
|
||||
"the,that,a",
|
||||
"frog,elephant,thing",
|
||||
"walked,treaded,grows",
|
||||
"slowly,quickly"
|
||||
].
|
||||
|
||||
FUNCTION getAmb RETURNS CHARACTER (
|
||||
i_cwords AS CHAR,
|
||||
i_iset AS INT
|
||||
):
|
||||
|
||||
DEF VAR cresult AS CHAR.
|
||||
DEF VAR ii AS INT.
|
||||
DEF VAR cword AS CHAR.
|
||||
|
||||
DO ii = 1 TO NUM-ENTRIES( cset [ i_iset ] ) WHILE NUM-ENTRIES( cresult, " " ) < EXTENT( cset ):
|
||||
|
||||
cword = ENTRY( ii, cset[ i_iset ] ).
|
||||
IF i_cwords = "" OR
|
||||
SUBSTRING( i_cwords, LENGTH( i_cwords ), 1 ) = SUBSTRING( cword, 1, 1 )
|
||||
THEN DO:
|
||||
IF i_iset = EXTENT ( cset ) THEN
|
||||
cresult = i_cwords + " " + cword.
|
||||
ELSE
|
||||
cresult = getAmb( i_cwords + " " + cword, i_iset + 1 ).
|
||||
END.
|
||||
|
||||
END.
|
||||
|
||||
RETURN cresult.
|
||||
|
||||
END FUNCTION. /* getAmb */
|
||||
|
||||
|
||||
MESSAGE getAmb( "", 1 ) VIEW-AS ALERT-BOX.
|
||||
27
Task/Amb/Oz/amb.oz
Normal file
27
Task/Amb/Oz/amb.oz
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
declare
|
||||
|
||||
fun {Amb Xs}
|
||||
case Xs of nil then fail
|
||||
[] [X] then X
|
||||
[] X|Xr then
|
||||
choice X
|
||||
[] {Amb Xr}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
fun {Example}
|
||||
W1 = {Amb ["the" "that" "a"]}
|
||||
W2 = {Amb ["frog" "elephant" "thing"]}
|
||||
W3 = {Amb ["walked" "treaded" "grows"]}
|
||||
W4 = {Amb ["slowly" "quickly"]}
|
||||
in
|
||||
{List.last W1 W2.1}
|
||||
{List.last W2 W3.1}
|
||||
{List.last W3 W4.1}
|
||||
W1#" "#W2#" "#W3#" "#W4
|
||||
end
|
||||
|
||||
in
|
||||
|
||||
{ForAll {SearchAll Example} System.showInfo}
|
||||
16
Task/Amb/PARI-GP/amb.parigp
Normal file
16
Task/Amb/PARI-GP/amb.parigp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
Amb(V)={
|
||||
amb(vector(#V,i,vector(#V[i],j,Vec(V[i][j]))),[])
|
||||
};
|
||||
amb(V,s)={
|
||||
if (#V == 0, return(concat(s)));
|
||||
my(v=V[1],U=vecextract(V,2^#V-2),t,final=if(#s,s[#s]));
|
||||
if(#s, s = concat(s,[" "]));
|
||||
for(i=1,#v,
|
||||
if ((#s == 0 || final == v[i][1]),
|
||||
t = amb(U, concat(s, v[i]));
|
||||
if (t, return(t))
|
||||
)
|
||||
);
|
||||
0
|
||||
};
|
||||
Amb([["the","that","a"],["frog","elephant","thing"],["walked","treaded","grows"],["slowly","quickly"]])
|
||||
86
Task/Amb/PL-I/amb.pli
Normal file
86
Task/Amb/PL-I/amb.pli
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
*process or(!) source attributes xref;
|
||||
amb: Proc Options(main);
|
||||
/*********************************************************************
|
||||
* 25.08.2013 Walter Pachl
|
||||
*********************************************************************/
|
||||
Dcl w(4,10) Char(40) Var
|
||||
Init('the','that','a','if',(6)(1)' ',
|
||||
'frog','elephant','thing',(7)(1)' ',
|
||||
'walked','treaded','grows','trots',(6)(1)' ',
|
||||
'slowly','quickly',(8)(1)' ');
|
||||
Dcl ns Char(40) Var;
|
||||
Dcl (i,k,j,ii,jj,m,n) Bin Fixed(31);
|
||||
n=hbound(w,1); /* number of sets */
|
||||
m=hbound(w,2); /* max number of words in set */
|
||||
Call show; /* show the input */
|
||||
Do i=1 To n-1; /* loop over sets */
|
||||
k=i+1; /* the following set */
|
||||
Do ii=1 To m; /* loop over elements in set k*/
|
||||
If words(w(i,ii))=i Then Do; /* a sentence part found */
|
||||
Do jj=1 To m; /* loop over following words */
|
||||
If right(w(i,ii),1)=left(w(k,jj),1) Then Do; /* fitting */
|
||||
ns=w(i,ii)!!' '!!w(k,jj); /* build new sentence (part) */
|
||||
If words(ns)=k Then /* 'complete' part */
|
||||
Call add(k,ns); /* add to set k */
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
Do jj=1 To m; /* show the results */
|
||||
If words(w(4,jj))=4 Then
|
||||
put edit('--> ',w(4,jj))(Skip,a,a);
|
||||
End;
|
||||
|
||||
add: Proc(ni,s);
|
||||
/*********************************************************************
|
||||
* add a sentence (part) to set ni
|
||||
*********************************************************************/
|
||||
Dcl (i,ni) Bin Fixed(31);
|
||||
Dcl s Char(40) Var;
|
||||
Do i=1 To m While(w(ni,i)>''); /* look for an empty slot */
|
||||
End;
|
||||
w(ni,i)=s; /* add the sentence (part) */
|
||||
End;
|
||||
|
||||
words: Proc(s) Returns(Bin Fixed(31));
|
||||
/*********************************************************************
|
||||
* return the number of blank separated words in s
|
||||
*********************************************************************/
|
||||
Dcl s Char(40) Var;
|
||||
Dcl nw Bin Fixed(31) Init(0);
|
||||
Dcl i Bin Fixed(31) Init(1);
|
||||
If s>'' Then Do;
|
||||
nw=1;
|
||||
Do i=1 To length(s);
|
||||
If substr(s,i,1)=' ' Then
|
||||
nw+=1;
|
||||
End;
|
||||
End;
|
||||
Return(nw);
|
||||
End;
|
||||
|
||||
show: Proc;
|
||||
/*********************************************************************
|
||||
* show the input sets
|
||||
*********************************************************************/
|
||||
Dcl (i,j,mm) Bin Fixed(31) Init(0);
|
||||
Dcl l(4) Bin Fixed(31) Init((4)0);
|
||||
Do i=1 To n;
|
||||
Do j=1 To m;
|
||||
If w(i,j)>'' Then Do;
|
||||
mm=max(mm,j); /* max number of words in any set */
|
||||
l(i)=max(l(i),length(w(i,j))); /* max word length in set i */
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
Put Edit('Input:')(Skip,a);
|
||||
Do j=1 To mm; /* output lines */
|
||||
Put Skip;
|
||||
Do i=1 To n;
|
||||
Put Edit(w(i,j),' ')(a(l(i)),a);
|
||||
End;
|
||||
End;
|
||||
Put Skip;
|
||||
End;
|
||||
|
||||
End;
|
||||
35
Task/Amb/Perl/amb-1.pl
Normal file
35
Task/Amb/Perl/amb-1.pl
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
use constant EXIT_FAILURE => 1;
|
||||
use constant EXIT_SUCCESS => 0;
|
||||
|
||||
sub amb {
|
||||
exit(EXIT_FAILURE) if !@_;
|
||||
for my $word (@_) {
|
||||
my $pid = fork;
|
||||
die $! unless defined $pid;
|
||||
return $word if !$pid;
|
||||
my $wpid = waitpid $pid, 0;
|
||||
die $! unless $wpid == $pid;
|
||||
exit(EXIT_SUCCESS) if $? == EXIT_SUCCESS;
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sub joined {
|
||||
my ($join_a, $join_b) = @_;
|
||||
substr($join_a, -1) eq substr($join_b, 0, 1);
|
||||
}
|
||||
|
||||
my $w1 = amb(qw(the that a));
|
||||
my $w2 = amb(qw(frog elephant thing));
|
||||
my $w3 = amb(qw(walked treaded grows));
|
||||
my $w4 = amb(qw(slowly quickly));
|
||||
|
||||
amb() unless joined $w1, $w2;
|
||||
amb() unless joined $w2, $w3;
|
||||
amb() unless joined $w3, $w4;
|
||||
|
||||
print "$w1 $w2 $w3 $w4\n";
|
||||
exit(EXIT_SUCCESS);
|
||||
27
Task/Amb/Perl/amb-2.pl
Normal file
27
Task/Amb/Perl/amb-2.pl
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use feature 'say';
|
||||
use re 'eval';
|
||||
|
||||
sub amb :prototype($@) {
|
||||
my $var = shift;
|
||||
join ' || ', map { "(?{ $var = '$_' })" } @_;
|
||||
}
|
||||
|
||||
sub joins {
|
||||
substr(shift,-1,1) eq substr(shift,0,1)
|
||||
}
|
||||
|
||||
my ($a,$b,$c,$d);
|
||||
'' =~ m/
|
||||
(??{ amb '$a', qw[the that a] })
|
||||
(??{ amb '$b', qw[frog elephant thing] })
|
||||
(??{ amb '$c', qw[walked treaded grows] })
|
||||
(??{ amb '$d', qw[slowly quickly] })
|
||||
(?(?{ joins($b, $c) })|(*FAIL))
|
||||
(?(?{ joins($a, $b) })|(*FAIL))
|
||||
(?(?{ joins($c, $d) })|(*FAIL))
|
||||
(?{ say "$a $b $c $d" })
|
||||
/x;
|
||||
40
Task/Amb/Perl/amb-3.pl
Normal file
40
Task/Amb/Perl/amb-3.pl
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub amb {
|
||||
if( @_ == 0 ) {
|
||||
no warnings 'exiting';
|
||||
next AMB;
|
||||
}
|
||||
my $code = pop;
|
||||
my @words = @_;
|
||||
my @index = (0) x @words;
|
||||
AMB: while( 1 ) {
|
||||
my @w = map $words[$_][$index[$_]], 0 .. $#_;
|
||||
return $code->( @w );
|
||||
} continue {
|
||||
my $i = 0;
|
||||
while( ++$index[$i] == @{$words[$i]} ) {
|
||||
$index[$i] = 0;
|
||||
return if ++$i == @index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my @w1 = qw(the that a);
|
||||
my @w2 = qw(frog elephant thing);
|
||||
my @w3 = qw(walked treaded grows);
|
||||
my @w4 = qw(slowly quickly);
|
||||
|
||||
sub joined {
|
||||
my ($join_a, $join_b) = @_;
|
||||
substr($join_a, -1) eq substr($join_b, 0, 1);
|
||||
}
|
||||
|
||||
amb( \(@w1, @w2, @w3, @w4), sub {
|
||||
my ($w1, $w2, $w3, $w4) = @_;
|
||||
amb() unless joined($w1, $w2);
|
||||
amb() unless joined($w2, $w3);
|
||||
amb() unless joined($w3, $w4);
|
||||
print "$w1 $w2 $w3 $w4\n";
|
||||
});
|
||||
39
Task/Amb/Phix/amb-1.phix
Normal file
39
Task/Amb/Phix/amb-1.phix
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">amb1</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">pass</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">pass</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">res</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;">sets</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]][$]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">k</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;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">k</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">ch</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">k</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">pass</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">amb1</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">idx</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;">pass</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: #008080;">end</span> <span style="color: #008080;">if</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: #0000FF;">{</span><span style="color: #000000;">pass</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sets</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"the"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"that"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"a"</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"frog"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"elephant"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"thing"</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"walked"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"treaded"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"grows"</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"slowly"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"quickly"</span><span style="color: #0000FF;">}}</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #004080;">integer</span> <span style="color: #000000;">pass</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">amb1</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">pass</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"success: "</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: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">res</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;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">res</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"failure\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<!--
|
||||
73
Task/Amb/Phix/amb-2.phix
Normal file
73
Task/Amb/Phix/amb-2.phix
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">amb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">testrid</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">resrid</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">flag</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">==</span><span style="color: #000000;">0</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">pass</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">pass</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">resrid</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">resrid</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">flag</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">res</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;">sets</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">k</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;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">k</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">flag</span> <span style="color: #008080;">or</span> <span style="color: #000000;">testrid</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">),</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">pass</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">amb</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">,</span><span style="color: #000000;">testrid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">resrid</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">),</span><span style="color: #000000;">idx</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;">pass</span> <span style="color: #008080;">and</span> <span style="color: #000000;">resrid</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</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: #008080;">end</span> <span style="color: #008080;">if</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: #0000FF;">{</span><span style="color: #000000;">pass</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">pairable</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]][$]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">AMB_Show</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</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: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">res</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;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<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;">"success: %v\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">pythagorean</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000080;font-style:italic;">/*sets*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000080;font-style:italic;">-- (note that res[idx]==sets[idx][res[idx]] in all cases)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;"><</span><span style="color: #000000;">3</span> <span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">*</span><span style="color: #000000;">x</span><span style="color: #0000FF;">+</span><span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">z</span><span style="color: #0000FF;">*</span><span style="color: #000000;">z</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">pythag_show</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000080;font-style:italic;">/*sets*/</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
|
||||
<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;">"success: %v\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #000080;font-style:italic;">-- see http://www.randomhacks.net/articles/2005/10/11/amb-operator</span>
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">not8</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000080;font-style:italic;">-- (note that idx==2 in all cases)
|
||||
-- (at the last moment, I flipped the test, after realising that
|
||||
-- someone had completely misunderstood the original article...
|
||||
-- return sets[1][res[1]]*sets[idx][res[idx]]!=8</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]]*</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]]=</span><span style="color: #000000;">8</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">not8_show</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"success: "</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">?{</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]],</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">][</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]]}</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sets</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"the"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"that"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"a"</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"frog"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"elephant"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"thing"</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"walked"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"treaded"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"grows"</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #008000;">"slowly"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"quickly"</span><span style="color: #0000FF;">}}</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sets2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">11</span><span style="color: #0000FF;">),</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sets3</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">}}</span>
|
||||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nThe original:\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">amb</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pairable</span><span style="color: #0000FF;">,</span><span style="color: #000000;">AMB_Show</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nSmall Pythagorean triples problem:\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">amb</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pythagorean</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pythag_show</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nSome strange not 8 problem:\n"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (now fixed)</span>
|
||||
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">amb</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">not8</span><span style="color: #0000FF;">,</span><span style="color: #000000;">not8_show</span><span style="color: #0000FF;">)</span>
|
||||
<!--
|
||||
38
Task/Amb/Picat/amb.picat
Normal file
38
Task/Amb/Picat/amb.picat
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
go ?=>
|
||||
% select which version of amb/2 and joins/2 to test
|
||||
member(Amb,[amb,amb2]),
|
||||
member(Joins,[joins,join2]),
|
||||
println([amb=Amb,joins=Joins]),
|
||||
test_amb(amb,joins, Word1,Word2,Word3,Word4),
|
||||
println([Word1, Word2, Word3, Word4]),
|
||||
nl,
|
||||
fail, % get other solutions
|
||||
nl.
|
||||
go => true.
|
||||
|
||||
% Test a combination of amb and joins
|
||||
test_amb(Amb,Joins, Word1,Word2,Word3,Word4) =>
|
||||
call(Amb, Word1, ["the","that","a"]),
|
||||
call(Amb, Word2, ["frog","elephant","thing"]),
|
||||
call(Amb, Word3, ["walked","treaded","grows"]),
|
||||
call(Amb, Word4, ["slowly","quickly"]),
|
||||
call(Joins, Word1, Word2),
|
||||
call(Joins, Word2, Word3),
|
||||
call(Joins, Word3, Word4).
|
||||
|
||||
% Based on the Prolog solution.
|
||||
amb(E, [E|_]).
|
||||
amb(E, [_|ES]) :- amb(E, ES).
|
||||
|
||||
joins(Left, Right) =>
|
||||
append(_, [T], Left),
|
||||
append([R], _, Right),
|
||||
( T != R -> amb(_, [])
|
||||
; true ).
|
||||
|
||||
% Another approach, using member/2 for
|
||||
% generating the words.
|
||||
amb2([],[]).
|
||||
amb2(Word,Words) :- member(Word,Words).
|
||||
|
||||
joins2(Word1,Word2) :- Word1.last() = Word2.first().
|
||||
18
Task/Amb/PicoLisp/amb.l
Normal file
18
Task/Amb/PicoLisp/amb.l
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
(be amb (@E @Lst)
|
||||
(lst @E @Lst) )
|
||||
|
||||
(be joins (@Left @Right)
|
||||
(^ @T (last (chop (-> @Left))))
|
||||
(^ @R (car (chop (-> @Right))))
|
||||
(or
|
||||
((equal @T @R))
|
||||
((amb @ NIL)) ) ) # Explicitly using amb fail as required
|
||||
|
||||
(be ambExample ((@Word1 @Word2 @Word3 @Word4))
|
||||
(amb @Word1 ("the" "that" "a"))
|
||||
(amb @Word2 ("frog" "elephant" "thing"))
|
||||
(amb @Word3 ("walked" "treaded" "grows"))
|
||||
(amb @Word4 ("slowly" "quickly"))
|
||||
(joins @Word1 @Word2)
|
||||
(joins @Word2 @Word3)
|
||||
(joins @Word3 @Word4) )
|
||||
17
Task/Amb/Prolog/amb.pro
Normal file
17
Task/Amb/Prolog/amb.pro
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
amb(E, [E|_]).
|
||||
amb(E, [_|ES]) :- amb(E, ES).
|
||||
|
||||
joins(Left, Right) :-
|
||||
append(_, [T], Left),
|
||||
append([R], _, Right),
|
||||
( T \= R -> amb(_, []) % (explicitly using amb fail as required)
|
||||
; true ).
|
||||
|
||||
amb_example([Word1, Word2, Word3, Word4]) :-
|
||||
amb(Word1, ["the","that","a"]),
|
||||
amb(Word2, ["frog","elephant","thing"]),
|
||||
amb(Word3, ["walked","treaded","grows"]),
|
||||
amb(Word4, ["slowly","quickly"]),
|
||||
joins(Word1, Word2),
|
||||
joins(Word2, Word3),
|
||||
joins(Word3, Word4).
|
||||
44
Task/Amb/PureBasic/amb.basic
Normal file
44
Task/Amb/PureBasic/amb.basic
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
Procedure Words_Ok(String1.s, String2.s)
|
||||
If Mid(String1,Len(String1),1)=Mid(String2,1,1)
|
||||
ProcedureReturn #True
|
||||
EndIf
|
||||
ProcedureReturn #False
|
||||
EndProcedure
|
||||
|
||||
Procedure.s Amb(Array A.s(1), Array B.s(1), Array C.s(1), Array D.s(1))
|
||||
Protected a, b, c, d
|
||||
For a=0 To ArraySize(A())
|
||||
For b=0 To ArraySize(B())
|
||||
For c=0 To ArraySize(C())
|
||||
For d=0 To ArraySize(D())
|
||||
If Words_Ok(A(a),B(b)) And Words_Ok(B(b),C(c)) And Words_Ok(C(c),D(d))
|
||||
ProcedureReturn A(a)+" "+B(b)+" "+C(c)+" "+D(d)
|
||||
EndIf
|
||||
Next
|
||||
Next
|
||||
Next
|
||||
Next
|
||||
ProcedureReturn "" ; Empty string, e.g. fail
|
||||
EndProcedure
|
||||
|
||||
If OpenConsole()
|
||||
Define Text.s
|
||||
Dim Set1.s(2)
|
||||
Dim Set2.s(2)
|
||||
Dim Set3.s(2)
|
||||
Dim Set4.s(1)
|
||||
|
||||
Set1(0)="the": set1(1)="that": set1(2)="a"
|
||||
Set2(0)="frog": set2(1)="elephant": set2(2)="thing"
|
||||
Set3(0)="walked": set3(1)="treaded": set3(2)="grows"
|
||||
Set4(0)="slowly": set4(1)="quickly"
|
||||
|
||||
text=Amb(set1(),set2(),Set3(),set4())
|
||||
If Text<>""
|
||||
PrintN("Correct sentence would be,"+#CRLF$+Text)
|
||||
Else
|
||||
PrintN("Failed to fine a correct sentence.")
|
||||
EndIf
|
||||
PrintN(#CRLF$+#CRLF$+"Press ENTER to exit."): Input()
|
||||
CloseConsole()
|
||||
EndIf
|
||||
100
Task/Amb/Python/amb-1.py
Normal file
100
Task/Amb/Python/amb-1.py
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import itertools as _itertools
|
||||
|
||||
class Amb(object):
|
||||
def __init__(self):
|
||||
self._names2values = {} # set of values for each global name
|
||||
self._func = None # Boolean constraint function
|
||||
self._valueiterator = None # itertools.product of names values
|
||||
self._funcargnames = None # Constraint parameter names
|
||||
|
||||
def __call__(self, arg=None):
|
||||
if hasattr(arg, '__code__'):
|
||||
##
|
||||
## Called with a constraint function.
|
||||
##
|
||||
globls = arg.__globals__ if hasattr(arg, '__globals__') else arg.func_globals
|
||||
# Names used in constraint
|
||||
argv = arg.__code__.co_varnames[:arg.__code__.co_argcount]
|
||||
for name in argv:
|
||||
if name not in self._names2values:
|
||||
assert name in globls, \
|
||||
"Global name %s not found in function globals" % name
|
||||
self._names2values[name] = globls[name]
|
||||
# Gather the range of values of all names used in the constraint
|
||||
valuesets = [self._names2values[name] for name in argv]
|
||||
self._valueiterator = _itertools.product(*valuesets)
|
||||
self._func = arg
|
||||
self._funcargnames = argv
|
||||
return self
|
||||
elif arg is not None:
|
||||
##
|
||||
## Assume called with an iterable set of values
|
||||
##
|
||||
arg = frozenset(arg)
|
||||
return arg
|
||||
else:
|
||||
##
|
||||
## blank call tries to return next solution
|
||||
##
|
||||
return self._nextinsearch()
|
||||
|
||||
def _nextinsearch(self):
|
||||
arg = self._func
|
||||
globls = arg.__globals__
|
||||
argv = self._funcargnames
|
||||
found = False
|
||||
for values in self._valueiterator:
|
||||
if arg(*values):
|
||||
# Set globals.
|
||||
found = True
|
||||
for n, v in zip(argv, values):
|
||||
globls[n] = v
|
||||
break
|
||||
if not found: raise StopIteration
|
||||
return values
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
return self()
|
||||
next = __next__ # Python 2
|
||||
|
||||
if __name__ == '__main__':
|
||||
if True:
|
||||
amb = Amb()
|
||||
|
||||
print("\nSmall Pythagorean triples problem:")
|
||||
x = amb(range(1,11))
|
||||
y = amb(range(1,11))
|
||||
z = amb(range(1,11))
|
||||
|
||||
for _dummy in amb( lambda x, y, z: x*x + y*y == z*z ):
|
||||
print ('%s %s %s' % (x, y, z))
|
||||
|
||||
|
||||
if True:
|
||||
amb = Amb()
|
||||
|
||||
print("\nRosetta Code Amb problem:")
|
||||
w1 = amb(["the", "that", "a"])
|
||||
w2 = amb(["frog", "elephant", "thing"])
|
||||
w3 = amb(["walked", "treaded", "grows"])
|
||||
w4 = amb(["slowly", "quickly"])
|
||||
|
||||
for _dummy in amb( lambda w1, w2, w3, w4: \
|
||||
w1[-1] == w2[0] and \
|
||||
w2[-1] == w3[0] and \
|
||||
w3[-1] == w4[0] ):
|
||||
print ('%s %s %s %s' % (w1, w2, w3, w4))
|
||||
|
||||
if True:
|
||||
amb = Amb()
|
||||
|
||||
print("\nAmb problem from "
|
||||
"http://www.randomhacks.net/articles/2005/10/11/amb-operator:")
|
||||
x = amb([1, 2, 3])
|
||||
y = amb([4, 5, 6])
|
||||
|
||||
for _dummy in amb( lambda x, y: x * y != 8 ):
|
||||
print ('%s %s' % (x, y))
|
||||
15
Task/Amb/Python/amb-2.py
Normal file
15
Task/Amb/Python/amb-2.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# joins :: String -> String -> Bool
|
||||
def joins(a, b):
|
||||
return a[-1] == b[0]
|
||||
|
||||
|
||||
print (
|
||||
[
|
||||
' '.join([w1, w2, w3, w4])
|
||||
for w1 in ['the', 'that', 'a']
|
||||
for w2 in ['frog', 'elephant', 'thing']
|
||||
for w3 in ['walked', 'treaded', 'grows']
|
||||
for w4 in ['slowly', 'quickly']
|
||||
if joins(w1, w2) and joins(w2, w3) and joins(w3, w4)
|
||||
]
|
||||
)
|
||||
37
Task/Amb/Python/amb-3.py
Normal file
37
Task/Amb/Python/amb-3.py
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
def main():
|
||||
print (
|
||||
unlines([
|
||||
unwords([w1, w2, w3, w4])
|
||||
|
||||
for w1 in ['the', 'that', 'a']
|
||||
if True
|
||||
|
||||
for w2 in ['frog', 'elephant', 'thing']
|
||||
if joins(w1, w2)
|
||||
|
||||
for w3 in ['walked', 'treaded', 'grows']
|
||||
if joins(w2, w3)
|
||||
|
||||
for w4 in ['slowly', 'quickly']
|
||||
if joins(w3, w4)
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
# joins :: String -> String -> Bool
|
||||
def joins(a, b):
|
||||
return a[-1] == b[0]
|
||||
|
||||
|
||||
# unlines :: [String] -> String
|
||||
def unlines(xs):
|
||||
return '\n'.join(xs)
|
||||
|
||||
|
||||
# unwords :: [String] -> String
|
||||
def unwords(xs):
|
||||
return ' '.join(xs)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
79
Task/Amb/Python/amb-4.py
Normal file
79
Task/Amb/Python/amb-4.py
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
from itertools import chain
|
||||
|
||||
|
||||
# amb :: [a] -> (a -> [b]) -> [b]
|
||||
def amb(xs):
|
||||
return lambda f: list(
|
||||
chain.from_iterable(
|
||||
map(f, xs)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# main :: IO ()
|
||||
def main():
|
||||
|
||||
xs = enumFromTo(1)(10)
|
||||
print ('Pythagorean triples from integers 1-10:')
|
||||
print (
|
||||
amb(xs)(
|
||||
lambda x: amb(xs)
|
||||
(lambda y: amb(xs)
|
||||
(lambda z: when(
|
||||
x * x + y * y == z * z
|
||||
)(
|
||||
(x, y, z)
|
||||
)
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
# joins :: String -> String -> Bool
|
||||
def joins(a, b):
|
||||
return a[-1] == b[0]
|
||||
|
||||
print ('\nRC problem given above:')
|
||||
print (
|
||||
amb(['the', 'that', 'a'])(
|
||||
lambda w1: amb(
|
||||
['frog', 'elephant', 'thing']
|
||||
)(lambda w2: amb(
|
||||
['walked', 'treaded', 'grows']
|
||||
)(lambda w3: amb(
|
||||
['slowly', 'quickly']
|
||||
)(lambda w4: when(
|
||||
joins(w1, w2) and joins(w2, w3) and joins(w3, w4)
|
||||
)(
|
||||
(w1, w2, w3, w4)
|
||||
))))
|
||||
)
|
||||
)
|
||||
print('\nAdditional problem reference in procedural version above:')
|
||||
print(
|
||||
amb([1, 2, 3])
|
||||
(
|
||||
lambda x: amb([4, 5, 6])
|
||||
(
|
||||
lambda y: when(x * y != 8)
|
||||
(
|
||||
(x, y)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
# GENERIC -------------------------------------------------
|
||||
|
||||
|
||||
# enumFromTo :: (Int, Int) -> [Int]
|
||||
def enumFromTo(m):
|
||||
return lambda n: list(range(m, 1 + n))
|
||||
|
||||
|
||||
# when :: Bool -> [a] -> [a]
|
||||
def when(p):
|
||||
return lambda x: [x] if p else []
|
||||
|
||||
# MAIN ---
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
42
Task/Amb/Python/amb-5.py
Normal file
42
Task/Amb/Python/amb-5.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
from itertools import chain
|
||||
|
||||
|
||||
# amb :: [a] -> (a -> [b]) -> [b]
|
||||
def amb(xs):
|
||||
return lambda f: list(
|
||||
chain.from_iterable(
|
||||
map(f, xs)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# when :: Bool -> [a] -> [a]
|
||||
def when(p):
|
||||
return lambda xs: xs if p else []
|
||||
|
||||
|
||||
# TEST ----------------------------------------------------
|
||||
|
||||
# joins :: String -> String -> Bool
|
||||
def joins(a, b):
|
||||
return a[-1] == b[0]
|
||||
|
||||
|
||||
print (
|
||||
amb(['the', 'that', 'a'])(
|
||||
lambda w1: when(True)
|
||||
|
||||
(amb(['frog', 'elephant', 'thing'])
|
||||
(lambda w2: when(joins(w1, w2))
|
||||
|
||||
(amb(['walked', 'treaded', 'grows'])
|
||||
(lambda w3: when(joins(w2, w3))
|
||||
|
||||
(amb(['slowly', 'quickly'])
|
||||
(lambda w4: when(joins(w3, w4))(
|
||||
|
||||
[w1, w2, w3, w4]
|
||||
))))))
|
||||
)
|
||||
)
|
||||
)
|
||||
23
Task/Amb/R/amb-1.r
Normal file
23
Task/Amb/R/amb-1.r
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
checkSentence <- function(sentence){
|
||||
# Input: character vector
|
||||
# Output: whether the sentence formed by the elements of the vector is valid
|
||||
for (index in 1:(length(sentence)-1)){
|
||||
first.word <- sentence[index]
|
||||
second.word <- sentence[index+1]
|
||||
|
||||
last.letter <- substr(first.word, nchar(first.word), nchar(first.word))
|
||||
first.letter <- substr(second.word, 1, 1)
|
||||
|
||||
if (last.letter != first.letter){ return(FALSE) }
|
||||
}
|
||||
return(TRUE)
|
||||
}
|
||||
|
||||
amb <- function(sets){
|
||||
# Input: list of character vectors containing all sets to consider
|
||||
# Output: list of character vectors that are valid
|
||||
all.paths <- apply(expand.grid(sets), 2, as.character)
|
||||
all.paths.list <- split(all.paths, 1:nrow(all.paths))
|
||||
winners <- all.paths.list[sapply(all.paths.list, checkSentence)]
|
||||
return(winners)
|
||||
}
|
||||
14
Task/Amb/R/amb-2.r
Normal file
14
Task/Amb/R/amb-2.r
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
sentence1 <- c("that", "thing", "grows", "slowly")
|
||||
sentence2 <- c("rosetta", "code", "is", "cool")
|
||||
sentence <- list(sentence1, sentence2)
|
||||
sapply(sentence, checkSentence)
|
||||
[1] TRUE FALSE
|
||||
|
||||
set1 <- c("the", "that", "a")
|
||||
set2 <- c("frog", "elephant", "thing")
|
||||
set3 <- c("walked", "treaded", "grows")
|
||||
set4 <- c("slowly", "quickly")
|
||||
sets <- list(set1, set2, set3, set4)
|
||||
amb(sets)
|
||||
$`26`
|
||||
[1] "that" "thing" "grows" "slowly"
|
||||
85
Task/Amb/REXX/amb-1.rexx
Normal file
85
Task/Amb/REXX/amb-1.rexx
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/* REXX **************************************************************
|
||||
* 25.08.2013 Walter Pachl derived from PL/I
|
||||
*********************************************************************/
|
||||
mm=0
|
||||
w.=''
|
||||
l.=0
|
||||
Call mkset 1,'the that a if'
|
||||
Call mkset 2,'frog elephant thing'
|
||||
Call mkset 3,'walked treaded grows trots'
|
||||
Call mkset 4,'slowly quickly'
|
||||
|
||||
Call show
|
||||
Do i=1 to 3 /* loop over sets */
|
||||
Call showm
|
||||
k=i+1 /* the following set */
|
||||
Do ii=1 To 10 /* loop over elements in set k*/
|
||||
If words(w.i.ii)=i Then Do /* a sentence part found */
|
||||
Do jj=1 To 10 /* loop over following words */
|
||||
If right(w.i.ii,1)=left(w.k.jj,1) Then Do /* fitting */
|
||||
ns=w.i.ii' 'w.k.jj /* build new sentence (part) */
|
||||
If words(ns)=k Then /* 'complete' part */
|
||||
Call add k,ns /* add to set k */
|
||||
End
|
||||
End
|
||||
End
|
||||
End
|
||||
End
|
||||
|
||||
Do jj=1 To 10 /* show the results */
|
||||
If words(w.4.jj)=4 Then
|
||||
Say '-->' w.4.jj
|
||||
End
|
||||
Return
|
||||
|
||||
add: Procedure Expose w.
|
||||
/*********************************************************************
|
||||
* add a sentence (part) to set ni
|
||||
*********************************************************************/
|
||||
Parse Arg ni,s
|
||||
Do i=1 To 10 While w.ni.i>'' /* look for an empty slot */
|
||||
End
|
||||
w.ni.i=s /* add the sentence (part) */
|
||||
Return
|
||||
|
||||
mkset: Procedure Expose w. mm l.
|
||||
/*********************************************************************
|
||||
* initialize the sets
|
||||
*********************************************************************/
|
||||
Parse Arg i,wl
|
||||
Do j=1 By 1 While wl<>''
|
||||
Parse Var wl w.i.j wl
|
||||
l.i=max(l.i,length(w.i.j))
|
||||
End
|
||||
mm=max(mm,j-1)
|
||||
Return
|
||||
|
||||
show: Procedure Expose w. mm l.
|
||||
/*********************************************************************
|
||||
* show the input
|
||||
*********************************************************************/
|
||||
Say 'Input:'
|
||||
Do j=1 To mm /* output lines */
|
||||
ol=''
|
||||
Do i=1 To 4
|
||||
ol=ol left(w.i.j,l.i)
|
||||
End
|
||||
Say strip(ol)
|
||||
End;
|
||||
say ''
|
||||
Return
|
||||
|
||||
showm: Procedure Expose w.
|
||||
/*********************************************************************
|
||||
* show the sets' contents
|
||||
*********************************************************************/
|
||||
dbg=0
|
||||
If dbg Then Do
|
||||
Do i=1 To 4
|
||||
Do j=1 To 10
|
||||
If w.i.j>'' Then
|
||||
Say i j w.i.j
|
||||
End
|
||||
End
|
||||
End
|
||||
Return
|
||||
18
Task/Amb/REXX/amb-2.rexx
Normal file
18
Task/Amb/REXX/amb-2.rexx
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/*REXX program demonstrates the Amd operator, choosing a word from each set. */
|
||||
@.1 = "the that a"
|
||||
@.2 = "frog elephant thing"
|
||||
@.3 = "walked treaded grows"
|
||||
@.4 = "slowly quickly"
|
||||
@.0 = 4 /*define the number of sets being ised.*/
|
||||
call Amb 1 /*find all word combinations that works*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*--------------------------------------------------------------------------------------*/
|
||||
Amb: procedure expose @.; parse arg # x; arg . u /*ARG uppercases U value. */
|
||||
if #>@.0 then do; y= word(u, 1) /*Y: is a uppercased U. */
|
||||
do n=2 to words(u); ?= word(u, n)
|
||||
if left(?, 1) \== right(y, 1) then return; y= ?
|
||||
end /*n*/
|
||||
say strip(x) /*¬show superfluous blanks.*/
|
||||
end
|
||||
do j=1 for words(@.#); call Amb #+1 x word(@.#, j) /*gen all combos recursively*/
|
||||
end /*j*/; return
|
||||
30
Task/Amb/Racket/amb.rkt
Normal file
30
Task/Amb/Racket/amb.rkt
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#lang racket
|
||||
|
||||
;; A quick `amb' implementation (same as in the Twelve Statements task)
|
||||
(define failures null)
|
||||
|
||||
(define (fail)
|
||||
(if (pair? failures) ((first failures)) (error "no more choices!")))
|
||||
|
||||
(define (amb/thunks choices)
|
||||
(let/cc k (set! failures (cons k failures)))
|
||||
(if (pair? choices)
|
||||
(let ([choice (first choices)]) (set! choices (rest choices)) (choice))
|
||||
(begin (set! failures (rest failures)) (fail))))
|
||||
|
||||
(define-syntax-rule (amb E ...) (amb/thunks (list (lambda () E) ...)))
|
||||
|
||||
(define (assert condition) (unless condition (fail)))
|
||||
|
||||
;; Problem solution
|
||||
|
||||
(define (joins? left right)
|
||||
(regexp-match? #px"(.)\0\\1" (~a left "\0" right)))
|
||||
|
||||
(let ([result (list (amb "the" "that" "a")
|
||||
(amb "frog" "elephant" "thing")
|
||||
(amb "walked" "treaded" "grows")
|
||||
(amb "slowly" "quickly"))])
|
||||
(for ([x result] [y (cdr result)]) (assert (joins? x y)))
|
||||
result)
|
||||
;; -> '("that" "thing" "grows" "slowly")
|
||||
18
Task/Amb/Raku/amb-1.raku
Normal file
18
Task/Amb/Raku/amb-1.raku
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#| an array of four words, that have more possible values.
|
||||
#| Normally we would want `any' to signify we want any of the values, but well negate later and thus we need `all'
|
||||
my @a =
|
||||
(all «the that a»),
|
||||
(all «frog elephant thing»),
|
||||
(all «walked treaded grows»),
|
||||
(all «slowly quickly»);
|
||||
|
||||
sub test (Str $l, Str $r) {
|
||||
$l.ends-with($r.substr(0,1))
|
||||
}
|
||||
|
||||
(sub ($w1, $w2, $w3, $w4){
|
||||
# return if the values are false
|
||||
return unless [and] test($w1, $w2), test($w2, $w3),test($w3, $w4);
|
||||
# say the results. If there is one more Container layer around them this doesn't work, this is why we need the arguments here.
|
||||
say "$w1 $w2 $w3 $w4"
|
||||
})(|@a); # supply the array as argumetns
|
||||
17
Task/Amb/Raku/amb-2.raku
Normal file
17
Task/Amb/Raku/amb-2.raku
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# The Task #
|
||||
my @firstSet = «the that a»;
|
||||
my @secondSet = «frog elephant thing»;
|
||||
my @thirdSet = «walked treaded grows»;
|
||||
my @fourthSet = «slowly quickly»;
|
||||
|
||||
.say for doAmb [@firstSet, @secondSet, @thirdSet, @fourthSet];
|
||||
|
||||
|
||||
sub doAmb( @lol ) { # Takes out the correct sentences.
|
||||
my @sentences = map *.join(" "), [X] @lol;
|
||||
grep &isAmb, @sentences;
|
||||
}
|
||||
|
||||
sub isAmb( $sentence ) { # Checks `$sentence` for correctness.
|
||||
$sentence !~~ / (.) " " (.) <!{$0 eq $1}> / # <https://docs.raku.org/language/regexes#Regex_boolean_condition_check>
|
||||
}
|
||||
41
Task/Amb/Red/amb.red
Normal file
41
Task/Amb/Red/amb.red
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
Red ["Amb operator"]
|
||||
|
||||
findblock: function [
|
||||
blk [block!]
|
||||
][
|
||||
foreach w blk [
|
||||
if all [word? w block? get w] [return w]
|
||||
if block? w [findblock w]
|
||||
]
|
||||
]
|
||||
|
||||
amb: function [
|
||||
cond [block!]
|
||||
][
|
||||
either b: findblock cond [
|
||||
foreach a get b [
|
||||
cond2: replace/all/deep copy/deep cond b a
|
||||
if amb cond2 [set b a return true]]
|
||||
][do cond]
|
||||
]
|
||||
|
||||
; examples
|
||||
|
||||
x: [1 2 3 4]
|
||||
y: [4 5 6]
|
||||
z: [5 2]
|
||||
print amb [x * y * z = 8]
|
||||
print [x y z]
|
||||
|
||||
a: ["the" "that" "a"]
|
||||
b: ["frog" "elephant" "thing"]
|
||||
c: ["walked" "treaded" "grows"]
|
||||
d: ["slowly" "quickly"]
|
||||
print amb [
|
||||
all [
|
||||
equal? last a first b
|
||||
equal? last b first c
|
||||
equal? last c first d
|
||||
]
|
||||
]
|
||||
print [a b c d]
|
||||
32
Task/Amb/Ring/amb.ring
Normal file
32
Task/Amb/Ring/amb.ring
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Project : Amb
|
||||
|
||||
set1 = ["the","that","a"]
|
||||
set2 = ["frog","elephant","thing"]
|
||||
set3 = ["walked","treaded","grows"]
|
||||
set4 = ["slowly","quickly"]
|
||||
text = amb(set1,set2,set3,set4)
|
||||
if text != ""
|
||||
see "Correct sentence would be: " + nl + text + nl
|
||||
else
|
||||
see "Failed to fine a correct sentence."
|
||||
ok
|
||||
|
||||
func wordsok(string1, string2)
|
||||
if substr(string1,len(string1),1) = substr(string2,1,1)
|
||||
return true
|
||||
ok
|
||||
return false
|
||||
|
||||
func amb(a,b,c,d)
|
||||
for a2 = 1 to len(a)
|
||||
for b2 =1 to len(b)
|
||||
for c2 = 1 to len(c)
|
||||
for d2 = 1 to len(d)
|
||||
if wordsok(a[a2],b[b2]) and wordsok(b[b2],c[c2]) and wordsok(c[c2],d[d2])
|
||||
return a[a2]+" "+b[b2]+" "+c[c2]+" "+d[d2]
|
||||
ok
|
||||
next
|
||||
next
|
||||
next
|
||||
next
|
||||
return ""
|
||||
49
Task/Amb/Ruby/amb.rb
Normal file
49
Task/Amb/Ruby/amb.rb
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
require "continuation"
|
||||
|
||||
class Amb
|
||||
class ExhaustedError < RuntimeError; end
|
||||
|
||||
def initialize
|
||||
@fail = proc { fail ExhaustedError, "amb tree exhausted" }
|
||||
end
|
||||
|
||||
def choose(*choices)
|
||||
prev_fail = @fail
|
||||
callcc { |sk|
|
||||
choices.each { |choice|
|
||||
callcc { |fk|
|
||||
@fail = proc {
|
||||
@fail = prev_fail
|
||||
fk.call(:fail)
|
||||
}
|
||||
if choice.respond_to? :call
|
||||
sk.call(choice.call)
|
||||
else
|
||||
sk.call(choice)
|
||||
end
|
||||
}
|
||||
}
|
||||
@fail.call
|
||||
}
|
||||
end
|
||||
|
||||
def failure
|
||||
choose
|
||||
end
|
||||
|
||||
def assert(cond)
|
||||
failure unless cond
|
||||
end
|
||||
end
|
||||
|
||||
A = Amb.new
|
||||
w1 = A.choose("the", "that", "a")
|
||||
w2 = A.choose("frog", "elephant", "thing")
|
||||
w3 = A.choose("walked", "treaded", "grows")
|
||||
w4 = A.choose("slowly", "quickly")
|
||||
|
||||
A.choose() unless w1[-1] == w2[0]
|
||||
A.choose() unless w2[-1] == w3[0]
|
||||
A.choose() unless w3[-1] == w4[0]
|
||||
|
||||
puts w1, w2, w3, w4
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue