Need to work on an array recursively, trouble passing data, java - java

Ok, I am having a really beginner mistake here, but I can't think of what I need to do. I have an array permArray that I am recursively filling with possible permutations. I have a public method that gets the parameters ready, then I work on the array in the private method that calls itself to work on smaller and smaller parts.
The problem I am having, is how do I pass the finished array back to the public method. Would I return the array every time I am finished with the recursion (after I have placed the last element in each section, where the section size is 1).
Oh, and also, this is practice, not homework.
//todo:
//need to determine what is wrong with my array of linked lists
package wordchains;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.StringTokenizer;
import javax.xml.soap.Node;
/**
*
* #author Samuel French
*/
public class WordChains {
public static void main(String[] args) {
//variables
int numWords = -1; //This will hold the number of words the user is inputting
String userInput; //holds the user input to be broken up into a string array
//Get the user's input, 0 is the quit value
Scanner sc = new Scanner(System.in);
System.out.print("Enter number of words: ");
numWords = sc.nextInt();
System.out.println(">");
sc.nextLine();
userInput = sc.nextLine();
String[] inputWords = userInput.split("\\s+");
int numElements = inputWords.length;
int numOfPerms = numOfPerms(numElements);
//We will start by checking the last letter of the first word
char cTest;
int wordChecking = 0;
int[][] permArray = genPerms(numElements, numOfPerms);
for (int col = 0; col < numOfPerms; col++) {
System.out.println();
for (int row = 0; row < numElements; row++) {
System.out.print(permArray[col][row] + " ");
}
}
}
public static int numOfPerms(int numElements) {
int numOfPerms = numElements;
numElements--;
while (numElements > 0) {
numOfPerms = numOfPerms * numElements;
System.out.println(numOfPerms);
numElements--;
}
return numOfPerms;
}
public static int[][] genPerms(int numElements, int totPerms) {
int permArray[][] = new int[totPerms][numElements];
//either do it like this or create an array of head nodes
List<LinkedList<Integer>> elementsLeftList = new ArrayList<LinkedList<Integer>>();
LinkedList tempList = new LinkedList();
for (int x = 0; x < numElements; x++) {
tempList.addLast(x);
}
for (int x = 0; x < totPerms; x++) {
elementsLeftList.add((LinkedList<Integer>) tempList.clone());
}
return privateGenPerms(permArray,elementsLeftList,totPerms,0,0,totPerms);
}
private static void privateGenPerms(int[][] permArray, List<LinkedList<Integer>> elementsLeftList, int totalPermutations, int elementPlacing, int sectionBegin, int sectionSize) {
//variables-
//totalPermutations - the total number of permutations in the whole problem
//elementPlacing - the element currently being placed's position, corresponds to the rows of permArray
//elementPlacingIndex - the number of times the element currently being placed has been placed
//sectionSize - the size of the total working section. First time this is the # of permutations
//permCounter - this counter counts the permutation working with within the section
//sectionBegin - counts the beginning of the section working with
//2 Data structures:
//permArray - 2d the array of permutations
//elementsLeftList - list of lists of elements left, corresponds to each permutation
int totalNumberOfElements = permArray[0].length;
//
int numberOfElementsLeftToPlace = totalNumberOfElements - elementPlacing;
//
int permCounter = sectionBegin;
//Base case
if (numberOfElementsLeftToPlace == 1) {
for (int x = 0; x < totalPermutations; x++) {
permArray[x][totalNumberOfElements - 1] = (int) elementsLeftList.get(permCounter).remove(0); //may need to be a remove 1, not sure
}
return; //need to decide what I am going to do here
}
//
int elementPlacingIndex = 0;
int elementCurrentlyPlacing = 0; //could be a 1, don't remember
//
int numberOfTimesToPlaceWithinCol = (sectionSize / numberOfElementsLeftToPlace);
//
//
for (; permCounter < (sectionBegin + sectionSize); permCounter++) {
//when we need to switch to a different partition of the section
if (elementPlacingIndex == numberOfTimesToPlaceWithinCol) {
elementPlacingIndex = 0;
elementCurrentlyPlacing++;
}
permArray[permCounter][elementPlacing] = (int) elementsLeftList.get(permCounter).remove(elementCurrentlyPlacing);
elementPlacingIndex++;
}
for (int newSectionBegin = sectionBegin; newSectionBegin < (sectionBegin + sectionSize); newSectionBegin = newSectionBegin + numberOfTimesToPlaceWithinCol) {
privateGenPerms(permArray, elementsLeftList, totalPermutations, (elementPlacing + 1), newSectionBegin, (sectionSize / numberOfElementsLeftToPlace));
}
}
}

The array is passed-by-reference, so any changes you make in the private function will be permanent and you do not need to return the modified array again.
I have not looked at your logic to see if this is the correct way to do it in your case though.

Related

Find different index in arrays compare

I'm trying to learn a bit Java with tutorials and currently I'm struggling with piece of code where I should find on which index is difference between arrays (if there is difference at all)
My code
Scanner scanner = new Scanner(System.in);
int[] arrOne = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int[] arrTwo = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int sumArrOne = 0;
int index = 0;
boolean diff = false;
for (int k : arrOne) {
if (Arrays.equals(arrOne, arrTwo)) {
sumArrOne += k;
} else {
for (int i : arrTwo) {
if (k != i) {
index = i;
diff = true;
break;
}
}
}
}
if (diff) {
System.out.println("Found difference at " + index + " index.");
} else {
System.out.println("Sum: " + sumArrOne);
}
So, if arrays are identical I'm sum array elements in arrOne. If they are not identical -> must show at which index they are not.
With this code when I input
1 2 3 4 5
1 2 4 3 5
I should get that difference is at index 2 instead I've got index 1.
I'm not quite sure why and would be glad if someone point me out where is my mistake.
I updated your code. Looks like you're misunderstanding the concept of indexes yet.
Use one common index to check with in both arrays, in my example it's simply called i:
import java.util.Arrays;
import java.util.Scanner;
public class BadArray {
static private final int INVALID_INDEX = Integer.MIN_VALUE;
public static void main(final String[] args) {
try (final Scanner scanner = new Scanner(System.in);) {
final int[] arrOne = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
final int[] arrTwo = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int sumArrOne = 0;
int diffIndex = INVALID_INDEX;
final int minLen = Math.min(arrOne.length, arrTwo.length);
for (int i = 0; i < minLen; i++) {
sumArrOne += arrOne[i];
if (arrOne[i] != arrTwo[i]) {
diffIndex = i;
break;
}
}
if (diffIndex != INVALID_INDEX) {
System.out.println("Found difference at " + diffIndex + " index.");
} else if (arrOne.length != arrTwo.length) {
System.out.println("Arrays are equal but have different length!");
} else {
System.out.println("Sum: " + sumArrOne);
}
}
}
}
I also put the scanner into a try-resource-catch to handle resource releasing properly.
Note you could also do the array lengths comparison right at the start if different array lengths play a more crucial role.
You are trying to find out which index has the first difference so you should iterate via the index rather than using a for-each loop (aka enhanced for loop). The following method should work for this.
/**
* Returns the index of the first element of the two arrays that are not the same.
* Returns -1 if both arrays have the same values in the same order.
* #param left an int[]
* #param right an int[]
* #return index of difference or -1 if none
*/
public int findIndexOfDifference(int[] left, int[] right) {
// short-circuit if we're comparing an array against itself
if (left == right) return -1;
for (int index = 0 ; index < left.length && index < right.length ; ++index) {
if (left[index] != right[index]) {
return index;
}
}
return -1;
}
In your code you compare, where the indexes are different, not the values at the indexes. Also your code has several other issues. I'll try to go through them step by step:
// compare the whole array only once, not inside a loop:
diff = !Arrays.equals(arrOne, arrTwo));
if (!diff) {
// do the summing without a loop
sumArrOne = Arrays.stream(arrOne).sum();
} else {
// find the difference
// it could be the length
index = Math.min(arrOne.length, arrTwo.length);
// or in some different values
for (int i = 0; i < index; i++) { // do a loop with counter
if (arrOne[i] != arrTwo[i]) {
index = i;
break;
}
}
}
It doesn't matter that I set index here above the loop as it's value will be overwritten anyways inside the loop, if relevant.

How to use create 2 Array with User input with Std.readAllInts()

This is how it should work, i Put in put for the 1 st array like: 2 3 1 2 3 4 5 6 then 2 and 3 are row and colum and the rest are the values. Problem is the 1st array work, but when i reach EOF ( ctrl+z) then there is out of bound exception. Which mean i cant input value for the 2nd Array like the 1st one. I know there is anotherway where that i can declare array size first then value. But how could i fix this f i still want to usr StdIn.readAllInts() ?
public class MatrixMult {
public static void main(String[] args){
System.out.println("First Matrix Config");
int[] einGabeMatrix1= StdIn.readAllInts();
int zeileM1 = einGabeMatrix1[0];
int spalteM1 = einGabeMatrix1[1];
int[][] ersteMatrix= new int [zeileM1][spalteM1];
int k=2;
int sum;
for(int i=0;i<zeileM1-1;i++){
for(int j=0;j<spalteM1-1;j++){
ersteMatrix[i][j]=einGabeMatrix1[k];
k++;
}
}
System.out.println("Second Matrix Config");
int[] einGabeMatrix2 = StdIn.readAllInts();
int zeileM2 = einGabeMatrix2[0];
int spalteM2 = einGabeMatrix2[1];
int h=2;
int[][] zweiteMatrix= new int [zeileM2][spalteM2];
for(int m=0;m<zeileM2-1;m++){
for(int n=0;n<spalteM2-1;n++){
zweiteMatrix[m][n]=einGabeMatrix2[h];
h++;
}
}
int[][] ergebnisMatrix= new int [zeileM1][spalteM2];
for (int t = 0; t < zeileM1; t++) {
for (int c = 0; c < spalteM2; c++) {
sum = 0;
for (int d = 0; d < spalteM1; d++) {
sum = sum + ersteMatrix[t][d] * zweiteMatrix[d][c];
}
ergebnisMatrix[t][c] = sum;
}
}
for(int i=0;i<zeileM1;i++){
for(int j=0;j<spalteM1;j++){
System.out.println(ergebnisMatrix[i][j]);
}
}
}
}
// This is StdIn.readAllInts(), standard method by java.
public static int[] readAllInts() {
String[] fields = readAllStrings();
int[] vals = new int[fields.length];
for (int i = 0; i < fields.length; i++)
vals[i] = Integer.parseInt(fields[i]);
return vals;
}
It looks like the issue is coming from the fact that StdIn.readAllInts() reads until the EOF. There will be no values left to read by the time your code gets to the second call.
I would suggest instead using the StdIn.readInt() call to read each integer one at a time and then you can use it within your loop to read the exact number of values your need.
Here is an example of how you could get the first 2 integers to find your matrix size:
int zeileM1 = StdIn.readInt();
int spalteM1 = StdIn.readInt();
You will also need to apply this method in your for loops to read the data into the matrix.

trying to add the sum of random ints in a temporary array and have the highest sum be output

my program is a kind of game. It gives the user 3 boards(arrays) of random ints and has them choose which board they think has the highest sum of numbers all within a time limit. I cant figure out how to add the sums of the individual arrays by using a temp array. I'm honestly just really stuck and don't know where to go from here. Any help would be appreciated. Ive been at this for hours.
import java.lang.reflect.Array;
import java.util.Random;
import java.util.Scanner;
import java.util.Arrays;
public class game
{
static Scanner scan = new Scanner(System.in); // Holds a local scanner
private static int secondsLeft; // Number of seconds after each turn
private static int score = 0; // Score variable which you update
private static NonBlockingHasNext t = new NonBlockingHasNext(); // Special class for timer
private static int [][][] gameBoard = new int [3][3][3]; // TODO 2: Initialize to a new 3x3x3 array
//static int row = 0;
//static int column = 0;
//static int depth = 0;
public static void main(String[] args)
{
// Give user instructions and begin
System.out.println("You will be presented 3 3x3 boards of random numbers, labeled 1, 2 and 3.");
System.out.println("Quickly select the board you believe to contain the largest sum of 9 numbers" +
" by entering the board number and pressing enter");
System.out.println("Press any key and hit enter to begin...");
scan.nextLine();
int numTurns = 10;
for (int i = 0; i < numTurns; i++)
{
reInit3dBoard();
print3dBoard(i, numTurns);
int choiceMade = countDownTimer();
choiceMade--; // Decrement to match with 0-indexed arrays
analyzeChoice(choiceMade);
}
}
//////////////////////////////////////////////////////
// countDownTimer() counts down from 10 seconds. Returns
// the user input if the value that is input is a 1, 2
// or 3. If the value is something else or no value is
// input, this method returns a -1.
//////////////////////////////////////////////////////
private static int countDownTimer()
{
// Some really complicated stuff to work around Java shortcomings.
// Basically, this code creates a new "thread" which allows us to
// run other code while a scanner in NonBlockingHasNext is waiting
// for a user input.
t = new NonBlockingHasNext();
(new Thread(t)).start();
System.out.println("Seconds left to make choice: ");
for (int i = 10; i > 0; i--)
{
secondsLeft = i;
System.out.print(secondsLeft + "...");
// Sleep for 1 second and....
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace(); }
// ...check again for input. If received a valid input in time, then return it
if (t.hasNext())
{
// Make sure choice is valid (1, 2 or 3)
int choice = t.nextInt(); //scan.nextInt();
if (choice >= 1 && choice <= 3)
{
System.out.println("\nYou chose grid #" + choice + " with " + secondsLeft + " seconds left!");
return choice;
}
}
}
// If we get here, then no choice was made!
System.out.println("\nNo choice made!");
return -1; // If no valid choice made
}
//////////////////////////////////////////////////////
// Simply assigns each element of the 3x3x3 3D board
// a random number from 1-9 (should not see 0's or 10's)
//////////////////////////////////////////////////////
private static void reInit3dBoard(){
Random rand = new Random();
{
for(int row=0;row<gameBoard.length; ++row){
for(int column=0;column<gameBoard[row].length; ++column){
for(int depth=0;depth<gameBoard[row][column].length; ++depth )
gameBoard[row][column][depth]=rand.nextInt(9)+1;
}
}
}
}
// TODO 3: Generate a random assignment of the gameBoard variable
// (see member variables) as described in the method header above.
// NOTE: You can just overwrite the values there.
private static int[][] randomFill() {
// TODO Auto-generated method stub
return null;
}
//////////////////////////////////////////////////////
// Prints the 3x3x3 3D board out to the console. It
// should print 3 2d boards. The line directly above each board
// should be labeled "Board 1:", "Board 2:" or "Board 3:".
// The line directly below each board should be blank.
//////////////////////////////////////////////////////
private static void print3dBoard(int turn, int numTurns)
{
System.out.println("--------------------------Turn " + (turn+1) + "/" + numTurns + "--------------------------");
for(int row=0; row<gameBoard.length; ++row)
{
System.out.println("\n\nboard:"+ row);
//System.out.println(Arrays.deepToString(gameBoard));
for(int column=0; column<gameBoard.length; ++column)
{System.out.println();
for(int depth=0; depth<gameBoard.length; ++depth)
{System.out.print(gameBoard[row][column][depth]);
}
}
}
}
// TODO 4: Print out the 3d board as described in the method header above.
// Make sure to label the boards 1-3 and not 0-2.
//////////////////////////////////////////////////////
// This method analyzes the choice made by the user
// conveniently passed into us for array-indexing purposes
// as a 0, 1 or 2.
//////////////////////////////////////////////////////
private static void analyzeChoice(int choiceMade)
{
// TODO 5: Create a counter array and use several FOR loops
// to compute the sum of each of the 3 boards.
int temp [][][] = new int [3][3][3];
temp = gameBoard;
int sum = 0;
// TODO 6: From your counter array, compute the max score
// TODO 7: Print out the score of all three boards (e.g., "Board 1 value: 34"). Number
// the boards 1-3 b/c this is what the user saw when selecting.
// Next to the selected board, add the string "(Right)" or "(Wrong)" if their guess
// was correct (i.e., the max board). Also, update the score by adding the number
// of seconds left when the guess was made.
// HINT: At this point, the member variable "score" holds the current score and the
// member variable "secondsLeft" holds the seconds left when the last selection was made.
// Print out the current score
System.out.println("\n***Current Score: " + score);
}
}
Just think of each board as 27 different variables. For example:
int space1 =gameBoard[1][1][1]
int space2 =gameBoard[1][1][2]
.
.
.
.
.
int space27 =gameBoard[3][3][3]
Then just add up spaces 1-27
This would be much easier than using a temporary array
If you want, you can store the sum of each board in its own array afterwords:
score1=space1+space2+space3...
int scores[3];
scores[1]=score1;
etc.
Edit: If you HAVE to use a temporary array just do it like this:
int score[3];
score[1]=gameBoard[1][1][1]+gameBoard[1][1][2]+gameBoard[1][1][3] ...
And skip the middleman
Maybe you should add another function which will count sum of array of type 3x3:
public static int countSum(int[][] arr) {
if(arr == null) return 0;
int sum = 0;
for(int i = 0; i < arr.length;i++) {
int[] arr1 = arr[i];
for(int j = 0; j < arr1.length; j++) {
sum+=arr1[j];
}
}
return sum;
}
and rewrite your analyzeChoice method:
private static void analyzeChoice(int choiceMade)
{
int temp [][][] = new int [3][3][3];
temp = gameBoard;
int[] sums = new int[]{0, 0, 0}; /*sums for each table*/
for(int i = 0; i < temp.length; i++) {
int[][] inner_arr = temp[i];
sums[i] = countSum(inner_arr);
}
int maxsum = 0;
int maxint = 0;
for(int i = 0; i < sums.length; i++) {
if(sums[i] > maxsum) {
maxsum = sums[i]; maxint = i;
}
}
if(maxint == choiceMade) {
score++;
}
// Print out the current score
System.out.println("\n***Current Score: " + score);
}

Using import java.util.Random; nextInt and user input

I am fairly new to java so this will probably seem like a basic question. I am trying to use the random java.util and nextInt to create a random number in a range specified by user input and then cast it as a character, to then be stored in an array;
gridCells[x][y] = (char)(r.nextInt(numberOfRegions) + 'a');
However, because I want nextInt to use user Input, and although im controlling the range of values, im guessing the error is caused because nextInt thinks numberOfRegions could be 0?
// Map Class
import java.util.Random;
public class map
{
// number of grid regions
private int numberOfRegions;
private boolean correctRegions = false
// grid constants
private int xCord = 13; // 13 so the -1 makes 12 for a 12x12 grid
private int yCord = 13;
// initiate grid
private int[][] gridCells = new int[xCord][yCord];
Random r = new Random();
map() { }
// ask for number of regions
public void regions()
{
keyboard qwerty = new keyboard(); // keyboard class
while(correctRegions = false)
{
System.out.print("Please enter the number of regions: ");
numberOfRegions = qwerty.readInt();
if(numberOfRegions < 2) // nothing less then 2 accepted
{
correctRegions = false;
}
else if(numberOfRegions > 4) // nothing greater then 4 accepted
{
correctRegions = false;
}
else
{
correctRegions = true;
}
}
}
// fills the grid with regions
public void populateGrid()
{
for(int x =0; x<gridCells[x].length-1; x++) // -1 to avoid outofboundsexception error
{
for(int y =0; y<gridCells[y].length-1; y++)
{
gridCells[x][y] = (char)(r.nextInt(numberOfRegions) + 'a');
}
}
}
public void showGrid()
{
for(int x=0;x<gridCells[x].length-1; x++)
{
for(int y=0; y<gridCells[x].length-1; y++)
{
System.out.print(gridCells[x][y] + " ");
}
System.out.println();
}
}
}
public void populateGrid()
{
for(int x =0; x<gridCells[x].length-1; x++) // -1 to avoid outofboundsexception error
{
for(int y =0; y<gridCells[y].length-1; y++)
{
gridCells[x][y] = (char)(r.nextInt(numberOfRegions) + 'a');
}
}
}
This is bogus, either you do index < array.length or index <= array.length-1.
index < array.length-1 is most likely not what you intended.
Also, if you get compilation errors, it is maybe because you did not initialize numberOfRegions. Normally, thats not an error but a warning, but maybe your compiler is set to issue an error in this case. Try
private int numberOfRegions = 0;
you have to know how the java.util.random works.
Random r = new Random();
int number = r.nextInt(numberOfRegions);
this will produce an integer from zero (0) to ur numberRegions.
to exclude zero from ur possible range of random number generated, do something like this
int number = 1 + r.nextInt(numberOfRegions);
with this, the minimum number that can be generated is 1
int number = 2 + r.nextInt(numberOfRegions);
with this, the minimum number that can be generated is 2
...and so on
Well I have found something:
Your while condition is an assignment:
while(correctRegions = false)
You should write:
while(correctRegions == false) // == is a boolean operator, = is an assignment

Eliminating Recursion

I've just been looking at the following piece of code
package test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(final String[] args) {
final int sizeA = 3;
final int sizeB = 5;
final List<int[]> combos = getAllCombinations(sizeA-1, sizeB);
int counter = 1;
for(final int[] combo : combos) {
System.out.println("Combination " + counter);
System.out.println("--------------");
for(final int value : combo) {
System.out.print(value + " ");
}
System.out.println();
System.out.println();
++counter;
}
}
private static List<int[]> getAllCombinations(final int maxIndex, final int size) {
if(maxIndex >= size)
throw new IllegalArgumentException("The maximum index must be smaller than the array size.");
final List<int[]> result = new ArrayList<int[]>();
if(maxIndex == 0) {
final int[] array = new int[size];
Arrays.fill(array, maxIndex);
result.add(array);
return result;
}
//We'll create one array for every time the maxIndex can occur while allowing
//every other index to appear, then create every variation on that array
//by having every possible head generated recursively
for(int i = 1; i < size - maxIndex + 1; ++i) {
//Generating every possible head for the array
final List<int[]> heads = getAllCombinations(maxIndex - 1, size - i);
//Combining every head with the tail
for(final int[] head : heads) {
final int[] array = new int[size];
System.arraycopy(head, 0, array, 0, head.length);
//Filling the tail of the array with i maxIndex values
for(int j = 1; j <= i; ++j)
array[size - j] = maxIndex;
result.add(array);
}
}
return result;
}
}
I'm wondering, how do I eliminate recursion from this, so that it returns a single random combination, rather than a list of all possible combinations?
Thanks
If I understand your code correctly your task is as follows: give a random combination of numbers '0' .. 'sizeA-1' of length sizeB where
the combination is sorted
each number occurs at least once
i.e. in your example e.g. [0,0,1,2,2].
If you want to have a single combination only I'd suggest another algorithm (pseudo-code):
Randomly choose the step-up positions (e.g. for sequence [0,0,1,1,2] it would be steps (1->2) & (3->4)) - we need sizeA-1 steps randomly chosen at sizeB-1 positions.
Calculate your target combination out of this vector
A quick-and-dirty implementation in java looks like follows
// Generate list 0,1,2,...,sizeB-2 of possible step-positions
List<Integer> steps = new ArrayList<Integer>();
for (int h = 0; h < sizeB-1; h++) {
steps.add(h);
}
// Randomly choose sizeA-1 elements
Collections.shuffle(steps);
steps = steps.subList(0, sizeA - 1);
Collections.sort(steps);
// Build result array
int[] result = new int[sizeB];
for (int h = 0, o = 0; h < sizeB; h++) {
result[h] = o;
if (o < steps.size() && steps.get(o) == h) {
o++;
}
}
Note: this can be optimized further - the first step generates a random permutation and later strips this down to desired size. Therefore it is just for demonstration purpose that the algorithm itself works as desired.
This appears to be homework. Without giving you code, here's an idea. Call getAllCombinations, store the result in a List, and return a value from a random index in that list. As Howard pointed out in his comment to your question, eliminating recursion, and returning a random combination are separate tasks.

Categories