I just started to learn some ada code and would create my very own primes calculator.
To procress, I use one of most known method, which is :
"each primes is a result of 6 * x -+ 1 "
So this is my code :
with Ada.Text_IO, Ada.Integer_Text_IO ;
use Ada.Text_IO, Ada.Integer_Text_IO ;
procedure main is
count_prime : Integer := 0 ;
counter : Integer := 1 ;
wanted : Integer ;
iteration : Integer := 0 ;
testing : Integer := 0 ;
is_prime : Boolean ;
answer : Character ;
begin
loop
Put("Prime calculator") ;
New_line(2) ;
Put("Put 'p' to process") ;
New_Line(1);
Put("Put 'q' to quit") ;
New_Line(2) ;
Put(">> ") ;
Get(answer) ;
if answer = 'p' then
Put("Enter wanted primes :");
Get(wanted) ;
Skip_line ;
if wanted > 0 then
Put("2");
New_Line(1);
if wanted > 1 then
Put("3");
New_Line(1);
end if ;
if wanted > 2 then
count_prime := 2;
loop
if counter = 1 then
counter := 0 ;
iteration := iteration + 1 ;
testing := ( 6 * iteration ) - 1 ;
else
counter := 1 ;
testing := ( 6 * iteration ) + 1 ;
end if ;
is_prime := True ;
for i in 2..(testing-1) loop
if (testing rem i = 0) then
is_prime := False ;
end if ;
end loop;
if is_prime = True then
Put(testing);
New_Line(1);
count_prime := count_prime + 1 ;
end if ;
exit when count_prime = wanted;
end loop ;
end if;
Put("Ended") ;
else
Put("It's can't be a negative number");
end if ;
end if ;
New_Line(3);
exit when answer = 'q' ;
end loop ;
end main ;
I really know this is a basic, I mean ouh, extremely basic program. But I would just solve the problem I've asked :
with 'p' and 2 :
2
3
with 'p' and '7'
2
3
5
7
11
13
17
with 'p' and 1200
2
3
19
23
29
31
37
41
....
Where are gone all primes between 3 and 19 ?
You keep running the calculation in a cycle, but do not reset it's initial state. The loop that performs the calculation continues using values of iteration, counter and a few other variables from the previous run.
Either decompose the loop into a separate procedure, or at least surround it with declare block, e.g.:
declare
count_prime : Integer := 2;
counter : Integer := 1;
iteration : Integer := 0;
testing : Integer := 0;
is_prime : Boolean;
begin
loop
…
end loop;
end;
However, I'd strongly recommend decomposing into a separate procedure.
if wanted > 2 then
count_prime := 2;
-- you probably want to reset iteration here...
iteration := 0;
loop
if counter = 1 then
Related
I turn to Stackoverflow yet again. having gotten help here previously I hope to be received equally friendly once more. I have an assignment where I need to draw a flag (including a box-like shape around it and a V-shape of crosses in its midst) in ADA. Ive managed to make the box and roughly half of the crosses. can anyone clue me in as to how one easiest fills in the remainder of the crosses?
Its supposed to be a V-shape, like this:
+ +
+ +
+
etc
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure exercise2 is
subtype Cross_Rows is Integer range 2..80;
Rows : Cross_Rows;
Flag_Width : Cross_Rows;
Left : Positive;
Right : Positive;
procedure Row_Get (Rows: out Cross_Rows) is
begin
Put("Enter the number of cross rows (min is 3): ");
Get(Rows);
Skip_Line;
end Row_Get;
procedure Print_Top (Rows: in Cross_Rows) is
begin
Flag_Width := (Rows * 2) + 4;
Put("+");
for Col in 1..Flag_Width-3 loop
Put("-");
end loop;
Put("+");
New_Line;
end Print_Top;
procedure Print_Middle (Rows: in Cross_Rows) is
begin
Left := 1;
Right := Flag_Width - 5;
for R in 1..Rows loop
Put("! ");
for C in 1..Flag_Width - 4 loop
if C = Left or else C = Right then
Put("+");
else
Put(" ");
end if;
end loop;
Left := Left + 1;
Right := Right - 1;
Put_Line("!");
end loop;
end Print_Middle;
procedure Print_Bottom (Rows: in Cross_Rows) is
begin
Flag_Width := (Rows * 2) + 4;
Put("+");
for C in 1..Flag_Width-3 loop
Put("-");
end loop;
Put_Line("+");
end Print_Bottom;
begin
Row_Get(Rows);
Print_Top(Rows);
Print_Middle(Rows);
Print_Bottom(Rows);
end exercise2;
EDIT: Thanks to Jim Rogers I managed to edit my program to draw the flag. Unfortunately its not exactly the way its meant to be as the top crosses are supposed to touch the sides and not be spaced like they are now. Additionally the Main program and the subprograms arent allowed to be more than 15 lines each so I compartmentalized them.
The smallest flag is supposed to look like this. I'll try to work with his code to achieve this. But any help is of value! :)
n=1
+---+
!+ +!
! + !
+---+
n=2
+-----+
!+ +!
! + + !
! + !
+-----+
You need to keep track of the left and right columns for the '+' characters, increasing the left column position and decreasing the right column position with each iteration of your loop for printing the crosses.
The following program works for any number of rows of crosses from 3 to 80.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Main is
subtype Cross_Rows is Integer range 3..80;
Rows : Cross_Rows;
Flag_Width : Cross_Rows;
Left : Positive;
Right : Positive;
begin
Put("Enter the number of cross rows (minimum is 3): ");
Get(Rows);
Skip_Line;
Flag_Width := (Rows * 2) + 4;
-- Print top row of flag boundary
for Col in 1..Flag_Width loop
Put("-");
end loop;
Put("-");
New_Line;
-- Print empty row below top flag boundary
Put("- ");
for C in 3..Flag_Width - 2 loop
Put(" ");
end loop;
Put_Line(" -");
-- Print crosses
Left := 1;
Right := Flag_Width - 5;
for R in 1..Rows loop
Put("- ");
for C in 1..Flag_Width - 4 loop
if C = Left or else C = Right then
Put("+");
else
Put(" ");
end if;
end loop;
Left := Left + 1;
Right := Right - 1;
Put_Line(" -");
end loop;
-- Print bottom flag rows
Put("- ");
for C in 3..Flag_Width - 2 loop
Put(" ");
end loop;
Put_Line(" -");
for C in 1..Flag_Width loop
Put("-");
end loop;
Put_Line("-");
end Main;
Example output is:
Enter the number of cross rows (minimum is 3): 7
-------------------
- -
- + + -
- + + -
- + + -
- + + -
- + + -
- + + -
- + -
- -
-------------------
Another approach uses the Set_Col procedure from Ada.Text_Io. Set_Col set the cursor to the specified column number in the current output line. For example, if the cursor starts at position 1 and you call Set_Col(10) the procedure will output 9 blank characters and set the column number to 10. You can then begin writing your non-blank output at column 10.
with Ada.Text_Io; use Ada.Text_IO;
with Ada.Integer_Text_Io; use Ada.Integer_Text_IO;
procedure V_columns is
subtype Cross_Rows is Integer range 3..80;
Rows : Cross_Rows;
Flag_Width : Positive;
Left : Positive;
Right : Positive;
begin
Put("Enter the number of cross rows (minimum is 3): ");
Get(Rows);
Skip_Line;
Flag_Width := (Rows * 2) + 4;
-- Print top row of flag boundary
for Col in 1..Flag_Width loop
Put("-");
end loop;
New_Line;
-- Print empty row below top flag boundary
Set_Col(1);
Put("|");
Set_Col(Positive_Count(Flag_Width));
Put_Line("|");
-- Print crosses
Left := 3;
Right := Flag_Width - 3;
for R in 1..Rows loop
Set_Col(1);
Put("|");
if Left < Right then
Set_Col(Positive_Count(Left));
Put("+");
Set_Col(Positive_Count(Right));
Put("+");
else
Set_Col(Positive_Count(Right));
Put("+");
end if;
Set_Col(Positive_Count(Flag_Width));
Put("|");
New_Line;
Left := Left + 1;
Right := Right - 1;
end loop;
-- Print bottom flag rows
Set_Col(1);
Put("|");
Set_Col(Positive_Count(Flag_Width));
Put_Line("|");
for C in 1..Flag_Width loop
Put("-");
end loop;
New_Line;
end V_Columns;
The output of the program is:
Enter the number of cross rows (minimum is 3): 7
------------------
| |
| + + |
| + + |
| + + |
| + + |
| + + |
| + + |
| + |
| |
------------------
You could also choose an approach in which the definition of the pattern (here: a flag) and the output mechanism are almost completely decoupled. This approach also allows you to parallelize the flag rendering in case you need to render really, really huge flags ;-):
main.adb
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
N : constant := 2;
Width : constant := 3 + 2 * N;
Height : constant := 3 + 1 * N;
type Screen_X is new Natural range 0 .. Width - 1;
type Screen_Y is new Natural range 0 .. Height - 1;
-------------
-- Pattern --
-------------
function Pattern (X : Screen_X; Y : Screen_Y) return Character is
Is_Border_LR : constant Boolean :=
X = Screen_X'First or else X = Screen_X'Last;
Is_Border_TB : constant Boolean :=
Y = Screen_Y'First or else Y = Screen_Y'Last;
-- The V-Shape is based on the implicit function:
--
-- abs (X - X0) + (Y - Y0) = 0
X0 : constant := (Screen_X'Last + Screen_X'First) / 2;
Y0 : constant := Screen_Y'Last - 1;
Is_V_Shape : constant Boolean :=
Integer (abs (X - X0)) + Integer (Y - Y0) = 0;
begin
if Is_Border_LR and Is_Border_TB then
return '+';
elsif Is_Border_LR then
return '!';
elsif Is_Border_TB then
return '-';
elsif Is_V_Shape then
return '+';
else
return ' ';
end if;
end Pattern;
begin
-- The Render loop.
for Y in Screen_Y loop
for X in Screen_X loop
Put (Pattern (X, Y));
end loop;
New_Line;
end loop;
end Main;
output (N = 1)
$ ./main
+---+
!+ +!
! + !
+---+
output (N = 2)
$ ./main
+-----+
!+ +!
! + + !
! + !
+-----+
I write my first ada program which include a condition that check if a value divide by a specific number haven't a decimal part :
EXEMPLE :
10 / 3 = 3.3333334 >> Wrong
12 / 2 = 6 >> Okay
45 / 5 = 9 >> Okay
...
But I can't find any function to do it...
this is my code :
with Ada.Text_IO, Ada.Integer_Text_IO ;
use Ada.Text_IO, Ada.Integer_Text_IO ;
procedure main is
...
testing : Natural := 0 ;
...
begin
...
if testing/i = ??? then -- if testing/i haven't decimal part --
...
end if ;
...
end main ;
This could work:
main.adb
with Ada.Text_IO;
procedure Main is
procedure Test_Remainder (X, Y : Integer) is
use Ada.Text_IO;
begin
-- Optional: add some test for Y being non-zero here...
Put (X'Image & " / " & Y'Image & " ==> ");
if (X rem Y = 0) then
Put_Line ("Okay");
else
Put_Line ("Wrong");
end if;
end Test_Remainder;
begin
Test_Remainder (10, 3);
Test_Remainder (12, 2);
Test_Remainder (45, 5);
end Main;
output
10 / 3 ==> Wrong
12 / 2 ==> Okay
45 / 5 ==> Okay
Note: For difference between mod and rem see e.g. Wikipedia.
I'm coding the spigot algorithm for displaying digits of pi in ada, but my output is wrong and I can't figure out why
I've tried messing with the range of my loops and different ways to output my data but nothings worked properly
with ada.integer_text_io; use ada.integer_text_io;
with Ada.Text_IO; use Ada.Text_IO;
procedure Spigot is
n : constant Integer := 1000;
length : constant Integer := 10*n/3+1;
x,q,nines,predigit :Integer :=0;
a: array (0..length) of Integer;
begin
nines:=0;
predigit:=0;
for j in 0..length loop
a(j):=2;
end loop;
for j in 1..n loop
q:=0;
for i in reverse 1..length loop
x:=10*a(i) + q*i;
a(i):= x mod (2*i-1);
q:= x/(2*i-1);
end loop;
a(1):= q mod 10;
q:=q/10;
if q = 9 then
nines:=nines+1;
elsif q = 10 then
put(predigit+1);
for k in 0..nines loop
put("0");
end loop;
predigit:=0;
nines:=0;
else
put(predigit);
predigit:=q;
if nines/=0 then
for k in 0..nines loop
put("9");
end loop;
nines:=0;
end if;
end if;
end loop;
put(predigit);
end Spigot;
so it should just be displayed at 0 3 1 4 1 5 9 2 6 5 3 5 8 9... but the output i get is 0 3 1 4 1 599 2 6 5 3 5 89... it should only be 1 digit at a time and also the outputted values for pi aren't completely correct
I don't know the algorithm well enough to talk about why the digits are off, but I did notice some issues:
Your array is defined with bounds 0 .. Length, which would give you 1 extra element
In your loop that does the calculation, you loop from 1..length, which is ok, but you don't adjust the variable i consistently. The array indices need to be one less than the i's used in the actual calculations (keep in mind they still have to be correctly in bounds of your array). For example
x:=10*a(i) + q*i;
needs to either be
x:=10*a(i-1) + q*i;
or
x:=10*a(i) + q*(i+1);
depending on what you decide your array bounds to be. This applies to multiple lines in your code. See this Stackoverflow thread
You assign A(1) when your array starts at 0
Your loops to print out "0" and "9" should be either 1..length or 0 .. length-1
When you print the digits using Integer_Text_IO.Put, you need to specify a width of 1 to get rid of the spaces
There might be more, that's all I saw.
I think you are translating this answer.
You need to be more careful of your indices and your loop ranges; for example, you’ve translated
for(int i = len; i > 0; --i) {
int x = 10 * A[i-1] + q*i;
A[i-1] = x % (2*i - 1);
q = x / (2*i - 1);
}
as
for i in reverse 1..length loop
x:=10*a(i) + q*i;
a(i):= x mod (2*i-1);
q:= x/(2*i-1);
end loop;
The loop ranges are the same. But in the seocnd line, the C code uses A[i-1], whereas yours uses a(i); similarly in the third line.
Later, for
for (int k = 0; k < nines; ++k) {
printf("%d", 0);
}
you have
for k in 0..nines loop
put("0");
end loop;
in which the C loop runs from 0 to nines - 1, but yours runs from 0 to nines. So you put out one more 0 than you should (and later on, likewise for 9s).
Also, you should use put (predigit, width=> 0).
So I am trying to use recursion and backtracking to solve a 4x4 sudoku.
When I call SolveSmallSudoku(L);
"Solving now..."
it gives me this "Error, (in SolveSmallSudoku) Matrix index out of range"
But I cannot spot any bug that is related to my matrix, L, indices. It seems like that my program doesn't do my backtracking part properly. I think my findPossibleEntries procedure works fine. It does find all the possible values for that certain cell. Anyone got any hint?
> L := Matrix(4,4,[ [0,4,0,0],[2,0,0,3],[4,0,0,1],[0,0,3,0] ]);
> isFull := proc(L)
local x, y;
for x from 1 to 4 do
for y from 1 to 4 do
if L[x,y]=0 then
return false;
end if;
end do;
end do;
return true;
end proc;
>findPossibleEntries := proc(L, i, j)
local x, y, possible:=[0,0,0,0];
local r:=1, c:=1;
#Checking possible entries in ith row
for y from 1 to 4 do
if not L[i,y] = 0 then
possible[L[i,y]] := 1;
end if;
end do;
#Checking possible entries in jth col
for x from 1 to 4 do
if not L[x,j] = 0 then
possible[L[x,j]] := 1;
end if;
end do;
#Checking possible entries block by block
if i >= 1 and i <= 2 then
r := 1;
elif i >= 3 and i <= 4 then
r := 3;
end if;
if j >= 1 and j <= 2 then
c := 1;
elif j >= 3 and j <= 4 then
c := 3;
end if;
#Using for-loop to find possible entries in the block
for x in range(r, r+1) do
for y in range(c, c+1) do
if not L[x,y] = 0 then
possible[L[x,y]] := 1;
end if;
end do;
end do;
#Now the list, possible, only holds the possible entries
for x from 1 to 4 do
if possible[x] = 0 then
possible[x] := x;
else
possible[x] := 0;
end if;
end do;
return possible;
end proc;
>SolveSmallSudoku := proc(L)
local x, y, i:=0, j:=0, possibleVal:=[0,0,0,0];
if isFull(L) then
print("Solved!");
print(L);
return;
else
print("Solving now...");
for x from 1 to 4 do
for y from 1 to 4 do
if L[x,y] = 0 then
i:=x;
j:=y;
break;
end if
end do;
#Breaks the outer loop as well
if L[x,y] = 0 then
break;
end if
end do;
#Finds all the possibilities for i,j
possibleVal := findPossibleEntries(L,i,j);
#Traverses the list, possibleVal to find the correct entries and finishes the sudoku recursively
for x from 1 to 4 do
if not possibleVal[x] = 0 then
L[i,j]:= possibleVal[x];
SolveSmallSudoku(L);
end if;
end do;
#Backtracking
L[i,j]:= 0;
end if;
end proc;
Get rid of,
#Breaks the outer loop as well
if L[x,y] = 0 then
break;
end if
As you had it originally that outer check was trying to access L[1,5] for your given example L.
Instead, replace the break in the inner loop with,
x:=4; break;
That will cause the outer loop to also complete at the next iteration (which happens to occur right after the inner loop ends or breaks. So you'll get the full break you wanted.
The code then seems to work as you intended, and the solution gets printed for your input example.
I'm trying to do a few mathematical operations on integers in a piece of vhdl code but when i try to compile the tool says "0 definitions of operator "+" match here". Here is what i'm trying to do:
for i in 0 to arr_size - 1 loop
for j in 0 to arr_size - 1 loop
for k in 0 to arr_size - 1 loop
for l in 0 to arr_size - 1 loop
for m in 0 to arr_size - 1 loop
mega_array(i)(j)(k)(l)(m) <= i*(arr_size**4) + j*(arr_size**3) + k*(arr_size**2) + l*(arr_size**1) + m*(arr_size**0);
end loop;
end loop;
end loop;
end loop;
end loop;
The problem was encountered in the line where mega_array is set. Note that this whole block is in a process.
Additionally:
arr_size : integer := 4;
sig_size : integer := 32
type \1-line\ is array (arr_size - 1 downto 0) of unsigned (sig_size - 1 downto 0);
type square is array (arr_size - 1 downto 0) of \1-line\;
type cube is array (arr_size - 1 downto 0) of square;
type hypercube is array (arr_size - 1 downto 0) of cube;
type \5-cube\ is array (arr_size - 1 downto 0) of hypercube;
signal mega_array : \5-cube\;
When reading your older post, the mega_array is an array of 4 levels with at the lowest level an unsigned. In your code in this question I see 5 levels. So at the fifth level you have bit. You can not assign an integer to a std_logic.
Could it be this code is what you want?
for i in 0 to arr_size - 1 loop -- 5-cube
for j in 0 to arr_size - 1 loop -- hypercube
for k in 0 to arr_size - 1 loop -- cube
for l in 0 to arr_size - 1 loop -- square
for m in 0 to arr_size - 1 loop -- 1-line
mega_array(i)(j)(k)(l) <= to_unsigned(i*(arr_size**4) + j*(arr_size**3) + k*(arr_size**2) + l*(arr_size**1), 32);
end loop
end loop;
end loop;
end loop;
end loop;
The to_unsigned functions converts the integer to an unsigned, what is the type of 1-line. The second parameter is the size of the vector to convert the integer into. It must be the same as the size of 1-line.