Can someone could be kind and help me out here. Thanks in advance...
My code below outputs the string as duplicates. I don't want to use Sets or ArrayList. I am using java.util.Random. I am trying to write a code that checks if string has already been randomly outputted and if it does, then it won't display. Where I am going wrong and how do I fix this.
public class Worldcountries
{
private static Random nums = new Random();
private static String[] countries =
{
"America", "Candada", "Chile", "Argentina"
};
public static int Dice()
{
return (generator.nums.nextInt(6) + 1);
}
public String randomCounties()
{
String aTemp = " ";
int numOfTimes = Dice();
int dup = 0;
for(int i=0 ; i<numOfTimes; i++)
{
// I think it's in the if statement where I am going wrong.
if (!countries[i].equals(countries[i]))
{
i = i + 1;
}
else
{
dup--;
}
// and maybe here
aTemp = aTemp + countries[nums.nextInt(countries.length)];
aTemp = aTemp + ",";
}
return aTemp;
}
}
So the output I am getting (randomly) is, "America, America, Chile" when it should be "America, Chile".
When do you expect this to be false?
countries[i].equals(countries[i])
Edit:
Here's a skeleton solution. I'll leave filling in the helper methods to you.
public String[] countries;
public boolean contains(String[] arr, String value) {
//return true if value is already in arr, false otherwise
}
public String chooseRandomCountry() {
//chooses a random country from countries
}
//...
int diceRoll = rollDice();
String[] selection = new String[diceRoll];
for ( int i = 0; i < selection.length; i++ ) {
while (true) {
String randomCountry = chooseRandomCountry();
if ( !contains(selection, randomCountry ) {
selection[i] = randomCountry;
break;
}
}
}
//...then build the string here
This doesn't check important things like the number of unique countries.
You need a data structure which allows you to answer the question "does it already contain item X?"
Try the collection API, for example. In your case, a good candidate is either HashSet() or LinkedHashSet() (the latter preserves the insert order).
You'd probably be better of using another structure where you save the strings you have printed. Since you don't want to use a set you could use an array instead. Something like
/*
...
*/
bool[] printed = new bool[countries.length];
for(int i=0 ; i<numOfTimes ; /*noop*/ )
{
int r = nums.nextInt(countries.length);
if (printed[r] == false)
{
i = i + 1;
printed[r] = true;
aTemp = aTemp + countries[r];
aTemp = aTemp + ",";
}
}
return aTemp;
Consider what you're comparing it to:
if (!countries[i].equals(countries[i]))
are you comparing c[i] to c[i]? or c[i] to c[i-1]? Or do you need to check the whole array for a particular string? Perhaps you need a list of countries that get output.
make list uniqueCountries
for each string called country in countries
if country is not in uniqueCountries
add country to uniqueCountries
print each country in uniqueCountries
When you do this, watch out for index out of bounds, and adjust accordingly
Much faster way to do it then using HashSets and other creepy stuff. Takes less code too:
public String randomCounties() {
List<String> results = Arrays.asList(countries);
Collections.shuffle(results);
int numOfTimes = Dice();
String result = " ";
for(int i=0 ; i<numOfTimes; i++) {
result = result + countries[i] + ", ";
}
return result;
}
If you want to avoid outputting duplicate values, you need to record what values have already been listed or remove values from the pool of possibilities when they get selected.
You mention that you do not want to use Sets or ArrayList (I assume you mean Lists in general), I assume that is a requirement of the assignment. If so, you can accomplish this by building arrays and copying data between them the same way that an ArrayList would.
one note, your current implementation chooses between 1 and 6 entries from and array of 4 entries. If you force the selections to be unique you need to decide how to handle the case when you have no more unique selections.
Related
Hoping for some help - I've been asked to write a hotel room system using methods for uni. All has been going well until I try to order the array alphabetically.
I have managed to get it to order within the method but it updated the main array (hotel). I want it to keep it within the order method, if that makes sense?
I've included a cut down version below without all the functions.
Currently it will reorder the array hotel so if you view the rooms the array will print like 'e,e,e,etc, George, Peter, Robert' instead of keeping its original form 'e, Robert, Peter, e,e,etc, George'
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String roomName;
int roomNum = 0;
String[] hotelRef = new String[12];
String[] hotel = new String[12];
initialise(hotel); //initialise
while (roomNum < 13) {
System.out.println("Please select from the menu:");
System.out.println("V : View rooms");
System.out.println("O : Order Guests alphabetically");
String selection = input.next();
switch (selection) {
//There are more switch cases on the original version
case "O":
order(hotel);
break;
default:
System.out.println("");
}
}
}
private static void order(String[] hotelRef) {
int j;
boolean flag = true; //will determine when the sort is finished
String temp;
String[] order = new String[12];
order = hotelRef;
while (flag) {
flag = false;
for (j = 0; j < order.length - 1; j++) {
if (order[j].compareToIgnoreCase(order[j + 1]) > 0) {
//ascending sort
temp = order[j];
order[j] = order[j + 1]; // swapping
order[j + 1] = temp;
flag = true;
}
}
}
for (int y = 0; y < order.length; y++) {
if (!order[y].equals("e")) {
System.out.println("Room " + y + " is occupied by " + order[y]);
}
}
System.out.println("Ordering completed");
}
You should clone the hotelRef instead of assigning the reference like this order = hotelRef;
You could do the following while creating the order array :
String[] order = new String[hotelRef.length]; // to make sure that order has the right size.
and instead of order = hotelRef;
for (int i=0;i<order.length;i++)
order[i]=hotelRef[i]; // thereby cloning
or use System.arraycopy() or any other method to accomplish cloning the array.
You can make copy of hotel array in your order method:
String[] hotelCopy = new String[hotelRef.length];
System.arraycopy(hotelRef, 0, hotelCopy, 0, hotelRef.length);
And then just use hotelCopy inside your order method.
The problem lies with the following line
order = hotelRef;
Change it to
order = hotelRef.clone();
Though you are creating a new object, you have assigned the reference to outer object only. So whatever changes you make in the inner object it will be reflected to the outer object.
I'm trying to store 5 different boolean answers (true or false) in 5 different array positions after each loop and then make a method to display the questions which were 'true'.
For example, a test run would go like this:
Question1: Content1 ~ (True or False?) False
Question2: Content2 ~ (True or False?) True
Question3: Content3 ~ (True or False?) False
(loop finished)
Question2: Content2
(exit)
And here is my code so far.
import javax.swing.*;
class booleanTest {
public static void main(String [] params) {
String[] data = {"Test1", "Test2", "Test3", "Test4", "Test5"};
boolean[] user = new boolean[5];
array_input(data, user);
System.out.println(user); // to see if it works atm
System.exit(0);
}
public static String array_input(String[] a, boolean[] b) {
String x = "";
for (int i=0; i<a.length; i++) {
x = JOptionPane.showInputDialog("Data: " + a[i]);
if(x.equals("yes")) {
b[i] = true;
}
else {
b[i] = false;
}
}
return x;
}
//public static String array_print() {
// print the boolean + question here
//}
}
It doesn't work, I understand that the b[i] = true part must be wrong, I should do something else?
If the value at an index of the boolean array is true, print out the value in the String array at that index.
public static void printTrue(boolean[] answers, String[] questions) {
// checking both indices to avoid ArrayIndexOutOfBoundsException
for (int i = 0; i < answers.length && i < questions.length; i++) {
// if the answer is true
if (answers[i]) {
System.out.println(questions[i] + ": " + true);
}
}
}
When you say System.out.println(user); prints something like [Z#3b9187c7, this is because the toString() implementation for Object returns class name + # + hex hashCode().
The Arrays#toString method creates a more readable result:
[false, false, false, true, true]
You only have to return values in a method when you have no other way of accessing the data. If you look at your code you see that you're not even using the returned value, and the last values for x will never be useful anyway. In that kind of case, you can make it a void method. Void methods are used when you want it to perform some kind of operation, but don't need it to return any values. Your code works because an array is an Object and the changes done to it can be seen even outside the method.
Here's more or less how I would implement it. Notice the variable names are a little more descriptive.
import javax.swing.*;
public class Main {
public static void main(String[] args) {
String[] questions = {"Test1", "Test2", "Test3", "Test4", "Test5"};
boolean[] responses = getUserResponses(questions);
}
public static boolean[] getUserResponses(String[] questions) {
boolean[] responses = new boolean[questions.length]; //use the length of the other array. Don't count on it always being 5
for (int i = 0; i< questions.length; i++) {
String x = JOptionPane.showInputDialog("Data: " + questions[i]);
if(x.equals("yes")) {
responses[i] = true;
}
else {
responses[i] = false;
}
}
return responses;
}
}
In general, it's better not to modify parameter Objects and to instead return new ones. Sometimes it is much more useful or necessary to do it that way, but in your case it was not.
It looks like you're on the correct path.
Array creation and element assignment:
Your code for this looks fine. You create the array using the new operator, as you would any object, but must specify an array size, as you did. Element assignment is done using an index, either an integer literal or an integer variable (in the case of your code above). Array indices range from 0 to size-1. It looks like you also got that part right.
Printing the results:
In your scenario, you only want to some of the results, where the array value is true. A simple loop with an if(user[i]) would do the trick.
for (int i = 0; i < user.length; i++) {
if (user[i]) {
System.out.println(data[i] + " = " + true);
}
}
I'm trying to compress an array of objects that will have empty items interspersed with complete items. I want to put all the full elements at the start in the same order they started with, and the empty elements on the end.
The object in question uses a String field, "name", and an int field, "weight". An empty version has "no name" and 0 respectively. So an array of the type the method needs to deal with will contain something like:
Fred | 4
Bob | 3
no name | 0
Gina | 9
no name | 0
Yuki | 7
After feeding through the method, the array should go Fred, Bob, Gina, Yuki, no name, no name.
My thought for step one was to just figure out which were full and which weren't, so I came up with this:
public void consolidate() {
boolean[] fullSlots = new boolean[spaces.length];
// pass 1: find empties
for (int i = 0; i < spaces.length; i++) {
fullSlots[i] = spaces[i].getName().equals("no name");
}
}
spaces is the array of objects, getName() retrieves the name field from the object.
I'm not sure where to go from here. Suggestions?
EDIT: Okay, here's what Infested came up with:
public void consolidate()
{
int numberOfEmpties = 0, spacesLength = spaces.length;
Chicken[] spaces2 = new Chicken[spacesLength];
for(int i = 0; i < spaces.length; i++)
{
spaces2[i] = new Chicken(spaces[i].getName(),
spaces[i].getWeight());
}
// pass 1: find empties
for (int i = 0, j = 0; i < spacesLength; i++)
{
if (spaces2[i].getName().equals("no name") == false)
{
spaces[j] = new Chicken(spaces2[i].getName(),
spaces2[i].getWeight());
j++;
}
else
{
numberOfEmpties++;
}
}
for (int i = spacesLength - 1; numberOfEmpties > 0 ; numberOfEmpties--, i--)
{
spaces[i] = new Chicken("no name", 0);
}
}
Tested and working.
Java's Arrays.sort is stable, meaning that the relative order of equal elements is not going to change.
This sort is guaranteed to be stable: equal elements will not be reordered as a result of the sort.
You can use this property of the sorting algorithm to sort all your elements with a simple comparator:
Arrays.sort(
spaces
, new Comparator() {
public int compare(Object o1, Object o2) {
MyClass a = (MyClass)o1;
MyClass b = (MyClass)o2;
boolean aIsEmpty = "no name".equals(a.getName());
boolean bIsEmpty = "no name".equals(b.getName());
if (aIsEmpty && !bIsEmpty) {
return 1;
}
if (!aIsEmpty && bIsEmpty) {
return -1;
}
return 0;
}
}
);
This will sort all items with non-empty names ahead of the items with empty names, leaving the relative order of both groups of objects unchanged within their respective group.
If your space constraints allow you to create a new array of MyClass, you can go for a simpler algorithm: go through the original array once, and make a count of non-empty items. Then create a new array, and make two indexes: idxNonEmpty = 0, and idxEmpty = NonEmptyCount+1. Then go through the original array one more time, writing non-empty objects to idxNonEmpty++, and empty objects to idxEmpty++.
ill assume its a method of the class:
public void consolidate()
{
int lengthOfSpaces = spaces.length , i, numberOfEmpties = 0;
Type[] spacesNumberTwo = new Type[lengthOfSpaces ];
// pass 1: find empties
for (i = 0; i < lengthOfSpaces ; i++)
{
if(spaces[i].getName().equals("no name") == false)
spacesNumberTwo[i] = new Type(spaces[i].getName(), spaces[i].getInt());
else
numberOfEmpties++;
}
for (i = lengthOfSpaces - 1; numberOfEmpties > 0 ; numberOfEmpties--, i--)
{
spacesNumberTwo[i] = new Type("no name", 0);
}
spaces = spacesNumberTwo
}
Right now I have my array sorting (which is better than getting an error) except it is sorting in the reverse than what I want it to sort in.
public static void sortDatabase(int numRecords, String[] sDeptArr,
int[] iCourseNumArr, int[] iEnrollmentArr)
{
System.out.println("\nSort the database. \n");
String sTemp = null;
int iTemp = 0;
int eTemp = 0;
String a, b = null;
for(int i=0; i<numRecords; i++)
{
int iPosMin = i+1;
for(int j=iPosMin; j<numRecords; j++)
{
a = sDeptArr[i];
b = sDeptArr[iPosMin];
if(a.compareTo(b) > 0)
{
sTemp= sDeptArr[j];
sDeptArr[j] = sDeptArr[iPosMin];
sDeptArr[iPosMin] = sTemp;
iTemp = iCourseNumArr[j];
iCourseNumArr[j] = iCourseNumArr[iPosMin];
iCourseNumArr[iPosMin] = iTemp;
eTemp = iEnrollmentArr[j];
iEnrollmentArr[j] = iEnrollmentArr[iPosMin];
iEnrollmentArr[iPosMin] = eTemp;
}
else if(sDeptArr[j].equals(sDeptArr[iPosMin]) && !(iCourseNumArr[j] < iCourseNumArr[iPosMin]))
{
sTemp= sDeptArr[i];
sDeptArr[i] = sDeptArr[iPosMin];
sDeptArr[iPosMin] = sTemp;
iTemp = iCourseNumArr[i];
iCourseNumArr[i] = iCourseNumArr[iPosMin];
iCourseNumArr[iPosMin] = iTemp;
eTemp = iEnrollmentArr[i];
iEnrollmentArr[i] = iEnrollmentArr[iPosMin];
iEnrollmentArr[iPosMin] = eTemp;
}
else continue;
}
}
}
Again, no array lists or array.sorts. I need just to reverse how this is sorting but I have no idea how.
just do a.compareTo(b) < 0 instead of the > 0
EDIT: I've figured out the problem. But since this is homework (thanks for being honest), I won't post my solution, but here are a few tips:
You are doing selection sort. The algorithm isn't as complicated as you made it. You only have to swap if the two elements you are checking are in the wrong order. I see you have 3 branches there, no need.
Take a look at when you are assigning a and b. Through the inner loop, where j is changing, a and b never change, because i and iPosMin stay the same. I hope that helps.
It's always good to break your algorithm down to discreet parts that you know works by extracting methods. You repeat the same swap code twice, but with different arguments for indices. Take that out and just make a:
-
// swaps the object at position i with position j in all arrays
private static void swap(String[] sDeptArr, int[] iCourseNumArr, int[] iEnrollmentArr, int i, int j)
Then you'll see you're code get a lot cleaner.
First I'd say you need to build a data structure to encapsulate the information in your program. So let's call it Course.
public class Course {
public String department;
public Integer courseNumber;
public Integer enrollment;
}
Why not use the built in sort capabilities of Java?
List<Course> someArray = new ArrayList<Course>();
...
Collections.sort( someArray, new Comparator<Course>() {
public int compare( Course c1, Course c2 ) {
int r = c1.compareTo( c2 );
if( r == 0 ) { /* the strings are the same sort by something else */
/* using Integer instead of int allows us
* to compare the two numbers as objects since Integer implement Comparable
*/
r = c1.courseNumber.compareTo( c2.courseNumber );
}
return r;
}
});
Hope that gets you an A on your homework. Oh and ditch the static Jr. Maybe one day your prof can go over why statics are poor form.
Hmm... I wonder what would happen of you altered the line that reads if(a.compareTo(b) > 0)?
This question already has answers here:
How to generate a random alpha-numeric string
(46 answers)
Closed 6 years ago.
I have an object called Student, and it has studentName, studentId, studentAddress, etc. For the studentId, I have to generate random string consist of seven numeric charaters,
eg.
studentId = getRandomId();
studentId = "1234567" <-- from the random generator.
And I have to make sure that there is no duplicate id.
Generating a random string of characters is easy - just use java.util.Random and a string containing all the characters you want to be available, e.g.
public static String generateString(Random rng, String characters, int length)
{
char[] text = new char[length];
for (int i = 0; i < length; i++)
{
text[i] = characters.charAt(rng.nextInt(characters.length()));
}
return new String(text);
}
Now, for uniqueness you'll need to store the generated strings somewhere. How you do that will really depend on the rest of your application.
This is very nice:
http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/RandomStringUtils.html - something like RandomStringUtils.randomNumeric(7).
There are 10^7 equiprobable (if java.util.Random is not broken) distinct values so uniqueness may be a concern.
You can also use UUID class from java.util package, which returns random uuid of 32bit characters String.
java.util.UUID.randomUUID().toString()
http://java.sun.com/j2se/1.5.0/docs/api/java/util/UUID.html
Random ran = new Random();
int top = 3;
char data = ' ';
String dat = "";
for (int i=0; i<=top; i++) {
data = (char)(ran.nextInt(25)+97);
dat = data + dat;
}
System.out.println(dat);
I think the following class code will help you. It supports multithreading but you can do some improvement like remove sync block and and sync to getRandomId() method.
public class RandomNumberGenerator {
private static final Set<String> generatedNumbers = new HashSet<String>();
public RandomNumberGenerator() {
}
public static void main(String[] args) {
final int maxLength = 7;
final int maxTry = 10;
for (int i = 0; i < 10; i++) {
System.out.println(i + ". studentId=" + RandomNumberGenerator.getRandomId(maxLength, maxTry));
}
}
public static String getRandomId(final int maxLength, final int maxTry) {
final Random random = new Random(System.nanoTime());
final int max = (int) Math.pow(10, maxLength);
final int maxMin = (int) Math.pow(10, maxLength-1);
int i = 0;
boolean unique = false;
int randomId = -1;
while (i < maxTry) {
randomId = random.nextInt(max - maxMin - 1) + maxMin;
synchronized (generatedNumbers) {
if (generatedNumbers.contains(randomId) == false) {
unique = true;
break;
}
}
i++;
}
if (unique == false) {
throw new RuntimeException("Cannot generate unique id!");
}
synchronized (generatedNumbers) {
generatedNumbers.add(String.valueOf(randomId));
}
return String.valueOf(randomId);
}
}
The first question you need to ask is whether you really need the ID to be random. Sometime, sequential IDs are good enough.
Now, if you do need it to be random, we first note a generated sequence of numbers that contain no duplicates can not be called random. :p Now that we get that out of the way, the fastest way to do this is to have a Hashtable or HashMap containing all the IDs already generated. Whenever a new ID is generated, check it against the hashtable, re-generate if the ID already occurs. This will generally work well if the number of students is much less than the range of the IDs. If not, you're in deeper trouble as the probability of needing to regenerate an ID increases, P(generate new ID) = number_of_id_already_generated / number_of_all_possible_ids. In this case, check back the first paragraph (do you need the ID to be random?).
Hope this helps.
Many possibilities...
You know how to generate randomly an integer right?
You can thus generate a char from it... (ex 65 -> A)
It depends what you need, the level of randomness, the security involved... but for a school project i guess getting UUID substring would fit :)