Factorial of a number in pl/sql (Not showing the correct output) - plsql

I have written down a code in pl/sql but output is not showing
having trouble with this code.
declare
num number(20):= 0;
val number(10):= 5;
temp number(10):= 0;
function factorial (n1 in number)
return number
is
fact number(10):= 1;
begin
temp:= n1;
loop
if fact <=0 then
exit;
else
fact := fact *temp;
temp:=temp-1;
end if;
end loop;
return fact;
end;
begin
num:= factorial(val);
dbms_output.put_line('Factorial of ' ||val||' is '||num);
end;
Output:- Factorial of 5 is 0

The line:
if fact <=0 then
should be:
if temp <=0 then
You don't really need the 'else' part, because the 'if' exits the loop anyway; so you could do:
loop
if temp <=0 then
exit;
end if;
fact := fact *temp;
temp:=temp-1;
end loop;
Or avoid the explicit check by using a while loop:
while temp > 0 loop
fact := fact *temp;
temp:=temp-1;
end loop;
... etc.
db<>fiddle

You are checking fact <= 0 rather than checking temp <= 0 and you should also declare the temp variable locally to the function:
declare
val number(10):= 5;
function factorial (n1 in number)
return number
is
fact number(10) := 1;
temp number(10) := n1;
begin
loop
if temp <=0 then
exit;
else
fact := fact *temp;
temp:=temp-1;
end if;
end loop;
return fact;
end;
begin
dbms_output.put_line('Factorial of ' ||val||' is '|| factorial(val) );
end;
/
Or, more simply:
declare
val number(10):= 5;
function factorial (n1 in number)
return number
is
fact number(10) := 1;
BEGIN
FOR temp IN 2 .. n1
LOOP
fact := fact *temp;
END LOOP;
RETURN fact;
END;
begin
dbms_output.put_line('Factorial of ' ||val||' is '|| factorial(val) );
end;
/
db<>fiddle here

Related

First two counters are never increased in dice rolling application

I am writing a program that rolls two dice and uses an array of counters to show how many times each total is shown. My code compiles fine and does run but for some reason the first two counters are never increased, and seems to print in numeric ascending order - which to me sounds like a problem with my random number function. But I cannot quite see where I have gone wrong. It also never iterates the correct amount of times, about half in fact. Here is my code.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Numerics.Discrete_Random;
-- procedure main - begins program execution
procedure main is
dice1, dice2, diceTotal : Integer;
type Count_Array is array(1 .. 11) of Integer;
intArray : Count_Array;
-- function returnRand - produces a random number and returns it
function returnRand return Integer is
type magicNumber is new Integer range 2 .. 12;
package Rand_Number is new Ada.Numerics.Discrete_Random(magicNumber);
use Rand_Number;
theNumber : magicNumber;
g : Generator;
begin
Reset(g);
theNumber := Random(g);
return Integer(theNumber);
end returnRand;
-- procedure rollDice - rolls two dice 36000 times and tallys the totals
procedure rollDice(dice1 : out Integer; dice2 : out Integer;
diceTotal : out Integer; intArray : in out Count_Array) is
begin
for I in 1 .. 36000 loop
dice1 := returnRand;
dice2 := returnRand;
diceTotal := dice1 + dice2;
if diceTotal = 2 then
intArray(1) := intArray(1) + 1;
elsif diceTotal = 3 then
intArray(2) := intArray(2) + 1;
elsif diceTotal = 4 then
intArray(3) := intArray(3) + 1;
elsif diceTotal = 5 then
intArray(4) := intArray(4) + 1;
elsif diceTotal = 6 then
intArray(5) := intArray(5) + 1;
elsif diceTotal = 7 then
intArray(6) := intArray(6) + 1;
elsif diceTotal = 8 then
intArray(7) := intArray(7) + 1;
elsif diceTotal = 9 then
intArray(8) := intArray(8) + 1;
elsif diceTotal = 10 then
intArray(9) := intArray(9) + 1;
elsif diceTotal = 11 then
intArray(10) := intArray(10) + 1;
elsif diceTotal = 12 then
intArray(11) := intArray(11) + 1;
end if;
end loop;
end rollDice;
-- procedure printResults - prints out the totals of each dice throw
procedure printResults(intArray : in Count_Array) is
begin
Put_Line("Dice Total Tally");
for I in Count_Array'Range loop
-- Set_Col(2);
-- Put(integer'image(I));
-- Set_Col(23);
Put(integer'image(intArray(I)));
New_Line;
end loop;
end printResults;
begin
New_Line;
intArray := (0,0,0,0,0,0,0,0,0,0,0);
rollDice(dice1, dice2, diceTotal, intArray);
printResults(intArray);
New_Line;
end main;
You roll two D11s (range 2..12), not D6s, so when you add them together, you get a range of 4..24 instead of the expected 2..12.
If you used the type system to model the problem, this would have been detected:
type Count_Array is array(2 .. 12) of Integer;
and then your if..elsif construct could be just:
intArray(diceTotal) := intArray(diceTotal) + 1;
Change your magicNumber to a 1..6 range to roll a D6 instead.
Also, there's no need to reset the Generator every time you roll a die. Once is sufficient.
Edit:
You could also go much further with the type system, and do something like this:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Discrete_Random;
procedure Main is
Number_Of_Dice : constant := 2;
type Die_Range is new Positive range 1 .. 6;
subtype Sums_Range is Die_Range'Base
range Number_Of_Dice*Die_Range'First..Number_Of_Dice*Die_Range'Last;
type Count_Array is array(Sums_Range) of Natural;
package Random_Die is new Ada.Numerics.Discrete_Random(Die_Range);
Die : Random_Die.Generator;
function Roll(Die : Random_Die.Generator) return Die_Range
renames Random_Die.Random;
procedure Roll_Dice(Sums : in out Count_Array) is
Dice_Total : Sums_Range'Base;
begin
for I in 1 .. 36_000 loop
Dice_Total := Roll(Die);
for I in 1..Number_Of_Dice-1 loop
Dice_Total := Dice_Total + Roll(Die);
end loop;
Sums(Dice_Total) := Sums(Dice_Total) + 1;
end loop;
end Roll_Dice;
procedure Print_Results(Sums : in Count_Array) is
begin
Put_Line("Dice Total Tally");
for I in Sums'Range loop
Put(Sums(I)'Image);
New_Line;
end loop;
end Print_Results;
Sums : Count_Array;
begin
Random_Die.Reset(Die);
New_Line;
Sums := (others => 0);
Roll_Dice(Sums);
Print_Results(Sums);
New_Line;
end Main;
Notice how easy this code will be to maintain when the requirements change, for example the number of dice cast per roll, or the type of dice (D4, D6, D8, D12, etc)

Error on running a pl/sql program to find sum of first 10 prime numbers

DECLARE
COUNT NUMBER;
prime NUMBER;
SUM NUMBER;
i NUMBER;
j NUMBER;
BEGIN
SUM := 2;
COUNT := 0;
prime := 1;
i := 3;
WHILE COUNT < 10
LOOP
j := i / 2;
FOR k IN 2 .. j
LOOP
IF i MOD j = 0
THEN
prime := 0;
END IF;
IF prime = 1
THEN
SUM := SUM + i;
COUNT := COUNT + 1;
END IF;
END LOOP;
i := i + 1;
END LOOP;
DBMS_OUTPUT.put_line (SUM);
END;
/
I'm trying to calculate the sum first 10 prime numbers. I wrote the above code but when I try to execute it, it throws an error:
ORA-06550: line 29, column 12: PLS-00103: Encountered the symbol
"+" when expecting one of the following: ( This error corresponds
to the line where I'm incrementing the value of sum.
COUNT and SUM are reserved keywords and must not be choosen as variable-names.
Add a prefix "v":
DECLARE
vCOUNT NUMBER;
prime NUMBER;
vSUM NUMBER;
i NUMBER;
j NUMBER;
BEGIN
vSUM := 2;
vCOUNT := 0;
prime := 1;
i := 3;
WHILE vCOUNT < 10
LOOP
j := i / 2;
FOR k IN 2 .. j
LOOP
IF i MOD j = 0
THEN
prime := 0;
END IF;
IF prime = 1
THEN
vSUM := vSUM + i;
vCOUNT := vCOUNT + 1;
END IF;
END LOOP;
i := i + 1;
END LOOP;
DBMS_OUTPUT.put_line (vSUM);
END;
/
Here a good article about naming-conventions in plsql:
https://www.guru99.com/pl-sql-identifiers.html
The error-message "expecting '('" shows that your db wants something like "SUM(someValue)".
An example would be something like this:
SELECT SUM(col1) FROM mytable

Ada Constraint_error invalid enumeration value

Im so close to finishing this lab I can taste it. I realize my Ada code is very novice as I just began working with it this semester. The error seems to persist at location 19 when I try to use 'put' on mainStk at said location. Im wondering why i cannot get access to mainStk(19) as this is what seems to be the issue.
This is the error code
raised CONSTRAINT_ERROR : mainStk.Input_IO.Put: invalid enumeration value [2018-03-07 18:46:16] process exited with status 1, elapsed time: 05.40s
This is the .adb its appearing in.
with Ada.Text_IO;
use Ada.Text_IO;
package body ProcsAndFuncs is
Base: array(1..N+1) of integer; --self descriptive arrays to maintain stacks
Top: array(1..N) of integer;
Old_Top: array(1..N) of integer;
mainStk: array(LowerB..UpperB) of Input;
package Int_IO is new Ada.Text_IO.Integer_IO(Integer);
use Int_IO; --IO routine for my integers
package Input_IO is new Ada.TExt_IO.Enumeration_IO(Input);
use Input_IO; --IO routine for Data
procedure ReA_Move(Snum: integer; Data: Input) is --procedure follows ReA1-ReA6 in notes (pg 22-23)
New_Base : array (1..N+1) of integer; --following variables from notes being declared and initalized
Growth : array (1..N) of Integer;
Alpha, Beta, Sig, Tau: float:= 0.00;
Growth_All: float:= 0.87; --divide 87% avail memory based on growth
Equal_All: float:= 0.13; --divide 13% avail memory equally
TotalInc, Avail, Delt: integer:= 0;
min_space: Integer:= 1;
J: integer;
begin
Avail:= M-L0; --beginning ReA1 from notes (p.22)
J:= N;
new_line;
Put("Contents of Old Top(J), Top(J), and Base(J) before repacking as requested:");
new_line;
for i in 1..N loop
put("old top("); put(i,1); put(")= ");
put(old_top(i),1);
put(".. Top("); put(i,1); put(")= ");
put(top(i),1);
put(".. Base("); put(i,1); put(")= ");
put(base(i),1);
new_line;
end loop;
while J>0 loop --ReA1 from notes
Avail:= Avail-(Top(j)-Base(j));
if top(j) > old_top(j) then
Growth(j):= Top(j)-old_top(j);
TotalInc:= TotalInc+Growth(j);
else
growth(j) := 0;
end if;
J:= J-1;
end loop;
if Avail < (Min_Space - 1) then --ReA2 from notes
Put("Insufficient memory for re-packing to occur, terminating.");
raise Program_Error;
end if;
growth_All:= 1.0-Equal_All; --ReA3 from notes
Alpha:= (Equal_All * Float(Avail)) / float(N);
beta:= (Growth_All * Float(Avail)) / float(totalinc); --ReA4 from notes
new_base(1):= base(1); --ReA5 from notes
Sig:= 0.0;
for j in 2..N loop
tau:= sig+alpha+(float(Growth(j-1)) * Beta);
new_base(j):=new_base(j-1)+(top(j-1)-base(j-1))+Integer(float'Floor(tau))-Integer(float'Floor(sig));
sig:= tau;
end loop;
Top(Snum):= Top(Snum)-1; --ReA6
for j in 2..N loop --MoA1 from notes
if new_base(j) < base(j) then
delt:= base(j)-new_base(j);
for l in integer range(base(j) + 2)..(top(j)) loop
mainStk(l-delt):= mainStk(l);
end loop;
base(j):= new_base(j);
top(j):= top(j)-delt;
end if;
end loop;
for j in 2 .. N loop --MoA2 from notes
if new_base(j) > Base(j) then
delt:= new_base(j)-base(j);
for l in (Top(j)-1)..(base(j)+1) loop
mainStk(l+delt):= mainStk(l);
end loop;
base(j):= new_base(j);
top(j):= top(j)+delt;
end if;
end loop;
top(Snum):= Top(Snum)+1; --jumping back to ReA6
mainStk(Top(Snum)):= data;
new_line;
Put("Bases and tops after repack as requested:"); new_line;
for J in 1..N loop --prepare for potential overflow
Put("Base("); put(j,1); put(")= ");
put(base(j),1);
Put(", Top("); put(j,1); put(")= ");
put(top(j),1);
new_line;
old_top(J):= Top(J);
end loop;
new_line;
put("continuing tansactions..");
end ReA_move;
procedure output is --declaration for procedure 'output' (procedures return no value)
begin
new_line;
new_line;
for i in 1..N loop --outputs conents of each transaction as requested
put("Stack #:");
put(i); new_line;
for j in base(i)+1..top(i) loop
if j < base(i+1) then
put(" Loc[" & integer'image(j) & " ]: ");
put(mainStk(j)); --put problem?
new_line;
end if;
end loop;
end loop;
end output;
procedure Push(Stack:Integer; Data:Input) is --procedure since no value returned
begin
top(Stack):= top(Stack)+1; --Insertion into stack from notes
if Top(Stack) > Base(Stack+1) then
new_line;
put("Overflow occured, calling Reallocate"); new_line; --report overflow
ReA_move(stack, data); --determine if additional space can be made
else
mainStk(Top(Stack)):= data; --insert data into stack
output;
end if;
end Push;
function Pop(Stack: Integer) return Input is --function used to return value
data: Input;
begin
if top(stack) = base(stack) then --implement Pop as in deletion from stack pg 21
put("Reporting underflow..");
return empty;
else
data:= mainStk(top(stack));
top(stack):= top(stack)-1;
return (mainStk(top(Stack)));
end if;
end Pop;
begin
Put("Initial Tops and Bases: ");
for j in 1..N loop --loop equally initializes Tops & Bases prior to transactions
base(j):= Integer(Float'Floor(((Float(j) - 1.0) / Float(N) * Float(M - L0)) + Float(L0)));
Top(j):= Base(j);
old_top(j):= top(j);
new_line;
Put("Base(");
put(j,1);
put(") = ");
put("Top(");
put(j,1);
put(")= ");
put(top(j),1);
end loop;
new_line;
put("Base(5)= 27");
end;
This is my generic which may or may not be needed.
generic
N:integer;
M:integer;
L0:integer;
LowerB:integer;
UpperB:integer;
package ProcsAndFuncs is
type Input is (Zhou, Wei, Burris, Shashidhar, Deering, An, Lester, Yang, Smith, Arcos,
Rabieh, Song, Cho, Varol, Karabiyik, Cooper, McGuire, Najar, Hope, Pray, NoHope, empty);
procedure ReA_move(Snum : in integer; Data : Input);
procedure push(stack : integer; Data : Input);
function pop(stack : Integer) return Input;
procedure output;
end;

Ada - Prime factorization of numbers

My first homework assignment in Ada is to create a program that states whether a number is composite or prime, display its factors, and then indicate its prime factorization. So for example the number 12 would be composite, 1,2,3,4,6,12. Prime factorization 2 * 2 * 3.
I'm mostly done, my code indicates if it's a composite number, and all the factors, just not sure how to code the actual prime factorization part where it would display the 2 * 2 * 3. I have done the rest, but could use some insight as to what code would be the best to proceed.
WITH Ada.Text_IO, Ada.Integer_Text_IO;
USE Ada.Text_IO, Ada.Integer_Text_IO;
PROCEDURE program_one IS
input: File_Type := Ada.Text_IO.Standard_Input;
Value: Integer;
AbsValue: Natural;
factorCount: Integer := 0;
begin
--Open(input, In_File);
WHILE NOT End_Of_File(input) LOOP
IF End_Of_Line(input) THEN
Skip_Line(input);
ELSE
Get(Input, Value);
Put(Value, Width => 1);
absValue := abs Value;
Put(": Positive Factors are: ");
FOR I IN Integer RANGE 1 .. absValue LOOP
IF absValue mod I = 0 THEN
Put(I, Width => 1);
factorCount := factorCount + 1;
IF I /= absValue THEN
Put(", ");
END IF;
END IF;
END LOOP;
New_Line;
IF FactorCount = 2 THEN
Put(Value, 6);
Put(" is prime.");
END IF;
IF FactorCount = 1 OR FactorCount = 0 THEN
Put(Value, 6);
Put(" is neither prime nor composite");
END IF;
IF FactorCount > 2 THEN
Put(Value, 6);
Put(" is composite");
END IF;
factorCount := 0;
New_Line;
END IF;
END LOOP;
Close(Input);
end program_one;

Recursive permutation

So I'm trying to permute all possible n digit long numbers out of x long array/set of elements. I've come up with a code that does that, however the digits are the same, how do I prevent that from happening. Here's my come(Pascal):
program Noname10;
var stop : boolean;
A : array[1..100] of integer;
function check( n : integer ) : boolean;
begin
if n = 343 // sets the limit when to stop.
then check := true
else check := false;
end;
procedure permute(p,result : integer);
var i : integer;
begin
if not stop
then if p = 0 then
begin
WriteLn(result);
if check(result)
then stop := true
end
else for i := 1 to 9 do
begin
permute(p - 1, 10*result+i);
end;
end;
begin
stop := false;
permute(3,0);
readln;
end.
Here is the code in Prolog
permutate(As,[B|Cs]) :- select(B, As, Bs), permutate(Bs, Cs).
select(A, [A|As], As).
select(A, [B|Bs], [B|Cs]) :- select(A, Bs, Cs).
?- permutate([a,b,c], P).
Pascal is much harder.
Here is an usefull algorithm, you might want to use. But it is not tested, so you have to debug it yourself. So you have to know how the algorithm works.
The Bell Permutation algorithm: http://programminggeeks.com/bell-algorithm-for-permutation/
procedure permutate(var numbers: array [1..100] of integer; size: integer;
var pos, dir: integer)
begin
if pos >= size then
begin
dir = -1 * dir;
swap(numbers, 1, 2);
end
else if pos < 1 then
begin
dir = -1 * dir;
swap(numbers, size-1, size);
end
else
begin
swap(numbers, pos, pos+1);
end;
pos = pos + dir;
end;
begin
var a, b: integer;
a = 1; b = 1;
while true do
begin
permutate(A, 5, a, b);
printArray(A, 5);
end;
end.

Resources