recursion using for do loop (pascal) - recursion

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;

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;

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

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.

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

Does PL/SQL have an intrinsic function to return a value of n when x is less than y?

I was thinking that there had to be a function that would act as a threshold, so that I didn't need to add a bunch of if-then-elses to my code.
I wrote a UDF to do what I need but if anyone knows of a PL/SQL function or code where I can say something like;
X := APPLY_THRESHOLD(LASTNAME_SCORE,PATIENT_LASTNAME_THRESHOLD,0);
Where X would either be the lastname_score, or 0, depending on whether it is greater than or equal to patient_last_name_threshold. The function I wrote is;
FUNCTION APPLY_THRESHOLD(IN_VALUE NUMBER,IN_THRESHOLD NUMBER, IN_FLOOR NUMBER) RETURN NUMBER DETERMINISTIC AS
BEGIN
IF IN_VALUE < IN_THRESHOLD
THEN
RETURN IN_FLOOR;
ELSE
RETURN IN_VALUE;
END IF;
END APPLY_THRESHOLD;
But if there is something built in to the language it would probably be faster.
Try this
select decode(sign(IN_VALUE - IN_THRESHOLD), -1, IN_FLOOR, IN_VALUE)
into x from dual;
sign( number ) Function
if number < 0 it will return -1, if number = 0 then 0 else 1

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