Find all combinations of Chess game [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am making a program that is calculating the number of possible solutions of a chess game with only bishops and queens. The user can put in the maximal number of queens and bishops, as well as the size of the chess board.
I will call any set of positions for the bishops and the queens on the board a combination. A combination counts as a solution if all squares are attacked.
So for example, if the user wants to calculate the possible number of solutions with 2 queens and 1 bishop on a 3x3 chess board, two of the solutions could be:
B-- ---
-Q- -Q-
--- ---
And if the user chooses 9 queens instead of 2:
QQQ BQQ
QQQ QQQ
QQQ QQQ
I have managed to create an algorithm to check if a combination is a valid solution. The problem I got is the algorithm to find all the possible combinations there is. So what I need is an algorithm that loops through all possible combinations, and for each one check if the combination is a valid solution. I think a recursive solution would be the best for this.

There might be some smart way to solve this much faster, but I will sketch how to do a brute force using recursion. If you have a board with n squares in total, and your solution checking algorithm runs in F(n), this solution will be O(F(n)*3^n) - not very fast for larger boards in other words.
For a normal 8 by 8 chess board with many pieces this might be completely useless, since you run into the wheat and chessboard problem, only worse since your solution checker is expensive and it grows by the power of 3, not the power of 2. If you have fewer pieces, the problem is somewhat mitigated by the fact that you can stop branching once all the pieces are placed.
I will assume your solution checking function is named cheack_solution that takes a two dimensional array with the board, and returns a boolean (true if the board is a solution, otherwise false).
//Just to start it off.
int count_solutions(max_queens, max_bishops, a, b) {
int[][] board= new int[a][b];
return recurse(board, 0, a*b, max_queens, max_bishops, 0, 0);
}
//This is where the actual work is done.
//board is the board so far, represented by a two dimensional array where
// -1 = Queen
// 0 = Empty
// 1 = Bishop
//i is the square we are currently on, and n is the total number of board.
//max_queens and max_bishops are the maximum allowed to place.
//queens and bishops are the number placed so far.
int recurse(board, i, n, max_queens, max_bishops, queens, bishops) {
if(i == n || (max_queens == queens && max_bishops == bishops)) {
//If we have placed all the pieces, it is time to check if it is a solution.
//Return one if it is, otherwise zero.
return (int) sheck_solution(board);
}
//We havent placed all the pieces yet. Time to do some recursion.
//Get the two dimensional x and y coordinates for the one dimensional coordinate i.
x = i / board.length;
y = i % board.length);
//Number of solutions = the sum of number of solutions for the alternatives.
int solutions = 0;
//Place a queen in the current spot.
if(queens < max_queens) {
board[x][y] = -1;
solutions += recurse(board, i+1, n, max_queens, max_bishops, queens + 1, bishops);
}
//Place a bishop in the current spot.
if(bishops < max_bishops) {
board[x][y] = 1;
solutions += recurse(board, i+1, n, max_queens, max_bishops, queens, bishops + 1);
}
//Place nothing in the current spot.
board[x][y] = 0;
solutions += recurse(board, i+1, n, max_queens, max_bishops, queens, bishops);
return solutions;
}
I have not tried this, and my Java is a bit rusty, so don't expect this to run at the first try. You will need some debugging. I think the logic behind it should be allright, though.
EDIT: As requested in comments, I will try to explain why this works. You can imagine all possible board states as a tree. First there are three branches, one for each alternative (queen, bishop, empty) for the first square. Each of those three branches has three branches for the second square, and each of those three branches has three branches for the third square and so on.
The recursion traverse all these branches, since every time the function is called it calls itself three times. However the two if statements limits the traversion so that when the maximum number for a type of piece is reached, it does not try to place more of that piece.
So why do we need to put the "leave empty" option last of the three options? That is because all the function calls uses the same board array. It is not copied. Therefore when the function exit it must leave the board in the same state as it recieved it. Since there was nothing in square i when the function was called, there should be nothing in square i when the function returns.

Related

Understanding a particular solution to 'Minimum Swaps to Group All 1's Together 2nd' problem

I am looking at the LeetCode problem 2134. Minimum Swaps to Group All 1's Together II:
A swap is defined as taking two distinct positions in an array and swapping the values in them.
A circular array is defined as an array where we consider the first element and the last element to be adjacent.
Given a binary circular array nums, return the minimum number of swaps required to group all 1's present in the array together at any location.
I am trying to study how other people came up with solutions of their own. I came across this particular one, but I don't understand the logic:
class Solution {
public int minSwaps(int[] nums) {
// number of ones
int cntones=Arrays.stream(nums).sum();
// worst case answer
int rslt=nums.length;
// position lft and figure better value for min/rslt
int holes = 0;
for(int i=0;i<cntones;i++) {
if(nums[i]==0)
holes++;
}
// better value for rslt from lft to rgt
// up to index of cntones.
rslt = Math.min(rslt, holes);
// they have a test case with one element
// and that trips up if you dont do modulo
int rgt=cntones % nums.length;
for(int lft=0;lft<nums.length;lft++) {
rslt=Math.min(rslt,holes);
if(nums[lft]!=nums[rgt])
if(nums[rgt]==1)
holes--;
else
holes++;
rgt=(rgt+1)%nums.length;
}
return rslt;
}
}
Why is the worst case, the length of the input array?
I'm thinking wait, wouldn't the worst case be something like [0,1,0,1,0,1...] where 0's and 1's are alternating? Can you give me an example?
I suppose #of holes can potentially be a possible solution in some cases, from counting 0's in a fixed length (the number of total 1's) of a window but because I do not understand the worst case, rslt from question #1, below line stumps me as well.
// better value for rslt from lft to rgt
// up to index of cntones.
rslt = Math.min(rslt, holes);
About the modulo below, I don't think cntones can ever be bigger than nums.length, in turn which will result in 0 all the time? I'm thinking for the case with one element, you'd have to check whether that one element is 0 or 1. How does below line cover that edge case?
// they have a test case with one element
// and that trips up if you dont do modulo
int rgt=cntones % nums.length;
Due to #1~#3 the last for loop makes no sense to me...
Why is the worst case, the length of the input array?
First note that a swap is only useful when it swaps a 0 with 1. Secondly, it makes no sense to swap the same digit a second time, as the result of such double swap could have been achieved with a single swap. So we can say that an upper limit for the number of swaps is the number of 0-digits or number of 1-digits (which ever is the least). In fact, this is an overestimation, because at least one 1-digit should be able to stay unmoved. But let's ignore that for now. To reach that worst case, there should be as many 1 as 0 digits, so then we have half of the length as worst case. Of course, by initialising with a value that is greater than that (like the length) we do no harm.
The example of alternating digits would be resolved by keeping half of those 1-digits unmoved, and moving the remaining 1-digits in the holes between them. So that means we have a number of swaps that is equal to about one fourth of the length of the array.
below line stumps me as well.
rslt = Math.min(rslt, holes);
As you said, there is a window moving over the circular array, which represents the final situation where all 1-digits should end up. So it sets the target to work towards. Obviously, the 1-digits that are already within that window don't need to be swapped. Each 0-digit inside that window has to be swapped with a 1-digit that is currently outside that window. Doing that will reach the target, and so the number of swaps for reaching that particular target window is equal to the number of holes (0-digits) inside that window.
As that exercise is done for each possible window, we are interested to find the best position of the window, i.e. the one where the number of holes (swaps) is minimised. That is what this line of code is doing. rslt is the minimum "so far" and holes is the fresh value we have for the current window. If that is less, then rslt should be updated to it. That's what happens in this statement.
About the modulo below, I don't think cntones can ever be bigger than nums.length, in turn which will result in 0 all the time? I'm thinking for the case with one element, you'd have to check whether that one element is 0 or 1. How does below line cover that edge case?
int rgt=cntones % nums.length;
That modulo only serves for the case that cntones is equal to nums.length. You are right that it will never exceed it. But the case where it is equal is possible (when the input only has 1-digits). And as rgt is going to be used as an index, it should not be equal to nums.length as that is an undefined slot in the array.
Due to #1~#3 the last for loop makes no sense to me...
It should be clear from the above details. That loop moves the window with one step at a time, and keeps the variable holes updated incrementally. Of course, we could have decided to count the number of holes from scratch in each window, but that would be a waste of time. As we go from one window to the next, we only lose one digit on the left and gain one on the right, so we can just update holes with that information and know how many holes there are in the current window -- the one that starts at lft and runs (circular) to rgt. In case the digit that we lose at the left is the same as the one we gain at the right, we obviously didn't change the number of holes. Where they are different, we either win or lose one hole in comparison with the previous window.

Displaying Numbers in Certain Shapes

I just thought of this problem 15 minutes ago and even though it appears insanely easy I'm having a serious problem coming up with an answer.
Basically what I would like to do is based on a number (n) given by the user, I would like to draw a square shape.
Example: let's say the user gives the number 2, the result should be:
12
43
Now, suppose the user gives the number 3, the result should be:
123
894
765
etc..
Please don't give me the solution to this problem, I just want a clue or two to get me going.
I thought about doing it with a simple java class but I'm still struggling to get past the first condition:
public class DrawSquareWithNumbers {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter your number: ");
int number = scanner.nextInt();
for (int i = 0; i <= number; i++) {
if (i<number)
System.out.print(i);
if (i>=number) {
System.out.println("\n"+i);
}
}
}
}
Any tip? Thanks in advance.
So I think I just put way too much time in this but it's a fun challenge so I thought let's give it a go.
I implented a code version for this solution and it works quite well although it's probably not the cleanest as I approached the whole problem backwards.
Here is my solution to try out online (note it's severely unoptimized and by no ways good Java code. It's a quick and dirty implementation to be honest):
https://ideone.com/97JB7Y
So the idea is quite simple: We first calculate the correct value for each position in a matrix and then we print that matrix out.
Let's go over it in a bit more detail:
We start of by creating the Matrix for our values to print:
With a given size n this is
int[][] values = new int[n][n];
Now we want to calculate the correct value at each point. I chose to tackle it the "wrong way" around by not starting at the first point but at the center of the spiral.
Basically imagine this matrix with n = 3:
[1][2][3]
[8][9][4]
[7][6][5]
Instead of at 1 I just start at 9. Reasoning for this is that it's actually easier to calculate the position spiraling out from a point over spiraling in to a point.
So starting at this center point we spiral out from there in a circular fashion. For the matrix
[1][2]
[4][3]
this means we visit 4 -> 3 -> 2 -> 1. And then just save the correct value in the matrix.
Only problem with my approach is that for a matrix with uneven size (3, 5, 7, etc.) I still visit the points in spiraling order, for 3x3 the order of visiting is e.g. 9 -> 4 -> 3 -> 2 -> 1 -> 8 -> 7 -> 6 -> 5, as visualized in this perfect picture I totally drew in Paint:
This leads to the result matrix being inversed as such:
[5][6][7]
[4][9][8]
[3][2][1]
This small problem is easily fixed though by simply printing the matrix out inversed once more should n%2 != 0.
Hope I could help with maybe a different approach to the problem.
I think you want to make nxn matrix with user entered number. So you can check the input and then you can use loop as for(i=1; i<=n; i++) for rows and similarly for column(for j=0;j<=n;j++) and then you can print your desired shape. Since you have asked to give you idea only so I am not posting any code here. If in case you get stuck somewhere you can refer : https://www.google.com/amp/s/www.geeksforgeeks.org/print-a-given-matrix-in-spiral-form/amp/
Ok, let's give this a try. First let's assume you'll have to store the matrix before printing it and that there's no magic formula that allows you to print what you need in a single iteration.
Now, you've the NxN matrix, for example for 3 it'd be 3x3, 9 positions. Instead of solving it with a series of ifs in an ugly way, you could use direction vectors for a cleaner solution. Also assume for now that you've another NxN matrix filled with booleans, all set to false, that will represent the already printed positions in the NxN matrix that you will print in the end. When you write a number in the final NxN matrix, you put the same position's boolean to true in the boolean matrix.
So for example, you want to print the positions of the first row, 1 2 3. You are displacing to the right to print. This'd be the direction (1,0), aka the starting direction vector. You advance through the NxN matrix using this coordinates. When you go outside the matrix (in the example, your x position is 3) you decrease your x position by one and you "spin" your direction vector (this should be done in a separate function). (1,0) would spin to (0,-1). You keep using this vector to iterate your matrix, spinning as necesary. After the first whole circle, you will get to an already printed position before going outside the matrix. So after every print you've to check not only if you go outside the matrix, but also if that position has already a number on it. For this, you use the boolean matrix.
This is how I'd solve it, there are probably many other ways (and better ones). For starters you could use null, or a mark, in the final matrix and save yourself the booleans one.
Create the result matrix beforehand, and declare a variable for the current number, starting value = 1, the current co-ordinates, starting with (0,0), the stepping direction starting with "to the right"
Start loop
Calculate the co-ordinates of next step, and check it
If it is off the matrix, then change direction, and re calculate, re-check
If free, then put the number in the matrix, increment it, and loop
If it is not free, then end loop, print out result matrix

getting the random number generator to remove a choice once the selection has been made? JAVA

I just wanted to start by saying that I have been searching though this (and a few other) site for the last 3 hours to no avail, i have read every post i could find in regards to my topic and either it did not apply or i couldn't quite understand what was happening.
I'm having 2 issues.
I can't seem to get the random number generator to discard a choice once it has been made.
My second issue is that there can only be one six point round per competition, and i cant seem to figure out how to limit it only to one with the specific constraints of a 6 point round.
The program is designed to simulate picking the jumps for a
skydiving competition. There are three separate competitions
(A,AA,AAA) (levels of difficulty, certain moves do not appear A or
AA, AAA is all inclusive) that the user can pick from as well as
whether the individual competition will be 6 or 10 rounds (A will
always be 6 rounds). Once the user has picked the competition and
number of rounds, the program is supposed to output the individual
moves to be completed for each round as well as the points for the
round (does this for all 6 or 10 rounds of the competition). Here is
where my first issue lies:
Once a move is picked, it cannot be
used again for the rest of the competition. I cannot for the
life of me figure out how to do this.
Moving on, there are two
separate categories for scoring, the numbered moves (1-22 in my
program) and the lettered moves (23 and up), the numbered are worth
2 points and the lettered are worth 1. each round is 5 or 6 points
The issue i am having with this is for there to be a 6 point round, it can only be made up of 3 numbered moves, no other
combination would be acceptable; and to add to that, there can only
be one six point round in the entirety of the competition.*
for(int i=0; i < round; i++ )
{
System.out.printf("\nRound %d:\n", i+1);
point = 0;
while(point < 5)
{
pickedRandom=false;
formation = myRandom.nextInt(38) + 1;
while(formation == 31)
{
formation = myRandom.nextInt(38) + 1;
}
if(point == 4 && pickedRandom && formation < 23 )
{
while(formation < 23)
formation = myRandom.nextInt(38) + 1;
}
if(formation < 23)
{
point+=2;
}
else
{
pickedRandom=true;
point++;
}
formationRound.set( formation, true );
if(formation > 22)
System.out.printf(" %s %s ",randomLetter(formation), formationName(formation));
else
System.out.printf(" %d %s", formation, formationName(formation));
}
System.out.println();
System.out.printf( " %s \n", point );
}
}
I don't understand your question due to formatting, your problem domain, or your code.
However I think you state you want to randomize some numbers, without replacements.
Some strategies to do so are:
Create a list of numbers, then shuffle it, pop a number off each time you need a random number, until your 'deck' is empty.
Maintain a set of numbers that have already been drawn. if the number is in the set, randomize another.
The lazy/brute force method of matching the 6 point round constraint would be to build your formations + competition in advance, in it's entirety. Check to see if it matches your constraints, if not, regenerate the whole competition.
This is only really economical in terms of performance if the chances of your constraints being invalid are fairly low. < 30-40%
Otherwise, you could regenerate only the current formation, but you would need to check that there are still possible valid formations remaining. I'm also not sure how badly this would affect your distribution of random formations.

Java: How to check if a generated level is possible?

I've created a text based game which automatically generates a map with 10x10 rooms, a few of the rooms are blocked by various debris and I couldn't work out the most efficient way to check if a player can still reach a key and get to the exit without them being cut off from the map.
Currently there's a low chance needed rooms are cut off from the rest of the map, making the level impossible, I thought about checking each adjacent square to the start position, and then repeat and repeat until all of the squares that are accessible are set to 'accessible' in a variable and then if the three objects aren't reachable just regen'ing the map again until they are.
This may be slow if it regens a few times though.
Does anyone have any thoughts on the repetitive part to keep it fast, or a better way of achieving this?
Here's an image of a generated map: #'s are blocked rooms.
http://postimg.org/image/8oo88jxgb/
You can use the Dijkstra's algorithm, or some other pathfinding algorithm, to check if there is a way from the room entrance to each object and then discard the invalid rooms. This would probably be a bit slow though, specially if the rooms get bigger or you add more objects.
A better option would be to guarantee by construction that each part of the room can be reached. This can be achieved using Binary Space Partioning (BSP). It can be used to create random dungeons while assuring that all the rooms are connected. You can find more information in this tutorial.
There is a lot of material about procedurally generated dungeons around. You can check another interesting tutorial here.
The real problem is that programmers have spent far too much time
worrying about efficiency in the wrong places and at the wrong times;
premature optimization is the root of all evil (or at least most of
it) in programming.
Donald Knuth (1974 Turing Award Lecture, Communications of the ACM 17 (12), (December 1974), pp. 667–673)
Taking Knuth's advice, I recommend implementing the simplest solution that comes to mind (as outlined in the question, for example) and only looking for a more efficient algorithm if that approach turns out to be a bottleneck in the program. If he was right for computers with the performance they had in 1974, he's much more right now ...
You could represent your board as a graph holding a coordinate value as the key and a set of coordinates as the values representing each coordinates neighbors..example Map<Coordinate, HashSet<Coordinate> = new Hashmap<Coordinate, HashSet<Coordinate>();.
Then populate the graph with each coordinate value as a key with their respective neighbors as their values.
Whenever a blocked off room appears, simply remove that coordinate from each of the coordinates neighbors that surround it.
So if you have coordinate (5,5) as a blocked room, you would removed (5,5) from (4,5)s neighbor set, (5,4)s neighbor set, (6,5)s neighbor set, and (5,6)s neighbor set. This would basically not allow you to move through this path any more.
To populate the graph you could use two loops:
for(int r = 0; r <= 10; r++){
for(int c = 0; c <= 10; c++){
HashSet<Coordinate> neighbors = new HashSet<Coordinate>();
if(r > 0){
neighbors.add(new Coordinate(r - 1, c));
}
if(r < 8){
neighbors.add(new Coordinate(r + 1, c));
}
if(c > 0){
neighbors.add(new Coordinate(r, c - 1));
}
if(c < 8){
neighbors.add(new Coordinate(r, c + 1));
}
graph.put((new Coordinate(r,c)), neighbors);
}
}
I hope this is what you were asking for.
Make an array A with a row for each room and a column for each room.
Put a 1 in each i, j (row,column) position if the two rooms are connected.
This matrix( A ) is the numeric representation of the graph that is your game, the nodes of the graph are rooms and the edges are doors.
Now take a vector with a length corresponding to the number of rooms you have and fill it with zeros except for a one in the position corresponding to the room you start in. This vector( P ) is the number of ways you can get to a given room after 0 transitions. To check if it is possible to get to a given room in ( n )transitions simply multiply P A^n and look for a non zero value in the position in the vector that represents the given room.
this is a generalization of maths described well here https://en.wikipedia.org/wiki/Markov_chain

How to output this to the screen?

I'm currently studying for my introductory CS final, and I'm having a really rough time with a few problems. The one I'm most worried about asks me to produce the code, in Java, to create the following output to the screen:
+
+++0
++++++00
++++++++++000
... (this pattern continues for 200 lines)
This might seem like a very basic question, but how do I go about doing this? I know that I should write some arrays and use for loops to go through them and output stuff to the screen, but I would really appreciate some guidance on how to solve this problem, along with others of its ilk. Thanks!
The pattern for the number of 0 is simply an arithmetic sequence. The number of + is as follows:
Row 1: 1
Row 2: 3 = 1 + 2
Row 3: 6 = 3 + 3
Row 4: 10 = 6 + 4
Turns out that these are triangular numbers. So, calculate the triangular number for each row in a loop, and have a nested loop that prints + that many times, then print the required number of 0.
I don't think this deserves a -1. Beginner question is not equal to a bad question.
As for the question itself. You have to carefully identify the pattern first and then word it in plain English. The pattern is quite simple.
Start with 1 cross and 0 zero. For each iteration, increase the growth
of crosses by 1 (so it's +1, +2, +3...) starting with a growth of 2
units and increase the growth of zeroes by 1 starting at 1 unit.
Now put this into pseudo-code and then code it. Be sure to understand the patterns first. I cannot stress this enough. Going right into coding will not help you.
First you need to be able to recogonize the pattern, then you need to be able to code it.
I'm going to go out on a limb and suggest that you are mixing the two "steps" of this problem together, so let's be very specific in dividing them.
The (parenthesis) items are the _additional_ elements.
index 0 : +
index 1 : +(++)(0)
index 2 : +++(+++)0(0)
index 3 : ++++++(++++)00(0)
so a good guess is that the pattern could be described as:
the previous number of +'s (and index + 1 more),
followed by the previous number of 0's (and one more).
combined with
index 0 is "+"
You might want to calculate index 4, 5, and 6 from this "rule" and see if it seems to describe the pattern correctly.
Now that you have the pattern, you really only need two variables, the number of + signs, and the number of 0s. You can calculate the "next" one from the previous one. The coding shouldn't be too hard, but if it is, then post your program and your "new" problem with that program in another question.
public class Answer {
public static void main(String[] args) {
int plusCount = 1;
for(int i=0; i<200; i++) {
for(int j=0; j<plusCount; j++) {
System.out.write('+');
}
plusCount += i+2;
for(int j=0; j<i; j++) {
System.out.write('0');
}
System.out.println();
}
}
}

Categories