Ada - traversing a list - what approach should I use? - recursion

I am working on an ADA project. Essentially I created a list and a list of lists.
So suppose I have a list like A -> B -> D -> E -> F, it means that the tower A is connected to tower B, D, E and F.
Now I also need to have a list to store all the main towers. So suppose I have A ->B -> D -> E -> F, and I have C->X->Y->Q, and E->P->R, the list of lists should be like:
A-> C-> E ( essentially the list of all the main nodes).
As mentioned above, I have a list and its connections. and Now i need to traverse these lists to find out if a connection is possible. For example: I have A ->B -> D -> E -> F, and I have C->X->Y->Q, and E->P->R. If i am asked is A ->R possible answer should be true. Since A -> E -> R.
My doubt is what approach should I use? BFS? Recursion? What will be the best one?

Nested for/of loop? Something like this:
Function Exists( Target, Source : Node ) return boolean is
begin
if Target = Source then
return True;
else
for List of Source loop
for Item of List loop
if Item = Target then
return True;
end if;
end loop;
end loop;
end if;
return false;
end Exists;
Or, if you're using the Vector for container there's this function:
function Contains
(Container : Vector;
Item : Element_Type) return Boolean;
which you would apply like so:
Package Inner_List is new Ada.Containers.Indefinite_Vectors(
Index_Type => Positive,
Element_Type => Integer
);
Package Outer_List is new Ada.Containers.Indefinite_Vectors(
Index_Type => Positive,
Element_Type => Inner_List.Vector,
"=" => Inner_List."="
);
Function Exists( Item : Integer; List : Outer_List.Vector ) return boolean is
begin
for Items of List loop
if Items.Contains(Item) then
return true;
end if;
end loop;
return false;
End Exists;

Related

Cartesian Product of Lists Using Ada

I am currently working on programming this (https://rosettacode.org/wiki/Cartesian_product_of_two_or_more_lists) in Ada, I am trying to do a Cartesian product between different sets. I need help figuring it out, the main issue is how would I be able to declare empty Pairs and calculate that if it's empty, then the result should be empty. Thank you!
Numbers I am trying to use:
{1, 2} × {3, 4}
{3, 4} × {1, 2}
{1, 2} × {}
{} × {1, 2}
My code:
with Ada.Text_IO; use Ada.Text_IO; -- Basically importing the functions that will be used to print out the results.
procedure Hello is -- Procedure is where variables & functions are declared!
type T_Pair is array(1..2) of Integer; -- Declare a type of array that contains a set of 2 numbers (Used for final result!).
type T_Result is array(1..4) of T_Pair; -- Declare a type of array that contains a set of T_Pair(s), used to hold the result.
Demo1 : T_Result;
Demo1A : T_Pair := (1, 2);
Demo1B : T_Pair := (3, 4);
function Fun_CartProd(p1: T_Pair; p2: T_Pair) return T_Result is
results: T_Result;
i: integer := 1;
begin
for j in 1..2 loop
for h in 1..2 loop
results(i) := (p1(j), p2(h));
i := i + 1;
end loop;
end loop;
return results;
end Fun_CartProd;
begin -- This is where the statements go
Demo1 := Fun_CartProd(Demo1A, Demo1B);
for K in 1 .. Demo1'length loop
Put(" [");
for B in 1 .. Demo1(K)'length loop
Put(Integer'Image(Demo1(K)(B)));
if Demo1(K)'length /= B then
Put(",");
end if;
end loop;
Put("]");
if Demo1'length /= K then
Put(",");
end if;
end loop;
Put_Line(""); -- Create a new line.
end Hello;
Since each set of integers can be any length, including empty, I would start with a type that can handle all those situations:
type Integer_Set is array(Positive range <>) of Integer; -- Input type
type Integer_Tuple is array(Positive range <>_ of Integer; -- Output type
and you can represent the empty sets and tuples this way:
Empty_Set : constant Integer_Set(1..0) := (others => <>);
Empty_Tuple : constant Integer_Tuple(1..0) := (others => <>);
The other problem isn't just how many elements are in each set, but how many sets you will be finding the product of. For this I would recommend some kind of container. An array won't work here because each of the individual sets can have different sizes (including empty), but Ada has a variety of "indefinite" containers that can handle that. Here is an example using vectors:
package Set_Vectors is new Ada.Containers.Indefinite_Vectors
(Index_Type => Positive,
Element_Type => Integer_Set);
package Tuple_Vectors is new Ada.Containers.Indefinite_Vectors
(Index_Type => Positive,
Element_Type => Integer_Tuple);
and you can then represent an empty result as:
Empty_Tuple_Vector : constant Tuple_Vectors.Vector := Tupler_Vectors.Empty_Vector;
Now you can create a function that takes in a vector of sets and returns a Cartesian product which will also be a vector of sets:
function Cartesian_Product(Inputs : Set_Vectors.Vector) return Tuple_Vectors.Vector;
If one of the input sets is empty, you return an Empty_Tuple_Vector. You can check if one of the input sets are empty by checking their Length attribute result. It will be 0 if they are empty. Additionally if the input vector is completely empty, you can decide to either return Empty_Tuple_Vector or raise an exception. For example:
if Inputs'Length = 0 then
return Empty_Tuple_Vector; -- or raise an exception, etc.
end if;
for Set of Inputs loop
if Set'Length = 0 then
return Empty_Tuple_Vector;
end if;
-- Maybe do other stuff here if you need
end loop;
Note that the logic you presented assumes only pairs of inputs. I don't have enough experience to convert your logic to account for variable inputs, but perhaps someone can comment on that if you need it.
Also note as Flyx commented, this does not semantically check if a set is a set or not on the inputs (I.E. no duplicate values).

How can I assign record x to record y with a single change?

Take the following example:
type MyArray is array(1..10) of Float;
type MyRecord is record
a: Float;
b: Integer;
c: Boolean;
d: MyArray;
end record;
…
function foo(x: MyRecord) return MyRecord is
y: MyRecord := x;
begin
y.b = -1;
return y.b;
end foo;
It would be nice if I could do something like this instead with foo:
function foo(x: MyRecord) return MyRecord is
(x with (b => -1));
Where the simpler notation (which is not valid Ada) allows me to write foo as an expression function. Is there a way to do something like this in Ada?
Well, Ada202x is working on Delta Aggregates which would be what you want essentially. Until then the only 2 options I could think of were:
Plain old aggregates:
function foo1(x : MyRecord) return MyRecord is
(a => x.a, b => -1, c => x.c, d => x.d);
Extended Return:
function foo2(x : MyRecord) return MyRecord is
begin
return Result : MyRecord := x do
Result.b := -1;
end return;
end foo2;
I know extended return doesn't get you the expression function you wanted, but it is a nicer syntax and can be used with limited types in interesting ways. Right now you will have to rely on plain old aggregate syntax.

Ada functions, accessing stack

Very new with Ada, this is my first time coding with it. Very lost. Any tips, and direction would be great.
Ada question:
I am trying to make: the function Top (S : Stack) return Item_Type, which returns the top item on the stack or raises the Underflow exception, to the generic unbounded stack package.
The function I added for this is at the bottom of this code block.
Current errors:
invalid use of subtype mark in expression or call
actual for "From" must be a variable
invalid use of subtype mark in expression or call
package body Unbound_Stack is
type Cell is record
Item : Item_Type;
Next : Stack;
end record;
procedure Push (Item : in Item_Type; Onto : in out Stack) is
begin
Onto := new Cell'(Item => Item, Next => Onto); -- '
end Push;
procedure Pop (Item : out Item_Type; From : in out Stack) is
begin
if Is_Empty(From) then
raise Underflow;
else
Item := From.Item;
From := From.Next;
end if;
end Pop;
function Is_Empty (S : Stack) return Boolean is
begin
return S = null;
end Is_Empty;
--added this code, and then had errors!
function Top (S : Stack) return Item_Type is
begin
--Raise the underflow
if Is_Empty(S) then
raise Underflow;
else
--or return top item from the stack, call pop
Pop (Item_Type, from => S);--I think I should pull from the stack w/pop
end if;
return Item_Type;
end Top;
end Unbound_Stack;
You're passing in a type (Item_Type) into Pop. Instead you need to declare a variable of type Item_Type and use that.
e.g.
function Top (S : Stack) return Item_Type is
Popped_Item : Item_Type;
begin
...
and then the call to Pop becomes:
Pop (Item => Popped_Item, From => S)
You have two error messages referring to this line:
Pop (Item_Type, from => S);--I think I should pull from the stack w/pop
The first one is pointing at Item_Type and says "invalid use of subtype mark in expression or call".
This means that you are using the name of a type in a place where that isn't allowed. Actual parameters to subprograms can never be types. You need to use (depending on the parameter direction) a variable or an expression for the actual parameter.

Working with private types in Ada to create a private int

I am trying to implement a private type in Ada like it is used in Java or C++. For example I want to have a "private int" in Ada.
As I have found here http://en.wikibooks.org/wiki/Ada_Programming/Object_Orientation#Encapsulation:_public.2C_private_and_protected_members I have to implement my variable in the package body. So I have tried to implement this like it is described on the example.
My problem is that I can't create a Create function for creating an object and set the values. My second problem is that I want to have children of this type. These children should have a Create function which sets the values for the masterclass and the subclass.
Here is my code which is not working. I have added comments on the points which is not working.
private with Ada.Finalization;
package MasterClass is
type MasterC is tagged private;
type MasterC_Class_Ref is access all MasterC'Class;
procedure printNumObjects;
procedure do( This : in MasterC );
function Make (f1, f2 : Float) return MasterC;
function getVar(This : MasterC) return float;
private
type Private_Part; -- declaration stub
type Private_Part_Pointer is access Private_Part;
type Private_Component is new Ada.Finalization.Controlled with record
P: Private_Part_Pointer;
end record;
overriding procedure Initialize (X: in out Private_Component);
overriding procedure Adjust (X: in out Private_Component);
overriding procedure Finalize (X: in out Private_Component);
type MasterC is tagged record
P : Private_Component;
end record;
end MasterClass;
package body MasterClass is
numObjects : Integer := 0;
type Private_Part is record -- complete declaration
fTest1, fTest2 : float := 0.0;
end record;
overriding procedure Initialize (X: in out Private_Component) is
begin
X.P := new Private_Part'(fTest1=>0.0, fTest2 => 0.0);
end Initialize;
overriding procedure Adjust (X: in out Private_Component) is
begin
X.P := new Private_Part'(fTest1 => X.P.fTest1, fTest2 => X.P.fTest2);
end Adjust;
overriding procedure Finalize (X: in out Private_Component) is
procedure Free is new Ada.Unchecked_Deallocation (Private_Part, Private_Part_Pointer);
begin
Free (X.P);
end Finalize;
function Make (f1, f2 : Float ) return MasterC is
begin
numObjects := numObjects + 1;
return new MasterC'(fTest1=>0.0, fTest2=>0.0); -- This is not working!
end Make;
procedure do( This : in MasterC ) is
begin
Put_Line( "doneMaster");
end do;
function getVar( This : MasterC )
return float is
begin
return This.P.P.fTest1; -- This is not working!
end getVar;
end MasterClass;
with MasterClass; use MasterClass;
package SubClass is
type SubC is new MasterClass.MasterC with
record
fExtra1 : float := 0.0;
fExtra2 : float := 0.0;
end record;
type SubC_Class_Ref is access all SubC'Class;
overriding procedure do(This : SubC);
function Make (f1, f2 : Float) return SubC;
function Make1 (f1, f2 , w, h: Float) return SubC;
end SubClass;
with MasterClass; use MasterClass;
package body SubClass is
function Make ( f1, f2 : Float ) return SubC is
begin
return ((fTest1 => f1, fTest2 => f2, fExtra1 => 0.0, fExtra2 => 0.0));
end Make;
function Make1 ( f1, f2, w, h: Float ) return SubC is
begin
return (fTest1 => f1, fTest2 => f2, fExtra1 => w, fExtra2 => h);
end Make1;
overriding procedure do( This : in SubC ) is
begin
do(MasterC(This));
Put_Line( "doneSub");
end do;
end SubClass;
I cant find any information how to implement this.
The lines which I don't how to implement is the return line in the Make function
return new MasterC'(fTest1=>0.0, fTest2=>0.0); -- This is not working!
Then the line for reading the values
return This.P.P.fTest1; -- This is not working!
And then the line in the Make function for the Subclass.
return ((fTest1 => f1, fTest2 => f2, fExtra1 => 0.0, fExtra2 => 0.0)); -- This is not working!
ajb's answer is very good, but I hope you'll allow me to "work up" to Ada's OOP facilities because they're actually fairly different than the Java equivalents. -- I'm typing off the top of my head here, so the examples might not be compilable, but should do to get the ideas across.
Package Test_1 is
Type Point is record
x, y : Integer;
end record;
-- Some operations
End Test_1;
In the above we are creating a type, but there's a problem here: it exposes the implementation and users can go and change the values directly, which could be disastrous if certain processes/properties need to be ensured. (It also introduces dependance on implementation details.)
In order to address this, we can make the record private and make clients use functions and procedures to alter the internal state -- just like getters and setters (but we haven't touched on any OOP yet).
Package Test_2 is
Type Point is private;
Function Create( x, y : Integer ) return Point;
Function Get_X ( P : Point ) return Integer;
Function Get_Y ( P : Point ) return Integer;
-- Some more operations.
Private
Type Point is record
x, y : Integer;
end record;
-- Ada 2012 expression-functions, for brevity.
Function Create( x, y : Integer ) return Point is ( x => x, y => y );
Function Get_X ( P : Point ) return Integer is ( P.X );
Function Get_Y ( P : Point ) return Integer is ( P.Y );
End Test_2;
In the above the change is made so that the implementation is private, this allows us to change the implementation (see below) without forcing clients to recompile. (We could change Test_3 to Test_2 and it would still work.)
Package Test_3 is
Type Point is private;
Function Create( x, y : Integer ) return Point;
Function Get_X ( P : Point ) return Integer;
Function Get_Y ( P : Point ) return Integer;
-- Some more operations.
Private
Type Point is record
x, y : Float;
end record;
-- Ada 2012 expression-functions, for brevity.
Function Create( x, y : Integer ) return Point is
( x => Float(x), y => Float(y) );
Function Get_X ( P : Point ) return Integer is
( Integer(P.X) );
Function Get_Y ( P : Point ) return Integer is
( Integer(P.Y) );
End Test_3;
So, as you can see private means something different in Ada than it does in Java. Because Ada had this notion of private before OOP was added (in Ada 95) it was carried over to the OOP. (Basically the idea is that changes in a private-type's implementation cannot cause a program to change states becoming legal or illegal as a result.)
As you can see, Ada also had the notion of records and indirected access [private types] and even inheritance [derived types]... but Ada still had the notion of types, and especially distinct types that could be prohibited from interacting (a type for length and another for weight), and subtypes [which were types with added constraints] were different enough that it wouldn't be a good fit, and so they needed some way to distinguish between a type and a "type-or-something-derived-from-it" which is where the 'class attribute comes in: Type_Name'Class denotes a whole branch of an inheritance tree of a tagged-type.
-- Declare an operation that must be overridden in derived types,
-- and which takes the specific type:
Function Operation( Input : Type_Name ) return Boolean is abstract;
-- Declare an operation that takes the whole class:
Function Operation( Input : Type_Name'Class ) return Boolean;
Because of the rule above, a record that had some private components needs to be in the private portion of the spec so that changes to its internal structure don't impact the legality of the clients.
Now we're at a point roughly analogous to what you're used to in Java: class-definitions and inheritance, but with this added idea that private is something dealing with client-use (and packages) rather than, strictly-speaking, the object (or type) itself.
Unlike in Java, you don't need new to create an object. new specifically allocates an object and returns an access to the object. So this:
return new MasterC'(fTest1=>0.0, fTest2=>0.0); -- This is not working!
fails because the function is declared to return a MasterC, not an access MasterC or any type that is declared as access MasterC (or access all MasterC'class or anything of the sort). The function doesn't return an access type at all. So don't use new. Instead, the form will be
return (P => ???); -- keep reading to see what ??? is
The value of P here is a PrivateComponent. This is a subtype of Ada.Finalization.Controlled with an additional component P, so the syntax will look like
return (P => (Ada.Finalization.Controlled with P => ???))
The value of that P will be Private_Part_Pointer, which is an access type (to Private_Part), so that's where you'd use new.
return (P => (Ada.Finalization.Controlled with P =>
new Private_Part' (ftest1=>0.0, ftest2=>0.0)));
It's really not that complicated. To create a value of a record type, put the values in parentheses with component-name => followed by a value for each component. To create a value of an access type, use new.
When returning a SubC, things get interesting. The SubC has the same components as a MasterC, plus the two you've added. Thus, it has three components: P, fExtra1, fExtra2. However, you can't use the name P here, because it's in the private part of MasterClass and is thus invisible to SubClass. To create a SubC, you'll have to call a function to create the MasterC part of the SubC. The result will look something like
return (MasterClass.Make(f1, f2) with fExtra1 => 0.0, fExtra2 => 0.0);
[Note: This is called an extension aggregate.]
This uses MasterClass.Make to create a MasterC, which will have a P component; the SubC function result uses that P component with the fExtra1 and fExtra2 you've specified to create the three components you need for a SubC.
Disclaimer: I haven't tested this (I'm at home and don't have a compiler handy), so I may have gotten some of the syntax wrong, or there may be other subtle errors I missed.
EDIT: Now that I can use a compiler, I've found that the above two changes make your source compile (the second change has to be implemented in two places); except that do is a reserved word and cannot be used as a procedure name, and printNumObjects needs a body. This statement:
return This.P.P.fTest1; -- This is not working!
compiles fine with my compiler.

How to change the range of the range type?

Lets say I have
function x return boolean is
type range0 is range 1..1;
begin
canse x is
when 4=> range0:=firstArray'range;
when 5=> range0:=secondArray'range;
when 6=> range0:=1..100;
end case;
end x;
Basically I would like to change the range of range0 on the go? How may I accomplish this without using the declare block?
Basically I would like to change the range of range0 on the go? How may I accomplish this without using the declare block?
Hm...
In Ada 2012 you can use if- and case-expressions, so you could have something like this:
Type Array_Type is Array(Positive Range <>) of Integer;
Array_1 : Array_Type(1..128);
Array_2 : Array_Type(33..63);
-- your variant-selector
Use_1 : constant Boolean:= True;
-- Your variant-range here:
Subtype Variant_Range is Positive Range
(if Use_1 then Array_1'First else Array_2'First)
..(if Use_1 then Array_1'Last else Array_2'Last);
Array_3 : Array_Type( Variant_Range );
All that said, this probably isn't the best way to go about it and using a declare-block is very likely going to be more easily maintained.
You could technically satisfy the stated requirements by converting the obvious way (declare block) into a local procedure :
function x return boolean is
procedure use_dynamic_range(first,last : in integer) is
type range0 is new integer range first .. last;
begin
null;
end use_dynamic_range;
begin
case z is
when 4=> use_dynamic_range(firstArray'first, firstArray'last);
when 5=> use_dynamic_range(secondArray'first, secondArray'last);
when 6=> use_dynamic_range(1,100);
end case;
end x;
Because it's a local procedure it executes in the same scope as the equivalent declare block, therefore it can access everything visible within X, so you don't need to pass it a huge parameter list.
What about something like :
function x return Boolean is
type Range_Info_Type is
record
First : Integer;
Last : Integer;
end record;
function Get_Range_Info_Type return Range_Info_Type is
begin
case z is
when 4=> return Range_Info_Type'(First => firstArray'First,
Last => FirstArray'Last);
when 5=> return Range_Info_Type'(First => secondArray'First,
Last => secondArray'Last);
when 6=> return Range_Info_Type'(First => 1,
Last => 100);
when others => return Range_Info_Type'(First => 1,
Last => 1);
end case;
end;
MyTypeInfo : constant Range_Info_Type := Get_Range_Info_Type;
-- Now declare the actual type I want to use.
type range0 is new Integer range MyTypeInfo.First .. MyTypeInfo.Last;
begin
return true;
end x;
A declare block might be easier to understand by this should do the trick.
Note that you cannot write type range0 is range <expr>..<expr> in your case since expr should be a static expression (see RM 3.5.4)
Another non declare-block answer from Ada 2012:
Minimum : Integer := Integer'First; --' SO highlight correction
Maximum : Integer := Integer'Last; --' *same*
Function In_Range(X : Integer) return Boolean is
( X in range Minimum..Maximum );
Subtype Variant_Range is Integer Range Integer
with Dynamic_Predicate => In_Range(Variant_Range);
WARNING: Though this should work, I have not tested it.

Resources