Handling an Array in Java (two columns) - java

For instance suppose I have the following String
String S = "5,a\n" +
"6,b\n" +
"9,a";
The format is always the same - one digit, then comma, then one character and then line end character.
For looping each row in String I use
for(String a : S.split("\\n")){}
I want to learn the character with highest amount, when grouped by character. For Instance, there is only one "b", so value is 6; whereas "a" has two lines, so its value is 5 + 9 = 14. Since 14 is maximum here, I want to find out "a" and 14 and save them in variables.

You can do something like below :
public static void main (String[] args) throws java.lang.Exception
{
String S = "5,a\n" +
"6,b\n" +
"9,a";
String[] lines = S.split("\\n");
Map<String, Integer> map = new HashMap<String, Integer>();
for( String t : lines )
{
String[] e = t.split(",");
Integer digit = Integer.parseInt(e[0]);
String c = e[1];
if ( map.get(c) != null )
{
Integer val = map.get(c);
val += digit;
map.put( c, val );
}
else
{
map.put( c, digit );
}
}
int max = 0;
String maxKey = null;
for ( String k : map.keySet() )
{
if ( map.get(k) > max )
{
max = map.get(k);
maxKey = k;
}
}
System.out.println("The maximum key is : " + maxKey );
System.out.println("The maximum value is : " + max );
}
Output is :
The maximum key is : a
The maximum value is : 14

Use a HashMap to store each pair, with the letter as the key. If the entry doesn't exist, put the first number. If it exists, get the entry and add the number, and then put the sum.
import java.util.HashMap;
import java.util.Map;
public class ParseTest {
public static void main(String[] args) {
String S = "5,a\n" + "6,b\n" + "9,a";
String maxKey = null;
int maxVal = 0;
Map<String, Integer> sums = new HashMap<>();
for (String a : S.split("\\n")) {
String[] split = a.split(",");
int value = Integer.parseInt(split[0]);
String key = split[1];
if (sums.containsKey(key)) {
sums.put(key, sums.get(key) + value);
} else {
sums.put(key, value);
}
if (sums.get(key) > maxVal) {
maxVal = sums.get(key);
maxKey = key;
}
}
System.out.println("Max key: " + maxKey + ", Sum: " + maxVal);
}
}

After finishing my answer, I found that many similar answers have been posted out :). Anyway, my solution:
public static void main(String[] args) {
String S = "5,a\n6,b\n9,a";
Map<String, Integer> map = new HashMap<String, Integer>();
String highestAmountChar = "";
int highestAmount = 0;
for (String str : S.split("\\n")) {
String[] amountChar = str.split(",");
if (map.get(amountChar[1]) == null) {
map.put(amountChar[1], Integer.parseInt(amountChar[0]));
} else {
map.put(amountChar[1], map.get(amountChar[1]) + Integer.parseInt(amountChar[0]));
}
if (highestAmount < map.get(amountChar[1])) {
highestAmount = map.get(amountChar[1]);
highestAmountChar = amountChar[1];
}
}
System.out.println("The character " + highestAmountChar + " has highest amount " + highestAmount);
}

You could use something like this without using HashMap or any collection for that matter
import java.util.Arrays;
public class Test {
public static void main(String args[]) {
String S = "5,a\n" +
"6,b\n" +
"9,a";
// Separate the string by number and letter
String[] separated = S.split("\\n");
// Create a new array to store the letters only
char[] letters = new char[separated.length];
// Write the letter
for (int i = 0; i < letters.length; i++) {
letters[i] = separated[i].charAt(2);
}
// Sort them haha
Arrays.sort(letters);
// And now find out which letter is repeated most
// Store the first letter
char previous = letters[0];
// Make it the most repeated one for now
char mostRepeated = letters[0];
int count = 1;
int maxCount = 1;
for (int i = 1; i < letters.length; i++) {
// since the array is sorted if the actual letter is the same as the previous one then keep counting
if (letters[i] == previous)
count++;
else {
if (count > maxCount) {
mostRepeated = letters[i - 1];
maxCount = count;
}
previous = letters[i];
count = 1;
}
}
char answer = count > maxCount ? letters[letters.length-1] : mostRepeated;
// Once you get the letter now just add all the numbers that goes with it
int sum = 0;
for (String s:separated) {
if (s.charAt(2) == answer) {
sum += Character.getNumericValue(s.charAt(0));
}
}
// Print the result by printing the letter and it sum
}
}

Related

How to refacor a code use only loops and simple arrays?

I wrote that code and it's working. But I need to refactor it. I can use only simple methods for solving the problem, for example: "for" loops and simple array.
public class Anagram {
public static void main(String[] args) throws IOException {
Anagram anagrama = new Anagram();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));) {
System.out.println("Enter word or phrase: ");
String userText = reader.readLine();
String resultAnagrama = anagrama.makeAnagram(userText);
System.out.println("Result of Anagrama : " + resultAnagrama);
}
}
This method take user's text and make anagram, but all non-letters should stay on the same places
/**
* #param text
* #return reversed text and all non-letter symbols stay on the same places
*/
public String makeAnagram(String text) {
HashMap<Integer, Character> mapNonLetters;
String[] textFragments = text.split(" ");
StringBuilder stringBuilder = new StringBuilder();
//Check each elements of array for availability symbols and make reverse of elements
for (int i = 0; i < textFragments.length; i++) {
char[] arrayCharacters = textFragments[i].toCharArray();
mapNonLetters = saerchNonLetters(arrayCharacters); // search symbols
StringBuilder builderAnagramString = new StringBuilder(textFragments[i]);
//Delete all non-letters from element of array
int reindexing = 0;
for (HashMap.Entry<Integer, Character> entry : mapNonLetters.entrySet()) {
int key = entry.getKey();
builderAnagramString.deleteCharAt(key - reindexing);
reindexing ++;
}
builderAnagramString.reverse();
//Insert all non-letters in the same places where ones stood
for (HashMap.Entry<Integer, Character> entry : mapNonLetters.entrySet()) {
int key = entry.getKey();
char value = entry.getValue();
builderAnagramString.insert(key, value);
}
textFragments[i] = builderAnagramString.toString();
stringBuilder.append(textFragments[i]);
if (i != (textFragments.length - 1)) {
stringBuilder.append(" ");
}
mapNonLetters.clear();
}
return stringBuilder.toString();
}
This method search all non-letters from each worв of user's text
/**
* Method search symbols
* #param arrayCharacters
* #return HashMap with symbols found from elements of array
*/
public HashMap<Integer, Character> saerchNonLetters(char[] arrayCharacters) {
HashMap<Integer, Character> mapFoundNonLetters = new HashMap<Integer, Character>();
for (int j = 0; j < arrayCharacters.length; j++) {
//Letters lay in scope 65-90 (A-Z) and 97-122 (a-z) therefore other value is non-letter
if (arrayCharacters[j] < 65 || (arrayCharacters[j] > 90 && arrayCharacters[j] < 97) ||
arrayCharacters[j] > 122) {
mapFoundNonLetters.put(j, arrayCharacters[j]);
}
}
return mapFoundNonLetters;
}
}
public class Anagram {
public static void main(String[] args) {
String text = "!Hello123 ";
char[] chars = text.toCharArray();
int left = 0;
int right = text.length() - 1;
while (left < right) {
boolean isLeftLetter = Character.isLetter(chars[left]);
boolean isRightLetter = Character.isLetter(chars[right]);
if (isLeftLetter && isRightLetter) {
swap(chars, left, right);
left++;
right--;
} else {
if (!isLeftLetter) {
left++;
}
if (!isRightLetter) {
right--;
}
}
}
String anagram = new String(chars);
System.out.println(anagram);
}
private static void swap(char[] chars, int index1, int index2) {
char c = chars[index1];
chars[index1] = chars[index2];
chars[index2] = c;
}
}
If I understand correctly and you need only 1 anagram, this should work:
String originalString = "This is 1 sentence with 2 numbers!";
System.out.println("original: "+originalString);
// make a mask to keep track of where the non letters are
char[] mask = originalString.toCharArray();
for(int i=0; i<mask.length; i++)
mask[i] = Character.isLetter(mask[i]) ? '.' : mask[i];
System.out.println("mask: "+ new String(mask));
// remove non letters from the string
StringBuilder sb = new StringBuilder();
for(int i=0; i< originalString.length(); i++) {
if(mask[i] == '.')
sb.append(originalString.charAt(i));
}
// find an anagram
String lettersOnlyAnagram = sb.reverse().toString();
// reinsert the non letters at their place
int letterIndex = 0;
for(int i=0; i<mask.length; i++) {
if(mask[i] == '.') {
mask[i] = lettersOnlyAnagram.charAt(letterIndex);
letterIndex++;
}
}
String anagram = new String(mask);
System.out.println("anagram: "+ anagram);
It prints out:
original: This is 1 sentence with 2 numbers!
mask: .... .. 1 ........ .... 2 .......!
anagram: sreb mu 1 nhtiwecn etne 2 ssisihT!

Evil Hangman Java Program

I am working on a Evil Hangman Program And for some reason I am getting this error:
What length word do you want to use? 4
How many wrong answers allowed? 4
guesses : 4
guessed : []
current : ----
Your guess? e
Exception in thread "main" java.lang.NullPointerException
at Game.HangmanManager.record(HangmanManager.java:142)
at Game.HangmanMain.playGame(HangmanMain.java:62)
at Game.HangmanMain.main(HangmanMain.java:42)
Here is my program:
package Game;
import java.util.*;
public class HangmanManager
{
private String pattern;
private int max;
private int length;
private SortedSet<Character> guessesMade;
private Set<String> currentWords;
private Map<String, Set<String>> patternMap;
public HangmanManager(List<String> dictionary , int length, int max)
{
this.max = max;
this.length = length;
if( length < 1 && max < 0)
{
throw new IllegalArgumentException();
}
words = new TreeSet<String>();
guessesMade = new TreeSet<Character>();
currentWords = new TreeSet<String>(); // current words =(words)
patternMap = new TreeMap<String, Set<String>>(); // patternMAP = < pattern, words>
for (String word : dictionary)
{
if (word.length() == length)
{
words.add(word); // if length of the word matches a word with the same length it will be added
}
}
}
public Set<String> words()
{
return words;
}
public int guessesLeft()
{
return max - guessesMade.size();
}
public SortedSet<Character> guesses()
{
return guessesMade;
}
public String pattern()
{
if (words.isEmpty())
{
throw new IllegalArgumentException("Invalid No Words");
}
pattern = " "; // blank for now
for (int i = 0; i < length; i++)
{
pattern += "-"; // will have a "-" for how long the length of the word is
}
return pattern; // will return the number of lines
}
public int record(char guess)
{
if (guessesLeft() < 1 || words.isEmpty())
{
throw new IllegalStateException();
}
if (!words.isEmpty() && guessesMade.contains(guess))
{
throw new IllegalArgumentException();
}
guessesMade.add(guess); // guess
int occurences = 0;
for( String word: words)
{
if( patternMap.containsKey (pattern))
{
occurences = generatePattern(word, guess); // the word including the guess letter will fill in the blank spots
currentWords.add(word); // the word will be added to the possibilities
currentWords = patternMap.get(pattern); // the word will be able to fill once the guesses are made
// if(patternMap.get(pattern)!=null)
// {
// currentWords = patternMap.get(pattern);
//
// }
patternMap.put(pattern, currentWords);
}
else
{
currentWords.add(word);
patternMap.put(pattern, currentWords);
}
}
words = find();
return occurences;
}
private Set<String> find()
{
int maxSize = 0;
Map <String, Integer> patternCount = new TreeMap<String, Integer>();
for (String key : patternMap.keySet()) // keyset equals word
{
patternCount.put(key, patternMap.get(key).size()); // size of the word
if (patternMap.get(key).size() > maxSize)
{
maxSize = patternMap.get(key).size();
pattern = key; // pattern will becomes based on the word
} else if (patternMap.get(key).size() == maxSize)
{
if (key.length() >= pattern.length())
{
pattern = key;
maxSize = patternMap.get(key).size(); // the pattern is now the word key
}
}
}
System.out.println("Current pattern: " + pattern);
return patternMap.get(pattern); // the pattern that will becomes now that the word was picked
}
private int generatePattern(String s, char guess)
{
int count = 0;
pattern = "";
for (int i = 0; i < length; i++)
{
if (s.charAt(i) == guess)
{
pattern += guess + " ";
count++;
} else
{
pattern += "- ";
}
}
return count;
}
}
The error seems to happen in the record method for the :
patternMap.put(pattern, currentWords); on Line 149
I ran the debugger numerous times and I do notice that if you follow the program you will see that currentWords becomes Null eventually after the program runs through the words after one time even though I instantiate it and I created a Map for patternMap.
If anyone can tell me what to do or what to change I will really appreciate it because I am so lost with this
patternMap is a TreeMap. As you said, your problem is with patternMap.put(pattern, currentWords); on line 149. According to the JavaDocs for TreeMap, put() throws NullPointerException...
if the specified key is null and this map uses natural ordering, or its comparator does not permit null keys
Since a TreeMap<String,Object> uses natural ordering of it's keys (i.e. String), the problem is that pattern is null. Why don't you just initialize pattern to a default value:
private String pattern = " ";

get the two most used words in sentence in java

How do I get the two most used words in a sentence for example here after it count the total number of appearances of all the words it should also display the two most used words
import javax.swing.*;
import java.util.*;
import java.awt.event.*;
import java.util.Map;
import java.util.HashMap;
public class Tokenizer
{
public static void main(String[] args)
{
int index = 0; int tokenCount; int i =0;
Map<String,Integer> wordCount = new HashMap<String,Integer>();
Map<Integer,Integer> letterCount = new HashMap<Integer,Integer>();
String message="The Quick brown fox jumps over the lazy brown dog";
StringTokenizer string = new StringTokenizer(message);
tokenCount = string.countTokens();
System.out.println("Number of tokens = " + tokenCount);
while (string.hasMoreTokens()) {
String word = string.nextToken().toLowerCase();
Integer count = wordCount.get(word);
Integer lettercount = letterCount.get(word);
if(count == null) {
wordCount.put(word, 1);
}
else {
wordCount.put(word, count + 1);
}
}
for (String words : wordCount.keySet())
{System.out.println("Word : " + words + " has count :" +wordCount.get(words));
}
}
Iterate thorough the HashMap and then keep track of the highest counts.
int first, second;
first = second = Integer.MIN_VALUE;
String firstWord, secondWord;
for (Map.Entry<String, Integer> entry : map.entrySet())
{
int count = entry.getValue();
String word = entry.getKey();
if (count > first)
{
second = first;
secondWord = firstWord;
first = count;
firstWord = word;
}
else if (count > second && count != first)
{
second = count;
secondWord = word;
}
}
System.out.println(firstWord + " " + first);
System.out.println(secondWord + " " + second);
You need to iterate over map's entry set.
This will return you entry object which will contain key and max value.
Map.Entry<String, Integer> max = null;
for (Map.Entry<String, Integer> entry : map.entrySet())
{
if (max == null || entry.getValue().compareTo(max .getValue()) > 0)
{
max = entry;
}
}
For second most used word,i would say you can remove the max one and then again from this way,you can retrieve second one.

Count Occurrence of each letter in a loop and display with letter with the most number of occurences

I'm having trouble in using this code I found on the net. my goal is to count the number of times a letter show and display the letter with the most occurrence and if there are 2 or more letters that occurred at the same number of times then they will both show up.
This is my current output:
Current Output
Here is the code i found on the net and working with:
public void fcount(String str)
{
int[] occurence = new int[255];
// Scanner scanner = new Scanner(System.in);
// str = scanner.nextLine();
// optional to put eveyting in uppercase
str = str.toUpperCase();
// convert to char
char[] digit = str.toCharArray();
// count
for(int i = 0; i < digit.length; i++)
occurence[digit[i]]++;
// find max
int max = 0; // max value
char maxValue = 0; // max index
for(int i = 0; i < occurence.length; i++)
{
// new max ?
if(occurence[i] > max) {
max = occurence[i];
maxValue = (char) i;
}
}
// result
System.out.println("Character used " + max + " times is: " + (char) maxValue);
// return "";
}
And Here is the the loop where i'm using it:
public void calpha()
{
char startUpper = 'A';
String cones = null;
for (int i = 0; i < 12; i++) {
cones = Character.toString(startUpper);
System.out.println(startUpper);
}
fcount(cones);
}
There is an error in you loop:
cones = Character.toString(startUpper);
You are just re-assigning the value of cones, so fcount receives a string containing only the last character.
A solution is
cones += Character.toString(startUpper);
You have an issue in your int[] occurence = new int[255]; statement and usage: occurence[digit[i]]++ may lead to IndexOutOfBoundsException since char type is up to 2^16
Your code can not deal with non-ANSII characters. Mine does.
import java.util.*;
class Problem {
public static void main(String args[]) {
final String input = "I see trees outside of my window.".replace(" ", "");
final List<Character> chars = new ArrayList<>(input.length());
for (final char c : input.toCharArray()) {
chars.add(c);
}
int maxFreq = 0;
final Set<Character> mostFrequentChars = new HashSet<>();
for(final char c : chars) {
final int freq = Collections.frequency(chars, c);
if (freq > maxFreq) {
mostFrequentChars.clear();
mostFrequentChars.add(c);
maxFreq = freq;
}
else {
if (freq == maxFreq) {
mostFrequentChars.add(c);
}
}
}
for (Character c : mostFrequentChars) {
System.out.println(c);
}
}
}
Try this code:
public static void main(String[] args) throws IOException {
char startUpper = 'A';
String cones = "";
for (int i = 0; i < 12; i++) {
cones += Character.toString(startUpper);
System.out.println(startUpper);
}
fcount(cones);
}
public static void fcount(String str) {
HashMap<Character, Integer> hashMap = new HashMap<Character, Integer>();
HashSet<Character> letters = new HashSet<Character>();
str = str.toUpperCase();
//Assume that string str minimium has 1 char
int max = 1;
for (int i = 0; i < str.length(); i++) {
int newValue = 1;
if (hashMap.containsKey(str.charAt(i))) {
newValue = hashMap.get(str.charAt(i)) + 1;
hashMap.put(str.charAt(i), newValue);
if (newValue>=max) {
max = newValue;
letters.add(str.charAt(i));
}
} else {
hashMap.put(str.charAt(i), newValue);
}
}
System.out.println("Character used " + max + " times is: " + Arrays.toString(letters.toArray()));
// return "";
}

sub arraylist's size isn't correct

After hard searchig I still haven't found the proper answer for my question and there is it:
I have to write a java program that enters an array of strings and finds in it the largest sequence of equal elements. If several sequences have the same longest length, the program should print the leftmost of them. The input strings are given as a single line, separated by a space.
For example:
if the input is: "hi yes yes yes bye",
the output should be: "yes yes yes".
And there is my source code:
public static void main(String[] args) {
System.out.println("Please enter a sequence of strings separated by spaces:");
Scanner inputStringScanner = new Scanner(System.in);
String[] strings = inputStringScanner.nextLine().split(" ");
System.out.println(String.join(" ", strings));
ArrayList<ArrayList<String>> stringsSequencesCollection = new ArrayList<ArrayList<String>>();
ArrayList<String> stringsSequences = new ArrayList<String>();
stringsSequences.add(strings[0]);
for (int i = 1; i < strings.length; i++) {
if(strings[i].equals(strings[i - 1])) {
stringsSequences.add(strings[i]);
} else {
System.out.println(stringsSequences + " " + stringsSequences.size());
stringsSequencesCollection.add(stringsSequences);
stringsSequences.clear();
stringsSequences.add(strings[i]);
//ystem.out.println("\n" + stringsSequences);
}
if(i == strings.length - 1) {
stringsSequencesCollection.add(stringsSequences);
stringsSequences.clear();
System.out.println(stringsSequences + " " + stringsSequences.size());
}
}
System.out.println(stringsSequencesCollection.size());
System.out.println(stringsSequencesCollection.get(2).size());
System.out.println();
int maximalStringSequence = Integer.MIN_VALUE;
int index = 0;
ArrayList<String> currentStringSequence = new ArrayList<String>();
for (int i = 0; i < stringsSequencesCollection.size(); i++) {
currentStringSequence = stringsSequencesCollection.get(i);
System.out.println(stringsSequencesCollection.get(i).size());
if (stringsSequencesCollection.get(i).size() > maximalStringSequence) {
maximalStringSequence = stringsSequencesCollection.get(i).size();
index = i;
//System.out.println("\n" + index);
}
}
System.out.println(String.join(" ", stringsSequencesCollection.get(index)));
I think it should be work correct but there is a problem - the sub array list's count isn't correct: All the sub arrayList's size is 1 and for this reason the output is not correct. I don't understand what is the reason for this. If anybody can help me to fix the code I will be gratefull!
I think it is fairly straight forward just keep track of a max sequence length as you go through the array building sequences.
String input = "hi yes yes yes bye";
String sa[] = input.split(" ");
int maxseqlen = 1;
String last_sample = sa[0];
String longest_seq = last_sample;
int seqlen = 1;
String seq = last_sample;
for (int i = 1; i < sa.length; i++) {
String sample = sa[i];
if (sample.equals(last_sample)) {
seqlen++;
seq += " " + sample;
if (seqlen > maxseqlen) {
longest_seq = seq;
maxseqlen = seqlen;
}
} else {
seqlen = 1;
seq = sample;
}
last_sample = sample;
}
System.out.println("longest_seq = " + longest_seq);
Lots of issues.
First of all, when dealing with the last string of the list you are not actually printing it before clearing it. Should be:
if(i == strings.length - 1)
//...
System.out.println(stringsSequences + " " + stringsSequences.size());
stringsSequences.clear();
This is the error in the output.
Secondly, and most importantly, when you do stringsSequencesCollection.add you are adding an OBJECT, i.e. a reference to the collection. When after you do stringsSequences.clear(), you empty the collection you just added too (this is because it's not making a copy, but keeping a reference!). You can verify this by printing stringsSequencesCollection after the first loop finishes: it will contain 3 empty lists.
So how do we do this? First of all, we need a more appropriate data structure. We are going to use a Map that, for each string, contains the length of its longest sequence. Since we want to manage ties too, we'll also have another map that for each string stores the leftmost ending position of the longest sequence:
Map<String, Integer> lengths= new HashMap<>();
Map<String, Integer> indexes= new HashMap<>();
String[] split = input.split(" ");
lengths.put(split[0], 1);
indexes.put(split[0], 0);
int currentLength = 1;
int maxLength = 1;
for (int i = 1; i<split.length; i++) {
String s = split[i];
if (s.equals(split[i-1])) {
currentLength++;
}
else {
currentLength = 1;
}
int oldLength = lengths.getOrDefault(s, 0);
if (currentLength > oldLength) {
lengths.put(s, currentLength);
indexes.put(s, i);
}
maxLength = Math.max(maxLength, currentLength);
}
//At this point, youll have in lengths a map from string -> maxSeqLengt, and in indexes a map from string -> indexes for the leftmost ending index of the longest sequence. Now we need to reason on those!
Now we can just scan for the strings with the longest sequences:
//Find all strings with equal maximal length sequences
Set<String> longestStrings = new HashSet<>();
for (Map.Entry<String, Integer> e: lengths.entrySet()) {
if (e.value == maxLength) {
longestStrings.add(e.key);
}
}
//Of those, search the one with minimal index
int minIndex = input.length();
String bestString = null;
for (String s: longestStrings) {
int index = indexes.get(s);
if (index < minIndex) {
bestString = s;
}
}
System.out.println(bestString);
Below code results in output as you expected:
public static void main(String[] args) {
System.out.println("Please enter a sequence of strings separated by spaces:");
Scanner inputStringScanner = new Scanner(System.in);
String[] strings = inputStringScanner.nextLine().split(" ");
System.out.println(String.join(" ", strings));
List <ArrayList<String>> stringsSequencesCollection = new ArrayList<ArrayList<String>>();
List <String> stringsSequences = new ArrayList<String>();
//stringsSequences.add(strings[0]);
boolean flag = false;
for (int i = 1; i < strings.length; i++) {
if(strings[i].equals(strings[i - 1])) {
if(flag == false){
stringsSequences.add(strings[i]);
flag= true;
}
stringsSequences.add(strings[i]);
}
}
int maximalStringSequence = Integer.MIN_VALUE;
int index = 0;
List <String> currentStringSequence = new ArrayList<String>();
for (int i = 0; i < stringsSequencesCollection.size(); i++) {
currentStringSequence = stringsSequencesCollection.get(i);
System.out.println(stringsSequencesCollection.get(i).size());
if (stringsSequencesCollection.get(i).size() > maximalStringSequence) {
maximalStringSequence = stringsSequencesCollection.get(i).size();
index = i;
//System.out.println("\n" + index);
}
}
System.out.println(stringsSequences.toString());

Categories