Reputation: 19
I am attempting a Kata from codewars. Here are the given directions from the kata: "Given two strings s1 and s2, we want to visualize how different the two strings are. We will only take into account the lowercase letters (a to z). First let us count the frequency of each lowercase letters in s1 and s2.
s1 = "A aaaa bb c"
s2 = "& aaa bbb c d"
s1 has 4 'a', 2 'b', 1 'c'
s2 has 3 'a', 3 'b', 1 'c', 1 'd'
So the maximum for 'a' in s1 and s2 is 4 from s1; the maximum for 'b' is 3 from s2. In the following we will not consider letters when the maximum of their occurrences is less than or equal to 1."
I managed to get only the lowercase letters into arrays from the strings but I am stuck on how to compare the two arrays where each letter has the max occurrences and build a string. If you have any advice at all, it is greatly appreciated! Here is my code:
public class Mix {
public static void main(String[] args){
mix("1aaAAB ", "cabBbB");
}
public static String mix(String s1, String s2) {
int count1[] = new int[256]; //Number of characters that were found
int count2[] = new int[256];
int length1 = s1.length();
int length2 = s2.length();
char char1[] = new char[s1.length()];
char char2[] = new char[s2.length()];
for(int i = 0; i < length1; i++){
if(Character.isLowerCase(s1.charAt(i))){
char1[i] = s1.charAt(i);
int found1 = 0; //found = 1 if it is found. found = 0 if not found
for(int j = 0; j <= i; j++){
if(s1.charAt(i) == char1[j]){
found1++;
}
}
}
} //Char[i] has lowercase letters
for(int i = 0; i < length2; i++){
if(Character.isLowerCase(s2.charAt(i))){
char2[i] = s2.charAt(i);
int found2 = 0;
for(int j = 0; j <= i; j++){
if(s2.charAt(i) == char2[j]){
found2++;
}
}
}
} //Char[i] has lowercase letters
//////////////////////////
for(int i = 0; i < char1.length; i++){
if(char1[i] != 0){
count1[char1[i]]++;
System.out.println("There are " + count1[char1[i]] + " of the letter " + char1[i]);
}
}
for(int j = 0; j < char2.length; j++){
if(char2[j] != 0){
count2[char2[j]]++;
System.out.println("There are " + count2[char2[j]] + " of the letter " + char2[j]);
}
}
/*
This is where my problems begin. my char1 and char2 arrays contain the lower case letters.
I don't know how to do this part though.
*/
StringBuilder result = new StringBuilder();
int index = 0;
for(int i = 0; i < char1.length; i++){
for(int j = 0; j < char2.length; j++){
if(char1[i] == char2[j]){
System.out.println("Char1 at i: " + char1[i] + " char2 at j: " + char2[j]);
if(count1[char1[i]] > count2[char2[j]]){
for(int k = 0; k < count1[char1[i]]; k++){
result.append(char1[i]);
}
} else if(count1[char1[i]] < count2[char2[j]]){
for(int l = 0; l < count2[char2[j]]; l++){
result.append(char2[j]);
}
} else{
for(int h = 0; h < count1[char1[i]]; h++){
result.append(char1[i]);
}
}
}
}
}
return "End"; //This return is arbitrary for right now
}
}
Upvotes: 0
Views: 467
Reputation: 401
It would be best to use a HashMap where the key is the character and the value is the number of occurrences
Filling the map would be like this: (I'm using my memory here so it might have a typing error)
char c = s1.indexAt(i);
if(map.contains(c)) {
map.put(c, map.get(c)++);
}else {
map.put(c,1);
}
Once filling both Maps, you can keep only 1 by updating the value of the keys found in both HashMaps to the Max value of both.
import java.util.HashMap;
import java.util.Map;
public class Mix {
public static void main(String[] args) {
System.out.println( mix("A aaaa bb c", "& aaa bbb c d") );
}
public static String mix(String s1, String s2) {
Map<Character, Integer> firstStringCharsOccurences = new HashMap<>();
Map<Character, Integer> secondStringCharsOccurences = new HashMap<>();
Map<Character, Integer> total = new HashMap<>();
for(int i=0; i<s1.length(); i++) {
if (Character.isLowerCase(s1.charAt(i))) {
/*
* it will put a pair into the map with the char at index i as key and the value either the old value+1
* if it already exist, or if this is the first occurrence of this character it will put 0+1
*/
firstStringCharsOccurences.put(s1.charAt(i),
firstStringCharsOccurences.getOrDefault(s1.charAt(i), 0) + 1);
}
}
for(int i=0; i<s2.length(); i++) {
if (Character.isLowerCase(s2.charAt(i))) {
secondStringCharsOccurences.put(s2.charAt(i),
secondStringCharsOccurences.getOrDefault(s2.charAt(i), 0) + 1);
}
}
for( Character c: secondStringCharsOccurences.keySet() ) {
total.put(c,
Math.max(firstStringCharsOccurences.getOrDefault(c, 0),secondStringCharsOccurences.get(c)));
}
for( Character c: firstStringCharsOccurences.keySet() ) {
total.put(c,
Math.max(secondStringCharsOccurences.getOrDefault(c, 0),firstStringCharsOccurences.get(c)));
}
StringBuilder answer = new StringBuilder();
for( Character c: total.keySet() ) {
char stringWithMostOccurrences = firstStringCharsOccurences.getOrDefault(c, 0) > secondStringCharsOccurences.getOrDefault(c, 0) ? '1' :
( firstStringCharsOccurences.getOrDefault(c, 0) < secondStringCharsOccurences.getOrDefault(c, 0) ? '2' : '=' );
answer.append(stringWithMostOccurrences);
answer.append(':');
for(int i=0; i< total.get(c) ; i++) {
answer.append(c);
}
answer.append('/');
}
return answer.toString();
}
}
One thing to mention, I didn't add the characters that aren't lower case to the final output.
Upvotes: 1
Reputation: 1
The best way to proceed are HashMaps.
Here my solution:
A method that convert a String into an HashMap. I used the merge method to avoid the check of the key.
private HashMap<Character, Integer> stringToHashMap(String s){
HashMap<Character, Integer> hashMap = new HashMap<>();
for (char c: s.toCharArray()){
if (Character.isLowerCase(c)){
hashMap.merge(c, 1, (a, b) -> a + b );
}
}
return hashMap;
}
A method that convert an HashMap into a String.
private String hashMapToString(HashMap<Character, Integer> hashMap){
StringBuilder result = new StringBuilder();
for (Map.Entry<Character,Integer> me : hashMap.entrySet()) {
for (int i= 0; i < me.getValue(); i++){
result.append(me.getKey());
}
}
return result.toString();
}
And here the method that calls the two helpers and merge the two HashMaps.
public String solution(String s1, String s2){
HashMap<Character, Integer> s1Map = stringToHashMap(s1);
HashMap<Character, Integer> s2Map = stringToHashMap(s2);
s2Map.forEach((key, value) -> s1Map.merge(key, value, Math::max));
return hashMapToString(s1Map);
}
Upvotes: 0