Using a WHILE statement to check against duplicates in Java - java

I am trying to write a program containing 3 String ArrayLists, where 1 item may be included in all 3 ArrayLists. However, the output must insure that the randomly selected items are all different. As I work through this issue, I am just using numbers so it will be easier to catch. I have been trying to solve this problem for a few days now, and figure there must be something I am overlooking. Here is the code for the method that must have the fault:
private void generateThree() {
// Find the maximum number the random can be.
index = thirdNumberArray.size();
// Initiate the random function.
Random rand = new Random();
// Generate a random number from 1 to the maximum.
randomInt = rand.nextInt(index);
// Access the item in the ArrayList using the random number as the index.
thirdDrawn = thirdNumberArray.get(randomInt);
// Check that the number is different than any previously set numbers.
while ((thirdDrawn.equals(secondDrawn)) || (thirdDrawn.equals(firstDrawn))) {
randomInt = rand.nextInt(index);
thirdDrawn = thirdNumberArray.get(randomInt);
}
// Set the output.
thirdNumberLabel.setText((thirdDrawn));
// Reset the index.
index = 0;
}
So far, the IF statement I use to check the secondDrawn against the firstDrawn has worked perfectly. But the above code still allows the thirdDrawn to display a duplicate of both the firstDrawn and secondDrawn. I know this problem has to be in my loop logic, but I just can't grasp what it is. I have tried multiple different IF statements, but they didn't solve the whole problem. Can anyone give me some feedback or corrections? Thanks in advance.

Any time you generate a number you want to draw, add it to a HashSet<String>. Then, have your if statement conditional check !myHashset.contains(thirdDrawn).

Related

How to get the previous value of a variable

I made a program that thinks of a number and you have to guess the number.
It is working well, but I got stuck.
First of all, you (the player) has 10 tries in a round. Every wrong guess subtracts 1 from the tries. If you reach 0 you lose.
The variable where the thing stores the randomized number looks like this:
int guess = Integer.parseInt(etGuess.getText().toString());
Of course I have an edittext field with the name etGuess.
So when the player enters the same number twice (for example: 5, then 5 again), the program subtracts 1 then again 1 (so 2) tries.
I'd like to know how can I get the previous value of the guess integer and check whether it was already guessed or not.
I think of something like this:
if ( previous_guess != guess )
Use a HashSet.
Here's how I would do this:
//Declare the variable outside of a function
HashSet<Integer> previousGuesses = new HashSet<Integer>();
//Check if it is already guessed
if (set.contains(guess)) {
//Alert the user that they can't use this.
}
//Adding a variable to it in a function:
set.add(guess);
Make sure to test if it contains before adding it or preforming any of the regular code.
Store all of your previous numbers in an array and then check the array then the player enters a new number.

Shuffle an array so every value will have a different index [duplicate]

This question already has answers here:
How to test randomness (case in point - Shuffling)
(11 answers)
Closed 8 years ago.
I have written a method to shuffle a String array
So the task is to implement WhiteElephant concept for a given string array of list of names.Should generate assignments to match the original elements.
I have written method to pick a random number and used a map to store the values so that each value will have a different index. But this prints out only 5 values. and i am confused now.
public static String[] generateAssignments(final String[] participants) {
Random r = new Random();
int size = participants.length;
HashMap val = new HashMap();
int change = 0;
String[] assignments = new String[6];
System.out.println("Using arrays");
for(int i=0; i<size;i++){
for(int j =0; j<size; j++){
change = r.nextInt(size);
if(val.containsValue(change) || change==i){
continue;
}
else val.put(i, change);
assignments[i] = participants[change];
System.out.println(assignments[i]);
break;
}
}
return assignments;
}
I appreciate your inputs.
Thanks,
Lucky
If your shuffle method is random (or pseudorandom) it will be near impossible to unit test since the output is non deterministic. If you allow for seeding a random number generator then you could ensure the output is consistent given the same seeds, though this doesn't show randomness.
You could also run the shuffle method a large number of times and check that each card shows up at each index an approixmately equal number of times. Over a large enough number of simulations this should help illustrate randomness.
FYI - There are some logical errors in both your shuffle() code and the test. I won't address those here; hopefully having a good test will allow you to figure out the problems!
Writing tests around Random data is hard.
The best option is to pass in an instance of Random to your shuffle() method or it's containing class. Then in test usages, you can pass in an instance of Random which has been seeded with a known value. Given that the Random code will behave the same every time and you control the input array, your test will be deterministic; you can confidently assert on each object in the sorted collection.
The only downside of this approach is that you won't have a test preventing you from re-writing your shuffle() method to simply re-order the elements every time into this specified order. But that might be over-thinking it; usually we can trust our future selves.
An alternative approach is to assume that in a Random world, given enough time, every data possibility will be realized.
I used this approach when testing a 6-sided die's roll() method. I needed to ensure that getting all values from 1-6 was possible. I didn't want to complicate the method signature or the Die constructor to take in an instance of Random. I also didn't feel confident in a test that used a known seed and simply always asserted 3 (i.e.).
Instead, I made the assumption that given enough rolls, all values from 1-6 would eventually be rolled. I wrote a test that infinitely called roll until all values from 1-6 had been returned. Then I added a timeout to the test so that it would fail after 1 second if the above condition hadn't been met.
#Test(timeout = 1000)
public void roll_shouldEventuallyReturnAllNumbersBetweenOneAndSixInclusively() {
Die die = new Die();
Set<Integer> rolledValues = new HashSet<Integer>();
int totalOfUniqueRolls = 0;
while (rolledValues.size() < Die.NUM_SIDES) {
if (rolledValues.add(die.roll())) {
totalOfUniqueRolls += die.getFaceValue();
}
}
assertEquals(summation(1, Die.NUM_SIDES), totalOfUniqueRolls);
}
Worst case scenario it fails after 1 second (which hasn't happened yet) but it usually passes in about 20 milliseconds.
The test must be reproducible: it is not useful if it depends on something random.
I suggest you to use mocking so the CUT (code under test) don't use the real Random class instantiated in production, but a different class written by you with a predictable behavior, giving you the possibility to make some significant assertions on two or three items.
It appears your shuffle() method will always return the same result. So given a input test array of however many elements in your test, just specify the exact output array you'd expect.
It looks like you are trying to write a very general test. Instead, your tests should be very specific: given a specific input A then you expect a specific output B.

Java bar chart method

I need to print out a bar chart, via a call from a method barChartPrinter. I.e. barChartPrinter(5, 6, 2); would print: a vertical column of 5 XX's followed by
a space then a vertical column of 6 XX's and a vertical column of 2 XX's.
The numbers are based on user input, so I'm thinking I need to gather the numbers and store those in an array. And I'm thinking a for loop will be involved,
but I'm not sure how I'd do it.
public class BarChart {
public static void main(String args[]) {
int[] list = new int[4];
Scanner input = new Scanner(System.in);
System.out.println("Enter four integers: ");
for(int i = 0; i < list.length; i++)
list[i] = input.nextInt();
System.out.println();
barChartPrinter(list);
}
public static void barChartPrinter(int[] numbers) {
int max = numbers[0];
for (int i = 0; i < numbers.length; i++)
if(numbers[i] > max)
max = numbers[i];
}
}
This is where I get stuck: defining the method that will print out the bar chart; given the user input values. The method needs to print out in this format, i.e.
barChartPrinter(1, 2, 3, 4) =
For some reason, it won't display how the bar chart should be constructed on here so I'll just describe it:
There would first be a column of XX, then a column of XX (two of these vertically to represent 2), then another column of XX (but this time three of these on top of each other, to represent the number 3) and finally another column of XX * 4 vertically.
Any pointers?
OK, by now I'm sure that you know that it would be trivially easy to create horizontal bar graphs:
2 6 4
**
******
****
Since the print and println methods of the console's PrintStream (the out of System.out) prints things horizontally. The trick for your assignment is how to print this graph vertically. And for that you're going to have to use a little logic. Since this is obviously homework, I'm not going to give you a solution but rather will suggest options.
You know that you'll need to use a loop of some sort to print lines in a row.
One possible solution has you figuring out how many times to loop in advance of the loop by first finding the maximal value held by the array. If you do this, then use a for loop.
Another possible solution you don't find max, but rather just loop til done. Here use a while loop. This would be the option I'd use, and I'd use a boolean variable, say named keepGoing to help tell the while loop when to keep looping and when to stop.
If you go with this latter option, you'll use an int counter in the loop to check what row you're on, and you'll advance this counter inside of the loop.
You will need to nest a for loop inside of your while loop to go through each array item.
You'd use this counter and the array items (in the for loop within the while loop) to see if the String that you will eventually print should have an "* " added to it.
After the inner for loop, you'll print the String you've created.
If no "* " are present (you could call myString.trim().isEmpty()), then keepGoing = false; and the while loop should stop.
Edit: your posted code is a bit off in that it tells the user to enter four numbers but only accepts three. You'll want to fix this.
Edit 2 You state:
Hey, sorry yeah I've sorted the code out. I've coded the way to find the max value within the method. I'm stuck on the step of actually producing the chart now. I know that it will print the XX's each row horizontally, but I'm still stumped as to how I can achieve this- I know it will involve a for loop, but I can't see how I can print the XX's for each column; apologies if I'm missing something obvious
Again, break up your problem by splitting up the big problem into little steps, the smallest you can think of, and then solve each small step. You know that you're going to have to construct a String to be printed, and so you should focus on that, on how to construct this String so that an asterisk is present where need be, and a space is present when the column should show no asterisk. Try to come up with a solution, even a partial solution and post it as an edit to your question, much like how I'm posting this edit to my answer.

Efficiently generating a list of random nonrepeating numbers in Java [duplicate]

This question already has answers here:
random number generator from a range for continuos analysis
(2 answers)
Closed 9 years ago.
I need to generate a list of non repeating random numbers between 0 and 1000 as efficiently as possible in Java. I only have 2 ideas right now and would like to know if there are any other better ideas and if not which I the following ideas should I use?
generate a random number r between 0 and 1000 and add it to another array called randomArray[r] at index r
generate another random number and check if randomArray[r] isn't already storing a previously generated random number
keep going until I'm done
generate an array and fill its element with its index
shuffle it like crazy(also, how can I do this efficiently?)
use the elements value in the array starting from the beginning.
Thanks!
java.util.Collections.shuffle method shuffle a List with equal likelihood. create a List and add value from 0 to 1000. Then use this method to shuffly the List.
List l = new ArrayList();
for(int i = 0; i <= 1000; i++)
l.add(i);
Collections.shuffle(l);
Now the list contains the shuffled values.
Try using a LinkedHashSet<Integer> (see documentation).
A regular HashSet<Integer> stores a set of Integers efficiently: placing a new number and checking if a number is already present is done in constant time (when storing the numbers in an array, as you mentioned, these lookups take linear time to check).
Now, since you say you want a list of numbers, we use a LinkedHashSet<Integer> which has all the properties of the regular HashSet<Integer>, and also garantees that if you loop over the elements, you will always iterate through them in the same order.
The code would look something like this:
Set<Integer> randomNumberList = new LinkedHashSet<Integer>();
int r;
// Make sure the number is not present in the list, and then add it:
do {
r = ... // Generate your next random number
} while( randomNumberList.contains(r) );
// At this point, we know r is not in the list, so add it:
randomNumberList.add(r);
// Do the previous as many times as you want.
// Now, to iterate over the list:
for(Integer number : randomNumberList) {
// Do something...
}
Note that the do-while loop is necessary if you want to make sure you actually add a number to the list.

How do I remove objects from an Array in java based on certain condition?

:)
I have
int[] code = new int[10];
It has the following values:
code[0] = 1234;
code[1] = 2222;
code[2] = 2121;
code[3] = 4321;
code[4] = 3333;
code[5] = 2356;
The code in this case refers to the serial number of the files.
The user is suppose to enter the code of the file to remove that specific file.
Let's say user enter 3333 as the code to remove.
code[4] = 3333 would be removed and code[5] = 2356 will move up to take its place. See below...
code[0] = 1234;
code[1] = 2222;
code[2] = 2121;
code[3] = 4321;
code[4] = 2356;
How would I tackle this problem?
I read up that using an Array List would make my life much easier.
However, I was told to just use an array.
Any help please? :)
How would I tackle this problem?
Allocate a new array and copy all of the values that you want to keep from the existing array to the new one.
You could also update the array in place, filling the "hole" at the end of the array with some special value that can't be a legal code.
Since this is a "sounds like homework" question, I'll leave you to figure out how to code it. (It is pretty simple. Just a loop, a test, and some careful manipulation of a second index.)
That's simply not possible. Arrays have a fixed size, so you'll have to make a second array with its size reduced by 1 and copy all values except the one you want to keep. Or keep track of the "working size" of the array separately, at which point you're begun to reimplement ArrayList.
You can simply set the value to something which is improbable (like -1 to save yourself the trouble of moving around and adjust arrays using System.arrayCopy or the likes. This of course assumes that the aim is to get the functionality working. If "moving" elements is an absolute requirement, you'd have to create a new array as mentioned by another comment here.

Categories