incorrect variable change in java - java

I have a problem in Eclipse. Why is the value of oldList different in LogCat while I don't change it between the tow Log command?
First I have an initialize method:
private void initialize() {
list[0][0] = 2;
list[0][1] = 4;
list[1][0] = 3;
list[1][1] = 7;
oldList = list;
going();
}
and in the going method, I printed oldList twice :
private void going() {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
Log.i("Log", "oldList = " + oldList[i][j]);
}
}
Log.i("Log", "---------------------------");
// ----------------------------------------------------
list[0][0] = 0;
list[0][1] = 5;
list[1][0] = 0;
list[1][1] = 0;
// ----------------------------------------------------
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
Log.i("Log", "oldList = " + oldList[i][j]);
}
}
}
but the two results is different in LogCat :
oldList = 2
oldList = 4
oldList = 3
oldList = 7
---------------------------
oldList = 0
oldList = 5
oldList = 0
oldList = 0
While i don't change it between the two logs. I just change the value of list, not oldList. Why does the output change?

Both list and oldlist refer to the exact same object. When you run
oldlist = list
you have two different "names" referring to the exact same object in memory. When you assign an object (in your case the array) to a variable, this object will not be copied.
Thus, as you change the list array in your going method, you are changing the object referred to by both list and oldlist.

oldlist and list are two references that point to the same array.

you can try this :
private void initialize() {
list[0][0] = 2;
list[0][1] = 4;
list[1][0] = 3;
list[1][1] = 7;
// simply
oldList[0] = list[0].clone();
oldList[1] = list[1].clone();
// or in a greater 2D arrays
for (int i = 0; i < list.length; i++) {
System.arraycopy(list[i], 0, oldList[i], 0, list[0].length);
}
going();
}

Related

Ordering a vector of randomly generated numbers

I´m trying to solve a question but i can´t find why my code is not working for this problem. I have generated a random vector of 100 elements and im trying to order them into another. Somehow, my new generated vector is filled with the last index value of the random vector.
int[] vetorAleatory = new int[100];
for (int i = 0; i < vetorAleatory.length; i++) {
vetorAleatory[i] = new Random().nextInt(1000);
}
int[] vetorByOrder = new int[100];
int newVetorPosition = 0;
for (int i = 0; i < 100; i++) {
for (int x = 0; x < 100; x++) {
vetorByOrder[newVetorPosition] = 2000;
if (vetorAleatory[i] < vetorByOrder[newVetorPosition]) {
boolean newEntry = true;
for (int y = 0; y < newVetorPosition; y++) {
if (vetorByOrder[y] == vetorByOrder[newVetorPosition]) {
newEntry = false;
break;
}
}
if (newEntry == true) {
vetorByOrder[newVetorPosition] = vetorAleatory[x];
}
}
if (x == 99) {
newVetorPosition++;
}
}
}
for (int i = 0;i<100;i++) {
System.out.print(vetorAleatory[i] + ", " + vetorByOrder[i] + System.lineSeparator());
}
First you do not need 3 loops to sort an array. You need only 2 and in case of quick search, it is even less than that. You can check this example Array sort and search, or you can use built in Arrays.sort method in Java

JAVA - Compare two arrays and create a new array with only the unique values from the first

I have to solve an exercise with the following criteria:
Compare two arrays:
int[] a1 = {1, 3, 7, 8, 2, 7, 9, 11};
int[] a2 = {3, 8, 7, 5, 13, 5, 12};
Create a new array int[] with only unique values from the first array. Result should look like this: int[] result = {1,2,9,11};
NOTE: I am not allowed to use ArrayList or Arrays class to solve this task.
I'm working with the following code, but the logic for the population loop is incorrect because it throws an out of bounds exception.
public static int[] removeDups(int[] a1, int[] a2) {
//count the number of duplicate values found in the first array
int dups = 0;
for (int i = 0; i < a1.length; i++) {
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
dups++;
}
}
}
//to find the size of the new array subtract the counter from the length of the first array
int size = a1.length - dups;
//create the size of the new array
int[] result = new int[size];
//populate the new array with the unique values
for (int i = 0; i < a1.length; i++) {
int count = 0;
for (int j = 0; j < a2.length; j++) {
if (a1[i] != a2[j]) {
count++;
if (count < 2) {
result[i] = a1[i];
}
}
}
}
return result;
}
I would also love how to solve this with potentially one loop (learning purposes).
I offer following soulution.
Iterate over first array, and find out min and max it's value.
Create temporary array with length max-min+1 (you could use max + 1 as a length, but it could follow overhead when you have values e.g. starting from 100k).
Iterate over first array and mark existed values in temorary array.
Iterate over second array and unmark existed values in temporary array.
Place all marked values from temporary array into result array.
Code:
public static int[] getUnique(int[] one, int[] two) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < one.length; i++) {
min = one[i] < min ? one[i] : min;
max = one[i] > max ? one[i] : max;
}
int totalUnique = 0;
boolean[] tmp = new boolean[max - min + 1];
for (int i = 0; i < one.length; i++) {
int offs = one[i] - min;
totalUnique += tmp[offs] ? 0 : 1;
tmp[offs] = true;
}
for (int i = 0; i < two.length; i++) {
int offs = two[i] - min;
if (offs < 0 || offs >= tmp.length)
continue;
if (tmp[offs])
totalUnique--;
tmp[offs] = false;
}
int[] res = new int[totalUnique];
for (int i = 0, j = 0; i < tmp.length; i++)
if (tmp[i])
res[j++] = i + min;
return res;
}
For learning purposes, we won't be adding new tools.
Let's follow the same train of thought you had before and just correct the second part:
// populate the new array with the unique values
for (int i = 0; i < a1.length; i++) {
int count = 0;
for (int j = 0; j < a2.length; j++) {
if (a1[i] != a2[j]) {
count++;
if (count < 2) {
result[i] = a1[i];
}
}
}
}
To this:
//populate the new array with the unique values
int position = 0;
for (int i = 0; i < a1.length; i++) {
boolean unique = true;
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
unique = false;
break;
}
}
if (unique == true) {
result[position] = a1[i];
position++;
}
}
I am assuming the "count" that you implemented was in attempt to prevent false-positive added to your result array (which would go over). When a human determines whether or not an array contains dups, he doesn't do "count", he simply compares the first number with the second array by going down the list and then if he sees a dup (a1[i] == a2[j]), he would say "oh it's not unique" (unique = false) and then stop going through the loop (break). Then he will add the number to the second array (result[i] = a1[i]).
So to combine the two loops as much as possible:
// Create a temp Array to keep the data for the loop
int[] temp = new int[a1.length];
int position = 0;
for (int i = 0; i < a1.length; i++) {
boolean unique = true;
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
unique = false;
break;
}
}
if (unique == true) {
temp[position] = a1[i];
position++;
}
}
// This part merely copies the temp array of the previous size into the proper sized smaller array
int[] result = new int[position];
for (int k = 0; k < result.length; k++) {
result[k] = temp[k];
}
Making your code work
Your code works fine if you correct the second loop. Look at the modifications I did:
//populate the new array with the unique values
int counter = 0;
for (int i = 0; i < a1.length; i++) {
for (int j = 0; j < a2.length; j++) {
if (a1[i] == a2[j]) {
result[counter] = a1[i];
counter++;
}
}
}
The way I would do it
Now, here is how I would create a method like this without the need to check for the duplicates more than once. Look below:
public static int[] removeDups(int[] a1, int[] a2) {
int[] result = null;
int size = 0;
OUTERMOST: for(int e1: a1) {
for(int e2: a2) {
if(e1 == e2)
continue OUTERMOST;
}
int[] temp = new int[++size];
if(result != null) {
for(int i = 0; i < result.length; i++) {
temp[i] = result[i];
}
}
temp[temp.length - 1] = e1;
result = temp;
}
return result;
}
Instead of creating the result array with a fixed size, it creates a new array with the appropriate size everytime a new duplicate is found. Note that it returns null if a1 is equal a2.
You can make another method to see if an element is contained in a list :
public static boolean contains(int element, int array[]) {
for (int iterator : array) {
if (element == iterator) {
return true;
}
}
return false;
}
Your main method will iterate each element and check if it is contained in the second:
int[] uniqueElements = new int[a1.length];
int index = 0;
for (int it : a1) {
if (!contains(it, a2)) {
uniqueElements[index] = it;
index++;
}
}

How to obtain reference to set created inside of loop?

int count = 0;
for (int i = 0; i < width - 1; i++)
{
for(int j = 0; j < height - 1; j++)
{
new HashSet();
count++;
}
}
I'm creating sets inside of two for loops, but how do I obtain reference to the sets? How would I be able to call "set1" or "set2" for example?
You can try to put them in an Arraylist.
int count = 0;
List<Set<YourClass>> arr = new ArrayList<Set<YourClass>>();
for (int i = 0; i < width - 1; i++)
{
for(int j = 0; j < height - 1; j++)
{
Set s = new HashSet<YourClass>();
arr.add(s);
count++;
}
}
Then you can call whichever one you want:
Set theFirstSet = arr.get(0);
And do things with them:
theFirstSet.add(your_class_instance);
The sets need a name e.g.
HashSet set1;
make them fields at class level so can refer anywhere.
set1 = new HashSet();

Finding multiple modes in an array of integers with 1000 elements

So I need a way to find the mode(s) in an array of 1000 elements, with each element generated randomly using math.Random() from 0-300.
int[] nums = new int[1000];
for(int counter = 0; counter < nums.length; counter++)
nums[counter] = (int)(Math.random()*300);
int maxKey = 0;
int maxCounts = 0;
sortData(array);
int[] counts = new int[301];
for (int i = 0; i < array.length; i++)
{
counts[array[i]]++;
if (maxCounts < counts[array[i]])
{
maxCounts = counts[array[i]];
maxKey = array[i];
}
}
This is my current method, and it gives me the most occurring number, but if it turns out that something else occurred the same amount of times, it only outputs one number and ignore the rest.
WE ARE NOT ALLOWED TO USE ARRAYLIST or HASHMAP (teacher forbade it)
Please help me on how I can modify this code to generate an output of array that contains all the modes in the random array.
Thank you guys!
EDIT:
Thanks to you guys, I got it:
private static String calcMode(int[] array)
{
int[] counts = new int[array.length];
for (int i = 0; i < array.length; i++) {
counts[array[i]]++;
}
int max = counts[0];
for (int counter = 1; counter < counts.length; counter++) {
if (counts[counter] > max) {
max = counts[counter];
}
}
int[] modes = new int[array.length];
int j = 0;
for (int i = 0; i < counts.length; i++) {
if (counts[i] == max)
modes[j++] = array[i];
}
toString(modes);
return "";
}
public static void toString(int[] array)
{
System.out.print("{");
for(int element: array)
{
if(element > 0)
System.out.print(element + " ");
}
System.out.print("}");
}
Look at this, not full tested. But I think it implements what #ajb said:
private static int[] computeModes(int[] array)
{
int[] counts = new int[array.length];
for (int i = 0; i < array.length; i++) {
counts[array[i]]++;
}
int max = counts[0];
for (int counter = 1; counter < counts.length; counter++) {
if (counts[counter] > max) {
max = counts[counter];
}
}
int[] modes = new int[array.length];
int j = 0;
for (int i = 0; i < counts.length; i++) {
if (counts[i] == max)
modes[j++] = array[i];
}
return modes;
}
This will return an array int[] with the modes. It will contain a lot of 0s, because the result array (modes[]) has to be initialized with the same length of the array passed. Since it is possible that every element appears just one time.
When calling it at the main method:
public static void main(String args[])
{
int[] nums = new int[300];
for (int counter = 0; counter < nums.length; counter++)
nums[counter] = (int) (Math.random() * 300);
int[] modes = computeModes(nums);
for (int i : modes)
if (i != 0) // Discard 0's
System.out.println(i);
}
Your first approach is promising, you can expand it as follows:
for (int i = 0; i < array.length; i++)
{
counts[array[i]]++;
if (maxCounts < counts[array[i]])
{
maxCounts = counts[array[i]];
maxKey = array[i];
}
}
// Now counts holds the number of occurrences of any number x in counts[x]
// We want to find all modes: all x such that counts[x] == maxCounts
// First, we have to determine how many modes there are
int nModes = 0;
for (int i = 0; i < counts.length; i++)
{
// increase nModes if counts[i] == maxCounts
}
// Now we can create an array that has an entry for every mode:
int[] result = new int[nModes];
// And then fill it with all modes, e.g:
int modeCounter = 0;
for (int i = 0; i < counts.length; i++)
{
// if this is a mode, set result[modeCounter] = i and increase modeCounter
}
return result;
THIS USES AN ARRAYLIST but I thought I should answer this question anyways so that maybe you can use my thought process and remove the ArrayList usage yourself. That, and this could help another viewer.
Here's something that I came up with. I don't really have an explanation for it, but I might as well share my progress:
Method to take in an int array, and return that array with no duplicates ints:
public static int[] noDups(int[] myArray)
{
// create an Integer list for adding the unique numbers to
List<Integer> list = new ArrayList<Integer>();
list.add(myArray[0]); // first number in array will always be first
// number in list (loop starts at second number)
for (int i = 1; i < myArray.length; i++)
{
// if number in array after current number in array is different
if (myArray[i] != myArray[i - 1])
list.add(myArray[i]); // add it to the list
}
int[] returnArr = new int[list.size()]; // create the final return array
int count = 0;
for (int x : list) // for every Integer in the list of unique numbers
{
returnArr[count] = list.get(count); // add the list value to the array
count++; // move to the next element in the list and array
}
return returnArr; // return the ordered, unique array
}
Method to find the mode:
public static String findMode(int[] intSet)
{
Arrays.sort(intSet); // needs to be sorted
int[] noDupSet = noDups(intSet);
int[] modePositions = new int[noDupSet.length];
String modes = "modes: no modes."; boolean isMode = false;
int pos = 0;
for (int i = 0; i < intSet.length-1; i++)
{
if (intSet[i] != intSet[i + 1]) {
modePositions[pos]++;
pos++;
}
else {
modePositions[pos]++;
}
}
modePositions[pos]++;
for (int modeNum = 0; modeNum < modePositions.length; modeNum++)
{
if (modePositions[modeNum] > 1 && modePositions[modeNum] != intSet.length)
isMode = true;
}
List<Integer> MODES = new ArrayList<Integer>();
int maxModePos = 0;
if (isMode) {
for (int i = 0; i< modePositions.length;i++)
{
if (modePositions[maxModePos] < modePositions[i]) {
maxModePos = i;
}
}
MODES.add(maxModePos);
for (int i = 0; i < modePositions.length;i++)
{
if (modePositions[i] == modePositions[maxModePos] && i != maxModePos)
MODES.add(i);
}
// THIS LIMITS THERE TO BE ONLY TWO MODES
// TAKE THIS IF STATEMENT OUT IF YOU WANT MORE
if (MODES.size() > 2) {
modes = "modes: no modes.";
}
else {
modes = "mode(s): ";
for (int m : MODES)
{
modes += noDupSet[m] + ", ";
}
}
}
return modes.substring(0,modes.length() - 2);
}
Testing the methods:
public static void main(String args[])
{
int[] set = {4, 4, 5, 4, 3, 3, 3};
int[] set2 = {4, 4, 5, 4, 3, 3};
System.out.println(findMode(set)); // mode(s): 3, 4
System.out.println(findMode(set2)); // mode(s): 4
}
There is a logic error in the last part of constructing the modes array. The original code reads modes[j++] = array[i];. Instead, it should be modes[j++] = i. In other words, we need to add that number to the modes whose occurrence count is equal to the maximum occurrence count

java : get computed values outside loop

I do some calculation inside for loop and when I println values inside the loop, I got the expected values,
now, I need also that these values will be available outside loop and not only get the latest value.
example :
String[][] matrix = { { "1", "2", "3" } };
String[] y= { "TEST" ,"BUG"};
int a = 0;
for (int i = 0; i < y; i++)
{
for (int j = 1; j < 4; j++)
{
int value = Integer.parseInt(matrix[i][j - 1]);
System.out.println(value ); //this is OK it print me 3 values
}
}
System.out.println(value ); //it print me only third value
I would like that the value 1,2,3 will be also available outside loop
If you want to have access to all three variables. you have to declare a data structure that holds all the values.
e.g.
String[][] matrix = { { "1", "2", "3" } };
List<Integer> list = new ArrayList();
String[] y= { "TEST" ,"BUG"};
int a = 0;
int value;
for (int i = 0; i < y; i++)
{
for (int j = 1; j < 4; j++)
{
value = Integer.parseInt(matrix[i][j - 1]);
list.add(value);
System.out.println(value ); //this is OK it print me 3 values
}
}
System.out.println(value );
Declare the variable value outside of your loop:
String[][] matrix = { { "1", "2", "3" } };
String[] y= { "TEST" ,"BUG"};
int a = 0;
int value = 0;
for (int i = 0; i < y; i++)
{
for (int j = 1; j < 4; j++)
{
value = Integer.parseInt(matrix[i][j - 1]);
System.out.println(value ); //this is OK it print me 3 values
}
}
System.out.println(value );
But if you need all three values available you should use array or some other containers like ArrayList:
String[][] matrix = { { "1", "2", "3" } };
String[] y= { "TEST" ,"BUG"};
int a = 0;
Arraylist<Integer> values = new Arraylist<Integer>();
for (int i = 0; i < y; i++)
{
for (int j = 1; j < 4; j++)
{
values.add(Integer.parseInt(matrix[i][j - 1]));
System.out.println(values); //this is OK it print me 3 values
}
}
System.out.println(values);
you have to declare your variable (that you want to use outside of the for-loop) on top of your code.
Example:
for (...) {
//only valid in this for loop
int i = 1;
}
//valid also after this for loop
int i = 1;
for (...) {
}

Categories

Resources