I need to compare the guess and code arrays and count the number of correct digits in the guess.
It works until there are duplicate numbers in the code array. I know it's something to do with the second for loop and subtracting from the correctDigits.
public static int digits(int[] code, int[] guess) {
int digits = 0;
for (int i = 0; i < code.length; i++) {
for (int j = 0; j < guess.length; j++) {
if (guess[j] == code[i]) {
digits++;
break;
}
}
}
for (int i = 0; i < code.length; i++) {
for (int j = i + 1; j < code.length; j++) {
if (code[i] == code[j] && code[i] != guess[j] && code[j] != guess[i]) {
digits--;
}
}
}
return digits;
}
Since you mentioned "only using loops and basic knowledge" I assume concepts like maps are not included here and "basic knowledge" means "arrays".
If all you need to know is the number of digits try to convert your input to a 10-element array of counts, i.e. each digit would be the input.
Example:
int[] codeDigits = new int[10];
for (int i = 0; i < code.length; i++) {
codeDigits[code[i]]++;
}
This would turn [5,9,9,9] into [0,0,0,0,0,1,0,0,0,3], i.e. 5: 1x, 9: 3x
Now do this for the guess as well, e.g. [0,0,9,9] becomes [2,0,0,0,0,0,0,0,0,2].
Now all you have to do is count the number of digits:
int counter = 0;
for( int i = 0; i < codeDigits.length; i++ ) {
if( codeDigits[i] >= guessDigits[i] ) {
counter += guessDigits[i]; //guessed the exact number or less -> use the guess
} else {
counter += codeDigits[i]; //guessed more -> use the code
}
}
If you are able to use a Math function then the loop body could be replaced by counter += Math.min(codeDigits[i], guessDigits[i]);.
One more illustration (with longer codes to illustrate better):
code: [5,0,9,9,1,7,1] -> [1,2,0,0,0,1,0,1,0,2]
guess: [9,9,0,9,7,4,2] -> [1,0,1,0,1,0,0,1,0,3]
-----------------------------------------
minimum of each digit: 1,0,0,0,0,0,0,1,0,2
If you sum those minimums you get 4 correct digits: 1x 0, 1x 7, 2x 9
there are several solutions. one of them is indexing duplicated values of code array, then check them at first loop (and remove the 2nd loop):
int correctDigits = 0;
int[] duplicateIndexes = new int[code.length];
for (int i=0; i < code.length; i++) {
if( duplicateIndexes[i] == 1) continue;
for (int j=0; j < code.length; j++) {
if( core[i] == core[j]) {
duplicateIndexes[j] == 1;
continue;
}
}
}
for (int i = 0; i < code.length; i++) {
if (duplicatedIndexes[i] == 1) continue;
for (int j = 0; j < guess.length; j++) {
if (guess[j] == code[i]) {
correctDigits++;
break;
}
}
}
You can generate two Maps from these arrays, which associating a Value with its number of occurrences.
Then iterate over the entries of the Map obtained from the code array and compare its values with the corresponding values from the Map created based on the guess array. That would allow determining the number of correct/incorrect guesses.
I hope this will work.
Code
public static int getCorrectDigits(int[] code, int[] guess) {
if (code.length != guess.length) {
throw new IllegalArgumentException("Different lengths");
}
int correctDigits = 0;
for (int i = 0; i < code.length; i++) {
if (guess[i] == code[i]) {
correctDigits++;
}
}
return correctDigits;
}
Output
Code - 5 9 9 9
Guess - 0 9 9 9
Passes - 3
Code - 5 9 9 9
Guess - 9 9 0 0
Passes - 1
Code - 5 9 9 9
Guess - 0 0 9 9
Passes - 2
Code - 5 9 9 9
Guess - 9 0 0 0
Passes - 0
You need to change the for loop to iterate over the guess instead of iterate over the code array:
public static int getCorrectDigits(int[] code, int[] guess) {
if (code.length != guess.length) {
throw new IllegalArgumentException("Different lengths");
}
int correctDigits = 0;
for (int i = 0; i < guess.length; i++) {
for (int j = 0; j < code.length; j++) {
if (guess[i] == code[j]) {
correctDigits++;
break;
}
}
}
return correctDigits;
#Test
void ex1() {
assertEquals(3, ArrayComp.getCorrectDigits(new int[] {5,9, 9, 9}, new int[] {0,9,9,9}));
} #Test
void ex2() {
assertEquals(2, ArrayComp.getCorrectDigits(new int[] {5,9, 9, 9}, new int[] {9,9,0,0}));
} #Test
void ex3() {
assertEquals(2, ArrayComp.getCorrectDigits(new int[] {5,9, 9, 9}, new int[] {0,0,9,9}));
} #Test
void ex4() {
assertEquals(1, ArrayComp.getCorrectDigits(new int[]{5, 9, 9, 9}, new int[]{9, 0, 0, 0}));
}
I thought I'd join in on the fun - maintain a boolean array of code digits used, requires only one nested loop and reverse the looping order:
public static int getCorrectDigits(int[] code, int[] guess) {
if (code.length != guess.length) {
throw new IllegalArgumentException("Different lengths");
}
int correctDigits = 0;
boolean[] used = new boolean[code.length];
for (int i = 0; i < guess.length; i++) {
for (int j = 0; j < code.length; j++) {
if (guess[i] == code[j] && !used[j]) {
correctDigits++;
used[j] = true;
break;
}
}
}
return correctDigits;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am trying to make the code so it wont print the same number twice or more. I have no clue how to make it that way. what do I need to change/add to make it print only one of each number?
public class LottoSpill {
public static int ran() {
int random = (int)(Math.random()*34+1);
return random;
}
public static int lottoRekke() {
int[] array = {ran(), ran(), ran(), ran(), ran(), ran(), ran()};
int ret = array[0];
for (int i = 0; i < array.length; i++){
for (int j = 1; j < array.length; j++){
if(array[i] == array[j]) {
array[i] = array[i] - array[j] + ran();
do {
j++;
i++;
} while(i < array.length || j < array.length);
for (int k = 0; k < array.length; k++) {
System.out.print(array[k] + " ");
}
} else if(array[i] != array[j]) {
do {
j++;
} while(j < array.length);
}
}
}
return ret;
}
public static void main(String[] args) {
lottoRekke();
}
}
this is the result of the code, as you can see the number 17 have been printed twice
25 10 17 20 17 6 27 [Finished in 0.3s]
Try this.
Generate a List of the numbers from 1 to 34. (or whatever your range is).
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 34; i++) {
list.add(i);
}
then call Collections.shuffle() on the list.
Collections.shuffle(list);
then just take the first 6 (or however many) numbers. They will be random and unique.
for (int i = 0; i < 6; i++) {
System.out.println(list.get(i));
}
EDIT
You can pass the starting and ending numbers or leave them out and hard code them in the method.
public static List<Integer> lottery(int start, int end) {
List<Integer> nums = new ArrayList<>();
for (int i = start; i <= end; i++) {
nums.add(i);
}
Collections.shuffle(nums);
return nums;
}
// e.g.
List<Integer> vals = lottery(1,34);
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
I have a problem with nested for loops in java. My problem is that at the beginning I don't know exactly how many for loops I will need. It is set somewhere in the middle of my program. So let say my program creates an array. If the array has 3 elements then I create a three for loops like below.
for(int i = 0; i<tab[0].length() ; i++){
for(int j = 0; j<tab[1].length() ; j++){
for(int k = 0; k<tab[2].length() ; k++){
System.out.println(i+" "+j+" "+k);
}
}
}
If my program created an array with 4 elements then it would be like this:
for(int i = 0; i<tab[0].length() ; i++){
for(int j = 0; j<tab[1].length() ; j++){
for(int k = 0; k<tab[2].length() ; k++){
for(int h = 0; h<tab[3].length() ; h++){
System.out.println(i+" "+j+" "+k+" "+h);
}
}
}
}
Can any one tell me how to do this with recursion? I can have 2 nested loops but I can have 10 of them and always at the end I would like to print in the console numbers associated with all loops (i,j,k,h)
Here is a solution. At each recursive call, previousTabs becomes 1 longer and tabs becomes 1 shorter.
public static void iterate(int[] previousValues, int[] tabs) {
if (tabs.length == 0) {
System.out.println(Arrays.toString(previousValues));
}
else {
final int[] values = new int[previousValues.length + 1];
for (int i = 0; i < previousValues.length; i++) {
values[i] = previousValues[i];
}
final int[] nextTabs = new int[tabs.length - 1];
for (int i = 0; i < nextTabs.length; i++) {
nextTabs[i] = tabs[i + 1];
}
for (int i = 0; i < tabs[0]; i++) {
values[values.length - 1] = i;
iterate(values, nextTabs);
}
}
}
public static void iterate(int[] tabs) {
iterate(new int[0], tabs);
}
i have an array of integers like this one :
A={1,1,4,4,4,1,1}
i want to count the each number once , for this example the awnser is 2 becuase i want to count 1 once and 4 once
i dont want to use sorting methods
i am unable to find a way to solve it using java.
i did this but it gives me 0
public static void main(String args[]) {
int a[] = { 1,1,4,4,4,4,1,1};
System.out.print(new Test4().uniques(a));
}
public int uniques(int[] a) {
int unique = 0;
int tempcount = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
if (a[i] == a[j]) {
tempcount++;
}
}
if (tempcount <= 2) {
unique=a[i];
}
tempcount = 0;
}
return unique;
}
the purpose of the question is to understand the logic of it but not solving it using ready methods or classes
This one should work. I guess this might be not the most elegant way, but it is pretty straightforward and uses only simple arrays. Method returns number of digits from array, but without counting duplicates - and this I believe is your goal.
public int uniques(int[] a) {
int tempArray[] = new int[a.length];
boolean duplicate = false;
int index = 0;
int digitsAdded = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < tempArray.length; j++) {
if (a[i] == tempArray[j]) {
duplicate = true;
}
}
if(!duplicate) {
tempArray[index] = a[i];
index++;
digitsAdded++;
}
duplicate = false;
}
//this loop is needed if you have '0' in your input array - when creating temp
//array it is filled with 0s and then any 0 in input is treated as a duplicate
//again - not most elegant solution, maybe I will find better later...
for(int i = 0; i < a.length; i++) {
if(a[i] == 0) {
digitsAdded++;
break;
}
}
return digitsAdded;
}
Okay first of all in your solution you are returning the int unique, that you are setting as the value that is unique a[i]. So it would only return 1 or 4 in your example.
Next, about an actual solution. You need to check if you have already seen that number. What you need to check is that for every number in the array is only appears in front of your position and not before. You can do this using this code below.
public int uniques(int[] a) {
int unique = 1;
boolean seen = false;
for (int i = 1; i < a.length; i++) {
for (int j = 0; j < i; j++) {
if (a[i] == a[j]) {
seen = true;
}
}
if (!seen) {
unique++;
}
seen = false;
}
return unique;
}
In this code you are iterating over the number you have seen and comparing to the number you are checking (a[i]). You know that for it to be unique you cant have seen it before.
I see two possible solutions:
using set
public int unique(int[] a) {
Set<Integer> set = new HashSet<>();
for (int i : a) {
set.add(i);
}
return set.size();
}
using quick sort
public int unique(int[] a) {
Arrays.sort(a);
int cnt = 1;
int example = a[0];
for (int i = 1; i < a.length; i++) {
if (example != a[i]) {
cnt++;
example = a[i];
}
}
return cnt;
}
My performance tests say that second solution is faster ~ 30%.
if restricted to only arrays, consider trying this:
Lets Take a temporary array of the same size of orignal array, where we store each unique letter and suppose a is your orignal array,
int[] tempArray= new int[a.length];
int tempArraycounter = 0;
bool isUnique = true;
for (int i = 0; i < a.length; i++)
{
isUnique = true;
for (int j = 0; j < tempArray.length; j++)
{
if(tempArray[j] == a[i])
isUnique = false;
}
if(isUnique)
{
tempArray[tempArraycounter] = a[i];
tempArraycounter++;
isUnique = false;
}
}
now tempArraycounter will be your answer ;)
Try Following code:
int test[]={1,1,4,4,4,1,1};
Set<Integer> set=new LinkedHashSet<Integer>();
for(int i=0;i<test.length;i++){
set.add(test[i]);
}
System.out.println(set);
Output :
[1, 4]
At the end set would contain unique integers.