How to use recursion to add the product of two Integers together? - ada

In this code, I am asking the user to input two integers (Index, Mindex) and then I display all the integers between 1..Index and 1..Mindex. What my problem is here that I do not know how to multiply the values of Integers in Index and Integers in `Mindex and then add up the product of these two together
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Add is
Index, Mindex : Integer;
procedure calc (Item : in Integer) is
New_Value : Integer;
begin
Put ("The value of the index is now");
Put (Item);
New_Line;
New_Value := (Item - 1);
if New_Value > 0 then
calc (New_Value);
end if;
end calc;
begin
Get (Index);
Get (Mindex);
calc (Index);
New_Line;
calc (Mindex);
end Add;

A factorial keeps chaining multiplication with each decreasing value: 5! = 5 * 4 * 3 * 2 * 1 = 120. In order to do the recursion, you'll need to have two cases inside your recursive function: If your value is above 1, then multiply that value with the next smallest number. That's the recursive part where you will call Factorial(N-1) inside of Factorial(N). Otherwise just return 1 (factorial of 0 is 1 mathematically, so both 1! and 0! equal 1).
The way this works in Ada is:
function Factorial(Value : Natural) return Natural is
begin
if Value > 1 then
-- Keep chaining the multiplication with recursion
return Value * Factorial(Value - 1);
else
-- No need to chain as the result is always 1
return 1;
end if;
end Factorial;
You can then call that Factorial function on each of your numbers and add the results.

Related

obtaining a list of prime numbers in Ada

I have made a program for obtaining a list of prime numbers in ADA and using the following online compiler:
https://rextester.com/l/ada_online_compiler
My code is the following:
--GNAT 8.3.0
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO;
procedure prime is
function isPrime(n:in Integer) return Boolean is
begin
for i in 2..n loop
if n mod i=0 then
return False;
end if;
end loop;
return True;
end isPrime;
begin
for i in 1..100 loop
if isPrime(i)=True then
Ada.Text_IO.Put_Line(Integer'Image(i));
end if;
Ada.Text_IO.Put_Line(Integer'Image(i));
end loop;
end prime;
And instead of printing a list of primes it only print 1. I have program the same code in C and no problem at all.
Your for loop in isPrime() checks every value higher than one as "n mod n = 0" which will cause you to return false for every value higher than 1. Change the for loop condition to
for i in 2..(n-1) loop
and work from there
Expanding on Jere's approach, several simple primality tests will simplify the divisibility test in the isPrime loop:
The only even prime, 2, can be handled immediately:
if N = 2 then
return True;
end if;
All remaining even numbers can be eliminated:
if N mod 2 = 0 then
return False;
end if;
This leaves odd numbers in the range 3 .. √N to check:
for i in 3 .. Positive (Sqrt (Float (N))) loop
if N mod i = 0 then
…
end if;
end loop;
It is even better by defining a Prime_Number type containing prime numbers.
subtype Prime_Number is Positive range 2 .. Positive'Last with
Dynamic_Predicate => (for all I in 2 .. (Prime_Number / 2)
=> (Prime_Number mod I) /= 0);
Then, use the code segment below to print out all prime numbers between 2 .. 100 range.
for Index in Positive range 2 .. 100 loop
if Index in Prime_Number then
Put_Line ("Prime number: " & Index'Image);
end if;
end loop;

Print sum of n numbers in plsql

CREATE OR REPLACE FUNCTION printsum(n IN number) IS
res number:=0;
BEGIN
while(n>0)
LOOP
res:=res+n;
n:=n-1;
EXIT WHEN n=0;
END LOOP;
dbms_output.put_line(' result of sum: '||res);
END;
/
I'm trying to print sum of n numbers, but I'm getting the following error:
Warning: Function created with compilation errors.
Two things:
number strictly speaking is not necessarily integral so best to use pls_integer or at least check in the code that the passed in argument is integral
if the question is asking how to return the sum of the first n positive integers, the correct answer is to used the closed form formula: n * (n + 1)/2
Using the formula gives you a constant time answer.
function printsum(n pls_integer) return n is
begin
if(n < 0) then raise value_error; end if; -- or a more meaningful exception
return (n * (n + 1) / 2);
end;
There are few errors in your code.
1) Function must have a Return but your code had missing Return statement at beginning and at end.
2) IN parameter cannot be reassigned inside the code. So you need to copy the IN parameter to a variable to iterate.
Try this:
CREATE OR REPLACE FUNCTION printsum( n IN NUMBER)
RETURN NUMBER
IS
res NUMBER:=0;
v_num NUMBER:=n;
BEGIN
WHILE(v_num>0)
LOOP
res := res + v_num;
v_num := v_num -1;
EXIT WHEN v_num=0;
END LOOP;
dbms_output.put_line(' result of sum: '||res);
RETURN(res);
END;
/
Output:
SQL> select printsum(10) from dual;
PRINTSUM(10)
------------
55
The following code snippet is the solution:
declare
sm number;
tmp number;
n number;
i number;
function sumn(n integer)
return number
is
sm number;
begin
sm:=0;
tmp:=n;
for i in 1..tmp LOOP
sm:=sm+i;
END LOOP;
return sm;
END;
begin
n:=10;
sm:=sumn(n);
dbms_output.put_line('sum is',sm);
end;
/

How to use Assert and loop_invariants

Specification:
package PolyPack with SPARK_Mode is
type Vector is array (Natural range <>) of Integer;
function RuleHorner (X: Integer; A : Vector) return Integer
with
Pre => A'Length > 0 and A'Last < Integer'Last;
end PolyPack ;
I want to write body of PolyPack package with Assert and loop_invariants that the gnatprove program can prove my function RuleHorner correctness.
I write my function Horner but I don;t know how put assertions and loop_invariants in this program to prove its corectness :
with Ada.Integer_Text_IO;
package body PolyPack with SPARK_Mode is
function RuleHorner (X: Integer; A : Vector) return Integer is
Y : Integer := 0;
begin
for I in 0 .. A'Length - 1 loop
Y := (Y*X) + A(A'Last - I);
end loop;
return Y;
end RuleHorner ;
end PolyPack ;
gnatprove :
overflow check might fail (e.g. when X = 2 and Y = -2)
overflow check might fail
overflow check are for line Y := (Y*X) + A(A'Last - I);
Can someone help me how remove overflow check with loop_invariants
The analysis is correct. The element type for type Vector is Integer. When X = 2, Y = -2, and A(A'Last - I) is less than Integer'First + 4 an underflow will occur. How do you think this should be handled in your program? Loop invariants will not work here because you cannot prove that an overflow or underflow cannot occur.
Is there a way you can design your types and/or subtypes used within Vector and for variables X and Y to prevent Y from overflowing or underflowing?
I am also curious why you want to ignore the last value in your Vector. Are you trying to walk through the array in reverse? If so simply use the following for loop syntax:
for I in reverse A'Range loop

recursion using for do loop (pascal)

I'm trying to use the concept of recursion but using for do loop. However my program cannot do it. For example if I want the output for 4! the answer should be 24 but my output is 12. Can somebody please help me?
program pastYear;
var
n,i:integer;
function calculateFactorial ( A:integer):real;
begin
if A=0 then
calculateFactorial := 1.0
else
for i:= A downto 1 do
begin
j:= A-1;
calculateFactorial:= A*j;
end;
end;
begin
writeln( ' Please enter a number ');
readln ( n);
writeln ( calculateFactorial(n):2:2);
readln;
end.
There are several problems in your code.
First of all it doesn't compile because you are accessing the undefined variable j.
Calculating the factorial using a loop is the iterative way of doing it. You are looking for the recursive way.
What is a recursion? A recursive function calls itself. So in your case calculateFactorial needs a call to itself.
How is the factorial function declared?
In words:
The factorial of n is declared as
1 when n equals 0
the factorial of n-1 multiplied with n when n is greater than 0
So you see the definition of the factorial function is already recursive since it's referring to itself when n is greater than 0.
This can be adopted to Pascal code:
function Factorial(n: integer): integer;
begin
if n = 0 then
Result := 1
else if n > 0 then
Result := Factorial(n - 1) * n;
end;
No we can do a few optimizations:
The factorial function doesn't work with negative numbers. So we change the datatype from integer (which can represent negative numbers) to longword (which can represent only positive numbers).
The largest value that a longword can store is 4294967295 which is twice as big as a longint can store.
Now as we don't need to care about negative numbers we can reduce one if statement.
The result looks like this:
function Factorial(n: longword): longword;
begin
if n = 0 then
Result := 1
else
Result := Factorial(n - 1) * n;
end;

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