How to define "+" for a record type - ada

I'm trying to create a package in ADA. I have three files, adb(main program), ads(package), and adb(body package). I can not see any problems with my main and package files. However, in my body package, I have trouble in writing a function that adds the values of P1 and P2 together and then returns its value.
My main program:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Price_Handling; use Price_Handling;
procedure Test_Price_Plus is
P1, P2 : Price_Type;
begin
P1.Dollar:= 19;
P1.Cents:= 50;
P2 := (Dollar => 10, Cents=> 0);
Put("P1 is ");
Put(P1);
New_Line;
Put("P2 is ");
Put(P2);
New_Line;
Put("If we add P1 and P2, then we get: ");
Put(P1 + P2);
New_Line;
end Test_Price_Plus;
My package:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
package Price_Handling is
type Price_Type is private;
procedure Get(Item: out Price_Type);
function "+"(Left, Right: in Price_Type) return Price_Type; -- Left(Dollar), Right(Cents)
private
type Price_Type is
record
Dollar, Cents: Integer;
end record;
end Price_Handling;
My Package Body:
Package Body Price_Handling is
procedure Put(Item:in Price_Type) is
begin
Put(Item.Dollar); Put(":");
Put(Item.Cents);
end Put;
function "+"(Left, Right: in Price_Type) return Price_type is
begin
-- Need to write a function that adds P1 and P2 together and return its value
end "+";

The easiest way for newcomers is probably just create a dummy result value and return it:
function "+"(Left, Right: in Price_Type) return Price_type is
Result : Price_Type;
begin
Result.Dollars := Left.Dollars + Right.Dollars;
Result.Cents := Left.Cents + Right.Cents;
-- If your cents are higher than 100, then we
-- need to increment dollars and adjust the cents
-- count
if Result.Cents > 99 then
Result.Dollars := Result.Dollars + 1;
Result.Cents := Result.Cents - 100;
end if;
return Result;
end "+";
However, this is really weak. Your Price_type is not design using types that can protect you from errors. If you want to leverage Ada's safety aspects, consider making a Cents subtype that restricts you to 0 to 99:
subtype Cents_Type is Natural range 0 .. 99;
That way, if you make a programming error and put in a value higher than 99 or negative, then the program will catch it and raise an exception. Same for dollars. Make a new type for non negative values:
subtype Dollars_Type is Natural;
Now update your record to use those types and also default initialize them:
type Price_Type is record
Dollars : Dollars_Type := 0;
Cents : Cents_Type := 0;
end record;
Then if you do that, you can update the + function to use a dummy variable to hold the cents in case you do go over 99 while adding them together.
function "+"(Left, Right: in Price_Type) return Price_type is
Result : Price_Type;
Cents_With_Overflow : Natural;
begin
Result.Dollars := Left.Dollars + Right.Dollars;
Cents_With_Overflow := Left.Cents + Right.Cents;
-- If your cents are higher than 100, then we
-- need to increment dollars and adjust the cents
-- count
if Cents_With_Overflow > 99 then
Result.Dollars := Result.Dollars + 1;
Result.Cents := Cents_With_Overflow - 100;
else
Result.Cents := Cents_With_Overflow;
end if;
return Result;
end "+";

Another approach for this problem is to convert the dollars and cents for each instance of Price_Type to a total number of cents. Simply add the two cents values then convert the result back to dollars and cents.
package Price_Handling is
type Price_Type is private;
function "+" (Left, Right : Price_Type) return Price_Type;
procedure Get(Item : out Price_type);
procedure Print(Item : in Price_Type);
private
subtype Cents_Type is Integer range 0..99;
type Price_Type is record
Dollars : Natural := 0;
Cents : Cents_Type := 0;
end record;
end Price_Handling;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
package body Price_Handling is
---------
-- "+" --
---------
function "+" (Left, Right : Price_Type) return Price_Type is
function To_Cents ( Item : Price_type) return Natural is
Temp : Natural := 100 * Item.Dollars + Item.Cents ;
begin
return Temp;
end To_Cents;
function To_Price(Item : in Natural) return Price_Type is
Dollars : Natural;
Cents : Cents_Type;
begin
Dollars := Item / 100;
Cents := Item mod 100;
return (Dollars, Cents);
end To_Price;
begin
return To_Price(To_Cents(Left) + To_Cents(Right));
end "+";
---------
-- Get --
---------
procedure Get (Item : out Price_type) is
begin
Put("Enter the dollars for the price: ");
Get(Item.Dollars);
Put("Enter the cents for the price: ");
Get(Item.Cents);
end Get;
-----------
-- Print --
-----------
procedure Print (Item : in Price_Type) is
begin
Put(Item => Item.Dollars, Width => 1);
Put (".");
if Item.Cents < 10 then
Put ("0");
end if;
Put (Item => Item.Cents, Width => 1);
end Print;
end Price_Handling;
with Price_Handling; use Price_Handling;
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
P1 , P2 : Price_Type;
begin
Get(P1);
Get(P2);
Put("The sum of P1 and P2 is: ");
Print(P1 + P2);
New_Line;
end Main;
An example of executing this program produces the following output:
Enter the dollars for the price: 10
Enter the cents for the price: 41
Enter the dollars for the price: 0
Enter the cents for the price: 32
The sum of P1 and P2 is: 10.73
Another example showing proper incrementation of the dollars amount when the two cents amounts sum to more than a dollar is:
Enter the dollars for the price: 10
Enter the cents for the price: 52
Enter the dollars for the price: 3
Enter the cents for the price: 95
The sum of P1 and P2 is: 14.47

Related

Using Ada, using instance of Ada.Numerics.Generic_Elementary_Functions(Real), calculating Nth root and output same

Using Ada 2018 (increment of 2012), within a loop structure, I need to calculate the Nth root of Integers.
In my package combinations.ads specification declaration (using GNAT GPS), I have
type Real is digits 6;
In package body combinations.adb, I have a procedure build, where before the begin, I instantiate Ada’s Generic_Elementary_Functions(Float), with
package Fermat_math is new
Ada.Numerics.Generic_Elementary_Functions(Real) ;
use Fermat_math
Later, in output section, I try:
-- -------------- buggy, fix
-- combo_sum_root := Fermat_math.Exp (Log (Integer(combo_sum_root) / n); — n is integer type
combo_sum_root := Real(combo_sum) ** (1/n) ;
-- -------------
put(" and sum's root is ");
put(combo_sum_root'image ); — -- gives all roots as 1.00000E+00
I had it working a few weeks back, with roots = 3.878… etc., but I lost that in careless version control.
Actual Code here:
— combinations.ads specification ------------------------------------------
with gearbox;
use gearbox;
with Ada.Float_Text_IO ; use Ada.Float_Text_IO;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics; use Ada.Numerics;
with Ada.Numerics.Elementary_Functions;
use Ada.Numerics.Elementary_Functions;
package combinations is
type combo_action is (add_element,clear, show, show_sum, Build);
type Real is digits 6 ;
combo_sum_root : Real ;
i,n,b, combos_cnt
,combo_sum : integer ;
procedure get_parms ;
Procedure build (b,n,r:integer) ;
end combinations;
-- combinations.adb BODY ---------------------------------------
with Text_IO ; use Text_IO;
with Ada.Text_IO ; use Ada.Text_IO;
with Ada.INteger_Text_IO ; use Ada.Integer_Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.UNbounded;
with gearbox ; use gearbox;
with Ada.Numerics.Generic_Elementary_Functions ;
package body combinations is
group, Intersection_count,r : Integer ;
done, get_value : boolean := false ;
CR: constant Character := Character'Val (13) ;
type gear_arrays is array(positive range <>) of integer;
-- ------------------------------------------------------------
procedure get_parms is
begin
...
end get_parms ;
-- --------------------------------------------------
procedure build (b,n,r: Integer) is
-- --------------------------------------------------
cnt, e_cnt, value : integer :=0 ;
launch, pause : character ;
run_again : String := " " ;
show_group : Unbounded_string ;
all_done, combo_done : boolean := false ;
combo_sum_root : Real ;
progress_string : Unbounded_String ;
gears:gear_array (1..r) ;
-- with Ada.Numerics.Generic_Elementary_Functions ; — in specification .ads file
package Fermat_math is new
Ada.Numerics.Generic_Elementary_Functions(Real) ;
use Fermat_math ;
begin
...
...
put("Selecting "); -- put(tot_combos, width=>1);
put(" Possible Combinations,"); New_line;
While Not all_done loop -- for all/x combiNatioNs
...
end loop;
-- ------------------------
combo_sum := 0;
for e in 1..r loop -- select r value, element of grou & size of combiatios
value := fermats(gears(e).position,1);
...
put ("Combination sum is "); put (combo_sum, width => 1);
…..
-- -------------- buggy, fix
-- combo_sum_root := Fermat_math.Exp (Log (Integer(combo_sum_root) / n);
combo_sum_root := Real(combo_sum) ** (1/n) ;
-- -------------
put(" and sum's root is ");
put(combo_sum_root'image ); -- gives all roots as 1.00000E+00
end loop;
group := group + 1; --
end if; -- is New group and shift
end loop; -- Not all doNe
eNd build;
begin -- package
Null;
end combinations;
The critical issue in your example is that "n is integer type." When you try to create a rational exponent, your expression 1/n evaluates to an Integer with value zero. The package Generic_Elementary_Functions requires that "Exponentiation by a zero exponent yields the value one."
The solution is to use the type Real when creating your exponent: 1.0 / Real(N). Expanding on #Jim Rogers' example, the code below also illustrates calculating the power via the logarithm:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Generic_Elementary_Functions;
procedure Nth_Root is
type Real is digits 6;
package Real_Functions is new Ada.Numerics.Generic_Elementary_Functions
(Real);
use Real_Functions;
N : constant Natural := 2;
Power : constant Real := 1.0 / Real(N);
Base : constant Real := 2.0;
begin
Put_Line ("√2:" & Real'Image (Sqrt (Base)));
Put_Line ("√2:" & Real'Image (Base**Power));
Put_Line ("√2:" & Real'Image (Exp (Power * Log (Base))));
end Nth_Root;
Console:
√2: 1.41421E+00
√2: 1.41421E+00
√2: 1.41421E+00
The "**" operator in Ada.Numerics.Generic_Elementary_Functions provides you with the ability to find the Nth root of a floating point number.
The following example compares use of the sqrt function and the "**" operator.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Generic_Elementary_Functions;
procedure Main is
type Real is digits 6;
package Real_Functions is new Ada.Numerics.Generic_Elementary_Functions(Real);
use Real_Functions;
base : Real := 2.0;
Power : Real := 1.0 / 2.0;
begin
Put_Line("sqrt of 2.0 is: " & Real'Image(sqrt(base)) & " and " &
Real'Image(base**Power));
end Main;
The result of this example is:
sqrt of 2.0 is: 1.41421E+00 and 1.41421E+00
The exponent for the "**" operator is simply the inverse of N.
Edit: Adding the manipulations to calculate an integer root of a number.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Numerics.Generic_Elementary_Functions;
procedure integer_roots is
function int_root (Num : Positive; Exponent : Positive) return Natural is
type Real is digits 6;
package real_functions is new Ada.Numerics.Generic_Elementary_Functions
(Real);
use real_functions;
Real_Num : Real := Real (Num);
Real_Exponent : Real := 1.0 / Real (Exponent);
Real_Result : Real := Real_Num**Real_Exponent;
begin
return Natural (Real'Truncation (Real_Result));
end int_root;
Num : Positive;
Exponent : Positive;
begin
Put ("Enter the base number: ");
Get (Num);
Skip_Line;
Put ("Enter the root: ");
Get (Exponent);
Put_Line
("The" & Exponent'Image & "th root of" & Num'Image & " is" &
Natural'Image (int_root (Num, Exponent)));
end integer_roots;
The function int_root shown above calculates the floating point root then converts the truncated result to the subtype Natural.
A sample execution of this program is:
Enter the base number: 10000
Enter the root: 20
The 20th root of 10000 is 1

Constraint Error running Heapify SiftDown

I am writing this code in Ada for a class where we have to teach ourselves the code. I understand heap sort, but the Ada syntax is really confusing me. I don't understand why I am getting a constraint error in this sort function.
Essentially we have to pass array "A" into this procedure, and it should organize it. I get the constraint error at siftDown(A(Start...A'Last));
Thank you in advance
Procedure sort_3(A : in out array_type) is
procedure swap(Left : in out Integer; Right : in out Integer) is
temp : Integer;
begin
temp := Left;
Left := Right;
Right := Temp;
end swap;
procedure siftDown(A : in out array_type) is
Count : Integer := 1;
root : Integer := Integer'Pos(A'First);
child : Integer := Integer'Pos(A'Last);
last : Integer := Integer'Pos(A'Last);
begin
while root * 2 + 1 <= last loop
child := root * 2 + 1;
if child + 1 <= last and then A(Integer'Val(child)) < A(Integer'Val(child + 1)) then
child := child + 1;
end if;
if A(Integer'Val(root)) < A(Integer'Val(child)) then
swap(A(Integer'Val(root)), A(Integer'Val(child)));
root := child;
else
exit;
end if;
end loop;
end siftDown;
procedure heapify(A : in out array_type) is
Count : Integer := 0;
First_Pos : Integer;
Last_Pos : Integer;
Start : Integer;
begin
First_Pos := A'First;
Last_Pos := A'Last;
Start := Integer'Val((Last_Pos - First_Pos + 1) / 2);
loop
siftDown(A(Start...A'Last));
if Start > Integer'First then
Start := Integer'Pred(Start);
else
exit;
end if;
end loop;
end heapify;
Last_Index : Integer := Integer'Last;
begin
heapify(A);
while Last_Index > Integer'First loop
swap(A(Last_Index), A(A'First));
Last_Index := Integer'Pred(Last_Index);
siftDown(A(A'First..Last_Index));
end loop;
end sort_3;
You have a syntax error in the code - an extra dot in A(Start...A'Last).
The syntax A(Start..A'Last) means a slice, part of array from Start to the last element. The Constraint_Error means that Start not in array bounds. Try to add
Ada.Text_IO.Put_Line (Start'Image);
before that line and you will see Start values and when it became out of the A'Range.
Your code has some references to Integer'First and Integer'Last, which are huge values that have nothing to do with the array A and its values. I'm pretty sure you should use A'First and A'Last instead.
Also a note on style: Using the same identifier, "A", for the parameter of the local (inner, nested) procedures as for the parameter "A" of the containing (outer) procedure, when these arrays can be different, invites confusion and errors. Better to use different identifiers.

Formal parameter "Item" is not referenced

By using subprograms, I try to write a program that displays a VAT table. It asks the user to enter some data and based on these data, displays a VAT-table. However, I get a warning which says: "Formal parameter "Item" is not referenced". My program does display a table but it looks terrible. Here you can see how far I have come:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
procedure Underprogram is
V_percent, S_length, H_price, L_price, Price_Wm : Float;
X: Integer;
procedure Get_Pop(Item : out Float ) is
begin
Put_Line("Write ur first price:");
Get(H_price, width=>0);
while H_price < 0.0 loop
Put("Wrong inout, try again! : ");
Get(H_price);
end loop;
loop
Put_Line("Write in your second price:");
Get(L_price, width=>0);
if H_price > L_price then
exit; end if; end loop;
Put_Line("Which VAT percent do ypu want? ");
Get(V_percent, width=>0);
while V_percent > 100.0 or V_percent <= 0.0 loop
Put_Line("The vat percent you fed in is invalid, try again! ");
Get(V_percent);
end loop;
Put_Line("Which step length do you want? ");
Get(S_length, width=>0);
while S_length < 0.1 or S_length > 1.0 loop
Put_Line("The step length you just fed in is out of the range: ");
Get(S_length);
end loop; end Get_Pop;
procedure Put_pop(Item : in Float) is
begin
X := Integer(Float'Floor((H_price-L_price) / S_length + 1.0));
Put_Line(" === Vattabell === ");
Put_Line("Price without VAT Vat Price with VAT ");
Put_Line("--------------- ---- -------------- ");
for I in 0..X -1 loop
Price_Wm := L_price + Float(I) * S_length;
Put(Price_Wm, 5,2,0);
Put((L_price + Float(I) * S_length) * V_percent/100.0,
13,2,0);
Put(Price_Wm * (1.0 + V_percent/100.0), 15,2,0);
New_Line;
end loop;
end Put_pop;
begin
Get_Pop(V_percent); Put_pop(V_percent);
Get_Pop(S_length); Put_pop(S_length);
Get_Pop(H_price); Put_pop(H_price);
Get_Pop(L_price); Put_pop(L_price);
Get_Pop(Price_Wm); Put_pop(Price_Wm);
end Underprogram;
Here is an update: I just rewrote my code based in the comments and it works fine. Now I wonder how I can add more functions and subprograms to this code so that the Underprogram procedure looks cleaner?. Right now I have just two subprograms:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
procedure Underprogram is
Higher, Lower, VAT, Step, Price_without_VAT: Float;
X : Integer;
procedure Get_data(Item: out Float) is
begin
Get(Item);
end Get_data;
procedure Put_data(Item: in Float) is
begin
Put(Item, 2,2,0); Put(" ");
end Put_data;
begin
Put("Write the higher price: ");
Get_data(Higher);
while Higher < 0.0 loop
Put("Wrong input, try again: ");
Get_data(Higher); end loop;
loop
Put("Write the lower price: ");
Get_data(Lower);
if Lower < Higher then
exit; end if; end loop;
Put("Write the VAT : ");
Get_data(VAT);
while VAT > 100.0 or VAT < 0.0 loop
Put("Wrong input, try again:");
Get_data(VAT);
end loop;
loop
Put("Write the step: ");
Get_data(Step);
if Step > 0.0 then
exit; end if; end loop;
Put_data(Higher);
Put_data(Lower);
Put_data(VAT);
Put_data(Step);
X := Integer(Float'Floor((Higher-Lower) / Step + 1.0));
Put_Line(" === VATTABELL === ");
Put_Line("Price without VAT VAT Price with VAT ");
Put_Line("--------------- ---- -------------- ");
for I in 0..X -1 loop
Price_without_VAT := Higher + Float(I) * Step;
Put(Price_without_VAT, 5,2,0);
Put((Higher + Float(I) * Step) * VAT/100.0, 13,2,0);
Put(Price_without_VAT * (1.0 + VAT/100.0), 15,2,0);
New_Line;
end loop;
end Underprogram;
The following code is your code after re-organized by the pretty printer provided in the GNAT Studio 2020 Community Edition:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
procedure Underprogram is
V_percent, S_length, H_price, L_price, Price_Wm : Float;
X : Integer;
procedure Get_Pop (Item : out Float) is
begin
Put_Line ("Write ur first price:");
Get (H_price, Width => 0);
while H_price < 0.0 loop
Put ("Wrong inout, try again! : ");
Get (H_price);
end loop;
loop
Put_Line ("Write in your second price:");
Get (L_price, Width => 0);
if H_price > L_price then
exit;
end if;
end loop;
Put_Line ("Which VAT percent do ypu want? ");
Get (V_percent, Width => 0);
while V_percent > 100.0 or V_percent <= 0.0 loop
Put_Line ("The vat percent you fed in is invalid, try again! ");
Get (V_percent);
end loop;
Put_Line ("Which step length do you want? ");
Get (S_length, Width => 0);
while S_length < 0.1 or S_length > 1.0 loop
Put_Line ("The step length you just fed in is out of the range: ");
Get (S_length);
end loop;
end Get_Pop;
procedure Put_pop (Item : in Float) is
begin
X := Integer (Float'Floor ((H_price - L_price) / S_length + 1.0));
Put_Line (" === Vattabell === ");
Put_Line ("Price without VAT Vat Price with VAT ");
Put_Line ("--------------- ---- -------------- ");
for I in 0 .. X - 1 loop
Price_Wm := L_price + Float (I) * S_length;
Put (Price_Wm, 5, 2, 0);
Put ((L_price + Float (I) * S_length) * V_percent / 100.0, 13, 2, 0);
Put (Price_Wm * (1.0 + V_percent / 100.0), 15, 2, 0);
New_Line;
end loop;
end Put_pop;
begin
Get_Pop (V_percent);
Put_pop (V_percent);
Get_Pop (S_length);
Put_pop (S_length);
Get_Pop (H_price);
Put_pop (H_price);
Get_Pop (L_price);
Put_pop (L_price);
Get_Pop (Price_Wm);
Put_pop (Price_Wm);
end Underprogram;
I simply copied the source into the GNAT Studio IDE, saved the file, then chose the Pretty Print option under the Code tab in the IDE. I did nothing to manually format the code.
See how the use of indentation helps visually identify the beginning and ending of procedures, functions, and loops.
The reason that the first pass through the table reports the VAT data as zero is that you pass V_Percent to Get_Pop as the actual for the out parameter Item, but you never assign to Item, with the result that the compiler assigns something to it on exit from the procedure, overwriting the value of V_Percent which you already assigned explicitly.
Get_Pop can’t logically have a single out parameter, because its job (as you’ve coded it) is to read four values. Either no parameters at all, or give each required value its own out parameter, or create a record type to hold all 4 values.

Is it necessary to wrap shared array data in a protected type?

I am aware that it is generally bad practice (and the ARM probably says that this is undefined behavior), but I am attempting to write a fast text parser containing many floating point numbers and it would be very expensive to wrap the loaded text into a protected type given that the data is examined character by character and may have up to a million floats or pass a slice on the stack.
Is it possible in Ada (GNAT) to "safely" divide up an unprotected array for consumption with multiple tasks given that the array is never written and only read?
As in:
Text : array (1..1_000_000) of Character := ...
begin
Task_1.Initialize (Start_Index => 1, End_Index => 10_000);
Task_2.Initialize (Start_Index => 10_001, End_Index => 20_000);
...
Yes. That is safe because there is no race condition associated with reading the data and there is no temporally overlapping write operation.
For example, the following code uses such a technique to perform parallel addition on an array of integers.
package Parallel_Addition is
type Data_Array is array(Integer range <>) of Integer;
type Data_Access is access all Data_Array;
function Sum(Item : in not null Data_Access) return Integer;
end Parallel_Addition;
package body Parallel_Addition is
---------
-- Sum --
---------
function Sum (Item : in not null Data_Access) return Integer is
task type Adder is
entry Set (Min : Integer; Max : Integer);
entry Report (Value : out Integer);
end Adder;
task body Adder is
Total : Integer := 0;
First : Integer;
Last : Integer;
begin
accept Set (Min : Integer; Max : Integer) do
First := Min;
Last := Max;
end Set;
for I in First .. Last loop
Total := Total + Item (I);
end loop;
accept Report (Value : out Integer) do
Value := Total;
end Report;
end Adder;
A1 : Adder;
A2 : Adder;
R1 : Integer;
R2 : Integer;
Mid : constant Integer := (Item'Length / 2) + Item'First;
begin
A1.Set (Min => Item'First, Max => Mid);
A2.Set (Min => Mid + 1, Max => Item'Last);
A1.Report (R1);
A2.Report (R2);
return R1 + R2;
end Sum;
end Parallel_Addition;
with Parallel_Addition; use Parallel_Addition;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Calendar; use Ada.Calendar;
procedure Parallel_Addition_Test is
The_Data : Data_Access := new Data_Array (1 .. Integer'Last / 5);
Start : Time;
Stop : Time;
The_Sum : Integer;
begin
The_Data.all := (others => 1);
Start := Clock;
The_Sum := Sum (The_Data);
Stop := Clock;
Put_Line ("The sum is: " & Integer'Image (The_Sum));
Put_Line
("Addition elapsed time is " &
Duration'Image (Stop - Start) &
" seconds.");
Put_Line
("Time per addition operation is " &
Float'Image(Float(Stop - Start) / Float(The_Data'Length)) &
" seconds.");
end Parallel_Addition_Test;

Static Referencing of Member Values - Ada

Hi
I am trying out my first program in Ada of creating a single player dice game.
But facing problem in maintaining score of the player.
Goal: Each player has 10 turns and scores 10 points if total of 2 rolls is 7
Problem: Every time total score gets reset and 10 does not get added to current score.
Total_Score is the final score to be displayed.
Please help!!! Any help appreciated!!!
Thanks :)
My code is as follows:
with Ada.Numerics.Discrete_Random,Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;
procedure Game is
subtype Die is Integer range 1 .. 6;
subtype Dice is Integer range 2*Die'First .. 2*Die'Last;
package Random_Die is new Ada.Numerics.Discrete_Random (Die);
use Random_Die;
type MY_TYPE is range 1..10;
package My_Int_IO is new Ada.Text_IO.Integer_IO(MY_TYPE);
use My_Int_IO;
My_Range : MY_TYPE;
G : Generator;
Roll : Dice; -- Total Rolled
Roll_One : INTEGER; -- Roll 1
Roll_Two : INTEGER; -- Roll 2
Total_Score : INTEGER; -- Current Score
Choice : INTEGER; -- Game Choice
Total_Roll : INTEGER; -- Total Rolled Returned
Score : INTEGER; -- Static Score count
function Roll_Dice return INTEGER is
begin
-- Start the generator in a unique state in each run
Reset (G);
Total_Score := 0;
-- Roll a pair of dice
Roll_One := Random(G);
Roll_Two := Random(G);
Put(Roll_One,3);
Put(Roll_Two,3);
Roll := Roll_One + Roll_Two;
return Roll;
end Roll_Dice;
begin
Total_Score := 0;
for Index in MY_TYPE loop
Put("Roll Dice: Press 1 To Exit: Press 2 ");
New_Line;
Get(Item => Choice);
if Choice = 1 then
Total_Roll := Roll_Dice;
if Total_Roll = 7 then
Put("Current Score : ");
Put(Total_Score , 3);
Total_Score := Total_Score + 10;
New_Line;
Put("Your Score : ");
Put(Total_Score, 3);
else
New_Line;
Put("Sorry! you do not score");
end if;
elsif Choice = 2 then
Put("Score ");
Put(Total_Score, 3);
exit when Choice = 2;
else
Put("Wrong Choice! You lost one chance! Try Again");
end if;
end loop;
New_Line;
Put("Total Score for this game: ");
Put(Total_Score, 3);
end Game;
Every time total score gets reset and 10 does not get added to current score.
That's because you set Total_Score to zero in the Roll_Dice function:
Total_Score := 0;
10 does get added to Total_Score:
Total_Score := Total_Score + 10;
but on the subsequent roll, the total is reset to zero.

Resources