I want to make the program choose from an ArrayList based on my Scanner Input.
Like, I write breakfast and than sweet, and it has to randomize the list breakfastSweet and print me the randomized index.
I am still learning Java, I am just playing around and trying to code little projects to train it.
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// program begins here, you get asked what kind of lunch you want to eat
// after asking for the meal type and answering it, it goes to the next question
System.out.println("Hi, welcome to Recipe-Randomizer! What kind of meal do you want, breakfast, lunch or maybe dinner?");
System.out.print("Type one of the give choices now: ");
String mealType = scanner.nextLine();
System.out.print("So you want to eat for " + mealType + ". Do you want to eat some sweet or savory " + mealType + "?\nType in one of the given choices: ");
String flavor = scanner.nextLine();
System.out.println("A " + flavor + " " + mealType + "? Well, let's see what we have here.\nI am going to pick a random recipe.\nPlease wait...");
// list of meals, list name describes
ArrayList<String> breakfastSweet = new ArrayList();
ArrayList<String> breakfastSavory = new ArrayList();
ArrayList<String> lunchSweet = new ArrayList();
ArrayList<String> lunchSavory = new ArrayList();
ArrayList<String> dinnerSweet = new ArrayList();
ArrayList<String> dinnerSavory = new ArrayList();
GetRandomFromList.outputMeal(mealType, flavor, dinnerSavory); // doesn't make sense to put the list already in, I want it to automatically select the right list.
}
}
And here is the class I have already written:
import java.util.ArrayList;
import java.util.Random;
public class GetRandomFromList {
private static String randomList(ArrayList<String> list) {
Random rand = new Random();
return list.get(rand.nextInt(list.size()));
}
// the list should be chosen automatically, so my code doesn't work as I want it to work
public static void outputMeal(String mealType, String flavor, ArrayList<String> list){
if (mealType.equals("breakfast") && flavor.equals("sweet")){
System.out.println("What about " + GetRandomFromList.randomList() + "?");
}
}
}
Can I somehow store a list in a variable, maybe like this:
if (mealType.equals("breakfast") && flavor.equals("sweet")){
// here make a variable of the breakfastSweet list
}
I know it's hard to understand me, but English isn't my main language, hope its understandble.
To me GetRandomFromList doesn't make sense, unless GetRandomFromList contains all the data, instead, just assign a reference of the chosen List to another variable and then shuffle it to get a random value, for example...
// Previously created lists
Random rand = new Random();
Scanner scanner = new Scanner(System.in);
System.out.println("Hi, welcome to Recipe-Randomizer! What kind of meal do you want, breakfast, lunch or maybe dinner?");
System.out.print("Type one of the give choices now: ");
String mealType = scanner.nextLine();
System.out.print("So you want to eat for " + mealType + ". Do you want to eat some sweet or savory " + mealType + "?\nType in one of the given choices: ");
String flavor = scanner.nextLine();
System.out.println("A " + flavor + " " + mealType + "? Well, let's see what we have here.\nI am going to pick a random recipe.\nPlease wait...");
ArrayList<String> userChoice = null;
if (mealType.equals("breakfast") && flavor.equals("sweet")) {
userChoice = breakfastSweet;
} else if {...}
if (userChoice != null) {
Collections.shuffle(userChoice, rand);
String value = userChoice.get(0);
}
As with most things, there are more than one way to skin this cat. For example, you could Maps to combine the type/flavors together or your could create a POJO which has information about it's type/flavor associated directly with it
POJO, with List filter...
public class Meal {
public enum Type {
BREAKFAST, LUNCH, DINNER;
public static Type forType(String value) {
try {
return Type.valueOf(value.toUpperCase());
} catch (IllegalArgumentException exp) {
return null;
}
}
}
public enum Flavor {
SWEET, SAVORY;
public static Flavor forFlavor(String value) {
try {
return Flavor.valueOf(value.toUpperCase());
} catch (IllegalArgumentException exp) {
return null;
}
}
}
private Type type;
private Flavor flavor;
private String description;
public Meal(Type type, Flavor flavor, String description) {
this.type = type;
this.flavor = flavor;
this.description = description;
}
public Type getType() {
return type;
}
public Flavor getFlavor() {
return flavor;
}
public String getDescription() {
return description;
}
public boolean matches(Type type, Flavor flavor) {
return getType() == type && getFlavor() == flavor;
}
}
So, this defines the expected type/flavors and then allows you to define a meal of a specific type/flavor and provides a simple matches method to determine if the Meal is of a specific type/flavor, because I'm lazy.
Then we can do something like...
List<Meal> meals = new ArrayList<>(16);
// Get user input
Meal.Type type = Meal.Type.forType(mealType.toUpperCase());
Meal.Flavor flavor = Meal.Flavor.forFlavor(flavorValue.toUpperCase());
if (type != null && flavor != null) {
List<Meal> matchingMeals = new ArrayList<>(16);
for (Meal meal : meals) {
if (meal.matches(type, flavor)) {
matchingMeals.add(meal);
}
}
Collections.shuffle(matchingMeals);
Meal meal = matchingMeals.get(0);
System.out.println(meal.getDescription());
} else {
if (type == null) {
System.out.println(mealType + " is not a valid type");
}
if (flavor == null) {
System.out.println(flavorValue + " is not a valid flavor");
}
}
to look up a random meal.
Now, because you should be running in Java 8+, you could also replace...
List<Meal> matchingMeals = new ArrayList<>(16);
for (Meal meal : meals) {
if (meal.matches(type, flavor)) {
matchingMeals.add(meal);
}
}
with...
Predicate<Meal> filter = meal -> meal.matches(type, flavor);
meals.stream().filter(filter).collect(Collectors.toList());
but that might be a bit of an ask
Map
Or, we can use a Map of some kind to link the List of data with a specific "key".
Since you have a "composite" key style (you strictly don't need to, but I like having the flavour and type separated), I started with a MealKey concept.
public class MealKey {
private Type type;
private Flavor flavor;
public MealKey(Type type, Flavor flavor) {
this.type = type;
this.flavor = flavor;
}
#Override
public int hashCode() {
int hash = 3;
hash = 97 * hash + Objects.hashCode(this.type);
hash = 97 * hash + Objects.hashCode(this.flavor);
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final MealKey other = (MealKey) obj;
if (this.type != other.type) {
return false;
}
if (this.flavor != other.flavor) {
return false;
}
return true;
}
}
The important thing here is to ensure that any instance of a key with the same type/flavor always returns the same hashCode
I then modified the POJO to make it simpler/easier to deal with...
public enum Type {
BREAKFAST, LUNCH, DINNER;
public static Type forType(String value) {
try {
return Type.valueOf(value.toUpperCase());
} catch (IllegalArgumentException exp) {
return null;
}
}
}
public enum Flavor {
SWEET, SAVORY;
public static Flavor forFlavor(String value) {
try {
return Flavor.valueOf(value.toUpperCase());
} catch (IllegalArgumentException exp) {
return null;
}
}
}
public class Meal {
private String description;
public Meal(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
Then we fill our Map with the values we want
Map<MealKey, List<Meal>> meals = new HashMap<>();
// Fill the meals
List<Meal> breakfastSweet = new ArrayList<>();
// Add some meals to the list
meals.put(new MealKey(Type.BREAKFAST, Flavor.SWEET), breakfastSweet);
And then we can look up the meals list based on the user input...
// Get user input
Type type = Type.forType(mealType.toUpperCase());
Flavor flavor = Flavor.forFlavor(flavorValue.toUpperCase());
if (type != null && flavor != null) {
MealKey key = new MealKey(type, flavor);
List<Meal> mealsList = meals.get(key);
if (mealsList != null) {
Collections.shuffle(mealsList);
System.out.println(mealsList.get(0).getDescription());
}
} else {
if (type == null) {
System.out.println(mealType + " is not a valid type");
}
if (flavor == null) {
System.out.println(flavorValue + " is not a valid flavor");
}
}
nb: You could simply the "key" by simply using a String of "type" + "value" if you really wanted to 😉
I would rely on Map as the way to structure your data:
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Hi, welcome to Recipe-Randomizer! What kind of meal do you want, breakfast, lunch or maybe dinner?");
System.out.print("Type one of the give choices now: ");
String mealType = scanner.nextLine();
System.out.print("So you want to eat for " + mealType + ". Do you want to eat some sweet or savory " + mealType + "?\nType in one of the given choices: ");
String flavor = scanner.nextLine();
System.out.println("A " + flavor + " " + mealType + "? Well, let's see what we have here.\nI am going to pick a random recipe.\nPlease wait...");
// list of meals, list name describes
Map<String, Map<String, List<String>>> meals = new HashMap<>();
Map<String, List<String>> breakfast = new HashMap<>();
breakfast.put("sweet", new ArrayList<>());
meals.put("breakfast", breakfast);
// The same for the following:
// - lunch --> sweet --> list
// - lunch --> savory --> list
// - dinner --> sweet --> list
// - dinner --> savory --> list
GetRandomFromList.outputMeal(mealType, flavor, meals);
}
}
And then your GetRandomFromList would be simpler:
public class GetRandomFromList {
private static String randomList(List<String> list) {
Random rand = new Random();
return list.get(rand.nextInt(list.size()));
}
public static void outputMeal(String mealType, String flavor, Map<String, Map<String, List<String>>> meals){
Map<String, List<String>> meal = meals.get(mealType);
if (meal.isEmpty()) {
System.out.println("No possibilities found");
} else {
List<String> mealFlavourPossibilities = meal.get(flavor);
if (mealFlavourPossibilities.isEmpty()) {
System.out.println("No possibilities found");
} else {
System.out.println("What about " + GetRandomFromList.randomList(mealFlavourPossibilities) + "?");
}
}
}
}
Related
I have been trying to figure this out for hours and I have had no luck doing so,
I'm trying to iterate over my Arraylist<Booking> which utilizes my Booking class file and trying to understand how I'm able to search it for the matching, case-insensitive term.
this is my current method:
private void searchBookings() {
if (bookings.size() <= 0) {
JOptionPane.showMessageDialog(null, "There are no bookings.", "Search Bookings", 3);
} else {
String searchTerm = JOptionPane.showInputDialog(null, "Please input search term: ", "Search Bookings", 3);
for (int i = 0; i < bookings.size(); i++) {
while (!bookings.get(i).getStudent().getName().equalsIgnoreCase(searchTerm)) {
i++;
if (bookings.get(i).getStudent().getName().equalsIgnoreCase(searchTerm)) {
String output = String.format("%-30s%-18s%-18b$%-11.2f\n", bookings.get(i).getStudent(), bookings.get(i).getLessons(), bookings.get(i).isPurchaseGuitar(), bookings.get(i).calculateCharge());
this.taDisplay.setText(heading + "\n" + output + "\n");
}
}
}
}
JOptionPane.showMessageDialog(null, "There is no booking with that name.", "Search Bookings", 3);
}
I know it's messy but, just trying to make do.
I am trying to retrieve the name of the booking as I am searching by name as well as provide an error message if that names does not exist, to do that I must
use bookings.getStudent().getName() I have had some luck as I can return the value but now I am not able to provide my error message if I do not find it. Any help is appreciated.
package com.mycompany.mavenproject1;
public class Booking {
private Student student;
private int lessons;
private boolean purchaseGuitar;
// CONSTANTS
final int firstDiscountStep = 6;
final int secondDiscountStep = 10;
final int tenPercentDiscount = 10;
final int twentyPercentDiscount = 5;
final double LESSON_COST = 29.95;
final double GUITAR_COST = 199.00;
double LESSON_CHARGE = 0;
final int MINIUMUM_LESSONS = 1;
public Booking() {
}
public Booking(Student student, int lessons, boolean purchaseGuitar) {
this.student = new Student(student.getName(), student.getPhoneNumber(), student.getStudentID());
this.lessons = lessons;
this.purchaseGuitar = purchaseGuitar;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public int getLessons() {
return lessons;
}
public void setLessons(int lessons) {
this.lessons = lessons;
}
public boolean isPurchaseGuitar() {
return purchaseGuitar;
}
public void setPurchaseGuitar(boolean purchaseGuitar) {
this.purchaseGuitar = purchaseGuitar;
}
public double calculateCharge() {
double tempCharge;
if (lessons < firstDiscountStep) {
LESSON_CHARGE = (lessons * LESSON_COST );
} else if (lessons < secondDiscountStep) {
tempCharge = (lessons * LESSON_COST) / tenPercentDiscount;
LESSON_CHARGE = (lessons * LESSON_COST) - tempCharge;
} else {
tempCharge = (lessons * LESSON_COST) / twentyPercentDiscount;
LESSON_CHARGE = (lessons * LESSON_COST) - tempCharge;
}
if (isPurchaseGuitar()) {
LESSON_CHARGE += GUITAR_COST;
}
return LESSON_CHARGE;
}
#Override
public String toString() {
return student + ","+ lessons + "," + purchaseGuitar +"," + LESSON_COST;
}
}
If I understood you correctly, you are searching for a given student name in your collection of bookings. And if it is present, set a formatted text.
First of all, use a for-each loop, because you don't use the index.
Secondly, return from the for-each loop, when you found your student.
private void searchBookings() {
if (bookings.size() <= 0) {
JOptionPane.showMessageDialog(null, "There are no bookings.", "Search Bookings", 3);
} else {
String searchTerm = JOptionPane.showInputDialog(null, "Please input search term: ", "Search Bookings", 3);
for (final Booking booking : bookings) // for-each
{
if (booking.getStudent().getName().equalsIgnoreCase(searchTerm))
{
String output = booking.getFormattedOutput();
this.taDisplay.setText(heading + "\n" + output + "\n");
return; // break out of the loop and method and don't display dialog message
}
}
}
JOptionPane.showMessageDialog(null, "There is no booking with that name.", "Search Bookings", 3);
}
Then there are multiple other things, which you could improve.
Don't get all the data from a booking just to format it externally. Let the Booking class handle the formatting and return you the string you desire. (move the formatting in a function inside the Booking class)
Instead of recreating a Student you receive in your Booking constructor, make the Student class immutable, and then you can just reuse the object provided.
Try also making the Booking class immutable. You provided some setters, but do you really want to change the student in a booking? Or would you rather create a new booking for the other student?
The calculteCharge method could be stateless. Just get the LESSON_CHARGE value and hold it in a local variable. Your method would also get threading-proof.
Make your constants final and better yet make them members of the class (by adding the static modifier) instead of every member.
Lastly, representing a money amount with a floating (double is better but not good either) number, you will run into funny situations. Try this calculation: 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1 for example.
One way would be to create a Money class which holds the value in cents as an integer. And when you want to display the amount you can divide it by 100 and format it accordingly. That way, you can also restrict it become negative.
PS: Sometimes we desperately try to find a solution that we don't give ourselves some rest. After a little break, you might recognize the problem. Oh and try debugging with breakpoints. Or this, if you use IntelliJ IDEA (which I would highly recommend, the community edition is free).
You're re-incrementing your counter variable, which is really not going to help. Try the following:
private void searchBookings() {
if (bookings.size() <= 0) {
JOptionPane.showMessageDialog(null, "There are no bookings.", "Search Bookings", 3);
} else {
String searchTerm = JOptionPane.showInputDialog(null, "Please input search term: ", "Search Bookings", 3);
boolean studentFound = false;
for (int i = 0; i < bookings.size(); i++) {
if (bookings.get(i).getStudent().getName().equalsIgnoreCase(searchTerm)) {
String output = String.format("%-30s%-18s%-18b$%-11.2f\n", bookings.get(i).getStudent(),
bookings.get(i).getLessons(), bookings.get(i).isPurchaseGuitar(),
bookings.get(i).calculateCharge());
this.taDisplay.setText(heading + "\n" + output + "\n");
studentFound = true;
break;
}
}
}
if (!studentFound) {
JOptionPane.showMessageDialog(null, "There is no booking with that name.", "Search Bookings", 3);
}
}
I am looking to create an algorithm in Java that can take any number of "players" and group them up a specified number of times each. However, two pairs cannot be the same. So, if we are supplied 9 players (dubbed 0, 1, 2, etc) by the user and each player should be paired 3 times, that means that this algorithm needs to be able to generate a list of pairs where each player is paired 3 times.
So 4 players being paired two times could be: {{0, 1}, {2, 3}, {0, 2}, {1, 3}}.
Obviously, it can be impossible in some scenarios (like 4 players being uniquely paired 20 times), but I have input restrictions to combat that.
{0, 1} and {1, 0} are equal pairs. The order of the numbers does not matter, they are not unique.
The preferable way for input is just given two numbers (number of players, number of pairs per players) and the preferable way for the output to be given is in a two dimensional array of integers (each player being dubbed by an integer), like I gave an example of.
Does anyone have any ideas on how to do this? Pseudo-code, actual code, any ideas are welcome. Thanks!
I think your question is valid and interesting to solve in code.
This is why I coded that whole thing.
There's one downside to my solution, or rather: the problem.
In certain situations, some players can have many matches between them, while others have little. So in the end, some players might not get matched properly.
In this case, you'd need a mathematical trick, or a backtracking algorithm, that steps back on parts of the solution and tries (brute-forces) other combinations. My algorithm has neither, but it indicates Exceptions and validity.
Also check the comments in the code.
package snippet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
public class BadPairingStuff6 {
static class Player {
public final int mID;
private final BadPairingStuff6 mParentLogic;
public int mMatches;
public Player(final int pID, final BadPairingStuff6 pBadPairingStuff5) {
mID = pID;
mParentLogic = pBadPairingStuff5;
}
#Override public int hashCode() {
return mID;
}
#Override public boolean equals(final Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final Player other = (Player) obj;
if (mID != other.mID) return false;
return true;
}
#Override public String toString() {
return "Player[" + mID + "]";
}
public void incMatches() {
++mMatches;
}
public int getMatches() {
return mMatches;
}
public boolean canPlayAnotherMatch() {
return getMatches() < mParentLogic.mPairingsAllowed;
}
}
static class Pairing {
public final Player mPlayer1;
public final Player mPlayer2;
public Pairing(final Player pPlayer1, final Player pPlayer2) {
if (pPlayer1.mID < pPlayer2.mID) {
mPlayer1 = pPlayer1;
mPlayer2 = pPlayer2;
} else {
mPlayer1 = pPlayer2;
mPlayer2 = pPlayer1;
}
}
#Override public String toString() {
return mPlayer1 + "+" + mPlayer2;
}
#Override public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + mPlayer1.mID;
result = prime * result + mPlayer2.mID;
return result;
}
#Override public boolean equals(final Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final Pairing other = (Pairing) obj;
if (mPlayer1 != other.mPlayer1) return false;
if (mPlayer2 != other.mPlayer2) return false;
return true;
}
}
static class PartnerMap {
private final HashMap<Player, ArrayList<Player>> mMap = new HashMap<>();
public PartnerMap(final Iterable<Player> pPlayers) {
for (final Player player : pPlayers) {
final ArrayList<Player> partners = new ArrayList<>();
for (final Player partner : pPlayers) {
if (player != partner) partners.add(partner);
}
mMap.put(player, partners);
}
}
public Player getPartner(final Player pPlayer) {
final ArrayList<Player> possiblePartners = mMap.get(pPlayer);
if (possiblePartners.size() < 1) throw new NotEnoughPartnersException(pPlayer);
return possiblePartners.get((int) (Math.random() * possiblePartners.size()));
}
public void removePartners(final Player pPlayer, final Player pPartner) {
System.out.println("\t\tBadPairingStuff5.PartnerMap.removePartners(" + pPlayer + ", " + pPartner + ")");
System.out.println("\t\t\tRemoving for " + pPlayer);
System.out.println("\t\t\t\tBEFORE: " + toString(mMap.get(pPlayer)));
mMap.get(pPlayer).remove(pPartner);
System.out.println("\t\t\t\tAFTER: " + toString(mMap.get(pPlayer)));
System.out.println("\t\t\tRemoving for " + pPartner);
System.out.println("\t\t\t\tBEFORE: " + toString(mMap.get(pPartner)));
mMap.get(pPartner).remove(pPlayer);
System.out.println("\t\t\t\tAFTER: " + toString(mMap.get(pPartner)));
}
static String toString(final Iterable<Player> pPlayers) {
final StringBuilder sb = new StringBuilder();
sb.append("[");
for (final Player player : pPlayers) {
sb.append(player.mID + " ");
}
sb.append("]");
return sb.toString();
}
public void removePlayerCompletely(final Player pPlayer) {
System.out.println("\t\t\tBadPairingStuff5.PartnerMap.removePlayerCompletely(" + pPlayer + ")");
for (final ArrayList<Player> partnerMap : mMap.values()) {
partnerMap.remove(pPlayer);
}
mMap.get(pPlayer).clear();
}
public void print() {
System.out.println("Partner Map");
for (final Entry<Player, ArrayList<Player>> e : mMap.entrySet()) {
System.out.println("\t" + e.getKey());
for (final Player v : e.getValue()) {
System.out.println("\t\t" + v);
}
}
}
}
public static class NotEnoughPartnersException extends IllegalStateException {
private static final long serialVersionUID = -7249807214069096317L;
private final Player mPlayer;
public NotEnoughPartnersException(final Player pPlayer) {
super("Not enough partners available for " + pPlayer + "!");
mPlayer = pPlayer;
}
public Player getPlayer() {
return mPlayer;
}
}
static class PairingResult {
public final ArrayList<Pairing> mCreatedPairings;
public final ArrayList<Exception> mExceptions;
public PairingResult(final ArrayList<Pairing> pCreatedPairings, final ArrayList<Exception> pExceptions) {
mCreatedPairings = pCreatedPairings;
mExceptions = pExceptions;
}
public boolean isValid() {
return mExceptions.size() < 1;
}
}
public static void main(final String[] args) {
final int players = 10;
final int pairingsAllowed = 4;
final PairingResult result = new BadPairingStuff6(players, pairingsAllowed).createPairings();
System.out.println("All pairings:");
final HashMap<Long, Long> playCounter = new HashMap<>();
for (final Pairing p : result.mCreatedPairings) {
System.out.println("\t" + p);
{
final Long oldCount = playCounter.get(Long.valueOf(p.mPlayer1.mID));
playCounter.put(Long.valueOf(p.mPlayer1.mID), Long.valueOf(oldCount == null ? 1 : (oldCount.longValue() + 1)));
}
{
final Long oldCount = playCounter.get(Long.valueOf(p.mPlayer2.mID));
playCounter.put(Long.valueOf(p.mPlayer2.mID), Long.valueOf(oldCount == null ? 1 : (oldCount.longValue() + 1)));
}
}
System.out.println("Pairings per Player: ");
for (final Entry<Long, Long> e : playCounter.entrySet()) {
System.out.println("\t" + e.getKey() + " -> " + e.getValue());
}
System.out.println("Exceptions:");
System.out.flush();
sleep();
for (final Exception e : result.mExceptions) {
e.printStackTrace();
}
System.err.flush();
sleep();
System.out.println("Valid result: " + result.isValid());
System.out.println("All done.");
}
/*
* OBJECT
*/
final int mPairingsAllowed;
private final ArrayList<Player> mPlayers = new ArrayList<>();
public BadPairingStuff6(final int pPlayersCount, final int pPairingsAllowed) {
mPairingsAllowed = pPairingsAllowed;
// create players
for (int i = 0; i < pPlayersCount; i++) {
mPlayers.add(new Player(i, this));
}
}
public PairingResult createPairings() {
final ArrayList<Pairing> createdPairings = new ArrayList<>();
final ArrayList<Exception> exceptions = new ArrayList<>();
final PartnerMap possiblePairings = new PartnerMap(mPlayers);
final HashSet<Player> playersToHandle = new HashSet<>(mPlayers);
while (!playersToHandle.isEmpty()) {
final ArrayList<Player> removePlayersPerRound = new ArrayList<>();
for (final Player player : playersToHandle) {
if (!player.canPlayAnotherMatch()) {
possiblePairings.removePlayerCompletely(player);
removePlayersPerRound.add(player);
continue;
}
try {
System.out.println("Creating matches for " + player + " (" + player.getMatches() + ")");
final Player partner = possiblePairings.getPartner(player);
if (!partner.canPlayAnotherMatch()) continue;
final Pairing newPairing = new Pairing(player, partner);
if (createdPairings.contains(newPairing)) System.out.println("WARNING! Double hit for " + newPairing);
createdPairings.add(newPairing);
possiblePairings.removePartners(player, partner);
player.incMatches();
partner.incMatches();
System.out.println("\tMatched with " + partner);
if (!partner.canPlayAnotherMatch()) {
possiblePairings.removePlayerCompletely(partner);
removePlayersPerRound.add(partner);
}
} catch (final NotEnoughPartnersException e) {
// the flushes and sleeps are only a cheap shot to keep System.out and System.err outputs in somewhat chronological order.
// this is for proof/debug/answer only, and should NOT be used in production!
System.out.flush();
sleep();
e.printStackTrace();
// throw e; // if you want to abort early
removePlayersPerRound.add(e.getPlayer());
exceptions.add(e);
System.err.flush();
sleep();
}
}
playersToHandle.removeAll(removePlayersPerRound);
}
possiblePairings.print();
return new PairingResult(createdPairings, exceptions);
}
// the sleeps are only a cheap shot to keep System.out and System.err outputs in somewhat chronological order.
// this is for proof/answer only, and should NOT be used in production
static void sleep(final long pMilliSec) {
try {
Thread.sleep(pMilliSec);
} catch (final InterruptedException e1) { /* */ }
}
static void sleep() {
sleep(100);
}
}
I use lots of inner static classes. This is for demonstration purposes only.
If you want to actually use those classes, put each of them into its separate file (remove the "static class", and add a "public class" where it's missing).
Also note that this complexity is needed for random assignments. If the algorithm could always churn out the same combinations, it would be about 1/10th of the code.
I have a class named Country. There is 2 Strings named "name" and "code" in Country class.
I made a constructor that includes both of them.
In main, I build up a Country with name "germany" and for name parameter,I enter "Germany" and for code, I enter "GER".
I also made an ArrayList called countries that works with the type "Country" and I've added germany in it.
So the question is, how can I call name parameter in that ArrayList?
ArrayList does not have a direct method to get the object by the value of its properties, however it allows to retrieve objects by index using method get(int i) or by iterating and comparing the value.
Country germany = new Country("Germany", "GER");
List<Country> countries = new ArrayList<>();
countries.add(germany);
// use index
for (int i = 0, n = countries.size(); i < n; i++) {
if (countries.get(i).getName().equals("Germany")) {
System.out.println("Found!");
}
}
// iterate by index
for (Country country : countries) {
if (country.getName().equals("Germany")) {
System.out.println("Found!");
}
}
// use Stream API filter
countries.stream()
.filter(country -> country.getName().equals("Germany"))
.forEach(country -> System.out.println("Found!"));
If you need to look up the counties by name directly, a map Map<String, Country> should be used instead:
Map<String, Country> countryDictionary = new HashMap<>();
countryDictionary.put("Germany", germany);
countryDictionary.get("Germany"); // returns appropriate country or null
You have he class Country with the appropriate constructor to instantiate an complete instance of a Country object. What you want is an ArrayList (or List) of Country, for example,
List<Country> countries = new ArrayList<>();
Now, to fill the ArrayList with instances of Country you can do:
countries.add(new Country("Germany", "GER"));
countries.add(new Country("Sweden", "SWE"));
countries.add(new Country("Canada", "CAN"));
countries.add(new Country("United States of America", "USA"));
To get the ISO3 code from a supplied country name you might do:
List<Country> countries = new ArrayList<>();
countries.add(new Country("Germany", "GER"));
countries.add(new Country("Sweden", "SWE"));
countries.add(new Country("Canada", "CAN"));
countries.add(new Country("United States", "USA"));
Scanner input = new Scanner(System.in);
// Get country code from country name:
String country = "";
while(country.isEmpty()) {
System.out.println("Enter a Country name or 'n' for next example:");
System.out.print("Country: --> " );
country = input.nextLine().trim();
if (country.equalsIgnoreCase("n")) {
break; // Break out of current while loop
}
if (!country.matches("(?i)[a-z]+")) {
System.out.println("Invalid Entry! Try again...\n");
}
else {
for (Country cntry : countries) {
String ctry = cntry.getName();
if (ctry.equalsIgnoreCase(country)) {
System.out.println("Country Code for " + ctry + " is: --> " + cntry.getCode());
System.out.println("The List contains: --> " + cntry.toString());
break; // Break out of loop;
}
}
}
country = "";
System.out.println();
}
System.out.println();
// Get Country Name from Country Code:
String code = "";
while(code.isEmpty()) {
System.out.println("Enter a Country Code or 'n' for next example:");
System.out.print("Code: --> " );
code = input.nextLine().trim().toUpperCase();
if (code.equalsIgnoreCase("n")) {
break; // Break out of current while loop
}
if (!code.matches("(?i)[a-z]{3}")) {
System.out.println("Invalid Entry! Try again...\n");
}
else {
for (Country cntry : countries) {
if (cntry.getCode().equalsIgnoreCase(code)) {
System.out.println("Country Name for " + code + " is: --> " + cntry.getName());
System.out.println("The List contains: --> " + cntry.toString());
break; // Break out of loop;
}
}
}
code = "";
System.out.println();
}
// Print the whole list:
System.out.println("\n The whole list:\n ===============");
for (Country cntry : countries) {
System.out.println(cntry.toString());
}
This of course assumes the Country class is something like this:
public class Country {
private String name;
private String code;
public Country(String name, String code) {
this.name = name;
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
#Override
public String toString() {
return String.format("%-15s %-5s", name, code);
}
}
All in all however, I think it's just easier to utilize the java.util.Locale class to get this information, for example:
public static String getISO3CountryCode(String countryName) {
String countryCode = null;
String[] isoCountries = java.util.Locale.getISOCountries();
for (String country : isoCountries) {
java.util.Locale locale = new java.util.Locale("en", country);
String iso3 = locale.getISO3Country();
String name = locale.getDisplayCountry();
if (name.equalsIgnoreCase(countryName)) {
countryCode = iso3;
}
}
return countryCode;
}
A way you might use this method:
System.out.println(getISO3CountryCode("Australia"));
or
String code = getISO3CountryCode("Australia")
This would ultimately supply you with the ISO-Alpha3 code of AUS. If you want the ISO-Alpha2 code (AU) then you would change the method code line of:
String iso = locale.getISO3Country();
with:
String iso = locale.getCountry();
If you want a list of all country codes...well I think you know what to do.
Right now I'm working on a method for comparing the scores of athletes in the olympics. So far I've had little trouble, however now I've reached a point where i need to compare two objects (athletes) scores and I'm not sure how to do it. This is my code for the Olympic class:
// A program using the Athlete class
public class Olympics {
public static void main(String args[]) {
System.out.println("The leader is " + Athlete.leader() +
", with a score of " + Athlete.leadingScore());
Athlete meryl = new Athlete("Meryl Davis", "U.S.");
meryl.addScore(75);
System.out.println(meryl);
Athlete tessa = new Athlete("Tessa Virtue", "Canada");
System.out.println(tessa);
System.out.println(); // blank line
tessa.addScore(50);
System.out.println(tessa);
System.out.println(meryl);
System.out.println("The leader is " + Athlete.leader() +
", with a score of " + Athlete.leadingScore());
System.out.println(); // blank line
tessa.addScore(100);
meryl.addScore(65);
System.out.println(tessa);
System.out.println(meryl);
System.out.println("The leader is " + Athlete.leader() +
", with a score of " + Athlete.leadingScore());
System.out.println(); // blank line
tessa.addScore(20);
System.out.println("Tessa's final score is " + tessa.getScore());
meryl.move("France");
System.out.println(meryl);
} // end main
} // end class Olympics
And this is the constructor class "Athlete":
public class Athlete {
private String name;
private String country;
protected int score;
public static int leadScore;
public Athlete(String athName, String athCountry) {
this.name = athName;
this.country = athCountry;
score = 0;
if (score < 1) {
System.out.println("Score cannot be lower than 1");
}
}
public int addScore(int athScore) {
score += athScore;
return score;
}
public static String leader(){
//TODO
}
public static int leadingScore() {
//MUST COMPARE BOTH ATHLETES
}
public int getScore(){
return score;
}
public void move(String newCountry) {
country = newCountry;
}
public String toString() {
return name + ": " + "from " + country + ", current score " + score;
}
}
So what I'm trying to do is have the program check Meryl's score compared to Tessa's and return that Athlete's score in leadingScore() and, using that athlete, return a leader(). Any help is appreciated! Thanks.
The function must take the two Athletes you're comparing as the parameters for this to work
public static int leadingScore(Athlete a1, Athlete a2) {
if (a1.getScore() < a2.getScore()) {
// do stuff
}
}
The lead score should not be in the athlete class, but rather in main () because one instance of an Athlete class would not know of other instances unless you put a self-referential list inside the class. Similarly, leadingScore should be in main ().
It or main can call each athlete and compare:
int merylScore = meryl.getScore ();
int tessaScore = tessa.getScore ();
int leadingScore = 0;
String leaderName = "";
if (merylScore > tessaScore) {
leadingScore = merylScore;
leaderName = meryl.getName ();
} else if (tessaScore > merylScore) {
leadingScore = tessaScore;
leaderName = tessa.getName ();
} else {
leadingScore = merylScore;
leaderName = "a tie between Meryl and Tessa";
}
System.out.println ("The leader is " + leaderName + ", with a score of " + leadingScore);
You should consider using a "collection". Use an array, a list ... or even a sorted list.
Stored your individual objects in the collection, then traverse the collection to find the highest score.
For example:
// Create athlete objects; add each to list
ArrayList<Athlete> athletes = new ArrayList<Athlete>();
Athlete meryl = new Athlete("Meryl Davis", "U.S.");
meryl.addScore(75);
...
athletes.add(meryl);
Athlete tessa = new Athlete("Tessa Virtue", "Canada");
...
athletes.add(tessa );
// Go through the list and find the high scorer
Athlete highScorer = ...;
for (Athlete a : athletes) {
if (highScorer.getScore() < a.getScore())
highScorer = a;
...
}
System.out.println("High score=" + highScorer.getScore());
Here's a good tutorial:
http://www.vogella.com/tutorials/JavaCollections/article.html
This my whole code.
I want to make a simple program that will read a
text file and put it to array then write it to the
same text file,
also can add and delete the existing input and my input.
Problem
The delete and writer part seems not working, only blank text file when I run the code
These are the error after I select the exit.
java.lang.NullPointerException at ContactList.writer(ContactList.java:51) at
ContactListDriver.main(ContactListDriver.java:73) at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at
java.lang.reflect.Method.invoke(Unknown Source) at
edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:27‌​2)
public class Contact {
//Each contact stores the name, phone number, and email address
private String name;
private String number;
private String email;
public Contact(String name, String number, String email)
{
this.name = name;
this.number = number;
this.email = email;
}
public String getName()
{
return name;
}
public String getNumber()
{
return number;
}
public String getEmail()
{
return email;
}
public void setName(String name)
{
this.name = name;
}
public void setNumber(String number)
{
this.number = number;
}
public void setEmail(String email)
{
this.email = email;
}
}
class for processing the inputs.
import java.io.*;
import java.lang.*;
import java.util.*;
public class ContactList {
public Contact[] myContacts;
public static final int MAX = 100;
private int numContacts;
public ContactList()
{
myContacts = new Contact[MAX];
numContacts = 0;
}
public void addContact(String name, String number, String email)
{
Contact c = new Contact(name, number, email);
myContacts[numContacts] = c;
numContacts++;
}
public void deleteContact(String name)
{
for ( int i = 0; i <= numContacts-1 ; i++){
if( name == myContacts[i].getName())
{
myContacts[i] = null;
break;
}
}
numContacts--;
}
public void writer(){
String x = "MyContacts.txt";
try {
PrintWriter outputs = new PrintWriter(x);
for( int i=0; i < myContacts.length; i++)
{
Contact c = myContacts[i];
if(c!=null){ // check if c is null before writing to file
outputs.println(""+c.getName()+" "+c.getNumber()+" "+c.getName());
outputs.flush();
}
}
outputs.close();
}catch (IOException e) {
e.printStackTrace();
}
catch(NullPointerException ex){
}
}
public void displayContacts()
{
int i;
for(i=0; i < myContacts.length; i++)
{
Contact c = myContacts[i];
if(null != c){
System.out.println("Name: " + c.getName());
System.out.println("Number: " + c.getNumber());
System.out.println("Email: " + c.getEmail());
System.out.println("------------------------------------");
}
}
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
The Driver....
public class ContactListDriver {
public static void main(String[] args) throws FileNotFoundException
{
ContactList cList = new ContactList();
File in = new File("MyContacts.txt");
Scanner sc = new Scanner(in);
int option;
char again = 'n';
String name = null;
String number = null;
String email = null;
while(sc.hasNext())
{
//read one line from text file
String entry = sc.nextLine();
//System.out.println(entry);
String[] con = entry.split("\\s+");
//System.out.println(con[0] + " " + con[1] + " " + con[2]);
cList.addContact(con[0], con[1], con[2]);
}
Scanner userIn = new Scanner(System.in);
do{
displayOptions();
option = userIn.nextInt();
switch(option)
{
case 1:
System.out.println(" Name > ");
name = userIn.next();
System.out.println(" Number > ");
number = userIn.next();
System.out.println(" Email Address > ");
email = userIn.next();
cList.addContact(name, number, email);
break;
case 2:
//delete contact
System.out.println("Contact Name > ");
name = userIn.next();
cList.deleteContact(name);
break;
case 3:
//display contact
cList.displayContacts();
break;
case 4:
cList.writer();
System.out.println(" are you sure ? press y ");
String x = userIn.next();
again = x.charAt(0);
break;
}
}while( again == 'n' );
}
private static void displayOptions() {
System.out.println("(1) Add");
System.out.println("(2) Delete");
System.out.println("(3) Show Contacts");
System.out.println("(4) Exit");
}
}
One problem I see is:
You have a extra break; statement inside deleteContact(String name) function
and String comparision name == myContacts[i].getName() should be name.equals(myContacts[i].getName())
public void deleteContact(String name)
{
for ( int i = 0; i <= numContacts-1; i++){
if( name.equals( myContacts[i].getName()))// string comparison uses equals();
{
myContacts[i] = null;
numContacts--; // this line should be inside of if condition
break;
}
// break; No need of breaking the loop here
}
}
Another problem is at writer() function
public void writer(){
String x = "MyContacts.txt";
try {
PrintWriter outputs = new PrintWriter(x);
for( int i=0; i < myContacts.length; i++)
{
Contact c = myContacts[i];
if(c!=null){ // check if c is null before writing to file
outputs.println(""+c.getName()+" "+c.getNumber()+" "+c.getName());
outputs.flush();
}
}
outputs.close();
}catch (IOException e) {
e.printStackTrace();
}
catch(NullPointerException ex){ // Or just catch the NPE
}
You have declared and initialized the Contact array of size MAX. but,it seems to be that you haven't initialized the elements though. i.e. c is null in the below code
Contact c = myContacts[i];
outputs.println(""+c.getName()+" "+c.getNumber()+" "+c.getName());
outputs.flush();
myContacts[i] should return a Contact instance. As said by Meno, there are lot of other problems in your code. You have to always cover all the possible scenarios while writing the code.
Most importantly you need to fix the ContactList class. It is inserting new elements into the last index, and deleting at any location using the name.
For example, let's say the ContactList has three elements in it at 0, 1 and 2 indexes. So numContacts is set to 3.
Now ContactList has elements as:
[0]C0, [1]C1, [2]C2, [3]null, ...
Then if the contact at 0 index is deleted (set to null), then numContacts is set to 2.
Now the ContactList has elements as:
[0]null, [1]C1, [2]C2, [3] null, ...
A new insert will be added to the index 2, and it will override the C2 value.
Simplest solution is to use an ArrayList instead of an array.
As others have mentioned there are few more issues to fix, but above is the most important in my opinion.
There are many issues with your code so not easy to say where to begin.
First: Your public void deleteContact(String name)-method is broken. It compares Strings using == instead of equals(). And worse: It creates null pointers mid in your array which will cause problems in your writer()-method.
Second: Why do you use arrays? You should use java.util.ArrayList which offers out-of-the-box implementations for adding, getting and deleting contacts.
Third: If you are missing your text file, you might have overlooked it because of missing path so you don't know where to look for this file. So please add a full path to file name.
Fourth: I would also use scanner.hasNextLine() instead of scanner.hasNext() if you then call scanner.nextLine().
Since you said you are not allowed to use ArrayList you should study its source code especially for removing elements. It does not only nullify the array bucket, but also to shift all following elements one index backwards so you don't have any null gap until the index given by element count. And two breaks in deleteContact()-method are really not necessary.