Same fringe: Difference between revisions
m
→{{header|Wren}}: Minor tidy
m (→{{header|Wren}}: Minor tidy) |
|||
(6 intermediate revisions by 6 users not shown) | |||
Line 11:
The package is generic, which allows Data to be essentially of any type.
<
type Data is private;
package Bin_Trees is
Line 36:
end record;
end Bin_Trees;</
The implementation is straightforward.
<
package body Bin_Trees is
Line 91:
end Tree;
end Bin_Trees;</
Next, we specify and implement package that defines a task type for tree traversal. This allows us to run any number of tree traversals in parallel, even on the same tree.
<
with procedure Process_Data(Item: Data);
with function Stop return Boolean;
Line 105:
-- except when Stop becomes true; in this case, the task terminates
end Inorder_Task;
end Bin_Trees.Traverse;</
<
task body Inorder_Task is
procedure Inorder(Tree: Tree_Type) is
Line 129:
Finish;
end Inorder_Task;
end Bin_Trees.Traverse;</
When comparing two trees T1 and T2, we will define two tasks, a "Producer.Inorder_Task" and a "Consumer.Inorder_Task". The producer will write data items to a buffer, the consumer will read items from the buffer and compare them with its own data items. Both tasks will terminate when the consumer finds a data item different from the one written by the producer, or when either task has written its last item and the other one has items left.
Line 135:
A third auxiliary task just waits until the consumer has finished and the result of the fringe comparison can be read.
<
procedure Main is
Line 296:
Ada.Text_IO.New_Line;
end loop;
end Main;</
Note that we do not call Destroy_Tree to reclaim the dynamic memory. In our case, this is not needed since the memory will be reclaimed at the end of Main, anyway.
Line 315:
=={{header|Bracmat}}==
<
=
. ( next
Line 352:
, (((a.b).c).x.y.z)
)
);</
Output:
<pre>x,x
Line 374:
=={{header|C}}==
With rudimentary coroutine support based on ucontext. I don't know if it will compile on anything other than GCC.
<
#include <stdlib.h>
#include <ucontext.h>
Line 494:
return 0;
}</
=={{header|c sharp|C#}}==
This task is almost custom designed for C# LINQ and is really trivial using that. Most of the following is support code. The only two routines that actually implement the task at hand are CompareTo and GetLeaves at the bottom. GetLeaves is a really simple BinTree procedure to retreive the leaves from left to right into an IEnumerable. That IEnumerable can be zipped with the result of GetLeaves on another tree and the results compared giving us our final answer and since everything is deferred in LINQ, this has the desirable property spoken of in the problem's description that no comparisons are done after a non-matching pair.
<
using System;
using System.Collections.Generic;
Line 633:
}
}
</syntaxhighlight>
Example output:
Line 639:
True Compare worked
False Compare worked
</pre>
=={{header|C++}}==
Walk through the trees using C++20 coroutines.
<syntaxhighlight lang="cpp">#include <algorithm>
#include <coroutine>
#include <iostream>
#include <memory>
#include <tuple>
#include <variant>
using namespace std;
class BinaryTree
{
// C++ does not have a built in tree type. The binary tree is a recursive
// data type that is represented by an empty tree or a node the has a value
// and a left and right sub-tree. A tuple represents the node and unique_ptr
// represents an empty vs. non-empty tree.
using Node = tuple<BinaryTree, int, BinaryTree>;
unique_ptr<Node> m_tree;
public:
// Provide ways to make trees
BinaryTree() = default; // Make an empty tree
BinaryTree(BinaryTree&& leftChild, int value, BinaryTree&& rightChild)
: m_tree {make_unique<Node>(move(leftChild), value, move(rightChild))} {}
BinaryTree(int value) : BinaryTree(BinaryTree{}, value, BinaryTree{}){}
BinaryTree(BinaryTree&& leftChild, int value)
: BinaryTree(move(leftChild), value, BinaryTree{}){}
BinaryTree(int value, BinaryTree&& rightChild)
: BinaryTree(BinaryTree{}, value, move(rightChild)){}
// Test if the tree is empty
explicit operator bool() const
{
return (bool)m_tree;
}
// Get the value of the root node of the tree
int Value() const
{
return get<1>(*m_tree);
}
// Get the left child tree
const BinaryTree& LeftChild() const
{
return get<0>(*m_tree);
}
// Get the right child tree
const BinaryTree& RightChild() const
{
return get<2>(*m_tree);
}
};
// Define a promise type to be used for coroutines
struct TreeWalker {
struct promise_type {
int val;
suspend_never initial_suspend() noexcept {return {};}
suspend_never return_void() noexcept {return {};}
suspend_always final_suspend() noexcept {return {};}
void unhandled_exception() noexcept { }
TreeWalker get_return_object()
{
return TreeWalker{coroutine_handle<promise_type>::from_promise(*this)};
}
suspend_always yield_value(int x) noexcept
{
val=x;
return {};
}
};
coroutine_handle<promise_type> coro;
TreeWalker(coroutine_handle<promise_type> h): coro(h) {}
~TreeWalker()
{
if(coro) coro.destroy();
}
// Define an iterator type to work with the coroutine
class Iterator
{
const coroutine_handle<promise_type>* m_h = nullptr;
public:
Iterator() = default;
constexpr Iterator(const coroutine_handle<promise_type>* h) : m_h(h){}
Iterator& operator++()
{
m_h->resume();
return *this;
}
Iterator operator++(int)
{
auto old(*this);
m_h->resume();
return old;
}
int operator*() const
{
return m_h->promise().val;
}
bool operator!=(monostate) const noexcept
{
return !m_h->done();
return m_h && !m_h->done();
}
bool operator==(monostate) const noexcept
{
return !operator!=(monostate{});
}
};
constexpr Iterator begin() const noexcept
{
return Iterator(&coro);
}
constexpr monostate end() const noexcept
{
return monostate{};
}
};
// Allow the iterator to be used like a standard library iterator
namespace std {
template<>
class iterator_traits<TreeWalker::Iterator>
{
public:
using difference_type = std::ptrdiff_t;
using size_type = std::size_t;
using value_type = int;
using pointer = int*;
using reference = int&;
using iterator_category = std::input_iterator_tag;
};
}
// A coroutine that iterates though all of the fringe nodes
TreeWalker WalkFringe(const BinaryTree& tree)
{
if(tree)
{
auto& left = tree.LeftChild();
auto& right = tree.RightChild();
if(!left && !right)
{
// a fringe node because it has no children
co_yield tree.Value();
}
for(auto v : WalkFringe(left))
{
co_yield v;
}
for(auto v : WalkFringe(right))
{
co_yield v;
}
}
co_return;
}
// Print a tree
void PrintTree(const BinaryTree& tree)
{
if(tree)
{
cout << "(";
PrintTree(tree.LeftChild());
cout << tree.Value();
PrintTree(tree.RightChild());
cout <<")";
}
}
// Compare two trees
void Compare(const BinaryTree& tree1, const BinaryTree& tree2)
{
// Create a lazy range for both trees
auto walker1 = WalkFringe(tree1);
auto walker2 = WalkFringe(tree2);
// Compare the ranges.
bool sameFringe = ranges::equal(walker1.begin(), walker1.end(),
walker2.begin(), walker2.end());
// Print the results
PrintTree(tree1);
cout << (sameFringe ? " has same fringe as " : " has different fringe than ");
PrintTree(tree2);
cout << "\n";
}
int main()
{
// Create two trees that that are different but have the same fringe nodes
BinaryTree tree1(BinaryTree{6}, 77, BinaryTree{BinaryTree{3}, 77,
BinaryTree{77, BinaryTree{9}}});
BinaryTree tree2(BinaryTree{BinaryTree{BinaryTree{6}, 77}, 77, BinaryTree{
BinaryTree{3}, 77, BinaryTree{9}}});
// Create a tree with a different fringe
BinaryTree tree3(BinaryTree{BinaryTree{BinaryTree{6}, 77}, 77, BinaryTree{77, BinaryTree{9}}});
// Compare the trees
Compare(tree1, tree2);
Compare(tree1, tree3);
}</syntaxhighlight>
{{out}}
<pre>
((6)77((3)77(77(9)))) has same fringe as (((6)77)77((3)77(9)))
((6)77((3)77(77(9)))) has different fringe than (((6)77)77(77(9)))
</pre>
Line 649 ⟶ 878:
''children'' returns the children of a branch node; ''content'' returns the content of a branch node.
A fringe value is either the content of a branch node without children, or a non-branch node.
<
(letfn [(walk [node]
(lazy-seq
Line 657 ⟶ 886:
(mapcat walk (children node)))
(list node))))]
(walk tree)))</
For this problem, binary trees are represented as vectors, whose nodes are either [''content'' ''left'' ''right''] or just ''content''.
<
(println (vfringe-seq [10 1 2])) ; (1 2)
(println (vfringe-seq [10 [1 nil nil] [20 2 nil]])) ; (1 2)</
Then we can use a general sequence-equality function:
<
(cond
(and (empty? s1) (empty? s2)) true
(not= (empty? s1) (empty? s2)) false
(= (first s1) (first s2)) (recur (rest s1) (rest s2))
:else false))</
=={{header|D}}==
===Short Version===
A short recursive solution that is not lazy (and lacks the const/immutable/pure/nothrow):
<
T data;
Node* L, R;
Line 694 ⟶ 923:
auto t3 = new N(1, new N(2, new N(3, new N(40), new N(51))));
writeln(sameFringe(t1, t3));
}</
{{out}}
<pre>true
Line 701 ⟶ 930:
===Strong Lazy Version===
This version is quite long because it tries to be reliable. The code contains contracts, unit tests, annotations, and so on.
<
import std.algorithm: equal;
Line 894 ⟶ 1,123:
writeln("sameFringe(t1, t2): ", sameFringe(t1, t2));
writeln("sameFringe(t1, t3): ", sameFringe(t1, t3));
}</
{{out}}
<pre>fringe(t1): [40, 50]
Line 903 ⟶ 1,132:
===Range Generator Version (Lazy)===
<
struct Node(T) {
Line 946 ⟶ 1,175:
auto t7 = new N(1, new N(2));
sameFringe(t6, t7).writeln;
}</
{{out}}
<pre>true
Line 956 ⟶ 1,185:
=={{header|Go}}==
<
import "fmt"
Line 1,026 ⟶ 1,255:
&node{int: 13}}
fmt.Println(sameFringe(t1, t2)) // prints true.
}</
=={{header|Haskell}}==
Line 1,032 ⟶ 1,261:
To get the fringe, we can simply use the solution for [[Flatten a list#Haskell|Flatten a list]], slightly modified for a binary tree instead of a general tree:
<
= Leaf a
| Node (Tree a)
Line 1,060 ⟶ 1,289:
y = Node (Leaf 0) (Node (Node (Leaf 2) (Leaf 3)) (Node (Leaf 4) (Leaf 5)))
z = Node (Leaf 1) (Node (Leaf 2) (Node (Node (Leaf 4) (Leaf 3)) (Leaf 5)))
mapM_ print $ sameFringe a <$> [a, b, c, x, y, z]</
{{Out}}
<pre>True
Line 1,073 ⟶ 1,302:
The following solution works in both languages:
<
aTree := [1, [2, [4, [7]], [5]], [3, [6, [8], [9]]]]
bTree := [1, [2, [4, [7]], [5]], [3, [6, [8], [9]]]]
Line 1,102 ⟶ 1,331:
procedure preorder(L)
if \L then suspend L | preorder(L[2|3])
end</
Output:
Line 1,115 ⟶ 1,344:
=={{header|J}}==
<
Note that the time/space optimizations here can change with the language implementation, but current implementations make no effort to treat trees efficiently.
Line 1,123 ⟶ 1,352:
Anyways, here's a recursive routine to convert a flat list into a binary tree:
<
And, here are two differently structured trees which represent the same underlying data:
<
ubp=: p:L:0] 10;~list2tree i.10</
And, here's our original operation in action (<code>1 {:: ubp</code> is a subtree of ubp which omits a leaf node):
<
1
bp sameFringe 1 {:: ubp
0</
=={{header|Java}}==
Line 1,142 ⟶ 1,371:
'''Code:'''
<
class SameFringe
Line 1,262 ⟶ 1,491:
}
}
}</
'''Output:'''
Line 1,276 ⟶ 1,505:
With this data structure, a test for whether two trees, s and t, have the same fringes could be implemented simply as:
<
but this entails generating the lists of leaves.
To accomplish the "same fringe" task efficiently in jq 1.4 without generating a list of leaves, a special-purpose function is needed. This special-purpose function, which is here named "next", would ordinarily be defined as an inner function of "same_fringe", but for clarity, it is defined as a top-level function.
<
# by ensuring that the non-null output of a call to "next" can also serve as input.
#
Line 1,312 ⟶ 1,541:
end;
eq([t,[]]|next; [u,[]]|next) ;</
'''Example''':
<
| [[[[[[1,2],3],4],5],6],7] as $b
| [[[1,2],3],[4,[5,[6,7]]]] as $c
Line 1,323 ⟶ 1,552:
same_fringe( ["a",["b",["c",[["x","y"],"z"]]]];
[[["a","b"],"c"],["x",["y","z"]]] )</
{{out}}
<
true
true
Line 1,336 ⟶ 1,565:
false
true
</syntaxhighlight>
=={{header|Julia}}==
<syntaxhighlight lang="julia">
using Lazy
Line 1,390 ⟶ 1,619:
println(equalsfringe(a, y) == false)
println(equalsfringe(a, z) == false)
</syntaxhighlight>
{{output}}
<pre>
Line 1,415 ⟶ 1,644:
In this example, an internal node of a tree is either a "branch", a table with exactly two elements, or the distinguished value None -- everything else is a fringe (leaf) value. <i>fringeiter</i> creates an iterator function to produce successive elements of the fringe.
<
None = {} -- a unique object for a truncated branch (i.e. empty subtree)
Line 1,471 ⟶ 1,700:
compare_fringe("(t1, t2)", t1, t2)
compare_fringe("(t1, t3)", t1, t3)
</syntaxhighlight>
{{out}}
Line 1,480 ⟶ 1,709:
We define an iterator “nodes” which yields the successive nodes of a tree. To compare the fringes, we get the successive nodes using an iterator for each tree and stop iterations as soon as a difference is found.
<
type Node = ref object
Line 1,563 ⟶ 1,792:
let s = if haveSameFringe(tree1, tree2): "have " else: "don’t have "
echo "The trees ", s, "same fringe: ", toSeq(tree1.nodes()).mapIt(it.value).join(", ")</
{{out}}
Line 1,572 ⟶ 1,801:
=={{header|OCaml}}==
While we could use a lazy datatype such as [http://caml.inria.fr/pub/docs/manual-ocaml/libref/Stream.html Stream] for this problem, this example implements the short-circuit behavior (returning on first mismatch) by tracking the parse state.
<
let rec next = function
Line 1,594 ⟶ 1,823:
let check a b =
print_endline (if samefringe a b then "same" else "different") in
check u v; check v u; check v w;</
Output:
<pre>same
Line 1,605 ⟶ 1,834:
The tree iterator is pretty simple: we use array references with index 0 as the left subtree and index 1 holding the right subtree. So as we go down the tree towards the first leaf, we push each right subtree that we will consider later onto the rtree stack. Eventually, we'll hit a leaf and return it. The next time we go into the iterator, we simply pull off the last deferred subtree and continue the process.
<
#!/usr/bin/perl
use strict;
Line 1,643 ⟶ 1,872:
}
}
</syntaxhighlight>
{{out}}
<pre>
Line 1,651 ⟶ 1,880:
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(notonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\Same_Fringe.exw
-- ============================
--
-- In some cases it may help to replace the single res with a table, such
-- that if you have concurrent task pairs {1,2} and {3,4} with a table of
-- result indexes ridx = {1,1,2,2}, then each updates res[ridx[tidx]]. In
-- other words if extending tasks[] rather than overwriting it, you would
-- also extend res[] and ridx[] and sdata[], and need freelist handling.
--</span>
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (multitasking)</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">}</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tasks</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">sdata</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: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</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;">active_tasks</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">show_details</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">scan</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">tree</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">level</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">tidx</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">object</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">left</span><span style="color: #0000FF;">,</span><span style="color: #000000;">data</span><span style="color: #0000FF;">,</span><span style="color: #000000;">right</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tree</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: #008080;">if</span> <span style="color: #000000;">left</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">scan</span><span style="color: #0000FF;">(</span><span style="color: #000000;">left</span><span style="color: #0000FF;">,</span><span style="color: #000000;">level</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tidx</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">sdata</span><span style="color: #0000FF;">[</span><span style="color: #000000;">tidx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">data</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">show_details</span> <span style="color: #008080;">then</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;">"task[%d] sets sdata[%d] to %v\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tidx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tidx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">data</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</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;">task_suspend</span><span style="color: #0000FF;">(</span><span style="color: #000000;">task_self</span><span style="color: #0000FF;">())</span>
<span style="color: #000000;">task_yield</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">right</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">scan</span><span style="color: #0000FF;">(</span><span style="color: #000000;">right</span><span style="color: #0000FF;">,</span><span style="color: #000000;">level</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tidx</span><span style="color: #0000FF;">)</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;">if</span> <span style="color: #000000;">level</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">show_details</span> <span style="color: #008080;">then</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;">"task[%d] ends\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tidx</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">active_tasks</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">tasks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">tidx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">sdata</span><span style="color: #0000FF;">[</span><span style="color: #000000;">tidx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #000080;font-style:italic;">-- (or use a separate flag or tasks[tidx])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t2</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">tasks</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">task_create</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"scan"</span><span style="color: #0000FF;">),{</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}),</span>
<span style="color: #000000;">task_create</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"scan"</span><span style="color: #0000FF;">),{</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t2</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;">active_tasks</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">active_tasks</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">do</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: #000000;">2</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">tasks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">task_schedule</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tasks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">task_yield</span><span style="color: #0000FF;">()</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;">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: #000080;font-style:italic;">-- (nb next might only be valid for active_tasks==2)</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">compare</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sdata</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">sdata</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">show_details</span> <span style="color: #008080;">then</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;">"compare(%v,%v) ==> %d, active tasks:%d\n"</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">sdata</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">sdata</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;">active_tasks</span><span style="color: #0000FF;">})</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;">while</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;">"test(%d,%d):%d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t2</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: #0000FF;">?</span><span style="color: #008000;">"started"</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">show_details</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #0000FF;">?</span><span style="color: #008000;">"done"</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,735 ⟶ 1,968:
task[1] sets sdata[1] to 1
task[2] sets sdata[2] to 1
compare(1,1) ==> 0, active tasks:2
task[1] sets sdata[1] to 2
task[2] sets sdata[2] to 2
compare(2,2) ==> 0, active tasks:2
task[1] ends
task[2] ends
compare(-1,-1) ==> 0, active tasks:0
test(1,1):0
test(1,2):0
Line 1,751 ⟶ 1,984:
test(3,2):1
test(3,3):0
"done"
</pre>
=={{header|Phixmonti}}==
<syntaxhighlight lang="Phixmonti">include ..\Utilitys.pmt
(
/# 1..3 are same #/
( "d" ( "c" ( "a" "b" ) ) )
( ( "d" "c" ) ( "a" "b" ) )
( ( ( "d" "c" ) "a" ) "b" )
/# and this one"s different! #/
( ( ( ( ( ( "a" ) "b" ) "c" ) "d" ) "e" ) "f" )
)
dup
len for >ps
tps get flatten ps> set
endfor
len 1 - for >ps
tps get swap tps 1 + get rot ==
( "Tree " tps " and " ps> 1 + " is " ) lprint
if "the same." else "different." endif ?
endfor</syntaxhighlight>
{{out}}
<pre>Tree 1 and 2 is the same.
Tree 2 and 3 is the same.
Tree 3 and 4 is different.
=== Press any key to exit ===</pre>
=={{header|PicoLisp}}==
This uses coroutines to traverse the trees, so it works only in the 64-bit version.
<
(co Rt
(recur (Tree)
Line 1,773 ⟶ 2,037:
(NIL (= Node1 Node2)) ) )
(co "rt1")
(co "rt2") ) )</
Test:
<
-> NIL
: (for N (5 4 6 3 7 1 2) (idx '*Tree2 N T))
Line 1,801 ⟶ 2,065:
: (cmpTrees *Tree1 *Tree2)
-> T</
=={{header|Python}}==
This solution visits lazily the two trees in lock step like in the Raku example, and stops at the first miss-match.
<
from itertools import zip_longest as izip_longest # Python 3.x
except:
Line 1,839 ⟶ 2,103:
assert not same_fringe(a, x)
assert not same_fringe(a, y)
assert not same_fringe(a, z)</
{{out}}
There is no output, which signifies success.
Line 1,857 ⟶ 2,121:
be added to any of the following variations, it's omitted for brevity.
<
#lang racket
Line 1,877 ⟶ 2,141:
(check-false (same-fringe? '((1 2 3) ((4 5 6) (7 8)))
'(((1 2 3) (4 6)) (8)))))
</syntaxhighlight>
{{out}}
Line 1,891 ⟶ 2,155:
that feeds it.
<
#lang racket
Line 1,907 ⟶ 2,171:
(let ([x1 (channel-get ch1)] [x2 (channel-get ch2)])
(and (equal? x1 x2) (or (void? x1) (loop))))))
</syntaxhighlight>
Channels are just a one of several thread-communication devices which
Line 1,915 ⟶ 2,179:
running.
<
#lang racket
Line 1,931 ⟶ 2,195:
(let ([x1 (read i1)] [x2 (read i2)])
(and (equal? x1 x2) (or (eof-object? x1) (loop))))))
</syntaxhighlight>
=== Generators ===
Line 1,937 ⟶ 2,201:
This version is very similar, except that now we use generators:
<
#lang racket
(require racket/generator)
Line 1,952 ⟶ 2,216:
(let ([x1 (g1)] [x2 (g2)])
(and (equal? x1 x2) (or (void? x1) (loop))))))
</syntaxhighlight>
Line 1,963 ⟶ 2,227:
delimited continuation operator.
<
#lang racket
Line 1,982 ⟶ 2,246:
(and (equal? x1 x2)
(or (void? x1) (loop iter1 iter2)))))))))
</syntaxhighlight>
=={{header|Raku}}==
Line 1,988 ⟶ 2,252:
{{works with|Rakudo|2018.03}}
Unlike in Perl 5, where <tt>=></tt> is just a synonym for comma, in Raku it creates a true Pair object. So here we use Pair objects for our "cons" cells, just as if we were doing this in Lisp. We use the <tt>gather/take</tt> construct to harvest the leaves lazily as the elements are visited with a standard recursive algorithm, using multiple dispatch to differentiate nodes from leaves. The <tt>eqv</tt> value equivalence is applied to the two lists in parallel.
<syntaxhighlight lang="raku"
multi sub fringey (Pair $node) { fringey $_ for $node.kv; }
multi sub fringey ( Any $leaf) { take $leaf; }
Line 2,013 ⟶ 2,277:
say not samefringe $a, $x;
say not samefringe $a, $y;
say not samefringe $a, $z;</
{{out}}
<pre>True
Line 2,026 ⟶ 2,290:
===Version 1 using father node ===
<
* Same Fringe
* 1 A A
Line 2,201 ⟶ 2,465:
i=mknode('I',t); Call attrite i,f,t
End
Return</
Output:
<pre>
Line 2,215 ⟶ 2,479:
===Version 2 without using father node ===
<
* Same Fringe
= 1 A A
Line 2,353 ⟶ 2,617:
i=mknode('I',t); Call attrite i,f,t
End
Return</
Output is the same as for Version 1
Line 2,359 ⟶ 2,623:
This REXX example is a re─written program that mimics the first version (above).
This REXX version has:
:::* elided a subroutine
:::* elided superfluous '''do ── end''' groups
:::* elided some stemmed array tails
:::* elided
:::* simplified some stem names
:::* displays the tree (as an ASCII display)
Line 2,372 ⟶ 2,636:
:::* combined subroutines '''ATTLEFT''' and '''ATTRIGHT''' into one
:::* streamlined the '''MAKE_TREE''' subroutine
<
_= left('', 28); say _ " A A "
say _ " / \ ◄════1st tree / \ "
Line 2,382 ⟶ 2,646:
say _ " / / \ / / \ "
say _ "G H I G δ I " ; say
#= 0; done.= 0; @.= 0 /*initialize:
do t#=1 for 2; call make_tree t#; end /*define tree numbers 1 and 2. */
z1= root.1; L1= @.1.z1; done.1.z1= 1 /*L1: is a leaf on tree number 1. */
z2= z1; L2= @.2.z2; done.2.z2= 1 /*L2: " " " " " " 2. */
do until \done.
end
if L1==0 then say L2 'exceeds leaves in
if
end /*#%2*/
exit 0
/*──────────────────────────────────────────────────────────────────────────────────────*/
do;
if next==. & @.t.q._Rson\==0 & @.t.q._Rson.vis==0 then /*R branch & not visited ? */
do;
if next==. then next= @.t.q._dad; return next /*father node; zero if
/*──────────────────────────────────────────────────────────────────────────────────────*/
make_node: parse arg name,t; #= # + 1;
@.t.q= name; @.t.q._Lson= 0; @.t.0= q
@.t.q._dad= 0; @.t.q._Rson= 0;
/*──────────────────────────────────────────────────────────────────────────────────────*/
make_tree: procedure expose @. root. #;
/*──────────────────────────────────────────────────────────────────────────────────────*/
son: procedure expose @.; parse arg ?,son,dad,t; LR= '_'?"SON"; @.t.son._dad= dad
q= @.t.dad.LR; if q\==0 then do; @.t.q._dad= son; @.t.son.LR= q; end
@.t.dad.LR= son; return</syntaxhighlight>
{{out|output}}
<pre>
Line 2,451 ⟶ 2,700:
G H I G δ I
A difference is: H ¬= δ
</pre>
Line 2,466 ⟶ 2,714:
Descend provides a list, or stack, of the leftmost ''unvisited'' nodes at each level of the tree. Two such lists are used as cursors to keep track of the remaining nodes. The main loop compares the top of each list (ie the leftmost remaining node) and breaks with ''false'' if different, or calls Ascend to update the lists. Updating may require calling Descend again if more unvisited left-nodes are found. If the end of both lists is reached simultaneously, and therefore the end of both trees, ''true'' is returned.
<
(define (entry tree) (car tree))
(define (left-branch tree) (cadr tree))
Line 2,500 ⟶ 2,748:
(null? l2)
(not (eq? (entry (car l1)) (entry (car l2))))) #f)
(else (next (ascend l1) (ascend l2))))))</
{{out}}
Line 2,508 ⟶ 2,756:
=={{header|Sidef}}==
{{trans|Perl}}
<
# 0..2 are same
[ 'd', [ 'c', [ 'a', 'b', ], ], ],
Line 2,543 ⟶ 2,791:
say ("tree[#{idx}] vs tree[#{idx+1}]: ",
cmp_fringe(trees[idx], trees[idx+1]))
}</
{{out}}
Line 2,555 ⟶ 2,803:
{{works with|Tcl|8.6}}
{{tcllib|struct::tree}}
<
package require struct::tree
Line 2,587 ⟶ 2,835:
rename $c2 {}
}
}</
Demonstrating:
<
struct::tree t1 deserialize {
root {} {}
Line 2,608 ⟶ 2,856:
# Print the boolean result of doing the comparison
puts [samefringe t1 t2]</
{{out}}
<pre>
c != cc
0
</pre>
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-dynamic}}
<syntaxhighlight lang="wren">import "./dynamic" for Struct
var Node = Struct.create("Node", ["key", "left", "right"])
// 'leaves' returns a fiber that yields the leaves of the tree
// until all leaves have been received.
var leaves = Fn.new { |t|
// recursive function to walk tree
var f
f = Fn.new { |n|
if (!n) return
// leaves are identified by having no children
if (!n.left && !n.right) {
Fiber.yield(n.key)
} else {
f.call(n.left)
f.call(n.right)
}
}
// return a fiber which walks the tree
return Fiber.new { f.call(t) }
}
var sameFringe = Fn.new { |t1, t2|
var f1 = leaves.call(t1)
var f2 = leaves.call(t2)
var l1
while (l1 = f1.call()) {
// both trees must yield a leaf, and the leaves must be equal
var l2
if ((l2 = f2.call()) && (!l2 || l1 != l2)) return false
}
// there must be nothing left in f2 after consuming all of f1
return !f2.call()
}
// the different shapes of the trees is shown with indention,
// the leaves being easy to spot by the key
var t1 = Node.new(3,
Node.new(1,
Node.new(1, null, null),
Node.new(2, null, null)
),
Node.new(8,
Node.new(5, null, null),
Node.new(13, null, null)
)
)
// t2 with negative values for internal nodes that can't possibly match
// positive values in t1, just to show that only leaves are being compared.
var t2 = Node.new(-8,
Node.new(-3,
Node.new(-1,
Node.new(1, null, null),
Node.new(2, null, null)
),
Node.new(5, null,null)
),
Node.new(13, null, null)
)
// t3 as t2 but with a different leave
var t3 = Node.new(-8,
Node.new(-3,
Node.new(-1,
Node.new(1, null, null),
Node.new(2, null, null)
),
Node.new(5, null,null)
),
Node.new(14, null, null) // 14 instead of 13
)
System.print("tree 1 and tree 2 have the same leaves: %(sameFringe.call(t1, t2))")
System.print("tree 1 and tree 3 have the same leaves: %(sameFringe.call(t1, t3))")
System.print("tree 2 and tree 3 have the same leaves: %(sameFringe.call(t2, t3))")</syntaxhighlight>
{{out}}
<pre>
tree 1 and tree 2 have the same leaves: true
tree 1 and tree 3 have the same leaves: false
tree 2 and tree 3 have the same leaves: false
</pre>
=={{header|zkl}}==
{{trans|Icon and Unicon}}
<
//Tree: (node,left,right) or (leaf) or (node,left) ...
aTree := T(1, T(2, T(4, T(7)), T(5)), T(3, T(6, T(8), T(9))));
Line 2,643 ⟶ 2,976:
else { genLeaves(tree[1]); genLeaves(tree[2]); }
}
}</
{{out}}
<pre>
|