need assistance with recursive method in Java - java

I'm kinda new to programming and need help doing a recursive method.I have a method that picks a random space in a 2d array and then I want to check if the space is free.If the space is free I want to use that space but if it isn't I want to pick a new random space in the 2d array.Thanks
import java.io.* ;
import java.util.ArrayList ;
public class WordSearchPuzzle
{
private char[][] puzzle ;
private ArrayList<String> puzzleWords ;
private int letterCount = 0 ;
private int gridDimensions;
public WordSearchPuzzle(ArrayList<String> userSpecifiedWords)
{
this.puzzleWords = userSpecifiedWords ;
}
private void createPuzzleGrid()
{
int i, itemLength;
String item;
for (i = 0; i < puzzleWords.size(); i++) {
item = puzzleWords.get(i);
itemLength = item.length();
letterCount = letterCount + itemLength;
}
gridDimensions = letterCount * 2;
puzzle = new char[gridDimensions][gridDimensions] ;
}
private void generateWordSearchPuzzle()
{
}
public void firstSpace(String Word)
{
int row, column;
row = (int)(Math.random() * gridDimensions +1);
column = (int)(Math.random() * gridDimensions +1);
if(puzzle[row][column] != ' '){
firstSpace();
}
}

The specific issue you mentioned in the comments is because the firstSpace method needs to have a string as a parameter. You should use:
firstSpace(word);
Also be aware that this method doesn't currently return anything so you have no way of knowing which space it chose.

I don't think adding 1 in your index calculations is necessary and could perhaps cause an array out of bounds exception. Although, that depends on your definition of gridDimensions.
The problem you specified in the comments is because the Java compiler was trying to find a method named 'void firstSpace()', this is a different method that 'void firstSpace(String word)'.
public void firstSpace(String word)
{
int row, column;
// No need to add 1, Java arrays are accessed with the first index
// being 0. Math.random() returns from 0 up to but not including 1.0.
// e.g. array size = 50, min index = 0, max index = 49
// Lets say you get very close to 1 e.g. 0.9999, then
// 0.9999 * 50 = 49.995 (after integer truncating you have 49)
row = (int)(Math.random() * gridDimensions);
column = (int)(Math.random() * gridDimensions);
if(puzzle[row][column] != ' ') {
// If this element is not "empty" then run the method again
// using recursion. null might be a better choice to compare
// to depending on how you initialized the array.
firstSpace(word);
} else {
// Otherwise we're finished and we can set the array element
// to the new word.
// (Assumed post condition (you might want to do something else once you
// find a blank index))
puzzle[row][column] = word;
}
}

Related

A method that returns an array with no duplicates

I am supposed to implement a method in Java that returns an array of integers with no duplicates. I have managed to do it, but my solution seems rather long. I would like to know of ways to improve it.
I added comments so it is easier for your guys to understand what the code does.
public class IntArrayProcessor {
private int[] a;
public IntArrayProcessor(int[] a) {
this.a = a;
}
/**
*
* #return Array with no repeated integers.
*/
public int[] getSet() {
/* creates an array with the same entries and length as this.a */
int[] duplicateA = new int[this.a.length];
/* stores the number of repeated entries in array this.a */
int numberOfDuplicates = 0;
/* is the integer a duplicate or not? */
boolean isDuplicate;
/**
* Counts the number of duplicates in array this.a
*/
for (int i = 0; i < this.a.length; i++) {
duplicateA[i] = this.a[i];
}
for (int i = 0; i < duplicateA.length; i++) {
isDuplicate = false;
for (int j = i + 1; j < this.a.length; j++) {
if (duplicateA[i] == this.a[j]) {
isDuplicate = true;
}
}
if (isDuplicate) {
numberOfDuplicates++;
}
}
/*
* the noDuplicate array has the lenght of the this.a array minus the
* number of repeated entries
*/
int[] noDuplicate = new int[this.a.length - numberOfDuplicates];
/* to keep track of the noDuplicate indexes */
numberOfDuplicates = 0;
/**
* An array with no repeated numbers
*/
for (int i = 0; i < duplicateA.length; i++) {
isDuplicate = false;
for (int j = i + 1; j < this.a.length; j++) {
if (duplicateA[i] == this.a[j]) {
isDuplicate = true;
}
}
if (!(isDuplicate)) {
noDuplicate[numberOfDuplicates] = duplicateA[i];
numberOfDuplicates++;
}
}
return noDuplicate;
}
}
An easy solution is to use the Stream API:
int[] distinctArray = IntStream.of(a).distinct().toArray();
If you don't want to use Stream API you can use a HashSet (or other collections that implement the Set interface).
Set<Integer> set = new HashSet<Integer>(Arrays.asList(array));
That is some rather long code! It seems like you are looking for a more homemade solution than the one that Max put up! Here is some psuedo-code for what I would do:
1. Create a dictionary that takes an int and returns a boolean.
2. For every element in your starting array add it to the dictionary with the boolean value of true (even though the value won't actually matter).
3. Find the number of keys in your dictionary (this will be the number of unique values found in the first array, which is also the length of your new array)
4. Create a new array given the length found in the previous step.
5. Run through each of the keys in the dictionary and add it to the new array!
Shortcut: Instead of step 4 & 5 typically getting the keys from the dictionary will return an array, which would be your end solution.
I'd be happy to write up a more formal solution if that is more helpful.
Note: If you are only familiar with Java, Dictionaries are almost synonymous to HashMaps and can be used interchangeably in this situation. Java's default implementation of a dictionary is called a HashMap
Note 2: Accessing the number of keys/getting all of the keys in a Dictionary/HashMap should be a function built-in, not one you have to write!

GC overhead limit exceeded - Arrays

i get this error after waiting long time for my code to execute and its pointing me to this method
public Iterable<Board> neighbors() {
Queue<Board> q = new LinkedList<>();
int n = dimension();
int x = 0, y = 0;
outer:
// do some stuff to get the x and y
if (y+1 < n) {
the line where i get the error -> int [][]arr = new int[n][n];
for (int i = 0; i < tiles.length; i++) {
arr[i] = Arrays.copyOf(tiles[i], n);
}
// do some stuff
Board br = new Board(arr);
if(!this.equals(br)) {
q.add(new Board(arr));
}
}
if (y-1 >= 0) {
int [][]arr = new int[n][n];
for (int i = 0; i < tiles.length; i++) {
arr[i] = Arrays.copyOf(tiles[i], n);
}
// do some stuff
Board br = new Board(arr);
if(!this.equals(br)) {
q.add(new Board(arr));
}
}
if (x-1 >= 0) {
int [][]arr = new int[n][n];
for (int i = 0; i < tiles.length; i++) {
arr[i] = Arrays.copyOf(tiles[i], n);
}
// do some stuff
Board br = new Board(arr);
if(!this.equals(br)) {
q.add(new Board(arr));
}
}
if (x+1 < n) {
int [][]arr = new int[n][n];
for (int i = 0; i < tiles.length; i++) {
arr[i] = Arrays.copyOf(tiles[i], n);
}
// do some stuff
Board br = new Board(arr);
if(!this.equals(br)) {
q.add(new Board(arr));
}
}
return q;
}
i basically need to copy tiles array and make changes to the copy "arr" but keep the tiles array without changing to use it later..i really don't like the way i'm doing it copying and pasting code i think its inefficient but no other way comes to my mind so i would like to know why i get this error "i know its because GC taking more time and not doing alot" but i want to know why its happening in this case also if there is better way to copy the array.
also i increased the heap memory to -Xmx1600m
Thanks for your time.
The Problem
It is likely that the problem arises from creating a lot of objects in a short period of time. See this answer for more information.
At the moment, one Board consist of at least four objects:
The Board itself
The array arr inside the board
The three arrays inside arr
Creating Less Objects
Our goal is to create fewer objects (arrays). Since you want to deal with small boards only, we could use one long to store the complete 3×3 board. A long has 64 bit. We use 64 / 9 = 7 bits per field to store the value on that field:
state = ... 0000100 0000011 0000010 0000001 0000000
4th field ↑ 2nd field ↑ 0th field
3rd field 1st field
The following class handles the bit operations.
class Board {
private final static int SIDE_LENGTH = 3;
private final static int FIELDS = SIDE_LENGTH * SIDE_LENGTH;
private final static int BITS_PER_FIELD = 64 / FIELDS;
private final static long FIELD_MASK = (1 << BITS_PER_FIELD) - 1;
private long state;
public Board() {
for (int field = 0; field < FIELDS; ++field) {
set(field, field);
}
}
/** Copy constructor. */
public Board(Board other) {
this.state = other.state;
}
public int get(int x, int y) {
return get(coordinatesToField(x, y));
}
public void set(int x, int y, int value) {
set(coordinatesToField(x, y), value);
}
private int coordinatesToField(int x, int y) {
return SIDE_LENGTH * y + x;
}
private int get(int field) {
return (int) ((state >>> (field * BITS_PER_FIELD)) & FIELD_MASK);
}
private void set(int field, int value) {
int shift = field * BITS_PER_FIELD;
state &= ~(FIELD_MASK << shift);
state |= (long) value << shift;
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (int field = 0; field < FIELDS; ++field) {
sb.append(get(field));
sb.append((field + 1) % SIDE_LENGTH == 0 ? "\n" : "\t");
}
return sb.toString();
}
// TODO implement equals and hashCode
}
When using this class, you don't have to deal with arrays anymore, which saves not only a lot of objects, but also the copy code in your prorgram.
The class also works for 1×1, 2×2, and 4×4 boards, but not for larger ones due to the 64 bit limit.
Usage Examples
public static void main(String[] args) {
// Create and print the initial board
// 0 1 2
// 3 4 5
// 6 7 8
Board b = new Board();
System.out.println(b);
// Copy an existing board
Bord copy = new Board(b);
// Set the upper right field to value 8
copy.set(2, 0, 8);
// Print the center field
// 4
Syste.out.println(copy.get(1, 1));
}
Additional Ideas
You even could avoid creating Board objects at all, and just store the long values. But that doesn't help when you are using generics (such as LinkedList) because of Java's auto boxing.
Also note that LinkedList wraps each entry in an additional node object. Maybe you can use a more efficient DataStructure like a circular buffer.
Depending on what you are doing, you might as well have a look at the Flyweight design pattern.

Need help developing a proper print method for this Java program

This program takes integers from user input and puts them in a collection. It then prints the positive values first, then the negative values, and doesn't print repeated numbers. It stops asking for input once the user enters 0. Here is the code:
public class Intcoll2
{
private int[] c;
private int[] d;
private int howmany = 0;
public Intcoll2()
{
c = new int[500];
}
public Intcoll2(int i)
{
c = new int[i]
}
public void insert(int i)
{
if (i > 0)
{
int j = 0;
while ((j <= howmany) && (c[j] != i)) j++;
if (j == howmany)
{
if (j == c.length - 1)
{
d = new int[2*c.length];
for (int k = 0; k<c.length; i++){
d[k] = c[k];
}
c = d;
}
c[j] = i; c[j + 1] = 0;
}
howmany++;
}
}
public int get_howmany()
{
int j=0, howmany=0;
while (c[j]!=0) {howmany++; j++;}
return howmany;
}
Now my current print method looks like this:
public void print()
{
int j = 0;
System.out.println();
while (j <= howmany)
{
System.out.println(c[j]); j++;
}
}
But when I try to use that in my client, it only prints out zeros. Any help with what I'm doing wrong would be greatly appreciated.
An answer that you were probably not looking for, but still on the only real answer you should care about.
Your problem is not that somewhere in that code a bug is hiding. The problem is that your code is confusing beyond limits:
Dont use single-character variable names.
The constructor that takes an int ... creates an empty array!
Dont say "collection" when you are using arrays.
Dont give fields and local variables the same name.
Seriously: understanding this mess is mainly complicated and hard because you wrote code that is hard to read.
Now you are asking other people to debug such complicated code that you (the author who created it!) do not understand in the first place.
Instead, you might throw this whole thing away. And slowly write it again; but in a way that isn't at all confusing to the reader.
I took a look at your class and rewrote it in a more legible manner. I didn't test it but I'm confident it works. You can check it out and hopefully understand what's happening. Hope this helps!
public class IntCollection2 {
private int[] collection; // A large allocation, not neccessarily filled up.
private int currentSize; // The number of spots currently filled in the collection.
public IntCollection2() {
collection = new int[500];
currentSize = 0;
}
public IntCollection2(int size) {
collection = new int[size];
currentSize = 0;
}
/**
* Inserts a new element into the internal array. If the current array is filled up,
* a new array double the size of the current one is allocated.
* #param element An int to insert into the collection. Must not be '0'.
* #return True if the element was successfully inserted, false if the element was
* equal to '0' and was ignored.
*/
public boolean insert(int element) {
if (element != 0) {
if (currentSize < collection.length - 1) {
collection[currentSize] = element;
} else {
int[] newCollection = new int[collection.length * 2];
for (int i = 0; i < currentSize; i++) {
newCollection[i] = collection[i];
}
newCollection[currentSize] = element;
collection = newCollection;
}
currentSize++;
return true;
} else {
return false;
}
}
/**
* Not actually necessary because the class automatically updates its currentSize
* every time a new element is inserted.
* #return The current number of filled spots in the internal array.
*/
public int getCurrentSize() {
int size = 0;
for (int i = 0; i < collection.length && collection[i] != 0; i++) {
size++;
}
return size;
}
/**
* Prints out all the elements currently in the collection, one on each line.
*/
public void print() {
System.out.println();
for (int i = 0; i < currentSize; i++) {
System.out.println(collection[i]);
}
}
}
FYI: this class just prints out every element in the collection, in order. You mentioned something about printing positive then negative values, but I leave that to you.
EDIT: I'm guessing you're brand new to programming, so I just want to clarify exactly what a collection is. An array is an ordered list of elements. When you create an array, the computer sets aside a bit of memory to hold exactly the number of elements you told it to. You cannot change the size of an existing array. A collection is basically a wrapper around an array. It makes a bigger array than it needs to hold its elements, and when its array becomes full, it allocates a new, bigger one that can hold more elements.

Creating multiple nested loops to generate two numbers that move through the length of a Array

As the title reads, I have been thinking about creating multiple nested loops that aim to achieve one purpose. Move two generated random numbers between 0-9 through each possible possition of an array.
For example, App generates first number (fNum) 1 and second number (sNum) 6. It then moves these numbers in the array which containts ABC. However firstNum and secondNum will need to also try all the possible combinations, so each one will need to be different with each loop.
-1ABC6
-A1BC6
-AB1C6
-ABC16
-ABC61
-AB6C1
-A6BC1
-6ABC1
-A6B1C
-A61BC
-A16BC
-A1B6C
-A1BC6
and so on...
I beleive the best way will be to create a method for generating a counter, which increments the numbers which I can call.
private int getNextNumber(int num) {
if (num == 0) {
return num;
} else {
num++;
}
if (num < 10) {
return num;
} else {
return -1;
}
}
Then I will need multiple nested loops... I have decided to go for several loops which will go infinitly.
while (j < maxlen) {
//J = 0 and maxlen = length of text so in this case 3 as it is ABC
//Add two numbers and check against answer
while (fNum != -1 || sNum != -1) {
//incrememnt numbers
fNum = getNextNumber(fNum);
System.out.println(fNum);
sNum = getNextNumber(sNum);
System.out.println(fNum);
}
String textIni = "ABC";
int lenOfText = textIni.length();
char[] split = textIni.toCharArray();
for (int i = 0; i < lenOfText; i++) {
//here it will look at the length of the Text and
//try the possible positions it could be at....
//maybe wiser to do a longer loop but I am not too sure
}
}
Since you don't need to store all possible combinations, we will save some memory using only O(n) storage with an iterative solution. I propose you a basic implementation but don't expect to use it on large arrays since it has a O(n³) complexity.
public static void generateCombinationsIterative(List<Integer> original, int fnum, int snum) {
int size = original.size();
for (int i=0 ; i<=size ; i++) {
List<Integer> tmp = new ArrayList<>(original);
tmp.add(i,fnum);
for (int j=0 ; j<=size + 1 ; j++) {
tmp.add(j,snum);
System.out.print(tmp + (i == size && j == size + 1 ? "" : ", "));
tmp.remove(j);
}
}
}
For your culture, here is an example of a recursive solution, which takes a lot of memory so don't use it if you don't need to generate the lists of results. Nevertheless, this is a more general solution that can deal with any number of elements to insert.
public static List<List<Integer>> generateCombinations(List<Integer> original, Deque<Integer> toAdd) {
if (toAdd.isEmpty()) {
List<List<Integer>> res = new ArrayList<>();
res.add(original);
return res;
}
int element = toAdd.pop();
List<List<Integer>> res = new LinkedList<>();
for (int i=0 ; i<=original.size() ; i++)
// you must make a copy of toAdd, otherwise each recursive call will perform
// a pop() on it and the result will be wrong
res.addAll(generateCombinations(insertAt(original,element,i),new LinkedList<>(toAdd)));
return res;
}
// a helper function for a clear code
public static List<Integer> insertAt(List<Integer> input, int element, int index) {
List<Integer> result = new ArrayList<>(input);
result.add(index,element);
return result;
}
Note that I did not use any array in order to benefit from dynamic data structures, however you can call the methods like this :
int[] arr = { 1,2,3 };
int fnum = 4, snum = 5;
generateCombinationsIterative(Arrays.asList(arr),fnum,snum);
generateCombinations(Arrays.asList(arr),new LinkedList<>(Arrays.asList(fnum,snum));
Note that both methods generate the combinations in the same order.

Complex Java Permutation Generation Problem

I am trying to work out the best way to generate all possible permutations for a sequence which is a fixed number of digits and each digit has a different alphabet.
I have a number of integer arrays and each one can have different length and when generating the permutations only the values of the array can occupy the position in the final results.
A specific example is an int array called conditions with the following data:
conditions1 = {1,2,3,4}
conditions2 = {1,2,3}
conditions3 = {1,2,3}
conditions4 = {1,2}
conditions5 = {1,2}
and I want to create a 5 column table of all the possible permutations - this case 144 (4x3x3x2x2). Column 1 can only use the values from conditions1 and column 2 from conditions2, etc.
output would be :
1,1,1,1,1
1,1,1,1,2
1,1,1,2,1
1,1,1,2,2
1,1,2,1,1
.
.
through to
4,3,3,2,2
It's been too long since since I've done any of this stuff and most of the information I've found relates to permutations with the same alphabet for all fields. I can use that then run a test after removing all the permutations that have columns with invalid values but sounds inefficient.
I'd appreciate any help here.
Z.
Look ma, no recursion needed.
Iterator<int[]> permutations(final int[]... conditions) {
int productLengths = 1;
for (int[] arr : conditions) { productLengths *= arr.length; }
final int nPermutations = productLengths;
return new Iterator<int[]>() {
int index = 0;
public boolean hasNext() { return index < nPermutations; }
public int[] next() {
if (index == nPermutations) { throw new NoSuchElementException(); }
int[] out = new int[conditions.length];
for (int i = out.length, x = index; --i >= 0;) {
int[] arr = conditions[i];
out[i] = arr[x % arr.length];
x /= arr.length;
}
++index;
return out;
}
public void remove() { throw new UnsupportedOperationException(); }
};
}
Wrapping it in an Iterable<int[]> will make it easier to use with a for (... : ...) loop. You can get rid of the array allocation by doing away with the iterator interface and just taking in as argument an array to fill.

Categories