This code produces accurate output, aside from the final column of data output.
The output is meant to show the non-decimal vote percent value of the candidates.
An error in my logic has caused the aforementioned value to print as 0.
Output appears as follows:
public class Candidate {
public String name;
public int numVotes;
public Candidate(String name, int numVotes) {
this.name = name;
this.numVotes = numVotes;
}
public String getName() {
return name;
}
public int getNumVotes() {
return numVotes;
}
public String toString() {
return getName() + " received " + getNumVotes() + " votes.";
}
}
import java.util.*;
public class TestCandidate {
public static void main(String [] args) {
ArrayList<Candidate> list = new ArrayList<Candidate>();
list.add(new Candidate("John Smith", 5000));
list.add(new Candidate("Mary Miller", 4000));
list.add(new Candidate("Michael Duffy", 6000));
list.add(new Candidate("Tim Robinson", 2500));
list.add(new Candidate("Joe Ashtony", 1800));
System.out.println("Results per candidate:");
System.out.println("______________________\n");
int total = getTotal(list);
printVotes(list);
System.out.print("\nCandidate\t\tVotes Received\t\t% of Total Votes");
printResults(list);
System.out.println("\n\nTotal number of votes in election: " + total);
}
public static void printResults(ArrayList<Candidate> list) {
String name = "";
int percent = 0;
int votes = 0;
int total = getTotal(list);
for(Candidate token : list) {
name = token.getName();
votes = token.getNumVotes();
percent = (votes / total) * 100;
System.out.printf("\n%1s\t%12d\t%17d", name, votes, percent);
}
}
public static void printVotes(ArrayList<Candidate> list) {
for(Candidate token : list) {
System.out.println(token);
}
}
public static int getTotal(ArrayList<Candidate> list) {
int total = 0;
for(Candidate token : list) {
total += token.getNumVotes();
}
return total;
}
}
You are performing integer division here.
percent = (votes / total) * 100;
votes will always be inferior or egal than total, so it's likely that votes/total will result in 0 due to integer division.
Either change percent as double and cast one of the operand of the division to double, or if you want to keep percent as an integer, multiply vote by 100 first and then divide it by total.
percent = (votes*100) / total;
Related
Problem Statement: I have a 2D array of strings containing student names and respective marks as below
String[][] scores = {{"Bob","85"},{"Mark","100"},{"Charles","63"},{"Mark","34"}};
I want to calculate the best average among all the students available, i.e with the above input the best average should be 85.
My Attempt:
I tried to solve this using HashMap as below.
public int bestAverageCalculator(String[][] scores) {
// This HashMap maps student name to their list of scores
Map<String,List<Integer>> scoreMap = new HashMap<String,List<Integer>>();
for(String[] score:scores) {
String name = score[0];
int currentScore =Integer.parseInt(score[1]);
if(scoreMap.containsKey(name)) {
List<Integer> scoreList = scoreMap.get(name);
scoreList.add(currentScore);
scoreMap.put(name, scoreList);
}
else {
List<Integer> scoreList = new ArrayList<Integer>();
scoreList.add(currentScore);
scoreMap.put(name, scoreList);
}
}
//scoreMap will be {Charles=[63], Bob=[85], Mark=[100, 34]}
//After Map is formed i am iterating though all the values and finding the best average as below
int bestAverage = 0;
for(List<Integer> value:scoreMap.values()) {
int sum = 0;
int count = 0;
for(int i:value) {
sum+=i;
count++;
}
int average = (int)Math.floor(sum/count);
if(average>bestAverage)
bestAverage = average;
}
return bestAverage;// returns 85
}
The implementation is correct and i am getting the answer as expected, but i was told the space complexity of the program is more and it can be achieved without using the List<Integer> for marks, i am not able to understand how average can be calculated on fly without storing list of marks.
Please suggest if any other methods can solve this other than HashMap.
Any help would be appreciated.
You could store for each student a constant amount of data :
the student's name
the sum of all the student's marks
the number of the student's marks
This will make the space complexity O(m) where m is the number of unique students (instead of your O(n) where n is the number of marks).
For example, you can have a Student class with these 3 properties (and store the data in a List<Student>), or you can have a Map<String,int[]> with the key being the student's name and the value being an array of two elements containing the sum of the marks and the number of marks.
You can construct this data while iterating over the input.
Now you can compute the average for each student and find the highest average.
Well for space saving you can store two numbers per person
avgSum and count and calculate average on the end.
I have implemented #Eran 's approach based on your code with a Map<String,int[]> with
key: student's name
value: an array of two elements [the sum of the scores, the number of scores]
public int bestAverageCalculator(String[][] scores) {
// This HashMap maps student name to their total scores and count in an int array format of [totalScores, count]
Map<String,int[]> scoreMap = new HashMap<String,int[]>();
for(String[] score:scores) {
String name = score[0];
int currentScore =Integer.parseInt(score[1]);
if(scoreMap.containsKey(name)) {
int[] scoreCount = scoreMap.get(name);
scoreCount[0] += currentScore;
scoreCount[1] ++;
scoreMap.put(name, scoreCount);
}
else {
int[] scoreCount = new int[]{currentScore, 1};
scoreMap.put(name, scoreCount);
}
}
int bestAverage = 0;
for(int[] value:scoreMap.values()) {
int average = (int)Math.floor(value[0]/value[1]);
if(average>bestAverage)
bestAverage = average;
}
return bestAverage;// returns 85
}
#Eran's idea but with Student class, at least for me it's much more clear
import java.util.*;
public class Main {
static String[][] scores = {{"Bob", "85"}, {"Mark", "100"}, {"Charles", "63"}, {"Mark", "34"}};
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
for (String[] score : scores) {
String name = score[0];
int currentScore = Integer.parseInt(score[1]);
Student student = findStudentByName(name, students);
if (student != null) {
student.setNumberOfScores(student.getNumberOfScores() + 1);
student.setSumOfScores(student.getSumOfScores() + currentScore);
} else {
student = new Student(name, 1, currentScore);
students.add(student);
}
}
findStudentWithBestAverage(students);
}
private static void findStudentWithBestAverage(List<Student> students) {
Student bestStudent = null;
int bestAverage = 0;
for (int i = 0; i < students.size(); i++) {
if ((students.get(i).getSumOfScores() / students.get(i).getNumberOfScores()) > bestAverage) {
bestStudent = students.get(i);
bestAverage = (students.get(i).getSumOfScores() / students.get(i).getNumberOfScores());
}
}
System.out.println(bestStudent + " with average: " + bestAverage);
}
private static Student findStudentByName(String name, List<Student> students) {
for (int i = 0; i < students.size(); i++) {
if (students.get(i).getName().equals(name)) {
return students.get(i);
}
}
return null;
}
public static class Student {
private String name;
private int numberOfScores;
private int sumOfScores;
public Student(String name, int numberOfScores, int sumOfScores) {
this.name = name;
this.numberOfScores = numberOfScores;
this.sumOfScores = sumOfScores;
}
public String getName() {
return name;
}
public int getNumberOfScores() {
return numberOfScores;
}
public void setNumberOfScores(int numberOfScores) {
this.numberOfScores = numberOfScores;
}
public int getSumOfScores() {
return sumOfScores;
}
public void setSumOfScores(int sumOfScores) {
this.sumOfScores = sumOfScores;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return name.equals(student.name);
}
#Override
public int hashCode() {
return Objects.hash(name);
}
#Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", numberOfScores=" + numberOfScores +
", sumOfScores=" + sumOfScores +
'}';
}
}
}
Foreword: sorry for all the code, I know most of it is redundant for this question.
This class takes a description (size), a cost, and a quantity as arguments and returns the number of times the object was created (transaction_number), the total quantity specified for all the objects created (total_quantity), and (is supposed to) return the total cost of all the object created.
public class SalesTransaction
{
private static int counter = 1;
public final int transaction_number;
private static int order_quantity = 0;
public final int total_quantity;
private static double temp_grand_total = 0;
public final double grand_total;
private String size;
private double cost;
private int quantity;
public SalesTransaction(String size, double cost, int quantity)
{
this.size = size;
this.cost = cost;
this.quantity = quantity;
this.transaction_number = counter++;
order_quantity += quantity;
this.total_quantity = order_quantity;
temp_grand_total += totalCostAfterTax(cost*quantity); // this is wrong!
this.grand_total = temp_grand_total;
}
public static double discountAmount(int quantity, double cost)
{
double discount_amount = 0;
if (quantity > 20)
{
discount_amount = cost * 0.10;
}
return discount_amount;
}
public static double totalCostBeforeTax(SalesTransaction temp)
{
double total_cost;
int quantity = temp.quantity;
double cost = temp.cost;
total_cost = quantity * cost;
double discount_amount = discountAmount(quantity, total_cost);
total_cost = total_cost - discount_amount;
return total_cost;
}
public static double totalCostAfterTax(double total_cost)
{
total_cost = total_cost * 1.15;
return total_cost;
}
public static void printStats(SalesTransaction temp)
{
System.out.println("Transaction Number: " + temp.transaction_number);
System.out.println("Size: " + temp.size);
System.out.println("Cost Per Table: "+ temp.cost);
System.out.println("Number of Tables: " + temp.quantity);
System.out.println("Total Tables So Far: " + temp.total_quantity);
double total_cost_before_tax = totalCostBeforeTax(temp);
double discount_amount = discountAmount(temp.quantity, total_cost_before_tax);
System.out.println("Discount: " + discount_amount);
double total_cost_after_tax = totalCostAfterTax(total_cost_before_tax);
temp.temp_grand_total = total_cost_after_tax;
System.out.println("Cost for this transaction: " + total_cost_after_tax);
System.out.println("Total cost: "+ temp.grand_total);
System.out.println();
}
}
And this is just a tester class.
public class SalesTester
{
public static void main(String[] args)
{
SalesTransaction one = new SalesTransaction("Small", 10.0, 10);
one.printStats(one);
SalesTransaction two = new SalesTransaction("Medium", 20.0, 30);
two.printStats(two);
SalesTransaction three = new SalesTransaction("Large", 30.0, 40);
three.printStats(three);
}
}
The problem is that I can't figure out how to store the grand_total. I tried doing it the same way I stored the total_quantity but I can see why that isn't working.
How can I keep track of the grand total of all the transactions (objects) so I can then print it out on the console?
I assume there's another way of expressing this in the constructor but I'm not sure how and I couldn't find any examples of this.
The simplest solution is to use a static field on your SalesTransaction class which holds the grand_total. A static variable is shared by all instances of a class.
private static double grandTotal = 0;
public SalesTransaction(double cost) {
grandTotal += cost;
}
However, this has some disadvantages in the long run. It would mean you can't have transactions as members of different grand totals. This is why it's called the singleton anti-pattern.
A much better way to solve the problem is to make an additional class such as TransactionGroup, which contains SalesTransaction objects in a List, and sums together the costs when needed.
public class TransactionGroup {
private List<SalesTransaction> transactions = new ArrayList<>();
public void addTransaction(SalesTransaction st) {
transactions.add(st);
}
public double getGrandTotal() {
double sum = 0;
for (SalesTransaction st : transactions) {
sum += st.getCost();
}
return sum;
}
}
Whenever I compile my code, I receive the following errors:
constructor SalesPerson in class SalesPerson cannot be applied to
given types; error: constructor Player in class Player cannot be
applied to given types;
But it doesn't list any types. The code in question is
Modify the DemoSalesperson application so each Salesperson has a successive ID number from 111 through 120 and a sales value that ranges from $25,000 to $70,000, increasing by $5,000 for each successive Salesperson. Save the file as DemoSalesperson2.java.*/
SalesPerson class:
public class SalesPerson {
// Data fields for Salesperson include an integer ID number and a double annual sales amount
private int idNumber;
private double salesAmount;
//Methods include a constructor that requires values for both data fields, as well as get and set methods for each of the data fields.
public SalesPerson(int idNum, double salesAmt) {
idNumber = idNum;
salesAmount = salesAmt;
}
public int getIdNumber() {
return idNumber;
}
public void setIdNumber(int idNum) {
idNumber = idNum;
}
public double getSalesAmount() {
return salesAmount;
}
public void setSalesAmount(double salesAmt) {
salesAmount = salesAmt;
}
}
Driver:
public class DemoSalesPerson2 {
public static void main(String[] args) {
SalesPerson s1 = new SalesPerson(111, 0);
final int NUM_PERSON = 10;
SalesPerson[] num = new SalesPerson[NUM_PERSON];
for (int x = 1; x < num.length; x++) {
// NUM_PERSON
num[x] = new SalesPerson((111 + x + "|" + 25000 + 5000 * (x)));
System.out.println(x + " " + s1.getIdNumber() + " " + s1.getSalesAmount());
}
}
}
Change this: num[x] = new SalesPerson((111 + x + "|" + 25000 + 5000 * (x)));
to this: num[x] = new SalesPerson((111 + x), (25000 + 5000 * (x)));
You had it right here SalesPerson s1 = new SalesPerson(111, 0);.
Notice the difference between the two constructor calls.
As Sssss pointed out, you're handing in a String as the constructor param when your method requires two ints.
Code jotted down here, haven't tested it. Should get you pointed in the right direction however.
public class DemoSalesPerson2
{
public static void main(String[] args)
{
SalesPerson[] num = new SalesPerson[10];
final int START_NUM =111;
final double START_SALARY=25_000;
for (int x =0; x<num.length; x++) {
num[x] =new SalesPerson(START_NUM+x,START_SALARY+5000*(x));
System.out.println(num[x].getIdNumber()+" "+num[x].getSalesAmount() );
}
}}
try this!!
I have a method in the Candy Class named pricePerHundredGrams and what it is supposed to do is multiply the variable price times 100.00 and divide that answer by the variable weightGrams, and finally return that result to the variable wammy. When the variable wammy is called for in the very 2nd last statement of this code, it is supposed to pass the answer to return result. And ultimately c1 and c2 should display that result as well...but I get NaN for "per hundred grams". What is wrong with my code?
public class whatever
{ public static void main (String[] args)
{
processCandies();
System.out.println("end of processing");
}
public static void processCandies()
{
Candy c1 = new Candy("Hershey", 145, 4.35, 233);
Candy c2 = new Candy("Milky Way", 390, 2.66, 126);
System.out.println(c1);
System.out.println(c2);
}
}
class Candy
{
private String name;
private int calories;
private double price;
private double weightGrams;
double wammy = pricePerHundredGrams(price, weightGrams);
/**
Constructor
#param name
#param calories
#param price
#param gram
*/
public Candy(String n, int cal, double p, double wG)
{
name = n;
calories = cal;
price = p;
weightGrams = wG;
}
public String getName()
{
return name;
}
public int getCalories()
{
return calories;
}
public double getPrice()
{
return price;
}
public double getWeightGrams()
{
return weightGrams;
}
public double pricePerHundredGrams(double price, double weightGrams)
{
return (price * 100.00) / weightGrams;
}
public String toString()
{
String result;
result = name + "\n" + calories + " calories\n" + weightGrams + " grams\n" + wammy + " per hundred grams\n";
return result;
}
}
You are initializing wammy with the result of pricePerHundredGrams, but price and weightGrams haven't been initialized yet, so they're both 0. For double arithmetic, 0 divided by 0 is NaN (it's indeterminate in math).
Initialize wammy after price and weightGrams have valid values in your constructor:
public Candy(String n, int cal, double p, double wG)
{
name = n;
calories = cal;
price = p;
weightGrams = wG;
// Initialize wammy here.
wammy = pricePerHundredGrams(price, weightGrams);
}
Additionally, since they are already instance variables, you don't need to pass price and weightGrams as parameters to pricePerHundredGrams.
I am doing a project and instead of using an array, I figured an array list would be better. I know I need to declare the array list and its methods, but I am not too sure where to go from there. Any suggestions? Here's code...
public class Student {
private String name;
private int[] tests;
public Student() {
this("");
}
public Student(String nm) {
this(nm, 3);
}
public Student(String nm, int n) {
name = nm;
tests = new int[n];
for (int i = 0; i < tests.length; i++) {
tests[i] = 0;
}
}
public Student(String nm, int[] t) {
tests = new int[t.length];
}
public Student(Student s) {
this(s.name, s.tests);
}
public int getNumberOfTests() {
return tests.length;
}
public void setName(String nm) {
name = nm;
}
public String getName() {
return name;
}
public void setScore(int i, int score) {
tests[i - 1] = score;
}
public int getScore(int i) {
return tests[i - 1];
}
public int getAverage() {
int sum = 0;
for (int score : tests) {
sum += score;
}
return sum / tests.length;
}
public int getHighScore() {
int highScore = 0;
for (int score : tests) {
highScore = Math.max(highScore, score);
}
return highScore;
}
public String toString() {
String str = "Name: " + name + "\n";
for (int i = 0; i < tests.length; i++) {
str += "test " + (i + 1) + ": " + tests[i] + "\n";
}
str += "Average: " + getAverage();
return str;
}
public String validateData() {
if (name.equals("")) {
return "SORRY: name required";
}
for (int score : tests) {
if (score < 0 || score > 100) {
String str = "SORRY: must have " + 0 + " <= test score <= " + 100;
return str;
}
}
return null;
}
}
I figured an array list would be better
Maybe. Maybe not. It depends. Does it look like you would get a benefit in using one based on the ArrayList API?
If your "list" never changes size, and you don't need to find things in it, then an array is just as good.
I know I need to declare the array list and its methods, but I am not
too sure where to go from there
You need to create a reference to an instance of an ArrayList. That's as simple as
List<Integer> myList = new ArrayList<Integer>();
in your class declaration. You don't need to "declare its methods". When you have a reference to an object, you can invoke its methods.
To use an ArrayList, you just need to declare and instantiate it:
// <SomeObject> tells Java what kind of things go in the ArrayList
ArrayList<SomeObject> aDescriptiveNameHere = new ArrayList<SomeObject>();
// This is also valid, since an ArrayList is also a List
List<SomeObject> list = new ArrayList<SomeObject>();
Then you can add things with the add() method:
// Please don't name your list "list"
list.add(new Thing(1));
list.add(new Thing(2));
You can get something by index (like you would with someArray[index]) as:
list.get(index);
// For example
Thing t = list.get(5);
You probably also need the size().
See the JavaDocs for more info.
All of the operations you're using are mirrored in the ArrayList API. One thing that's worth noting is that you cannot declare an ArrayList of primitive types, but for each of the primitive types there exists an Object that is the boxed version of the primative.
The boxed version of int is Integer, so you have
ArrayList<Integer> myList = new ArrayList<Integer>();
From there, you need to look up the methods you would need to use in order to manipulate the array. For example, if you want to add the number 42 to the end of the array, you would say
myList.add(42);
The ArrayList API is located here.
I think it could be better to use the stl vector instead make your own arrays
I tried to change the array to arraylist.
Reply if this doesn't compile correctly.
import java.util.ArrayList;
public class Student {
private String name;
// private int[] tests;
private ArrayList<Integer> tests;
public Student() {
this("");
}
public Student(String nm) {
// this(nm, 3);
name = nm;
}
/*
* public Student(String nm, int n) { name = nm; tests = new int[n]; for
* (int i = 0; i < tests.length; i++) { tests[i] = 0; } }
*/
/*
* public Student(String nm, int[] t) { tests = new int[t.length]; }
*/
public Student(Student s) {
this(s.name, s.tests);
}
public Student(String name2, ArrayList<Integer> tests2) {
name = name2;
tests = tests2;
}
public int getNumberOfTests() {
return tests.size();
}
public void setName(String nm) {
name = nm;
}
public String getName() {
return name;
}
// public void setScore(int i, int score) {
// tests[i - 1] = score;
public void setScore(int score) {
tests.add(score);
}
public int getScore(int i) {
// return tests[i - 1];
return tests.get(i - 1);
}
public int getAverage() {
int sum = 0;
for (int score : tests) {
sum += score;
}
// return sum / tests.length;
return sum / tests.size();
}
public int getHighScore() {
int highScore = 0;
for (int score : tests) {
highScore = Math.max(highScore, score);
}
return highScore;
}
public String toString() {
String str = "Name: " + name + "\n";
for (int i = 0; i < tests.size(); i++) {
str += "test " + (i + 1) + ": " + tests.get(i) + "\n";
}
str += "Average: " + getAverage();
return str;
}
public String validateData() {
if (name.equals("")) {
return "SORRY: name required";
}
for (int score : tests) {
if (score < 0 || score > 100) {
String str = "SORRY: must have " + 0 + " <= test score <= "
+ 100;
return str;
}
}
return null;
}
public ArrayList<Integer> getTests() {
return tests;
}
public void setTests(ArrayList<Integer> tests) {
this.tests = tests;
}
}