Reputation: 677
My program is working fine, in terms of output, but for some of my test cases it takes too long to find an answer (sometimes taking 18 seconds). I would like to know how I can improve the performance of my code.
What my code does: It's a take on Pebble Solitaire. The user inputs n number of games and after that inputs a strings of length 23 that contains a combinations of only 'o' (pebble) and '-' (empty space). If there are 2 adjacent pebbles and an empty space on either side, ie (oo- OR -oo), then you remove the middle pebble and you swap other two pieces with each other, ex 'oo-' will turn into '--o'.
My current approach is pretty much an exhaustive approach where it tries out every possible move and results the move set with the least number of pebbles left.
I would like to know how I can improve this solution without making it multi-threaded.
Here is what I have:
package Pebble;
import java.util.Scanner;
public class PebbleSolitaire {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int numOfGames = Integer.parseInt(input.nextLine());
while (numOfGames > 0){
char[] values = input.nextLine().toCharArray();
long startTime = System.nanoTime();
System.out.println(solve(values));
System.out.println("Time to finish in ms: " + (System.nanoTime() - startTime) / 1000000);
numOfGames--;
}
input.close();
}
private static int solve(char[] game){
if(game != null && game.length == 0){
return -1;
}
int result = 0;
for (int i = 0; i < game.length; i++){
if(game[i] == 'o'){
result++;
}
}
//print(game);
for (int i = 0; i < game.length; i++ ){
char[] temp = new char[game.length];
copyArray(temp, game);
if (i-2 >= 0 && temp[i] == '-' && temp[i-2] == 'o' && temp[i-1] == 'o'){//move pebble forwards
temp[i-1] = temp[i-2] = '-';
temp[i] = 'o';
result = Math.min(result, solve(temp));
}
copyArray(temp, game);
if(i+2 < temp.length && temp[i] == '-' && temp[i+1] == 'o' && temp[i+2] == 'o'){//move pebble backwards
temp[i+1] = temp[i+2] = '-';
temp[i] = 'o';
result = Math.min(result, solve(temp));
}
}
return result;
}
private static void copyArray(char[] copy, char[] og){
for(int x = 0; x < copy.length; x++){
copy[x] = og[x];
}
}
private static void print(char[] c){
for(char ch: c){
System.out.print(ch);
}
System.out.println();
}
}
My sample input and output:
2
-o----ooo----o----ooo--
6
Time to finish in ms: 0
oooooooooo-ooooooooooo-
4
Time to finish in ms: 18149
EDIT: Would making this completely iterative drastically improve the performance?
Upvotes: 1
Views: 116
Reputation: 51413
Maybe you can improve this parte:
for (int i = 0; i < game.length; i++ ){
char[] temp = new char[game.length];
copyArray(temp, game);
if (i-2 >= 0 && temp[i] == '-' && temp[i-2] == 'o' && temp[i-1] == 'o'){//move pebble forwards
temp[i-1] = temp[i-2] = '-';
temp[i] = 'o';
result = Math.min(result, solve(temp));
}
copyArray(temp, game);
if(i+2 < temp.length && temp[i] == '-' && temp[i+1] == 'o' && temp[i+2] == 'o'){//move pebble backwards
temp[i+1] = temp[i+2] = '-';
temp[i] = 'o';
result = Math.min(result, solve(temp));
}
}
to:
for (int i = 0; i < game.length; i++ ){
char[] temp = null;
if (i-2 >= 0 && game[i] == '-' && game[i-2] == 'o' && game[i-1] == 'o'){//move pebble forwards
temp = new char[game.length];
copyArray(temp, game);
temp[i-1] = temp[i-2] = '-';
temp[i] = 'o';
result = Math.min(result, solve(temp));
}
if(i+2 < game.length && game[i] == '-' && game[i+1] == 'o' && game[i+2] == 'o'){//move pebble backwards
if(temp == null) temp = new char[game.length];
copyArray(temp, game);
temp[i+1] = temp[i+2] = '-';
temp[i] = 'o';
result = Math.min(result, solve(temp));
}
}
Basically, only creating and "copyArray(temp, game);" when strictly necessary.
Upvotes: 1