Missing operand in for loop - ada

I have such a bubble sort statement;
procedure Bubble_Sort (Data: in out List) is
sorted: Boolean := false;
last : Integer := Data'LAST;
temp : Integer;
begin
while (not (sorted)) loop
sorted := true;
for check in range Data'First..(last-1) loop
if Data(check) < Data(check+1) then
-- swap two elements
temp := Data(check);
Data(check) := Data(check+1);
Data(check+1) := temp;
-- wasn't already sorted after all
sorted := false;
end if;
end loop;
last := last - 1;
end loop;
end Bubble_sort;
I have defined 'Data' like this:
Unsorted : constant List := (10, 5, 3, 4, 1, 4, 6, 0, 11, -1);
Data : List(Unsorted'Range);
And the type definition of 'List' is;
type List is array (Index range <>) of Element;
on the line
for check in range Data'Range loop
I get missing operand error. How can I solve this problem?

remove the range keyword:
for check in Data'Range loop
The range keyword is used to define ranges and subtypes (sometimes anonymous), which is not needed when you use the 'Range attribute.

Related

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.

Pascal problem using dispose and later asigning NILL to that pointer. This problem only occurs when I use a for x in z

procedure freeMem (var v: tTabla; i: integer);
var
p : tPEntero;
begin
for p in v do
if p^ < i then
begin
dispose(p);
p := NIL;
end;
writeln('Memory disposed.');
end;
I have an array of 4 pointers that point to this integers:
[1, 2, 3, 4]
In the main program I call the procedure freeMem(table, 2); meaning that the expected result when I call the method writeTable(table); should be:
[NIL, 2, 3, 4]
But the result obtained is:
[12800, 2, 3, 4]
Basically a random value where I disposed the pointer.
If I modify the procedure freeMem(v, i) and don't use a for -- in -- do it works somehow, I wanna know why it doesn't work the other way
procedure freeMem (var v: tTabla; i: integer);
var
indice: integer;
begin
for indice:=1 to MAX do
if v[indice]^ < i then
begin
dispose(v[indice]);
v[indice] := NIL;
end;
writeln('Memory disposed.');
end;

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;

expected type "..." defined at ....... error in Ada

I have such a Karatsuba algorithm implementation I have written in ADA.
procedure Karatsuba (Factor_1, Factor_2 : in Number; Product : out Number) is
m : Integer;
m2 : Integer;
low1 : Number := (0,1);
high1 : Number := (0,1);
low2 : Number := (0,1);
high2 : Number := (0,1);
z0 : Index;
z1 : Index;
z2 : Index;
x : Integer;
y : Integer;
hc1 : Index;
hc2 : Index;
begin
low1 := (others => 0);
high1 := (others => 0);
low2 := (others => 0);
high2 := (others => 0);
if Factor_1'Length = 1 or Factor_2'Length = 1 then
Standard(Factor_1, Factor_2,Product);
end if;
-- calculates the size of the numbers
m := Integer'Max(Factor_1'Length, Factor_2'Length);
m2 := m / 2;
-- split the digit sequences about the middle
for Factor_1_Index in Factor_1'Range loop
x := x + 1;
if x <= m2 then
low1(Factor_1_Index) := Factor_1(Factor_1_Index);
else
high1(hc1) := Factor_1(Factor_1_Index);
hc1 := hc1 + 1;
end if;
end loop;
for Factor_2_Index in Factor_2'Range loop
y := y + 1;
if y <= m2 then
low2(Factor_2_Index) := Factor_2(Factor_2_Index);
else
high2(hc2) := Factor_2(Factor_2_Index);
hc2 := hc2 + 1;
end if;
end loop;
-- 3 calls made to numbers approximately half the size
z0 := Karatsuba(low1, low2, Product);
z1 := Karatsuba((low1 + high1), (low2 + high2), Product);
z2 := Karatsuba(high1, high2, Product);
Product := (z2*10**(2*m2))+((z1-z2-z0)*10**(m2))+(z0);
end Karatsuba;
On the last 4 lines before "end Karatsuba" line, I get the error "expected type 'Index' defined at ...". The errors I'm receiving are, respectively,
expected type "Index" defined at ....
found package or procedure name
there is no applicable operator "+" for type "Number" defined at ......
This is another class that I have assigned some variables:
package ITI8590.Natural_Number_Multiplication is
type Digit is range 0 .. 1;
type Index is new Positive;
type Number is array (Index range <>) of Digit;
for Digit'Size use 1;
procedure Standard(Factor_1, Factor_2 : in Number; Product : out Number);
procedure Karatsuba(Factor_1, Factor_2 : in Number; Product : out Number);
end ITI8590.Natural_Number_Multiplication;
Now why I get this error? I couldn't solve it, and I'm stuck in it. Could you help me?
Thanks,
Karatsuba is a procedure, so at the end instead of
z0 := Karatsuba(low1, low2, Product);
z1 := Karatsuba((low1 + high1), (low2 + high2), Product);
z2 := Karatsuba(high1, high2, Product);
it should probably read
Karatsuba(low1, low2, z0);
Karatsuba((low1 + high1), (low2 + high2), z1);
Karatsuba(high1, high2, z2);
which requires you to declare z0, z1, z2 as Number rather than Index. Note, Product is an out parameter to the procedure, so all your code achieved was to overwrite it twice with intermediate results (3 times, counting the call to Standard above).
But then you have a problem: the compiler says
yusuf.ada:25:12: unconstrained subtype not allowed (need initialization)
yusuf.ada:25:12: provide initial value or explicit array bounds
which is calling for something related to the way you have declared low1 etc:
low1 : Number := (0,1);
high1 : Number := (0,1);
low2 : Number := (0,1);
high2 : Number := (0,1);
The trouble with this approach is that you’ve now constrained the bounds of the variables: low1 is fixed to have 2 elements (set to values that you then overwrite), and can’t be expanded. I don’t know how the algorithm is supposed to work, but this seems unlikely to be right; for a start, what happens if the inputs have more than 2 digits?
One approach that might work is to use the number of digits in the input parameters:
Max_Digits : constant Positive := Factor_1’Length + Factor_2’length;
pragma Assert (Product’Length >= Max_Digits, “possible overflow”);
low1 : Number (1 .. Max_Digits) := (others => 0);
etc.
And, as ajb has commented, you’ll need to define operators +, -, *, ** between Numbers and Integers as needed, particularly in the expression (z2*10**(2*m2))+((z1-z2-z0)*10**(m2))+(z0) in the last line of the procedure.

Pascal. Recursive function to count amount of odd numbers in the sequence

I need to write recursive function to count amount of odd numbers in the sequence
Here my initial code:
program OddNumbers;
{$APPTYPE CONSOLE}
uses
SysUtils;
function GetOddNumbersAmount(const x: array of integer; count,i:integer):integer;
begin
if((x[i] <> 0) and (x[i] mod 2=0)) then
begin
count:= count + 1;
GetOddNumbersAmount:=count;
end;
i:=i+1;
GetOddNumbersAmount:=GetOddNumbersAmount(x, count, i);
end;
var X: array[1..10] of integer;
i,amount: integer;
begin
writeln('Enter your sequence:');
for i:=1 to 10 do
read(X[i]);
amount:= GetOddNumbersAmount(X, 0, 1);
writeln('Amount of odd numbers: ', amount);
readln;
readln;
end.
When i type the sequence and press "enter", program closed without any errors and i can't see the result.
Also, i think my function isn't correct.
Can someone help with that code?
UPD:
function GetOddNumbersAmount(const x: array of integer; count,i:integer):integer;
begin
if((x[i] <> 0) and (x[i] mod 2<>0)) then
count:= count + 1;
if(i = 10) then
GetOddNumbersAmount:=count
else
GetOddNumbersAmount:=GetOddNumbersAmount(x, count, i+1);
end;
You don't provide an end of recursion, i.e., you always call your function GetOddNumbersAmount again, and your program never terminates. Thus, you get an array index error (or a stack overflow) and your program crashes.
Please note, that every recursion need a case where it terminates, i.e. does not call itself. In your case, it should return if there are no elements in the array left.
In addition, you are counting the even numbers, not the odd ones.
You passed a static array to a dynamic so the index get confused:
Allocat the array with
SetLength(X,10)
allocates an array of 10 integers, indexed 0 to 9.
Dynamic arrays are always integer-indexed, always starting from 0!
SetLength(X,10)
for it:=0 to 9 do begin
X[it]:= random(100);
And second if you know the length a loop has more advantages:
function GetEvenNumbersAmount(const x: array of integer; count,i:integer):integer;
begin
for i:= 0 to length(X)-1 do
if((x[i] <> 0) and (x[i] mod 2=0)) then begin
inc(count);
//write(inttostr(X[i-1])+ ' ') :debug
end;
result:=count;
end;

Resources