Random Generate String from ArrayList without replacement in JAVA - java

I am trying to create a program that will allow users to enter a list of names. And then the program will pull from the ArrayList randomly and pull each name one at a time until all names have been used. I have the scanner part completed as seen below:
public class Auction
{
public static void main (String[] args)
{
Scanner scan = new Scanner(System.in);
ArrayList<String> names = new ArrayList<String> ();
char quit = 'Y';
String playername = null;
while (quit == 'Y')
{
System.out.println("\nPlayer Name:");
playername = scan.next();
names.add (playername);
System.out.print("Enter Another Name? (Y/N) \n");
String word = scan.next();
word = word.toUpperCase();
quit = word.charAt(0);
}
}
}
I have another class where I tried to complete the random generation with no success. There doesn't appear to be any errors but it's not working either. I know I am way off on the "random without replacing" part but I was just trying to get it to work before I moved on. I'm not sure if I am even referencing the ArrayList from the other Auction Class. Like a lot of others, I am new to Java so be gentle. I have spent a week on this which should probably have taken me a few hours. I appreciate your help.
public class Draft
{
Random randomGenerator;
ArrayList<String> names;
String randName() {
int index = randomGenerator.nextInt(names.size());
System.out.println("Next on the Block" + names.get(index));
return names.get(index);
}
}

Just use Collections.shuffle() to shuffle the list itself:
Collections.shuffle(names);
Your list is now randomized and you can take elements from the top until it's empty. For example, using an iterator:
Iterator<List> it = names.iterator();
while (it.hasNext()) {
String name = it.next();
it.remove(); // optionally remove
System.out.println("Next on the block" + name);
}
Or, if there's no need to actually remove the name from the list, using a simple for loop:
for (String name : names) {
System.out.println("Next on the block" + name);
}

Related

Java, Reading two different types of variables from a file and using them as objects later

I working on a project that is based on reading a text from a file and putting it as objects in my code.
My file has the following elements:
(ignore the bullet points)
4
Christmas Party
20
Valentine
12
Easter
5
Halloween
8
The first line declares how many "parties" I have in my text file (its 4 btw)
Every party has two lines - the first line is the name and the second one is the number of places available.
So for example, Christmas Party has 20 places available
Here's my code for saving the information from the file as objects.
public class Parties
{
static Scanner input = new Scanner(System.in);
public static void main(String[] args) throws FileNotFoundException
{
Scanner inFile = new Scanner(new FileReader ("C:\\desktop\\file.txt"));
int first = inFile.nextInt();
inFile.nextLine();
for(int i=0; i < first ; i++)
{
String str = inFile.nextLine();
String[] e = str.split("\\n");
String name = e[0];
int tickets= Integer.parseInt(e[1]); //this is where it throw an error ArrayIndexOutOfBoundsException, i read about it and I still don't understand
Party newParty = new Party(name, tickets);
System.out.println(name+ " " + tickets);
}
This is my SingleParty Class:
public class SingleParty
{
private String name;
private int tickets;
public Party(String newName, int newTickets)
{
newName = name;
newTickets = tickets;
}
Can someone explain to me how could I approach this error?
Thank you
str only contains the party name and splitting it won't work, as it won't have '\n' there.
It should be like this within the loop:
String name = inFile.nextLine();
int tickets = inFile.nextInt();
Party party = new Party(name, tickets);
// Print it here.
inFile().nextLine(); // for flushing
You could create a HashMap and put all the options into that during your iteration.
HashMap<String, Integer> hmap = new HashMap<>();
while (sc.hasNext()) {
String name = sc.nextLine();
int tickets = Integer.parseInt(sc.nextLine());
hmap.put(name, tickets);
}
You can now do what you need with each entry in the HashMap.
Note: this assumes you've done something with the first line of the text file, the 4 in your example.
nextLine() returns a single string.
Consider the first iteration, for example, "Christmas Party".
If you split this string by \n all you're gonna get is "Christmas Party" in an array of length 1. Split by "blank space" and it should work.

Passing arrays as parameters and make calculations

I have to make a Java Program, where a user type in the total numbers of students, so I made this code:
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
int numReaders = 0;
Scanner scan = new Scanner(System.in);
System.out.println("Enter the number of magazin readers:");
numReaders = scan.nextInt();
Now, after adding the total number of students, we should add their names into an array:
//Creating an array of names, where the length is the total number entered by the user
String[] nameStr = new String[numReaders];
int[] ages = new int[numReaders];
for(int i=0; i<numReaders; i++)
{
Scanner n = new Scanner(System.in);
System.out.println("Enter the name of reader: "+i);
nameStr[i] = n.next();
}
After that, we should add correspondingly the age of each name, so I made this portion of code:
for(int i=0; i<numReaders; i++)
{
Scanner a = new Scanner(System.in);
System.out.println("Enter the age of reader: "+i);
ages[i] = a.nextInt();
}
//Display the results
System.out.println("Number of readers is: "+numReaders);
for (int i=0; i<numReaders; i++)
{
System.out.println("The name of reader "+i+" is "+nameStr[i]+ " and his age is "+ages[i]);
}
After making this code, I tested it using Ideone and Command Prompt and it works properly:
Now, I need to call method according to selection of the user:
if he typed 'a' a method should be called to specify the name and the age of the oldest student.
If he typed 'b' a method called to see how many students have an age specified by the user and If he typed 'c', a function called to calculate the average age of them all.
I am new to methods so I don't know how to add arrays into methods and make statements.
Here is the full code:
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
int numReaders = 0;
Scanner scan = new Scanner(System.in);
System.out.println("Enter the number of magazin readers:");
numReaders = scan.nextInt();
//Creating an array of names, where the length is the total number entered by the user
String[] nameStr = new String[numReaders];
int[] ages = new int[numReaders];
for(int i=0; i<numReaders; i++)
{
Scanner n = new Scanner(System.in);
System.out.println("Enter the name of reader: "+i);
nameStr[i] = n.next();
}
for(int i=0; i<numReaders; i++)
{
Scanner a = new Scanner(System.in);
System.out.println("Enter the age of reader: "+i);
ages[i] = a.nextInt();
}
//Display the results
System.out.println("Number of readers is: "+numReaders);
for (int i=0; i<numReaders; i++)
{
System.out.println("The name of reader "+i+" is "+nameStr[i]+ " and his age is "+ages[i]);
}
//Choosing a statistic
//if a:
System.out.println("Please choose a, b or C:");
Scanner stat = new Scanner(System.in);
char X;
X = stat.next().charAt(0);
if(X=='a')
System.out.println(X+X);
else if(X=='b')
//System.out.println(X);
//Scanner newAge = new Scanner(System.in);
//int ageToSearchFor = newAge.nextInt();
//maxAge(ageToSearchFor);
else
System.out.println(X);
}
}
Right, so to start with your user enters an input, for example 'a', so let's go with this:
Firstly, you need to create the method where the name of the oldest student is displayed, so let's call it 'getOldestStudent' - when naming methods this is the typical naming convention, starting lowercase and then moving to uppercase for each new word - try and make them as intuitive as possible.
When making the method signature, you need to give it its visibility and also what it is going to return. In this case, as you are only using one class, we will give it private, so it is only visible by this class.
Now we need to return 2 things, so we can either put these into a string or put them into an array, which is what I would recommend, so we are going to return an array. However, you want to input an array to search through, so this goes in tbe brackets as parameters (or arguments). Therefore our method signature is the following:
private String[] getOldestStudent(String[] students, int[] ages)
Then inside this method, you can simply do the code you need to find the oldest student, add their name and age to the array and then return this.
Need anymore help just drop a comment.
On a side note, you would have been better off creating a 'Student' object and then giving this object a 'name' property and an 'age' property and then simply making an array of students and getters and setters (or accessors and mutators) for these properties.
James Lloyd's covers your question pretty well, I thought I might add some input as I think you are struggling with some principles.
At first, I would do as James advised and create a class Student that stores the values for each person.
public class Student {
public String name;
public int age;
// Constructors allow you to create a new Object and set some variables
// when you create it.
public Student (String name) {
this.name = name;
}
}
I used public to avoid getters and setters for this explanation, but I'd use private most had I to write it by myself.
Anyways, that way you only have to use one instead of two arrays (and name and age are connected with each other, e.g., you know the age of a student you know the name of, whereas with two different arrays it could happen that you don't know if nameArray[0] belongs to ageArray[0].
So you have an array Student[] students = new Student[numReaders]; and you can set each Student after reading the input, i.e., after reading the name you call students[i] = new Student(name); If you want to set the age of a Student afterwards you can do so by using student[i].age = age.
Now that we have filled our array, we can advance to your actual question.
char method;
method = stat.next().charAt(0);
// I think switch is a little easier to read for such cases
switch(method) {
case 'a': Student oldest = getOldestStudent(students);
if (oldest != null)
System.out.println(oldest.name);
break;
case 'b': //another method
break;
default: // equals to else as if none of the other cases was fulfilled
break;
}
Now you can write your own method for each scenario you have to cover.
public Student getOldestStudent(Student[] students) {
// at first we check some cases that do not require further checks
if (students.length == 0) {
System.out.println("No students have been specified");
return null; // this might lead to a NullPointerException so check the return Object whether it is null before doing anything with it
} else if (students.length == 1)
return students[0];
// no we have to see which students if the oldest in the regular case
// the first student will be used for comparison
Student oldestStudent = students[0];
for (int i = 1; i < students.length; i++) {
// see if our current student is older
if (oldestStudent.age < students[i].age)
oldestStudent = students[i];
}
return oldestStudent;
}
This way you can easily access the Students name afterwards (see above in the switch). You can build all your methods like this by passing the array to the methods and iterating through it. Depending on whether you want to return one or more Students (as it might vary between the different methods) you have to change the return type from Student to Student[].

How to compare a string to multiple string arrays

I'm trying to write a program in which the user inputs their grocery list then based upon the type of item it is the program will give you a good order to shop for your items(i.e puts the meats together and the vegetables together)
here's my current problem, I can't get the user input to compare to the multiple string type arrays I have of store items.
String[] VegiFruit = {"Apples", "Lettuce", "Broccoli"};
String[] Meats = {"Ground beef", "Hambuger"};
Scanner USER_IN = new Scanner(System.in);
Methods Use = new Methods(); //This is another class I have, it just makes printing empty lines and lines of **** look nicer
Use.border();
System.out.println("Enter Item name then follow instructions.");
Use.space();
System.out.print("Item 1: ");
String InptOne = USER_IN.nextLine();
}
for (int i = 0; i < VegiFruit.length; i++)
{
if(Arrays.asList(VegiFruit).contains(InptOne))
{
System.out.println("Item is a VEGI");
}
}
for(int p = 0; p < Meats.length; p++)
{
if(Arrays.asList(Meats).contains(InptOne))
{
System.out.println("Item is a MEAT");
}
}
you need not go through the loops as contains method will compare with all the elements in the list.
I ran your code and the below works fine.
if(Arrays.asList(VegiFruit).contains(InptOne))
{
System.out.println("Item is a VEGI "+InptOne);
}
if(Arrays.asList(Meats).contains(InptOne))
{
System.out.println("Item is a MEAT "+InptOne);
}
However, please note that this is case senstive comparison and if the user does not enter the vegetable in your format then it will not work.
To solve that problem, you can take 2 approaches:
Have the list of veegetables/meat in caps and make the input.toUpperCase() before comparing it in contain method.
2.Use the answer on Array contains() without case sensitive lookup?

Java arrays in 2 arraylist

I have to write a program which allows the user to keep track of all the countries he has visited, and their capitals using 2 arraylists: Countries and Capitals. The user has three options to choose from a menu, he may either:
Add a country and its corresponding capital in the Countries and Capital arraylists respectively.
Query the system for the capital of a country by inputing the country's name. (If the country was visited, the capital should be displayed, else he should be given an error message: “You did not visit this country”).
Exit the program
For example the arraylist Countries contains [“England”, “France”, “Reunion”, “Nepal”] and the one for Capitals contains [“London”, “Paris”, “St.Denis”, “Kathmandu”]. If the user has visited Kenya whose capital is Nairobi, and wishes to add this to the arraylists, the Countries and Capitals arraylists should become: [“England”, “France”, “Reunion”, “Nepal”, “Kenya”] and Capitals contains [“London”, “Paris”, “St.Denis”, “Kathmandu”, “Nairobi”] respectively. If he wished to query for the capital of France the system should display “Paris”. If the user wishes to look for the capital of Australia – the system should display “You did not visit this country”.
So here is what I have come up so far:
import java.util.*;
public class MyClass {
public static void main(String[] args) {
ArrayList<String> countries = new ArrayList<String>();
Scanner sc = new Scanner(System.in);
String country;
String capital;
String search;
countries.add("England");
countries.add("France");
countries.add("Reunion");
countries.add("Nepal");
ArrayList<String> capitals = new ArrayList<String>();
capitals.add("London");
capitals.add("Paris");
capitals.add("St Denis");
capitals.add("Kathmandu");
System.out.println("Please choose one option:");
System.out.println("1. Add a new country and its capital.");
System.out.println("2. Search for the capital of a country.");
System.out.println("3. Exit.");
int opt = sc.nextInt();
if (opt == 1) {
country = sc.nextLine();
capital = sc.nextLine();
countries.add(country);
capitals.add(capital);
} else if (opt == 2) {
System.out.println("Enter the capital of the country.");
search = sc.next();
for (int i = 0; i < countries.size(); i++) {
for (int j = 0; j < capitals.size(); j++) {
if (search.equals(capitals.get(j))) {
System.out.println("The country is " + countries.get(i));
}
}
}
} else {
System.exit(0);
}
}
}
But actually, the for loop apparently does not work as when I enter the capital of the city, the program just terminates right there.
EDIT: I can't use HashMap but lists
You can just use a HashMap, with the country as key and the capital as value:
HashMap<String, String> hashMap = new HashMap<String, String>();
// add data to the HashMap
hashMap.put("England", "London"); //assign value "London" to key "England"
// get data from the HashMap
hashMap.get("England"); //returns "London"
EDIT: If you still want to use lists, you can do the following to retrieve the corresponding value. The benefit of this is that it works both ways:
capitals.get(countries.indexOf("England")); //it will return "London"
countries.get(capitals.indexOf("London")); //it will return "England"
Note this will only work if the lists are properly ordered (so the first country matches the first capital, the second country matches the second capital, etc)
Oh boy. Quite a few problems here.
First of all: Your code has no problem (related to what you call the problem) with the for loop.
You main method executes exactly one of the if branches, and then terminates. If you want the program to run re-prompting the menu after every completed operation until the terminate option is requested, you need to wrap the menu in a while loop:
int opt= sc.nextInt();
while (opt != 3) {
if (...)
}
System.exit(0);
In second place: in Java you usually don't do paired arrays (i.e. two arrays that are semantically linked by the positions of their elements). You can either create a class:
class CountryAndCapital {
String country;
String capital;
//...
}
ArrayListy<CountryAndCapital> myArray = new ArrayList<>();
or, as other have suggested, use a Map, which is a data structure that links one data to another (in this case, the capital to the country), and also prevents duplicates (in a sense...):
Map<String, String> countryToCapital = new HashMap<>();
countryToCapital.put("France", "Paris");
//...
Finally: if your arrays are paired, there is no need to iterate over both! You can iterate over the country one and just take that index over to the capitals one:
for(int i=0; i<capitals.size();i++) {
if(search.equals(capitals.get(i))) {
System.out.println("The country is "+countries.get(i));
}
}
There is a problem with you approach: There are countries with more than one capital
I think a good data structure that fits your needs would be a
Map<County,Capital[]>
Maps are very useful, the docs are here
Bonus dumb thought: If I visited Vatican City State, I'd have been at the same time in Rome, although not in Italy. Well... that would be true if the Vatican City had an airport, otherwise I surely have been in Italy right before
Put your code in while loop
Use HashMap instead
Give message before getting input from user
always try to take whole line as input when getting input from console
HashMap<String, String> countries = new HashMap<>();
Scanner sc = new Scanner(System.in);
String country;
String capital;
String search;
countries.put("England", "London");
countries.put("France", "Paris");
countries.put("Reunion", "St Denis");
countries.put("Nepal", "Kathmandu");
while (true) {
System.out.println("Please choose one option:");
System.out.println("1. Add a new country and its capital.");
System.out.println("2. Search for the capital of a country.");
System.out.println("3. Exit.");
System.out.print("Enter your choice : ");
int opt = Integer.parseInt(sc.nextLine());
if (opt == 1) {
System.out.print("Country : ");
country = sc.nextLine();
System.out.print("Capital : ");
capital = sc.nextLine();
countries.put(country, capital);
} else if (opt == 2) {
System.out.print("Enter the capital of the country : ");
search = sc.nextLine();
for(Map.Entry<String, String> entry : countries.entrySet()){
if(search.equals(entry.getValue())){
System.out.println("The country is " + entry.getKey());
break;
}
}
} else {
System.exit(0);
}
}

arraylist isn't printing out correctly in a separate method for loop? wrapper class or loops to blame?

for my project, i have an arraylist for the user to input whatever names they want in one method as long as it isn't stop. then in a separate method, the values i just inputted have to be called out again, so i can input more information for each name.
example:
enter names:
name: bob
name: joe
name: Stop
this triggers another method to prompt more info:
bob:
enter age:
enter address:
joe:
enter age:
enter address:
However, right now, the arraylist isn't printing out correctly, and i'm getting repeats of certain names, while other names don't show up in the second method. Also, the loop in the second method doesn't end. i enter in info for the names i entered, but i keep getting prompted with "name:" and no actual arraylist value. I suspect something is wrong with my loops, but i don't quite know how to fix it? I also thought that maybe the problem has something to do with how i'm using a wrapper to put in values into the arraylist, but i don'tknow how to fix that.
in the second method, I've tried swapping the countervariable to keep track of the order in the Array List with a separate counter in the second method, but it doesn't seem to make a difference. In the first method, i've tried swapping the loop with different a boolean while loop, with a straight up while (!input.equals("Stop")), a for loop counter inside of the previous two options, if loops, and some combination of the above.
here is my code
Scanner console = new Scanner(System.in);
private ArrayList<Directory> nameList; //i have to use object oriented programming to store values in the Directory Class
public int i;
first method:
private void addName()
{
Scanner LocalInput = new Scanner(System.in);
Directory buffer = null;
String ID = null;
System.out.println("Enter Station Designations Below, Enter Stop to quit");
boolean breaker = false;
while(breaker ==false)
{
System.out.print("Name: ");
ID = (LocalInput.nextLine());
if(ID.equals("Stop"))
breaker = true;
else
buffer = new Directory(ID);
nameList.add(buffer);
}
}
second method:
private void getInfo()
{
Scanner LocalInput = new Scanner(System.in);
Directory buffer;
buffer = nameList.get(i);
double age; String address;
System.out.println("Enter Temperatures below...");
System.out.println("" + nameList.get(i));
for (i = 0; i < nameList.size(); i++)
{
System.out.println("Name: " + buffer.GetID()); //there's a getter and setter in the Directory class
System.out.println( "Age:\t");
age = LocalInput.nextDouble();
System.out.print( "Address:\t");
address = LocalInput.nextLine();
buffer= new Directory(age, address);
nameList.add(buffer);
}
}
Critique of first method
I haven't looked closely yet, but I strongly suspect this is the problem:
if(ID.equals("Stop"))
breaker = true;
else
buffer = new Directory(ID);
nameList.add(buffer);
You appear to be expecting the last statement only to be executing when ID is not equal to "Stop", but actually it's always going to execute. Unlike (say) Python, whitespace is irrelevant in Java. If you statements to be considered as a block, you need braces:
if(ID.equals("Stop"))
breaker = true;
else {
buffer = new Directory(ID);
nameList.add(buffer);
}
Personally I would put braces around both parts:
if (ID.equals("Stop")) {
breaker = true;
} else {
buffer = new Directory(ID);
nameList.add(buffer);
}
... and quite possibly get rid of the somewhat-irrelevant buffer variable:
if (ID.equals("Stop")) {
breaker = true;
} else {
nameList.add(new Directory(ID));
}
I'd also get rid of the breaker variable, and limit the scope of ID (changing its name, too, to comply with normal conventions) with a result of:
while (true) {
System.out.print("Name: ");
string id = LocalInput.nextLine();
if (id.equals("Stop")) {
break;
}
nameList.add(new Directory(ID));
}
Critique of second method
This is really odd at the moment. It's not at all clear where the i variable is declared, or why you only fetch buffer once, or why you're just adding to the existing list rather than mutating the existing object. I suspect you really want:
for (Directory entry : nameList) {
System.out.println("Name: " + entry.GetID());
System.out.println( "Age:\t");
double age = LocalInput.nextDouble();
entry.setAge(age);
System.out.print( "Address:\t");
String address = LocalInput.nextLine();
entry.setAddress(address);
}
Note that your current loop will always continue until i equals nameList.size() - but you're always increasing the size in the loop, so you'll never terminate.
private void getInfo()
{
Scanner LocalInput = new Scanner(System.in);
double age; String address;
for (Directory name : nameList) {
System.out.println("Name: " + name .GetID());
System.out.println( "Age:\t");
double age = LocalInput.nextDouble();
name.setAge(age);
System.out.print( "Address:\t");
String address = LocalInput.nextLine();
name.setAddress(address);
}
}
get method should be like this
and Add must be -
private void addName()
{
Scanner LocalInput = new Scanner(System.in);
Directory buffer = null;
String ID = null;
System.out.println("Enter Station Designations Below, Enter Stop to quit");
boolean breaker = false;
while(breaker ==false)
{
System.out.print("Name: ");
ID = (LocalInput.nextLine());
if(ID.equals("Stop"))
breaker = true;
else {
buffer = new Directory(ID);
nameList.add(buffer);
}
}
}
Consider using the break keyword, then you don't need the breakerflag and the else branch:
while(true)
{
System.out.print("Name: ");
ID = (LocalInput.nextLine());
if(ID.equals("Stop"))
break;
buffer = new Directory(ID);
nameList.add(buffer);
}
Sorry was already posted...

Categories