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?
Related
So for this extra credit problem in my calculus class, my other nerdy classmates and I decided that we would build a program to brute force a solution. One of these steps involves permutations. Through this algorithm, I managed to get it to work (I think):
public void genPermutations(int[] list, int k){
System.out.println("List: " + Arrays.toString(list));
System.out.println("----------------------");
if(k > list.length){
System.out.println("Not enough elements!");
return;
}
int[] counts = new int[list.length];
for(int i = 0; i < counts.length; i++){
counts[i] = 1;
}
int[] data = new int[k];
permutationHelper(list, counts, data, 0, k);
}
public void permutationHelper(int[] list, int[] counts, int[] data, int index, int k){
if(index == k){
//System.out.println(Arrays.toString(data));
permutations.add(data);
}else{
for(int i = 0; i < list.length; i++){
if(counts[i] == 0){
continue;
}
data[index] = list[i];
counts[i]--;
permutationHelper(list, counts, data, index + 1, k);
counts[i]++;
}
}
}
I have an ArrayList that stores all of the possible permutations (as integer arrays) that can be made from k elements of the list that I pass into the function. The problem is that if I print all of these permutations outside of the function, say after I call the genPermutations function, every permutation now is the same. But, when I print out the data where the comment is in the permutationHelper function, it correctly lists every possible permutation; I'm just unable to access them within the program later. My question is why are the values changing when I exit the function? Any help would be greatly appreciated.
Here are some pictures:
What is printed where the comment is.
What is printed later in the program.
The code used to print everything outside of the function is:
for(int i = 0; i < permutations.size(); i++){
System.out.println(Arrays.toString(permutations.get(i)));
}
I don't really know if that's necessary to know, but I just thought I'd include it just in case. Thanks in advance.
You're constantly modifying the same array object. Instead of adding different arrays to your list, you're in fact adding a reference to the same array over and over again.
To fix, instead of adding the data array to your list, you would have to add a copy of it, e.g. using Arrays.copyOf():
permutations.add(Arrays.copyOf(data, data.length));
Here the problem is that you are modifying the array after adding it to the list, you are modifying the same object again and again in different iterations. You were getting [3,2,1] in the list is because that was the outcome from last iteration. So as a fix you can use the following code. What it does is it will create a copy of data array and add that to the list.
int[] temp = Arrays.copyOf(data, data.length);
permutations.add(temp);
OR you can use clone() from array as follows.
int[] temp = data.clone();
permutations.add(temp);
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.
So given a string such as: 0100101, I want to return a random single index of one of the positions of a 1 (1, 5, 6).
So far I'm using:
protected int getRandomBirthIndex(String s) {
ArrayList<Integer> birthIndicies = new ArrayList<Integer>();
for (int i = 0; i < s.length(); i++) {
if ((s.charAt(i) == '1')) {
birthIndicies.add(i);
}
}
return birthIndicies.get(Randomizer.nextInt(birthIndicies.size()));
}
However, it's causing a bottle-neck on my code (45% of CPU time is in this method), as the strings are over 4000 characters long. Can anyone think of a more efficient way to do this?
If you're interested in a single index of one of the positions with 1, and assuming there is at least one 1 in your input, you can just do this:
String input = "0100101";
final int n=input.length();
Random generator = new Random();
char c=0;
int i=0;
do{
i = generator.nextInt(n);
c=input.charAt(i);
}while(c!='1');
System.out.println(i);
This solution is fast and does not consume much memory, for example when 1 and 0 are distributed uniformly. As highlighted by #paxdiablo it can perform poorly in some cases, for example when 1 are scarce.
You could use String.indexOf(int) to find each 1 (instead of iterating every character). I would also prefer to program to the List interface and to use the diamond operator <>. Something like,
private static Random rand = new Random();
protected int getRandomBirthIndex(String s) {
List<Integer> birthIndicies = new ArrayList<>();
int index = s.indexOf('1');
while (index > -1) {
birthIndicies.add(index);
index = s.indexOf('1', index + 1);
}
return birthIndicies.get(rand.nextInt(birthIndicies.size()));
}
Finally, if you need to do this many times, save the List as a field and re-use it (instead of calculating the indices every time). For example with memoization,
private static Random rand = new Random();
private static Map<String, List<Integer>> memo = new HashMap<>();
protected int getRandomBirthIndex(String s) {
List<Integer> birthIndicies;
if (!memo.containsKey(s)) {
birthIndicies = new ArrayList<>();
int index = s.indexOf('1');
while (index > -1) {
birthIndicies.add(index);
index = s.indexOf('1', index + 1);
}
memo.put(s, birthIndicies);
} else {
birthIndicies = memo.get(s);
}
return birthIndicies.get(rand.nextInt(birthIndicies.size()));
}
Well, one way would be to remove the creation of the list each time, by caching the list based on the string itself, assuming the strings are used more often than they're changed. If they're not, then caching methods won't help.
The caching method involves, rather than having just a string, have an object consisting of:
current string;
cached string; and
list based on the cached string.
You can provide a function to the clients to create such an object from a given string and it would set the string and the cached string to whatever was passed in, then calculate the list. Another function would be used to change the current string to something else.
The getRandomBirthIndex() function then receives this structure (rather than the string) and follows the rule set:
if the current and cached strings are different, set the cached string to be the same as the current string, then recalculate the list based on that.
in any case, return a random element from the list.
That way, if the list changes rarely, you avoid the expensive recalculation where it's not necessary.
In pseudo-code, something like this should suffice:
# Constructs fastie from string.
# Sets cached string to something other than
# that passed in (lazy list creation).
def fastie.constructor(string s):
me.current = s
me.cached = s + "!"
# Changes current string in fastie. No list update in
# case you change it again before needing an element.
def fastie.changeString(string s):
me.current = s
# Get a random index, will recalculate list first but
# only if necessary. Empty list returns index of -1.
def fastie.getRandomBirthIndex()
me.recalcListFromCached()
if me.list.size() == 0:
return -1
return me.list[random(me.list.size())]
# Recalculates the list from the current string.
# Done on an as-needed basis.
def fastie.recalcListFromCached():
if me.current != me.cached:
me.cached = me.current
me.list = empty
for idx = 0 to me.cached.length() - 1 inclusive:
if me.cached[idx] == '1':
me.list.append(idx)
You also have the option of speeding up the actual searching for the 1 character by, for example, useing indexOf() to locate them using the underlying Java libraries rather than checking each character individually in your own code (again, pseudo-code):
def fastie.recalcListFromCached():
if me.current != me.cached:
me.cached = me.current
me.list = empty
idx = me.cached.indexOf('1')
while idx != -1:
me.list.append(idx)
idx = me.cached.indexOf('1', idx + 1)
This method can be used even if you don't cache the values. It's likely to be faster using Java's probably-optimised string search code than doing it yourself.
However, you should keep in mind that your supposed problem of spending 45% of time in that code may not be an issue at all. It's not so much the proportion of time spent there as it is the absolute amount of time.
By that, I mean it probably makes no difference what percentage of the time being spent in that function if it finishes in 0.001 seconds (and you're not wanting to process thousands of strings per second). You should only really become concerned if the effects become noticeable to the user of your software somehow. Otherwise, optimisation is pretty much wasted effort.
You can even try this with best case complexity O(1) and in worst case it might go to O(n) or purely worst case can be infinity as it purely depends on Randomizer function that you are using.
private static Random rand = new Random();
protected int getRandomBirthIndex(String s) {
List<Integer> birthIndicies = new ArrayList<>();
int index = s.indexOf('1');
while (index > -1) {
birthIndicies.add(index);
index = s.indexOf('1', index + 1);
}
return birthIndicies.get(rand.nextInt(birthIndicies.size()));
}
If your Strings are very long and you're sure it contains a lot of 1s (or the String you're looking for), its probably faster to randomly "poke around" in the String until you find what you are looking for. So you save the time iterating the String:
String s = "0100101";
int index = ThreadLocalRandom.current().nextInt(s.length());
while(s.charAt(index) != '1') {
System.out.println("got not a 1, trying again");
index = ThreadLocalRandom.current().nextInt(s.length());
}
System.out.println("found: " + index + " - " + s.charAt(index));
I'm not sure about the statistics, but it rare cases might happen that this Solution take much longer that the iterating solution. On case is a long String with only a very few occurrences of the search string.
If the Source-String doesn't contain the search String at all, this code will run forever!
One possibility is to use a short-circuited Fisher-Yates style shuffle. Create an array of the indices and start shuffling it. As soon as the next shuffled element points to a one, return that index. If you find you've iterated through indices without finding a one, then this string contains only zeros so return -1.
If the length of the strings is always the same, the array indices can be static as shown below, and doesn't need reinitializing on new invocations. If not, you'll have to move the declaration of indices into the method and initialize it each time with the correct index set. The code below was written for strings of length 7, such as your example of 0100101.
// delete this and uncomment below if string lengths vary
private static int[] indices = { 0, 1, 2, 3, 4, 5, 6 };
protected int getRandomBirthIndex(String s) {
int tmp;
/*
* int[] indices = new int[s.length()];
* for (int i = 0; i < s.length(); ++i) indices[i] = i;
*/
for (int i = 0; i < s.length(); i++) {
int j = randomizer.nextInt(indices.length - i) + i;
if (j != i) { // swap to shuffle
tmp = indices[i];
indices[i] = indices[j];
indices[j] = tmp;
}
if ((s.charAt(indices[i]) == '1')) {
return indices[i];
}
}
return -1;
}
This approach terminates quickly if 1's are dense, guarantees termination after s.length() iterations even if there aren't any 1's, and the locations returned are uniform across the set of 1's.
for(int i = 0; i < bag.length; i++)
{
if(bag[i].equals(a))
{
tmp = bag[i];
bag[i] = bag[bag.length-1];
bag[bag.length-1] = tmp;
numElements--;
break;
}
}
The goal of this is to find an object in the array and then remove it? is it possible??
Changing the length of an array is not possible. Recall that array is a static data structure whose size is determined before hand. Increasing or decreasing is not supported in this data structure. The fact that one has to increase or decrease the size depending on the usecase means that they have picked up the wrong data structure. They should perhaps go with an ArrayList.
Anyway, coming back to your question, you can simulate the 'size decrease' by maintaining a variable which you let track the array index and decrease the size of this variable. This lets you give the impression of shrinking the array.
The code you have provided does the same. Note however, that you should be using this modified index to track the contents of your array.
for(int i = 0; i < bag.length; i++)
{
if(bag[i].equals(a))
{
tmp = bag[i];
bag[i] = bag[bag.length-1];
bag[bag.length-1] = tmp;
numElements--;
break;
}
}
Whenever a particular bag at a given index equals to the item under question i.e., 'a', we swap elements so that the current bag element to be removed moves to the last and also we reduce the size of our new index - numElements by 1 to simulate this.
If you have the full code with you, please consider adding the following snippet at the end of that program to understand this more:
// Simulation of the array shrinking.
for(int i = 0; i < numElements; i++)
{
System.out.println( bag[i] );
}
// Movement of uninteresting elements to the end of the array.
for(int i = 0; i < bag.length; i++)
{
System.out.println( bag[i] );
}
It's not possible to change the length of an array. You can overwrite the element you wish to remove with the last element of the array and then copy the first bag.length - 1 elements of your array to a new array whose length is bag.length - 1.
for(int i = 0; i < bag.length; i++) {
if(bag[i].equals(a)) {
bag[i] = bag[bag.length-1];
bag = Arrays.copyOf (bag, bag.length - 1);
break;
}
}
public static String[] removeElements(String[] input) {
List<String> result = new ArrayList<String>();
String deleteValue = "somevalue";
for(String item : input)
if(!deleteValue .equals(item))
result.add(item);
return result.toArray(input);
}
This is one method you can fit this into your program.
You cannot decrease the size of an array. okay no problem! you can create your own data structure which supports that right?
Now, create a class named say MyArray with functions like increaseLenght(int) and decreseLength(int). Try it if you want to, will be fun for sure..
You cannot reduce the size of an array. Arrays are fixed length. What you can do is have a variable that indicates how many entries of the array you are using. This is what you are doing with numElements. The standard class ArrayList is implemented like this. The data is kept in an array and a private field size is used. With an ArrayList, when you remove an element, all the elements to the right are shifted left. However I also like your idea.
I would suggest 2 changes.
Make the last element null instead. If you are removing the element, why does it still need to be in the array?
Use numElements - 1 rather than bag.length-1 as the array could be bigger.
With these changes it becomes:
for(int i = 0; i < bag.length; i++)
{
if(bag[i].equals(a))
{
bag[i] = bag[numElements-1];
bag[numElements-1] = null;
numElements--;
break;
}
}
I have to implement a Selection Sort in Java according to these parameters:
Implement a variation to the SelectionSort that locates both the smallest and largest elements while scanning the list and positions them at the beginning and the end of the list, respectively. On pass number one, elements x0,...,xn-1 are scanned; on pass number two, elements x1,...,xn-2 are scanned; and so on.
I am passing the method an array of size 32, and when I print the array it is not sorted. What's the matter with my code?
static void selectionSort() {
scramble();
int smallIndex = 0; //index of smallest to test
int largeIndex = array.length - 1; //index of largest to test
int small = 0; //smallest
int large; //largest
int smallLimit = 0; //starts from here
int largeLimit = array.length - 1; //ends here
int store; //temp stored here
int store2;
for(int i = 0; i < array.length/2; i++) { //TODO not working...
small = array[smallLimit];
large = array[largeLimit];
for(int j = smallLimit; j <= largeLimit; j++) {
if(array[j] < small) {
smallIndex = j;
small = array[j];
}
else if(array[j] > large) {
largeIndex = j;
large = array[j];
}
}
store = array[smallLimit];
store2 = array[smallIndex];
array[smallLimit] = store2;
array[smallIndex] = store;
store = array[largeLimit];
array[largeLimit] = array[largeIndex];
array[largeIndex] = store;
smallLimit++;
largeLimit--;
}
print();
}
Think about the extreme cases: what happens when the largest or smallest item is found at smallLimit or largeLimit. When that happens you have two problems:
largeIndex and smallIndex are not set. They maintain their values from a previous iteration.
Swapping the smallest item to its correct place moves the largest item. The second swap moves the smallest item where the largest should go, and the largest ends up in a random location. Step through the code on paper or in a debugger if you find this hard to visualize.
These problems are easy to fix. You could have avoided the problem following a few guidelines:
Use fewer moving parts. You can always get the value of small using smallIndex, if you just used smallIndex there would be no danger of different variables falling out of step.
Declare the variables in the smallest possible scope. If smallIndex was declared in the loop body and not outside the compiler would have told you there's a chance it was not set before the swap.
Destructive updates like the first swap here can always make a previous calculation obsolete. When you can't avoid this from happening, look for ways two updates can step on each other's toes.
Like #Joni, clearly pointed out, there is big caveat with swapping two elements twice during a traversal of the array. Since you have to implement the sorting algorithm in-place, you need to take into account the positions of the elements to be swapped as it happens in succession.
Another limiting case that you need to see is when there are just three elements left i.e. the last iteration of the for loop. This is how I would go about it:
store = array[smallLimit];
store2 = array[smallIndex];
array[smallLimit] = small;
array[smallIndex] = store;
smallLimit++;
//No problem with swapping the first two elements
store = array[largeLimit];
//However the first swap might cause the other elements to shift
//So we do this check
if((array[largeIndex] == large))
{array[largeLimit] = array[largeIndex];
array[largeIndex] = store;
largeLimit--;
}
//Just a limiting case, where amongst the last three elements, first swap happens.
//The smallest element is in place, just take care of the other two elements.
if(largeLimit - smallLimit == 1){
if(array[largeLimit] != large){
array[smallLimit] = array[largeLimit];
array[largeLimit] = large;
largeLimit--;
}
}
Working DEMO for the snippet mentioned above, building upon your code. Hope it gets you started in the right direction.