Recursive backtracking in Java for solving a crossword - java

I need to solve a crossword given the initial grid and the words (words can be used more than once or not at all).
The initial grid looks like that:
++_+++
+____+
___+__
+_++_+
+____+
++_+++
Here is an example word list:
pain
nice
pal
id
The task is to fill the placeholders (horizontal or vertical having length > 1) like that:
++p+++
+pain+
pal+id
+i++c+
+nice+
++d+++
Any correct solution is acceptable, and it's guaranteed that there's a solution.
In order to start to solve the problem, I store the grid in 2-dim. char array and I store the words by their length in the list of sets: List<Set<String>> words, so that e.g. the words of length 4 could be accessed by words.get(4)
Then I extract the location of all placeholders from the grid and add them to the list (stack) of placeholders:
class Placeholder {
int x, y; //coordinates
int l; // the length
boolean h; //horizontal or not
public Placeholder(int x, int y, int l, boolean h) {
this.x = x;
this.y = y;
this.l = l;
this.h = h;
}
}
The main part of the algorithm is the solve() method:
char[][] solve (char[][] c, Stack<Placeholder> placeholders) {
if (placeholders.isEmpty())
return c;
Placeholder pl = placeholders.pop();
for (String word : words.get(pl.l)) {
char[][] possibleC = fill(c, word, pl); // description below
if (possibleC != null) {
char[][] ret = solve(possibleC, placeholders);
if (ret != null)
return ret;
}
}
return null;
}
Function fill(c, word, pl) just returns a new crossword with the current word written on the current placeholder pl. If word is incompatible with pl, then function returns null.
char[][] fill (char[][] c, String word, Placeholder pl) {
if (pl.h) {
for (int i = pl.x; i < pl.x + pl.l; i++)
if (c[pl.y][i] != '_' && c[pl.y][i] != word.charAt(i - pl.x))
return null;
for (int i = pl.x; i < pl.x + pl.l; i++)
c[pl.y][i] = word.charAt(i - pl.x);
return c;
} else {
for (int i = pl.y; i < pl.y + pl.l; i++)
if (c[i][pl.x] != '_' && c[i][pl.x] != word.charAt(i - pl.y))
return null;
for (int i = pl.y; i < pl.y + pl.l; i++)
c[i][pl.x] = word.charAt(i - pl.y);
return c;
}
}
Here is the full code on Rextester.
The problem is that my backtracking algorithm doesn't work well. Let's say this is my initial grid:
++++++
+____+
++++_+
++++_+
++++_+
++++++
And this is the list of words:
pain
nice
My algorithm will put the word pain vertically, but then when realizing that it was a wrong choice it will backtrack, but by that time the initial grid will be already changed and the number of placeholders will be reduced. How do you think the algorithm can be fixed?

This can be solved in 2 ways:
Create a deep copy of the matrix at the start of fill, modify and return that (leaving the original intact).
Given that you already pass around the matrix, this wouldn't require any other changes.
This is simple but fairly inefficient as it requires copying the matrix every time you try to fill in a word.
Create an unfill method, which reverts the changes made in fill, to be called at the end of each for loop iteration.
for (String word : words.get(pl.l)) {
if (fill(c, word, pl)) {
...
unfill(c, word, pl);
}
}
Note: I changed fill a bit as per my note below.
Of course just trying to erase all letter may erase letters of other placed words. To fix this, we can keep a count of how many words each letter is a part of.
More specifically, have a int[][] counts (which will also need to be passed around or be otherwise accessible) and whenever you update c[x][y], also increment counts[x][y]. To revert a placement, decrease the count of each letter in that placement by 1 and only remove letters with a count of 0.
This is somewhat more complex, but much more efficient than the above approach.
In terms of code, you might put something like this in fill:
(in the first part, the second is similar)
for (int i = pl.x; i < pl.x + pl.l; i++)
counts[pl.y][i]++;
And unfill would look something like this: (again for just the first part)
for (int i = pl.x; i < pl.x + pl.l; i++)
counts[pl.y][i]--;
for (int i = pl.x; i < pl.x + pl.l; i++)
if (counts[pl.y][i] == 0)
c[pl.y][i] = '_';
// can also just use a single loop with "if (--counts[pl.y][i] == 0)"
Note that, if going for the second approach above, it might make more sense to simply have fill return a boolean (true if successful) and just pass c down to the recursive call of solve. unfill can return void, since it can't fail, unless you have a bug.
There is only a single array that you're passing around in your code, all you're doing is changing its name.
See also Is Java "pass-by-reference" or "pass-by-value"?

You identified it yourself:
it will backtrack, but by that time the initial grid will be already
changed
That grid should be a local matrix, not a global one. That way, when you back up with a return of null, the grid from the parent call is still intact, ready to try the next word in the for loop.
Your termination logic is correct: when you find a solution, immediately pass that grid back up the stack.

Related

can someone help me fix this code(string)-java

I try to write a old maid.
After dealing cards,and sorting, i have two parts of card,one is playerDeck, one is computerDeck. now the pairs need to be removed.but i was stuck at this stage.
for example(just an example )
playerDeck:
'A♡', 'A♢', '8♡', '8♢', '8♠', 'Q♠', '2♠', '4♣', '7♢', '7♣', 'K♣', 'A♡', 'J♡', '9♣', '3♢'
computerDeck:
'3♡','3♣', '10♡','10♠','10♣', '6♡', 'K♡','K♢', 'A♣', 'A♠', '4♢', '7♡','7♠'
String q;
String p;
ArrayStringsTools AA=new ArrayStringsTools();//this is a class that i will use for removing item
for(int i=0;i<playerDeck.length-1;i++){
q=playerDeck[i];
q=q.substring(0,1);//i try to find the first character
p=playerDeck[i+1];//after finding first character, i can compare them,and if they are same, then i can remove them
p=p.substring(0,1);
if(q==p){
AA.removeItemByIndex(playerDeck,26,i);//this is the method that i used for removing same item,i will put this code below
AA.removeItemByIndex(playerDeck,26,i+1);//there are 51 cards in total,player has 26, computer has 25
}
}
public static int removeItemByIndex(String[] arrayOfStrings, int currentSize, int itemToRemove){//this is the method i used for removing item(first is the array of Deck, second is the size of Deck,third is the index of item to remove)
if( arrayOfStrings == null || currentSize > arrayOfStrings.length) {
System.out.println("ArrayStringsTools.removeItemByIndex: wrong call");
return currentSize;
}
if( itemToRemove < 0 || itemToRemove >= currentSize ) {
System.out.println("ArrayStringsTools.removeItem: item "
+ itemToRemove + " out of bounds. Array Unchanged.");
return currentSize;
}
int i;
for( i = itemToRemove; i < currentSize-1; i++){
arrayOfStrings[i] = arrayOfStrings[i+1];
}
arrayOfStrings[i]= null;
return currentSize-1;
i think i wrote correctly, but it doesnt show any difference compared with the origin.
the result should be:
playerDeck: '8♠', 'Q♠', '2♠', '4♣', 'K♣', 'A♡', 'J♡', '9♣', '3♢'
computerDeck:'10♣', '6♡', '4♢'
or is there another way to do this,because when a pair removed,there are two empty spaces, so... I've been struggling for a long time......
To compare the 1st character, change this line
if (q == p) {
to
if (q.charAt(0) == p.charAt(0)) {
Notice that q == p checks to see if the q and p refer to the same string, and do not look at the contents at all. If you want to compare full strings (or any other object that is not a char, an int, or so on) by content, you should use equals: q.equals(p) returns true only if both have the same content.
If you want to compare two strings,you can use 'equals',like
if(q.equals(p)){//q==p if true,they are save in the same location-this may not be what you want,and in this code it will be false forever.
}

How to draw a triangle in a 2D array (Java)

For a class project we need to be able to draw a triangle in a 2D array of chars. Algorithmically I can't work out how to do it.
My current code is this (but it does not work):
public void fill() {
for (int i = 0; i < h; i++) {
double x=h;
while(x<=0){
drawing.setPoint(i, x, myChar);
x=Math.ceil(x/2);
}
}
}
I want the output to look something like this:
....*....
...***...
..*****..
.*******.
*********
We can't use any pre-existing methods or classes that relate to drawing.
Thanks for your help
Based on your drawing, you need 9 columns for 5 rows. So,
int height = 5;
int width = 2*height - 1;
Even though I'm not sure what drawing.setPoint(i, x, myChar); does, I think this example will get you going. I will build a String based on chars.
char fill = '*';
char blank = '.';
I'll start the rows at 0 but the columns at 1 to make the math a little clearer.
For row = 0, ....*.... you need one star in column = 5.
For row = 1, ...***... you need three stars in column = 4,5,6.
For row = 3, .*******. you need seven stars in column = 2,3,4,5,6,7,8.
Notice that for row i you need a star in column j if the distance between the height = 5 and the column j is less than or equal to i. That is, when | height - column | <= row
for (int row = 0; row < height; row ++) {
StringBuilder line = new StringBuilder(width);
for (int column = 1; column <= width; column ++) {
char out = Math.abs(column - height) <= row ? fill : blank;
line.append(out);
}
System.out.println(line);
}
This yields
....*....
...***...
..*****..
.*******.
*********
I assume you can use Math.abs since your example has Math.ceil. If not, you can convert Math.abs to an if statement.
There are lots of ways to tackle this, and you've already seen one answer which draws the picture row-by-row.
I'm going to assume that you've already got routines to create char[][] and to print the characters in that array of arrays to the screen. It looks as if you already have a setPoint() method too, to poke a point into the structure.
As a beginner, I don't think it helps you to be given a solution. You need to be pointed in the right direction to solve it yourself.
Lots of experienced coders now use Test Driven Design, and you could learn from this: start with a simple case, create a test for that, make that test pass, repeat with more tests until there are no more tests to write.
Eventually you should learn a test framework like jUnit, but for now you can "test" by just running your program. So the first test is, does it work for height == 1?
You can pass this test (for now that means, run the program and see that the output looks right) with:
public void drawTriangle(int height) {
drawing.setPoint(0,5,'*')
}
Job done.
Now to make it work for height==2:
public void drawTriangle(int height) {
drawing.setPoint(0,5,'*');
if(height == 2) {
drawing.setPoint(1,4,'*');
drawing.setPoint(1,5,'*');
drawing.setPoint(1,6,'*');
}
}
This still works for height == 1, but also works for height == 2.
But you can immediately see an opportunity for a loop to replace those three commands for the second row. So:
public void drawTriangle(int height) {
drawing.setPoint(0,5,'*');
if(height == 2) {
for(int 4; i<7; i++) {
drawing.setPoint(1,i,'*');
}
}
}
... and you can pull that out into a method:
public void drawTriangle(int height) {
drawing.setPoint(0,5,'*');
if(height == 2) {
drawRow2();
}
}
private void drawRow2() {
for(int 4; i<7; i++) {
drawing.setPoint(1,i,'*');
}
}
This is called refactoring -- writing something that works, but isn't written the best way, testing it to ensure it works, then changing the way it's written one step at a time, so it still works, but in a tidier way.
Hopefully you can see where this is going. You can modify drawRow2() to be more general -- drawRow(int rowNumber), and gradually replace the literal numbers in there with variables derived from rowNumber. Then you can use drawRow(0) to draw the first row, and drawRow(1) to draw the second. Then you can draw a three row triangle by adding drawRow(2), and then you can improve that by using a loop instead.

Optimal render draw-order function with specified z-index values

I found recently the default renderable sort function in LibGDX wasn't quite up to my needs. (see; Draw order changes strangely as camera moves? )
Essentially a few objects rendered in front when they should render behind.
Fortunately, the renderables in question always have a guarantied relationship. The objects are attached to eachother so when one moves the other moves. One object can be seen as being literally "pinned" to the other, so always in front.
This gave me the idea that if I specified a "z-index" (int) and "groupname" (String) for each object, I could manually take over the draw order, and for things with the same groupname, ensure they are positioned next to eachother in the list, in the order specified by the z-index. (low to high)
//For example an array of renderables like
0."testgroup2",11
1."testgroup",20
2."testgroup2",10
3.(no zindex attribute)
4."testgroup",50
//Should sort to become
0."testgroup",20
1."testgroup",50
2.(no zindex attribute)
3."testgroup2",10
4."testgroup2",11
// assuming the object2 in testgroup2 are closer to the camera, the one without a index second closest, and the rest furthest<br>
//(It is assumed that things within the same group wont be drastically different distances)
I implemented a sort system in libgdx to do this as followed;
/**
* The goal of this sorter is to sort the renderables the same way LibGDX would do normally (in DefaultRenderableSorter)<br>
* except if they have a ZIndex Attribute.<br>
* A Zindex attribute provides a groupname string and a number.<br>
* Renderables with the attribute are placed next to others of the same group, with the order within the group determined by the number<br>
*
* For example an array of renderables like;<br><br>
* 0."testgroup",20<br>
* 1."testgroup2",10<br>
* 2.(no zindex attribute)<br>
* 3."testgroup",50<br>
* <br>Should become;<br><br>
* 0."testgroup",20<br>
* 1."testgroup",50<br>
* 2.(no zindex attribute)<br>
* 3."testgroup2",10<br>
* <br>
* assuming the object in testgroup2 is closer to the camera, the one without a index second closest, and the rest furthest<br>
* (It is assumed that things within the same group wont be drastically different distances)<br>
*
* #param camera - the camera in use to determine normal sort order when we cant place in a existing group
* #param resultList - an array of renderables to change the order of
*/
private void customSorter(Camera camera, Array<Renderable> resultList) {
//make a copy of the list to sort. (This is probably a bad start)
Array <Renderable> renderables = new Array <Renderable> (resultList);
//we work by clearing and rebuilding the Renderables array (probably not a good method)
resultList.clear();
//loop over the copy we made
for (Renderable o1 : renderables) {
//depending of if the Renderable as a ZIndexAttribute or not, we sort it differently
//if it has one we do the following....
if (o1.material.has(ZIndexAttribute.ID)){
//get the index and index group name of it.
int o1Index = ((ZIndexAttribute)o1.material.get(ZIndexAttribute.ID)).zIndex;
String o1GroupName = ((ZIndexAttribute)o1.material.get(ZIndexAttribute.ID)).group;
//setup some variables
boolean placementFound = false; //Determines if a placement was found for this renderable (this happens if it comes across another with the same groupname)
int defaultPosition = -1; //if it doesn't find another renderable with the same groupname, this will be its position in the list. Consider this the "natural" position based on distance from camera
//start looping over all objects so far in the results (urg, told you this was probably not a good method)
for (int i = 0; i < resultList.size; i++) {
//first get the renderable and its ZIndexAttribute (null if none found)
Renderable o2 = resultList.get(i);
ZIndexAttribute o2szindex = ((ZIndexAttribute)o2.material.get(ZIndexAttribute.ID));
if (o2szindex!=null){
//if the renderable we are comparing too has a zindex, then we get its information
int o2index = o2szindex.zIndex;
String o2groupname = o2szindex.group;
//if its in the same group as o1, then we start the processing of placing them nexto eachother
if (o2groupname.equals(o1GroupName)){
//we either place it in front or behind based on zindex
if (o1Index<o2index){
//if lower z-index then behind it
resultList.insert(i, o1);
placementFound = true;
break;
}
if (o1Index>o2index){
//if higher z-index then it should go in front UNLESS there is another of this group already there too
//in which case we just continue (which will cause this to fire again on the next renderable in the inner loop)
if (resultList.size>(i+1)){
Renderable o3 = resultList.get(i+1);
ZIndexAttribute o3szindex = ((ZIndexAttribute)o3.material.get(ZIndexAttribute.ID));
if (o3szindex!=null){
String o3groupname = o3szindex.group;
if (o3groupname!=null && o3groupname.equals(o1GroupName)){
//the next element is also a renderable with the same groupname, so we loop and test that one instead
continue;
}
}
}
// Gdx.app.log("zindex", "__..placeing at:"+(i+1));
//else we place after the current one
resultList.insert(i+1, o1);
placementFound = true;
break;
}
}
}
//if no matching groupname found we need to work out a default placement.
int placement = normalcompare(o1, o2); //normal compare is the compare function in DefaultRenderableSorter.
if (placement>0){
//after then we skip
//(we are waiting till we are either under something or at the end
} else {
//if placement is before, then we remember this position as the default (but keep looking as there still might be matching groupname, which should take priority)
defaultPosition = i;
//break; //break out the loop
}
}
//if we have checked all the renderables positioned in the results list, and none were found with matching groupname
//then we use the defaultposition to insert it
if (!placementFound){
//Gdx.app.log("zindex", "__no placement found using default which is:"+defaultPosition);
if (defaultPosition>-1){
resultList.insert(defaultPosition, o1);
} else {
resultList.add(o1);
}
}
continue;
}
//...(breath out)...
//ok NOW we do placement for things that have no got a ZIndexSpecified
boolean placementFound = false;
//again, loop over all the elements in results
for (int i = 0; i < resultList.size; i++) {
Renderable o2 = resultList.get(i);
//if not we compare by default to place before/after
int placement = normalcompare(o1, o2);
if (placement>0){
//after then we skip
//(we are waiting till we are either under something or at the end)
continue;
} else {
//before
resultList.insert(i, o1);
placementFound = true;
break; //break out the loop
}
}
//if no placement found we go at the end by default
if (!placementFound){
resultList.add(o1);
};
} //go back to check the next element in the incomeing list of renderables (that is, the copy we made at the start)
//done
}
//Copy of the default sorters compare function
//;
private Camera camera;
private final Vector3 tmpV1 = new Vector3();
private final Vector3 tmpV2 = new Vector3();
public int normalcompare (final Renderable o1, final Renderable o2) {
final boolean b1 = o1.material.has(BlendingAttribute.Type) && ((BlendingAttribute)o1.material.get(BlendingAttribute.Type)).blended;
final boolean b2 = o2.material.has(BlendingAttribute.Type) && ((BlendingAttribute)o2.material.get(BlendingAttribute.Type)).blended;
if (b1 != b2) return b1 ? 1 : -1;
// FIXME implement better sorting algorithm
// final boolean same = o1.shader == o2.shader && o1.mesh == o2.mesh && (o1.lights == null) == (o2.lights == null) &&
// o1.material.equals(o2.material);
o1.worldTransform.getTranslation(tmpV1);
o2.worldTransform.getTranslation(tmpV2);
final float dst = (int)(1000f * camera.position.dst2(tmpV1)) - (int)(1000f * camera.position.dst2(tmpV2));
final int result = dst < 0 ? -1 : (dst > 0 ? 1 : 0);
return b1 ? -result : result;
}
As far as I can tell my customSorter function produces the order I want - the renderables now look like they are drawn in the right order.
However, this also seems like a hackjob, and I am sure my sorting algorithm is horrendously inefficient.
I would like advice on how to either;
a) Improve my own algorithm, especially in regards to any quirks to bare in mind when doing cross-platform LibGDX development (ie, array types, memory management in regards to android/web etc)
b) Alternative more efficient solutions having a similar "z index override" of the normal draw-order sorting.
Notes;
. The grouping is necessary. This is because while things are firmly stuck relatively to eachother within a group, groups themselves can also move about in front/behind eachother. (but not between). This makes it tricky to do a "global" override of the draw order, rather then a local one per group.
. If it helps, I can add/change the zindexattribute object in any way.
. I am thinking somehow "pre-storeing" each group of objects in a array could help things, but not 100% sure how.
First of all do never copy a list if not needed. The list with renderables could be really huge since it also could contain resources. Copying will be very very slow. If you need something local and you need performance try to make it final since it can improve the performance.
So a simple approach would be the default sorting of Java. You need to implement a Comperator for your class for example the Class with z index could look like this:
public class MyRenderable {
private float z_index;
public MyRenderable(float i)
{
z_index = i;
}
public float getZ_index() {
return z_index;
}
public void setZ_index(float z_index) {
this.z_index = z_index;
}
}
If you want a faster sort since your list wont change that much on runtime you could implement a insertion sort since it does a faster job if the list is kind of presorted. If it is not pre sorted it does take longer but in general it should only be the first sort call where it is alot disordered in your case.
private void sortList(ArrayList<MyRenderable> array) {
// double starttime = System.nanoTime();
for (int i = 1; i < array.size(); i++) {
final MyRenderable temp = array.get(i);
int j = i - 1;
while (j >= 0 && array.get(j).getZ_index() < temp.getZ_index()) {
array.set(j + 1, array.get(j));
j--;
}
array.set(j + 1, temp);
}
// System.out.println("Time taken: " + (System.nanoTime() - starttime));
}
To use this method you simply call it with your Array
sortList(renderbales);
In your case you need to take care of the ones that do not have a Z index. Maybe you could give them a 0 since they'll get sorted at the right position(i guess). Else you can use the given methods in z case and the regular in no z case as you do already.
After the conversation in the comments. I dont think it is a good idea to push everything into one list. It's hard to sort and would be very slow. A better approach would be a list of groups. Since you want to have groups, programm a group. Do not use String names, use IDs or types (way more easy to sort and it doesn't really matter). So a simple group would be this:
public class Group{
//think about privates and getters or methods to add things which also checks some conditions and so on
public int groupType;
public ArrayList<MyRenderable> renderables;
}
And now all your groups into a list. (this contains all your renderbales then)
ArrayList<Group> allRenderables = new ArrayList<>();
Last but not least sort the groups and sort the renderables. Since i dont think that your group ids/names will change on runtime, sort them once or even use a SortedSet instead of a ArrayList. But basically the whole sorting looks like this:
for(Group g: allRenderables)
sortRenderables(g.renderables); //now every group is sorted
//now sort by group names
sortGroup(allRenderables);
With the following insertionsorts as shown above
public static void sortRenderables(ArrayList<MyRenderable> array) {
for (int i = 1; i < array.size(); i++) {
final MyRenderable temp = array.get(i);
int j = i - 1;
while (j >= 0 && array.get(j).getZ_index() < temp.getZ_index()) {
array.set(j + 1, array.get(j));
j--;
}
array.set(j + 1, temp);
}
}
public static void sortGroup(ArrayList<Group> array) {
for (int i = 1; i < array.size(); i++) {
final Group temp = array.get(i);
int j = i - 1;
while (j >= 0 && array.get(j).groupType < temp.groupType) {
array.set(j + 1, array.get(j));
j--;
}
array.set(j + 1, temp);
}
}

Java Android trying to place a 10*10 grid over a bitmap to see how much of a colour is in each grid section

to describe my issue I must first discuss what I am trying to do, http://i.imgur.com/rcHwze5.png here is an image of a letter with a 10*10 grid over it. For every box in the grid if 1/3 of the pixels are colored a 1 is added to the ArrayList, otherwise a 0 is added. Here is my 3 methods that I have created to do this: https://gist.github.com/VincentMc/7ddf3c282e80bbff7835 BoundBM is a bitmap object with the letter drawn onto it.
Here is an image of my desired output http://i.imgur.com/B0QnUW8.png
Here is an image of my actual output http://i.imgur.com/WgRVXLv.png
It seems once a 1 is added on a row it is constantly added until it reaches the next row, but I can't seem to see why??
Any help would be greatly appreciated I have been at this quite a while, Thanks!
do it in two step:
1: sort each string:
public String sortString(String s1){
char[] chars = s1.toCharArray();
Arrays.sort(chars);
String sorted = new String(chars);
return sorted;
}
2: put each of your string in an array and use:
Arrays.sort(stringArray);
Out of the Code-Segmet you offered, i cant see an obvious mistake. But your design is inviting mistakes. To avoid these you may try:
Don't use count as a classwide variable, thou its not relevant for the hole class but only for the method. So make it an return statement, that you dont loose control over it, that it may be set anywhere or is only changed locally in a method.
totalp should not be calculated in every countPixel() method call, because it is a fixed value for your BoundBM. Initialize it in your constructor maybe, or with loading the bitmap.
At last, you know how large your output array is supposed to be, it doesnt make much sense for me, to keep it a list and to add it. Create an 2D array, and write it directly.
Hope it will help
reineke
EDIT: found the mistake!
in code line 27 you set x to 0 and not to the initial value of the input x, so you continue at the wrong position!!
Here is what i would do:
final int GRID=10;
totalp = boundBM.getWidth()/GRID * boundBM.getHeight()/GRID;
//this method now does not need to read boundBM, so it is more opject-oriented
public int countPixels(int x, int y, int h, int w){
count = 0;
for (i=x; i<x+w; i++){
for(k =y; k<y+h; k++){
if(c != boundBM.getPixel(i, k)) count++;
}
}
//funny thing
return (count>totalp/3) ? 1 : 0;
}
public void createNeuralInput(){
int h = boundBM.getHeight()/GRID;
int w = boundBM.getWidth()/GRID;
int[][] array= new int[GRID][GRID];
for(int i = 0; i < GRID; i++) {
for(int j = 0; j < GRID ; j++) {
n1.add(countPixels(i*h, j*w, h, w));
//i would prefer:
//array[i][j]=countPixels(i*h, j*w);
}
}
}

Delete some elements from the array

I need to delete elements from the array points. This is how I do this. The problem is that pts.length is always the same, and the removed elements have the value null. Therefore at some moment I receive the error message java.lang.NullPointerException.
for (int i = 0; i < points.length; i++) {
int ind = r.nextInt(pts.length);
TSPPoint pt = points[ind];
pts = removeElements(points,ind);
solPoints[i] = pt;
System.out.println(pts.length);
}
private static TSPPoint[] removeElements(TSPPoint[] input, int ind) {
List<TSPPoint> result = new LinkedList<TSPPoint>();
for(int i=0; i<input.length; i++)
if(i != ind)
result.add(input[i]);
return (TSPPoint[]) result.toArray(input);
}
What your code seems to (be supposed to) do is to remove random elements from the original array of points and append them to the pts array, i.e., create a permutation of points.
If this is the case, I suggest converting your array to a List and using Collections.shuffle.
#nrathaus has found the bug for you. It's simply that you've got your arrays confused (you're passing points into removeElements, but using pts everywhere else).
But if memory churn is being an issue, there's a much more efficient way to implement removeElements, using System.arraycopy rather than a temporary LinkedList.:
private static TSPPoint[] removeElements(TSPPoint[] input, int ind) {
TSPPoint[] rv;
if (ind >= 0 && ind < input.length) {
// New array will be one smaller
rv = new TSPPoint[input.length - 1];
if (rv.length > 0) {
// Copy the bit before the element we delete
if (ind > 0) {
System.arraycopy(input, 0, rv, 0, ind);
}
// Copy the rest
System.arraycopy(input, ind + 1, rv, ind, input.length - ind);
}
}
else {
// No change
rv = input;
}
return rv;
}
Mind you, if you're doing this a lot, creating and releasing all of these arrays may not be ideal. Using a List throughout may be better.
Wow, for deleting every element you recreate the rest of the array in a LinkedList, which you then turn into an array... The performance of this code, both in time and space, is terrible and so is readability, maintainability and testability.
Why not drop using arrays all together?.. convert points into an ArrayList and use remove(index) directly on that list and use an iterator of the llist to remove multiple elements as you iterate through?

Categories