I'm creating a scheduling and registration system for a class project. I'm required to be able to add and delete rooms and courses. Each course can only last an hour and may not happen at the same time as another course in the same room. I'm able to delete the course itself, but I'm having trouble deleting the time associated with that course.
What I've done is create an ArrayList of Rooms with each room being able to hold an ArrayList of Courses. Each of these courses has a specific hour which is checked if it's in use using an ArrayList of times. I was able to add the courses hour to the list and halt the user from creating another course with the exact time slot in the same room. However, whenever I remove the course I'm trying to remove the time as well so that another course that's created may use that time slot. Problem is, the time slot gets filled and stays filled even after removing the course and I'm not sure why.
Some guidelines:
Rooms can be added and deleted by the user. (To delete a room, no course should be scheduled in this room).
All courses can be deleted by the user.
The user can create courses by specifying a room number and the participants.
A room cannot hold more than one course at any one-hour slot.
To be honest I've been working for around 7 hours straight and I'm not to confident in my code, if I'm even doing things right, or even what I'm talking about really. I apologize if I'm not being specific enough or making any sense, please let me know if something needs clarification. If you have any other tips/pointers or see any other mistakes please let me know. Thanks in advance.
Course.java
package Schedule;
import java.util.ArrayList;
public class Course extends Room {
private String name;
private int roomNum, hour, students;
private static ArrayList < Course > courseList = new ArrayList < > ();
private static ArrayList < Integer > times = new ArrayList < > (24);
public Course() {}
public Course(String name, int hour, int roomNum, int students) { //Constructor
this.name = name;
if (hour > 7 && hour < 18) {
this.hour = hour;
} else {
System.out.println("Not a valid time slot. Time set to 6:00PM/1800 HOURS. ");
this.hour = 18;
}
this.students = students;
this.roomNum = roomNum;
boolean inUse = checkTime(hour, roomNum);
if (inUse == false) {
times.add(hour);
Room.addCourse(roomNum, this);
courseList.add(this);
}
}
public static void deleteCourse(int courseNum, int roomNum) {
boolean pass;
pass = Room.removeCourse(courseNum, roomNum);
if (pass == true) {
times.remove(courseNum);
courseList.remove(courseNum);
System.out.println("Course Removed ");
}
}
public static boolean checkTime(int hour, int roomNum) {
boolean exist = false;
for (int i = 0; i < courseList.size(); i++) {
if (courseList.get(i).hour == hour && courseList.get(i).roomNum == roomNum) {
exist = true;
System.out.println("Time already in use, course could not be added. ");
}
}
return exist;
}
}
Room.java
package Schedule;
import java.util.ArrayList;
public class Room {
private int number, numOfClasses;
private static int numOfRooms = 1000;
private static ArrayList < Room > roomList = new ArrayList < > ();
private ArrayList < Course > courseList = new ArrayList < > ();
public Room() {}
public Room(int number, int numOfClasses) { //Constructor
this.number = number;
this.numOfClasses = numOfClasses;
if (roomList.size() < numOfRooms) {
roomList.add(this);
System.out.println("Room added");
} else {
System.out.println("Room couldn't be added, not enough rooms available.");
}
}
public static void numOfRooms(int r) {
numOfRooms = r;
}
public static void deleteRoom(int roomNum) { //Delete room
boolean exist = false;
for (int i = 0; i < roomList.size(); i++) {
if (roomList.get(i).getRoomNum() == roomNum) {
if (roomList.get(i).courseList.size() > 0) {
System.out.printf("%s%d%s%n", "Cannot delete room ", roomNum, " " + "There is currently a course in the room. ");
} else {
roomList.remove(i);
System.out.printf("%s%d%s%n", "Room ", roomNum, " Deleted");
}
exist = true;
}
}
if (exist == false) {
System.out.printf("%s%d%s%n", "Room ", roomNum, " does not exist, could not delete.");
}
}
public int getRoomNum() {
return number;
}
public static ArrayList < Room > getRoomList() {
return roomList;
}
public static void addCourse(int roomNum, Course c) { //Add Course to room.
boolean empty = true;
for (int i = 0; i < roomList.size(); i++) {
if (roomList.get(i).getRoomNum() == roomNum) {
roomList.get(i).courseList.add(c);
System.out.printf("%s%d%n", "Course added to room ", roomNum);
empty = false;
}
}
if (empty == true) {
System.out.println("No rooms with that room number. ");
}
}
public static boolean removeCourse(int courseNum, int roomNum) {
boolean exist = false;
try {
for (int i = 0; i < roomList.size(); i++) {
if (roomList.get(i).getRoomNum() == roomNum) {
roomList.get(i).courseList.remove(courseNum);
exist = true;
}
}
if (exist == false) {
System.out.println("Could not find course to delete. ");
}
} catch (IndexOutOfBoundsException e) {
System.out.println("Error: Could not find a room or course to delete. ");
}
return exist;
}
}
ScheduleDemo.java
//For adding rooms, create a room object and input the room number and number of courses.
//For adding courses, create a course object and input the Name, hour1, room number, and # of students.
//For Deleting rooms, type Room.deleteRoom("room number").
//For Deleting Courses, type Course.deleteCourse("Course number", "Room Number").
package Schedule;
public class ScheduleDemo {
public static void main(String[] args) {
Room.numOfRooms(100);
Room room0 = new Room(0, 1);
Room room1 = new Room(3, 1);
Room room2 = new Room(99, 1);
Course course0 = new Course("Course", 9, 3, 10);
Course course1 = new Course("Course2", 9, 99, 12);
Course.deleteCourse(0, 99);
Course course2 = new Course("Help", 9, 99, 122);
Room.deleteRoom(56);
Room.deleteRoom(99);
Course.deleteCourse(1, 99);
}
}
Output:
Room added
Room added
Room added
Course added to room 3
Course added to room 99
Course Removed
Time already in use, course could not be added.
Room 56 does not exist, could not delete.
Room 99 Deleted
Could not find course to delete.
BUILD SUCCESSFUL (total time: 0 seconds)
UPDATE:
I managed to fix the issues by removing course and room number completely and instead passed the name of the course. Since I was passing in the index (courseNum) of each course, I ended up deleting the wrong course which is why my times didn't delete properly. By searching the name of the course in both my Course list and my room course list, I was able to accurately delete the right course from both list. Here's what I fixed.
Main
Course course1 = new Course("Course2", 9, 99, 12); //Creates Course2 and time slot
Course.deleteCourse("Course2"); //Deletes Course2 and time slot
Course course2 = new Course("Help", 9, 99, 122); //Adds course Help into same hour
/*
New Output
Course added to room 99
Course Removed
Course added to room 99
*/
Course
public static void deleteCourse(String name) {
boolean pass;
pass = Room.removeCourse(name);
if (pass == true) {
for (int i = 0; i < courseList.size(); i++) {
if (courseList.get(i).getName().equals(name)) {
times.clear();
courseList.remove(i);
System.out.println("Course Removed ");
}
}
}
}
public String getName() {
return name;
}
Room
public static boolean removeCourse(String name) {
boolean exist = false;
try {
for (int j = 0; j < roomList.size(); j++) {
for (int i = 0; i < roomList.get(j).courseList.size(); i++) {
if (roomList.get(j).courseList.get(i).getName().equals(name)) {
roomList.get(j).courseList.remove(i);
exist = true;
}
}
}
if (exist == false) {
System.out.println("Could not find course to delete. ");
}
} catch (IndexOutOfBoundsException e) {
System.out.println("Could not find a room or course to delete. ");
}
return exist;
}
Now I can move forward to other things. Thanks!
I think the main issue is you are deleting the CourseList using index. And I think you are assuming that RoomNum 99 is associated with course Num 0. In fact there is no concept of course number in your application. By default it becomes the index of the List.
private static ArrayList < Course > courseList = new ArrayList < > ();
courseList.add(object of type Course);
courseList.remove(courseNum); // Note course Num becomes an index here
So this removes the wrong entry. Course2 which is in Room number 99 still remains in the list thereby saying that the course is still running.
EDIT: This design is very confusing and will not work if you have to remember the relationship between course number and the course name. You have not modeled the relationship anywhere in your design.
When you declare something static it makes the member belong to the class instead of belonging to the instance. Therefore, let's look at your ArrayLists content when you're running the program.
Room room0 = new Room(0, 1);
Room room1 = new Room(3, 1);
Room room2 = new Room(99, 1);
Course course0 = new Course("Course", 9, 3, 10);
// courseList : {course0} | hours : {9}
Course course1 = new Course("Course2", 9, 99, 12);
// courseList : {course0,course1} | hours : {9,9}
Course.deleteCourse(0, 99);
// courseList : {course1} | hours : {9}
Since your Arraylist is static, your deleteCourse method doesn't delete the course 0 of the room 99. It removes the course1 from your Room courseList but not from the staticarray list !
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'm having a problem making an efficient algorithm that validates my date and odometer input within a given sorted data set. I'm trying to implement a gas mileage tracking program. The sorted data has a date with corresponding odometer value.
Sample Data Set:
Date Odometer Index
2021-2-14 156830 0
2021-2-5 156572 1
2021-2-4 156255 2
Index 0 being the top and recent data entry.
Sample Input:
Date: 2021-2-15
Odometer: 157000
I have to determine which position/order the inputted date belongs inside my data set. Since the user date input is greater than my top/recent date I know this belongs to the very top. Then I compare the odometer from that data to my input. If user odometer input is greater than data odometer then it is valid. If its less than then its invalid.
Another Sample Input:
Date: 2021-2-14
Odometer: 156255
Its okay if the user date input has the same date given in the data set. However, odometer cannot be less than the previously recorded at 156572 on 2021-2-5. So its invalid.
Here is my test input validation algorithm so far:
public static Date[] dates = new Date[3];
public static int[] odometer = new int[3];
public static void main(String[] args)
{
dates[0] = new Date(2021,2,14);
dates[1] = new Date(2021,2,5);
dates[2] = new Date(2021,2,4);
odometer[0] = 156830;
odometer[1] = 156572;
odometer[2] = 156255;
//Inputs
Date inputDate = new Date(2021,2,14);
int inputOdo = 156255;
if(!hasDuplicate(inputDate, inputOdo))//Checks for duplicate
{
int index = -1;
for(int i=0; i<dates.length; i++)
{
if(inputDate.compareTo(dates[i]) >= 0)
{
index = i;
break;
}
}
if(index == 0)
{
if(inputOdo <= odometer[index] && inputDate.compareTo(dates[index]) > 0)
{
System.out.println("Mileage cannot be less than "
+ "your previously recorded fill-up at\n"+odometer[index]+" miles on "+dates[index].toString()+".\n");
}
}else{
if(index > 0)
{
int top = index-1;
int bottom = index;
if(inputOdo >= odometer[top])
{
System.out.println("Mileage cannot be higher than "
+ "your previously recorded fill-up at\n"+odometer[top]+" miles on "+dates[top].toString()+".\n");
}else{
if(inputOdo <= odometer[bottom] && bottom != dates.length-1 && !inputDate.equals(dates[bottom]))
{
System.out.println("Mileage cannot be less than "
+ "your previously recorded fill-up at\n"+odometer[bottom]+" miles on "+dates[bottom].toString()+".\n");
}
}
}else{
int bottom = dates.length-1;
if(inputOdo >= odometer[bottom])
{
System.out.println("Mileage cannot be higher than "
+ "your previously recorded fill-up at\n"+odometer[bottom]+" miles on "+dates[bottom].toString()+".\n");
}
}
}
System.out.println("Gas has been added!");
}else{
System.out.println("Another fill-up with this date and mileage already exist.");
}
hasDuplicate method:
//Checks for duplicate
public static boolean hasDuplicate(Date date, int odo)
{
boolean duplicate = false; //Initialize duplicate variable
//Checks if date and mileage exist already
for(int i=0; i<dates.length; i++)
{
if(date.equals(dates[i]) && odo == odometer[i]) {
return true;
}
}
return duplicate;
}
I hope someone can understand what I am trying to achieve here. Any help and idea will be great! I'm a newbie.
Some changes which you may do-
Instead of having different array of data and odometer, use an object which implements Comparable interface
class MileageData implements Comparable<MileageData> {
LocalDate date;
int odometer;
public MileageData(LocalDate date, int odometer) {
this.date = date;
this.odometer = odometer;
}
#Override
public boolean equals(final Object obj) {
MileageData anotherData = (MileageData)obj;
return anotherData.date.equals(this.date) && anotherData.odometer == this.odometer;
}
#Override
public int hashCode(){
int hash = 7;
hash = 31 * hash + this.date.hashCode();
hash = 31 * hash + this.odometer;
return hash;
}
#Override
public int compareTo(final MileageData o) {
if (o.date.isBefore(this.date)) {
return -1;
} else if (o.date.isAfter(this.date)) {
return 1;
} else {
return 0;
}
}
#Override
public String toString(){
return this.date.toString()+" "+this.odometer;
}
}
Storing MileageData in Treeset which will sort data in the order given in compareTo method of MileageData.
Set<MileageData> data = new TreeSet<>();
data.add(new MileageData(LocalDate.of(2021,2,14),156830));
data.add(new MileageData(LocalDate.of(2021,2,4),156255));
data.add(new MileageData(LocalDate.of(2021,2,4),156255));
data.add(new MileageData(LocalDate.of(2021,2,5),156572));
As Treeset will not store duplicate data, you don't need separate check for duplicates. Above set will return only three objects instead of four.
I'm having a little trouble with a fairly simple assignment, but couldn't find an answer here that seemed to work.
I need to have a 2D ArrayList that contains staff data, and then be able to run a separate function that allows the user to input a staff member's name, searches the ArrayList for that name, and if it exists, display the full row of data.
Here's what I've got so far:
The ArrayList
List<List<String>> staffArrayString = new ArrayList<>();
staffArrayString.add(Arrays.asList("Steven George", "12 York Road", "07123456678", "Permanent", "York", "27000/yr"));
staffArrayString.add(Arrays.asList("Rina Veyer", "20 Leeds Road", "08987987765", "Part Time", "Leeds", "10/hr"));
staffArrayString.add(Arrays.asList("Brian Lym", "13 Bradford Road", "07123234345", "Permanent", "Bradford", "27000/yr"));
The search function
public void staffNameSearch() {
System.out.println("Enter name of staff member:");
String staffName = in.next();
boolean found = false;
int row = 0;
for (int i = 0; i < staffArrayString.size(); i++) {
for (int j = 0; j < staffArrayString.get(i).size(); j++) {
if (staffArrayString.get(i).get(j).equals(staffName)) {
row = staffArrayString.get(i).size();
found = true;
}
}
}
if (found = true) {
System.out.print(staffArrayString.get(row) + " ");
}
}
I'm currently getting an output of 'Exception in thread "main" java.lang.IndexOutOfBoundsException' at the print line on the end there, but I can't for the life of me work out why. I'd appreciate any advice on this (especially if it's some obvious and stupid mistake on my part!).
The error is occuring because you are setting row to something unrelated to the row counter. When you discover the row (variable i) which has the name in the jth element, set row=i.
Be careful about if (found = true) - it is incorrect; prefer:
a) if (found)
b) if (found == true)
For efficiency, include && !found in the for loops so they exit as soon as you find something.
You can use for each loop for simpler.
System.out.println("Enter name of staff member:");
String staffName = in.next();
boolean found = false;
String[] foundArray;
for(String[] staffArray: staffArrayString){
for(String str : staffArray){
if(str.equals(staffName)){
foundArray = staffArray;
found = true;
break;
}
}
}
if (found == true) {
System.out.print(foundArray + " ");
}
You might be able to simplify the code a little bit by using a Map and a Staff class.
For example, the Staff class
public class Staff{
String name;
String address;
String id; // ?
boolean permanent; // Or a enum if there are more than 2 values
String city; // ?
int payrate;
boolean hourly;
#Override
public String toString(){ // Easily convert the class to a String
return String.format("%s %s %s %s %s $%d/%s",
name,
address,
id,
permanent ? "Permanent" : "Part-time",
city,
payrate,
hourly ? "hr" : "yr");
}
}
And for the code to read it
private Map<String, Staff> staffDirectory; // String is the name in lowercase
public void staffNameSearch() {
// Code
if(staffDirectory.containsKey(staffName)){ // Make sure staffName is lowercase
System.out.print(staffDirectory.get(staffName) + " ");
} else {
System.out.println("Name not found");
}
}
This way you can avoid using loops and get O(1) efficiency.
I am trying to write a program that mimics the actions of a vending machine for my CS class. I have a double array stock that represents the the number of items at a particular "slot" [my vending machine is weird and is kinda like one long vending machine with 1 column of different items]. Here is my code so far:
public class VendingMachine
{
// define fields here
public static double itemPrice[];
public static String[] itemName;
public static int stock[][];
public static int maxPerSlot;
public static double cashAmmount;
public VendingMachine(int numslots, int maxperslot, double cash)
{
final int numSlots = numslots;
maxPerSlot = maxperslot;
cashAmmount = cash;
stock = new int[numSlots][1];
itemPrice = new double[numSlots];
itemName = new String[numSlots];
// complete this method
}
public void setProduct(int slot, String product, double price)
{ int Slot = slot;
itemPrice[Slot] = price;
itemName[Slot] = product;
stock[Slot][0] = 0;
//
}
public void restockProduct(String product, int quantity)
{
String Product = product;
int Quantity = quantity;
for(int i = 0; i < itemName.length;i++){
if (Quantity > (maxPerSlot-stock[i][0])){
return;
}
if (Product.equals(itemName[i])&&Quantity < maxPerSlot){
stock[i][0] += Quantity;
}else if ((maxPerSlot-stock[i][0])==0){
continue;
}
}
//Put # of products in slot that holds it and if that slot is full put the rest in the next
//available slot that holds that product, if all full return error.
}
public double getCashOnHand()
{
return cashAmmount; // replace this line with your code
}
public int getQuantity(int slot)
{
return stock[slot][0]; // replace this line with your code
}
public int getQuantity(String product)
{ int total = 0;
for (int i = 0; i<itemName.length;i++){
if (product == itemName[i]){
total += this.getQuantity(i);
}
}
return total;
}
public boolean buyItem(int slot)
{ int snum = slot;
double price = 0;
if (stock[snum][0] != 0){
stock[snum][0]--;
price= itemPrice[snum];
cashAmmount += price;
return true;
} else {
return false;}
// replace this line with your code
}
}
and the main method that runs it:
public class vmd
{
public static void main(String[] args)
{
boolean success;
// vending machine w/ 20 slots, 10 items maximum per slot, $5 cash on hand
VendingMachine v = new VendingMachine(20, 10, 5.00);
v.setProduct(0, "Cheesy Poofs", 0.75);
v.setProduct(1, "Red Bull", 1.25);
v.setProduct(2, "Cheesy Poofs", 0.75);
v.restockProduct("Cheesy Poofs", 8);
v.restockProduct("Red Bull", 7);
v.restockProduct("Cheesy Poofs", 5); // 2 more go into slot 0, remaining 3 into slot 2
success = v.buyItem(0);
System.out.println(success); // should print "true"
System.out.println(v.getCashOnHand()); // should print "5.75"
System.out.println(v.getQuantity(2));// should print "9"
System.out.println(v.getQuantity("Cheesy Poofs")); // should print "12"
}
}
When I run this thought I consistently get:
true
5.75
8
15
as my out put when I am suppose to get:
true
5.75
9
12
as my output. Why is this? I am assuming it has something to do with the restockProduct() method but I can't seem to narrow it down and its really getting on my nerves. According to my CS teacher the restockProduct() method is suppose to add the given quantity of the specified product to the vending machine and Put as many of the items as possible into the first slot that has been designated to hold that particular kind of product (using setProduct()).
If not all of the items will fit into the first slot, put as many of the rest as possible into the second slot that holds that kind of product, etc. For partial credit, your method should at least be able to find the first slot designated for the specified product and put all of the items there".
You are right, restockProducts doesn't do what you want it to. Here's what you have:
public void restockProduct(String product, int quantity)
{
String Product = product;
int Quantity = quantity;
for(int i = 0; i < itemName.length;i++){
if (Quantity > (maxPerSlot-stock[i][0])){
return;
}
if (Product.equals(itemName[i])&&Quantity < maxPerSlot){
stock[i][0] += Quantity;
}else if ((maxPerSlot-stock[i][0])==0){
continue;
}
}
So when you restock "Cheesy Poofs", the first time, here's what happens:
On loop 0, you are Cheesy Poofs, so you put 8 items in there.
On loop 1, you have the wrong type, so nothing goes there
On loop 2, you have Cheesy Poofs, so you put 8 there.
Somehow, you need to remember that you've put 8 in the first slot. Also, you need to have a mechanism to put some into one slot, and some into another, right now I don't see that being possible in your code.
you have several problems in your restockProduct described by others, anyway you can change you restockProduct function to this one:
public void restockProduct(final String product, int quantity)
{
for (int i = 0; i < itemName.length; i++)
{
if ( (product.equals(itemName[i]) || "".equals(product) ) && (maxPerSlot - stock[i][0]) > 0)
{
stock[i][0] += quantity;
if (stock[i][0] > maxPerSlot)
{
quantity = stock[i][0] - maxPerSlot;
stock[i][0] = maxPerSlot;
}
else
return;
}
}
if (quantity > 0)
throw new IllegalArgumentException("Cannot stock product");
}
NOTE: we're either inserting product to slot where product already is OR where no products at all
NOTE2: after inserting we're checking is there any rest we should insert further or everything is here
Your problem is here:
for(int i = 0; i < itemName.length;i++){
if (Quantity > (maxPerSlot-stock[i][0])){
return;
}
Your first call to restock "Cheesy Poofs"
v.restockProduct("Cheesy Poofs", 8);
puts 8 items into the machine.
Your second call to restock cheesy poofs:
v.restockProduct("Cheesy Poofs", 5);
Fails to do anything. Your if statement says that if the quantity (5) is greater than maxPerSlot - current stock which is (10 - 8) or just 2, then return.
5 is greater than 2 so the method ends and nothing is added to your machine.
Additionally you need to put some sort of control in there to break out of the loop once you've added all 8 items to the machine. As it stands you're adding 8 cheesy poofs to two different slots. Once you add the 8 to the first Cheesy Poof row you should remove 8 from what you have left to stock.
I took the liberty of reconstructing that method and this is what I think you're trying to achieve:
public void restockProduct(String product, int quantity)
{
String Product = product;
int Quantity = quantity;
for(int i = 0; i < itemName.length;i++){
if (Product.equals(itemName[i])){
if (Quantity > (maxPerSlot-stock[i][0])){
Quantity -= maxPerSlot-stock[i][0];
stock[i][0] += maxPerSlot-stock[i][0];
}
if (Quantity <= (maxPerSlot-stock[i][0])){
stock[i][0] += Quantity;
return;
}
}
}
}
I have a 1,000,000 user list with different ages, and I want to perform a search in Java that will output just the number of people in the group based on their age range.
For example:
Age Group Age Range
1 6 years old or younger
2 7 to 18 years old
3 19 to 26 years old
4 27 to 49 years old
5 50 to 64 years old
6 65 to 79 years old
7 80 years old or older
I want my output to display the number of people that falls within the age group if I enter a particular age group. That is:
If I enter 1
The output should be:
**** users found (total number of users that falls within the
age range 6 years old or younger)
Any kind of data structure is perfectly OK.
This is what I've done so far:
/**
A template used to read data lines into java.util.ArrayList data structure.
Input file: pjData.csv
Input file must be saved under the same directory/folder as the program.
Each line contains 5 fields, separated by commas. For example,
959695171, 64, AZ, M, 1
355480298, 101, TN, F, 1
**/
import java.io.*;
import java.util.*;
public class pj3Template2
{
public static void main(String args[])
{
String line;
String id, s, g;
Integer a, sa;
StringTokenizer st;
HealthDS2 records = new HealthDS2();
try {
FileReader f = new FileReader("pjData.csv");
BufferedReader in = new BufferedReader(f);
while ((line = in.readLine()) != null)
{
st = new StringTokenizer(line, ",");
id = st.nextToken(",").trim();
a = Integer.valueOf(st.nextToken(",").trim());
s = st.nextToken(",").trim().toUpperCase();
g = st.nextToken(",").trim().toUpperCase();
sa = Integer.valueOf(st.nextToken().trim());
records.add(new HealthRec2(id, a, s, g, sa));
} // loop until the end of file
in.close();
f.close();
}
catch (Exception e) { e.printStackTrace(); };
System.out.println(records.getSize() + " records processed.");
// Search by age
System.out.print("Enter 1-character age abbreviation to search: ");
String ui;
Scanner input = new Scanner(System.in);
ui = input.next().trim();
System.out.println("Searching all records in: " + ui);
ArrayList <HealthRec2> al = records.searchByAge(Integer.valueOf(ui.trim()));
System.out.println(al.size() + " records found.");
}
}
/**
Data class Sample records:
5501986, 31, WV, F, 1
1539057187, 5, UT, M, 2
**/
class HealthRec2
{
String ID;
Integer age;
String state;
String gender;
int status;
public HealthRec2() { }
public HealthRec2(String i, Integer a, String s, String g, int sa)
{ ID = i; age = a; state = s; gender = g; status = sa; }
// Reader methods
public String getID() { return ID; }
public Integer getAge() { return age; }
public String getState() { return state; }
public String getGender() { return gender; }
public int getStatus() { return status; }
// Writer methods
public void setAge(Integer a) { age = a; }
public void setState(String s) { state = s; }
public void setGender(String g) { gender = g; }
public void setStatus(int sa) { status = sa; }
public String toString()
{ return ID + " " + age + " " + state + " " + gender + " " + status; }
} // HealthRec
// Data structure used to implement the requirement
// This implementation uses java.util.ArrayList
class HealthDS2
{
ArrayList <HealthRec2> rec;
public HealthDS2()
{ rec = new ArrayList <HealthRec2>(); }
public HealthDS2(HealthRec2 r)
{
rec = new ArrayList <HealthRec2>();
rec.add(r);
}
public int getSize() { return rec.size(); }
public void add(HealthRec2 r) { rec.add(r); }
// Search by age
// No data validation is needed -- assuming the 1-character age is valid
// Returns an ArrayList of records
public ArrayList <HealthRec2> searchByAge(Integer a)
{
ArrayList <HealthRec2> temp = new ArrayList <HealthRec2>();
for (int k=0; k < rec.size(); ++k)
{
if (rec.get(k).getAge().equals(a))
temp.add(rec.get(k));
}
return temp;
} // searchByAge
} // HealthDS
My goal is to search based on state, status, gender and age group. I've done that for the others, but I'm just having a little problem with the age group since it is grouped rather than just searching for a particular age in the data file. I tried creating seven arraylists for each group but I am still having a little problem switching between groups.
This code does:
get min and max ages for the selected group
iterate through the ages and increments a counter for any age within the min/max
prints out the results
For very large datasets you'll need to use better data-structures like #kyticka mentions.
public static void main (String[] args) throws java.lang.Exception
{
int[] groupMin = new int[]{0, 10, 20};
int[] groupMax = new int[]{10, 20, 9999};
int[] ages = new int[]{ 1, 2, 3, 10, 12, 76, 56, 89 };
int targetGroup = 1;
int count = 0;
for( int age : ages ){
if( age >= groupMin[targetGroup] && age < groupMax[targetGroup] ){
count++;
}
}
System.out.println("Group " + targetGroup + " range is " +
groupMin[targetGroup] + " - " + groupMax[targetGroup]);
System.out.println("Count: " + count);
}
You can play with it here: http://ideone.com/DAWGYX
You can use some way to initialize your 1000000 users or even below code will generate random age for Users:
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class UserListDemo {
int age;
class Users{
int age=0;
public Users(int a)
{
age=a;
}
public void setAge(int age)
{
this.age=age;
}
public int getAge()
{
return this.age;
}
}
public static void main(String a[])
{
UserListDemo uld=new UserListDemo();
ArrayList<Users> data=new ArrayList<Users>();
uld.initializeUsers(data);
System.out.println("Enter age group choice");
System.out.println("Enter 1 for age group 1-6");
System.out.println("Enter 2 for age group 7-18");
System.out.println("Enter 3 for age group 19-26");
System.out.println("Enter 4 for age group 27-49");
System.out.println("Enter 5 for age group 50-64");
System.out.println("Enter 6 for age group 65-79");
System.out.println("Enter 7 for age group 80-Older");
Scanner sc=new Scanner(System.in);
String choice=sc.nextLine();
int ch=Integer.valueOf(choice);
long result=0;
switch(ch)
{
case 1:
for(Users us:data)
{
if(us.age<=6)
result++;
}
case 2:
for(Users us:data)
{
if( us.age>=7 && us.age<=18 )
result++;
}
case 3:
for(Users us:data)
{
if( us.age>=19 && us.age<=26 )
result++;
}
case 4:
for(Users us:data)
{
if( us.age>=27 && us.age<=49 )
result++;
}
case 5:
for(Users us:data)
{
if( us.age>=50 && us.age<=64 )
result++;
}
case 6:
for(Users us:data)
{
if( us.age>=65 && us.age<=79 )
result++;
}
case 7:
for(Users us:data)
{
if( us.age>=80)
result++;
}
}
System.out.println("For the entered age group :"+ch+" ::"+result+" user has been found");
}
public void initializeUsers(ArrayList<Users> data)
{
Users us;
Random rand=new Random();
for(long l=0;l<1000000L;l++)
{
us=new Users(rand.nextInt(100));
data.add(us);
}
}
}
The efficient answer, with 1M records, would be to use several Maps as indices, or even an actual database. However, since the exercise explicitly mentions ArrayLists, you are probably still learning the basics, so I will stick to those.
First, you need to be able to retrieve the group for a given person. You can do that in two ways.
Option A is to add the group as a field at initialization time
// within HealthRec2
int group; // stores group number as an attribute
private static final int[] ageGroups = // age limits for each group
new int[]{6, 18, 26, 49, 64, 79};
private void updateGroup() { // <-- called from constructor and from setAge()
int currentGroup = 0;
for (int limit : ageGroups) {
currentGroup ++; // advance to next group
if (age <= limit) break; // stop looking at limits once we reach one
}
group = currentGroup;
}
private int getGroup() { return group; }
Option B is to calculate it on-the-fly for each record, instead of storing it as an attribute:
// within HealthRec2
private static final int[] ageGroups = // age limits for each group
new int[]{6, 18, 26, 49, 64, 79};
public int getGroup() {
int currentGroup = 0;
for (int limit : ageGroups) {
currentGroup ++; // advance to next group
if (age <= limit) break; // stop looking at limits once we reach one
}
return currentGroup;
}
With either option, you could now have very similar logic to look up people in a given age group as you have to look up records from a given state or with a given gender.
Option A is more expensive up-front, because even if you do not need the age group, you still have to calculate it and store it in an attribute, just in case. Option B is more expensive if you need to call getGroup several times for the same record - as option A's getGroup is a lot faster.
Idea one: sort and use binary search http://en.wikipedia.org/wiki/Binary_search
Idea two: use interval tree http://en.wikipedia.org/wiki/Interval_tree