I need help making Lowest price grocery program in Java - java

My code below
import java.util.*;
import java.io.*;
public class main {
public int finalcost;
public static void main(String[] args) throws FileNotFoundException, IOException {
Scanner input = new Scanner(System.in);
int totalAdd = 0;
boolean done = false;
// to store specific properties ex item size and price
HashMap<String, String> specificPropsMap = new HashMap<String, String>();
// stores an array list of all the sizes and price
ArrayList<HashMap<String, String>> propsList = new ArrayList<HashMap<String, String>>();
// the item list stores the name of the item as the KEY and item size and price
// as data
HashMap<String, ArrayList<HashMap<String, String>>> itemsMap = new HashMap<String, ArrayList<HashMap<String, String>>>();
// this stores the service name than the cost.this is the one we will be adding
// too after getting the data;
HashMap<String, Integer> cartMap = new HashMap<String, Integer>();
BufferedReader br = new BufferedReader(new FileReader("PA2.txt"));
String line = br.readLine();
while ((line = br.readLine()) != null) {
// stores the data base on commas
String[] fields = line.split(",");
String serviceName = fields[0];
String fileName = fields[1];
String cost = fields[2];
if (specificPropsMap.containsKey(serviceName)) {
// do nothing
} else {
specificPropsMap.put(serviceName, null);
}
// gets the file name from the first reader
BufferedReader brCVS = new BufferedReader(new FileReader(fileName));
String lineCVS = brCVS.readLine();
while ((lineCVS = brCVS.readLine()) != null) {
String[] cvsFields = lineCVS.split(",");
String brandName = cvsFields[0];
String nameItem = cvsFields[1];
String itemSize = cvsFields[2];
String itemPrice = cvsFields[3];
// check if itemname is in specificPropsMap
if (specificPropsMap.containsKey(cvsFields[1])) {
// do nothing
} else {
specificPropsMap.put(itemSize, nameItem);
}
propsList.add(specificPropsMap);
if (itemsMap.containsKey(nameItem)) {
// do nothing
} else {
itemsMap.put(nameItem, null);
}
} // end inner while loop
int stringCosttoInt = Integer.parseInt(cost.trim());
if (cartMap.containsKey(serviceName)) {
// do nothing
} else {
cartMap.put(serviceName, stringCosttoInt);
}
} // end outer while loop
System.out.println("Welcome to Assisgnment two app");
while (done == false) {
System.out.println("Enter the item you are looking for or enter done check out: ");
String key = input.nextLine(); // use key to find if item is in the itemsMap;
if (key == "done") {
done = true;
} else {
if (itemsMap.containsKey(key)) {
System.out.println("Enter the Size you want :");
// now check for the item name, than size, if not return item not there;
int sizeKey = input.nextInt(); // use key to find item in the area
if (itemsMap.containsValue(specificPropsMap.containsKey(sizeKey))) {
System.out.println("How many of " + key + " do you want:");
int numOfProduct = input.nextInt();
// add it to the cart;
} else {
System.out.println("No: " + sizeKey + " in the system");
}
} else {
System.out.println("No item by the name of: " + key + " in the system");
}
}
}
br.close();
input.close();
}
}
Question: How do I set the user input to search the item class to return the lowest total cost. The user enters item name, size and the amount. I know in storing the name in item, but I don't know how to match it with user input or how to get that data if that makes sense.2nd in also little confused when I read the file and i'm storing it as a String, I don't know how to make it into an int so I can do math with it..

Just to give you some help with the approach, I won't be going into detail about parsing, I think you got that covered.
Look at it from another perspective, from the input. What is the flow of the program?
User enters required item and size
Look if item is present
User enters quantity
Add to cart
Repeat
When 'done', check which Service offers lowest total price
Note: Assuming an item present in one Brand is present in all
So let's devise a Data Structure that can support this:
We need to maintain a Cart for each Service. In the end, we can cycle through each cart and return the lowest.
Maintain a Map<String, Integer> where String is the Service, and Integer is the total price
Whenever an Item is added by the user, add the price of that Item to each respective Service
Eg. If Lays is added, add price of Lays in Prime to total price of Prime, price of Lays in InstaCart to total price of InstaCart, etc
First thing you need to look up is if the Item is present; we can store it in a Map, say itemsMap.
What specific properties does each item have? There's service, brand, size, price. We can store it in another Map, say specificPropsMap.
Each Item can have multiple specific properties. i.e., There can be different combination of size, service, etc. for the same Item. So each Item needs to store multiple specific properties, which can be a List, say propsList.
To understand the above:
//Starting from the bottom-up
//To store specific properties
//Contains key-value pairs like: service = Amazon, brand = Nestle, size = 10g, price = 2
HashMap<String, String> specificPropsMap; //Has one set of specific props
//Consider an Item; it can have multiple specific properties, which we'll store as a List
//Eg: For Item = 'dark chocolate'
//specificProps1: service = Amazon, brand = Nestle, size = 10, price = 2
//specificProps1: service = InstaCart, brand = Cadbury, size = 10, price = 3
//Required: List<specificPropsMap>
ArrayList<HashMap<String, String>> propsList; //Has a list of specificPropsMaps for one item
//Now we need to store all Items; it can be a Map
//Required: Map<ItemName, propsList for that Item>
HashMap<String, ArrayList<HashMap<String, String>>> itemsMap;
//Initialize cart Map while parsing services
HashMap<String, Integer> cartMap; //Has initial values "Amazon" = 0, InstaCart = 0
//To find if an Item is present:
itemsMap.contains("Dark chocolate");
//Find prices from each service for that Item and size, and quantity
int reqSize = 10; //Assume req. size = 10
int reqQuantity = 5;
ArrayList<HashMap<String, String>> propsList = itemsMap.get("Dark chocolate")
for (HashMap<String, String> specificPropsMap : propsList) { //For each set of props
int size = Integer.parseInt(specificPropsMap.get("size"));
if (size == reqSize) {
String service = specificPropsMap.get("service"); //Say Amazon
int price = Integer.parseInt(specificPropsMap.get("price")); //Say 2
int initialPriceInCart = cartMap.get(service); //Initially 0
int finalPriceInCart = initialPriceInCart + price * reqQuantity;
cartMap.put(service, finalPriceInCart); //Cart price updated
}
}
//Find lowest priced service
String lowestPrice = Integer.MAX_VALUE; //Initially set as high as possible
String lowestService = "";
for (String key : cartMap.keySet()) {
if (cartMap.get(key) < lowestPrice) {
lowestPrice = cartMap.get(key);
lowestService = key;
}
}
General pointers that I can think of:
Population: Populate all these values initially while reading from the files.
Conversion : Convert values such as size, price to a standard (kg, cents/dollars, etc)
Naming : It's better to keep it descriptive (brand or brandName instead of bName)
Error handling : Add checks/try-catch blocks wherever necessary
Edit: Added steps. Might look a bit complex since we have some entries in the txt and some in the csv, but it's actually easy:
Read txt file; you now have a service and a csv file. Thus, for each service(outer loop)
Add the service as a key to cartMap if it's not already present
Create a new specificPropsMap, add service to this
Read the csv corresponding to that service. For each item(inner loop)
Store all props in the same specificPropsMap
You now have the prop item from the csv
Check if item is present in itemsMap
If present, skip to next step. If not, add item to the itemsMap as a key, with an empty List as value
Do itemsMap.get(item), you'll have the propsList
Add specificPropsMap to the propsList
Repeat for all items and all services.

Related

I want to insert ID with the value being a List containing the Records matching that ID

ArrayList<Dashboard> dashRec=new ArrayList<Dashboard>();
HashMap<Object, List<Dashboard>> map = new HashMap<>();
int x=0;
Dashboard dash=new Dashboard();
while(rs.next()) {
if (x == 0){
x=rs.getInt(1);
}
int y = rs.getInt(1);
if(x==y) {
dashRec=new ArrayList<Dashboard>();
dash=new Dashboard();
dash.setREQUEST_ID(rs.getInt(1));
dash.setLOGIN_USER(rs.getString(2));
dash.setPRICE(rs.getInt(3));
dashRec.add(dash);
}
if(y!=x){
dash.getREQUEST_ID();
dash.getLOGIN_USER();
map.put(dash,dashRec);
x=y;
//1st arraylist is inserted in map.
///
}
I want to insert ID with the value being a List containing the Records matching that ID.I have done it for first set of rows. How to do it for n rows?Suppose for next two rows I want another list to be added in map.Similarly for n set of rows I want logic.
You can use Map like this
Map<Integer, List<Dashboard>> map = new HashMap<>();
while (rs.next()) {
Integer id = rs.getInt(1);
if (!map.containsKey(id)) {
map.put(id, new ArrayList<>());
}
Dashboard dash = new Dashboard();
dash.setREQUEST_ID(id);
dash.setLOGIN_USER(rs.getString(2));
dash.setPRICE(rs.getInt(3));
map.get(id).add(dash);
}

How to get values from the second column of a 2d array based on the fiest column value?

I have a Set of data. For example:
car accord
car civic
suv landcruzer
suv landrover
muv innova
I want store it in a scanner or hash map and retrieve the values based on the input.
If "car" is the input I want to pass URL+/accord and URL+/civic as its output
If "muv" is the input, I want to pass URL+/innova as its output
String URL = "www.abc.com";
String Vehicletype = "";
#DataProvider(name = "irLanguage")
public Object[][] lang() {
#SuppressWarnings("resource")
Scanner s = new Scanner(
"Car /accord/\n" +
"Car /civic/\n" +
"suv /landcruzer/\n" +
"suv /rangerover/\n" +
"muv /innova/\n");
Map<String, List<String>> map = new LinkedHashMap<String, List<String>>();
while (s.hasNext()) {
String key = s.next();
if (!map.containsKey(key))
map.put(key, new LinkedList<String>());
map.get(key).add(s.next());
}
urlArray = map.get(vehicletype);
String[][] shades = new String[urlArray.size()][2];
for (int i = 0; i < urlArray.size(); i++) {
shades[i][0] = urlArray.get(i).toString();
shades[i][1] = URL + urlArray.get(i).toString();
lang = shades[i][0];
System.out.println(shades[i][0]);
}
return shades;
}
Here, the code is working fine. That is , if the input vehicle type is car then the output url is www.abc.com/accord/ and www.abc.com/civic/
and if the vehicle type is muv, it only returns www.abc.com/innova/ . This setup works fine for me. But, I wonder if there is any simpler method to do this.
Can anybody with good knowledge in java can help?
You have the right idea, I would build a HashMap that contains one Key (e.g. "car") and all the desired Values for that Key (e.g. "accord", "civic")
HashMap<String, ArrayList<String>> vehicles = new HashMap<String, ArrayList<String>>();
ArrayList<String> makes = new ArrayList<String>();
makes.add("accord");
makes.add("civic");
vehicles.put("car", makes);
makes.clear();
makes.add("landcruzer");
makes.add("rangerover");
vehicles.put("suv", makes);
makes.clear();
makes.add("innova");
vehicles.put("muv", makes);
makes.clear();
Now that you've got the vehicles HashMap built, you can fetch a Key and get all Values and build your URLs.
makes = vehicles.get("car");
for (String make : makes)
{
System.out.println("www.abc.com/" + make);
}

Getting the highest column value from csv file and storing it into arraylist

I'm trying to store into arraylistONE the Sub Name of Name that has the highest admin value.
In this case,
All-Purpose Flour it is 1 3/4 cups all-purpose flour
Baking Powder it is 1/4 teaspoon baking soda and 1/2 cup of plain
Baking Soda it is 8 teaspoons of baking powder
If a Name only has 0 admin values it should be,
Brewed Coffee it should always store the first value in the file which is 1 cup brewed coffee
And for the rest of the data that has lesser admin value, they are stored into arraylistTWO.
I'm stuck in reading the csv file and i don't know how to store into arraylistONE the Sub Name of Name that has the highest admin value and for the rest of the data that has lesser admin value, i don't know how to store into arraylistTWO.
This is the work i've done so far:
try {
br = new BufferedReader (new FileReader ("/sdcard/TABLE_BF.csv"));
while ((sCurrentline = br.readLine ()) != null) {
subIng.add(sCurrentline.split (","));
}
arrSubIng = new String[subIng.size ()][];
subIng.toArray (arrSubIng);
} catch (IOException e) {
e.printStackTrace ();
}
First of all I think it makes sense to create a simple class that holds the data since it will be easier to filter and sort using objects rather than arrays of values.
public class Ingredient {
String name;
String subName;
int status;
int admin;
public Ingredient(String name, String subName, String status, String admin) {
this.name = name;
this.subName = subName;
this.status = Integer.valueOf(status);
this.admin = Integer.valueOf(admin);
}
public String getName() {
return name;
}
public int getAdmin() {
return admin;
}
//more get and set methods here. I have only included what is needed for my answer
}
Then you read and create a list of Ingredient objects.
List<Ingredient> data = new ArrayList<>();
try {
String sCurrentline = null;
BufferedReader br = new BufferedReader(new FileReader("/sdcard/MAIN_BF.csv"));
while ((sCurrentline = br.readLine()) != null) {
String[] arr = sCurrentline.split(",");
Ingredient ingredient = new Ingredient(arr[0], arr[1], arr[2], arr[3]);
data.add(ingredient);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
Then we group the list by name into a Map
Map<String, List<Ingredient>> ingredientsByName = data.stream().collect(Collectors.groupingBy(Ingredient::getName));
And loop over that map to find the max admin value for each ingredient and add them to the correct list
List<Ingredient> main = new ArrayList<>();
List<Ingredient> other = new ArrayList<>();
//Sort on `admin` in descending order
Comparator<Ingredient> compartor = Comparator.comparing(Ingredient:: getAdmin, (i1, i2) -> {
if (i2 > i1) {
return -1;
} else if (i2 < i1) {
return 1;
}
return 0;
});
//Go through each list (ingredient) and find the one with max `admin` value
//and add it to the `main` list then add the rest to `other`
ingredientsByName.forEach( (k, group) -> {
Ingredient max = group.stream().max(compartor).get();
if (max.getAdmin() == 0) {
max = group.get(0);
}
main.add(max);
group.remove(max);
other.addAll(group);
});
I would load the entire contents of the file into memory and store it in a java.util.List<String>. Then you could sort the List by Name and admin. Then just iterate through the List. Whenever you hit a different Name, you know that its associated admin value is the largest. So you add that to your first ArrayList and all the others to your second ArrayList.

How to select random text value from specific row using java

I have three input fields.
First Name
Last item
Date Of Birth
I would like to get random data for each input from a property file.
This is how the property file looks. Field name and = should be ignored.
- First Name= Robert, Brian, Shawn, Bay, John, Paul
- Last Name= Jerry, Adam ,Lu , Eric
- Date of Birth= 01/12/12,12/10/12,1/2/17
Example: For First Name: File should randomly select one name from the following names
Robert, Brian, Shawn, Bay, John, Paul
Also I need to ignore anything before =
FileInputStream objfile = new FileInputStream(System.getProperty("user.dir "+path);
in = new BufferedReader(new InputStreamReader(objfile ));
String line = in.readLine();
while (line != null && !line.trim().isEmpty()) {
String eachRecord[]=line.trim().split(",");
Random rand = new Random();
//I need to pick first name randomly from the file from row 1.
send(firstName,(eachRecord[0]));
If you know that you're always going to have just those 3 lines in your property file I would get put each into a map with an index as the key then randomly generate a key in the range of the map.
// your code here to read the file in
HashMap<String, String> firstNameMap = new HashMap<String, String>();
HashMap<String, String> lastNameMap = new HashMap<String, String>();
HashMap<String, String> dobMap = new HashMap<String, String>();
String line;
while (line = in.readLine() != null) {
String[] parts = line.split("=");
if(parts[0].equals("First Name")) {
String[] values = lineParts[1].split(",");
for (int i = 0; i < values.length; ++i) {
firstNameMap.put(i, values[i]);
}
}
else if(parts[0].equals("Last Name")) {
// do the same as FN but for lastnamemap
}
else if(parts[0].equals("Date of Birth") {
// do the same as FN but for dobmap
}
}
// Now you can use the length of the map and a random number to get a value
// first name for instance:
int randomNum = ThreadLocalRandom.current().nextInt(0, firstNameMap.size(0 + 1);
System.out.println("First Name: " + firstNameMap.get(randomNum));
// and you would do the same for the other fields
The code can easily be refactored with some helper methods to make it cleaner, we'll leave that as a HW assignment :)
This way you have a cache of all your values that you can call at anytime and get a random value. I realize this isn't the most optimum solution having nested loops and 3 different maps but if your input file only contains 3 lines and you're not expecting to have millions of inputs it should be just fine.
Haven't programmed stuff like this in a long time.
Feel free to test it, and let me know if it works.
The result of this code should be a HashMap object called values
You can then get the specific fields you want from it, using get(field_name)
For example - values.get("First Name"). Make sure to use to correct case, because "first name" won't work.
If you want it all to be lower case, you can just add .toLowerCase() at the end of the line that puts the field and value into the HashMap
import java.lang.Math;
import java.util.HashMap;
public class Test
{
// arguments are passed using the text field below this editor
public static void main(String[] args)
{
// set the value of "in" here, so you actually read from it
HashMap<String, String> values = new HashMap<String, String>();
String line;
while (((line = in.readLine()) != null) && !line.trim().isEmpty()) {
if(!line.contains("=")) {
continue;
}
String[] lineParts = line.split("=");
String[] eachRecord = lineParts[1].split(",");
System.out.println("adding value of field type = " + lineParts[0].trim());
// now add the mapping to the values HashMap - values[field_name] = random_field_value
values.put(lineParts[0].trim(), eachRecord[(int) (Math.random() * eachRecord.length)].trim());
}
System.out.println("First Name = " + values.get("First Name"));
System.out.println("Last Name = " + values.get("Last Name"));
System.out.println("Date of Birth = " + values.get("Date of Birth"));
}
}

How to find different genre then add to arrayed linked list

I'm trying to get genres from a file of movies and then check to see if genre is the same. so if in the file there are movies with the same genre they should be stored in the same array of linklist.
i need check the genre's hashcode and then find out if any other movie in the file hash the same hashcode for genre then place that particular genre in a linked list. so basically I have this so far and i also have a link list class etc and not using java.util
public class LoadingMovies {
private static final int size = 22;
private static HashMap<String, Movies> hash = new HashMap(size);
private static HashEntry<String, Movies> hasher = new HashEntry();
private static List<Movies> linked = new List<>();
public static void loadMovies(String filename) throws FileNotFoundException {
String split = ","; //split with comma
Scanner in = new Scanner(new File(filename));
ArrayList<String> arraylist = new ArrayList<>();
String wordIn;
Movies movie = new Movies();
while (in.hasNextLine()) {
wordIn = in.nextLine();
String splitter[] = wordIn.split(split);
String movieTitle = splitter[0];
String movieGenre = splitter[1];
String ageRating = splitter[2];
double scoreRating = Double.parseDouble(splitter[3]);
movie.setTitle(movieTitle);
movie.setGenre(movieGenre);
movie.setAgeRating(ageRating);
movie.setScoreRating(scoreRating);
//System.out.println(movie.getGenre());
arraylist.add(movie.getGenre);
// hash.find(movie.getGenre().hashCode());
// hash.insert(movie.getGenre().hashCode(), movie);
}
}
}
This is what i have so far. I already read in the file now I want to check to see if a genre (String) in the file is same and then add that genre to link list. how can I do this?
A HashMap<String, List<Movie>> seems to be what you're looking for:
Map<String, List<Movie>> movieGenres = new HashMap<>();
while (in.hasNextLine()) {
// code you have
List<Movie> moviesInThisGenre = moviewGenres.get(genre);
if (moviesInThisGenre == null) {
moviesInThisGenre = new LinkedList<>();
movieGenres.put(genre, moviesInThisGenre);
}
moviesInThisGenre.add(movie);
}
You would need a Map that maps from genre String to Lists of Movies:
HashMap<String, List<Movies>> genres = new Hash...
then when you add a Movie:
String g = movie.getGenre();
if (!genres.containsKey(g)
genres.put(g, new ArrayList<Movies>));
genres.get(g).add(movie);
Explanation
A HashMap stores values for key objects, where each key object can only occur once in the map. Thus, when you want to store multiple movies for one genre String, the value type should be a collection (List, Set, etc.).
e.g.
HashMap<String, Movies> genres ... ;
...
genres.put(g, movie);
will override any Movie value you had for that genre before.
But, since you cannot know at runtime if the genre already exists in your Map, you have to put a new (empty) list for an unknown genre. Any movies with that genre can now be added to that list.

Categories