Related
I have to work out how to change code so that the output in the columns or rows I have changes. I have done the following for one that is supposed to print 5 by 5 rows of asterisks with the third row having plus signs instead. It is almost right but something is making the plus signs happen on the 4th row instead of the third. My lecturer said something about it in class being to do with when the value is grabbed, but I can't remember what and it's the weekend so I can't ask him.
I have read a few questions and that gave me a jumping point but I'm still unclear on the following things;
Can you please tell me where I'm going wrong with the third line and fourth line being opposite to how I would like them and give me any pointers on how to change things in specific rows or columns?
Thanks, here is my code;
public class OutputB
{
public static void main(String[] args)
{
int rows = 5; // tells the program how many rows
int cols = 5; // tells the program how many columns
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
if(r != 3)
{
System.out.print("*");
}
else
{
System.out.print("+");
}
System.out.println();
You're starting at zero, which means the third increment is actually the fourth. You have two options to fix this. You can either subtract 1 from the desired row number...
int rows = 5; // tells the program how many rows
int cols = 5; // tells the program how many columns
int rowOfThePlusSymbol = 3;
...
if(r != rowOfThePlusSymbol-1)
...or you you can start at 1 in your for loop. If you do so, be sure to put <= in your for loop also, so you loop the desired number of times.
...
for (int r = 1; r <= rows; r++)
{
for (int c = 1; c <= cols; c++)
...
}
I don't encourage using the latter solution because it is normal practice to start at zero when using increments or indexes of lists.
What I am trying to do is make it so that the game I am creating will randomly change characters every 5 seconds.
I got this working via a timer, the only problem is I don't want them repeating, I'm currently working on dummy code so it's just changing the screen colour, but how can I make it so that it doesn't repeat the number it just called?
if (timer <= 0)
{
num = rand.Next(2);
timer = 5.0f;
}
That is the current code and then in the draw I've literally just done "if num equals a certain number then change background colour".
I tried adding a prev_num checker but I can't get it to work properly (here it is)
if (timer <= 0)
{
prev_number = num;
num = rand.Next(2);
if (prev_number == num)
{
num = rand.Next(2);
}
else
{
timer = 5.0f;
}
}
Consider that if you're picking (for example) a random number from 1-5 then there are five possible outcomes, so you would use rand.Next(5) to select the zero-based "ordinal" or index of the outcome, then convert it into the range you actually want (in this case, by adding one).
If you want a random number from 0-4, excluding the number you just picked, then there are only four possible outcomes, not five - if the previous number was 3, then the possible outcomes are 0, 1, 2 or 4. You can then simplify your algorithm by choosing one of those four outcomes (rand.Next(4)) and mapping that ordinal to your desired range. A simple mapping would be to say if the new random number is below the previous number, return it as-is, otherwise (if equal or greater) add one.
int new_num = rand.Next(4);
if(new_num >= prev_num)
{
new_num++;
}
Your new number is now guaranteed to be in the same range as the previous number, but not equal to it.
Maybe just put it into a loop instead of a single check?
Also, I think because your timer was inside the else then it was not always
updated correctly.
if (timer <= 0)
{
tempNum = rand.Next(2);
do
{
tempNum = rand.Next(2);
}
while (tempNum == num)
num = tempNum;
timer = 5.0f;
}
Create an array of sequential numbers and then shuffle them (like a deck of cards) when your application begins.
int[] numbers = new int[100];
for(int i = 0; i < numbers.Length; i++)
numbers[i] = i;
Shuffle(numbers);
Using a function to shuffle the list:
public static void Shuffle<T>(IList<T> list)
{
Random rng = new Random();
int n = list.Count;
while (n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
You can then access them sequentially out of the list. They will be random as the list was shuffled, but you won't have any repetitions since each number only exists once in the list.
if (timer <= 0)
{
num = numbers[index];
index++;
timer = 5.0f;
}
An 2d array of bits are given.
var map1 = [[0,0,0,0,0,0,0,0],
[0,0,0,0,1,0,0,0],
[0,0,1,1,1,1,1,0],
[0,0,1,0,0,0,1,0],
[0,0,1,1,0,0,1,0],
[0,0,1,0,0,0,1,0],
[0,0,1,1,1,1,1,0],
[0,0,0,0,0,0,0,0]];
How I can programmaticaly check if some of the "ones" are forming a closed path ?
http://jsfiddle.net/RvN3k/
The two left bitmaps contains closed paths, the upper one is obvious, the lower one are simply a closed path with nothing inside.
The two right bitmaps doesn't contains closed paths, in the upper example one bit is missing, in the lower example the one diagonal pixel doesn't count, orthogonal paths only.
Find a cell that holds a 1, then "flood" from there on. By this I mean: use a second map, all initially set to 0. When you encounter the first 1, set the cell in the second map to 1. Now check all adjacent cells, setting the cell in the second map to 1 if that in the original map is also 1. Once you try to set a cell that was already 1, you know you have encountered a closed path; do not check that cell again or you'll get an infinite loop.
EDIT: if you want a complete list of all cells connected to one cell by closed paths, juts add every cell you encounter during the "flooding" to a list that initially only holds the starting cell. If at some point you don't find another cell to flood, there is no closed path and you can throw away the list. Depending on whether you want the little "stubs" in your linked bitmaps to be considered part of the path or not, you'll have to do some branching, introducing new lists for each branch, merging them if they intersect.
I've forked your fiddle and added a method findCycle().
var fill = function(map, x, y) {
if (Math.min(x,y) >= 0 && Math.max(x,y) < mapSize && map[x][y] == 0) {
map[x][y] = -1;
for (var dx = -1; dx <=1; dx +=1) {
for (var dy=-1; dy<=1; dy += 1) {
fill(map, x+dx, y+dy);
}
}
}
}
function detect(map) {
for(var x = 0; x + 1 < mapSize; x++){
for(var y = 0; y + 1 < mapSize; y++){
if (map[x][y] == 0) {
map[x][y] = -2;
return;
}
else if (map[x][y]== 1 && map[x+1][y]==1 && map[x][y+1]== 1 && map[x+1][y+1]==1) {
map[x][y] = -2;
return;
}
}
}
}
function findCycle(mapData) {
for(var x = 0; x < mapSize; x++){
for(var y = 0; y < mapSize; y++){
if (mapData[x][y] == 0) {
fill(mapData, x, y);
detect(mapData);
return;
}
}
}
}
It finds the first 0. Recursively fills all adjacent 0's with "-1". Then searches for any still existing 0's that couldn't be reached from the initial 0. (while at the same time searching for a square of four "1" (red) squares.
http://jsfiddle.net/bn6pa/1/
A black square is drawn at the first point where it finds a cycle.
How about this:
for each cell that's set to 1
set that cell to -1
recursively look for neighbouring cells set to 1, and set them to -1
if you find a neighbouring cell that is already set to -1, loop found
clean-up (set all cells that are set to -1 to 0, they are no longer relevant)
This ought to run close to O(N).
Here, I've implemented this into a fiddle, check it out here. You'll notice that the 4th example is odd: I haven't worked out the kinks because your problem definition doesn't state if you wanted the largest possible loop or any. In fact, you just wanted to know if there was a loop, which is known the moment you hit a light blue pixel.
I need serious help dividing the positive numbers and the negative numbers.
I am to accumulate the total of the negative values and separately accumulate the total of the positive values. After the loop, you are then to display the sum of the negative values and the sum of the positive values.
The data is suppose to look like this:
-2.3 -1.9 -1.5 -1.1 -0.7 -0.3 0.1 0.5 0.9 1.3 1.7 2.1 2.5 2.9
Sum of negative values: -7.8 Sum of positive
values: 12
So far I have this:
int main () {
int num, num2, num3, num4, num5, sum, count, sum1;
int tempVariable = 0;
int numCount = 100;
int newlineCount = 0, newlineCount1 = 0;
float numCount1 = -2.3;
while (numCount <= 150)
{
cout << numCount << " ";
numCount += 2;
newlineCount ++;
if(newlineCount == 6)
{
cout<< " " << endl;
newlineCount = 0;
}
}
**cout << "" << endl;
while (numCount1 <=2.9 )
{
cout << numCount1 << " ";
numCount1 += 0.4;
newlineCount1 ++;
} while ( newlineCount1 <= 0 && newlineCount >= -2.3 );
cout << "The sum is " << newlineCount1 << endl;**
return 0;
}
I do not know C/C++ but here is a general idea of the loop assuming the values are coming from an array. (since I am unaware of how they are coming in, i.e. user input, etc.)
Logic:
Use a for loop structure opposed to a while, to loop over each element of the array.
Initialize two variables to keep count, positiveSum and negativeSum.
At each iteration of the element, check to see if it's greater than 0. That's how you can divide the positive and negative numbers accordingly.
If greater than zero, add the element onto the running positiveSum, else add it to the running sum of negativeSum.
When the loop finishes, positiveSum and negativeSum should have the calculated sum.
If this is homework, (I don't remember if the homework tag was there prior to the question, or was added on later) this pseudo code should point you in the right direction without explicitly doing the entire work for you.
Pseudo Java Code (not tested or compiled)
// as a good convention, I always initialize variables,
// for numbers I always use zero's.
double positiveSum, negativeSum = 0.0;
// assuming array holds the array of values.
for (i=0; i < array.length; i++) {
// if positive, add it to the count
if (array[i] > 0) positiveSum = positiveSum + array[i];
// else negative
else negativeSum = negativeSum + array[i];
}
Once it's completed, both positiveSum and negativeSum should hold the correct calculated sum.
If you have any questions along the way, I can edit my answer to help you achieve the correct answer, I wish I could give it away but that's what your responsibilities are for homework.
I would loop through each number individually, let's call it currentValue
if the number is negative, negativeNumberTotal += currentValue
else if positive, positiveNumberTotal += currentValue
You will get your individual totals that way. Very simple.
You are clearly overcomplicating the problem. First of all you don't need two separate loops for the numbers, as there is a constant 0.4 difference between them, even between -0.3 and 0.1. You only have to check if it's negative or not to know how to sum them up.
Loops are simpler if you use an integer as counter. As you want 14 numbers you can simply count from 0 to 13, and from that you can easily calculate the corresponding floating point value.
Example C# code:
double negSum = 0.0, posSum = 0.0;
for (int i = 0; i < 14; i++) {
double number = -2.3 + (double)i * 0.4;
if (number < 0) {
negSum += number;
} else {
posSum += number;
}
}
You can of course use a floating point number in the loop, but then you need to take into account the inexact nature of floating point numbers. You should make sure to use an ending interval that is something like halfway between the last number that you want and the next.
double negSum = 0.0, posSum = 0.0;
for (double number = -2.3; number < 3.1; number += 0.4) {
if (number < 0) {
negSum += number;
} else {
posSum += number;
}
}
Also, when repeatedly accumulating floating point numbers (like adding 0.4 over and over again), you also accumulate rounding errors. Most numbers can't be represented exactly as floating point numbers, so it's likely that you are actually adding something like 0.3999999999999994225 instead of 0.4 each iteration. It's not likely to add up to something that is enough to show up in this small example, but you should be aware of this effect so that you can anticipate it in situations with more numbers.
You have several magic numbers, whose purpose I'm not sure of, e.g numcount1 = -2.3 In general you want to avoid magic numbers.
You might want to give your variables more descriptive names than num1, num2, etc.
Could you explain more precisely what the parameters are for your assignment?
EDIT:
I've noticed that you are using very weird conditions to control your loop. You are continuing until numcount1 is = 2.9, which is a very fragile sort of setup. The first thing I would do in your shoes is to rewrite your program so that the loop terminates when there are no more numbers to add. (Alternatively, you could just make it stop after, say 12 values.)
EDIT AGAIN:
OK, how about this
int sumOfPos = 0, sumOfNeg = 0, currentValue = -2.3, terminationValue = 2.9;
while (currentValue <= terminationValue) {
if ( /* there is a missing condition here */ ) {
// need a statement here to increment your negative counter
} else {
// need a statement here to increment your positive counter
}
}
// put some statements here to do output
This is easily solvable with pure math:
lowerBound = -2.3
upperBound = 2.9
incAmount = 0.4
signChange = lowerBound % incAmount
numBelowChange = -(lowerBound-signChange)/incAmount
avgNegValue = -(numBelowChange+1)/2.0*incAmount + signChange
sumOfNegative = numBelowChange*avgNegValue
numAboveChange = (upperBound-signChange)/incAmount
avgPosValue = (numAboveChange+1)/2.0*incAmount + signChange
sumOfPositive = numAboveChange*avgPosValue + signChange
It's more accurate, and more efficient than looping and adding.
With the constants you provided,
signChange = 0.1
numBelowChange = 6.0
avgNegValue = -1.3
sumOfNegative = -7.8
numAboveChange = 7.0
avgPosValue = 1.7
sumOfPositive = 12.0
If you're unfamiliar with the % operator, x%y means "divide x by y and return the remainder". So 5%2=1
http://en.wikipedia.org/wiki/Modulo_operator
I'm not a programmer, but I thought it was best to keep the inside of a loop as lean as possible. This version works without any if statements inside the loop, just simple addition. It's late at night, and I've had a couple of whiskies, but I think this algorithm would work (it worked when I tried implementing it in python). It's psuedo code, so you'll have to write it up in yr language of choice:
neg_total =0
abs_total=0
loop with i in all_your_numbers
total += i
abs_total += abs(i)
end
neg_total=(total-abs_total)/2
pos_total=abs_Total+neg_Total
print "sum of negative values =", neg_total
print "sum of positive values =", pos_total
I'm not sure if this is good programming practice, I'm just chuffed that it worked. Points if you can explain how.
I'm practicing for the upcoming ACM programming competition in a week and I've gotten stumped on this programming problem.
The problem is as follows:
You have a puzzle consisting of a square grid of size 4. Each grid square holds a single coin; each coin is showing either heads (H) and tails (T). One such puzzle is shown here:
H H H H
T T T T
H T H T
T T H T
Any coin that is current showing Tails (T) can be flipped to Heads (H). However, any time we flip a coin, we must also flip the adjacent coins direct above, below and to the left and right in the same row. Thus if we flip the second coin in the second row we must also flip 4 other coins, giving us this arrangment (coins that changed are shown in bold).
H T H H
H H H T
H H H T
T T H T
If a coin is at the edge of the puzzle, so there is no coin on one side or the other, then we flip fewer coins. We do not "wrap around" to the other side. For example, if we flipped the bottom right coin of the arragnement above we would get:
H T H H
H H H T
H H H H
T T T H
Note: Only coins showing (T) tails can be selected for flipping. However, anytime we flip such a coin, adjacent coins are also flipped, regardless of their state.
The goal of the puzzle is to have all coins show heads. While it is possible for some arragnements to not have solutions, all the problems given will have solutions. The answer we are looking for is, for any given 4x4 grid of coins what is the least number of flips in order to make the grid entirely heads.
For Example the grid:
H T H H
T T T H
H T H T
H H T T
The answer to this grid is: 2 flips.
What I have done so far:
I'm storing our grids as two-dimensional array of booleans. Heads = true, tails = false.
I have a flip(int row, int col) method that will flip the adjacent coins according the rules above and I have a isSolved() method that will determine if the puzzle is in a solved state (all heads). So we have our "mechanics" in place.
The part we are having problems with is how should we loop through, going an the least amount of times deep?
Your puzzle is a classic Breadth-First Search candidate. This is because you're looking for a solution with the fewest possible 'moves'.
If you knew the number of moves to the goal, then that would be ideal for a Depth-First Search.
Those Wikipedia articles contain plenty of information about the way the searches work, they even contain code samples in several languages.
Either search can be recursive, if you're sure you won't run out of stack space.
EDIT: I hadn't noticed that you can't use a coin as the primary move unless it's showing tails. That does indeed make order important. I'll leave this answer here, but look into writing another one as well.
No pseudo-code here, but think about this: can you ever imagine yourself flipping a coin twice? What would be the effect?
Alternative, write down some arbitrary board (literally, write it down). Set up some real world coins, and pick two arbitrary ones, X and Y. Do an "X flip", then a "Y flip" then another "X flip". Write down the result. Now reset the board to the starting version, and just do a "Y flip". Compare the results, and think about what's happened. Try it a few times, sometimes with X and Y close together, sometimes not. Become confident in your conclusion.
That line of thought should lead you to a way of determining a finite set of possible solutions. You can test all of them fairly easily.
Hope this hint wasn't too blatant - I'll keep an eye on this question to see if you need more help. It's a nice puzzle.
As for recursion: you could use recursion. Personally, I wouldn't in this case.
EDIT: Actually, on second thoughts I probably would use recursion. It could make life a lot simpler.
Okay, perhaps that wasn't obvious enough. Let's label the coins A-P, like this:
ABCD
EFGH
IJKL
MNOP
Flipping F will always involve the following coins changing state: BEFGJ.
Flipping J will always involve the following coins changing state: FIJKN.
What happens if you flip a coin twice? The two flips cancel each other out, no matter what other flips occur.
In other words, flipping F and then J is the same as flipping J and then F. Flipping F and then J and then F again is the same as just flipping J to start with.
So any solution isn't really a path of "flip A then F then J" - it's "flip <these coins>; don't flip <these coins>". (It's unfortunate that the word "flip" is used for both the primary coin to flip and the secondary coins which change state for a particular move, but never mind - hopefully it's clear what I mean.)
Each coin will either be used as a primary move or not, 0 or 1. There are 16 coins, so 2^16 possibilities. So 0 might represent "don't do anything"; 1 might represent "just A"; 2 might represent "just B"; 3 "A and B" etc.
Test each combination. If (somehow) there's more than one solution, count the number of bits in each solution to find the least number.
Implementation hint: the "current state" can be represented as a 16 bit number as well. Using a particular coin as a primary move will always XOR the current state with a fixed number (for that coin). This makes it really easy to work out the effect of any particular combination of moves.
Okay, here's the solution in C#. It shows how many moves were required for each solution it finds, but it doesn't keep track of which moves those were, or what the least number of moves is. That's a SMOP :)
The input is a list of which coins are showing tails to start with - so for the example in the question, you'd start the program with an argument of "BEFGJLOP". Code:
using System;
public class CoinFlip
{
// All ints could really be ushorts, but ints are easier
// to work with
static readonly int[] MoveTransitions = CalculateMoveTransitions();
static int[] CalculateMoveTransitions()
{
int[] ret = new int[16];
for (int i=0; i < 16; i++)
{
int row = i / 4;
int col = i % 4;
ret[i] = PositionToBit(row, col) +
PositionToBit(row-1, col) +
PositionToBit(row+1, col) +
PositionToBit(row, col-1) +
PositionToBit(row, col+1);
}
return ret;
}
static int PositionToBit(int row, int col)
{
if (row < 0 || row > 3 || col < 0 || col > 3)
{
// Makes edge detection easier
return 0;
}
return 1 << (row * 4 + col);
}
static void Main(string[] args)
{
int initial = 0;
foreach (char c in args[0])
{
initial += 1 << (c-'A');
}
Console.WriteLine("Initial = {0}", initial);
ChangeState(initial, 0, 0);
}
static void ChangeState(int current, int nextCoin, int currentFlips)
{
// Reached the end. Success?
if (nextCoin == 16)
{
if (current == 0)
{
// More work required if we want to display the solution :)
Console.WriteLine("Found solution with {0} flips", currentFlips);
}
}
else
{
// Don't flip this coin
ChangeState(current, nextCoin+1, currentFlips);
// Or do...
ChangeState(current ^ MoveTransitions[nextCoin], nextCoin+1, currentFlips+1);
}
}
}
I would suggest a breadth first search, as someone else already mentioned.
The big secret here is to have multiple copies of the game board. Don't think of "the board."
I suggest creating a data structure that contains a representation of a board, and an ordered list of moves that got to that board from the starting position. A move is the coordinates of the center coin in a set of flips. I'll call an instance of this data structure a "state" below.
My basic algorithm would look something like this:
Create a queue.
Create a state that contains the start position and an empty list of moves.
Put this state into the queue.
Loop forever:
Pull first state off of queue.
For each coin showing tails on the board:
Create a new state by flipping that coin and the appropriate others around it.
Add the coordinates of that coin to the list of moves in the new state.
If the new state shows all heads:
Rejoice, you are done.
Push the new state into the end of the queue.
If you like, you could add a limit to the length of the queue or the length of move lists, to pick a place to give up. You could also keep track of boards that you have already seen in order to detect loops. If the queue empties and you haven't found any solutions, then none exist.
Also, a few of the comments already made seem to ignore the fact that the problem only allows coins that show tails to be in the middle of a move. This means that order very much does matter. If the first move flips a coin from heads to tails, then that coin can be the center of the second move, but it could not have been the center of the first move. Similarly, if the first move flips a coin from tails to heads, then that coin cannot be the center of the second move, even though it could have been the center of the first move.
The grid, read in row-major order, is nothing more than a 16 bit integer. Both the grid given by the problem and the 16 possible moves (or "generators") can be stored as 16 bit integers, thus the problems amounts to find the least possible number of generators which, summed by means of bitwise XOR, gives the grid itself as the result. I wonder if there's a smarter alternative than trying all the 65536 possibilities.
EDIT: Indeed there is a convenient way to do bruteforcing. You can try all the 1-move patterns, then all the 2-moves patterns, and so on. When a n-moves pattern matches the grid, you can stop, exhibit the winning pattern and say that the solution requires at least n moves. Enumeration of all the n-moves patterns is a recursive problem.
EDIT2: You can bruteforce with something along the lines of the following (probably buggy) recursive pseudocode:
// Tries all the n bit patterns with k bits set to 1
tryAllPatterns(unsigned short n, unsigned short k, unsigned short commonAddend=0)
{
if(n == 0)
tryPattern(commonAddend);
else
{
// All the patterns that have the n-th bit set to 1 and k-1 bits
// set to 1 in the remaining
tryAllPatterns(n-1, k-1, (2^(n-1) xor commonAddend) );
// All the patterns that have the n-th bit set to 0 and k bits
// set to 1 in the remaining
tryAllPatterns(n-1, k, commonAddend );
}
}
To elaborate on Federico's suggestion, the problem is about finding a set of the 16 generators that xor'ed together gives the starting position.
But if we consider each generator as a vector of integers modulo 2, this becomes finding a linear combination of vectors, that equal the starting position.
Solving this should just be a matter of gaussian elimination (mod 2).
EDIT:
After thinking a bit more, I think this would work:
Build a binary matrix G of all the generators, and let s be the starting state. We are looking for vectors x satisfying Gx=s (mod 2). After doing gaussian elimination, we either end up with such a vector x or we find that there are no solutions.
The problem is then to find the vector y such that Gy = 0 and x^y has as few bits set as possible, and I think the easiest way to find this would be to try all such y. Since they only depend on G, they can be precomputed.
I admit that a brute-force search would be a lot easier to implement, though. =)
Okay, here's an answer now that I've read the rules properly :)
It's a breadth-first search using a queue of states and the moves taken to get there. It doesn't make any attempt to prevent cycles, but you have to specify a maximum number of iterations to try, so it can't go on forever.
This implementation creates a lot of strings - an immutable linked list of moves would be neater on this front, but I don't have time for that right now.
using System;
using System.Collections.Generic;
public class CoinFlip
{
struct Position
{
readonly string moves;
readonly int state;
public Position(string moves, int state)
{
this.moves = moves;
this.state = state;
}
public string Moves { get { return moves; } }
public int State { get { return state; } }
public IEnumerable<Position> GetNextPositions()
{
for (int move = 0; move < 16; move++)
{
if ((state & (1 << move)) == 0)
{
continue; // Not allowed - it's already heads
}
int newState = state ^ MoveTransitions[move];
yield return new Position(moves + (char)(move+'A'), newState);
}
}
}
// All ints could really be ushorts, but ints are easier
// to work with
static readonly int[] MoveTransitions = CalculateMoveTransitions();
static int[] CalculateMoveTransitions()
{
int[] ret = new int[16];
for (int i=0; i < 16; i++)
{
int row = i / 4;
int col = i % 4;
ret[i] = PositionToBit(row, col) +
PositionToBit(row-1, col) +
PositionToBit(row+1, col) +
PositionToBit(row, col-1) +
PositionToBit(row, col+1);
}
return ret;
}
static int PositionToBit(int row, int col)
{
if (row < 0 || row > 3 || col < 0 || col > 3)
{
return 0;
}
return 1 << (row * 4 + col);
}
static void Main(string[] args)
{
int initial = 0;
foreach (char c in args[0])
{
initial += 1 << (c-'A');
}
int maxDepth = int.Parse(args[1]);
Queue<Position> queue = new Queue<Position>();
queue.Enqueue(new Position("", initial));
while (queue.Count != 0)
{
Position current = queue.Dequeue();
if (current.State == 0)
{
Console.WriteLine("Found solution in {0} moves: {1}",
current.Moves.Length, current.Moves);
return;
}
if (current.Moves.Length == maxDepth)
{
continue;
}
// Shame Queue<T> doesn't have EnqueueRange :(
foreach (Position nextPosition in current.GetNextPositions())
{
queue.Enqueue(nextPosition);
}
}
Console.WriteLine("No solutions");
}
}
If you are practicing for the ACM, I would consider this puzzle also for non-trivial boards, say 1000x1000. Brute force / greedy may still work, but be careful to avoid exponential blow-up.
The is the classic "Lights Out" problem. There is actually an easy O(2^N) brute force solution, where N is either the width or the height, whichever is smaller.
Let's assume the following works on the width, since you can transpose it.
One observation is that you don't need to press the same button twice - it just cancels out.
The key concept is just that you only need to determine if you want to press the button for each item on the first row. Every other button press is uniquely determined by one thing - whether the light above the considered button is on. If you're looking at cell (x,y), and cell (x,y-1) is on, there's only one way to turn it off, by pressing (x,y). Iterate through the rows from top to bottom and if there are no lights left on at the end, you have a solution there. You can then take the min of all the tries.
It's a finite state machine, where each "state" is the 16 bit integer corresponding the the value of each coin.
Each state has 16 outbound transitions, corresponding to the state after you flip each coin.
Once you've mapped out all the states and transitions, you have to find the shortest path in the graph from your beginning state to state 1111 1111 1111 1111,
I sat down and attempted my own solution to this problem (based on the help I received in this thread). I'm using a 2d array of booleans, so it isn't as nice as the people using 16bit integers with bit manipulation.
In any case, here is my solution in Java:
import java.util.*;
class Node
{
public boolean[][] Value;
public Node Parent;
public Node (boolean[][] value, Node parent)
{
this.Value = value;
this.Parent = parent;
}
}
public class CoinFlip
{
public static void main(String[] args)
{
boolean[][] startState = {{true, false, true, true},
{false, false, false, true},
{true, false, true, false},
{true, true, false, false}};
List<boolean[][]> solutionPath = search(startState);
System.out.println("Solution Depth: " + solutionPath.size());
for(int i = 0; i < solutionPath.size(); i++)
{
System.out.println("Transition " + (i+1) + ":");
print2DArray(solutionPath.get(i));
}
}
public static List<boolean[][]> search(boolean[][] startState)
{
Queue<Node> Open = new LinkedList<Node>();
Queue<Node> Closed = new LinkedList<Node>();
Node StartNode = new Node(startState, null);
Open.add(StartNode);
while(!Open.isEmpty())
{
Node nextState = Open.remove();
System.out.println("Considering: ");
print2DArray(nextState.Value);
if (isComplete(nextState.Value))
{
System.out.println("Solution Found!");
return constructPath(nextState);
}
else
{
List<Node> children = generateChildren(nextState);
Closed.add(nextState);
for(Node child : children)
{
if (!Open.contains(child))
Open.add(child);
}
}
}
return new ArrayList<boolean[][]>();
}
public static List<boolean[][]> constructPath(Node node)
{
List<boolean[][]> solutionPath = new ArrayList<boolean[][]>();
while(node.Parent != null)
{
solutionPath.add(node.Value);
node = node.Parent;
}
Collections.reverse(solutionPath);
return solutionPath;
}
public static List<Node> generateChildren(Node parent)
{
System.out.println("Generating Children...");
List<Node> children = new ArrayList<Node>();
boolean[][] coinState = parent.Value;
for(int i = 0; i < coinState.length; i++)
{
for(int j = 0; j < coinState[i].length; j++)
{
if (!coinState[i][j])
{
boolean[][] child = arrayDeepCopy(coinState);
flip(child, i, j);
children.add(new Node(child, parent));
}
}
}
return children;
}
public static boolean[][] arrayDeepCopy(boolean[][] original)
{
boolean[][] r = new boolean[original.length][original[0].length];
for(int i=0; i < original.length; i++)
for (int j=0; j < original[0].length; j++)
r[i][j] = original[i][j];
return r;
}
public static void flip(boolean[][] grid, int i, int j)
{
//System.out.println("Flip("+i+","+j+")");
// if (i,j) is on the grid, and it is tails
if ((i >= 0 && i < grid.length) && (j >= 0 && j <= grid[i].length))
{
// flip (i,j)
grid[i][j] = !grid[i][j];
// flip 1 to the right
if (i+1 >= 0 && i+1 < grid.length) grid[i+1][j] = !grid[i+1][j];
// flip 1 down
if (j+1 >= 0 && j+1 < grid[i].length) grid[i][j+1] = !grid[i][j+1];
// flip 1 to the left
if (i-1 >= 0 && i-1 < grid.length) grid[i-1][j] = !grid[i-1][j];
// flip 1 up
if (j-1 >= 0 && j-1 < grid[i].length) grid[i][j-1] = !grid[i][j-1];
}
}
public static boolean isComplete(boolean[][] coins)
{
boolean complete = true;
for(int i = 0; i < coins.length; i++)
{
for(int j = 0; j < coins[i].length; j++)
{
if (coins[i][j] == false) complete = false;
}
}
return complete;
}
public static void print2DArray(boolean[][] array)
{
for (int row=0; row < array.length; row++)
{
for (int col=0; col < array[row].length; col++)
{
System.out.print((array[row][col] ? "H" : "T") + " ");
}
System.out.println();
}
}
}