I'm currently reading Programming in Lua Fourth Edition and I'm already stuck on the first exercise of "Chapter 2. Interlude: The Eight-Queen Puzzle."
The example code is as follows:
N = 8 -- board size
-- check whether position (n, c) is free from attacks
function isplaceok (a, n ,c)
for i = 1, n - 1 do -- for each queen already placed
if (a[i] == c) or -- same column?
(a[i] - i == c - n) or -- same diagonal?
(a[i] + i == c + n) then -- same diagonal?
return false -- place can be attacked
end
end
return true -- no attacks; place is OK
end
-- print a board
function printsolution (a)
for i = 1, N do -- for each row
for j = 1, N do -- and for each column
-- write "X" or "-" plus a space
io.write(a[i] == j and "X" or "-", " ")
end
io.write("\n")
end
io.write("\n")
end
-- add to board 'a' all queens from 'n' to 'N'
function addqueen (a, n)
if n > N then -- all queens have been placed?
printsolution(a)
else -- try to place n-th queen
for c = 1, N do
if isplaceok(a, n, c) then
a[n] = c -- place n-th queen at column 'c'
addqueen(a, n + 1)
end
end
end
end
-- run the program
addqueen({}, 1)
The code's quite commented and the book's quite explicit, but I can't answer the first question:
Exercise 2.1: Modify the eight-queen program so that it stops after
printing the first solution.
At the end of this program, a contains all possible solutions; I can't figure out if addqueen (n, c) should be modified so that a contains only one possible solution or if printsolution (a) should be modified so that it only prints the first possible solution?
Even though I'm not sure to fully understand backtracking, I tried to implement both hypotheses without success, so any help would be much appreciated.
At the end of this program, a contains all possible solutions
As far as I understand the solution, a never contains all possible solutions; it either includes one complete solution or one incomplete/incorrect one that the algorithm is working on. The algorithm is written in a way that simply enumerates possible solutions skipping those that generate conflicts as early as possible (for example, if first and second queens are on the same line, then the second queen will be moved without checking positions for other queens, as they wouldn't satisfy the solution anyway).
So, to stop after printing the first solution, you can simply add os.exit() after printsolution(a) line.
Listing 1 is an alternative to implement the requirement. The three lines, commented respectively with (1), (2), and (3), are the modifications to the original implementation in the book and as listed in the question. With these modifications, if the function returns true, a solution was found and a contains the solution.
-- Listing 1
function addqueen (a, n)
if n > N then -- all queens have been placed?
return true -- (1)
else -- try to place n-th queen
for c = 1, N do
if isplaceok(a, n, c) then
a[n] = c -- place n-th queen at column 'c'
if addqueen(a, n + 1) then return true end -- (2)
end
end
return false -- (3)
end
end
-- run the program
a = {1}
if not addqueen(a, 2) then print("failed") end
printsolution(a)
a = {1, 4}
if not addqueen(a, 3) then print("failed") end
printsolution(a)
Let me start from Exercise 2.2 in the book, which, based on my past experience to explain "backtracking" algorithms to other people, may help to better understand the original implementation and my modifications.
Exercise 2.2 requires to generate all possible permutations first. A straightforward and intuitive solution is in Listing 2, which uses nested for-loops to generate all permutations and validates them one by one in the inner most loop. Although it fulfills the requirement of Exercise 2.2, the code does look awkward. Also it is hard-coded to solve 8x8 board.
-- Listing 2
local function allsolutions (a)
-- generate all possible permutations
for c1 = 1, N do
a[1] = c1
for c2 = 1, N do
a[2] = c2
for c3 = 1, N do
a[3] = c3
for c4 = 1, N do
a[4] = c4
for c5 = 1, N do
a[5] = c5
for c6 = 1, N do
a[6] = c6
for c7 = 1, N do
a[7] = c7
for c8 = 1, N do
a[8] = c8
-- validate the permutation
local valid
for r = 2, N do -- start from 2nd row
valid = isplaceok(a, r, a[r])
if not valid then break end
end
if valid then printsolution(a) end
end
end
end
end
end
end
end
end
end
-- run the program
allsolutions({})
Listing 3 is equivalent to List 2, when N = 8. The for-loop in the else-end block does what the whole nested for-loops in Listing 2 do. Using recursive call makes the code not only compact, but also flexible, i.e., it is capable of solving NxN board and board with pre-set rows. However, recursive calls sometimes do cause confusions. Hope the code in List 2 helps.
-- Listing 3
local function addqueen (a, n)
n = n or 1
if n > N then
-- verify the permutation
local valid
for r = 2, N do -- start from 2nd row
valid = isplaceok(a, r, a[r])
if not valid then break end
end
if valid then printsolution(a) end
else
-- generate all possible permutations
for c = 1, N do
a[n] = c
addqueen(a, n + 1)
end
end
end
-- run the program
addqueen({}) -- empty board, equivalent allsolutions({})
addqueen({1}, 2) -- a queen in 1st row and 1st column
Compare the code in Listing 3 with the original implementation, the difference is that it does validation after all eight queens are placed on the board, while the original implementation validates every time when a queen is added and will not go further to next row if the newly-added queen causes conflicts. This is all what "backtracking" is about, i.e. it does "brute-force" search, it abandons the search branch once it finds a node that will not lead to a solution, and it has to reach a leaf of the search tree to determine it is a valid solution.
Back to the modifications in Listing 1.
(1) When the function hits this point, it reaches a leaf of the search tree and a valid solution is found, so let it return true representing success.
(2) This is the point to stop the function from further searching. In original implementation, the for-loop continues regardless of what happened to the recursive call. With modification (1) in place, the recursive call returns true if a solution was found, the function needs to stop and to propagate the successful signal back; otherwise, it continues the for-loop, searching for other possible solutions.
(3) This is the point the function returns after finishing the for-loop. With modification (1) and (2) in place, it means that it failed to find a solution when the function hits this point, so let it explicitly return false representing failure.
Related
I am implementing a recursive program to calculate the certain values in the Schroder sequence, and I'm having two problems:
I need to calculate the number of calls in the program;
Past a certain number, the program will generate incorrect values (I think it's because the number is too big);
Here is the code:
let rec schroder n =
if n <= 0 then 1
else if n = 1 then 2
else 3 * schroder (n-1) + sum n 1
and sum n k =
if (k > n-2) then 0
else schroder k * schroder (n-k-1) + sum n (k+1)
When I try to return tuples (1.), the function sum stops working because it's trying to return int when it has type int * int;
Regarding 2., when I do schroder 15 it returns:
-357364258
when it should be returning
3937603038.
EDIT:
firstly thanks for the tips, secondly after some hours of deep struggle, i manage to create the function, now my problem is that i'm struggling to install zarith. I think I got it installed, but ..
in terminal when i do ocamlc -I +zarith test.ml i get an error saying Required module 'Z' is unavailable.
in utop after doing #load "zarith.cma";; and #install_printer Z.pp_print;; i can compile, run the function and it works. However i'm trying to implement a Scanf.scanf so that i can print different values of the sequence. With this being said whenever i try to run the scanf, i dont get a chance to write any number as i get a message saying that '\\n' is not a decimal digit.
With this being said i will most probably also have problems with printing the value, because i dont think that i'm going to be able to print such a big number with a %d. The let r1,c1 = in the following code, is a example of what i'm talking about.
Here's what i'm using :
(function)
..
let v1, v2 = Scanf.scanf "%d %d" (fun v1 v2-> v1,v2);;
let r1,c1 = schroder_a (Big_int_Z.of_int v1) in
Printf.printf "%d %d\n" (Big_int_Z.int_of_big_int r1) (Big_int_Z.int_of_big_int c1);
let r2,c2 = schroder_a v2 in
Printf.printf "%d %d\n" r2 c2;
P.S. 'r1' & 'r2' stands for result, and 'c1' and 'c2' stands for the number of calls of schroder's recursive function.
P.S.S. the prints are written differently because i was just testing, but i cant even pass through the scanf so..
This is the third time I've seen this problem here on StackOverflow, so I assume it's some kind of school assignment. As such, I'm just going to make some comments.
OCaml doesn't have a function named sum built in. If it's a function you've written yourself, the obvious suggestion would be to rewrite it so that it knows how to add up the tuples that you want to return. That would be one approach, at any rate.
It's true, ints in OCaml are subject to overflow. If you want to calculate larger values you need to use a "big number" package. The one to use with a modern OCaml is Zarith (I have linked to the description on ocaml.org).
However, none of the other people solving this assignment have mentioned overflow as a problem. It could be that you're OK if you just solve for representable OCaml int values.
3937603038 is larger than what a 32-bit int can hold, and will therefore overflow. You can fix this by using int64 instead (until you overflow that too). You'll have to use int64 literals, using the L suffix, and operations from the Int64 module. Here's your code converted to compute the value as an int64:
let rec schroder n =
if n <= 0 then 1L
else if n = 1 then 2L
else Int64.add (Int64.mul 3L (schroder (n-1))) (sum n 1)
and sum n k =
if (k > n-2) then 0L
else Int64.add (Int64.mul (schroder k) (schroder (n-k-1))) (sum n (k+1))
I need to calculate the number of calls in the program;
...
the function 'sum' stops working because it's trying to return 'int' when it has type 'int * int'
Make sure that you have updated all the recursive calls to shroder. Remember it is now returning a pair not a number, so you can't, for example, just to add it and you need to unpack the pair first. E.g.,
...
else
let r,i = schroder (n-1) (i+1) in
3 * r + sum n 1 and ...
and so on.
Past a certain number, the program will generate incorrect values (I think it's because the number is too big);
You need to use an arbitrary-precision numbers, e.g., zarith
I've been working on a hex calculator for a while, but seem to be stuck on the subtraction portion, particularly when B>A. I'm trying to simply subtract two positive integers and display the result. It works fine for A>B and A=B. So far I'm able use two 7-segment displays to show the integers to be subtracted and I get the proper difference as long as A>=B
When B>A I see a pattern that I'm not able to debug because of my limited knowledge in Verilog case/if-else statements. Forgive me if I'm not explaining the best way but what I'm observing is that once the first number, A, "reaches" 0 (after being subtracted from) it loops back to F. The remainder of B is then subtracted from F rather than 0.
For example: If A=1, B=3
A - B =
1 - 1 = 0
0 - 1 = F
F - 1 = E
Another example could be 4-8=C
Below are the important snippets of code I've put together thus far.
First, my subtraction statement
always#*
begin
begin
Cout1 = 7'b1000000; //0
end
case(PrintDifference[3:0])
4'b0000 : Cout0 = 7'b1000000; //0
4'b0001 : Cout0 = 7'b1111001; //1
...
4'b1110 : Cout0 = 7'b0000110; //E
4'b1111 : Cout0 = 7'b0001110; //F
endcase
end
My subtraction is pretty straightforward
output [4:0]Difference;
output [4:0] PrintDifference;
assign PrintDifference = A-B;
I was thinking I could just do something like
if A>=B, Difference = B-A
else, Difference = A-B
Thank you everyone in advance!
This is expected behaviour of twos complement addition / subtraction which I would recommend reading up on since it is so essential.
The result obtained can be changed back into an unsigned form by inverting all the bits and adding one. Checking the most significant bit will tell you if the number is negative or not.
I have a recursive function, as follows, where b >= 0
def multiply(a,b):
if b == 0:
return 0
elif b % 2 == 0:
return multiply(2*a, b/2)
else:
return a + multiply(a, b-1)
I would like to know how many times the function will run in terms of a and b.
Thanks.
If binary representation of b (call it B) ends with 1, like xxxx1 than next call to multiply has B = xxxx0.
If B ends with 0, like xxxx0 than next value of B is xxxx.
With that, digit of binary representation of b adds one call if it is 0, and two calls if it is 1. Summing that total number of calls equals to length of initial B + number of ones in initial B.
I might be wrong here, but I think your function does not work the way you intend it. In recursion the most important thing as a propper ending criteria, since it will run forever elseways.
Now your ending criteria is a==0, but with each recursive call you do not decrease a. Just make a pen & paper simulation with a=5 and check if it would stop at any point.
I am trying to write a recursive function that will return true if second number is power of first number.
For example:
find_power 3 9 will return true
find_power 2 9 will return false because the power of 2 is 8 not 9
This is what I have tried but I need a recursive solution
let rec find_power first second =
if (second mod first = 0)
return true
else
false ;;
A recursive function has the following rough form
let rec myfun a b =
if answer is obvious then
obvious_answer
else
let (a', b') = smaller_example_of_same_problem a b in
myfun a' b'
In your case, I'd say the answer is obvious if the second number is not a multiple of the first or if it's 1. That is essentially all your code is doing now, it's testing the obvious part. (Except you're not handling the 0th power, i.e., 1.)
So, you need to figure out how to make a smaller example of the same problem. You know (by hypothesis) that the second number is a multiple of the first one. And you know that x * a is a power of a if and only if x is a power of a. Since x is smaller than x * a, this is a smaller example of the same problem.
This approach doesn't work particularly well in some edge cases, like when the first number is 1 (since x is not smaller than x * 1). You can probably handle them separately.
I'm new to prolog. I'm doing a recursive program the problem is that even though it prints the answer.. it doesn't stop after printing the answer and eventually gives "Out of local stack".
I've read it could be a left recursion issue but as I've already told you I'm new to prolog and I don't really understand what happens...
so.. here's code.
f(X, Y):-
Y is sqrt(1-((X-1)*(X-1))).
sum(SEGMENTS, 1, TOTAL):-
f(2/SEGMENTS*1,H1),
TOTAL is (2/SEGMENTS)*H1.
sum(SEGMENTS, NR, TOTAL):-
N1 is (NR-1),
sum(SEGMENTS, N1, S1),
f(2/SEGMENTS*NR,H1),
f(2/SEGMENTS*N1,H2),
TOTAL is S1 + (2/SEGMENTS)*((H1+H2)/2).
It's supposed to calculate a semicircle area with the trapezoid rule or something similar.
As I've already told you .. it does finishes but after getting to the base case sum(segments, 1, total) it calls the function with the second alternative... :S
Thanks guys!
Also: Here's what I get when I run it
?- sum(3000,3000,TOTAL).
TOTAL = 1.5707983753431007 ;
ERROR: Out of local stack
The problem is that backtracking will attempt the case of NR value of 1 on the second sum clause after the first clause has succeeded. This causes a long recursion process (since NR is being decremented continually for each recursive call, attempting to wrap around through all negative integer values, etc).
A simple way to resolve the problem is in your second sum clause. Since the intention is that it is for the case of NR > 1, put NR > 1 as your first statement:
sum(SEGMENTS, NR, TOTAL) :-
NR > 1,
N1 is (NR-1),
sum(SEGMENTS, N1, S1),
f(2/SEGMENTS*NR,H1),
f(2/SEGMENTS*N1,H2),
TOTAL is S1 + (2/SEGMENTS)*((H1+H2)/2).
Also note that the expression f(2/SEGMENTS*NR, H1) doesn't compute the expression 2/SEGMENTS*NR and pass it to f. It actually passes that expression symbolically. It just happens to work here because f includes it on the right hand side of an is/2 so it is evaluated as desired. If you trace it, you'll see what I mean.