JAVA Code that checks for duplicates doesn't work - java

I am learning how to code and my teacher gave me an exercise to create a lottery program that generates 6 random numbers between 1 and 49 with no duplicates and one bonus number that could be a duplicate. My program generates all the numbers fine, but for some reason duplicates still appear. Could someone please explain why the code that checks for duplicates doesn't work, as I have been struggling to understand why it doesn't work. Please bear in mind that I'm a new programmer so try and keep explanations beginner friendly. Thanks in advance.
int[] lottonums = new int[6];
//Generates 6 random numbers between 1-49
for(int i = 0; i < lottonums.length; i++){
lottonums[i] = (int)(Math.random()* 49 +1);
}
//Checks for duplicates
for(int x = 0; x < 6; x ++){
for(int y = x + 1; y < 6; y ++){
while(lottonums[x] == lottonums[y]){
lottonums[y] = (int)(Math.floor(Math.random() * 49 + 1));
}
}
}
//Bonus ball, no checks for duplicates
int bonusBall = (int)(Math.random() * 49 + 1);
Arrays.sort(lottonums);
System.out.println("\nThe lottery numbers are: ");
for( int nu = 0; nu < lottonums.length; nu ++){
System.out.print(lottonums[nu] + " " );
}
System.out.println("\nThe bonus number is: " + bonusBall + "\n");

Best Way to have unique number is by using Set instead of array.
if you are not aware much about set have a look into it set TreeSet
Basically if you look at your code
//Checks for duplicates
for(int x = 0; x < 6; x ++){
for(int y = x + 1; y < 6; y ++){
while(lottonums[x] == lottonums[y]){
//below line does not gurrantee its going to insert unique number
//example [1,2,6,6] here at index 2 and 3 6 is there
//now you got this while checking duplicate
//after you are generating new random suppose new generated number is 2
// as you are not going back to check duplicate so it will be inserted
lottonums[y] = (int)(Math.floor(Math.random() * 49 + 1));
}
}
}
you can try the below solution using set
which fits yous requirement
// TreeSet will have unique element in sorted manner no need to sort again
TreeSet<Integer> set=new TreeSet<>();
int n=6;
while(set.size()<n-1)
{
set.add((int)(Math.random()* 49 +1));
}
//Bonus ball, no checks for duplicates
int bonusBall = (int)(Math.random() * 49 + 1);
System.out.println("\nThe lottery numbers are: ");
for( int nu :set){
System.out.print(nu + " " );
}
System.out.println("\nThe bonus number is: " + bonusBall + "\n");
}

Related

Error when picking out unique numbers in an array

This is a problem in my textbook for my Java class where the user enters 10 integers. The program is supposed to read all integers and only display the unique numbers (not duplicated) as the output. I am having trouble understanding why my output is not picking up the last unique value in the array (5). Can anyone give some insight to this issue? Any help would be appreciated. (Since we are in the early stages of the class and understanding the language, our assignment is to complete this using a nested loop.)
-The output is:
Enter 10 numbers: 1 2 3 2 1 6 3 4 5 2
The number of distinct numbers is 5
The distinct numbers are: 1 2 3 6 4
-When it should be:
Enter 10 numbers: 1 2 3 2 1 6 3 4 5 2
The number of distinct numbers is 6
The distinct numbers are: 1 2 3 6 4 5
public class ch7e5{
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter 10 numbers: ");
int[] numberArray = new int[10];
//create array for all numbers
int[] distinctArray = new int[10];
//create array for distinct numbers
int distinct = 0;
for (int i = 0; i < 10; i++)
numberArray[i] = input.nextInt();
distinctArray[0] = numberArray[0];
//first value will be distinct
for (int i = 1; i < numberArray.length; i++) {
//loop to go through remaining values in numberArray
boolean exists = false;
//create boolean
for (int j = 0; j < numberArray.length; j++) {
//loop to check if value exists already in distinctArray
if (numberArray[i] == distinctArray[j]) {
exists = true;
break;
//break out of inner loop
}
}
if (exists == false) {
//if value is unique then add it to the distinct array
distinct++;
distinctArray[distinct] = distinctArray[i];
}
}
//}
System.out.println("The number of distinct numbers is " + distinct);
System.out.print("The distinct numbers are: ");
for (int k = 0; k < distinct; k++)
System.out.print(distinctArray[k] + " ");
}
}```
There are 3 distinct numbers, 1, 2, and 3 are not any of them as they appear twice. The output should be 6 4 5. I'm not sure how you got 5 distinct numbers here, maybe you inputted them wrong? I would try not using a scanner at first and try putting the numbers in the array manually. Additionally, I would create a boolean array length 10 starting all true to record if numbers are distinct. If a number appears twice, the corresponding boolean in the array will be false. I will update this with code once i have written it.
EDIT: apparently having a duplicate does not delete it from the distinct list. If this is the case, please elaborate on the title.
Here is my code:
public class Main {
public static void main(String[] args) {
int inputs = 3;
int[] numberArray = new int[inputs];
int distinct = 0;
boolean[] mirror = new boolean[inputs];
//just setting up arrays
for(int i = 0; i < numberArray.length; i++) {
//numberArray[i] = i;
mirror[i] = true;
}
numberArray[0] = 1;
//finds out what numbers are not distinct
for (int x = 0; x < numberArray.length; x++) {
for (int y = 0; y < numberArray.length; y++) {
System.out.println("x is " + x);
System.out.println("y is " + y);
if(numberArray[x] == numberArray[y] && x != y) {
System.out.println(numberArray[x] + " is not distinct");
mirror[x] = false;//if current position in array matches any other position, number is not distinct
}
}
}
//calculates how many are distinct
for(int j = 0; j < inputs; j++) {
if(mirror[j]) {distinct++;}
}
//outputs text
System.out.println("The number of distinct numbers is " + distinct);
System.out.print("The distinct numbers are: ");
for(int k = 0; k < inputs; k++){
if(mirror[k]) {System.out.print(numberArray[k] + " ");}
}
}
}
The error was here
distinct++;
distinctArray[distinct] = distinctArray[i];
1, you should increment distinct after adding a number to distinctArray, and 2, you should have done distinctArray[distinct] = numberArray[i]. Right now, you're just putting what is possibly a 0 into distinctArray[distinct].
A shorter way to do it would be this
int[] distinctArray = Arrays.stream(numberArray).distinct().toArray();
System.out.println("The number of distinct numbers is " + distinctArray.length);
System.out.print("The distinct numbers are: ");
for (int d : distinctArray) System.out.print(d + " ");
Output:
Enter 10 numbers: 1 2 3 2 1 6 3 4 5 2
The number of distinct numbers is 6
The distinct numbers are: 1 2 3 6 4 5

How would I sort this ArrayList output by Count column

I'm just trying to sort the tabbed output by the Count and have all the other columns be sorted appropriately.
int maxNum = A6DiceRolling.diceSides;
Scanner sc = new Scanner(System.in);
int rollnum;
int randomValue;
NumberFormat formatter = new DecimalFormat("#0.00");
ArrayList<Integer> numbers = new ArrayList<Integer>();
ArrayList<Integer> counts = new ArrayList<Integer>();
//Using ArrayList for my Sum and Counts
System.out.println("Welcome to the Dice Roll Stats Calculator!");
System.out.println("Enter amount of rolls: ");
rollnum = sc.nextInt();
for (int i = 0; i < rollnum; i++) {
randomValue = (1 + (int) (Math.random() * maxNum)) + (1 + (int) (Math.random() * maxNum));
if (numbers.contains(randomValue)) {
int position = numbers.indexOf(randomValue);
counts.set(position, counts.get(position) + 1);
} else {
numbers.add(randomValue);
counts.add(1);
}
}
System.out.println("Sum\tCount\tPercentage");
System.out.println("----\t---\t----------");
for (int i = 0; i < numbers.size(); i++) {
System.out.println(numbers.get(i) + "\t" + counts.get(i)
+ "\t" + formatter.format(((double) (counts.get(i) * 100)) / rollnum) + "%");
What I need is an output that sorts my 'count' column.
I'm not familiar with the sort method for Array, but since ArrayList is different, I don't know where to begin looking on how to implement it to what I've got here.
What I'm getting as an output now:
After 1000 rolls of 6-sided Dice
Sum Count Percentage
--- --- ----------
3 63 6.30%
5 116 11.60%
9 93 9.30%
7 167 16.70%
11 59 5.90%
4 85 8.50%
8 139 13.90%
10 90 9.00%
6 138 13.80%
2 27 2.70%
12 23 2.30%
Assuming both the lists have the same size i.e. numbers and counts - you should sort the counts list first using Collections.sort() API and then iterate over the counts list instead of numbers
Collections.sort(counts);
for (int i = 0; i < counts.size(); i++) {
System.out.println(numbers.get(i) + "\t" + counts.get(i)
+ "\t" + formatter.format(((double) (counts.get(i) * 100)) / rollnum) + "%");
For further readings on how to sort a list and why it's different than Set or Map, go through this post
Why is there no SortedList in Java?

Java arraylist throwing dice

I'm new to Java and i'm trying to make a arraylist.
I made a small program that asks the user for a amount of dices to roll :
System.out.println("How many dices do you want to throw?");
int diceAmount = input.nextInt();
then I made a loop to print the dices but I can't get it to make the amount of dices to be random. I have to count the total dices with the random results also:
for (int i = 1; i <= diceAmount; i++) {
System.out.print(i + "-");
Random rand = new Random();
(int i = 1; i <= diceAmount; i++) {
// roll the dice once
int roll1 = rand.nextInt(6) + 1;
System.out.print(i + "-" + roll1);
}
UPDATE:
Here is the way to sum up the numbers. So let's say you roll 2 dice every time.
Random rand = new Random();
// roll the dice once
int roll1 = rand.nextInt(6) + 1;
int roll2 = rand.nextInt(6) + 1;
sum = roll1 + roll2;
System.out.println("You got " + sum + ". Not bad!");
For each die roll you want a random number (presumably 1-6, if its a traditional die). So your loop is correct, but the body of the loop needs fixing:
for(int i = 0; i < diceAmount; i++){ //repeats diceAmount times
//Do loop stuff.
}
To get a random number, start with Math.random(). This will return a random double in the range [0 .. 1). This means that 0 is a valid return, but 1 is not. From there we want to stretch the range to go up to 6.
Math.random() * 6
Returns a random double in the range [0 ..6). We need integers, not doubles, so let's cast that.
(int)(Math.random() * 6)
Returns a random int in the range [0 .. 6) -> [0 .. 5]. From there, just add 1.
(int)(Math.random() * 6) + 1
Will return a random int in the range [1 .. 6], which is precisely your goal. So all together:
for(int i = 0; i < diceAmount; i++){
int dieRoll = (int)(Math.random() * 6) + 1;
System.out.println(dieRoll);
}
Use Math.random() to randomise your number of dice. There are lots of overloaded version of random() method. Read about Java.Math in Oracle documentation.

Working with random integers

Here is the assignment:
For this program, there are two "parts". The first part will run the trials and determine how many caps each trial opens before finding a winning cap. Every trial (person) will be a winner. The number of caps opened by each trial is written to the file.
The second part of the program will read in the values and calculate the average. The average should be between 4.5 and 5.5 since there is a 1 in 5 chance of winning.
It compiles and runs, but the average is always 0.
My code:
int randNum = 0;
Random randNumList = new Random();
int counter = 0;
Scanner in = new Scanner(System.in);
System.out.println("How many trials will there be?");
int trials = in.nextInt();
int winner = 0;
PrintWriter outFile = new PrintWriter (new File("cap.txt"));
//run trials
for (int loop = 1; loop <= trials; loop++)
{
//select random number until 5 is selected
randNum = randNumList.nextInt(6);
for (randNum = randNumList.nextInt(6); randNum == 5; randNum++)
{
randNum = randNumList.nextInt(6);
counter++;
}
outFile.println(loop + " " + randNum);
}
outFile.close ( ); //close the file when finished
String token = " ";
Scanner inFile = new Scanner(new File("cap.txt"));
while (inFile.hasNext())
{
token = inFile.next();
if(token.equals("5"))
winner++;
}
double average = winner/counter;
System.out.println("The average number is " + average);
Apart from the int/int division accuracy problem which should be winner/(double)counter or (double)winner/counter try changing your inner for loop to a do while. In general, prefer while when you don't know the exact number of iterations.
Also, randNumList.nextInt(6) is [0-5], thus there are 6 possible outcomes -> there is a 1 in 6 chance of winning. To correct this, use randNumList.nextInt(5) + 1
for (int loop = 1; loop <= trials; loop++) {
//select random number until 5 is selected
do {
randNum = randNumList.nextInt(5) + 1;
counter++;
} while (randNum != 5);
outFile.println(loop + " " + randNum); //why here?? maybe you should add it below counter++;
}
also if(token.equals("5")) won't work, as you write (loop + randNum), it should work if you use outFile.println(randNum);
Your cap.txt file doesn't contain "5" => winner = 0 and average = 0/counter = 0 (always).
winner/counter returns an int not a double (integer division because both operands are integer so the result is truncated). Try this:
winner/(double)counter
That does return a double.

Equal Spacing In print statements

So I was just about finished with a small little program and when I ran it everything worked fine. I did have 1 small technical issue that I didnt like and it was an unevenly spaced "table" if you would. In a nutshell I want it so my outputs are aligned on both sides.
Original output:
How many numbers should be generated?
10
What is the number of values of each random draw?
1000
- 1 108
- 2 90
- 3 101
- 4 98
- 5 117
- 6 97
- 7 89
- 8 111
- 9 93
- 10 96
Code:
import java.util.Random;
import java.util.Scanner;
public class tester
{
public static void main(String[] args)
{
Random rnum = new Random();
Scanner in = new Scanner(System.in);
int x = 0;
int y = 0;
int num = 0;
int length = 0;
System.out.println("How many numbers should be generated?");
x = in.nextInt();
System.out.println("What is the number of values of each random draw?");
y = in.nextInt();
int[] roll = new int[x];
for(int i = 1; i<=y; i++){
num = rnum.nextInt(x);
roll[num] = roll[num] + 1;
}
length = (int) Math.log10(x) + 1;
for(int i = 0; i < x; i++){
System.out.println(i+1 + " " + roll[i]); //This is the code that prints the original output
/*
* This is the code I attempted that did not give the desired result
* a = i;
System.out.println(i+1);
while(Math.log10(i) < length){
System.out.print(" ");
length--;
}
System.out.print(roll[i]);*/
}
}
}
Take a look at the System.out.format (https://docs.oracle.com/javase/tutorial/essential/io/formatting.html) and in perticular the width option. This is probably what you are wanting.
Two ways to go about this:
1) As stated already, look at the System.out.format directory. It has a wide availability of methods to format your output
2) Change the spacing in a manual way, where the spacing depends on the amount of characters in the number to the left.

Categories