I have HashMap where key is bird specie and value is number of perceptions. Here is my code:
public class Program {
public static void main(String[] args) {
HashMap<String, Integer> species = new HashMap<>();
Scanner reader = new Scanner(System.in);
species.put("hawk (buteo jamaicensis)", 0);
species.put("eagle (aquila chrysaetos)", 0);
species.put("sparrow (passeridae)", 0);
System.out.println("Add perception");
System.out.println("What was perceived?"); //output should be "hawk"/"eagle"/"sparrow"
String perception = reader.nextLine();
// Change here the value of hashmap key.
ArrayList<String> list = new ArrayList<>();
for (HashMap.Entry<String, Integer> entry: species.entrySet()) {
System.out.println((entry.getKey()+" : "+entry.getValue()+" perception"));
}
}
My goal is to change key value to from 0 to 1, when scanner is asking what was perceived.
For example:
Scanner is asking "What was perceived?" and output is "hawk". Then the program should change key "hawk (buteo jamaicensis)" value from 0 to 1. So the goal output would be now:
sparrow (passeridae) : 0 perception
eagle (aquila chrysaetos) : 0 perception
hawk (buteo jamaicensis) : 1 perception
Use String.indexOf check if the input string is substring of the key, and if it is, set the new value:
// Change here the value of hashmap key.
for (HashMap.Entry<String, Integer> entry: species.entrySet()) {
if (entry.getKey().indexOf(perception) >= 0) {
entry.setValue(entry.getValue() + 1);
}
for (HashMap.Entry<String, Integer> entry: species.entrySet()) {
if (entry.getKey().equals(perception)) {
entry.setValue(entry.getValue() + 1);
}
}
Related
I am trying to beat a sololearn challenge where we store the name of a player in a hashmap and then I am needed to iterate through the values of each player hashmap and get the name of the player with the highest score. I have been given a template code but do not have any idea on how to complete the class Bowling with a method called getWinner() to get the name of the player with the maximum points please help
import java.util.*;
public class Bowling {
HashMap<String, Integer> players;
Bowling() {
players = new HashMap<String, Integer>();
}
public void addPlayer(String name, int p) {
players.put(name, p);
}
//your code goes here
void getWinner(){
//help me complete this to get the name or the winner
}
}
public class Program {
public static void main(String[ ] args) {
Bowling game = new Bowling();
Scanner sc = new Scanner(System.in);
for(int i=0;i<3;i++) {
String input = sc.nextLine();
String[] values = input.split(" ");
String name = values[0];
int points = Integer.parseInt(values[1]);
game.addPlayer(name, points);
}
game.getWinner();
}
}
You get the entrySet (key, value), use a Comparator and compare them by the value and use Collections.max() to get the highest value. After this just get the key and you have the player name:
Collections.max(players.entrySet(), Comparator.comparingInt(Map.Entry::getValue)).getKey();
You can get all key from a map with keySet() and so get the values associated to the key. So here a key would be the name of a player and the values is score.
So here is a simple answer if there is no tie :).
void getWinner(){
int currentBestScore = 0;
String currentWinner = "nobody"
for ( String playerName : players.keySet() ) {
if(players.get(playerName)>=currentBestScore){
currentWinner = playerName;
}
}
System.out.println(playerName);
}
Below are chunks of my code from my quiz program in Java. I am trying to read/write high scores to a file and sort the high score table.
public static void main(String[] args) throws IOException {
sort(highscoreTable);
int score1 = 0;
int score2 = 0;
int totalscore = 0;
int NumberofQuestions = 5;
// RECORDS TO STORE QUESTION, ANSWER WOULD BE HERE //
private static void start(int NumberofQuestions, String[] Answers, String[][] questions, int score1, int score2, int totalscore) throws IOException {
// DISPLAYED ON THE HOME SCREEN SO USER CAN CHOOSE WHAT THEY WANT TO DO
System.out.println("[0] Leave\n");
while(true) {
System.out.println("[1] Play");
System.out.println("[2] Highscore");
System.out.print("Enter Choice: ");
String useranswer = scanner.nextLine();
System.out.println();
if (useranswer.equals("1")) {
mainLoop(NumberofQuestions, Answers, questions, score1, score2, totalscore);
} else if (useranswer.equals("2")) {
sort(highscoreTable);
} else if (useranswer.equals("0")) {
try {
save();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
I wanted this bit to be displayed on the screen first, if the user presses 2, i wanted to program to read from the file and show the preious high scores
public static void save() throws IOException {
String aggFileName = "agg-"+String.valueOf("06.txt");
FileWriter fstream = new FileWriter(aggFileName);
BufferedWriter out = new BufferedWriter(fstream);
for (Map.Entry<String, String> entry : highscoreTable.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); //this statement prints out my keys and values
out.write(entry.getKey() + "--" + entry.getValue() + "\n");
System.out.println("Done");
out.flush(); // Flush the buffer and write all changes to the disk
}
out.close(); // Close the file
}
The save method works perfectly and I have no problem with it.
public static void mainLoop(int NumberofQuestions, String[]Answers, String[][] questions, int score1, int score2, int totalscore) throws IOException {
// USER WOULD ANSWER QUESTIONS HERE
addHighscore(name, totalscore);
}
public static void addHighscore(String name, int totalscore) throws IOException {
highscoreTable.put(String.valueOf(totalscore), name);
}
The function here adds the users name and total score to a treemap
public static void highscoreImport(HashMap highscoreTable) throws IOException {
String filePath = "agg-06.txt";
String line;
BufferedReader reader = new BufferedReader(new FileReader(filePath));
while ((line = reader.readLine()) != null)
{
String[] parts = line.split("--", 2);
if (parts.length >= 2)
{
String key = parts[0];
String value = parts[1];
highscoreTable.put(key, value);
} else {
}
}
for (Object key : highscoreTable.keySet())
{
System.out.println(key + "--" + highscoreTable.get(key));
}
reader.close();
}
This is the part I'm having issues with. I want the program to get the information from the file, and now merge it with the data that is coming from the users recent quiz, and then sort the scores (I want a high score table) so that when the users types "2" to see the high score table, it will be in descending order
public static void sort(HashMap highscoreTable) throws IOException {
System.out.println("Before Sorting:");
Set set = highscoreTable.entrySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()) {
Map.Entry me = (Map.Entry)iterator.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
Map<Integer, String> map = new TreeMap<Integer, String>(highscoreTable);
System.out.println("After Sorting:");
Set set2 = map.entrySet();
Iterator iterator2 = set2.iterator();
while(iterator2.hasNext()) {
Map.Entry me2 = (Map.Entry)iterator2.next();
System.out.print(me2.getKey() + ": ");
System.out.println(me2.getValue());
}
}
Here, the list outputted "before" and "after" sorting is the same unsorted list
Sorry for the long read, I would appreciate any help or pointers in fixing this.
Since in the addHighscore method you are doing:
highscoreTable.put(String.valueOf(totalscore), name);
I assume it is a Map<String, String> (both key and value types are String).
But in the sort method you do...
Map<Integer, String> map = new TreeMap<Integer, String>(highscoreTable);
If the types of highscoreTable are correctly defined, the TreeMap instantiation should fail at compiling time. If not, and as the constructor TreeMap(Map) gets ordered by the natural order of its keys (see Javadoc), it is probably ordering it by String order or other. So "111" will be before "12" and other unexpected results. It is a good practice to define the types in all the collections and other generic type classes.
The trouble is with the type of the score. You are inserting the score as a string. A second minor issue is the sort order should be reversed.
Look at the following example:
public class Test {
public static void main(String[] args) throws IOException {
System.out.println("String scores:");
HashMap<String, String> scores = new HashMap<>();
scores.put("12", "John");
scores.put("240", "Mary");
scores.put("14", "Sean");
scores.put("35", "Pat");
sort(scores);
System.out.println();
System.out.println("Integer scores:");
HashMap<Integer,String> integerScores = new HashMap<>();
integerScores.put(12, "John");
integerScores.put(240, "Mary");
integerScores.put(14, "Sean");
integerScores.put(35, "Pat");
sort(integerScores);
}
public static void sort(HashMap highscoreTable) throws IOException {
System.out.println("Before Sorting:");
Set set = highscoreTable.entrySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()) {
Map.Entry me = (Map.Entry)iterator.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
Map<Integer, String> map = new TreeMap<Integer, String>(Collections.reverseOrder()); // Descending
map.putAll(highscoreTable);
System.out.println("After Sorting:");
Set set2 = map.entrySet();
Iterator iterator2 = set2.iterator();
while(iterator2.hasNext()) {
Map.Entry me2 = (Map.Entry)iterator2.next();
System.out.print(me2.getKey() + ": ");
System.out.println(me2.getValue());
}
}
}
This example uses your sort method on 'scores', and 'integerScores'.
Here is the sorted output:
String scores:
35: Pat
240: Mary
14: Sean
12: John
Integer scores:
240: Mary
35: Pat
14: Sean
12: John
You can see in the first sort that 35 comes before 240, because 3 comes before 2. It is doing a string sort. The second sort is by the value of an integer. Once you understand this, it is easy to fix your code.
The original code inserts the key as a String:
highscoreTable.put(key, value);
The key should be an Integer:
highscoreTable.put(Integer.valueOf(key), value);
Also note that the provided answer can be easily run. It includes data (which is simpler that attaching a file), and output. When questions are formatted this way, it is easier to get help.
By calling a method ,at my case countInNumbers, is returning results as an array.
System.out.println(countIntInNumbers(Array));
result:
{1=17, 2=10, 3=16, 4=17, 5=13, 6=22, 7=10, 8=15, 9=16, 10=19, 11=11, 12=15, 13=16, 14=13, 15=19, 16=17, 17=13, 18=21, 19=19, 20=15,}
I try to separate the numbers on different table depending their total value.
Example... I want to display the numbers that their total is between 3 and 4 to separate table than the other numbers.
Facing this problem cause the results as you may notice are Map since i am new in Java and I am so confused at this point.
Anyone can suggest from something to start of?
Updated:::
countIntInNumbers method as follows
public static Map<Integer, Integer> countIntInNumbers(int[][] mat) {
Map<Integer, Integer> intOccurences = new HashMap<>();
for (int[] row : mat) {
for (int intInRow : row) {
Integer occurences = intOccurences.get(intInRow);
if (occurences == null) { // first occurrence
intOccurences.put(intInRow, 1);
} else { // increment
intOccurences.put(intInRow, occurences.intValue() + 1);
}
}
}
return intOccurences;
I try to separate the numbers on different table depending their total value. Example... I want to print all numbers that their total is between 3 and 4 to separate table than the other numbers.
We are not sure what you are asking here but if you mean that you want to display the numbers which have a total between 2 numbers then you could do something like:
private void printNumbers(Map<Integer, Integer> intOccurences, int minTotal, int maxTotal){
boolean first = false;
System.out.print("{");
for (Map.Entry<Integer, Integer> entry : intOccurences.entrySet()) {
int total = entry.getValue();
if (total >= minTotal && total <= maxTotal) {
if (first) {
first = false;
} else {
System.out.print(", ");
}
System.out.print(entry.getKey() + "=" + total);
}
}
System.out.print("}");
}
If you are taking about copying the values to a new map then maybe something like:
private Map<Integer, Integer> extractNumbers(Map<Integer, Integer> intOccurences,
int minTotal, int maxTotal) {
Map<Integer, Integer> result = new HashMap<>();
for (Map.Entry<Integer, Integer> entry : intOccurences.entrySet()) {
int total = entry.getValue();
if (total >= minTotal && total <= maxTotal) {
result.put(entry.getKey(), total);
}
}
// not sure if you want to remove the ones from the original map
return result;
}
If you want to compare the value of a map just get it by key. Then since the values of the map are of wrapper Integer you can compare using ==, >=, <= since the Integer equals() method simply compares the int value it wraps with the other Integer's int value. In example:
// Adding some test values to the map
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 5);
map.put(2, 6);
map.put(3, 5);
// Get values by key map.get(key)
// Compare values map.get(key) == map.get(key) or use >=, <=
System.out.println(map.get(1) <= map.get(2)); // true
System.out.println(map.get(1) == map.get(3)); // true
System.out.println(map.get(1) >= map.get(2)); // false
In your countIntInNumbers it seems you are just returning and printing the map by using its toString() method. If I got you right you want to print the keys which values are between 3 and 4. In this case the values are Integer so there will not be any value between 3 and 4 other than the integers themselves.
Okay after seeing your edit, convert your raw matrix to a map and then search for the values you need, and put them into a new map. Something like this:
public static Map<Integer, Integer> countIntInNumbers(int[][] mat) {
Map<Integer, Integer> matConvertedToMap = new HashMap<>();
for(int i=0; i<mat.length; i++)
{
matConvertedToMap.put(mat[i][0], mat[i][1]);
}
Map<Integer, Integer> intOccurences = new HashMap<>();
for (Map.Entry<Integer, Integer> entry : matConvertedToMap.entrySet())
{
if(entry.getValue() == 3 || entry.getValue() == 4)
{
intOccurences.put(entry.getKey(), entry.getValue());
}
}
return intOccurences;
}
Not sure what the comparison really is and what you are expected to return but that should give you a general feeling of how to iterate through the map.
So I have this program that calculates the sum of all the petshops with the same key but different values. However, now, I would like to calculate the average of each petshop with the same key. I was thinking about using a counter in order to get how many times a petshop is contained in the arraylist. But it does not work. would I need to run another for each loop?
public class AverageCost {
public void calc(ArrayList<Pet> pets) {
Map<String, Double> hm = new HashMap<>();
for (Pet i : pets) {
String name = i.getShop();
// If the map already has the pet use the current value, otherwise 0.
double price = hm.containsKey(name) ? hm.get(name) : 0;
price += i.getPrice();
hm.put(name, price);
}
System.out.println("");
for (String key : hm.keySet()) {
System.out.printf("%s: %s%n", key, hm.get(key));
}
}
What you are asking for is an algorithm to calculate the cumulative moving average without storing the number of terms you have so far accumulated. I don't think this is possible (for example see https://en.wikipedia.org/wiki/Moving_average#Cumulative_moving_average where 'n', the number of terms so far, is required). My suggestion is to use two passes - the first to store the numbers and the second to calculate the averages.
public void calc(List<Pet> pets) {
// First pass
Map<String, List<Double>> firstPass = new HashMap<>();
for (Pet pet : pets) {
String name = pet.getShop();
if (firstPass.containsKey(name)) {
firstPass.get(name).add(pet.getPrice());
} else {
List<Double> prices = new ArrayList<>();
prices.add(pet.getPrice());
firstPass.put(name, prices);
}
}
// Second pass
Map<String, Double> results = new HashMap<>();
for (Map.Entry<String, List<Double>> entry : firstPass.entrySet()) {
Double average = calcAverage(entry.getValue());
results.put(entry.getKey(), average);
// Print results
System.out.printf("%s: %s%n", entry.getKey(), average);
}
}
private double calcAverage(List<Double> values) {
double result = 0;
for (Double value : values) {
result += value;
}
return result / values.size();
}
You can introduce second map for counting or use compound value object in your map to hold both accumulated price and number of pets:
Map<String, PetStatistics> hm = new HashMap<>();
for (Pet i : pets) {
String name = i.getShop();
// If the map already has the pet use the current value, otherwise 0.
PetStatistics stats = hm.get(name);
if (stats == null) {
stats = new PetStatistics(0, 0); // count and price
hm.put(name, stats);
}
stats.addPrice(i.getPrice());
stats.incrementCount();
}
You can use the Collections.frequency to get the number of occurrence and divide the whole sum
for (String key : hm.keySet()) {
int w = Collections.frequency(pets, new Pet(key));
System.out.printf("%s: %s%n", key, hm.get(key)/w);
}
This simple game asks for the number of the players and their names and counts their score.How can i get the player with the highest score?
main:
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
HashMap<String,Integer> players= new HashMap<String,Integer>();
System.out.printf("Give the number of the players: ");
int numOfPlayers = scanner.nextInt();
for(int k=1;k<=numOfPlayers;k++)
{
System.out.printf("Give the name of player %d: ",k);
String nameOfPlayer= scanner.next();
players.put(nameOfPlayer,0);//score=0
}
//This for finally returns the score
for(String name:players.keySet())
{
System.out.println("Name of player in this round: "+name);
//::::::::::::::::::::::
//::::::::::::::::::::::
int score=players.get(name)+ p.getScore();;
//This will update the corresponding entry in HashMap
players.put(name,score);
System.out.println("The Player "+name+" has "+players.get(name)+" points ");
}
}
This what i tried myself:
Collection c=players.values();
System.out.println(Collections.max(c));
You can use Collections.max() to get the maximum value of the Collection of hashmap entries obtained by HashMap.entrySet() with custom comparator for comparing values.
Example:
HashMap<String,Integer> players= new HashMap<String,Integer>();
players.put("as", 10);
players.put("a", 12);
players.put("s", 13);
players.put("asa", 15);
players.put("asaasd", 256);
players.put("asasda", 15);
players.put("asaws", 5);
System.out.println(Collections.max(players.entrySet(),new Comparator<Entry<String, Integer>>() {
#Override
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
return o1.getValue().compareTo(o2.getValue());
}
}));
You can modify above code to best meet your condition.