Knight's tour using backtracking - recursion

I have been given some initialisation code and told to write a function knight(n,y,x) to print a solution to the problem.
This initialisation code is
size = 8
board = []
for y in range(size) :
board = board + [[-1]*size]
moves= [[1,2],[1,-2],[-1,2],[-1,-2],
[2,1],[2,-1],[-2,1],[-2,-1]]
And my code so far, which just seems to run forever is
def knight(n,y,x):
if n == 0:
board[y][x] = 0
n = 1
elif n == (size**2) :
return board
for j,i in moves:
y1 = y+j
x1 = x+i
if y1 < size and x1 < size and y1>=0 and x1>=0 and board[y1][x1] == -1:
board[y1][x1] = n
knight(n+1,y1,x1)
board[y1][x1] = -1
return
But I can't figure why it is a problem. I have looked through a few of the existing questions on here but they use multiple functions where we have been told to just use the one. Could anybody please help?

I have found a problem in your code, which fixes it for everything up to 7x7 boards. I assume it works on 8x8, it just takes exponentially longer. You might have to implement some algorithm improvements to get it to be quicker. Anyway the error I found was:
You ARE finding the board, but you only return it one frame back. You need to set it up so that, if a board is found, the code returns it all the way back.
Try replace the following line:
knight(n+1,y1,x1)
with the following:
sol = knight(n+1,y1,x1)
if sol is not None:
return sol
I'll have a go at trying to get an answer from the 8x8, and update this if I can help any more.

Related

Why does my custom Binomial Function give me an $Inf$ in return?

So for the statistical computing class I'm in, one of the questions from a recent lecture featured this code:
nchoosek = 1 #initialize at 1
n = 200
k = 100
for (i in 1:(n-k)){
nchoosek = nchoosek*(k+i)/i }
nchoosek
The reason I'm posting is I was just playing around with this little bit of code and when n = k it will give you Inf in return. Why am I getting this value? Thanks.
When n == k the for loop runs through the values 1:0 which is c(1,0) which is not what you want. Put in an if statement which skips the for loop if k>=n and it should work.

Which python code will be included in the Dask graph

Which python code written in the client side of #dask is really added to the task graph?
In this script for example, I am reading an hdf5 dataset of 4 dim, using a loop for the fourth dimension.
I calculate the sum for each dim called here g for generation and subtract the result of this generation and the one before it.
Then i am calling the deriv.visualize() to see how it generates the graph.
alive = []
derivate = []
board = []
deriv = 0
rest_1 = 0
hf5 = h5py.File('Datata.h5', 'r')
hds5 = hf5.get('dataset')
list(hf5.keys())
last_gen = hds5.attrs.get('last_gen')
for g in range(0,generations):
board = hds5[g]
arr = da.asarray(board, chunks=(4,5,4))
res = arr.sum()
if g!=0 :
deriv = res - rest_1
rest_1 = res
deriv.visualize()
Here is the graph i am getting
Here without calling .compute() the subtract operator is added to the dask graph apparently, how do we explain this ?
If i add a .compute() in the "res = arr.sum().compute()" and keep the rest as it is, where the subtraction will be executed ? in the client side or in one of the workers ?
An other question which is more general, if i wanna keep the partial sums in the workers, and perform the subtraction (on partial sum of the current and last generation) in the workers, is there a way to say that i want theses operations to be performed on the same chunks over different generations? (for example the worker 0 will operate always on the 3 first rows of each generation, like in mpi even if it's not the same thing at all)?
Dask does not look at your Python code, and so can not see anything other than what you give to it. In this case it is these two lines:
arr = da.asarray(x, chunks=(4,5,4))
res = arr.sum().compute()

Using increments in a for loop

I am trying to run a for loop in Julia using bounds for integration where fI and r are arrays of the same length. I know this is incorrect, but this is the gist of what I want to do.
a = zeros(1:length(fI))
for i = 1:length(fI)
a[i] = (fI[i+1] - fI[i])/(r[i+1] - r[i])
end
How can I set increments of n+1 in Julia? Haven't had any luck finding the answer elsewhere.
Just let me know if I can clarify anything. I'm still pretty new to the language.
Ranges are specified by start:stepsize:end. Thus the answer is for i = 1:(n+1):length(fI).
I am not completely sure what you want to do, but it looks as you want to create a new variable based on the difference between elements in the other variables. If that is your use case, you can use diff, e.g.
fI, r = rand(10), rand(10)
a = diff(fI) ./ diff(r)
Your code will crash since for the last "i" you access beyond the array length
fI[i+1] = fI[length(fI)+1]
a = zeros(1:length(fI))
for i = 1:length(fI)
a[i] = (fI[i+1] - fI[i])/(r[i+1] - r[i])
end
Maybe you intend the following
n = length(fI) - 1
a = zeros(1:n)
for i = 1:n
a[i] = (fI[i+1] - fI[i])/(r[i+1] - r[i])
end

Reactive programming: how to get a moving average using Reactive.jl

I am wanting to have a signal / function that outputs the moving average of x periods. I have come up with two approaches, both of which work, but I believe the second is more properly reactive. Does anyone know of a better method?
Method 1
#time (
x = Signal(100);
col = foldp(Int[], x) do acc, val
push!(acc, val)
end;
for i in rand(90:110, 100)
push!(x, i)
end;
)
This code executes for me in 0.102663 seconds and can easily yield an average over the last 100 signals: mean(value(col))
Method 2
#time (
a = Signal(100);
sar = Vector{Signal}(101);
sar[1] = a;
for i in 1:100
sar[i+1] = previous(sar[i])
end;
for i in rand(90:110, 100)
push!(a, i)
end;
)
This code executes for me in 0.034911 seconds and can also easily yeild an average of the last 100 signals:
sarval = map(value, sar)
mean(sarval[2:end])`
Neither method above directly provides an output signal; here is Method 1 applied to create a moving average of specified length as a continuing signal:
Method 1 Applied
x = Signal(initial_value)
col = foldp(Float64[], x) do acc, elem
push!(acc, elem)
end
macro moving_average(per, collec)
quote
map($collec) do arr
length(arr) < $per ? mean(arr) : mean(arr[(end-$per+1):end])
end
end
end
ma_period = #moving_average(period_length, col)
This code uses the first method to generate a signal of arrays of all past signals, the length of which increases linearly with the number of signals. For signals that update thousands of times, this seems unwieldy (at best). This does not seem ideal, and I am looking for some ideas for a better approach. Not sure how to take Method 2 and turn it into a signal output, and not sure if it is the best approach I could take.
Also related question: there is a nice built in function previous(signal) that provides a signal lagging 1 update behind signal. Is there a way to specify a signsl that legs a specified, arbitrary number of updates behind signal?

Completely stumped about this error: Error in seq.default(start.at, NROW(data), by = by) : wrong sign in 'by' argument

When I run this code, it works for about 100 iterations of the for loop then throws this error:Error in seq.default(start.at, NROW(data), by = by) :
wrong sign in 'by' argument
Here is the data that I used, and here is my code...
library(igraph)
library(zoo)
#import network data as edgelist
fake.raw.data <- read.csv("fakedata.csv")
fake.raw.data <- fake.raw.data[,2:3]
as.matrix(fake.raw.data)
#create igraph object from edglist data
fgraph <- graph_from_data_frame(fake.raw.data, directed = TRUE)
#finding the shortest paths that go through "special chain"
POI <- list()
df.vertices <- get.data.frame(fgraph, what = "vertices")
list.vertices <- as.list(df.vertices[,1])
AverageEBForPath <- function(graph = fgraph, from, to, mode = "out", chain){
browser()
asp <- all_shortest_paths(graph, from = from, to = to, mode)$res
for(i in seq_along(asp)){
if(sum(rollapply(names(asp[[i]]), length(chain), identical, chain)) == 1){
print(names(asp[[i]]))
}
}
}
AverageEBForPath(from = 32, to = V(fgraph), chain = c(32, 15, 9))
If anybody could help that would be extremely appreciated. I have been working on this for days, and I am really stuck.
Looking through the code of rollapply, there's a bit where it works out where in the array to start the rolling. The code it uses is:
start.at <- if (partial < 0)
max(-min(width[[1]]), 0) + 1
else 1
Note that in the function itself, width is a list generated from the window width that you're trying to use and the alignment you want... Given that you're passing a window width of 3 and a default alignment of "centre", the width list the function has generated for the code above is a list of three integers: [-1, 0, 1]
Which means that, using the code above, it has decided that given you're after a centre aligned window of width 3, the place to start is the second value in the data (because max(-min(width[[1]]),0) + 1 in the above code evaluates to 2).
All very reasonable, but whilst all of the rest of the instances of asp[[i]] have either 2 or 3 vertices, asp[[100]] has only one vertex (as you rightly pointed out) - so it throws a bit of fit trying to find the second one in order to start rolling through it!
I'm not entirely sure what your function is eventually going to do, so the ball's a bit in your court to work out how best to handle this, I think you've got two options given what you're seeing:
Option 1
Use the partial = TRUE setting on your rollapply, which will just always start at the first vertex no matter what (see the code snippet above!)
Option 2
Use align="left" in your rollapply. In this case, the width list we saw in the rollapply function itself would be [0, 1, 2] for a window width of 3 and start.at would evaluate to 1.
Hope that rambling and convoluted attempt at an answer helps!

Resources