Removing smallest key from treeMap - java

I'm creating a scoring system using a treeMap and I want to only display the top 3 results. When the player inputs the 4th result (if it's bigger than the current smallest value) how do I make it delete the smallest value and replace it with the new value. My code so far so sorting the scores:
Map<Integer, String> treeMap = new TreeMap<Integer, String>(new MyCopr());
treeMap.put(name1val, name1);
treeMap.put(name2val, name2);
treeMap.put(name3val, name3);
treeMap.put(tempval, tempname);
for (Map.Entry<Integer, String> entry : treeMap.entrySet()) {
playername1.append("Key : " + entry.getKey() + " Value : "
+ entry.getValue() + "\n");
}
}
class MyCopr implements Comparator<Integer> {
#Override
public int compare(Integer lhs, Integer rhs) {
return rhs.compareTo(lhs);
}
}
From here what can I do to replace the smallest value? Thanks.

I would use a set of scores (like this) -
private static int MAX_SCORES = 3;
private SortedSet<Score> scores = new TreeSet<Score>();
public Set<Score> getScores() {
return scores;
}
public void addScore(String name, int score) {
scores.add(new Score(name, score));
while (scores.size() > MAX_SCORES) {
scores.remove(scores.first());
}
}
private class Score implements Comparable<Score> {
private String name;
private int score;
private Score(String name, int score) {
this.name = name;
this.score = score;
}
public int compareTo(Score obj) {
if (this == obj) {
return 0;
}
if (this.score < obj.score) {
return -1;
} else if (this.score > obj.score) {
return 1;
}
return name.compareTo(obj.name);
}
public String toString() {
return name + " - score = " + score;
}
}
And then use it like so ...
System.out.println(obj.getScores());
obj.addScore("Player 1", 1);
obj.addScore("Player 2", 2);
obj.addScore("Player 3", 3);
System.out.println(obj.getScores());
obj.addScore("Player 4", 4);
System.out.println(obj.getScores());
Which yields this (when I run it) -
[]
[Player 1 - score = 1, Player 2 - score = 2, Player 3 - score = 3]
[Player 2 - score = 2, Player 3 - score = 3, Player 4 - score = 4]

Related

toString method for arrays

I am struggling with an actually very easy task, which is print out items from an item array like:
arr[3,4,2,5]
0 items (0 kg)
0 items (1 kg)
0 items (2 kg)
and so on.
This is what I have done, but my program will not print anything :( Heeelp me please.
import java.util.ArrayList;
import java.util.Arrays;
public class Suitcase {
private ArrayList<Item> items = new ArrayList<>();
private final int maxWeight;
private int[] arr = new int[items.size()];
public Suitcase(int maxWeight) {
this.maxWeight = maxWeight;
}
public void addItem(Item item) {
int itemsWeight = 0;
for(Item i: items){
itemsWeight += i.getWeight();
}
if(itemsWeight + item.getWeight() <= this.maxWeight){
items.add(item);
}
}
public void array() {
for(Item item: items){
int index = item.getWeight();
this.arr[index] += 1;
}
}
public String toString() {
String returnValue = "";
for(int i = 0; i < arr.length; i++){
returnValue = arr[i] + " items " + i + " kg";
}
return returnValue;
}
}
public class Item {
private int weight;
private String name;
public Item(String name, int weight) {
this.name = name;
this.weight = weight;
}
public String getName() {
return this.name;
}
public int getWeight() {
return this.weight;
}
public String toString() {
return this.name + "(" + String.valueOf(this.weight) + ")";
}
}
Here is my main class, but it will not print anything:
public class Main {
public static void main(String[] args) {
Item book = new Item("Lord of the rings", 2);
Item phone = new Item("Nokia 3210", 1);
Item brick = new Item("brick", 4);
Suitcase suitcase = new Suitcase(5);
System.out.println(suitcase.toString());
suitcase.addItem(book);
System.out.println(suitcase);
suitcase.addItem(phone);
System.out.println(suitcase);
suitcase.addItem(brick);
System.out.println(suitcase);
}
}
Notes:
You do not need to call suitcase.toString() while printing the suitcase object. When System.out.println(suitcase); is implicitly gets converted into System.out.println(suitcase.toString());.
You can make your design simpler by having a variable to keep track of the total weight in the suitcase. Also, create a variable in Item to keep track of item's count in the suitcase.
You do not need int[] arr. It is simply adding unwanted complexity. Remove it.
It is better to use enhanced for loop if you can do so.
Given below is the code incorporating the points mentioned above:
import java.util.ArrayList;
class Suitcase {
private ArrayList<Item> items = new ArrayList<>();
private final int maxWeight;
private int totalWeight;
public Suitcase(int maxWeight) {
this.maxWeight = maxWeight;
}
public void addItem(Item item) {
if (totalWeight + item.getWeight() <= maxWeight) {
int index = items.indexOf(item);
if (index == -1) {// It means the item does not exist in the suitcase
items.add(item);
}
// If the item already exists, do not add it's entry again; just update its
// count and the totalWeight of the suitcase
totalWeight += item.getWeight();
item.setCount(item.getCount() + 1);
System.out.println(item.getName() + " was added in the suitcase");
} else {
System.out.println(item.getName() + " can not be accommodated in the suitcase.");
}
}
public String toString() {
String returnValue = "";
for (Item item : items) {
returnValue += "No. of " + item.getName() + " in the suitcase = " + item.getCount()
+ ", its total weight = " + item.getCount() * item.getWeight() + "kg\n";
}
if (returnValue.isEmpty()) {
returnValue = "The suitcase is empty.";
} else {
returnValue += "Total weight of the suitcase = " + totalWeight + "kg";
}
return returnValue;
}
}
class Item {
private int weight;
private String name;
private int count;
public Item(String name, int weight) {
this.name = name;
this.weight = weight;
}
public String getName() {
return this.name;
}
public int getWeight() {
return this.weight;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
#Override
public String toString() {
return "Item [weight=" + weight + ", name=" + name + ", count=" + count + "]";
}
}
public class Main {
public static void main(String[] args) {
Item book = new Item("Lord of the rings", 2);
Item phone = new Item("Nokia 3210", 1);
Item brick = new Item("brick", 4);
Suitcase suitcase = new Suitcase(5);
System.out.println(suitcase);
suitcase.addItem(book);
suitcase.addItem(phone);
suitcase.addItem(brick);
suitcase.addItem(phone);
suitcase.addItem(book);
System.out.println(suitcase);
}
}
Output:
The suitcase is empty.
Lord of the rings was added in the suitcase
Nokia 3210 was added in the suitcase
brick can not be accommodated in the suitcase.
Nokia 3210 was added in the suitcase
Lord of the rings can not be accommodated in the suitcase.
No. of Lord of the rings in the suitcase = 1, its total weight = 2kg
No. of Nokia 3210 in the suitcase = 2, its total weight = 2kg
Total weight of the suitcase = 4kg
Make sure to change your "toString()" function, currently it is only printing the last value, change it to:
public String toString(){
String returnValue ="";
for(int i = 0; i<arr.length;i++ ){
returnValue += arr[i] + " items " +i+" kg"; //notice its '+='
}
return returnValue;
}
You initialize your arr with value 0. Note that the initial size of new ArrayList() is 0. Take a look at this example:
import java.util.ArrayList;
class Main {
private static ArrayList<Object> items = new ArrayList();
private static int[] arr = new int[items.size()];
public static void main(String[] args) {
System.out.println(items.size()); # => 0
System.out.println(arr.length); # => 0
}
}
As a result when you call System.out.println(suitcase) the for loop in Suitcase's toString() method iterates over exactly 0 elements - therefore not outputting anything.

Compare Integer, arrays of class instances

Ok so I'm kind of in the loss here but here goes. So I need to sort the array medalList when they get printed out. First I need to sort by gold medals which are added to the index [0], second after silvers in index [1], third after bronze in index [2] and last if a team is tied they get sorted by team name. Do I need to call a sorting method in another class, keep track of one and sort through and compare to the rest of the teams and if they're the best print them out first?
How do I compare Integers in an array of one classes to another?
When a user enters a certain command a list of teams with their results will get printed out.
As of now it looks like this:
1st 2nd 3rd Team Name
0 0 0 North Korea
3 1 1 America
5 0 2 France
2 1 3 Germany
I want it to say:
1st 2nd 3rd Team Name
5 0 2 France
3 1 1 America
2 1 3 Germany
0 0 0 North Korea
import java.util.ArrayList;
import java.util.Arrays;
public class Team {
private String teamName;
private ArrayList<Participant> participantList = new ArrayList<Participant>();
private int[] medalList = new int[3];
public Team(String teamName) {
this.teamName = teamName;
}
public String getTeamName() {
return teamName;
}
public void addParticipant(Participant participant) {
participantList.add(participant);
}
public void removeFromTeam(int participantNr){
for(int i = 0; i < participantList.size(); i++){
if(participantList.get(i).getParticipantNr() == participantNr){
participantList.remove(i);
}
}
}
public void printOutParticipant() {
for(int i = 0; i < participantList.size(); i++){
System.out.println(participantList.get(i).getName() + " " + participantList.get(i).getLastName());
}
}
public boolean isEmpty() {
boolean empty = false;
if (participantList.size() == 0) {
empty = true;
return empty;
}
return empty;
}
public void emptyMedalList(){
Arrays.fill(medalList, 0);
}
public void recieveMedals(int medal) {
if(medal == 1){
int gold = 0;
gold = medalList[0];
medalList[0] = ++gold;
} else if (medal == 2){
int silver = 0;
silver = medalList[1];
medalList[1] = ++silver;
} else if (medal == 3){
int bronze = 0;
bronze = medalList[2];
medalList[2] = ++bronze;
}
}
public void printMedals(){
System.out.println(medalList[0] + " " + medalList[1] + " " + medalList[2] + " " + teamName);
}
public int compareTo(Team team) {
int goldDif = Integer.compare(team.medalList[0], this.medalList[0]);
if (goldDif != 0)
return goldDif;
int silverDif = Integer.compare(team.medalList[1], this.medalList[1]);
if (silverDif != 0)
return silverDif;
int bronzeDif = Integer.compare(team.medalList[2], this.medalList[2]);
if (bronzeDif != 0)
return bronzeDif;
return this.getTeamName().compareTo(team.getTeamName());
}
public String toString() {
return teamName;
}
}
Make your Team class comparable
public class Team implements Comparable<Team> {
and add a comparison method
#Override
public int compareTo(final Team other) {
for (int i = 0; i < 3; i++) {
final int compareMedals = Integer.compare(medalList[i], other.medalList[i])
if (compareMedals != 0) {
return compareMedals;
}
}
return teamName.compareTo(other.teamName);
}
This will check gold medals first, then silver medals if the amount of gold medals is equal and so on and use the team name comparison as a last resort. You can then sort a collection of Teams with
final List<Team> teams = new ArrayList<>();
...
Collections.sort(teams);
EDIT:
Or if you like it in Java 8 style you could also write your comparison method like
#Override
public int compareTo(final Team other) {
return Stream.of(0, 1, 2)
.map(i -> Integer.compare(medalList[i], other.medalList[i]))
.filter(i -> i != 0)
.findFirst()
.orElse(teamName.compareTo(other.teamName));
}

Creating an arraylist of names with lowest scores

I have an a tournament class which I try to obtain winners by obtaining the lowest scores and making an arraylist from it. I thought maybe I could use my winnerScore method into my winners method?
This is my attempt:
(but i end up with an error because they aren't the same type)
/**
* Returns the list of winners, that is, the names of those players
* with the lowest total score.
* The winners' names should be stored in the same order as they occur
* in the tournament list.
* If there are no players, return empty list.
* #return list of winners' names
*/
public ArrayList<String> winners() {
ArrayList<String> result = new ArrayList<String>();
if (result.isEmpty()) {
return null;
}
result.add(players);
// Supply this code!
return result;
}
I have this method that I have made, is there some way to incoperate it into winners method?
/*
* Assume as precondition that the list of players is not empty.
* Returns the winning score, that is, the lowest total score.
* #return winning score
*/
public int winningScore() {
Player thePlayer = players.get(0);
int result = thePlayer.totalScore();
// Supply this code!
for(int i=0; i <par.length; i++)
if(par[i] > result)
result = par[i];
return result;
}
This is the Junit test for the winners method:
#Test(timeout=3000)
public void testWinners() {
int [] par = {3,4,5,4,5,3,4,3,5,3,4,5,4,3,4,5,4,3};
int [] scores1 = {3,4,3,5,3,4,4,3,5,3,3,4,3,4,3,4,3,4};
int [] scores2 = {4,4,3,5,3,4,4,3,5,3,3,4,3,4,3,4,3,4};
int [] scores3 = {3,4,3,5,3,4,4,3,5,3,3,4,3,4,3,4,3,5};
Tournament T = new Tournament(par);
T.enter("Norman", 2, scores1);
T.enter("Palmer", 4, scores2);
T.enter("Scott", 1, scores3);
ArrayList<String> winners = T.winners();
assertTrue(winners.get(0).equals("Norman"));
}
Any help will be greatly appreciated thanks.
I couldn't leave this one alone. Improvements:
#Test(timeout=3000)
public void testWinners() {
Tournament t = new Tournament();
// int [] par = {3,4,5,4,5,3,4,3,5,3,4,5,4,3,4,5,4,3}; // par does not matter
int [] scores1 = {3,4,3,5,3,4,4,3,5,3,3,4,3,4,3,4,3,4};
int [] scores2 = {4,4,3,5,3,4,4,3,5,3,3,4,3,4,3,4,3,4};
int [] scores3 = {3,4,3,5,3,4,4,3,5,3,3,4,3,4,3,4,3,5};
t.enter("Norman", 2, scores1);
t.enter("Palmer", 4, scores2);
t.enter("Scott", 1, scores3);
assertTrue(winners.get(0).equals("Palmer"));
}
And the class:
public class Tournament {
List<Player> players = new ArrayList<>();
private void enter(String name, int par, int[] scores) {
players.add(new Player(name, par, scores));
}
public List<Player> getWinners() {
List<Player> ps = new ArrayList<Player>(players);
Collections.sort(ps);
return ps;
}
private class Player implements Comparable<Player> {
public String name;
public int totalScore;
public Player(String name, int par, int[] scores) {
this.name = name;
for (int score : scores) {
totalScore += score;
}
//System.out.println(" " + name + " " + totalScore + ", par " + par + ", total " + (totalScore - par));
totalScore -= par;
}
#Override
public int compareTo(Player o) {
return Integer.compare(totalScore, o.totalScore);
}
}
}

Sorting values from ArrayList inside HashMap

I'm having a hard time trying to solve my problem. I have to sort students in descending order by highest average mark and also to show the average mark of all students. I will include my Main class and declarations from my other classes.
public Main()
{
ArrayList<Student> students = new ArrayList<Student>();
Student A = new Student("John", "Doe", 1000);
students.add(A);
Student B = new Student("Michael", "Hawk", 2000);
students.add(B);
Student C = new Student("Nicholas", "Johnson", 3000);
students.add(C);
HashMap<Integer, ArrayList<PassedExams>> map = new HashMap<Integer, ArrayList<PassedExams>>();
for (Student student : students)
{
map.put(student.getIndeks(), new ArrayList<PassedExams>());
}
for (Entry<Integer,ArrayList<PassedExams>> exam : map.entrySet())
{
if (exam.getKey() == 1000)
{
ArrayList<PassedExams> passedExam = exam.getValue();
passedExam.add(new PassedExams("CS102", 6));
passedExam.add(new PassedExams("CS220", 8));
exam.setValue(passedExam);
}
if (exam.getKey() == 2000)
{
ArrayList<PassedExams> passedExam = exam.getValue();
passedExam.add(new PassedExams("MA101", 10));
passedExam.add(new PassedExams("CS101", 7));
exam.setValue(passedExam);
}
if (exam.getKey() == 3000)
{
ArrayList<PassedExams> passedExam = exam.getValue();
passedExam.add(new PassedExams("CS115", 9));
passedExam.add(new PassedExams("MA102", 7));
exam.setValue(passedExam);
}
}
for (Student student : students)
{
System.out.println(student.toString() + " " + map.get(student.getIndex()));
}
}
`
public class PassedExams
{
private String code;
private Integer mark;
// get and set methods
// aswell as toString();
}
`
public class Student
{
private String name, surname;
private Integer index;
// get and set methods
// aswell as toString();
}
EDIT: Adding input and output
What is seen by default:
Student Name: John Surname: Doe Index: 1000 [Predmet: Code: CS102 Mark: 6, Predmet: Code: CS220 Mark: 8]
Student Name: Michael Surname: Hawk Index: 2000 [Predmet: Code: MA101 Mark: 10, Predmet: Code: CS101 Mark: 7]
Student Name: Nicholas Surname: Johnson Index: 3000 [Predmet: Code: CS115 Mark: 9, Predmet: Code: MA102 Mark: 7]
What should be seen after sort:
Student Name: Michael Surname: Hawk Index: 2000 [Predmet: Code: MA101 Mark: 10, Predmet: Code: CS101 Mark: 7]
Student Name: Nicholas Surname: Johnson Index: 3000 [Predmet: Code: CS115 Mark: 9, Predmet: Code: MA102 Mark: 7]
Student Name: John Surname: Doe Index: 1000 [Predmet: Code: CS102 Mark: 6, Predmet: Code: CS220 Mark: 8]
And total average mark:
Total average mark from students is: 7.83
Also I guess I should change from Integer to Double because of the line above.
Draken is right, it's more elegant to model the passed exams list as property of a student. However, you can sort your students with the way things are.
When you want to define an order on a list in Java you can write a special Comparator:
//sorting starts here
Collections.sort(students, new Comparator<Student>() {
#Override
public int compare(Student o1, Student o2) {
double sum1 = 0, sum2 = 0;
for (PassedExams pe : map.get(o1.getIndex())) sum1+=pe.mark;
for (PassedExams pe : map.get(o2.getIndex())) sum2+=pe.mark;
sum1 /= map.get(o1.getIndex()).size();
sum2 /= map.get(o2.getIndex()).size();
return Double.compare(sum2, sum1);
}
});
Here's the elegant way to do it (I'm using Java 1.7, so please ignore the lack of predicates!)
Main
public class App {
public static void main(String[] args) {
new App();
}
public App()
{
ArrayList<Student> students = new ArrayList<Student>();
Student A = new Student("John", "Doe", 1000);
students.add(A);
Student B = new Student("Michael", "Hawk", 2000);
students.add(B);
Student C = new Student("Nicholas", "Johnson", 3000);
students.add(C);
for (Student student : students)
{
if (student.getIndex() == 1000)
{
student.getPassedExamList().add(new PassedExam("CS102", 6));
student.getPassedExamList().add(new PassedExam("CS220", 8));
}
if (student.getIndex() == 2000)
{
student.getPassedExamList().add(new PassedExam("MA101", 10));
student.getPassedExamList().add(new PassedExam("CS101", 7));
}
if (student.getIndex() == 3000)
{
student.getPassedExamList().add(new PassedExam("CS115", 9));
student.getPassedExamList().add(new PassedExam("MA102", 7));
}
}
for (Student student : students)
{
System.out.println(student.toString() + " " + student.getPassedExamList());
}
Collections.sort(students);
System.out.println("\nSorted\n");
for (Student student : students)
{
System.out.println(student.toString() + " " + student.getPassedExamList());
}
System.out.println("\nCalculating average\n");
double total = 0;
double count = 0;
for (Student student : students)
{
count += student.getPassedExamList().size();
total += student.getTotalMarks();
}
DecimalFormat df = new DecimalFormat("0.##");
System.out.println("Average is " + df.format(total / count));
}
}
Passed exam
public class PassedExam {
private String code;
private Integer mark;
public PassedExam(String code, int mark){
this.code = code;
this.mark = mark;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Integer getMark() {
return mark;
}
public void setMark(Integer mark) {
this.mark = mark;
}
#Override
public String toString() {
return "PassedExams{" +
"code='" + code + '\'' +
", mark=" + mark +
'}';
}
}
Student
public class Student implements Comparator<Student>, Comparable<Student> {
private String name, surname;
private Integer index;
private List<PassedExam> passedExamList = new ArrayList<PassedExam>();
public Student(String name, String surname, int index){
this.name = name;
this.surname = surname;
this.index = index;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public Integer getIndex() {
return index;
}
public void setIndex(Integer index) {
this.index = index;
}
public List<PassedExam> getPassedExamList() {
return passedExamList;
}
public int getTotalMarks(){
int total = 0;
for(PassedExam exam : passedExamList)
total += exam.getMark();
return total;
}
#Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", surname='" + surname + '\'' +
'}';
}
#Override
public int compare(Student o1, Student o2) {
return Integer.compare(o2.getTotalMarks(), o1.getTotalMarks());
}
#Override
public int compareTo(Student o) {
return Integer.compare(o.getTotalMarks(), this.getTotalMarks());
}
}
The thing that allows me to call Collections.sort() is the fact that I implement Comparable<Student> on the Student class. I then add the method compareTo() and state how I want it sorting. Since you wanted descending order, I've reverse the normal order of comparison. You can read more on Comparable here
I don't think you need a hashMap
First add all students in the list.
Implement a Comparator, the comparator would probably have a method: getExamsForStudent()
Then sort the list using Collections.sort(list, comparator).

Duplicate values in a hashSet

I am trying to count the number of combinations of 1, 5, 10 and 25 that sum to n. Given that I don't want any repetitions (like 1+5 = 6 and 5+1 = 6). I am using a hashSet. I implemented a class named ResultSet that saves the number of 1, 5, 10, and 25 in a solution and I overrode the equals method. However, for some reason, my solution hashSet keeps returning duplicate values. Why?
import java.util.HashSet;
public class Solution {
public static void main(String[] args) {
int N = 6;
int combinationsSolution = new Combine(N).getSolution();
System.out.println("N= " + N + " Number of solutions= " + combinationsSolution);
}
}
class Combine {
private int solution;
private int n;
private HashSet<ResultSet> cacheUnordered = new HashSet<ResultSet>();
public Combine(int N) {
this.n = N;
this.solution = solve(n);
}
public int getSolution() {
return solution;
}
public int solve(int N) {
solve(N, 0, 0, 0, 0);
for (ResultSet r:cacheUnordered){
System.out.println(r.toString());
}
return cacheUnordered.size();
}
public void solve(int N, int substracted1, int substracted5, int substracted10, int substracted25) {
if (N == 0) {
cacheUnordered.add(new ResultSet(substracted1, substracted5, substracted10, substracted25));
} else if (N > 0) {
solve(N - 1, substracted1 + 1, substracted5, substracted10, substracted25);
solve(N - 5, substracted1, substracted5 + 1, substracted10, substracted25);
solve(N - 10, substracted1, substracted5, substracted10 + 1, substracted25);
solve(N - 25, substracted1, substracted5, substracted10, substracted25 + 1);
}
}
}
class ResultSet {
private int numberOf1;
private int numberOf5;
private int numberOf10;
private int numberOf25;
public ResultSet(int num1, int num5, int num10, int num25) {
numberOf1 = num1;
numberOf5 = num5;
numberOf10 = num10;
numberOf25 = num25;
}
#Override
public String toString(){
String result;
result = numberOf1 + " " + numberOf5 + " " + numberOf10 + " " + numberOf25;
return result;
}
#Override
public boolean equals(Object r2) {
if (r2 == null) {
return false;
}
if (!(r2 instanceof ResultSet)) {
return false;
}
ResultSet rr = (ResultSet) r2;
if (rr.numberOf1 == this.numberOf1 && rr.numberOf5 == this.numberOf5
&& rr.numberOf10 == this.numberOf10 && rr.numberOf25 == this.numberOf25) {
System.out.println("Comparing " + this.toString() + " to " + rr.toString());
return true;
} else {
return false;
}
}
public int getNum1() {
return numberOf1;
}
public int getNum5() {
return numberOf5;
}
public int getNum10() {
return numberOf10;
}
public int getNum25() {
return numberOf25;
}
}
For your ResultSet class, you defined an equals() method but not a hashCode() method. You need both methods for HashSet to work correctly. Please see this explanation. (It talks about HashMap, but it also applies to HashSet.)
As JavaDoc Clearly Specified
Note that it is generally necessary to override the hashCode method
whenever this method is overridden, so as to maintain the general
contract for the hashCode method, which states that equal objects must
have equal hash codes.
and you have not followed it , that is why you get duplicates ,
Please Read How HashCode and Equals Work it will help you out to understand the above statement better

Categories

Resources