Count the numbers of numeric value in a given string - java

Java program to accept a string and count total numeric values.
public class Test2{
public static void main(String[] args){
String str = "I was 2 years old in 2002";
int count = 0, i;
for(i = 0; i < str.length(); i++){
if(str.charAt(i) >= 48 && str.charAt(i) <= 57){
count++;
// while(str.charAt(i) >= 48 && str.charAt(i) <= 57)
// i++;
}
}
System.out.println("Output: " +count);
}
}
Output = 5
After uncommenting the two lines written inside while loop -
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 25
at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:48)
at java.base/java.lang.String.charAt(String.java:712)
at Test2.main(Test2.java:9)
The output should be 2, because there are two numeric values - 2 and 2002
I have commented on the two lines in the above code, after uncommenting the code, the same logic works perfectly in C++.

An alternative to #DarkMatterยดs answer using Pattern:
public static void main(String[] args) {
String str = "I was 2 years old in 2002";
long count = Pattern.compile("\\d+").matcher(str).results().count();
System.out.println(count);
}

You are checking individual charters so it counts every digit (as you probably realize). Java String has some nice tools to help you here. You could split the line into words and check each against a regular expression using String.matches():
String str = "I was 2 years old in 2002";
int count = 0;
for(String s : str.split(" ")) {
if(s.matches("[0-9]*")) {
count++;
}
}
System.out.println(count);
You can do the same thing (almost) with a stream:
String str = "I was 2 years old in 2002";
long count = Arrays.stream(str.split(" "))
.filter(s -> s.matches("[0-9]*")).count();
System.out.println(count);

In C, strings end in an ASCII NUL character (well, in basic C, strings don't exist, it's a library bolt-on, but most bolt-ons have NUL terminated strings). In java, that's not how it works.
The reason that your code is not working in java, but it is in C, is that you just keep going until you hit a non-digit character in that inner while loop. That means if the string ends in a digit (which yours does), your code asks the string: Give me the character at (one position beyond its length). In C that works; that's ASCII NUL, and thus your inner loop ends, as that's not a digit.
In java it doesn't, because you can't ask for a character beyond the end of a string.
You can 'fix' your code as pasted by also adding a check that i is still below length: if (i < str.length() && str.charAt(i).... ).
As the other answers showed you, there are more java idiomatic ways to solve this problem too, and probably the strategies shown in the other answers is what your average java coder would most likely do if faced with this problem. But there's nothing particularly wrong with your C-esque solution, once you add the 'check length' fix.

below code will input String from user and return the number of occurrences of numeric values as count.
import java.util.Scanner;
public class NumberCountingString
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
String str = in.nextLine();
int count = 0, i;
int size = str.length(); // will only get size once instead of using in loop which will always get size before comparing
for(i = 0; i < size; i++)
{
if(Character.isDigit(str.charAt(i))) //if char is digit count++
{
count++;
for (int j = i; j < size; ) //inner loop to check if next characters are also digits
{
if(Character.isDigit(str.charAt(j))) // if yes skip next char
{
i++;
j=i;
}
else{ //break inner loop
break;
}
}
}
}
System.out.println("Output: " +count);
}
}

There are many options in Java as already shared by others. Below is very similar to your existing code and gives your desired output:
public static void main(String[] args) {
String str = "I was 2 years old in 2002";
String[] splittedString = str.split(" ");
int count = 0, i;
for (i = 0; i < splittedString.length; i++) {
if (StringUtils.isNumeric(splittedString[i])) {
count++;
}
}
System.out.println("Output: " + count);
}

You can split this string into an array of words, then filter those words where codePoints of the characters match digits, i. e. allMatch (Character::isDigit), and count these words:
String str = "I was 2 years old in 2002";
long count = Arrays
// split string into an array of words
.stream(str.split("\\s+"))
// for each word check the code points of the
// characters, whether they are digits or not.
.filter(w -> w.codePoints()
.mapToObj(ch -> (char) ch)
.allMatch(Character::isDigit))
.count();
System.out.println(count); // 2
See also: Transform String to byte then to int

Related

Modify the characters of words in a Java string with punctuation, but keep the positions of said punctuation?

For instance, take the following list of Strings, disregarding the inverted commas:
"Hello"
"Hello!"
"I'm saying Hello!"
"I haven't said hello yet, but I will."
Now let's say I'd like to perform a certain operation on the characters of each word โ€” for instance, say I'd like to reverse the characters, but keep the positions of the punctuation. So the result would be:
"olleH"
"olleH!"
"m'I gniyas olleH!"
"I tneva'h dias olleh tey, tub I lliw."
Ideally I'd like my code to be independent of the operation performed on the string (another example would be a random shuffling of letters), and independent of all punctuationโ€”so hyphens, apostrophes, commas, full stops, en/em dashes, etc. all remain in their original positions after the operation is performed. This probably requires some form of regular expressions.
For this, I was thinking that I should save the indices and characters of all punctuation in a given word, perform the operation, and then re-insert all punctuation at their correct positions. However, I can't think of a way to do this, or a class to use.
I have a first attempt, but this unfortunately does not work with punctuation, which is the key:
jshell> String str = "I haven't said hello yet, but I will."
str ==> "I haven't said hello yet, but I will."
jshell> Arrays.stream(str.split("\\s+")).map(x -> (new StringBuilder(x)).reverse().toString()).reduce((x, y) -> x + " " + y).get()
$2 ==> "I t'nevah dias olleh ,tey tub I .lliw"
Has anyone got an idea how I might fix this? Thanks very much. There's no need for full working codeโ€”maybe just a signpost to an appropriate class I could use to perform this operation.
No need to use regex for this, and you certainly shouldn't use split("\\s+"), since you'd lose consecutive spaces, and the type of whitespace characters, i.e. the spaces of the result could be incorrect.
You also shouldn't use charAt() or anything like it, since that would not support letters from the Unicode Supplemental Planes, i.e. Unicode characters that are stored in Java strings as surrogate pairs.
Basic logic:
Locate start of word, i.e. start of string or first character following whitespace.
Locate end of word, i.e. last character preceding whitespace or end of string.
Iterating from beginning and end in parallel:
Skip characters that are not letters.
Swap the letters.
As Java code, with full Unicode support:
public static String reverseLettersOfWords(String input) {
int[] codePoints = input.codePoints().toArray();
for (int i = 0, start = 0; i <= codePoints.length; i++) {
if (i == codePoints.length || Character.isWhitespace(codePoints[i])) {
for (int end = i - 1; ; start++, end--) {
while (start < end && ! Character.isLetter(codePoints[start]))
start++;
while (start < end && ! Character.isLetter(codePoints[end]))
end--;
if (start >= end)
break;
int tmp = codePoints[start];
codePoints[start] = codePoints[end];
codePoints[end] = tmp;
}
start = i + 1;
}
}
return new String(codePoints, 0, codePoints.length);
}
Test
System.out.println(reverseLettersOfWords("Hello"));
System.out.println(reverseLettersOfWords("Hello!"));
System.out.println(reverseLettersOfWords("I'm saying Hello!"));
System.out.println(reverseLettersOfWords("I haven't said hello yet, but I will."));
System.out.println(reverseLettersOfWords("Works with surrogate pairs: ๐“๐“‘๐“’+๐““ "));
Output
olleH
olleH!
m'I gniyas olleH!
I tneva'h dias olleh tey, tub I lliw.
skroW htiw etagorrus sriap: ๐““๐“’๐“‘+๐“
Note that the special letters at the end are the first 4 shown here in column "Script (or Calligraphy)", "Bold", e.g. the ๐“ is Unicode Character 'MATHEMATICAL BOLD SCRIPT CAPITAL A' (U+1D4D0), which in Java is two characters "\uD835\uDCD0".
UPDATE
The above implementation is optimized for reversing the letters of the word. To apply an arbitrary operation to mangle the letters of the word, use the following implementation:
public static String mangleLettersOfWords(String input) {
int[] codePoints = input.codePoints().toArray();
for (int i = 0, start = 0; i <= codePoints.length; i++) {
if (i == codePoints.length || Character.isWhitespace(codePoints[i])) {
int wordCodePointLen = 0;
for (int j = start; j < i; j++)
if (Character.isLetter(codePoints[j]))
wordCodePointLen++;
if (wordCodePointLen != 0) {
int[] wordCodePoints = new int[wordCodePointLen];
for (int j = start, k = 0; j < i; j++)
if (Character.isLetter(codePoints[j]))
wordCodePoints[k++] = codePoints[j];
int[] mangledCodePoints = mangleWord(wordCodePoints.clone());
if (mangledCodePoints.length != wordCodePointLen)
throw new IllegalStateException("Mangled word is wrong length: '" + new String(wordCodePoints, 0, wordCodePoints.length) + "' (" + wordCodePointLen + " code points)" +
" vs mangled '" + new String(mangledCodePoints, 0, mangledCodePoints.length) + "' (" + mangledCodePoints.length + " code points)");
for (int j = start, k = 0; j < i; j++)
if (Character.isLetter(codePoints[j]))
codePoints[j] = mangledCodePoints[k++];
}
start = i + 1;
}
}
return new String(codePoints, 0, codePoints.length);
}
private static int[] mangleWord(int[] codePoints) {
return mangleWord(new String(codePoints, 0, codePoints.length)).codePoints().toArray();
}
private static CharSequence mangleWord(String word) {
return new StringBuilder(word).reverse();
}
You can of course replace the hardcoded call to the either mangleWord method with a call to a passed-in Function<int[], int[]> or Function<String, ? extends CharSequence> parameter, if needed.
The result with that implementation of the mangleWord method(s) is the same as the original implementation, but you can now easily implement a different mangling algorithm.
E.g. to randomize the letters, simply shuffle the codePoints array:
private static int[] mangleWord(int[] codePoints) {
Random rnd = new Random();
for (int i = codePoints.length - 1; i > 0; i--) {
int j = rnd.nextInt(i + 1);
int tmp = codePoints[j];
codePoints[j] = codePoints[i];
codePoints[i] = tmp;
}
return codePoints;
}
Sample Output
Hlelo
Hlleo!
m'I nsayig oHlel!
I athen'v siad eohll yte, btu I illw.
srWok twih rueoatrsg rpasi: ๐“‘๐“’๐“+๐““
I suspect there's a more efficient solution but here's a naive one:
Split sentence into words on spaces (note - if you have multiple spaces my implementation will have problems)
Strip punctuation
Reverse each word
Go through each letter, and insert character from reversed word AND insert punctuation from original word if necessary
public class Reverser {
public String reverseSentence(String sentence) {
String[] words = sentence.split(" ");
return Arrays.stream(words).map(this::reverseWord).collect(Collectors.joining(" "));
}
private String reverseWord(String word) {
String noPunctuation = word.replaceAll("\\W", "");
String reversed = new StringBuilder(noPunctuation).reverse().toString();
StringBuilder result = new StringBuilder();
for (int i = 0; i < word.length(); ++i) {
char ch = word.charAt(i);
if (!Character.isAlphabetic(ch) && !Character.isDigit(ch)) {
result.append(ch);
}
if (i < reversed.length()) {
result.append(reversed.charAt(i));
}
}
return result.toString();
}
}

breaking down any String

Hi guys I am busy with breaking / splitting Strings.
However the String is not fixed so when the input changes the program still has to work with any character input.
Till now I got this far but I got lost.
I have made an array of characters and set the size of the array equal to the lenght of any string that is will get as input. I made a for loop to loop through the characters of a string.
how do I insert my string now into the array because I know that my string is not yet in there? Then when its finally looping through the characters of my string is has to printout numbers and operands on different lines. So the ouput would look like in this case like this;
1
+
3
,
432
.
123
etc
I want to do this without using matchers,scanner, etc. I want to use basic Java techniques like you learn in the first 3 chapters of HeadfirstJava.
public class CharAtExample {
public static void main(String[] args) {
// This is the string we are going to break down
String inputString = "1+3,432.123*4535-24.4";
int stringLength = inputString.length();
char[] destArray = new char[stringLength];{
for (int i=0; i<stringLength; i++);
}
You could use Character.isDigit(char) to distinguish numeric and not numeric chars as actually this is the single criteria to group multiple chars in a same line.
It would give :
public static void main(String[] args) {
String inputString = "1+3,432.123*4535-24.4";
String currentSequence = "";
for (int i = 0; i < inputString.length(); i++) {
char currentChar = inputString.charAt(i);
if (Character.isDigit(currentChar)) {
currentSequence += currentChar;
continue;
}
System.out.println(currentSequence);
System.out.println(currentChar);
currentSequence = "";
}
// print the current sequence that is a number if not printed yet
if (!currentSequence.equals("")) {
System.out.println(currentSequence);
}
}
Character.isDigit() relies on unicode category.
You could code it yourself such as :
if (Character.getType(currentChar) == Character.DECIMAL_DIGIT_NUMBER) {...}
Or you could code it still at a lower level by checking that the int value of the char is included in the range of ASCII decimal values for numbers:
if(currentChar >= 48 && currentChar <= 57 ) {
It outputs what you want :
1
+
3
,
432
.
123
*
4535
-
24
.
4
It's easier than you might think.
First: to get an array with the chars of your string you just use the toCharArray() method that all strings have. ex. myString.toCharArray()
Second: When you see that a character is not a number, you want to move to the next line, print the character and then move to the next line again. The following code does exactly that :
public class JavaApplication255 {
public static void main(String[] args) {
String inputString = "1+3,432.123*4535-24.4";
char[] destArray = inputString.toCharArray();
for (int i = 0 ; i < destArray.length ; i++){
char c = destArray[i];
if (isBreakCharacter(c)){
System.out.println("\n" + c);
} else {
System.out.print(c);
}
}
}
public static boolean isBreakCharacter(char c){
return c == '+' || c == '*' || c == '-' || c == '.' || c == ',' ;
}
char[] charArray = inputString.toCharArray();
Here is a possible solution where we go character by character and either add to an existing string which will be our numbers or it adds the string to the array, clears the current number and then adds the special characters. Finally we loop through the array as many times as we find a number or non-number character. I used the ASCII table to identify a character as a digit, the table will come in handy throughout your programming career. Lastly I changed the array to a String array because a character can't hold a number like "432", only '4' or '3' or '2'.
String inputString = "1+3,432.123*4535-24.4";
int stringLength = inputString.length();
String[] destArray = new String[stringLength];
int destArrayCount = 0;
String currentString = "";
for (int i=0; i<stringLength; i++)
{
//check it's ascii value if its between 0 (48) and 9 (57)
if(inputString.charAt(i) >= 48 && inputString.charAt(i) <= 57 )
{
currentString += inputString.charAt(i);
}
else
{
destArray[destArrayCount++] = currentString;
currentString = "";
//we know we don't have a number at i so its a non-number character, add it
destArray[destArrayCount++] = "" + inputString.charAt(i);
}
}
//add the last remaining number
destArray[destArrayCount++] = currentString;
for(int i = 0; i < destArrayCount; i++)
{
System.out.println("(" + i + "): " + destArray[i]);
}
IMPORTANT - This algorithm will fail if a certain type of String is used. Can you find a String where this algorithm fails? What can you do to to ensure the count is always correct and not sometimes 1 greater than the actual count?

Having trouble with for loops

So, I need to write a program using loops that takes a string and counts what and how many letters appear in that string. (string "better butter" would print "b appears 2 times, e appears 3 times, ' '(space) appears 1 time, and so on). While I understand the idea and concept behind this assignment, actually pulling it off has been rough.
My nested for loop is where the problems are coming from, I assume. What I've written only loops once (i think) and just shows the first character and says there's only one of that character.
Edit: Preferably without using Map or arrays. I'm fine with using them if it's the only way, but they've not been covered in my class so I'm trying to avoid them. Every other similar question to this (that I've found) uses Map or array.
import java.util.Scanner;
class myString{
String s;
myString() {
s = "";
}
void setMyString(String s) {
this.s = s;
}
String getMyString() {
return s;
}
String countChar(String s){
s = s.toUpperCase();
int cnt = 0;
char c = s.charAt(cnt);
for (int i = 0; i <= s.length(); i++)
for (int j = 0; j <= s.length(); j++) //problem child here
c = s.charAt(cnt);
cnt++;
if (cnt == 1)
System.out.println(c+" appears "+cnt+" time in "+s);
else
System.out.println(c+" appears "+cnt+" times in "+s);
return "for"; //this is here to prevent complaint from the below end bracket.
}
}
public class RepeatedCharacters {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s;
System.out.println("Enter a sentence: ");
s = in.nextLine();
myString myS = new myString();
// System.out.println(myS.getMyString());
// System.out.println(myS.countChar());
myS.countChar(s);
}
}
First you will need to scan the entire string and store the
counts of each characters. Later you can just print the counts.
Algorithm 1:
Use a HashMap to store the character as key and its count as value. (If you are new to Java, you might want to read up on
HashMaps.)
Every time you read a character in your for loop, check if it present in the HashMap. If yes, then increment the count by 1. Else
add a new characters to the map with count 1.
Printing:
Just iterate on your HashMap and print out the character and
their respective counts.
Issue with your code: You are trying to print the count as soon as you
read a character. But the character might appear again later in the
string. So you need to keep track of the characters you have already
read.
Algorithm 2:
String countChar(String s){
has_processed = []
for i = 0 to n
cnt = 0
if s.charAt(i) has been processed
continue;
for j = i+1 to n
if (s.charAt(i) == s.charAt(j))
cnt++
add s.charAt(i) to has_processed array
print the count of s.charAt(i)
}
Use a frequency array to get an answer in linear time.
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
String s = "better butter";
int freq[] = new int[26];
int i;
for (i = 0; i < s.length(); i++) {
if (s.charAt(i) >= 'a' && s.charAt(i) <= 'z')
freq[s.charAt(i)-'a']++;
}
for (i = 0; i < freq.length; i++) {
if (freq[i] == 0) continue;
System.out.println((char)(i+'a') + " appears " + freq[i] + " times" );
}
}
}
Ideone Link
Note that this can be expanded to include uppercase letters, but for demonstrative purposes, only lowercase letters are handled in the above code.
EDIT: While the OP did ask if it was possible to do this without an array, I would recommend against such. That solution would have terrible time complexity and repeat character counts (unless an array is used to keep track of seen characters, which is counter to the aim). Thus, the above solution is the best way to do it in a reasonable amount of time (linear) with limited space consumption.
I would do the following. Create a HashMap which keeps track of which unique characters are in the string and the count for each character.
You only need to iterate over the string once, and put each character into the HashMap. if the characer is in the map, icrement the integer count in the map, else add 1 to the map for that character. Print out the map with toString() to get the result. The whole thing can be done in about 4 lines of code.
The only thing being done in your nested for loop with the following
c = s.charAt(cnt)
is setting the c char to the value of the first letter (i.e. index 0 of the string) over and over and over until you've looped through the string n^2 times. In other words, you're not incrementing your cnt counter within the for loops at all.
Suggestion: try to use meaningful names for your variables; it will help you a lot in your career. Also class names should always start with a capital letter.
Although it is not the quickest solution in terms of performance, the most simple solution should be:
import java.util.HashMap;
import java.util.Map;
...
Map<String, Integer> freq = new HashMap<String, Integer>();
...
int count = freq.containsKey(word) ? freq.get(word) : 0;
freq.put(word, count + 1);
Source: Most efficient way to increment a Map value in Java
Please next time use the search function before posting a new question.
Here is my version of countChar(String s)
boolean countChar(String s) {
if(s==null) return false;
s = s.toUpperCase();
//view[x] will means that the characted in position x has been just read
boolean[] view = new boolean[s.length()];
/*
The main idea is:
foreach character c = s.charAt(x) in the string s, I have a boolean value view[x] which say if I have already examinated c.
If c has not been examinated yet, I search for other characters equals to c in the rest of the string.
When I found other characters equals to c, I mark it as view and I increment count with count++.
*/
for (int i = 0; i < s.length(); i++) {
if (!view[i]) {
char tmp = s.charAt(i);
int count = 0;
for (int j = i; j < s.length(); j++) {
if (!view[j] && s.charAt(j) == tmp) {
count++;
view[j] = true;
}
}
System.out.println("There were " + count + " " + tmp);
}
}
return true;
}
It should work, excuse me for my English because I'm italian

How to check if a string contains all the letters of the alphabet? [duplicate]

This question already has answers here:
Check if string has all the letters of the alphabet
(15 answers)
Closed 6 years ago.
I am trying to check if a string contains all the letters of the alphabet. I created an ArrayList which contains the whole alphabet. I converted the string to char array and I'm iterating through the character array, and for every character present in the ArrayList I'm removing an element from it. And in the end, I'm trying to check if the Arraylist is empty to see if all elements have been removed. That would indicate the string contains all the letters of the alphabet.
Unfortunately, the code is throwing IndexOutOfBoundsException error inside the if condition where I'm removing elements from the arraylist
List<Character> alphabets = new ArrayList<Character>();
alphabets.add('a');
alphabets.add('b');
alphabets.add('c');
alphabets.add('d');
alphabets.add('e');
alphabets.add('f');
alphabets.add('g');
alphabets.add('h');
alphabets.add('i');
alphabets.add('j');
alphabets.add('k');
alphabets.add('l');
alphabets.add('m');
alphabets.add('n');
alphabets.add('o');
alphabets.add('p');
alphabets.add('q');
alphabets.add('r');
alphabets.add('s');
alphabets.add('t');
alphabets.add('u');
alphabets.add('v');
alphabets.add('w');
alphabets.add('x');
alphabets.add('y');
alphabets.add('z');
// This is the string- I've just put a random example
String str = "a dog is running crazily on the ground who doesn't care about the world";
//Remove all the spaces
str = str.replace(" ", "");
// Convert the string to character array
char[] strChar = str.toCharArray();
for (int i = 0; i < strChar.length; i++) {
char inp = strChar[i];
if (alphabets.contains(inp)) {
alphabets.remove(inp);
}
}
if (alphabets.isEmpty())
System.out.println("String contains all alphabets");
else
System.out.println("String DOESN'T contains all alphabets");
All these solutions seem to do a lot of work for a relatively simple check, especially given Java 8's stream API:
/* Your lowercase string */.chars()
.filter(i -> i >= 'a' && i <= 'z')
.distinct().count() == 26;
Edit: For speed
If you want to end the string iteration as soon as the entire alphabet is found while still using streams, then you can keep track with a HashSet internally:
Set<Integer> chars = new HashSet<>();
String s = /* Your lowercase string */;
s.length() > 25 && s.chars()
.filter(i -> i >= 'a' && i <= 'z') //only alphabet
.filter(chars::add) //add to our tracking set if we reach this point
.filter(i -> chars.size() == 26) //filter the 26th letter found
.findAny().isPresent(); //if the 26th is found, return
This way, the stream will cease as soon as the Set is filled with the 26 required characters.
There are some (even still) more efficient solutions in terms of performance below, but as a personal note I will say to not bog yourself in premature optimization too much, where you could have readability and less effort in writing the actual code.
List.remove removes by index. Since a char can be cast to an int you are effectively removing index values that do not exist, ie char 'a' is equal to int 97. As you can see your list does not have 97 entries.
You can do alphabet.remove(alphabets.indexOf(inp));
As pointed out by #Scary Wombat(https://stackoverflow.com/a/39263836/1226744) and #Kevin Esche (https://stackoverflow.com/a/39263917/1226744), there are better alternative to your algorithm
O(n) solution
static Set<Integer> alphabet = new HashSet<>(26);
public static void main(String[] args) {
int cnt = 0;
String str = "a dog is running crazily on the ground who doesn't care about the world";
for (char c : str.toCharArray()) {
int n = c - 'a';
if (n >= 0 && n < 26) {
if (alphabet.add(n)) {
cnt += 1;
if (cnt == 26) {
System.out.println("found all letters");
break;
}
}
}
}
}
Adding to #Leon answer, creating a List and removing from it seems quite unnecessary. You could simply loop over 'a' - 'z' and do a check with each char. Additionally you are looping over the whole String to find out, if each letter is present. But the better version would be to loop over each letter itself. This can potentionally safe you a few iterations.
In the end a simple example could look like this:
// This is the string- I've just put a random example
String str = "a dog is running crazily on the ground who doesn't care about the world";
str = str.toLowerCase();
boolean success = true;
for(char c = 'a';c <= 'z'; ++c) {
if(!str.contains(String.valueOf(c))) {
success = false;
break;
}
}
if (success)
System.out.println("String contains all alphabets");
else
System.out.println("String DOESN'T contains all alphabets");
Regex is your friend. No need to use a List here.
public static void main(String[] args) {
String s = "a dog is running crazily on the ground who doesn't care about the world";
s = s.replaceAll("[^a-zA-Z]", ""); // replace everything that is not between A-Za-z
s = s.toLowerCase();
s = s.replaceAll("(.)(?=.*\\1)", ""); // replace duplicate characters.
System.out.println(s);
System.out.println(s.length()); // 18 : So, Nope
s = "a dog is running crazily on the ground who doesn't care about the world qwertyuioplkjhgfdsazxcvbnm";
s = s.replaceAll("[^a-zA-Z]", "");
s = s.toLowerCase();
s = s.replaceAll("(.)(?=.*\\1)", "");
System.out.println(s);
System.out.println(s.length()); //26 (check last part added to String) So, Yes
}
Another answer has already pointed out the reason for exception. You have misused List.remove(), as it implicitly convert char to int which it called the List.remove(int) which remove by index.
The way to solve is actually easy. You can make it call the List.remove(Object) by
alphabets.remove((Character) inp);
Some other improvements:
You should use Set instead of List in this case.
You can even use a boolean[26] to keep track of whether an alphabet has appeared
You do not need to convert your string to char array. Simply do a str.charAt(index) will give you the character at certain position.
One integer variable is enough to store this information. You can do it like this
public static boolean check(String input) {
int result = 0;
input = input.toLowerCase();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c >= 'a' && c <= 'z') {
result |= 1 << (input.charAt(i) - 'a');
}
}
return result == 0x3ffffff;
}
Each bit corresponds to a letter in English alphabet. So if your string contains all letters the result will be of form 00000011111111111111111111111111
How about creating
List<String> alphabets = new ArrayList <String> ();
and add values as strings
then
for (String val : alphabets) { // if str is long this will be more effecient
if (str.contains (val) == false) {
System.out.println ("FAIL");
break;
}
}
You can get rid of the exception, by changing this line in your code
char inp = strChar[i];
to
Character inp = strChar[i];
Refer https://docs.oracle.com/javase/7/docs/api/java/util/List.html#remove(java.lang.Object)
List.remove('char') is treated as List.remove('int'), which is why you are getting indexOutOfBoundsException, because it is checking the ASCII value of 'a' which is 97. Converting variable 'inp' to Character would call List.remove('Object') api.
And if you like Java 8 streams like me:
final List<String> alphabets = new ArrayList<>();
And after filling alphabets with a-z:
final String str = "a dog is running crazily on the ground who doesn't care about the world";
final String strAsLowercaseAndWithoutOtherChars = str.toLowerCase()
.replaceAll("[^a-z]", "");
final boolean anyCharNotFound = alphabets.parallelStream()
.anyMatch(t -> !strAsLowercaseAndWithoutOtherChars.contains(t));
if (anyCharNotFound) {
System.out.println("String DOESN'T contains all alphabets");
} else {
System.out.println("String contains all alphabets");
}
This converts the string to lower case (skip if you really are only looking for the small letters), removes all characters from the string which are not small letters and then checks for all members of your alphabets if they are contained in the string by using a parallel stream.
Here's another naive solution that uses String.split("") to split every character into a String[] array, then Arrays.asList() to convert that to a List<String>. You can then call yourStringAsList.containsAll(alphabet) to determine whether your String contains the alphabet:
String yourString = "the quick brown fox jumps over the lazy dog";
List<String> alphabet = Arrays.asList("abcdefghijklmnopqrstuvwxyz".split(""));
List<String> yourStringAsList = Arrays.asList(yourString.split(""));
boolean containsAllLetters = yourStringAsList.containsAll(alphabet);
System.out.println(containsAllLetters);
This approach might not be the fastest, but I think the code is a littler easier to understand than the solutions proposing loops and streams and whatnot.
Just do something like
sentence.split().uniq().sort() == range('a', 'z')
For Java 8, it could be written like:
boolean check(final String input) {
final String lower = input.toLowerCase();
return IntStream.range('a', 'z'+1).allMatch(a -> lower.indexOf(a) >= 0);
}
Convert the string to lower case or capitals. Then loop thru the equivalent ascii decimal values for A-Z or a-z and return false if not found in character array. You will have to cast the int to char.
I've thought about playing with the ASCII codes of the characters.
String toCheck = yourString.toLowerCase();
int[] arr = new int[26];
for(int i = 0; i < toCheck.length(); i++) {
int c = ((int) toCheck.charAt(i)) - 97;
if(c >= 0 && c < 26)
arr[c] = arr[c] + 1;
}
After running the loop you eventually get an array of counters, each representing a letter of alphabet (index) and it's occurrence in the string.
boolean containsAlph = true;
for(int i = 0; i < 26; i++)
if(arr[i] == 0) {
containsAlph = false;
break;
}
Character inp = strChar[i];
Use this instead of char, List remove method have 2 overloaded methods , one with object and one with int .If you pass char its been treated as the int one.

Counting uppercase and lowercase characters of String and appending count to the character [duplicate]

This question already has answers here:
How to count uppercase and lowercase letters in a string?
(8 answers)
Closed 6 years ago.
I am trying to print the output of a String to find the count of uppercase and lowercase in it.
E.g. if string = "AaaBBbCc",
I need the output as : "A1a2B2b1C1c1".
I.E. count of uppercase 'A' then count of lowercase 'a', appending with the characters.
Below is the code snippet till where I have done. Can any one suggest how it goes.
I know code is not up-to the mark :(
public static void main(String[] args) {
String str = "AaaBBbCc";
int upperCount=0;
int lowerCount=0;
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if(ch>='A' && ch<='Z'){
upperCount++;
System.out.println("Uppercase letter is : "+ch+upperCount);
}
if(ch>='a' && ch<='z'){
lowerCount++;
System.out.println("Lower case letter is : "+ch+lowerCount);
}
}
System.out.println("upper count is :"+upperCount+" & lower count is: "+lowerCount);
}
What you are trying to accomplish here is called Run-length encoding. This is sometimes referred to as a form of lossless data compression in which the length of a continuous character is appended to a single instance of that character. Here is a modified version from RosettaCode that should do the trick for you:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RunLengthEncoding {
public static String encode(String source) {
StringBuffer dest = new StringBuffer();
for (int i = 0; i < source.length(); i++) {
int runLength = 1;
while (i+1 < source.length() && source.charAt(i) == source.charAt(i+1)) {
runLength++;
i++;
}
/* We will swap these so they fit your format of [Letter][Count]
dest.append(runLength);
dest.append(source.charAt(i));
*/
dest.append(source.charAt(i));
dest.append(runLength);
}
return dest.toString();
}
public static void main(String[] args) {
String example = "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";
System.out.println(encode(example));
}
}
You are on the right track. If you want to count which letters appear, not only if they are upper or lower case, you could create 2 int[] arrays upperCaseCount and lowerCaseCount = new int[26]. You could use these arrays to keep count of which letters are appearing.
Hint you can exploit the fact that char can be used as int to determine which index you should increment:
int index = ? //'a' should be 0 for lower, and 'A' should be 0 for upper
lowerCaseCount[index]++ or upperCaseCount[index]++;

Categories