Specific comparison of two arrays in java - java

There are many symbol games working in this way so this should sound familiar to you.
Facts:
I have two arrays with same length of 4.
(A[4] and B[4])
I fill them with random integers from 1 to 6.
I can NOT sort them in any way (they must stay the same).
Problems:
I need to compare them and after that I need to have 3 values. FIRST one needs to count how many elements are the same and in the same place. I do it like this and it is working:
int first = 0;
int k = 0;
for (int j=1; j<=4; j++)
{
k++;
if (A[k] == B[j])
{
first++;
}
}
SECOND one needs to count how many elements are the same BUT not at the same place. THIRD one needs to count how many elements are not the same at all.
I need a solution to count either SECOND or THIRD number, because after that I can just subtract like 4-(first+second) or 4-(first+second).

Here's the logic you should use: loop over the first array; for each element, check if the corresponding element of the second array is the same - if yes, increment your first counter. If they are not the same, then check whether the second array contains the corresponding element of the first array. If it does, then it's definitely not in the same position (you just checked same positions) - increment your second count. Otherwise, increment your third count. The code can be as following:
int[] A = {...};
int[] B = {...};
List<Integer> lstB = new ArrayList<Integer>(B.length);
for (int index = 0; index < B.length; index++) {
lstB.add(B[index]);
}
int first = 0, second = 0, third = 0;
for(int i=0; i<4; i++) {
if(A[i] == B[i]) {
first++;
}
else if(lstB.contains(A[i]) {
second++;
}
else {
third++;
}
}

SOLUTION
Eventually I made the right algorithm. In general, the solution is to keep track of what fields you used when counting FIRST value. And here is the code:
int first = 0;
int second = 0;
int third = 0;
boolean[] codeUsed = new boolean[4];
boolean[] guessUsed = new boolean[4];
//same value and same place
for (int i = 0; i < 4; i++)
{
if (A[i] == B[i])
{
first++;
codeUsed[i] = guessUsed[i] = true;
}
}
//same value but not right place
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (!codeUsed[i] && !guessUsed[j] && A[i] == B[j])
{
second++;
codeUsed[i] = guessUsed[j] = true;
break;
}
}
}
//not the same value
third = 4 - first - second;

Related

I don't know how assign new value to the empty array

I am a beginner in coding. I have to write a code that will divide array with random numbers into two different arrays. One array will contain odd numbers, the other one even numbers. But something is wrong, and i don't really know what to do.
According to the console the problem is in the place where there is a lot of exclamation marks. when i change those lines to System.out.println("x") it works perfectly fine.
public void P_N () {
int I_E = 0; // amount of even numbers
int I_O = 0; // amount of odd numbers
for (int i = 0; i < tab2.length; i++) { // tab2 is a array with random numbers
if (tab2[i] % 2 == 0)
I_E = I_E + 1;
else
I_O = I_O+1;
}
int [] tab_E = new int[I_E]; // array with even numbers
int [] tab_O = new int [I_O]; // array with odd numbers
for (int i = 0; i < tab2.length; i++){
if (tab2[i] % 2 == 0){
tab_E[i] = tab2[i]; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
for (int i = 0; i < tab2.length; i++){
if (tab2[i] % 2 != 0){
tab_O[i] = tab2[i]; //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
for (int i = 0; i< tab_E.length; i++) {
System.out.println("Even array: " + tab_E[i]);
System.out.println("------------------------------------------------");
}
for (int i = 0; i< tab_O.length; i++) {
System.out.println("Odd array: " + tab_O[i]);
}
}
Problem is in going out of bounds for arrays tab_E and tab_O, when variable i is more tab_E.length. Just create another variable, for example "j". And iterate throug your array using it. Like I'v written below
int j = 0;
for (int i = 0; i < tab2.length; i++) {
if (tab2[i] % 2 == 0) {
tab_E[j++] = tab2[i];
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
j = 0;
for (int i = 0; i < tab2.length; i++) {
if (tab2[i] % 2 != 0) {
tab_O[j++] = tab2[i];
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
}
I would rather use 2 ArrayLists one for even numbers and another one is for odd numbers and later convert it into array using toArray() method.
public void P_N(){
ArrayList<Integer> evenNumberList = new ArrayList<Integer>();
ArrayList<Integer> oddNumberList = new ArrayList<Integer>();
for (int i = 0; i < tab2.length; i++) { // tab2 is a array with random numbers
if (tab2[i] % 2 == 0) {
evenNumberList.add(tab2[i]);
} else {
oddNumberList.add(tab2[i]);
}
}
int[] evenNumberArray = evenNumberList.toArray();
int[] oddNumberArray = oddNumberList.toArray();
}
This will take some extra space but makes your application more efficient, I hope this helps.
You have initialized the even/odd number arrays with a quantity of the even/odd numbers accordingly:
int [] tab_E = new int[I_E]; // array with even numbers
int [] tab_O = new int [I_O]; // array with odd numbers
Ii is reasonable to assume that the sizes of even or odd number arrays are might be much smaller than the size of the original source array.
But in this even number filtering loop (as well as in the odd filtering loop) you use source array index values to address target array positions, end eventually face the ArrayIndexOutOfBoundsException.
for (int i = 0; i < tab2.length; i++)
{
if (tab2[i] % 2 == 0)
{
tab_E[i] = tab2[i]; //here the same i value is used to address non existing index in tab_E array
}
}
A quick fix might be the following:
int tab_E_index = 0;
for (int i = 0; i < tab2.length; i++){
if (tab2[i] % 2 == 0){
tab_E[tab_E_index] = tab2[i]; //i value gets incremented every loop iteration
tab_E_index++; //tab_E_index value get incremented only when even number is added to the tab_E array
}
}
Please don't just copy/paste it, but try to understand what caused the issue on the first place. Good luck and happy coding.

Not able to add to ArrayList properly

I have 2 methods in my program, one to add ***** above and below the smallest int in the array and one to add %%%%% above and below the largest. The method for the largest is essentially the same as the other but for some reason isn't adding what is needed.
Here is the smallest element method:
public static ArrayList smallestElement() {
int smallest = array[0];
for (int i = 0; i < array.length; i++)
if (array[i] < smallest)
smallest = array[i];
String smallestString = String.valueOf(smallest);
ArrayList<String> list = new ArrayList<String>();
for(int i = 0; i < array.length; i++) {
if (smallestString.equals(String.valueOf(array[i]))) {
list.add("*****");
list.add(Integer.toString(array[i]));
list.add("*****");
} else {
list.add(Integer.toString(array[i]));
}
}
return list;
}
Here is the method for the largest element:
public static ArrayList largestElement() {
int largest = array[0];
for (int i = 0; i < array.length; i++)
if (array[i] > largest)
largest = array[i];
String largestString = String.valueOf(largest);
for(int i = 0; i < array.length; i++) {
if (largestString.equals(String.valueOf(array[i]))) {
smallestElement().add("%%%%%");
smallestElement().add(Integer.toString(array[i]));
smallestElement().add("%%%%%");
} else {
smallestElement().add(Integer.toString(array[i]));
}
}
System.out.println(smallestElement());
return smallestElement();
}
}
If anyone knows why this isn't performing correctly, I would really appreciate the help
You are creating a new object every time you are executing the smallestElement function. Instead do something like,
ArrayList<String> list = smallestElement();
Then use this list object every time you are calling smallestElement() method
You have already created the list 3 times over by this line
smallestElement().add("%%%%%");
smallestElement().add(Integer.toString(array[i]));
smallestElement().add("%%%%%");
Create just 1 list and use it instead of calling the smallestelementelement() function multiple times
You are overcomplicating things here. There is no need to turn that minimum array value into a string right there (and to then do String comparisons later on). Btw: those string comparisons are also your problem: your code will definitely not work when your minimal value shows up several times in your array - because your code will put in those patterns for each match!
Instead, you could do something like:
int indexToUse = 0;
for (int i = 0; i < array.length; i++) { // please always use braces!
if (array[i] < array[indexToUse]) {
indexToUse = i;
}
}
List<String> valuesWithMarkerStrings = new ArrayList<>();
for (int i = 0; i < array.length; i++) {
if (i == indexToUse -1 || i == indexToUse+1) {
valuesWithMarkerStrings.add("******");
} else {
valuesWithMarkerStrings.add(Integer.toString(array[i]);
}
}
(where my solution assumes that you want to have *** ... instead of array[i] for such rows ... )

Java for loop needs to pick up where it left off

I need the second for loop to pick up where it left off. Every time the if statement is true I need a slot to fill in the array used in the first for loop. But I don't want the same key value to keep getting added. I need the second for loop to move to the next key value. (In the code below, arrl is an ArrayList of objects that have a value)
int temp = 0;
int count = 0;
for(int i = 0; i < eeVal.length; i++)
{
count= 0;
for(int j = temp; j < arrl.size(); j++)
{
if(arrl.get(j).getValue() == 1 && count == 0)
{
eeVal[i] = arrl.get(j);
count++;
temp=j;
}
}
}
}
return eeVal;
You need another variable to track where the inside loop has gotten to. Something like the following:
int temp = 0;
for(int i = 0; i < eeVal.length; i++)
{
for(int j = temp; j < arrl.size(); j++)
{
if(arrl.get(j).getValue() == 1)
{
eeVal[i] = arrl.get(j);
}
temp=j;
}
}
}
return eeVal;
This way, once the outside loop runs the second time around, the inside loop will start from 'temp' until the end of the loop.
From your explanation, it sounds like you do not want the inner for loop. The traversal of arrl needs to be manually controlled using a variable, e.g.`cnt', which only gets incremented when your condition for incrementing it is satisfied.
What you probably are looking for is a List.
In your answer, you don't need the first loop. This one has issues though - index i can go out of bounds.
int i = 0;
for(int j = 0; j < arrl.size(); j++) {
if(arrl.get(j).getValue() == 1) {
eeVal[i++] = arrl.get(j);
}
}
return eeVal;
What you need is a dynamic collections such as List.
Using list (I am calling the type as MyType).
List<MyType> vals = new ArrayList<>();
for(MyType item : arrl) {
if(item.getValue() == 1) {
vals.add(arrl.get(j));
}
}
return vals.toArray(new MyType[vals.size()]);
The code was picking up where the last correct value was. I needed to add 1 to j when I wanted progress to know where I left off.
int count2 = 0;
int progress = 0;
for(int i = 0; i < retVal[h].length; i++)
{
count2 = 0;
for(int j = progress; j < arr.size(); j++)
{
if(arr.get(j).getLevel() == h && count2==0)
{
retVal[h][i] = arr.get(j);
count2++;
progress = j+1;
}
}
}
return retVal;

How to compare two arrays of different sizes?

So my task is to read a file line by line and store the integers into an array. Then to add the integers in spots 1-5, 2-6, 3-7 etc. and store those into a new array.
In array 1 there is 4 more values than array 2. I need to compare these Arrays and see if array1 is 0.999 bigger than array2.
If it is indeed larger, I need to print out the LOCATION of the number in the array 1.
Right now my problem is my code is outputting that every number is larger than the corresponding number in array 2.
Code:
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
public class Asgn7
{
public static void main(String[] args) throws FileNotFoundException
{
Scanner file = new Scanner(new File("asgn7data.txt"));
double[] array = new double[file.nextInt()];
double[] newArray = new double[array.length - 4];
double tempVal = 0;
int j = 0;
int count = 0;
while(file.hasNext())
{
for(int i = 0; i < array.length ; i++)
{
array[i] = file.nextInt();
}
for(j = 0; j < array.length - 4; j++)
{
for(int k = 0; k < 5; k++)
{
newArray[j] += array[j+k] / 5;
}
}
for(int i = 2; i < array.length; i++)
{
if(array[i] > (newArray[i-2] + 0.999));
{
count++;
tempVal = count;
}
System.out.println(tempVal);
}
}
}
}
The values which should be compared are from 3-13.
Judging by the picture, you are not placing the values in the correct index in the second array, or you are not matching the correct ones.
If you want it to look exactly like in the picture, the second array should be declared:
double[] newArray = new double[array.length - 2];
And the loop to fill it should be changed to:
for(j = 2; j < array.length - 2; j++)
{
for(int k = -2; k <= 2; k++)
{
newArray[j] += array[j+k] / 5;
}
}
This will put the averages in the third, fourth, fifth... elements in newArray. And now you can compare them directly:
for(int i = 2; i < array.length - 2; i++)
{
if(array[i] > (newArray[i] + 0.999))
{
count++;
tempVal = count;
}
System.out.println(tempVal);
}
If you want to save the two unused spaces, as you originally did, rather than responding exactly to the picture, then you should calculate the values as you originally did. But remember to compare each element to the one two places before it and stop 2 places before the end.
Instead of
for(int i = 2; i < array.length; i++)
use
for(int i = 2; i < array.length - 2; i++)
To print the location, your construct with the count and tempVal is unnecessary. You just need to print i+1. Also note that you have a ; after your if. This means it's an empty if, and the block after it is always performed. Never have a ; after an if, for, while etc.
Not clear with what you are asking for in your question but without questioning what's the logic, by just looking at your code:
for(int i = 2; i < array.length; i++)
{
if(array[i] > (newArray[i-2] + 0.999));
{
count++;
tempVal = count;
}
System.out.println(tempVal);
}
}
if you relocate the system.out line as follows, I think you will get what you expect as follows:
for(int i = 2; i < array.length - 2; i++)
{
if(array[i] > (newArray[i-2] + 0.999));
{
System.out.println(tempVal);
// count++;
// tempVal = count;
}
}
}
PS: Please note that I have also changed the boundary for the loop to stop iteration on 13th member of the array, instead of 15.
Are you sure you're parsing the numbers correctly?
See Java: Reading integers from a file into an array
Why don't you print them out after parsing for verification?
btw, this will overflow the index of the 2nd array (since it is created using new double[array.length - 4]):
for(int i = 2; i < array.length; i++)
so does your code run?

Randomize tictactoe

A while I did an assignment creating a tictactoe program through eclipse. It works well enough, with me clicking empty boxes to place O's, and the program inputting X's afterward. However, I was using a pretty simple code for the placement of X's:
public int putX(){
for(int i=0; i<3;i++)
for(int j = 0;j<3;j++) {
if(position[i][j]==' ') {
position[i][j]='X';
return 0;
}
}
return -1; //some error occurred. This is odd. No cells were free.
}
Because of this, the X's are just placed in the row of each column, going down until the next column. Can someone show me a simple way to randomize this program?
What we want to do is generate an array of all the possible points, and pick one of those points at random. We use a for loop to iterate through all points in the 3x3 array, and add the valid ones to our temporary array, and then we choose a random index, and place an X there.
String[] list = new String[9]; // maximum 9 points
int size = 0;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(position[i][j] == ' ') {
list[size] = "" + i + j;
size++;
}
}
}
int index = (int) (Math.random() * (size+1));
position[Integer.parseInt(list[index].charAt(0))][Integer.parseInt(list[index].charAt(1))] = 'X';
Alternatively, instead of storing the x,y coordinates of the point in a String we could store them in a java.awt.Point like so:
Point[] list = new Point[9]; // maximum 9 points
int size = 0;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(position[i][j] == ' ') {
list[size] = new Point(i, j);
size++;
}
}
}
int index = (int) (Math.random() * (size+1));
position[list[index].getX()][list[index].getY()] = 'X';
As you can see, the code for using a Point is practically the same, but instead of parsing the coordinates out of the String, we can just access them directly from the Class.
You should also check to make sure that there are some elements left, by checking if size is still 0 after the for loop. If so, you should probably return -1 (what your existing code does). Otherwise, at the end of the whole code return 0.

Categories