How to resolve the algorithm Same fringe step by step in the Ada programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Same fringe step by step in the Ada programming language

Table of Contents

Problem Statement

Write a routine that will compare the leaves ("fringe") of two binary trees to determine whether they are the same list of leaves when visited left-to-right. The structure or balance of the trees does not matter; only the number, order, and value of the leaves is important. Any solution is allowed here, but many computer scientists will consider it inelegant to collect either fringe in its entirety before starting to collect the other one. In fact, this problem is usually proposed in various forums as a way to show off various forms of concurrency (tree-rotation algorithms have also been used to get around the need to collect one tree first). Thinking of it a slightly different way, an elegant solution is one that can perform the minimum amount of work to falsify the equivalence of the fringes when they differ somewhere in the middle, short-circuiting the unnecessary additional traversals and comparisons. Any representation of a binary tree is allowed, as long as the nodes are orderable, and only downward links are used (for example, you may not use parent or sibling pointers to avoid recursion).

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Same fringe step by step in the Ada programming language

Source code in the ada programming language

generic
   type Data is private;
package Bin_Trees is

   type Tree_Type is private;

   function Empty(Tree: Tree_Type) return Boolean;
   function Left (Tree: Tree_Type) return Tree_Type;
   function Right(Tree: Tree_Type) return Tree_Type;
   function Item (Tree: Tree_Type) return Data;
   function Empty return Tree_Type;

   procedure Destroy_Tree(N: in out Tree_Type);
   function Tree(Value: Data) return Tree_Type;
   function Tree(Value: Data; Left, Right : Tree_Type) return Tree_Type;

private

   type Node;
   type Tree_Type is access Node;
   type Node is record
      Left, Right: Tree_Type := null;
      Item: Data;
   end record;

end Bin_Trees;


with Ada.Unchecked_Deallocation;

package body Bin_Trees is

   function Empty(Tree: Tree_Type) return Boolean is
   begin
      return Tree = null;
   end Empty;

   function Empty return Tree_Type is
   begin
      return null;
   end Empty;

   function Left (Tree: Tree_Type) return Tree_Type is
   begin
      return Tree.Left;
   end Left;

   function Right(Tree: Tree_Type) return Tree_Type is
   begin
      return Tree.Right;
   end Right;

   function Item (Tree: Tree_Type) return Data is
   begin
      return Tree.Item;
   end Item;

   procedure Destroy_Tree(N: in out Tree_Type) is
      procedure free is new Ada.Unchecked_Deallocation(Node, Tree_Type);
   begin
      if not Empty(N) then
         Destroy_Tree(N.Left);
         Destroy_Tree(N.Right);
         Free(N);
      end if;
   end Destroy_Tree;

   function Tree(Value: Data; Left, Right : Tree_Type) return Tree_Type is
      Temp : Tree_Type := new Node;
   begin
      Temp.all := (Left, Right, Value);
      return Temp;
   end Tree;

   function Tree(Value: Data) return Tree_Type is
   begin
      return Tree(Value, null, null);
   end Tree;

end Bin_Trees;


   generic
      with procedure Process_Data(Item: Data);
      with function Stop return Boolean;
      with procedure Finish;
   package Bin_Trees.Traverse is
      task Inorder_Task is
         entry Run(Tree: Tree_Type);
         -- this will call each Item in Tree and, at the very end, it will call Finish
         -- except when Stop becomes true; in this case, the task terminates
      end Inorder_Task;
   end Bin_Trees.Traverse;


   package body Bin_Trees.Traverse is
      task body Inorder_Task is
         procedure Inorder(Tree: Tree_Type) is
         begin
            if not Empty(Tree) and not Stop then
               Inorder(Tree.Left);
               if not Stop then
                  Process_Data(Item => Tree.Item);
               end if;
               if (not Stop) then
                  Inorder(Tree.Right);
               end if;
            end if;
         end Inorder;
         T: Tree_Type;
      begin
         accept Run(Tree: Tree_Type) do
            T := Tree;
         end Run;
         Inorder(T);
         Finish;
      end Inorder_Task;
   end Bin_Trees.Traverse;


with Ada.Text_IO, Bin_Trees.Traverse;

procedure Main is

   package B_Trees is new Bin_Trees(Character); use B_Trees;

   function Same_Fringe(T1, T2: Tree_Type) return Boolean is

      protected type Buffer_Type is
         entry Write(Item: Character);
         entry Write_Done;
         entry Read_And_Compare(Item: Character);
         entry Read_Done;
         entry Wait_For_The_End;
         function Early_Abort return Boolean;
         function The_Same return Boolean;
      private
         Current: Character;
         Readable: Boolean := False;
         Done: Boolean := False;
         Same: Boolean := True;
         Finished: Boolean := False;
      end Buffer_Type;

      protected body Buffer_Type is

         entry Write(Item: Character) when not Readable is
         begin
            Readable := True;
            Current  := Item;
         end Write;

         entry Write_Done when not Readable is
         begin
            Readable := True;
            Done     := True;
         end Write_Done;

         entry Read_And_Compare(Item: Character) when Readable is
         begin
            if Done then -- Producer is already out of items
               Same := False;
               Finished := True;
               -- Readable remains True, else Consumer might lock itself out
            elsif
              Item /= Current then
               Same := False;
               Finished := True;
               Readable := False;
            else
                 Readable := False;
            end if;
         end Read_And_Compare;

         entry Read_Done when Readable is
         begin
            Readable := False;
            Same     := Same and Done;
            Finished := True;
         end Read_Done;

         entry Wait_For_The_End when (Finished) or (not Same) is
         begin
            null; -- "when ..." is all we need
         end Wait_For_The_End;

         function The_Same return Boolean is
         begin
            return Same;
         end The_Same;

         function Early_Abort return Boolean is
         begin
            return not The_Same or Finished;
         end Early_Abort;

      end Buffer_Type;

      Buffer: Buffer_Type;

      -- some wrapper subprogram needed to instantiate the generics below

          procedure Prod_Write(Item: Character) is
          begin
             Buffer.Write(Item);
          end Prod_Write;

          function Stop return Boolean is
          begin
             return Buffer.Early_Abort;
          end Stop;

          procedure Prod_Stop is
          begin
             Buffer.Write_Done;
          end Prod_Stop;

          procedure Cons_Write(Item: Character) is
          begin
             Buffer.Read_And_Compare(Item);
          end Cons_Write;

          procedure Cons_Stop is
          begin
             Buffer.Read_Done;
          end Cons_Stop;

      package Producer is new B_Trees.Traverse(Prod_Write, Stop, Prod_Stop);
      package Consumer is new B_Trees.Traverse(Cons_Write, Stop, Cons_Stop);

   begin
      Producer.Inorder_Task.Run(T1);
      Consumer.Inorder_Task.Run(T2);
      Buffer.Wait_For_The_End;
      return Buffer.The_Same;
   end Same_Fringe;

   procedure Show_Preorder(Tree: Tree_Type; Prefix: String := "") is
      use Ada.Text_IO;
   begin
      if Prefix /= "" then
         Ada.Text_IO.Put(Prefix);
      end if;
      if not Empty(Tree) then
         Put("(" & Item(Tree));      Put(", ");
         Show_Preorder(Left(Tree));  Put(", ");
         Show_Preorder(Right(Tree)); Put(")");
      end if;
      if Prefix /= "" then
         New_Line;
      end if;
   end Show_Preorder;

   T_0: Tree_Type := Tree('a', Empty, Tree('b'));
   T: array(1 .. 5) of Tree_Type;

begin
   T(1) := Tree('d', Tree('c'), T_0);
   T(2)  := Tree('c', Empty, Tree('a', Tree('d'), Tree('b')));
   T(3)  := Tree('e', T(1), T(2));
   T(4)  := Tree('e', T(2), T(1));
   T(5)  := Tree('e', T_0, Tree('c', Tree('d'), T(1)));

   -- First display the trees you have (in preorder)
   for I in T'Range loop
      Show_Preorder(T(I), "Tree(" & Integer'Image(I) & " ) is ");
   end loop;
   Ada.Text_IO.New_Line;

   -- Now compare them, which have the same fringe?
   for I in T'Range loop
      for J in T'Range loop
         if Same_Fringe(T(J), T(I)) then
            Ada.Text_IO.Put("same(");
         else
            Ada.Text_IO.Put("DIFF(");
         end if;
         Ada.Text_IO.Put(Integer'Image(I) & "," & Integer'Image(J) & " ); ");
      end loop;
      Ada.Text_IO.New_Line;
   end loop;
end Main;


  

You may also check:How to resolve the algorithm Loops/Infinite step by step in the Vedit macro language programming language
You may also check:How to resolve the algorithm Integer sequence step by step in the 0815 programming language
You may also check:How to resolve the algorithm Luhn test of credit card numbers step by step in the Icon and Unicon programming language
You may also check:How to resolve the algorithm Arrays step by step in the Euphoria programming language
You may also check:How to resolve the algorithm Floyd's triangle step by step in the AppleScript programming language