Java count string index 0 in array - java

Im trying to keep track of occurrences of strings that start with certain letters in an array. Given the following array, count the number of occurrences of strings that start with "T", "B, and "A" for example..
String[] month_codes = {"July 2007", "TRUCKS", "APPLES", "BEANS", "COATS", "BANANA", "CODES"}
Output would look like this for each month:
T A B
July 2 1 2
Augu ....
Sept ....
This is the code I used but it only captures one occurrence
public static int extract_counts(String[] month_array){
for(int i=0; i < month_array.length; i++){
System.out.println(month_array[i]);
if(month_array[i].startsWith("T")){
july_ab++;
}
}
return july_ab;
}

What I would do is iterate through all of the items once, counting the number of occurrences. Then I'd print the results.
The easiest way to do this, in my opinion, would be to use an array of integers representing the 26 letters in the English alphabet:
int[] frequency = new int[26];
// frequency[0] is the number of words that start with A
Here, we can take advantage of the fact that Java initializes an integer arrays with all zeroes.
Then we'd iterate through the month_array and count how many words start with each letter.
for( String word : month_array ) {
char firstLetter = word.toLowerCase().charAt(0);
int index = firstLetter - 'a'; // a = 0, b = 1, etc.
frequency[index]++;
}
At the end of this for-loop, the frequency array now contains how many words start with each letter. We could print them like this:
for(int i = 0; i < 26; i++) {
System.out.print( frequency[i] );
}
Of course, this would be in order from A to Z. You'd also probably want to print the headers with the letters A-Z first before iterating through your months.
In your example, your first word is "July 2007" -- of course you'd need to omit this first item before counting since you'd otherwise be artificially incrementing (for example) the 'J' counter.
public int[] extractCounts( String[] month_array ) {
int[] frequency = new int[26];
for(int i = 1; i < month_array.length; i++) {
// here, we start at 1 to omit the 'July 2007' record
String word = month_array[i];
char firstLetter = word.toLowerCase().charAt(0);
int index = firstLetter - 'a';
frequency[index]++;
}
return frequency;
}
public void printCounts(String month, int[] frequencies) {
System.out.print(month + "\t");
for(int frequency : frequencies) {
System.out.print(frequency);
System.out.print("\t");
}
}

String[] month_codes = ...;
Map<Character, Long> result = Arrays.stream(month_codes)
.collect(Collectors.groupingBy(
str -> Character.toLowerCase(str.charAt(0)),
Collectors.counting()));
So, Map<Character, Long> contains following data:
'a' -> 1
'b' -> 2
'c' -> 2
't' -> 1
'j' -> 1

You can do it in several ways.
I am providing you a way which can find the occurrences (Starting chars) using single loop and Map to store only occurrence of String start with "A", "B" and "T".
Here is the code:
public static Map<String, Integer> extract_counts(String[] month_array){
Map<String, Integer> map = new HashMap<>();
for(int i=0; i < month_array.length; i++){
//System.out.println(month_array[i]);
if(month_array[i].startsWith("T")){
if(map.containsKey("T")){
map.put("T", map.get("T") + 1);
}else {
map.put("T", 1);
}
}
if(month_array[i].startsWith("A")){
if(map.containsKey("A")){
map.put("A", map.get("A") + 1);
}else {
map.put("A", 1);
}
}
if(month_array[i].startsWith("B")){
if(map.containsKey("B")){
map.put("B", map.get("B") + 1);
}else {
map.put("B", 1);
}
}
}
return map;
Calling the method:
String[] month_codes = {"July 2007", "TRUCKS", "APPLES", "BEANS", "COATS", "BANANA", "CODES"};
System.out.println(extract_counts(month_codes));
Will get output like this:
{A=1, B=2, T=1}

Related

String Occurrence According to the order

I have a Problem where i need to find the first occurrence of the char according to the order which they occur in the given String.
For Example :
I have a String "Unitedin" where the char "n" and "i" have a multiple occurrence in the String.
char n occurred at charAt(1,7)
char i occurred at charAt (2,6)
But the char "i" had occurred first before char "n".
I have Tried Something like this But i am not getting the required output.Can Anyone Help me please?
Note : Challenge is Not to use any type of List or Hashset or Hashmap
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
StringBuilder nodup = new StringBuilder();
StringBuilder dup = new StringBuilder();
System.out.println("Enter a string : ");
String instring = in.next();
for (int i = 0; i < instring.length(); i++) {
for (int j = i + 1; j < instring.length(); j++) {
if (instring.charAt(i) == instring.charAt(j)) {
nodup.append(instring.charAt(i));
} else {
dup.append(instring.charAt(i));
}
}
}
System.out.print(nodup.toString());
i am getting the OutPut as : ni . but the Required output is in.
The LinkedHashMap class works really well for your particular problem. You may iterate the character array from your input string, and then add the characters, along with their counts, as keys, into the LinkedHashMap. Since LinkedHashMap preserves insertion order, to get the output you want you need only iterate the map and print out all keys whose counts are greater than one. The order of the character keys will be fixed at the first occurrence of each letter.
String input = "Unitedin";
LinkedHashMap<Character, Integer> map = new LinkedHashMap<>();
for (char chr : input.toCharArray()) {
Integer count = map.get(chr);
map.put(chr, count == null ? 1 : count + 1);
}
for (Map.Entry<Character, Integer> entry : map.entrySet()) {
if (entry.getValue() > 1) System.out.println(entry.getKey());
}
This prints:
n
i
If your objective is to view the first recurrence of a character, then this should do it. The order will be the order in which a repeated character is found in your string.
String input = "Unitedin";
Stringbuilder sb = new Stringbuilder();
Map<Character, Integer> map = new HashMap<>();
for (char chr : input.toCharArray()) {
Integer count = map.get(chr);
count = count != null ? count + 1 else 1;
map.put(chr, count);
if(count > 1) {
sb.append(chr);
}
}
System.out.println(sb.toString()); // Output: in
EDIT: I understand from your comment that you cannot use an instance of List, HashSet, or HashMap? Then is LinkedHashMap allowed? If not, then you'll need to recreate that functionality somehow.
You could map characters a-z and A-Z in an int array of 52 (26 + 26). Rather than insert the count into a map, you map the character to its appropriate spot in the array and update the count. Good luck!

Java: Finding jumbled word

In my country there is Game Show called Slagalica where one of the tasks is to find longest word in array of 12 letters. Size of the longest word is always 10, 11 or 12.
I have file with words from my language I use as database. Words that have 10, 11 or 12 letters in them I've saved in List (listWordSize10_11_12).
When I enter jumbled word [12 letters] in I want from my program to find what word is that originally. I know how to make it work when jumbled word is 12 letters word but I can't work it out when it's less.
Example: 10 letter word is jumbled + 2 random letters.
Goal is for that 10 letter word to be recognized and printed in original state.
Where is what I've done:
// un-jumbling word
System.out.println("Unesite rijec koja treba da se desifruje: ");
String jumbledWord = tast.nextLine();
char[] letter = jumbledWord.toCharArray();
Arrays.sort(letter);
String sorted_Mistery_Word = new String(letter);
for (int i = 0; i < listWordSize10_11_12.size(); i++) {
int exception = 0;
char[] letter_2 = listWordSize10_11_12.get(i).toCharArray();
Arrays.sort(letter_2);
String longWords = new String(letter_2);
int j = i;
while(longWords.length()>i){
if(sorted_Mistery_Word.charAt(j)!=longWords.charAt(i)){
exception++;
j++;
}
}
if(exception < 3){
System.out.println("Your word is: "+listWordSize10_11_12.get(i));
break;
}
}
Thanks!!!
P.S. This is not a homework or some job, just project I've been doing for fun!
Thanks everyone for the help, I've learned a lot!
Your basic approach for 12 characters, which I would characterize as fingerprinting, will also work for 10 or 11 letter words with some modification.
That is, rather that just sorting the letters in each candidate word as you examine it to create the fingerprint, pre-process your array to create a small(ish) fingerprint of each word as a byte[]. Using the English alphabet and ignoring case, for example, you could create a 26-byte array for each word, where each byte position contained the count of each letter in the word.
That is fingerprint[0] contains the number of 'a' characters in the word, and fingerprint[25] the number of 'z' characters.
Then just replace your sorted_Mistery_Word.charAt(j)!=longWords.charAt(i) check with a loop that increments a temporary array for each letter in the mystery word. Finally, check that the temporary array has at least the same value for every position. Something like:
byte [] makeFingerprint(String s) {
byte[] fingerprint = new byte[26];
for (char c : letter_2) {
fingerprint[c - 'a']++;
}
return fingerprint;
}
/** determine if sub is a subset of super */
boolean isSubset(byte[] sub, byte[] super) {
for (int i=0; i < sub.length; i++) {
if (sub[i] > super[i])
return false;
}
return true;
}
void findMatch(String jumbledWord) {
byte[] fingerprint = makeFingerprint(jumbledWord);
for (byte[] candidate : fingerprintList) {
if (isSubset(fingerprint, candidate)) {
System.out.println("Your word is: " + ...);
break;
}
}
}
Here I omitted the creation of the fingerprintList - but it just involves fingerprint each word.
There are plenty of optimizations possible, but this should already be quite a bit faster than your version (and is "garbage free" in the main loop). It can handle candidates of any length (not just 10-12 chars). The biggest optimization, if you will check many words, is to try to use the "fingerpint" as a key for direct lookup. For the 12 character case this is trivial (direct lookup), but for the 10 and 11 or this you would likely have to use type of technique for higher-dimensional searching - locality sensitive hashing seems like a natural fit.
Here's one way to go about the problem. Let's say (since no example input was provided) that there's 3 String[]'s, arr3 (that represents the 10-letter-words you have), arr4 (that represents the 11-letter-words you have), and arr5 (you guessed it, represents the 12-letter words you have). This is what I made for those:
String[] arr3 = { "map", "cat", "dog" };
String[] arr4 = { "four", "five", "nine" };
String[] arr5 = { "funny", "comma", "brace" };
So based on what you said, if we got the input of pam, we'd want the output of map. If we got the input of enni we'd want the output of nine. And if we got the input of yfunn we'd want the output of funny. So how to go about doing this? I like what #cricket_007 mentioned about using maps. But first, let's get the permutations down.
Based off of the linked SO question, I came up with this modified/variation to get the jumbled text:
public static List<String> jumble(String str) {
List<String> result = new ArrayList<String>();
permutation(result, "", str);
return result;
}
private static void permutation(List<String> l, String prefix, String s) {
int n = s.length();
if (n == 0) {
l.add(prefix);
} else {
for (int i = 0; i < n; i++)
permutation(l, prefix + s.charAt(i), s.substring(0, i) + s.substring(i + 1, n));
}
}
This code will let us easily construct a single map for us to store jumbled text in as a key, and the answer to that jumbled text as a value.
All together, the final code looks like this:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Appy {
public static void main(String[] args) {
String[] arr3 = { "map", "cat", "dog" };
String[] arr4 = { "four", "five", "nine" };
String[] arr5 = { "funny", "comma", "brace" };
List<String> permutations = new ArrayList<String>();
Map<String, String> map = new HashMap<String, String>();
for (String s : arr3) {
permutations = jumble(s);
for (String str : permutations)
map.put(str, s);
}
for (String s : arr4) {
permutations = jumble(s);
for (String str : permutations)
map.put(str, s);
}
for (String s : arr5) {
permutations = jumble(s);
for (String str : permutations)
map.put(str, s);
}
System.out.println("test = 'pam' -> " + map.get("pam"));
System.out.println("test = 'enni' -> " + map.get("enni"));
System.out.println("test = 'yfunn' -> " + map.get("yfunn"));
}
public static List<String> jumble(String str) {
List<String> result = new ArrayList<String>();
permutation(result, "", str);
return result;
}
private static void permutation(List<String> l, String prefix, String s) {
int n = s.length();
if (n == 0) {
l.add(prefix);
} else {
for (int i = 0; i < n; i++)
permutation(l, prefix + s.charAt(i), s.substring(0, i) + s.substring(i + 1, n));
}
}
}
Which gives the resulting output of:
test = 'pam' -> map
test = 'enni' -> nine
test = 'yfunn' -> funny
Now applying this logic, adapting for your case of 10, 11, and 12 letter words should be relatively simple. Cheers!

Counting letter frequencies and print letter:count, but not duplicates in java strings

public static void main(String[] args) {
TextIO.putln("Text?");
String line = TextIO.getln();
line = line.toLowerCase();
char[] arr = line.toCharArray();
for(int i = 0; i < line.length(); i++){
if(Character.isLetter(arr[i])){
int count;
int j;
for(j = 0,count = 0; j < line.length(); j++){;
if( arr[i] == arr[j]){
count++;
}
}
System.out.printf("%c:%d\n", arr[i],count);
}
}
}
If I enter the string josh it prints out
j:1
o:1
s:1
h:1
If I enter joshh it prints
j:1
o:1
s:1
h:2
h:2
but I want
j:1
o:1
s:1
h:2
How do I, for any string with duplicates, only print out the unique letter and how many times it occurs total? I was thinking of maybe implementing a for loop that just checks for each letter and increment it such as
for ('a' : string)
total++
and then increment the 'a' by one, so the next loop would check how many occurrences of b, then c, and so on.
How much java do you know? Is this an assignment? Have you been through data structures? Two options:
Sort and then count
Use a map (dictionary if you come from Python as your username suggests), increment in the first pass and then iterate over the keys to print the values
From what I can tell, it looks like the issue lies in the for loop you are using while printing.
What happens is that you evaluate for every single character in the string and print. Once you evaluate for the first h in josh, your program then moves on to the second h, evaluates again, and as a result, prints h and its count again.
You could try a data structure such as a dictionary which accounts for unique elements. Or, as you count how many times letters appear, you can have another array that holds letters already seen. If you check against this array before counting how many times a letter appears you can see if the letter has already been counted, if so you can just skip this character and move on to the next. It isnt the most elegant solution, but it would work
public static void main(String[] args) {
TextIO.putln("Text?");
String line = TextIO.getln();
line = line.toLowerCase();
// char[] arr = line.toCharArray();
Map<Character, Integer> occurrences=new LinkedHashMap<Character, Integer>();
for(int i = 0; i < line.length(); i++){
int ch=line.charAt(i);
if(Character.isLetter(ch)){
if(occurrences.containsKey(ch)) {
occurrences.put(ch, occurrences.get(ch)+1); // increment
}
else {
occurrences.put(ch, 1);
}
}
}
for(char ch : occurrences.keySet()) {
System.out.print(ch+":"+occurrences.get(ch)+";");
}
System.out.println();
}
Try this.
Map<Character, Integer> map = new LinkedHashMap<>();
for (char c : line.toCharArray())
if (Character.isLetter(c))
map.compute(c, (k, v) -> v == null ? 1 : v + 1);
for (Entry<Character, Integer> e : map.entrySet())
System.out.printf("%c:%d\n", e.getKey(), e.getValue());

Find the index value of a character stored in HashMap

I'm looking out to print the index value of a respective character as many times as it would appear using HashMap.
For example, let's say I have String str = "Hello World". The program as of now displays the occurence of characters via {d=1, W=1, e=1, r=1, o=2, l=3, H=1}.
What I intend to achieve as resultset is {d=[9], o=[4, 6], r=[7], W=[5], H=[0], l=[2, 3, 8], e=[1]} where *=[*] represents key=[indexValue].
(The whitespace character is not to be taken into consideration in the final resultSet.)
import java.util.HashMap;
import java.util.Map;
public class ConcordanceOfStrings {
public static void main(String[] args) {
String str = "Hello World";
//code to remove whitespaces
String newStr = str.replaceAll(" ", "");
Map<Character, Integer> numCount = new HashMap<Character, Integer>(Math.min(newStr.length(), 26));
System.out.println("The count is: ");
for(int i=0; i<newStr.length(); i++){
char charAt = newStr.charAt(i);
if(!numCount.containsKey(charAt)){
numCount.put(charAt, 1);
}
else{
numCount.put(charAt, numCount.get(charAt)+1);
}
}
System.out.println(numCount);
}
}
You're very close. Right now, you are storing the result in a Map<Character, Integer>, so a map from each character to the number of times it appears in the String.
To store all the indexes where the character appears, you need to have a Map<Character, List<Integer>>: each character will be mapped to a list of integers, which will be the list of the indexes where this character appears.
In your current code, you just need to adapt the logic that populates the map:
if(!numCount.containsKey(charAt)){
numCount.put(charAt, new ArrayList<>(Arrays.asList(i))); // <-- we store a list containing the first index i
// numCount.put(charAt, 1);
} else{
numCount.get(charAt).add(i); // <-- we add to the existing list the index i
// numCount.put(charAt, numCount.get(charAt)+1);
}
In the case where the map doesn't contain the character, we initialize the mapping with a list containing the first index i. Arrays.asList(i) returns a fixed-size list so I wrapped it in another ArrayList.
In the case where the map already contains the character, we just need to get the current list of indexes and add the one we just found.
If you are using Java 8, your whole code could be written more simply with Streams:
Map<Character, List<Integer>> numCount =
IntStream.range(0, str.length())
.filter(i -> str.charAt(i) != ' ')
.boxed()
.collect(Collectors.groupingBy(
i -> str.charAt(i),
Collectors.mapping(v -> v - 1, Collectors.toList())
));
You need something more than just Map you need something like Map>. Here is a example of a modification to your algorithm:
Map<Character, List<Integer>> positions = new HashMap<>();
Map<Character, Integer> numCount = new HashMap<Character, Integer>(Math.min(newStr.length(), 26));
for (int i = 0; i < newStr.length(); i++) {
char charAt = newStr.charAt(i);
if (!numCount.containsKey(charAt)) {
numCount.put(charAt, 1);
}
else {
numCount.put(charAt, numCount.get(charAt) + 1);
}
if(!positions.containsKey(charAt)){
List<Integer> cPosition = new LinkedList<>();
cPosition.add(i);
positions.put(charAt, cPosition);
}
else{
List<Integer> cPosition = positions.get(charAt);
cPosition.add(i);
//positions.put(charAt, cPosition); because of references there is no need to do this
}
}

Java Isomorphic Code

I am kind of stuck on this java problem involving returning the number of isomorphic pairs in an array of Strings. The code I have written keeps returning incorrect number of isomorphic word pairs.
The definition of isomorphic words is given as follows: Two words are called isomorphic if the letters in one word can be remapped to get the second word. Remapping a letter means replacing all occurrences of it with another letter. The ordering of the letters remains unchanged. No two letters may map to the same letter, but a letter may map to itself.
For example, the words "abca" and "zbxz" are isomorphic because we can map 'a' to 'z', 'b' to 'b' and 'c' to 'x'.
I am not inlcuding the getMap method which I call in the function. The getMap method take any string as input, and returns a map where the keys are the letters in the string, and the corresponding values are the number of times the letter appears in the string.
public class IsomorphicWords {
public int countPairs(String[] words) {
Set <String> pairs = new HashSet<String>();
for (String word:words){
Map noOfOccurencesOfEachLetter= getMap(word);
ArrayList<Integer> valuesFromFirstWord = new ArrayList<Integer>(noOfOccurencesOfEachLetter.values());
Collections.sort(valuesFromFirstWord);
java.util.List<String> list = new ArrayList<String>(Arrays.asList(words));
list.remove(word);
String[] oneLessWord = list.toArray(new String[words.length-1]);
for(String secondWord:oneLessWord){
Map secondNoOfOccurencesOfEachLetter = getMap(secondWord);
ArrayList<Integer> valuesFromSecondWord = new ArrayList<Integer>(secondNoOfOccurencesOfEachLetter.values());
Collections.sort(valuesFromSecondWord);
if (valuesFromFirstWord.equals(valuesFromSecondWord)){
pairs.add(""+word+","+secondWord+"");
}
else{
continue;
}
}
}
return pairs.size()/2;
public Map getMap(String word){
HashMap<String,Integer> noOfOccurencesOfEachLetter= new HashMap<String,Integer>();
for (int i=0;i<word.length();i++){
char letter = word.charAt(i);
String letterInDictionary= Character.toString(letter);
if (noOfOccurencesOfEachLetter.containsKey(letterInDictionary)==true){
int count= noOfOccurencesOfEachLetter.get(letterInDictionary);
noOfOccurencesOfEachLetter.put(letterInDictionary, count+1);
}
else{
noOfOccurencesOfEachLetter.put(letterInDictionary, 1);
}
}
return noOfOccurencesOfEachLetter;
}
}
I'd really appreciate any feedback you can give me on this code.
Thanks,
Junaid
The reason why it gives the incorrect answer probably comes from you take the letter count, and don't look at the position that they have in both words. The first solution that comes up in me, is to create a new array in which you translate the letters to the index of the first occurrence of this letter for each word. For example: "abcd" would be "0123", "abca" would be "0120" and "fhjf" would be "0120" as well. Then you can simply compare the results. I hope this helps...
public int countPairs(String[] words) {
int isomorphicPairs = 0;
for (int i = 0; i < words.length; i++) {
for (int j = i+1; j < words.length; j++) {
if (words[i].length() == words[j].length()) {
String tmp = new String(words[j]);
for (int k = 0; k < tmp.length(); k++)
tmp = tmp.replaceAll("" + tmp.charAt(k), "" + words[i].charAt(k));
if (words[i].equals(tmp)) isomorphicPairs++;
}
}
}
return isomorphicPairs;
}

Categories

Resources