June 2018 Update
This commit is contained in:
parent
ba8067c3b7
commit
22f33d4004
5278 changed files with 84726 additions and 14379 deletions
101
Task/Amb/C-sharp/amb-3.cs
Normal file
101
Task/Amb/C-sharp/amb-3.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
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 };
|
||||
_itemsChoices.Add(array);
|
||||
return array;
|
||||
}
|
||||
|
||||
public void Require(Func<bool> predicate) =>
|
||||
_constraints.Add(new Constraint { Predicate = predicate, AppliesForItems = _itemsChoices.Count });
|
||||
|
||||
public bool RequireFinal(Func<bool> predicate)
|
||||
{
|
||||
Require(predicate);
|
||||
return Disambiguate();
|
||||
}
|
||||
|
||||
public bool Disambiguate()
|
||||
{
|
||||
try
|
||||
{
|
||||
Disambiguate(0, 0);
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex) when (ex.Message == "Success")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
interface IChoices
|
||||
{
|
||||
int Length { get; }
|
||||
int Index { get; set; }
|
||||
}
|
||||
|
||||
interface IConstraint
|
||||
{
|
||||
int AppliesForItems { get; }
|
||||
bool Invoke();
|
||||
}
|
||||
|
||||
List<IChoices> _itemsChoices = new List<IChoices>();
|
||||
List<IConstraint> _constraints = new List<IConstraint>();
|
||||
|
||||
void Disambiguate(int itemsTracked, int constraintIndex)
|
||||
{
|
||||
while (constraintIndex < _constraints.Count && _constraints[constraintIndex].AppliesForItems <= itemsTracked)
|
||||
{
|
||||
if (!_constraints[constraintIndex].Invoke())
|
||||
return;
|
||||
constraintIndex++;
|
||||
}
|
||||
|
||||
if (itemsTracked == _itemsChoices.Count)
|
||||
{
|
||||
throw new Exception("Success");
|
||||
}
|
||||
|
||||
for (var i = 0; i < _itemsChoices[itemsTracked].Length; i++)
|
||||
{
|
||||
_itemsChoices[itemsTracked].Index = i;
|
||||
Disambiguate(itemsTracked + 1, constraintIndex);
|
||||
}
|
||||
}
|
||||
|
||||
class Constraint : IConstraint
|
||||
{
|
||||
internal int AppliesForItems;
|
||||
int IConstraint.AppliesForItems => AppliesForItems;
|
||||
|
||||
internal Func<bool> Predicate;
|
||||
public bool Invoke() => Predicate?.Invoke() ?? default;
|
||||
}
|
||||
|
||||
class ChoiceArray<T> : IChoices, IValue<T>
|
||||
{
|
||||
internal T[] Values;
|
||||
|
||||
public int Index { get; set; }
|
||||
|
||||
public T Value { get { return Values[Index]; } }
|
||||
|
||||
public int Length => Values.Length;
|
||||
|
||||
public override string ToString() => Value.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Task/Amb/C-sharp/amb-4.cs
Normal file
36
Task/Amb/C-sharp/amb-4.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
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.RequireFinal(() => set3.Value.Last() == set4.Value[0]);
|
||||
|
||||
WriteLine($"{set1} {set2} {set3} {set4}");
|
||||
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.RequireFinal(() => x.Value* y.Value == 8);
|
||||
|
||||
WriteLine($"{x} * {y} = 8");
|
||||
Read();
|
||||
Read();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,24 +6,24 @@ joinable = (:aFormer:aLater)(aFormer[aFormer length - 1] == aLater[0]).
|
|||
|
||||
dispatcher =
|
||||
{
|
||||
eval object:anArray func2:aFunction
|
||||
eval(object anArray, Func2 aFunction)
|
||||
[
|
||||
^ aFunction eval(anArray[0],anArray[1]).
|
||||
^ aFunction(anArray[0],anArray[1]).
|
||||
]
|
||||
|
||||
eval object:anArray func3:aFunction
|
||||
eval(object anArray, Func3 aFunction)
|
||||
[
|
||||
^ aFunction eval(anArray[0], anArray[1],anArray[2]).
|
||||
^ aFunction(anArray[0], anArray[1],anArray[2]).
|
||||
]
|
||||
|
||||
eval object:anArray func4:aFunction
|
||||
eval(object anArray, Func4 aFunction)
|
||||
[
|
||||
^ aFunction eval(anArray[0],anArray[1],anArray[2],anArray[3]).
|
||||
^ aFunction(anArray[0],anArray[1],anArray[2],anArray[3]).
|
||||
]
|
||||
|
||||
eval object:anArray func5:aFunction
|
||||
eval(object anArray, Func5 aFunction)
|
||||
[
|
||||
^ aFunction eval(anArray[0],anArray[1],anArray[2],anArray[3],anArray[4]).
|
||||
^ aFunction(anArray[0],anArray[1],anArray[2],anArray[3],anArray[4]).
|
||||
]
|
||||
|
||||
}.
|
||||
|
|
@ -32,9 +32,9 @@ class AmbValueCollection
|
|||
{
|
||||
object theCombinator.
|
||||
|
||||
constructor new args:Arguments
|
||||
constructor new(V<object> Arguments)
|
||||
[
|
||||
theCombinator := SequentialEnumerator new args:Arguments.
|
||||
theCombinator := SequentialEnumerator new(Arguments).
|
||||
]
|
||||
|
||||
seek : aCondition
|
||||
|
|
@ -55,15 +55,15 @@ class AmbValueCollection
|
|||
|
||||
ambOperator =
|
||||
{
|
||||
generic for args:Arguments
|
||||
= AmbValueCollection new args:Arguments.
|
||||
generic for(V<object> Arguments)
|
||||
= AmbValueCollection new(Arguments).
|
||||
}.
|
||||
|
||||
program =
|
||||
public program =
|
||||
[
|
||||
try(ambOperator
|
||||
for(("the","that","a"),("frog", "elephant", "thing"),("walked", "treaded", "grows"),("slowly", "quickly"));
|
||||
seek(:a:b:c:d) ( joinable eval(a,b) && joinable eval(b,c) && joinable eval(c,d) );
|
||||
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) ])
|
||||
{
|
||||
on(Exception e)
|
||||
|
|
|
|||
|
|
@ -2,51 +2,55 @@
|
|||
# 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,objs...)
|
||||
n=length(objs)
|
||||
if n==1 return end
|
||||
states=cell(n)
|
||||
values=cell(n)
|
||||
# starting point, we put down the first value from the first iterable object
|
||||
states[1]=start(objs[1])
|
||||
values[1],states[1]=next(objs[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(objs[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(objs[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(objs[i])
|
||||
values[i],states[i]=next(objs[i],states[i])
|
||||
end
|
||||
end
|
||||
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
|
||||
|
||||
println(join(amb(
|
||||
(s1,s2)->s1[end]!=s2[1],
|
||||
["the","that","a"],
|
||||
["frog","elephant","thing"],
|
||||
["walked","treaded","grows"],
|
||||
["slowly","quickly"]
|
||||
)," "))
|
||||
amb((s1,s2) -> s1[end] != s2[1], # failure function
|
||||
["the", "that", "a"],
|
||||
["frog", "elephant", "thing"],
|
||||
["walked", "treaded", "grows"],
|
||||
["slowly", "quickly"]) |>
|
||||
x -> join(x, " ") |>
|
||||
println
|
||||
|
|
|
|||
|
|
@ -1,41 +1,104 @@
|
|||
// version 1.1.3
|
||||
// version 1.2.41
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
typealias Constraint<T> = (T, T) -> Boolean
|
||||
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")
|
||||
|
||||
fun <T> amb(lists: List<List<T>>, res: MutableList<T>, cons: Constraint<T>): Boolean {
|
||||
if (lists.isEmpty()) return true
|
||||
if (lists[0].isEmpty()) return false
|
||||
val z = res.size
|
||||
for ((i, el) in lists[0].withIndex()) {
|
||||
if (i == 0) res.add(el) else res[z] = el
|
||||
if (z > 0 && !cons(res[z - 1], res[z])) continue
|
||||
if (amb(lists.drop(1), res, cons)) return true
|
||||
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
|
||||
}
|
||||
res.removeAt(z)
|
||||
return false
|
||||
|
||||
suspend fun amb(): Nothing = suspendCoroutine<Nothing> { }
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val wordLists = listOf(
|
||||
listOf("the", "that", "a"),
|
||||
listOf("frog", "elephant", "thing"),
|
||||
listOf("walked", "treaded", "grows"),
|
||||
listOf("slowly", "quickly")
|
||||
)
|
||||
val res = mutableListOf<String>()
|
||||
val cons: Constraint<String> = { x, y -> x.last() == y.first() }
|
||||
if (amb(wordLists, res, cons))
|
||||
println(res)
|
||||
@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
|
||||
println("No solution found")
|
||||
val numLists = listOf(
|
||||
listOf(1, 2, 3),
|
||||
listOf(7, 6, 4, 5)
|
||||
)
|
||||
val res2 = mutableListOf<Int>()
|
||||
val cons2: Constraint<Int> = { x, y -> x * y == 8 }
|
||||
if (amb(numLists, res2, cons2))
|
||||
println(res2)
|
||||
else
|
||||
println("No solution found")
|
||||
{
|
||||
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)
|
||||
}
|
||||
|
|
|
|||
44
Task/Amb/Rust/amb.rust
Normal file
44
Task/Amb/Rust/amb.rust
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
use std::ops::Add;
|
||||
struct Amb<'a> {
|
||||
list: Vec<Vec<&'a str>>,
|
||||
}
|
||||
fn main() {
|
||||
let amb = Amb {
|
||||
list: vec![
|
||||
vec!["the", "that", "a"],
|
||||
vec!["frog", "elephant", "thing"],
|
||||
vec!["walked", "treaded", "grows"],
|
||||
vec!["slowly", "quickly"],
|
||||
],
|
||||
};
|
||||
match amb.do_amb(0, 0 as char) {
|
||||
Some(text) => println!("{}", text),
|
||||
None => println!("Nothing found"),
|
||||
}
|
||||
}
|
||||
impl<'a> Amb<'a> {
|
||||
fn do_amb(&self, level: usize, last_char: char) -> Option<String> {
|
||||
if self.list.is_empty() {
|
||||
panic!("No word list");
|
||||
}
|
||||
if self.list.len() <= level {
|
||||
return Some(String::new());
|
||||
}
|
||||
let mut res = String::new();
|
||||
let word_list = &self.list[level];
|
||||
for word in word_list {
|
||||
if word.chars().next().unwrap() == last_char || last_char == 0 as char {
|
||||
res = res.add(word).add(" ");
|
||||
let answ = self.do_amb(level + 1, word.chars().last().unwrap());
|
||||
match answ {
|
||||
Some(x) => {
|
||||
res = res.add(&x);
|
||||
return Some(res);
|
||||
}
|
||||
None => res.clear(),
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue