If a String contains a certain letter an exact amount of times - java

In Java, is there a way of saying .. for example "Does this word contain a Z three times?"
I'm guessing there could be some clever char value?
String word = "pizzaz"
// Check if word contains three z's
boolean b = word.contains("SOME CLEVER CHAR VALUE??");
If possible, could an integer value be used when passing through the "amount of times" i.e.
int letterAmount = 3;

You can use a regex to do that. Following your example:
word.matches(".*(z.*){3}.*")
it returns true if your string has 3 z's.

A somewhat expensive and roundabout way to count single-character matches is as follows:
String s = "pizzaz";
int numMatches = s.length() - s.replaceAll("z", "").length();
When the length of the string with all "z"s removed is subtracted from the length of the original string, you end up with the number of zs in the original string.

Using Apache Commons:
boolean hasThreeZs = StringUtils.countMatches("pizzaz", "z") == 3;
or using Spring's version of StringUtils
boolean hasThreeZs = StringUtils.countOccurrencesOf("pizzaz", "z") == 3;

Depending on the size of the string, another option is to just walk through the string, counting characters:
public static boolean contansCharCount(String s, char targetC, int targetCount) {
char[] sArray = s.toCharArray();
int actualCount = 0;
for(char c : sArray)
actualCount = (c == targetC) ? actualCount + 1 : actualCount;
return (actualCount == targetCount);
}
This takes O(N) time.

String word = "pizzaz";
System.out.println(word.replaceAll("[^z]","").equals("zzz"));

Related

letter change, what am I doing wrong?

So im trying the following challenge:
Using the Java language, have the function LetterChanges(str) take the str parameter being passed andmodify it using the following algorithm. Replace every letter in the string with the letter following it in thealphabet (ie. c becomes d, z becomes a). Then capitalize every vowel in this new string (a, e, i, o, u) and finally return this modified string.
This is my code
class LetterChange {
public static String LetterChanges(String str) {
String alphabet = "AbcdEfghIjklmnOpqrstUvwxyz";
char currentChar,letter;
int i = 0;
while (i < str.length())
{
currentChar = str.charAt(i);
for(int x = 0; x < alphabet.length(); x++)
{
letter = alphabet.charAt(x);
if (currentChar == letter){
str = str.replace(currentChar,alphabet.charAt(x+1));
i++;
}
}
}
when I run it it is returning the last char in string +1 letter in alphabet. for example if i was to run "bcd" it returns "EEE". I dont understand why its replacing all chars with the result of the loop for the last char.
When you go through the loop the first time you get
"bcd"--> "ccd"
Now, str.replace will turn this into "ddd" on next turn, then "EEE".
I.e., replace replaces every occurrence on each turn.
It is true that debugging it in the IDE will help you in the future!
Also, what if you had a lowercase vowel in your string?
public class Alphabet {
public static String LetterChanges(String str) {
String alphabet = "AbcdEfghIjklmnOpqrstUvwxyz";
char[] string = str.toLowerCase().toCharArray();
for (int i=0; i < string.length; i++) {
char d = alphabet.charAt(((alphabet.toLowerCase().indexOf(string[i]))+1) % 26);
string[i]=d;
}
return new String(string);
}
public static void main(String[] args) {
System.out.println(Alphabet.LetterChanges("aabb"));
}
}
alphabet.charAt(
((alphabet.toLowerCase().indexOf(string[i]))
+1) % 26)
1) use toLowerCase on the input and your string map to eliminate case problems
2) find character at index+1 in string map 'alphabet', treating it as a circular buffer using a modulus that takes z to a.
index 25 (z) + 1 == 26 --> 0 (A) because 26 is 0 mod 26 while index 0(A) + 1 = 1 --> 1 mod 26. It is only necessary to wrap the z to A while not changing the other 25 indices and is more efficient than branching with an "if" statement.
Does this solution help?
public static String letterChanges(String str) {
String alphabet = "AbcdEfghIjklmnOpqrstUvwxyz";
StringBuilder stringBuilder = new StringBuilder();
for (char letter : str.toCharArray()) {
if (alphabet.contains(Character.toString(letter))) {
int index = alphabet.indexOf(letter) + 1;
if (index >= 26) {
index = 0;
}
stringBuilder.append(alphabet.charAt(index));
}
}
return stringBuilder.toString();
}
The previous solution was hard to follow, so it's difficult to explain why it wasn't working without debugging through it to see where it goes wrong. It was easier to use a for-each loop to go through the str parameter and find matches using Java's provided methods like .indexOf and .charAt.
Also, Java uses lower camel case method naming, letterChanges instead of LetterChanges :)
Let me know if you have any questions.
You are getting that result because on every replacing you are re-setting the input string. I recommend you:
Better try with two different variables: Let the input variable be unmodified, and work on the output one.
Since strings are unmodifiable -as you already know- better declare them as arrays of char.
For the shake of optimization, base your algorithm on one single loop, which will iterate over the characters of the input string. For each character, decide if it is alphabetic or not, and in case it is, what character should it be replaced with.

How to take a 1's complement of a binary String

I have a String of length >10^4 which has only binary numbers.
How can I take 1's complement of it ?
Example- Sting a = "0101"
I want String b = "1010"
Is there any better method other than replacing every character using StringBuffer/StringBuilder?
I suggest to avoid reinventing the wheel you use BigInteger. It’s not method gives you almost what you want, only it gives you a negative number when applied to a positive one. To get back into positive, add 2^n where n is the length of the original string:
String a = "0101";
BigInteger twoToLength = new BigInteger("2").pow(a.length());
String b = twoToLength.add(new BigInteger(a, 2).not()).toString(2);
System.out.println(b);
This prints:
1010
The argument 2 to the constructor and toString() is an radix indicating binary numbers.
We are not quite there yet: if the original string has leading ones, the leading zeroes in the result are not printed. You will have to prepend these manually to get the same string length as you had originally. I think the easiest way to do this is to add 2^(n+1) instead of 2^n so we are sure there is at least one 1 bit in front of the bits we really care about. So we remove this bit only after converting back to a string:
String a = "0101";
int length = a.length();
// add a couple of more bits in front to make sure we have a positive number
BigInteger twoToLengthPlus1 = BigInteger.ONE.shiftLeft(length + 1);
String b = twoToLengthPlus1.add(new BigInteger(a, 2).not()).toString(2);
// remove extra bits from the front again
b = b.substring(b.length() - length);
With this change 1010 becomes 0101.
Does it have to be a String? If a CharSequence is enough, you can do this:
public class BinaryComplementCharSequence implements CharSequence {
private final String source;
public BinaryComplementCharSequence(String source) {
this.source = source;
}
#Override
public int length() {
return source.length();
}
#Override
public char charAt(int index) {
switch (source.charAt(index)) {
case '0':
return '1';
case '1':
return '0';
default:
throw new IllegalStateException();
}
}
#Override
public CharSequence subSequence(int start, int end) {
return new BinaryComplementCharSequence(source.substring(start, end));
}
#Override
public String toString() {
return new StringBuilder(length()).append(this).toString();
}
}
If you really need a String, call toString() (but that uses a StringBuilder again).
You've already figured it out: use a StringBuilder and replace every bloody char individually.
You could also use a char array: char ca[] = str.toCharArray() to extract the characters, modify individual chars in ca, String newstr =new String(ca) to pack the array back into a String. Might be slightly faster.
Take your pick.
Every char check with '1' and invert:
char[] charsConverted = new char[a.length()];
char[] charArray = a.toCharArray();
for (int i = 0; i < charArray.length; i++) {
boolean b = charArray[i] == '1';
charsConverted[i] = !b ? '1' : '0';
}
String b= String.valueOf(charsConverted);

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.

Java- Palindrome Program

I have been assigned to complete a palindrome program. However, I cannot use the charAt method.
Typically, I'd be able to solve this fairly quickly. However, since I cannot use charAt, I have no clue as to how I should go about doing this.
My idea is to take the length of the string, divide it by two (however this limits me to strings only with an even number of chars) then convert the substrings into int's and then finally compare the two int's.
This is my code thus far-
public static boolean isPal(String s)
{
int length = s.length();
int math = length / 2;
String side1 = s.substring(1,math);
String side2 = s.substring(math, length);
int s1 = Integer.parseInt(side1);
int s2 = Integer.parseInt(side2);
if(s1 == s2){
return true;
} else {
return false;
}
}
However, I have realized that this might not, and probably is not, the best way to handle the situation. I am currently running into this error-
Exception in thread "main" java.lang.NumberFormatException: For input string: "i"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at Palindrome.isPal(Lab08st.java:47)
at Lab08st.main(Lab08st.java:20)
I believe it is because I need a for loop of sorts.
However, having inadequate Java experience, I am unsure.
I am open to any and all suggestions. (So long as they do not require charAt)
Use this:
public static boolean isPal(String s) {
char[] chars = s.toCharArray();
int len = chars.length;
for (int i = 0; i < len ; i++) {
if(chars[i] != chars[len-i-1] ){
return false;
}
}
return true;
}
Your approach is flawed in several ways:
Integer.parseInt(String) only works on optionally-signed digit strings that represent base-10 numbers representable as type int. Your function will utterly fail on non-numeric inputs, and on inputs that are too large for the halves to be represented as ints (some 19-20-character inputs; all longer inputs).
Your function will fail on any input having an odd number of characters, because you cannot split such inputs evenly into halves.
Your logic is flawed anyway. It would judge "1010" a palindrome (which it isn't), and it would judge "1001" not a palindrome (though it is one).
You can pick out the input String's characters one-by-one via a variety of techniques, among them:
You can get the characters in a char[] via String.toCharArray(), as has elsewhere been suggested.
You can consume the input via a series of substring() invocations.
You can use a StringCharacterIterator to iterate over the characters
Since it's not clear why you are not permitted to use charAt(), here's an approach that altogether avoids relying on indexing:
import java.text.StringCharacterIterator;
// ...
public static boolean isPal(String s)
{
StringCharacterIterator it = new StringCharacterIterator(s);
String reversed = ""
for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
reversed = c + reversed;
}
return reversed.equals(s);
}
There are more efficient approaches, but that one is clear and simple.
Or here's one that doesn't rely (explicitly) on any classes other then String, but does use the indexes 0 and 1:
public static boolean isPal(String s)
{
String tail = s;
String reversed = ""
while (tail.length() > 0) {
reversed = tail.substring(0, 1) + reversed;
tail = tail.substring(1);
}
return reversed.equals(s);
}
Or since you had the idea of splitting the String into two, perhaps that was directed by your instructor? Are you perhaps studying recursion? Because you can also reverse the input string via a recursive algorithm: (1) split the string in two (as evenly as possible works best); (2) recursively reverse each half; (3) put the reversed halves back together in the opposite order. (Implementation left as an exercise.)
With all that said, do note that Reticality's one-liner using StringBuilder.reverse() is better on all counts if it satisfies the requirements.
My Solution-
import java.util.*;
public class MyClass {
public static void main(String args[]) {
String str = "pappap";
String sp = str.toLowerCase();
char[] ch = sp.toCharArray();
int len = ch.length;
int lastIndex = ch.length-1;
int count = 1;
int first = 0;
int last = sp.length()-1;
for(; first < last ;){
if(ch[first] == ch[last] ){
first= first+1;
last= last-1;
}
else{
count = 0;
break;
}
}
String result = (count == 1) ? "Palindrome" : "Not a palindrome " ;
System.out.println(result);
}
}
If you are checking to see if a number, given to you as a string, is a palindrome, then you might use math to do it. Use an algorithm that compares the least significant with the most significant digit, then remove those to digits and continue. If there are an odd number of digits then you don't need to compare that middle digit with anything -- you just need the number of digits / 2 steps.
This code left as an exercise because it is homework.

Count occurence of a character in a string

I tried to count the occurrence of alphabets in a string, but I substitue them with numbers to make it clearer. Then when I run that code, it doesnt display the results I want.I dont really know why...Please help!! Thank you so much!!
Scanner Scanner1 = new Scanner(System.in);
out.println("Please type in a string below.");
String UserInput = Scanner1.nextLine();
String Index = "12345";
int length = 2;//Modified
int[] count = new int[length];
int length2 = 5; //Modified
int n1 = 0;
int n2 = 0;
out.println(UserInput.charAt(n1));//Modified
out.println(Index.charAt(n2));//Modified
for (int i = 0; i < length; i++) {
if (UserInput.charAt(n1) == Index.charAt(n2)) {
n1++;
count[length - (length - n1)]++;
} else {
n2++;
if(n2==length2)
{
n2 = n2-length2;
}
}
}
A relatively short and neat way to count a specific character in a string is using the return value of the replaceAll method:
public static int countChar(final String str, final char c) {
return str.replaceAll("[^" + c + "]","").length();
}
The pattern [^x] (x can be replaced with any char (or amount of different chars)) will match everything in a given String except x. So [^T] of TEST would replace E and S with the given replacement (which is "" (nothing)) and keeps the Ts. The method would return TT. If you count that length, you'll receive the count of the searched character of the given string.
The example
System.out.println(countChar("TEST", 'T'));
System.out.println(countChar("TEST", 'E'));
System.out.println(countChar("TEST", 'S'));
prints
2
1
1
(keep in mind that is method is case sensitive)
use collections like Hashmap. Here Character stores every unique character encountered and Integer stores the count of every character whenever it is encountered.

Categories