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.
Related
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
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).
This function is a school practice problem (it is running but does not work properly).
My task is to call for a integer from the user.
When the number arrives, my task is to write out (with a recursive algorithm)
what is the sum of the number with the numbers before the given number.
For example if our number is 10 then the upshot is 55 because 1+2+3+4+5+6+7+8+9+10 = 55, etc.
I've already tried to write this code:
function egesszamosszeg(n:integer) : integer;
begin
egesszamosszeg:=0
if n=1 then
egesszamosszeg:=1
else
for n:=1 to egesszamosszeg do
begin
egesszamosszeg:=egesszamosszeg+1;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var egesszam:integer;
begin
egesszam:=strtoint(Inputbox('','Give an integer please!',''));
Showmessage(inttostr(Egesszamosszeg(egesszam)));
end;
My problem is that I do not know what is the main problem with this code.
I do not know what is the main problem with this code.
There are several problems with your code: it's iterative, not recursive; it's way too complicated; this loop:
for n:=1 to egesszamosszeg do
is effectively:
for n:=1 to 0 do
Consider this simple function which effectively implements the gist of your problem:
function egesszamosszeg(n:integer) : integer;
begin
egesszamosszeg := n;
if (n > 1) then
egesszamosszeg := egesszamosszeg + egesszamosszeg(n - 1);
end;
begin
writeln(egesszamosszeg(10));
end.
You are simply trying to increment egesszamosszeg (couldn't you use an easier name?), instead of adding the consecutive numbers to it. But your loop is wrong: eggesszamosszeg is 0, so you are in fact doing for n := 1 to 0 do. That loop will never run. Don't re-use n, use another variable for the loop index:
for i := 1 to n do
egesszamosszeg := egesszamosszeg + i;
But you say it must be recursive, so it must call itself with a different parameter value. Then do something like:
function egesszamosszeg(n: integer): integer;
begin
if n = 1 then // terminating condition
egesszamosszeg := 1
else
egesszamosszeg := n + egesszamosszeg(n - 1); // recursion
end;
In most Pascals, you can use the pseudo-variable Result instead of the function name. Often, that makes typing a little easier.
FWIW, did you know that you could make this a little simpler and do not need recursion or iteration at all? The result can be calculated directly:
function egesszamosszeg(n: Integer): Integer;
begin
result := n * (n + 1) div 2;
end;
For 1..10, that will give 10 * 11 div 2 = 55 too.
See: https://www.wikihow.com/Sum-the-Integers-from-1-to-N
In effect, you count (1+10) + (2+9) + (3+8) + (4+7) + (5+6) = 5 * 11 = 55. You can do the same for any positive number. Same with 1..6: (1+6) + (2+5) + (3+4) = 3 * 7 = 21.
That leads to the formula:
sum = n * (n + 1) div 2
(or actually:
n div 2 * (n+1) // mathematically: n/2 * (n+1)
which is the same).
I am trying to find the greatest common factor for some numbers that i have put into a table. So far I have the function that is suppose to calculate the gcf
CREATE FUNCTION gcd (x INTEGER, y INTEGER) RETURN INTEGER AS
ans INTEGER;
BEGIN
IF (y <= x) AND (x MOD y = 0) THEN
ans := y;
ELSIF x < y THEN
ans := gcd(y, x);
ELSE
ans := gcd(y, x MOD y);
END IF;
RETURN ans;
END;
and here I create and random populate my table
DROP TABLE numere
/
CREATE TABLE numbers (number NUMBER(3) NOT NULL)
/
set serveroutput on
DECLARE
number NUMBER(3);
cursor c1 is
SELECT * FROM note;
BEGIN
FOR i IN 1 .. 10 LOOP
number:=dbms_random.value(20,100);
insert into numbers values(number);
end loop;
commit;
END;
/
How can I integrate the gcf into my code? I want to display the numbers followed by their gcf.
I am not sure about your gcd function. It seems to me not working. There are many on the web. This is one of them:
CREATE OR REPLACE FUNCTION find_gcd (
p_n1 IN POSITIVE
, p_n2 IN POSITIVE
)
RETURN POSITIVE
IS
l_n1 POSITIVE := p_n1;
l_n2 POSITIVE := p_n2;
BEGIN
WHILE NOT (l_n1 = l_n2)
LOOP
CASE SIGN(l_n1 - l_n2)
WHEN +1
THEN l_n1 := l_n1 - l_n2;
ELSE l_n2 := l_n2 - l_n1;
END CASE;
END LOOP;
RETURN (l_n1);
END find_gcd;
/
You can simply amend your PL/SQL block to call the gcd function and print out the results (I here assumed you want to find the gcd for each number and the following number in your table, so I used LEAD function):
DECLARE
lv_number NUMBER(3);
lv_gcd INTEGER;
BEGIN
FOR i IN 1 .. 10 LOOP
lv_number:=dbms_random.value(20,100);
insert into numbers values(lv_number);
end loop;
commit;
FOR i in (select COL_VAL, lead(COL_VAL) over (order by rowid) nxt_val from numbers)
LOOP
lv_gcd := find_gcd(i.COL_VAL, i.nxt_val);
DBMS_OUTPUT.PUT_LINE('GCD for '||TO_CHAR(i.COL_VAL)||' and '|| TO_CHAR(i.nxt_val) ||' is '||TO_CHAR(lv_gcd));
END LOOP;
END;
/
I am stuck on my quicksort program. I need to count the total number of times the sorting function calls itself.
procedure quick (first, last, counter: integer);
var i, k, x : integer;
begin
i := first;
k := last;
x := a[(i+k) div 2];
counter := counter + 1;
while i<=k do begin
while a[i] < x do
i:= i+1;
while a[k] > x do
k:= k-1;
if i<=k then begin
prohod(i,k);
i:=i+1;
k:=k-1;
end;
end;
if first<k then quick(first,k, counter);
if i<last then quick(i,last, counter);
P:= P + counter;
end;
I tried this, where P is global variable and counter is recursive variable, first called as 1 ( quick(1, n, 1) ) . Sadly did not work. I also set P:= 0; right before I called the sorting (quick) procedure (I am not quite sure if it is correct way to approach the problem but it's all I could come up with).
Any ideas how to make this correctly and / or why my counter is not working?
This looks overly complex. If you just remove the counter, initialize P with the value -1 (instead of 0) and replace P := P + counter with P := P + 1, it should work.