I'm trying to get N ways of solves a N rook problem. The issue I am having is currently, I seem to get n*n solutions while it needs to be N! . Below is my code, I have written it in simple loops and functions, so it's quite long. Any help would be greatly appreciated
Note: Please ignore case for n = 2. I get some duplicates which I thought I would handle via JSON.stringify
var createMatrix = function (n) {
var newMatrix = new Array(n);
// build matrix
for (var i = 0; i < n; i++) {
newMatrix[i] = new Array(n);
}
for (var i = 0; i < n; i++) {
for (var j = 0; j < n; j++) {
newMatrix[i][j] = 0;
}
}
return newMatrix;
};
var newMatrix = createMatrix(n);
// based on rook position, greying out function
var collision = function (i, j) {
var col = i;
var row = j;
while (col < n) {
// set the row (i) to all 'a'
col++;
if (col < n) {
if (newMatrix[col][j] !== 1) {
newMatrix[col][j] = 'x';
}
}
}
while (row < n) {
// set columns (j) to all 'a'
row++;
if (row < n) {
if (newMatrix[i][row] !== 1) {
newMatrix[i][row] = 'x';
}
}
}
if (i > 0) {
col = i;
while (col !== 0) {
col--;
if (newMatrix[col][j] !== 1) {
newMatrix[col][j] = 'x';
}
}
}
if (j > 0) {
row = j;
while (row !== 0) {
row--;
if (newMatrix[i][row] !== 1) {
newMatrix[i][row] = 'x';
}
}
}
};
// checks position with 0 and sets it with Rook
var emptyPositionChecker = function (matrix) {
for (var i = 0; i < matrix.length; i++) {
for (var j = 0; j < matrix.length; j++) {
if (matrix[i][j] === 0) {
matrix[i][j] = 1;
collision(i, j);
return true;
}
}
}
return false;
};
// loop for every position on the board
loop1:
for (var i = 0; i < newMatrix.length; i++) {
var row = newMatrix[i];
for (var j = 0; j < newMatrix.length; j++) {
// pick a position for rook
newMatrix[i][j] = 1;
// grey out collison zones due to the above position
collision(i, j);
var hasEmpty = true;
while (hasEmpty) {
//call empty position checker
if (emptyPositionChecker(newMatrix)) {
continue;
} else {
//else we found a complete matrix, break
hasEmpty = false;
solutionCount++;
// reinitiaze new array to start all over
newMatrix = createMatrix(n);
break;
}
}
}
}
There seem to be two underlying problems.
The first is that several copies of the same position are being found.
If we consider the case of N=3 and we visualise the positions by making the first rook placed red, the second placed green and the third to be placed blue, we get these three boards:
They are identical positions but will count as 3 separate ones in the given Javascript.
For a 3x3 board there are also 2 other positions which have duplicates. The gets the count of unique positions to 9 - 2 - 1 -1 = 5. But we are expecting N! = 6 positions.
This brings us to the second problem which is that some positions are missed. In the case of N=3 this occurs once when i===j==1 - ie the mid point of the board.
This position is reached:
This position is not reached:
So now we have the number of positions that should be found as 9 - 2 - 1 - 1 +1;
There appears to be nothing wrong with the actual Javascript in as much as it is implementing the given algorithm. What is wrong is the algorithm which is both finding and counting duplicates and is missing some positions.
A common way of solving the N Rooks problem is to use a recursive method rather than an iterative one, and indeed iteration might very soon get totally out of hand if it's trying to evaluate every single position on a board of any size.
This question is probably best taken up on one of the other stackexchange sites where algorithms are discussed.
Hello fellow programmers,
I'm trying to build a tower defense-like game in canvas, HTML. I'm currently working on the process of detecting coordinates within a range of a defense. Here's what I have worked out so far:
this.defensesInRangeArcher = 0;
for (var i = 0; i < buildArcherX.length; i++) {
for (var i = 0; i < buildArcherY.length; i++) {
if (Math.sqrt(Math.pow(buildArcherX[i] - this.x, 2) + Math.pow(buildArcherY[i] - this.y, 2)) <= arch.radius + 7) {
this.defensesInRangeArcher += 1;
this.attackByArcher = true;
} else {
this.attackByArcher = false;
}
}
}
So far in the following code, I have made it so that the "Defenses" could detect multiple coordinates within a range. "this" is able to detect the number of "defenses" in range but then arose a problem. Archers shoot one at a time but it affects all of "this" in range of the "defense". However, I don't want that so I was wondering how I could make it shoot one at a time.
I decided to use a global variable shown in the following code but had a bug in it.
this.defensesInRangeArcher = 0;
for (var i = 0; i < buildArcherX.length; i++) {
for (var i = 0; i < buildArcherY.length; i++) {
if (Math.sqrt(Math.pow(buildArcherX[i] - this.x, 2) + Math.pow(buildArcherY[i] - this.y, 2)) <= arch.radius + 7) {
this.defensesInRangeArcher += 1;
if (!v.singleAimArcher && !this.dead) {
this.attackByArcher = true;
v.singleAimArcher = true;
}
} else {
this.attackByArcher = false;
v.singleAimArcher = false;
}
}
}
It worked for the first defense it passed by, however not for the second one it passed by, so on.
I was wondering what kind of solution I could get to solve this.
Thanks!
I've been working on a project for my class and I've completed it theoretically but it has some problems where it does not execute as fast as I'd like. The task is as follows: You have a 10x10 board to make moves on. You go up, down, left or right randomly. If a move takes you off the board skip it. Do this until 1,000,000 steps are taken or you reach the top right of the board. We are also supposed to count the max number of steps that a single tile received and the same with the minimum. I have done this using a 2D array and it counts sometimes and will output however it takes multiple button clicks to get an output. I'm not sure if this is a memory allocation error related to how I am accessing the 2D array to keep track of number of steps or not. I am relatively new to javascript so I don't know if my way was all that efficient.
Code
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Path Game</h1>
<!-- Starts Game -->
<button onclick="doGame()">Click Here to start Game</button>
<p id="MaxSteps"></p>
<p id="MinSteps"></p>
<p id="totalSteps"></p>
<p id="reachedSteps"></p>
<p id="reachedSquare"></p>
<p id="reachedBoth"></p>
<!-- JS -->
<script>
function doGame()
{
var gameBoard = [0,0];
var stepCount = 0;
//10x10 array to hold step counts (may be a better way. check back later)
//Cell counter
var cells = [
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0]
];
while(true)
{
var oneMove = Math.floor(1+(Math.random()*4));
//Conditional checks
//Check if both square and step counts are satisfied
if(gameBoard[0] == 9 && gameBoard[1] == 9 && stepCount == 1000000)
{
document.getElementById("reachedBoth").innerHTML = "Reached 1,000,000 steps and top square";
break;
}
//Reached Top right before 1,000,000 steps
else if(gameBoard[0] == 9 && gameBoard[1] == 9)
{
document.getElementById("reachedSquare").innerHTML = "Reached Top right square";
break;
}
//Reached 1,000,000 steps before top right
else if(stepCount == 1000000)
{
document.getElementById("reachedSteps").innerHTML = "Reached 1,000,000 steps";
break;
}
//Movement on the board
var x = gameBoard[0];
var y = gameBoard[1];
cells[x][y] += 1;
//Move left
if(oneMove == 1)
{
//Initialized at 1 so less than is suitable
if(gameBoard[0] < 0)
{
gameBoard[0] = 0; //Reset
}
else{
gameBoard[0]--;//Goes left
}
}
//Move right
else if(oneMove == 2)
{
//If its at the edge, keep it there or keeps from going over
if(gameBoard[0] >= 9)
{
gameBoard[0] = 9; //Reset
}
else{
gameBoard[0]++;//Goes right
}
}
//Move up
else if(oneMove == 3)
{
//If its at the edge, keep it there or keeps from going over
if(gameBoard[1] >= 9)
{
gameBoard[1] = 9; //Reset
}
else{
gameBoard[1]++;//Goes up
}
}
//Move down
else if(oneMove == 4)
{
//Initialized at 1 so less than is suitable
if(gameBoard[1] < 0)
{
gameBoard[1] = 0; //Reset
}
else{
gameBoard[1]--;//Goes down
}
}
stepCount++; //Count the steps
}
var max = 0;
var min = Infinity;
//Find max
for(var i = 0; i < cells.length;i++)
{
for(var j = 0; j < cells[i].length; j++)
{
if(max < cells[i][j])
{
max = cells[i][j];
}
}
}
//Find min
for(var i = 0; i < cells.length;i++)
{
for(var j = 0; j < cells[i].length; j++)
{
if(min > cells[i][j])
{
min = cells[i][j];
}
}
}
//Total Steps print
document.getElementById("MaxSteps").innerHTML = "Max steps were: " + max;
document.getElementById("MinSteps").innerHTML = "Min steps were: " + min;
document.getElementById("totalSteps").innerHTML = "Total steps were: " + stepCount;
}
</script>
</body>
</html>
This block is the one that strikes me as particularly inefficient:
if(oneMove == 1)
{
//Initialized at 1 so less than is suitable
if(gameBoard[0] < 1)
{
gameBoard[0] = 1; //Reset
}
else{
gameBoard[0]--;//Goes left
}
}
//Move right
else if(oneMove == 2)
{
//If its at the edge, keep it there or keeps from going over
if(gameBoard[0] >= 10)
{
gameBoard[0] = 10; //Reset
}
else{
gameBoard[0]++;//Goes right
}
}
//Move up
else if(oneMove == 3)
{
//If its at the edge, keep it there or keeps from going over
if(gameBoard[1] >= 10)
{
gameBoard[1] = 10; //Reset
}
else{
gameBoard[1]++;//Goes up
}
}
//Move down
else if(oneMove == 4)
{
//Initialized at 1 so less than is suitable
if(gameBoard[1] < 1)
{
gameBoard[1] = 1; //Reset
}
else{
gameBoard[1]--;//Goes down
}
}
This is for a class, so I won't offer you an answer directly, but can you think of a solution that instead of incrementing or decrementing your gameboard counters directly using the random value that was generated?
For example, if I had a simple 1-dimension gameboard like so:
var gameboard = [0,0,0];
var position = 0,
direction = 0;
function move() {
direction = Math.round(Math.random()) * 2 - 1;
position += direction;
}
The only thing that is missing is to account for the possibility that I have moved off the gameboard. If the requirement were to start your marker on the other side of the board (think PacMan), this could also be accomplished using the modulo operator, which in JS is %:
function move() {
direction = Math.round(Math.random()) * 2 - 1;
position += direction;
position = (position + 3) % 3;
}
Unfortunately, given your requirements, I don't see a way around if conditions to stay on the board:
position = position < 0 ? 0 : position;
position = position > 2 ? 2 : position;
Hopefully this should get you going in the right direction. The above three lines of code could actually be combined into one line, though I prefer to make them a bit more readable.
A few more notes:
Storing your x and y positions in a two-element array called
gameBoard is just confusing. Just call them x and y (as you do at the
end of your code).
Though the requirements don't call for it, try
generating the game board and performing all math so that instead of
10 elements, the game could be changed to n elements by changing only
one value in your code. It's good to have the smallest set of
controls as possible.
Good luck with your class!
I coded quite rough code but it works, but I though I should learn better way to do it next time, so I need help to get this code more proper.
The purpose of this code is image slider.
Image of the slider
I would like to have animation from right to left when the button is pressed, but I'm kinda out of ideas how to do it. There's total 4 images on the slider. It will only show 3 at a time, and it will rotate them on proper order, but I haven't figured how to add animation that would hide the first image as the rest images "appear" from the right side.
Javascript
function rullaaVasen(j) {
var divit = $("#portfolio").find("div").toArray();
//a , b, c - using them to switch classes which have different background images
if(j == 1) {
a = 2;
b = 3;
c = 4;
i = 2;
v = 4;
} else if(j == 2) {
a = 3;
b = 4;
c = 1;
i = 3;
v = 3;
} else if(j == 3) {
a = 4;
b = 1;
c = 2;
i = 4;
v = 2;
} else if(j == 4) {
a = 1;
b = 2;
c = 3;
i = 1;
v = 1;
}
$(divit[0]).attr("class","sivu1 kuva" + a);
$(divit[1]).attr("class","sivu2 kuva" + b);
$(divit[2]).attr("class","sivu3 kuva" + c);
$("#vasenNappi").attr('onClick', 'rullaaVasen('+i+');');
$("#oikeaNappi").attr('onClick', 'rullaaOikea('+v+');');
}
Html
<div id="slideri">
<div id="vasenNappi" onClick="rullaaVasen(1);"></div>
<div id="portfolio">
<div class="sivu1 kuva1"></div>
<div class="sivu2 kuva2"></div>
<div class="sivu3 kuva3"></div>
</div>
<div id="oikeaNappi" onClick="rullaaOikea(1);"></div>
Thanks in advance for any answers!
Try this code.
//increment a based on j. Since 5 is the limit if a is 5 it is reset to 1.
a = (j+1)==5?1:(j+1);
//increment b based on a. Since 5 is the limit if b is 5 it is reset to 1.
b = (a+1)==5?1:(a+1);
//increment c based on b. Since 5 is the limit if c is 5 it is reset to 1.
c = (b+1)==5?1:(b+1);
//i is same as a.
i = a;
//v is based on j
v = 5-j;
From what I understand from your code is that you were doing a change of variables a, b, c, i and v within 1-5 based on value of j.
here is a js fiddle http://jsfiddle.net/7HX2C/1/ of a "slider".
also pasted the jsfiddle below.
//usage
var slider = new slider();
slider.slide(0); //slides to index 0 and shows 1,2,3 of 1,2,3,4
slider.next(); //goes to index 1 and shows 2,3,4 of 1,2,3,4 one more would show 3,4,1
slider.prev(); //goes back to index 0 and shows 1,2,3 of 1,2,3,4 one more would show 4,1,2
//slider
function slider() {
var self = this;
self.div = $("div");
self.items = [1, 2, 3, 4]; //an array of the items to slide
self.currentIndex = 0; //which one you are currently looking at
self.displayAmount = 3; //how many items to display
self.currentItems = []; //an array of the items to show out of items array
self.slide = function (j) {
self.currentItems = [];
self.currentIndex = j;
//start looping from current index, loop as long as i is less than the items we have and current items to show is less than the display amount
for (var i = self.currentIndex; i < self.items.length && self.currentItems.length < self.displayAmount; i++) {
self.currentItems.push(self.items[i]);
}
//if current items isn't hitting our display amount
if (self.currentItems.length < self.displayAmount) {
//calculate how many we need to add
var amountToAdd = self.displayAmount - self.currentItems.length;
//loop through starting from 0 and add the amount missing as long as current items never gets longer than the items we have
for (var i = 0; i < amountToAdd && self.currentItems.length < self.items.length; i++) {
self.currentItems.push(self.items[i]);
}
}
};
self.next = function () {
var slideTo = self.currentIndex + 1;
if (slideTo > self.items.length) {
slideTo = 0;
}
self.slide(slideTo);
};
self.prev = function () {
var slideTo = self.currentIndex - 1;
if (slideTo < 0) {
slideTo = self.items.length - 1;
}
self.slide(slideTo);
};
self.showInfo = function() {
self.div.html(self.currentItems.toString() + " of " + self.items.toString() + " is displayed");
}
}
I'm trying to create a simple memory matching game and I'm having trouble assigning one number to each table cell from my cardValues array. My giveCellValue function is supposed to generate a random number then pick that number from the array and give it to one of the table cells but I'm a little over my head on this one and having trouble accomplishing this task.
var countCells;
var cardValues = [];
var checker = true;
var createTable = function (col, row) {
$('table').empty();
for (i = 1; i <= col; i++) {
$('table').append($('<tr>'));
}
for (j = 1; j <= row; j++) {
$('tr').append($('<td>'));
}
countCells = row * col;
};
createTable(3, 6);
for (i = 1; i <= countCells / 2; i++) {
cardValues.push(i);
if (i === countCells / 2 && checker) {
checker = false;
i = 0;
}
}
var giveCellValue = function () {
var random = Math.ceil(Math.random() * cardValues.length) - 1;
for (i = 0; i <= cardValues.length; i++) {
$('td').append(cardValues[random]);
cardValues.splice(random, 1);
}
};
giveCellValue();
console.log(cardValues);
Use
var countCells;
var cardValues = [];
var checker = true;
var createTable = function (col, row) {
$('table').empty();
for (var i = 0; i < col; i++) {
$('table').append($('<tr>'));
}
for (var j = 0; j < row; j++) {
$('tr').append($('<td>'));
}
countCells = row * col;
};
createTable(3, 6);
for (i = 0; i < countCells; i++) {
cardValues.push(i % 9 + 1);
}
var giveCellValue = function () {
var len = cardValues.length, tds = $('td');
for (var i = 0; i < len; i++) {
var random = Math.floor(Math.random() * cardValues.length);
tds.eq(i).append(cardValues.splice(random, 1));
}
};
giveCellValue();
console.log(cardValues);
Demo: Fiddle
Leaving aside the problems that have already been mentioned in the comments above...
If I understand it right, you want to assign each of the numbers in cardValues to a random table cell?
Seems like the problem is with this line:
var random = Math.ceil(Math.random() * cardValues.length) - 1;
What this does is generates a random number once. If you access the variable random at a later time, you're not calling the full line of code again, you're just getting the same value that was calculated the first time. E.g. if the above code runs, spits out '7' as its random number and stores that in random, then every time you go through the for loop, the value of random will always be '7' rather than being re-generated every time - make sense?
Try putting the randomiser inside the for loop - that way it will be run multiple times, generating a new random number every time:
var giveCellValue = function () {
var random;
for (i = 0; i <= cardValues.length; i++) {
random = Math.ceil(Math.random() * cardValues.length) - 1;
$('td').append(cardValues[random]);
cardValues.splice(random, 1);
}
};
Actually, I'd change line 4 above to random = Math.floor(Math.random() * cardValues.length); too which should have the same effect.