Why it is oveflow in contador in ada? - ada

I dont know why the prove is error at the overflow in the variable contador. I need help.
contador: Integer;
J: Integer;
function noPrimos (lista : My_Array) return Boolean
with
Global => contador,
--Depends => ...,
Pre => True and contador < Integer'Last,
Post => (noPrimos'Result = True or noPrimos'Result = False);
FILE ADB
function noPrimos (lista : My_Array) return Boolean is
contador: Integer;
begin
for I in lista'Range loop
contador:= 0;
if lista(I) /= 1 then
for J in 1.. lista(I) loop
if lista(I) rem J = 0 then
contador := contador + 1;
end if;
end loop;
if contador <= 2 then
return false;
end if;
else
return true;
end if;
pragma Loop_Variant(Increases => I);
end loop;
return true;
end noPrimos;
The problem is the overflow the result:
Phase 1 of 2: generation of Global contracts ...
Phase 2 of 2: flow analysis and proof ...
15:40: medium: overflow check might fail (e.g. when contador = 2147483647)
47:40: medium: overflow check might fail (e.g. when contador = 0)

First of all, I assume that the function noPrimos will return True only if the list lista does not contain any primes. That being said, I'm a little bit puzzled by some aspects of the code snippet:
The type definition of My_Array is missing.
The role of the global instance of contador (english: counter) is not clear from the given code snippet. By writing Global=> contador, you state that the global variable contador will be read by the function noPrimos (see also here), but that doesn't happen because the local instance of contador shadows the global instance of contador.
The reason for the variable J being defined globally is not clear, you can omit it.
The precondition True (on the left side of the Boolean operator and) is trivial and can be omitted.
The postcondition states that the result of noPrimos can either be True or False. This is trivial as noPrimos returns a boolean and can therefore be omitted. The postcondition should state the function's expected result given its inputs.
The loop variant pragma Loop_Variant(Increases => I); is trivial as the variable I will increase by the definition of the for-loop. Hence the loop variant can be omitted.
Below is an example of a function No_Primes that searches the given list L for primes and returns True if none are found. It proves in GNAT CE 2019:
primes.ads (spec)
package Primes with SPARK_Mode is
type List is
array (Natural range <>) of Positive;
--
-- Returns True if N is a prime number (or False otherwise).
--
function Is_Prime (N : Positive) return Boolean
with
Global => null,
Post => Is_Prime'Result =
(if N = 1 then False
else (for all I in 2 .. N - 1 => N rem I /= 0));
--
-- Returns True if list L does not contain any prime numbers (or False otherwise).
--
function No_Primes (L : List) return Boolean
with
Global => null,
Post => No_Primes'Result =
(for all I in L'Range => Is_Prime (L (I)) = False);
end Primes;
primes.adb (body)
package body Primes with SPARK_Mode is
--------------
-- Is_Prime --
--------------
function Is_Prime (N : Positive) return Boolean is
begin
if N = 1 then
return False;
else
for I in 2 .. N - 1 loop
if N rem I = 0 then
return False;
end if;
pragma Loop_Invariant
(for all J in 2 .. I => N rem J /= 0);
end loop;
end if;
return True;
end Is_Prime;
---------------
-- No_Primes --
---------------
function No_Primes (L : List) return Boolean is
begin
for I in L'Range loop
if Is_Prime (L (I)) then
return False;
end if;
pragma Loop_Invariant
(for all J in L'First .. I => Is_Prime (L (J)) = False);
end loop;
return True;
end No_Primes;
end Primes;
A small test program (main.adb)
with Ada.Text_IO; use Ada.Text_IO;
with Primes; use Primes;
procedure Main is
-- Some test vectors.
L1 : List := (1 => 1); -- Expect TRUE : 1 is not a prime.
L2 : List := (1, 2, 3, 5, 7); -- Expect FALSE : All are prime except 1.
L3 : List := (2, 3, 5, 7); -- Expect FALSE : All are prime.
L4 : List := (1, 4, 6, 8, 9); -- Expect TRUE : None are prime.
L5 : List := (4, 6, 8, 9); -- Expect TRUE : None are prime.
L6 : List := (3, 4, 5); -- Expect FALSE : 3 and 5 are prime.
begin
Put_Line ("No_Primes (L1) = " & Boolean'Image (No_Primes (L1)));
Put_Line ("No_Primes (L2) = " & Boolean'Image (No_Primes (L2)));
Put_Line ("No_Primes (L3) = " & Boolean'Image (No_Primes (L3)));
Put_Line ("No_Primes (L4) = " & Boolean'Image (No_Primes (L4)));
Put_Line ("No_Primes (L5) = " & Boolean'Image (No_Primes (L5)));
Put_Line ("No_Primes (L6) = " & Boolean'Image (No_Primes (L6)));
end Main;
yields
No_Primes (L1) = TRUE
No_Primes (L2) = FALSE
No_Primes (L3) = FALSE
No_Primes (L4) = TRUE
No_Primes (L5) = TRUE
No_Primes (L6) = FALSE

Related

"Taking on a Challenge in SPARK Ada" - Sum ghost function in post-condition having unintended behavior

I am writing a piece of software in SPARK Ada which requires the post-condition to verify that the function return value is equal to the summed values of an array. Upon proving the file where the function resides, I keep getting an error which doesn't quite add up, no pun intended (I will post screenshots of the code so as to allow a better look). The only acceptable values allowed in the array of size 10 are 0s or 1s.
In the example below (and opposed to the other answer), I separated the ghost function that computes the partial sum into a generic ghost package SPARK_Fold. From this package I use the ghost function Sum_Acc to proof the summation loop in Calc_ST. The package Example can be proven using GNAT CE 2020 with prove level set to 1.
Credits for the underlying method: AdaCore blog post.
example.ads
with SPARK_Fold;
package Example with SPARK_Mode is
subtype EEG_Reading_Index is Integer range 0 .. Integer'Last - 1;
subtype EEG_Reading is Integer range 0 .. 1;
type EEG_Readings is array (EEG_Reading_Index range <>) of EEG_Reading;
package Sum_EEG_Readings is
new SPARK_Fold.Sum
(Index_Type => EEG_Reading_Index,
Element_In => EEG_Reading,
List_Type => EEG_Readings,
Element_Out => Natural);
function Calc_ST (EEG : EEG_Readings) return Natural with
Pre => EEG'Length > 0,
Post => Calc_ST'Result = Sum_EEG_Readings.Sum_Acc (EEG) (EEG'Last);
end Example;
example.adb (just computing the sum as usual here).
package body Example with SPARK_Mode is
-------------
-- Calc_ST --
-------------
function Calc_ST (EEG : EEG_Readings) return Natural is
Result : Natural := EEG (EEG'First);
begin
for I in EEG'First + 1 .. EEG'Last loop
pragma Loop_Invariant
(Result = Sum_EEG_Readings.Sum_Acc (EEG) (I - 1));
Result := Result + EEG (I);
end loop;
return Result;
end Calc_ST;
end Example;
spark_fold.ads (a generic helper package)
package SPARK_Fold with Ghost is
-- Based on the blog post:
-- https://blog.adacore.com/taking-on-a-challenge-in-spark
---------
-- Sum --
---------
generic
type Index_Type is range <>;
type Element_In is range <>;
type List_Type is array (Index_Type range <>) of Element_In;
type Element_Out is range <>;
package Sum with Ghost is
type Partial_Sums is array (Index_Type range <>) of Element_Out;
function Sum_Acc (L : List_Type) return Partial_Sums with
Ghost,
Pre => (L'Length > 0),
Post => (Sum_Acc'Result'Length = L'Length)
and then (Sum_Acc'Result'First = L'First)
and then (for all I in L'First .. L'Last =>
abs (Sum_Acc'Result (I)) <= Element_Out (I - L'First + 1) * Element_Out (Element_In'Last))
and then (Sum_Acc'Result (L'First) = Element_Out (L (L'First)))
and then (for all I in L'First + 1 .. L'Last =>
Sum_Acc'Result (I) = Sum_Acc'Result (I - 1) + Element_Out (L (I)));
end Sum;
-----------
-- Count --
-----------
generic
type Index_Type is range <>;
type Element is range <>;
type List_Type is array (Index_Type range <>) of Element;
with function Choose (X : Element) return Boolean;
-- Count the number of elements for which Choose returns True.
package Count with Ghost is
type Partial_Counts is array (Index_Type range <>) of Natural;
function Count_Acc (L : List_Type) return Partial_Counts with
Ghost,
Pre => (L'Length > 0),
Post => (Count_Acc'Result'Length = L'Length)
and then (Count_Acc'Result'First = L'First)
and then (for all I in L'First .. L'Last =>
Count_Acc'Result (I) <= Natural (I) - Natural (L'First) + 1)
and then (Count_Acc'Result (L'First) = (if Choose (L (L'First)) then 1 else 0))
and then (for all I in L'First + 1 .. L'Last =>
Count_Acc'Result (I) = Count_Acc'Result (I - 1) + (if Choose (L (I)) then 1 else 0));
end Count;
end SPARK_Fold;
spark_fold.adb
package body SPARK_Fold is
---------
-- Sum --
---------
package body Sum is
function Sum_Acc (L : List_Type) return Partial_Sums is
Result : Partial_Sums (L'Range) := (others => 0);
begin
Result (L'First) := Element_Out (L (L'First));
for Index in L'First + 1 .. L'Last loop
-- Head equal.
pragma Loop_Invariant
(Result (L'First) = Element_Out (L (L'First)));
-- Tail equal.
pragma Loop_Invariant
(for all I in L'First + 1 .. Index - 1 =>
Result (I) = Result (I - 1) + Element_Out (L (I)));
-- Result within bounds.
pragma Loop_Invariant
(for all I in L'First .. Index - 1 =>
abs (Result (I)) <= Element_Out (I - L'First + 1) * Element_Out (Element_In'Last));
Result (Index) := Result (Index - 1) + Element_Out (L (Index));
end loop;
return Result;
end Sum_Acc;
end Sum;
-----------
-- Count --
-----------
package body Count is
function Count_Acc (L : List_Type) return Partial_Counts is
Result : Partial_Counts (L'Range) := (others => 0);
begin
if Choose (L (L'First)) then
Result (L'First) := 1;
else
Result (L'First) := 0;
end if;
for Index in L'First + 1 .. L'Last loop
-- Head equal.
pragma Loop_Invariant
(Result (L'First) = (if Choose (L (L'First)) then 1 else 0));
-- Tail equal.
pragma Loop_Invariant
(for all I in L'First + 1 .. Index - 1 =>
Result (I) = Result (I - 1) + (if Choose (L (I)) then 1 else 0));
-- Bounds.
pragma Loop_Invariant
(for all I in L'First .. Index - 1 =>
Result (I) <= Natural (I) - Natural (L'First) + 1);
if Choose (L (Index)) then
Result (Index) := Result (Index - 1) + 1;
else
Result (Index) := Result (Index - 1) + 0;
end if;
end loop;
return Result;
end Count_Acc;
end Count;
end SPARK_Fold;
This is the fix:
function CalcST(eegR: in eegReadings) return Natural is
supT: Integer := eegR(eegR'First);
begin
-- Sums the number of ones in the array
for Index in eegR'First + 1 .. eegR'Last loop
pragma Loop_Invariant --
(supT = sumEEGR (eegR) (Index - 1));
pragma Loop_Invariant -- additional loop invariant
(supT <= Index - 1);
if eegR(Index) = 1
then supT := supT + eegR(Index);
end if;
end loop;
return supT;
end CalcST;

Heterogeneous tuple in Ada

Is it possible in ada to create a heterogeneous tuple on the stack without the new operator and access types? I need to make N 2-d arrays depending on a known number in compile time. To be more precise, a certain number of tensors depends on the number of layers in the neural network. I made it like this:
subtype Layer_Value_Type is Float range 0.0 .. 1.0;
package My_Activate is new Activate (Value_Type => Layer_Value_Type);
package My_Logsig is new My_Activate.Logsig;
package My_Layer is new Layer (Value_T => Layer_Value_Type);
package My_Net is new Net (Value_Type => My_Layer.Value_Type,
Layer_Package => My_Layer);
use My_Layer;
Layer1 : My_Layer.Layer (5, null);
Layer2 : My_Layer.Layer (10, My_Logsig.Func'Access);
Layer3 : My_Layer.Layer (3, My_Logsig.Func'Access);
Layers_Array : My_Net.Layers_Array := (Layer1, Layer2, Layer3);
Net : My_Net.Net (Layers_Array'Length);
begin
declare
begin
Net.Make (Layers_Array);
Net.FeedForward(Input => (0.3, 0.4, 0.5, 0.6, 0.7));
end;
generic
type Value_T is digits <>;
package Layer with SPARK_Mode is
subtype Value_Type is Value_T;
type Activate_Type is access function (Item : in Float) return Value_Type;
type Layer (Num : Natural := 0; F : Activate_Type := null) is private;
procedure Make (This : out Layer; Num : in Natural; F : in Activate_Type := null);
private
type Layer (Num : Natural := 0; F : Activate_Type := null) is
record
Length : Natural := Num;
Func : Activate_Type := F;
FuncDeriv : Activate_Type;
end record;
end Layer;
generic
type Value_Type is digits <>;
with package Layer_Package is new Layer(Value_T => Value_Type);
package Net is
type Layers_Array is array (Positive range <>) of Layer_Package.Layer;
type Net (Layers_Num : Positive) is tagged limited private;
subtype Input_Array is Ada.Numerics.Real_Arrays.Real_Vector;
procedure Make (This :in out Net; Layers : in Layers_Array);
function Is_Input_Valid (This : in out Net; Vector : in Input_Array) return Boolean;
procedure FeedForward (This : in out Net; Input : in Input_Array)
with Pre => This.Is_Input_Valid (Vector => Input);
private
--types declaration of values
subtype Value_Arr is Ada.Numerics.Real_Arrays.Real_Vector;
type Values_Arr_Ref is access all Value_Arr;
--types declaration of biases
subtype Bias_Arr is Value_Arr;
type Bias_Arr_Ref is access all Bias_Arr;
--types declaration of waights
subtype Layer_Waights is Ada.Numerics.Real_Arrays.Real_Matrix;
type Layer_Waights_Ref is access all Layer_Waights;
--types declaration of tensors
type Values_Tensor is array (Positive range <>) of Values_Arr_Ref;
type Waights_Tensor is array (Positive range <>) of Layer_Waights_Ref;
--types declaration of activate function array
type Activate_Arr is array (Positive range <>) of Layer_Package.Activate_Type;
type Net (Layers_Num : Positive) is tagged limited
record
Values : Values_Tensor (1 .. Layers_Num);
Waights : Waights_Tensor (2 .. Layers_Num);
Activates : Activate_Arr (2 .. Layers_Num);
end record;
end Net;
procedure Make (This : in out Net; Layers : in Layers_Array) is
type Waight_Tensor_Arr is array (Positive range <>, Positive range <>) of Value_Type;
--task for random number generator
task type Tensor_Randomizer is
entry Init (Item : in out Layer_Waights);
end Tensor_Randomizer;
task body Tensor_Randomizer is
My_Generator : Ada.Numerics.Float_Random.Generator;
function Get return Value_Type with
Post => (Get'Result >= Value_Type'First + 0.2) and
(Get'Result <= Value_Type'Last - 0.2)
is
use Ada.Numerics.Float_Random;
Ratio_For_Large : constant := 0.7;
type Sign_Type is new Boolean with Default_Value => False;
type Constraint_Type is new Boolean with Default_Value => False;
begin
return Result : Value_Type do
declare
Tmp : Value_Type := 0.0;
Is_Negative : Sign_Type;
Large : constant := 0.8;
Small : constant := 0.2;
Is_Over_Constraints : Constraint_Type;
begin
Tmp := Value_Type (Random (Gen => My_Generator));
Is_Negative := (if Tmp >= 0.0 then False else True);
Is_Over_Constraints := (if abs (Tmp) >= Large or abs (Tmp) <= Small then
True else False);
case Is_Over_Constraints is
when False =>
Result := Tmp;
when True =>
Result := (case Is_Negative is
when False => (if abs (Tmp) >= Large then
Tmp * Ratio_For_Large else 0.5 - Tmp),
when True => 0.0 - (abs (Tmp) * (if abs (Tmp) >= Large then
Ratio_For_Large else -0.5 + Tmp)));
end case;
end;
end return;
end Get;
begin
Ada.Numerics.Float_Random.Reset (Gen => My_Generator);
accept Init (Item : in out Layer_Waights) do
begin
Item := (others => (others => Float(Get)));
end;
end Init;
end Tensor_Randomizer;
type Task_Array_Base_Type is array (This.Waights'Range) of Tensor_Randomizer;
subtype Task_Array_Type is Task_Array_Base_Type with
Dynamic_Predicate => Task_Array_Type'Length <= 8;
Task_Array : Task_Array_Type;
--this procedure initializing values tensor to value
procedure Init_Values_Tensor with
Post => (for all I of This.Values (1).all => I = 0.0)
is
Idx : Positive := This.Values'First;
begin
for I of Layers loop
declare
Local_Values_Arr : aliased Value_Arr (1 .. I.Num) := (others => 0.0);
begin
This.Values (Idx) := new Value_Arr (1 .. I.Num);
This.Values (Idx).all := Local_Values_Arr;
Idx := Idx + 1;
end;
end loop;
end Init_Values_Tensor;
--this procedure initializing waights tensor to random value
procedure Init_Waight_Tensor is
Idx : Positive := This.Values'First;
begin
for I in This.Waights'Range loop
This.Waights(I) := new Layer_Waights (1 .. Layers (Idx + 1).Num, 1 .. Layers (Idx).Num);
Task_Array (I).Init (Item => This.Waights (I).all);
Idx := Idx + 1;
end loop;
end Init_Waight_Tensor;
--this procedure initializing activate functions array
procedure Init_Activates is
begin
for I in This.Activates'Range loop
This.Activates (I) := Layers (I).F;
end loop;
end Init_Activates;
begin
Init_Values_Tensor;
Init_Waight_Tensor;
Init_Activates;
end Make;
In C++ I made it like this:
#include<cstddef>
#include<utility>
#include<array>
#include<tuple>
template<typename T>
struct Sigmoid{
void Function(){
}
};
template<typename T, std::size_t num, template<typename> class policy>
struct Layer{
using value_type = T;
using value_arr_type = std::array<T, num>;
static constexpr std::size_t _valuesNum{num};
};
template<typename Tuple, std::size_t... I>
constexpr auto tensor_impl(Tuple t, std::index_sequence<I...>){
using namespace std;
constexpr std::array res{std::get<I>(t)._valuesNum...};
std::tuple<array<array<float, get<I>(t)._valuesNum>, get<I+1>(t)._valuesNum>...> tup{};
return tup;
}
template<typename... Args, typename Indices = std::make_index_sequence<sizeof...(Args)-1>>
constexpr auto tensor_helper(){
constexpr std::tuple<Args...> args;
constexpr std::tuple arr{tensor_impl(args, Indices{})};
return arr;
}
template<typename T, typename... Args> requires(
(std::is_same_v<typename T::value_type, typename Args::value_type>) && ...)
class Net{
std::tuple<typename T::value_arr_type, typename Args::value_arr_type...> values{};
// std::tuple<std::array<std::array<typename T::value_type, 4>, sizeof...(Args)>> waights{};
public:
decltype(tensor_helper<T, Args...>()) _waights{tensor_helper<T, Args...>()};
decltype(auto) tensors(){return _waights;}
};
int main(){
using layer1 = Layer<float, 2, Sigmoid>;
using layer2 = Layer<float, 3, Sigmoid>;
using layer3 = Layer<float, 2, Sigmoid>;
Net<layer1, layer2, layer3> net{};
}
Yes, look at generic packages, you can then instantiate that and create new tuple types from there.
The primary trick for avoiding to use new is to avoid using access types.
Remove all your declarations of access types, and use the actual types instead.
If you just don't want to use new yourself, you can use the various indefinite containers from the standard library.
If you have to avoid using the heap/storage pools completely, you can declare a variant record:
type R (S : T := D) is
record
F1 : T1;
case S is
when V2 =>
F2 : T2;
when V3 =>
F3 : T3;
end case;
end record;
You can make regular arrays of type R using only the stack.

Ada - Long (Grade-School) Multiplication of BigNum Integers

I am trying to implement the Grade-School Multiplication algorithm in Ada, and am currently getting an index out of bounds error. I'd appreciate any input on how to fix the error, and successfully implement the Algorithm. Thanks in advance!
I have a package BigNumPkg which defines type BigNum is array(0..Size - 1) of Integer;
The function I am trying to implement currently looks like this:
FUNCTION "*" (X, Y : BigNum) RETURN BigNum IS
Product : BigNum:= Zero;
Carry : Natural := 0;
Base : Constant Integer := 10;
BEGIN
FOR I IN REVERSE 0..Size-1 LOOP
Carry := 0;
FOR N IN REVERSE 0..Size-1 LOOP
Product(N + I - 1) := Product(N + I - 1) + Carry + X(N) * Y(I);
Carry := Product(N + I -1) / Base;
Product(N + I -1) := Product(N +I-1) mod Base;
END LOOP;
Product(I+Size-1) := Product(I+Size-1) + Carry;
END LOOP;
RETURN Product;
END "*";
Package specification:
package Big_Integer is
Base : constant := 10;
Size : constant := 3;
type Extended_Digit is range 0 .. Base * Base;
subtype Digit is Extended_Digit range 0 .. Base - 1;
type Instance is array (0 .. Size - 1) of Digit;
function "*" (Left, Right : in Instance) return Instance;
function Image (Item : in Instance) return String;
end Big_Integer;
You can of course adjust the parameters as needed, but these are nice for manual inspection of the results. Note that I haven't assured myself that the range of Extended_Digit is correct, but it seems to work in this case.
Package implementation:
with Ada.Strings.Unbounded;
package body Big_Integer is
function "*" (Left, Right : in Instance) return Instance is
Carry : Extended_Digit := 0;
Sum : Extended_Digit;
begin
return Product : Instance := (others => 0) do
for I in Left'Range loop
for J in Right'Range loop
if I + J in Product'Range then
Sum := Left (I) * Right (J) + Carry + Product (I + J);
Product (I + J) := Sum mod Base;
Carry := Sum / Base;
else
Sum := Left (I) * Right (J) + Carry;
if Sum = 0 then
Carry := 0;
else
raise Constraint_Error with "Big integer overflow.";
end if;
end if;
end loop;
if Carry /= 0 then
raise Constraint_Error with "Big integer overflow.";
end if;
end loop;
end return;
end "*";
function Image (Item : in Instance) return String is
Buffer : Ada.Strings.Unbounded.Unbounded_String;
begin
for E of reverse Item loop
Ada.Strings.Unbounded.Append (Buffer, Digit'Image (E));
end loop;
return Ada.Strings.Unbounded.To_String (Buffer);
end Image;
end Big_Integer;
Test driver:
with Ada.Text_IO;
with Big_Integer;
procedure Use_Big_Integers is
use all type Big_Integer.Instance;
procedure Multiply (A, B : in Big_Integer.Instance);
procedure Multiply (A, B : in Big_Integer.Instance) is
use Ada.Text_IO;
begin
Put (Image (A));
Put (" * ");
Put (Image (B));
Put (" = ");
Put (Image (A * B));
New_Line;
exception
when Constraint_Error =>
Put_Line ("Constraint_Error");
end Multiply;
begin
Multiply (A => (0 => 1, others => 0),
B => (others => Big_Integer.Digit'Last));
Multiply (A => (0 => Big_Integer.Digit'Last, others => 0),
B => (0 => Big_Integer.Digit'Last, others => 0));
Multiply (A => (0 => 2, others => 0),
B => (others => Big_Integer.Digit'Last));
Multiply (A => (2 => 0, 1 => 1, 0 => 2),
B => (2 => 0, 1 => 4, 0 => 5));
Multiply (A => (2 => 0, 1 => 2, 0 => 2),
B => (2 => 0, 1 => 4, 0 => 5));
Multiply (A => (2 => 0, 1 => 2, 0 => 3),
B => (2 => 0, 1 => 4, 0 => 5));
end Use_Big_Integers;
It is good style to provide a complete reproducer, but never mind...
When I is going to be used as an index into Y, it is good style to write the loop statement as for I in reverse Y'Range ... end loop;. Similarly for N.
Are you certain that N + I - 1 always is a valid index for Product? I'm pretty sure that you can get both too large and too small indices with your current implementation. I suspect that the too small indices is an off-by-one error in the implementation of the algorithm. The too large indices are because you haven't thought clearly about how to handle integer overflow (the traditional way in Ada is to raise Constraint_Error).
Shouldn't yo check the value of Carry at the end of the function?

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