June 2018 Update
This commit is contained in:
parent
ba8067c3b7
commit
22f33d4004
5278 changed files with 84726 additions and 14379 deletions
|
|
@ -2,4 +2,9 @@
|
|||
|
||||
Some languages offer direct support for [[wp:Algebraic_data_type|algebraic data types]] and pattern matching on them. While this of course can always be simulated with manual tagging and conditionals, it allows for terse code which is easy to read, and can represent the algorithm directly.
|
||||
|
||||
As an example, implement insertion in a [[wp:Red_Black_Tree|red-black-tree]]. A red-black-tree is a binary tree where each internal node has a color attribute ''red'' or ''black''. Moreover, no red node can have a red child, and every path from the root to an empty node must contain the same number of black nodes. As a consequence, the tree is balanced, and must be re-balanced after an insertion.
|
||||
|
||||
;Task:
|
||||
As an example, implement insertion in a [[wp:Red_Black_Tree|red-black-tree]].
|
||||
|
||||
A red-black-tree is a binary tree where each internal node has a color attribute ''red'' or ''black''. Moreover, no red node can have a red child, and every path from the root to an empty node must contain the same number of black nodes. As a consequence, the tree is balanced, and must be re-balanced after an insertion.
|
||||
<br><br>
|
||||
|
|
|
|||
45
Task/Pattern-matching/C++/pattern-matching-1.cpp
Normal file
45
Task/Pattern-matching/C++/pattern-matching-1.cpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
enum Color { R, B };
|
||||
template<Color, class, auto, class> struct T;
|
||||
struct E;
|
||||
|
||||
template<Color col, class a, auto x, class b> struct balance {
|
||||
using type = T<col, a, x, b>;
|
||||
};
|
||||
template<class a, auto x, class b, auto y, class c, auto z, class d>
|
||||
struct balance<B, T<R, T<R, a, x, b>, y, c>, z, d> {
|
||||
using type = T<R, T<B, a, x, b>, y, T<B, c, z, d>>;
|
||||
};
|
||||
template<class a, auto x, class b, auto y, class c, auto z, class d>
|
||||
struct balance<B, T<R, a, x, T<R, b, y, c>>, z, d> {
|
||||
using type = T<R, T<B, a, x, b>, y, T<B, c, z, d>>;
|
||||
};
|
||||
template<class a, auto x, class b, auto y, class c, auto z, class d>
|
||||
struct balance<B, a, x, T<R, T<R, b, y, c>, z, d>> {
|
||||
using type = T<R, T<B, a, x, b>, y, T<B, c, z, d>>;
|
||||
};
|
||||
template<class a, auto x, class b, auto y, class c, auto z, class d>
|
||||
struct balance<B, a, x, T<R, b, y, T<R, c, z, d>>> {
|
||||
using type = T<R, T<B, a, x, b>, y, T<B, c, z, d>>;
|
||||
};
|
||||
|
||||
template<auto x, class s> struct insert {
|
||||
template<class, class = void> struct ins;
|
||||
template<class _> struct ins<E, _> { using type = T<R, E, x, E>; };
|
||||
template<Color col, class a, auto y, class b> struct ins<T<col, a, y, b>> {
|
||||
template<int, class = void> struct cond;
|
||||
template<class _> struct cond<-1, _> : balance<col, typename ins<a>::type, y, b> {};
|
||||
template<class _> struct cond<1, _> : balance<col, a, y, typename ins<b>::type> {};
|
||||
template<class _> struct cond<0, _> { using type = T<col, a, y, b>; };
|
||||
using type = typename cond<x < y ? -1 : y < x ? 1 : 0>::type;
|
||||
};
|
||||
template<class> struct repaint;
|
||||
template<Color col, class a, auto y, class b>
|
||||
struct repaint<T<col, a, y, b>> { using type = T<B, a, y, b>; };
|
||||
using type = typename repaint<typename ins<s>::type>::type;
|
||||
};
|
||||
template<auto x, class s> using insert_t = typename insert<x, s>::type;
|
||||
|
||||
template<class> void print();
|
||||
int main() {
|
||||
print<insert_t<1, insert_t<2, insert_t<0, insert_t<4, E>>>>>();
|
||||
}
|
||||
103
Task/Pattern-matching/C++/pattern-matching-2.cpp
Normal file
103
Task/Pattern-matching/C++/pattern-matching-2.cpp
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
#include <memory>
|
||||
#include <variant>
|
||||
|
||||
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
|
||||
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
enum Color { R, B };
|
||||
using E = std::monostate;
|
||||
template<class, Color> struct Node;
|
||||
template<class T, Color C> using Ptr = std::unique_ptr<Node<T, C>>;
|
||||
template<class T> using Tree = std::variant<E, Ptr<T, R>, Ptr<T, B>>;
|
||||
template<class T, Color Col> struct Node {
|
||||
static constexpr auto C = Col;
|
||||
Tree<T> left;
|
||||
T value;
|
||||
Tree<T> right;
|
||||
};
|
||||
template<Color C, class A, class T, class B> Tree<T> tree(A&& a, T& x, B&& b) {
|
||||
return Tree<T>{Ptr<T, C>{new Node<T, C>{std::move(a), std::move(x), std::move(b)}}};
|
||||
}
|
||||
|
||||
template<class T> Tree<T> balance(Tree<T> s) {
|
||||
auto&& ll = [](Ptr<T, R>& s, Ptr<T, R>& t, auto&, Ptr<T, B>& u, auto&, auto&, auto&) {
|
||||
auto& [a, x, b] = *s;
|
||||
auto& [s_, y, c] = *t;
|
||||
auto& [t_, z, d] = *u;
|
||||
return tree<R>(tree<B>(a, x, b), y, tree<B>(c, z, d));
|
||||
};
|
||||
auto&& lr = [](auto&, Ptr<T, R>& s, Ptr<T, R>& t, Ptr<T, B>& u, auto&, auto&, auto&) {
|
||||
auto& [a, x, t_] = *s;
|
||||
auto& [b, y, c] = *t;
|
||||
auto& [s_, z, d] = *u;
|
||||
return tree<R>(tree<B>(a, x, b), y, tree<B>(c, z, d));
|
||||
};
|
||||
auto&& rl = [](auto&, auto&, auto&, Ptr<T, B>& s, Ptr<T, R>& t, Ptr<T, R>& u, auto&) {
|
||||
auto& [a, x, u_] = *s;
|
||||
auto& [b, y, c] = *t;
|
||||
auto& [t_, z, d] = *u;
|
||||
return tree<R>(tree<B>(a, x, b), y, tree<B>(c, z, d));
|
||||
};
|
||||
auto&& rr = [](auto&, auto&, auto&, Ptr<T, B>& s, auto&, Ptr<T, R>& t, Ptr<T, R>& u) {
|
||||
auto& [a, x, t_] = *s;
|
||||
auto& [b, y, u_] = *t;
|
||||
auto& [c, z, d] = *u;
|
||||
return tree<R>(tree<B>(a, x, b), y, tree<B>(c, z, d));
|
||||
};
|
||||
auto&& l = [](auto& s) -> Tree<T>& {
|
||||
return *std::visit(overloaded{[&](E) { return &s; }, [](auto& t) { return &t->left; }}, s);
|
||||
};
|
||||
auto&& r = [](auto& s) -> Tree<T>& {
|
||||
return *std::visit(overloaded{[&](E) { return &s; }, [](auto& t) { return &t->right; }}, s);
|
||||
};
|
||||
return std::visit([&](auto&... ss) -> Tree<T> {
|
||||
if constexpr (1 <
|
||||
std::is_invocable_v<decltype(ll), decltype(ss)...> +
|
||||
std::is_invocable_v<decltype(lr), decltype(ss)...> +
|
||||
std::is_invocable_v<decltype(rl), decltype(ss)...> +
|
||||
std::is_invocable_v<decltype(rr), decltype(ss)...>)
|
||||
throw std::logic_error{""};
|
||||
else
|
||||
return overloaded{ll, lr, rl, rr, [&](auto&... ss) { return std::move(s); }}(ss...);
|
||||
}, l(l(s)), l(s), r(l(s)), s, l(r(s)), r(s), r(r(s)));
|
||||
}
|
||||
template<class T> Tree<T> ins(T& x, Tree<T>& s) {
|
||||
return std::visit(overloaded{
|
||||
[&](E) -> Tree<T> { return tree<R>(s, x, s); },
|
||||
[&](auto& t) {
|
||||
auto& [a, y, b] = *t;
|
||||
static constexpr auto Col = std::remove_reference_t<decltype(*t)>::C;
|
||||
return x < y ? balance(tree<Col>(ins(x, a), y, b)) :
|
||||
y < x ? balance(tree<Col>(a, y, ins(x, b))) :
|
||||
std::move(s);
|
||||
},
|
||||
}, s);
|
||||
}
|
||||
template<class T> Tree<T> insert(T x, Tree<T> s) {
|
||||
return std::visit(overloaded{
|
||||
[](E) -> Tree<T> { throw std::logic_error{""}; },
|
||||
[](auto&& t) {
|
||||
auto& [a, y, b] = *t;
|
||||
return tree<B>(a, y, b);
|
||||
}
|
||||
}, ins(x, s));
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
template<class T> void print(Tree<T> const& s, int i = 0) {
|
||||
std::visit(overloaded{
|
||||
[](E) {},
|
||||
[&](auto& t) {
|
||||
auto& [a, y, b] = *t;
|
||||
print(a, i + 1);
|
||||
std::cout << std::string(i, ' ') << "RB"[t->C] << " " << y << "\n";
|
||||
print(b, i + 1);
|
||||
}
|
||||
}, s);
|
||||
}
|
||||
int main(int argc, char* argv[]) {
|
||||
auto t = Tree<std::string>{};
|
||||
for (auto i = 1; i != argc; ++i)
|
||||
t = insert(std::string{argv[i]}, std::move(t));
|
||||
print(t);
|
||||
}
|
||||
84
Task/Pattern-matching/Kotlin/pattern-matching.kotlin
Normal file
84
Task/Pattern-matching/Kotlin/pattern-matching.kotlin
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
// version 1.1.51
|
||||
|
||||
import Color.*
|
||||
|
||||
enum class Color { R, B }
|
||||
|
||||
sealed class Tree<A : Comparable<A>> {
|
||||
|
||||
fun insert(x: A): Tree<A> {
|
||||
val t = ins(x)
|
||||
return when (t) {
|
||||
is T -> {
|
||||
val (_, a, y, b) = t
|
||||
T(B, a, y, b)
|
||||
}
|
||||
|
||||
is E -> E()
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun ins(x: A): Tree<A>
|
||||
}
|
||||
|
||||
class E<A : Comparable<A>> : Tree<A>() {
|
||||
|
||||
override fun ins(x: A): Tree<A> = T(R, E(), x, E())
|
||||
|
||||
override fun toString() = "E"
|
||||
}
|
||||
|
||||
data class T<A : Comparable<A>>(
|
||||
val cl: Color,
|
||||
val le: Tree<A>,
|
||||
val aa: A,
|
||||
val ri: Tree<A>
|
||||
) : Tree<A>() {
|
||||
|
||||
private fun balance(): Tree<A> {
|
||||
if (cl != B) return this
|
||||
val res =
|
||||
if (le is T && le.le is T && le.cl == R && le.le.cl == R) {
|
||||
val (_, t, z, d) = this
|
||||
val (_, t2, y, c) = t as T
|
||||
val (_, a, x, b) = t2 as T
|
||||
T(R, T(B, a, x, b), y, T(B, c, z, d))
|
||||
}
|
||||
else if (le is T && le.ri is T && le.cl == R && le.ri.cl == R) {
|
||||
val (_, t, z, d) = this
|
||||
val (_, a, x, t2) = t as T
|
||||
val (_, b, y, c) = t2 as T
|
||||
T(R, T(B, a, x, b), y, T(B, c, z, d))
|
||||
}
|
||||
else if (ri is T && ri.le is T && ri.cl == R && ri.le.cl == R) {
|
||||
val (_, a, x, t) = this
|
||||
val (_, t2, z, d) = t as T
|
||||
val (_, b, y, c) = t2 as T
|
||||
T(R, T(B, a, x, b), y, T(B, c, z, d))
|
||||
}
|
||||
else if (ri is T && ri.ri is T && ri.cl == R && ri.ri.cl == R) {
|
||||
val (_, a, x, t) = this
|
||||
val (_, b, y, t2) = t as T
|
||||
val (_, c, z, d) = t2 as T
|
||||
T(R, T(B, a, x, b), y, T(B, c, z, d))
|
||||
}
|
||||
else this
|
||||
return res
|
||||
}
|
||||
|
||||
override fun ins(x: A): Tree<A> = when (x.compareTo(aa)) {
|
||||
-1 -> T(cl, le.ins(x), aa, ri).balance()
|
||||
+1 -> T(cl, le, aa, ri.ins(x)).balance()
|
||||
else -> this
|
||||
}
|
||||
|
||||
override fun toString() = "T($cl, $le, $aa, $ri)"
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
var tree: Tree<Int> = E()
|
||||
for (i in 1..16) {
|
||||
tree = tree.insert(i)
|
||||
}
|
||||
println(tree)
|
||||
}
|
||||
38
Task/Pattern-matching/REXX/pattern-matching.rexx
Normal file
38
Task/Pattern-matching/REXX/pattern-matching.rexx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*REXX pgm builds a red/black tree (with verification & validation), balances as needed.*/
|
||||
parse arg nodes '/' insert /*obtain optional arguments from the CL*/
|
||||
if nodes='' then nodes = 13.8.17 8.1.11 17.15.25 1.6 25.22.27 /*default nodes.*/
|
||||
if insert='' then insert= 22.44 44.66 /* " inserts*/
|
||||
top=.
|
||||
call Dnodes nodes /*define nodes, balance them as added. */
|
||||
call Dnodes insert /*insert nodes, balance them as needed.*/
|
||||
call Lnodes /*list the nodes (with indentation). */
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
Dnodes: arg $d; do j=1 for words($d); t=word($d, j) /*color: encoded into LEV.*/
|
||||
parse var t p '.' a "." b '.' x 1 . . . xx
|
||||
call Vnodes p a b
|
||||
if x\=='' then call err "too many nodes specified: " xx
|
||||
if p\==top then if @.p==. then call err "node isn't defined: " p
|
||||
if p ==top then do; !.p=1; L.1=p; end /*assign the top node. */
|
||||
@.p=a b; n=!.p + 1 /*assign node; bump level.*/
|
||||
if a\=='' then do; !.a=n; @.a=; maxL=max(maxL, !.a); end
|
||||
if b\=='' then do; !.b=n; @.b=; maxL=max(maxL, !.b); end
|
||||
L.n=space(L.n a b) /*append to the level list*/
|
||||
end /*j*/
|
||||
return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
err: say; say '***error***: ' arg(1); say; exit 13
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
Lnodes: do L=1 for maxL; w=length(maxL); rb=word('(red) (black)', 1 + L//2)
|
||||
say "level:" right(L, w) left('', L+L) " ───► " rb ' ' L.L
|
||||
end /*lev*/
|
||||
return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
Vnodes: arg $v; do v=1 for words($v); y=word($v, v)
|
||||
if \datatype(y, 'W') then call err "node isn't a whole number: " y
|
||||
y=y/1 /*normalize the Y integer: no LZ, dot*/
|
||||
if top==. then do; LO=y; top=y; HI=y; L.=; @.=; maxL=1; end
|
||||
LO=min(LO, y); HI=max(HI, y)
|
||||
if @.y\==. & @.y\=='' then call err "node is already defined: " y
|
||||
end /*v*/
|
||||
return
|
||||
Loading…
Add table
Add a link
Reference in a new issue