Same fringe: Difference between revisions

m
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.
 
<langsyntaxhighlight Adalang="ada">generic
type Data is private;
package Bin_Trees is
Line 36:
end record;
 
end Bin_Trees;</langsyntaxhighlight>
 
The implementation is straightforward.
 
<langsyntaxhighlight Adalang="ada">with Ada.Unchecked_Deallocation;
 
package body Bin_Trees is
Line 91:
end Tree;
 
end Bin_Trees;</langsyntaxhighlight>
 
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.
 
<langsyntaxhighlight Adalang="ada"> generic
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;</langsyntaxhighlight>
 
<langsyntaxhighlight Adalang="ada"> package body Bin_Trees.Traverse is
task body Inorder_Task is
procedure Inorder(Tree: Tree_Type) is
Line 129:
Finish;
end Inorder_Task;
end Bin_Trees.Traverse;</langsyntaxhighlight>
 
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.
 
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO, Bin_Trees.Traverse;
 
procedure Main is
Line 296:
Ada.Text_IO.New_Line;
end loop;
end Main;</langsyntaxhighlight>
 
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}}==
<langsyntaxhighlight Bracmatlang="bracmat">( ( T
=
. ( next
Line 352:
, (((a.b).c).x.y.z)
)
);</langsyntaxhighlight>
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.
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
Line 494:
 
return 0;
}</langsyntaxhighlight>
 
=={{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.
<langsyntaxhighlight lang="csharp">
using System;
using System.Collections.Generic;
Line 633:
}
}
</syntaxhighlight>
</lang>
 
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.
<langsyntaxhighlight lang="clojure">(defn fringe-seq [branch? children content tree]
(letfn [(walk [node]
(lazy-seq
Line 657 ⟶ 886:
(mapcat walk (children node)))
(list node))))]
(walk tree)))</langsyntaxhighlight>
For this problem, binary trees are represented as vectors, whose nodes are either [''content'' ''left'' ''right''] or just ''content''.
<langsyntaxhighlight lang="clojure">(defn vfringe-seq [v] (fringe-seq vector? #(remove nil? (rest %)) first v))
(println (vfringe-seq [10 1 2])) ; (1 2)
(println (vfringe-seq [10 [1 nil nil] [20 2 nil]])) ; (1 2)</langsyntaxhighlight>
Then we can use a general sequence-equality function:
<langsyntaxhighlight lang="clojure">(defn seq= [s1 s2]
(cond
(and (empty? s1) (empty? s2)) true
(not= (empty? s1) (empty? s2)) false
(= (first s1) (first s2)) (recur (rest s1) (rest s2))
:else false))</langsyntaxhighlight>
 
=={{header|D}}==
===Short Version===
A short recursive solution that is not lazy (and lacks the const/immutable/pure/nothrow):
<langsyntaxhighlight lang="d">struct Node(T) {
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));
}</langsyntaxhighlight>
{{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.
<langsyntaxhighlight lang="d">import std.array: empty;
import std.algorithm: equal;
 
Line 894 ⟶ 1,123:
writeln("sameFringe(t1, t2): ", sameFringe(t1, t2));
writeln("sameFringe(t1, t3): ", sameFringe(t1, t3));
}</langsyntaxhighlight>
{{out}}
<pre>fringe(t1): [40, 50]
Line 903 ⟶ 1,132:
 
===Range Generator Version (Lazy)===
<langsyntaxhighlight lang="d">import std.stdio, std.concurrency, std.range, std.algorithm;
 
struct Node(T) {
Line 946 ⟶ 1,175:
auto t7 = new N(1, new N(2));
sameFringe(t6, t7).writeln;
}</langsyntaxhighlight>
{{out}}
<pre>true
Line 956 ⟶ 1,185:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 1,026 ⟶ 1,255:
&node{int: 13}}
fmt.Println(sameFringe(t1, t2)) // prints true.
}</langsyntaxhighlight>
 
=={{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:
<langsyntaxhighlight lang="haskell">data Tree a
= 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]</langsyntaxhighlight>
{{Out}}
<pre>True
Line 1,073 ⟶ 1,302:
The following solution works in both languages:
 
<langsyntaxhighlight lang="unicon">procedure main()
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</langsyntaxhighlight>
 
Output:
Line 1,115 ⟶ 1,344:
=={{header|J}}==
 
<langsyntaxhighlight Jlang="j">sameFringe=: -:&([: ; <S:0)</langsyntaxhighlight>
 
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:
 
<langsyntaxhighlight Jlang="j">list2tree=: (<.@-:@# ({. ,&<&list2tree}. ) ])^:(1<#)</langsyntaxhighlight>
 
And, here are two differently structured trees which represent the same underlying data:
 
<langsyntaxhighlight Jlang="j">bp=: list2tree p: i.11
ubp=: p:L:0] 10;~list2tree i.10</langsyntaxhighlight>
 
And, here's our original operation in action (<code>1 {:: ubp</code> is a subtree of ubp which omits a leaf node):
 
<langsyntaxhighlight Jlang="j"> ubp sameFringe bp
1
bp sameFringe 1 {:: ubp
0</langsyntaxhighlight>
 
=={{header|Java}}==
Line 1,142 ⟶ 1,371:
 
'''Code:'''
<langsyntaxhighlight lang="java">import java.util.*;
 
class SameFringe
Line 1,262 ⟶ 1,491:
}
}
}</langsyntaxhighlight>
 
'''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:
<langsyntaxhighlight lang="jq">(t|flatten) == (s|flatten)</langsyntaxhighlight>
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.
<langsyntaxhighlight lang="jq"># "next" allows one to generate successive leaves, one at a time. This is accomplished
# 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) ;</langsyntaxhighlight>
'''Example''':
<langsyntaxhighlight lang="jq"> [1,[2,[3,[4,[5,[6,7]]]]]] as $a
| [[[[[[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"]]] )</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="sh">$ jq -n -f Same_Fringe.jq
true
true
Line 1,336 ⟶ 1,565:
false
true
</syntaxhighlight>
</lang>
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">
<lang Julia>
using Lazy
 
Line 1,390 ⟶ 1,619:
println(equalsfringe(a, y) == false)
println(equalsfringe(a, z) == false)
</syntaxhighlight>
</lang>
{{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.
 
<langsyntaxhighlight lang="lua">local type, insert, remove = type, table.insert, table.remove
 
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>
</lang>
 
{{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.
 
<langsyntaxhighlight Nimlang="nim">import random, sequtils, strutils
 
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(", ")</langsyntaxhighlight>
 
{{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.
<langsyntaxhighlight OCamllang="ocaml">type 'a btree = Leaf of 'a | BTree of ('a btree * 'a btree)
 
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;</langsyntaxhighlight>
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.
 
<langsyntaxhighlight lang="perl">
#!/usr/bin/perl
use strict;
Line 1,643 ⟶ 1,872:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,651 ⟶ 1,880:
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(notonline)-->
<lang Phix>--
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\Same_Fringe.exw
-- demo\rosetta\Same_Fringe.exw
-- ============================
-- ============================
--
--
-- Requires 0.7.5 or later (implementation revealed that task_yield did not
-- In some cases it may help to replace the single res with a table, such
-- have side effects of e_all properly set.)
-- 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
constant tests = {{0,1,{0,2,0}},
-- other words if extending tasks[] rather than overwriting it, you would
{{0,1,0},2,0},
-- also extend res[] and ridx[] and sdata[], and need freelist handling.
{{0,1,0},2,{0,3,0}},
--</span>
}
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (multitasking)</span>
 
sequence tasks
<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>
integer res = 0
<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>
sequence sdata = repeat(0,2)
<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>
integer active_tasks
integer show_details = 1
<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>
procedure scan(sequence tree, integer level, integer tidx)
<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>
object {left,data,right} = tree
<span style="color: #000000;">active_tasks</span>
if res=0 then
<span style="color: #004080;">bool</span> <span style="color: #000000;">show_details</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
if left!=0 then scan(left,level+1,tidx) end if
sdata[tidx] = data
<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>
if show_details then
<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>
printf(1,"task[%d] sets sdata[%d] to ",tidx)
<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>
?data
<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>
end if
<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>
if res=0 then
<span style="color: #008080;">if</span> <span style="color: #000000;">show_details</span> <span style="color: #008080;">then</span>
task_suspend(task_self())
<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>
task_yield()
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<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>
if right!=0 then scan(right,level+1,tidx) end if
<span style="color: #000000;">task_suspend</span><span style="color: #0000FF;">(</span><span style="color: #000000;">task_self</span><span style="color: #0000FF;">())</span>
end if
<span style="color: #000000;">task_yield</span><span style="color: #0000FF;">()</span>
if level=1 then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if show_details then
<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>
printf(1,"task[%d] ends\n",tidx)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<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>
active_tasks -= 1
<span style="color: #008080;">if</span> <span style="color: #000000;">show_details</span> <span style="color: #008080;">then</span>
tasks[tidx] = 0
<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>
sdata[tidx] = -1 -- (or use a separate flag)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #000000;">active_tasks</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
end procedure
<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>
?"started"
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
procedure test(integer t1, integer t2)
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
tasks = {task_create(routine_id("scan"),{tests[t1],1,1}),
task_create(routine_id("scan"),{tests[t2],1,2})}
<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>
active_tasks = 2
<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>
res = 0
<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>
while active_tasks>0 do
<span style="color: #000000;">active_tasks</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
if tasks[1] then
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
task_schedule(tasks[1],1)
<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>
task_yield()
<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>
end if
<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>
if tasks[2] then
<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>
task_schedule(tasks[2],1)
<span style="color: #000000;">task_yield</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
if res=0 then
<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>
res = compare(sdata[1],sdata[2])
<span style="color: #000080;font-style:italic;">-- (nb next might only be valid for active_tasks==2)</span>
if show_details then
<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>
?{res,sdata[1],sdata[2],active_tasks}
<span style="color: #008080;">if</span> <span style="color: #000000;">show_details</span> <span style="color: #008080;">then</span>
end if
<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) ==&gt; %d, active tasks:%d\n"</span><span style="color: #0000FF;">,</span>
end if
<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>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
printf(1,"test(%d,%d):%d\n",{t1,t2,res})
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end procedure
<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>
test(1,1)
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
show_details = 0
test(1,2)
<span style="color: #0000FF;">?</span><span style="color: #008000;">"started"</span>
test(1,3)
<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>
test(2,1)
<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>
test(2,2)
<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>
test(2,3)
<span style="color: #000000;">show_details</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
test(3,1)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
test(3,2)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
test(3,3)</lang>
<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
{0,1,1,2}
task[1] sets sdata[1] to 2
task[2] sets sdata[2] to 2
compare(2,2) ==> 0, active tasks:2
{0,2,2,2}
task[1] ends
task[2] ends
compare(-1,-1) ==> 0, active tasks:0
{0,-1,-1,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.
<langsyntaxhighlight PicoLisplang="picolisp">(de nextLeaf (Rt Tree)
(co Rt
(recur (Tree)
Line 1,773 ⟶ 2,037:
(NIL (= Node1 Node2)) ) )
(co "rt1")
(co "rt2") ) )</langsyntaxhighlight>
Test:
<langsyntaxhighlight PicoLisplang="picolisp">: (balance '*Tree1 (range 1 7))
-> NIL
: (for N (5 4 6 3 7 1 2) (idx '*Tree2 N T))
Line 1,801 ⟶ 2,065:
 
: (cmpTrees *Tree1 *Tree2)
-> T</langsyntaxhighlight>
 
=={{header|Python}}==
This solution visits lazily the two trees in lock step like in the Raku example, and stops at the first miss-match.
<langsyntaxhighlight lang="python">try:
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)</langsyntaxhighlight>
{{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.
 
<langsyntaxhighlight lang="racket">
#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>
</lang>
 
{{out}}
Line 1,891 ⟶ 2,155:
that feeds it.
 
<langsyntaxhighlight lang="racket">
#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>
</lang>
 
Channels are just a one of several thread-communication devices which
Line 1,915 ⟶ 2,179:
running.
 
<langsyntaxhighlight lang="racket">
#lang racket
 
Line 1,931 ⟶ 2,195:
(let ([x1 (read i1)] [x2 (read i2)])
(and (equal? x1 x2) (or (eof-object? x1) (loop))))))
</syntaxhighlight>
</lang>
 
=== Generators ===
Line 1,937 ⟶ 2,201:
This version is very similar, except that now we use generators:
 
<langsyntaxhighlight lang="racket">
#lang racket
(require racket/generator)
Line 1,952 ⟶ 2,216:
(let ([x1 (g1)] [x2 (g2)])
(and (equal? x1 x2) (or (void? x1) (loop))))))
</syntaxhighlight>
</lang>
 
 
Line 1,963 ⟶ 2,227:
delimited continuation operator.
 
<langsyntaxhighlight lang="racket">
#lang racket
 
Line 1,982 ⟶ 2,246:
(and (equal? x1 x2)
(or (void? x1) (loop iter1 iter2)))))))))
</syntaxhighlight>
</lang>
 
=={{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" perl6line>sub fringe ($tree) {
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;</langsyntaxhighlight>
{{out}}
<pre>True
Line 2,026 ⟶ 2,290:
===Version 1 using father node ===
 
<langsyntaxhighlight REXXlang="rexx">/* REXX ***************************************************************
* Same Fringe
* 1 A A
Line 2,201 ⟶ 2,465:
i=mknode('I',t); Call attrite i,f,t
End
Return</langsyntaxhighlight>
Output:
<pre>
Line 2,215 ⟶ 2,479:
 
===Version 2 without using father node ===
<langsyntaxhighlight lang="rexx">/* REXX ***************************************************************
* Same Fringe
= 1 A A
Line 2,353 ⟶ 2,617:
i=mknode('I',t); Call attrite i,f,t
End
Return</langsyntaxhighlight>
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:
:::* &nbsp; elided a subroutine
:::* &nbsp; elided superfluous &nbsp; '''do ── end''' &nbsp; groups
:::* &nbsp; elided some stemmed array tails
:::* &nbsp; elided somean REXXunneeded variables'''select''' &nbsp; (LVL, DEBUG, ···)structure
:::* &nbsp; simplified some stem names
:::* &nbsp; displays the tree &nbsp; (as an ASCII display)
Line 2,372 ⟶ 2,636:
:::* &nbsp; combined subroutines &nbsp; '''ATTLEFT''' &nbsp; and &nbsp; '''ATTRIGHT''' &nbsp; into one
:::* &nbsp; streamlined the &nbsp; '''MAKE_TREE''' &nbsp; subroutine
<langsyntaxhighlight lang="rexx">/*REXX pgm examines the leaves of 2 binary trees (as shown below), and finds inequities.*/
_= 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: #, (leaves), DONE., nodes*/
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 #%2 /*loop for the number of (tree) leaves.*/
if L1==L2 then do; if L1==0 then call sayXdo; say 'The trees are equal.'; leave; end
say ' The ' L1 " leaf is identical in both trees."
do until \done.1.z1; z1= go_nextnxt(z1, 1); L1= @.1.z1; end; done.1.z1=1
do until \done.12.z1z2; z2=nxt(z2,2); L2=@.2.z2; end; done.2.z2=1
do until \done.2.z2; z2= go_next(z2, 2); L2= @.2.z2; enditerate
done.2.z2= 1
end
if L1==0 then say L2 'exceeds leaves in else1st selecttree'
if when L1L2==0 then callsay sayX L2L1 'exceeds leaves in 1st2nd tree'
whensay L2==0 then call sayX'A L1difference is: 'exceeds leaves in 2nd tree'L1 "¬=" L2; leave
end /*#%2*/
otherwise call sayX 'A difference is: ' L1 '¬=' L2
exit 0
end /*select*/
end /*#%2*/
exit
/*──────────────────────────────────────────────────────────────────────────────────────*/
go_nextnxt: procedure expose @.; arg q,t; next= . /*find next node in the tree. */
if @.t.q._Lson\==0 &, @.t.q._Lson.vis==0 then /*thereL abranch left& branchnot invisited tree? */
do; next=@.t.q._Lson.vis==0 then do; next= @.t.q._Lson.vis=1; end /*has node──►next beennode; visited?Lside done*/
if next==. & @.t.q._Rson\==0 & @.t.q._Rson.vis==0 then /*R branch & not visited ? */
next= @.t.q._Lson /*point to ──► next node.*/
do; next=@.t.q._Rson; @.t.q._Lson_Rson.vis= 1; end /*leftside is──►next completed.node; Rside done*/
if next==. then next= @.t.q._dad; return next /*father node; zero if enddone*/
if next==. & @.t.q._Rson\==0 &, /*there a right tree branch ? */
@.t.q._Rson.vis==0 then do; next= @.t.q._Rson /*has node been visited? */
next= @.t.q._Rson /*point to ──► next node.*/
@.t.q._Rson.vis= 1 /*rightside is completed.*/
end
if next==. then next= @.t.q._dad /*process the father node. */
return next /*next node (or 0, if done).*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
make_node: parse arg name,t; #= # + 1; q= @.t.0 + 1 /*make new node/branch on tree*/
@.t.q= name; @.t.q._Lson= 0; @.t.0= q
@.t.q._dad= 0; @.t.q._Rson= 0; return q return q /*number of node just created.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
make_tree: procedure expose @. root. #; parse arg tree /*construct a couple of trees.*/
if tree==1 then hhha= make_node('HA', tree); root.tree= a; hhh= substr('Hδ', tree, /* [↓] must be a wood duck*/1)
else hhhb= make_node('δB', tree); call son 'L', b, /*the odd duck in thea, tree. */
ac= make_node('AC', tree); call son 'R', c, a, root.tree= a
bd= make_node('BD', tree); call son 'L', bd, ab, tree
ce= make_node('CE', tree); call son 'R', ce, ab, tree
df= make_node('DF', tree); call son 'L', df, bc, tree
eg= make_node('EG', tree); call son 'RL', eg, bd, tree
fh= make_node('F'hhh, tree); call son 'L', fh, cf, tree /*quacks like a duck? */
gi= make_node('GI', tree); call son 'LR', gi, df, tree; return
/*quacks like a duck?*/ h= make_node(hhh, tree); call son 'L', h, f, tree
i= make_node('I', tree); call son 'R', i, f, tree
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
son: procedure expose @.; parse arg ?,son,dad,t; LR= '_'?"SON"; @.t.son._dad= dad
sayX: say; say arg(1); say; exit /*display a message and exit. */
q= @.t.dad.LR; if q\==0 then do; @.t.q._dad= son; @.t.son.LR= q; end
/*──────────────────────────────────────────────────────────────────────────────────────*/
@.t.dad.LR= son; return</syntaxhighlight>
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</lang>
{{out|output}}
<pre>
Line 2,451 ⟶ 2,700:
G H I G δ I
 
The A leaf is identical in both trees.
The B leaf is identical in both trees.
The D leaf is identical in both trees.
The G leaf is identical in both trees.
The E leaf is identical in both trees.
The C leaf is identical in both trees.
The F leaf is identical in both trees.
 
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.
 
<langsyntaxhighlight Schemelang="scheme">; binary tree helpers from "Structure and Interpretation of Computer Programs" 2.3.3
(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))))))</langsyntaxhighlight>
 
{{out}}
Line 2,508 ⟶ 2,756:
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby">var trees = [
# 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]))
}</langsyntaxhighlight>
 
{{out}}
Line 2,555 ⟶ 2,803:
{{works with|Tcl|8.6}}
{{tcllib|struct::tree}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.6
package require struct::tree
 
Line 2,587 ⟶ 2,835:
rename $c2 {}
}
}</langsyntaxhighlight>
Demonstrating:
<langsyntaxhighlight lang="tcl"># Make some trees to compare...
struct::tree t1 deserialize {
root {} {}
Line 2,608 ⟶ 2,856:
 
# Print the boolean result of doing the comparison
puts [samefringe t1 t2]</langsyntaxhighlight>
{{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}}
<langsyntaxhighlight lang="zkl">var G=Utils.Generator;
//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]); }
}
}</langsyntaxhighlight>
{{out}}
<pre>
9,476

edits