Java question here:
If i have a string "a", how can I "add" value to the string, so I get a "b" and so on?
like "a++"
String str = "abcde";
System.out.println(getIncrementedString(str));
Output
bcdef
//this code will give next char in unicode sequence
public static String getIncrementedString(String str){
StringBuilder sb = new StringBuilder();
for(char c:str.toCharArray()){
sb.append(++c);
}
return sb.toString();
}
If you use the char primitive data type you can accomplish this:
char letter = 'a';
letter++;
System.out.println(letter);
prints out b
i made some changes to te paulo eberman code, to handle digits and characters, if valuable for someone i share this mod....
public final static char MIN_DIGIT = '0';
public final static char MAX_DIGIT = '9';
public final static char MIN_LETTER = 'A';
public final static char MAX_LETTER = 'Z';
public String incrementedAlpha(String original) {
StringBuilder buf = new StringBuilder(original);
//int index = buf.length() -1;
int i = buf.length() - 1;
//while(index >= 0) {
while (i >= 0) {
char c = buf.charAt(i);
c++;
// revisar si es numero
if ((c - 1) >= MIN_LETTER && (c - 1) <= MAX_LETTER) {
if (c > MAX_LETTER) { // overflow, carry one
buf.setCharAt(i, MIN_LETTER);
i--;
continue;
}
} else {
if (c > MAX_DIGIT) { // overflow, carry one
buf.setCharAt(i, MIN_DIGIT);
i--;
continue;
}
}
// revisar si es numero
buf.setCharAt(i, c);
return buf.toString();
}
// overflow at the first "digit", need to add one more digit
buf.insert(0, MIN_DIGIT);
return buf.toString();
}
i hope be usefull for someone.
use this code to increment char value by an integer
int a='a';
System.out.println("int: "+a);
a=a+3;
char c=(char)a;
System.out.println("char :"+c);
Convert the string to a char.
Increment the char.
Convert the char
back to a string.
Example:
//convert a single letter string to char
String a = "a";
char tmp = a.charAt(0);
//increment char
tmp++;
//convert char to string
String b = String.valueOf(tmp);
System.out.println(b);
Assuming you want something like aaab => aaac and not => bbbc, this would work:
public String incremented(String original) {
StringBuilder buf = new StringBuilder(original);
int index = buf.length() -1;
while(index >= 0) {
char c = buf.charAt(i);
c++;
buf.setCharAt(i, c);
if(c == 0) { // overflow, carry one
i--;
continue;
}
return buf.toString();
}
// overflow at the first "digit", need to add one more digit
buf.insert(0, '\1');
return buf.toString();
}
This treats all characters (in fact char values) the same, and fails (does strange stuff) for some unicode code-points outside the first plane (which occupy two char values in a String).
If you only want to use english lowercase letters as digits, you can try this variant:
public final static char MIN_DIGIT = 'a';
public final static char MAX_DIGIT = 'z';
public String incrementedAlpha(String original) {
StringBuilder buf = new StringBuilder(original);
int index = buf.length() -1;
while(index >= 0) {
char c = buf.charAt(i);
c++;
if(c > MAX_DIGIT) { // overflow, carry one
buf.setCharAt(i, MIN_DIGIT);
i--;
continue;
}
buf.setCharAt(i, c);
return buf.toString();
}
// overflow at the first "digit", need to add one more digit
buf.insert(0, MIN_DIGIT);
return buf.toString();
}
This does a => b => c, y => z => aa => ab.
if you want to do more calculation with the string, consider staying with StringBuilder (or StringBuffer for multithreaded access) instead of repeatedly copying between String and StringBuilder.
Or use a class made to do this, like BigInteger.
Related
I am having an issue with a particular leetcode problem called Valid Palindrome. My code works for all test cases except the last test case 479/480.
In this test case a 106890 length string is passed in but my code takes too long to solve it.
I decided to try take a different approach and use the StringBuilder class to reverse the string and then simply use reversedString.equals(originalString) to compare whether they are a palindrome. This approach solves the question and passes all testcases
Why doesn't my two pointer approach work? Why does it fail on the last test case?
Here is my solution (Two Pointer)
class Solution {
public static boolean isPalindrome(String s) {
String fixedString = "";
for (char c : s.toCharArray()) {
if (Character.isDigit(c) || Character.isLetter(c)) {
fixedString += c;
}
}
fixedString = fixedString.toLowerCase();
int i = 0;
int j = fixedString.length() - 1;
System.out.println(fixedString.toCharArray());
while (i <= j) {
if (fixedString.toCharArray()[i] != fixedString.toCharArray()[j]) {
return false;
}
i += 1;
j -= 1;
}
return true;
}
}
Here is my second solution using StringBuilder.
public class Valid_Palindrome {
public static void main(String args[]){
System.out.println(isPalindrome("A man, a plan, a canal: Panama"));
}
public static boolean isPalindrome(String s) {
String fixedString = "";
for(char c : s.toCharArray()){
if(Character.isDigit(c) || Character.isLetter(c)){
fixedString += c;
}
}
fixedString = fixedString.toLowerCase();
StringBuilder sb = new StringBuilder(fixedString);
sb = sb.reverse();
System.out.println(sb);
return sb.toString().equals(fixedString);
}
}
Technically speaking, isn't the second solution supposed to be much slower since it is using StringBuilder?
How do I optimize my first solution?
Here is the input string that is passed in my leetcode.
Don't build or reverse or do anything with the string, except iterate over half its characters.
In pseudo code:
Loop over the first half of the characters
For the ith character, compare it with the (length - i - 1)th character
If different, return false
If loop ends, return true
It is generally slow to perform string concatenation in a loop. Use a StringBuilder instead in the first loop to create the filtered string.
StringBuilder sb = new StringBuilder(s.length());
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isLetterOrDigit(c))
sb.append(Character.toLowerCase(c));
}
for (int i = 0, j = sb.length() - 1; i < j; i++, j--)
if (sb.charAt(i) != sb.charAt(j))
return false;
return true;
There are a couple of statements in your code that are probably slowing it down.
fixedString += c;
This creates a new StringBuilder object. The contents of fixedString are copied to it. Then the character (c) is appended. Then the StringBuilder is converted to a String and that String is assigned to variable fixedString.
if (fixedString.toCharArray()[i] != fixedString.toCharArray()[j])
Method toCharArray creates a new char[] and copies the contents of the String to it.
I suggest that you create the char[] once only and work with it. Of-course you need to remove the non-letters and non-digits from the original string as well as convert to lower case.
Here is my rewrite of your [two pointer] solution.
(Note that I assume that a null or empty string is not a palindrome.)
public static boolean isPalindrome(String s) {
if (s != null && !s.isEmpty()) {
char[] chars = s.toCharArray();
char[] temp = new char[chars.length];
int count = 0;
for (char c : chars) {
if (Character.isDigit(c) || Character.isLetter(c)) {
temp[count++] = Character.toLowerCase(c);
}
}
char[] letters = new char[count];
System.arraycopy(temp, 0, letters, 0, count);
int i = 0;
int j = count - 1;
System.out.println(letters);
while (i < j) {
if (letters[i] != letters[j]) {
return false;
}
i++;
j--;
}
return true;
}
return false;
}
The method takes 2 parameters (String,char) and returns the string with the char replaced by '+' if index is even and '#' if index is odd.
The String I use is "Mary Bella Abracadabra" and the expected output is "M+ry Bell+ +br#c#d#br+". Instead I get "M#ry Bell# #br#c#d#br#".
I can't find the error in my code. It seems that all indexes where char ch is found are odd.
public String emphasize (String phrase, char ch){
String phraseEmph = "";
char c1 = '#';
char c2 = '+';
for (int i=0; i < phrase.length(); i++){
char c = phrase.charAt(i);
char cc = Character.toLowerCase(c);
if ((cc == ch) && ((i % 2) == 0)){
phraseEmph = phrase.replace(c,c2);
phrase = phraseEmph;
}
else if ((cc == ch) && ((i % 2)!= 0)){
phraseEmph = phrase.replace(c,c1);
phrase = phraseEmph;
}
phrase = phrase;
}
return phrase;
}
public void testEmphasize(){
String phrase = "Mary Bella Abracadabra";
char ch = 'a';
String Emphasized = emphasize(phrase,ch);
System.out.println("Emphasized : " + Emphasized);
}
When you call replace it doesn't just replace the current 'a', it replaces all of them. You'll need to find a different way to replace characters so that you only change one at a time.
(I've purposefully avoided suggesting a fix. It'll be more educational if you come up with it yourself.)
Note Array start with 0 in java. String is immutable and don't provide many mutable methods. It's best to make use of StringBuilder as shown below both for easiness and memory efficiency.
public static String emphasize(String phrase, char ch) {
StringBuilder phraseEmph = new StringBuilder(phrase);
char c1 = '#';
char c2 = '+';
for (int i = 0; i < phrase.length(); i++) {
char c = phrase.charAt(i);
char cc = Character.toLowerCase(c);
if ((cc == ch) && ((i % 2) == 0)) {
phraseEmph.setCharAt(i, c2);
} else if ((cc == ch) && ((i % 2) != 0)) {
phraseEmph.setCharAt(i, c1);
}
}
return phraseEmph.toString();
}
Use StringBuilder instead of String for concatenation to a string inside a loop because it is much faster and consumes less memory.
Convert both the characters in the same case (e.g. lowercase) before comparing. This way, you can pass the character to the function in any case.
You should not use String#replace for this case as it replaces all occurrences of replacement character/string in the string being replaced.
Demo:
public class Main {
public static void main(String[] args) {
// Test
System.out.println(emphasize("Mary Bella Abracadabra", 'a'));
System.out.println(emphasize("Mary Bella Abracadabra", 'A'));
}
public static String emphasize(String phrase, char ch) {
char c1 = '#';
char c2 = '+';
StringBuilder sb = new StringBuilder();
// Convert the char parameter to lower case
char chLower = Character.toLowerCase(ch);
for (int i = 0; i < phrase.length(); i++) {
char c = phrase.charAt(i);
if (Character.toLowerCase(c) == chLower) {
if (i % 2 == 0) {
sb.append(c1);
} else {
sb.append(c2);
}
} else {
sb.append(c);
}
}
return sb.toString();
}
}
Output:
M+ry Bell+ +br#c#d#br+
M+ry Bell+ +br#c#d#br+
Here are some suggestions.
use a StringBuilder to make the character replacements. Intialize to the original string. You can then use setCharAt to make the change.
Use indexOf in conjunction with toLowerCase. Then you don't need to verify if you found the character, just use the index returned and return the final string if -1.
then just check for even or or indices like you are doing but assign to a holding char variable.
Then use that to replace the character. Like this pseudocode
char repl;
if (even) {
repl = '#';
} else {
repl = '+';
}
make replacement
don't do a check for both even or odd. Just check for one condition, Otherwise it must be the other condition (not need to check again).
Aside from my recommendations, here is another way of doing it.
The main difference is that it uses the even/odd result to index into the array to replace the character.
public static String emphasize(String phrase, char ch) {
StringBuilder sb = new StringBuilder(phrase);
char[] chars = { '#', '+' };
int idx = -1;
while ((idx = phrase.toLowerCase().indexOf(ch, idx + 1)) >= 0) {
sb.setCharAt(idx, chars[idx % 2]);
phrase = sb.toString();
}
return phrase;
}
Full tested simplified code :
public class Main {
public static void main(String[] args) {
String phrase = "Maryaa Bella Abracadabra";
char ch = 'a';
System.out.println("Original : " + phrase);
String Emphasized = emphasize(phrase,ch);
System.out.println("Emphasized : " + Emphasized);
}
public static String emphasize (String phrase, char ch){
StringBuilder temp = new StringBuilder(phrase);
char c1 = '#';
char c2 = '+';
for (int i = 0; i < phrase.length(); i++){
char c = phrase.charAt(i);
char cc = Character.toLowerCase(c);
if(cc == ch) {
if(i%2 == 0){
temp.setCharAt(i, c1);
} else {
temp.setCharAt(i, c2);
}
}
}
return temp.toString();
}
}
Output :
Original : Maryaa Bella Abracadabra
Emphasized : M+ry#+ Bell+ +br#c#d#br+
Your code is very inefficient, my suggestion :
class emphasize {
private String phrase;
private char ch;
public emphasize(String phrase, char ch) {
this.phrase = phrase;
this.ch = ch;
}
public String execute() {
char chars[] = phrase.toCharArray();
for (int i = 0 ; i < chars.length ; i++) {
/* As char is primitive type I can use == */
if (chars[i]==Character.toLowerCase(ch) || chars[i]==Character.toUpperCase(ch)) chars[i] = i%2==0 ? '+' : '#';
}
return String.valueOf(chars);
}
}
public class Main {
public static void main(String[] args) {
String phrase = "Mary Bella Abracadabra";
char ch = 'a';
emphasize obj = new emphasize(phrase, ch);
System.out.println(obj.execute());
}
}
Output :
I have written this code that replaces the characters in a string with a custom supplied alphabet:
//Replaces characters in string with custom alphabet.
public static String getStringWithCustomAlphabet(String string, String customAlphabet){
String shiftedString = "";
//Loop through every character in #plainText
for (int i = 0; i < string.length(); i++) {
//Store current character of loop in #charToAdd
char charToAdd = string.charAt(i);
int index = getAlphabet().indexOf(charToAdd);
//If index is valid
if (index != -1) charToAdd = customAlphabet.charAt(index);
//Add the character to #cipherText
shiftedString += charToAdd;
}
return shiftedString;
}
public static String getAlphabet() {
return "abcdefghijklmnopqrstuvwxyz ";
}
This code works. However, I want to be able to use not only a String alphabet but an integer alphabet. So, for example:
int[] numberArray {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26};
getStringWithCustomAlphabet("abcxyz", numberArray); //Should return 0,1,2,23,24,25
Maybe there is some way to simply this code and not use a for loop?
Strategy pattern may save you a lot of time and give you maximum flexibility. Suppose that we define an AlphabetConverter interface, as:
#FunctionalInterface
interface AlphabetConverter {
String convert(char ch);
}
Then, define the convertAlphabet method accepting an AlphabetConverter, as:
public String convertAlphabet(String actual, AlphabetConverter converter) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < actual.length(); i++) {
sb.append(converter.convert(actual.charAt(i)));
}
return sb.ToString();
}
Now, you can implement AlphabetConverter, one for replacement with String alphabet, and one for int array, or even use a lambda function.
For lower case use this :
String str = "abcdef";
char[] ch = str.toCharArray();
for (char c : ch) {
int temp = (int) c;
int temp_integer = 96; //for lower case
if (temp <= 122 & temp >= 97)
System.out.print(temp-temp_integer);
}
Output will be -:123456
For Upper case :
String str = "DEFGHI";
char[] ch = str.toCharArray();
for (char c : ch) {
int temp = (int) c;
int temp_integer = 64; //for upper case
if (temp <= 90 & temp >= 65)
System.out.print(temp-temp_integer);
}
Output Will be -:456789
I need to write a Java program that reads a string and determines if there are these two letters: the lowercase letter āeā or ādā.
That's what i written so far! any ideas why this doesn't work?
class ex2 {
public static void main(String[] args) {
//boolean arg1;
char e = 'e';
char d = 'd';
String x = "This is my test";
char[] xh = new char[x.length()];
for(int i=0; i<= x.length();i++) {
if (xh[i] == e || xh[i] == d) {
// arg1 = true;
System.out.println("Correct"); // Display he string
} else {
//arg1 = false;
System.out.println("Wrong");
}
}
}
}
First you have an ArrayOutOfBound exception because you need to stop just before the length, i.e. i<x.length().
Now your problem is that you test against an array of char that is full of null chars. You need to test against the string :
if (x.charAt(i) == e || x.charAt(i) == d) {
You never put anything in your array. char[] xh = new char[x.length()]; simply declares an array of length equal to x, it does not set the elements of xh to the elements of x. Instead, use:
char[] xh = x.toCharArray();
You also need to change your loop to:
for(int i=0; i < x.length(); i++) {
to avoid the out of bounds exception you are currently seeing.
Your main problem is the fact that you don't properly iterate over the char of your String, here is the best way to do it:
for (int i = 0, length = x.length(); i < length; i++) {
char c = x.charAt(i);
...
}
Assuming that you use Java 8, you could rely on the Stream API to do the same thing as next:
boolean result = x.chars().anyMatch(c -> c == 'e' || c == 'd');
this is the simple solution if you want to use it
NOTE from comments, you must keep account that if there is no e and d, this will iterate twice on the content of the String but not is second code as second example is just short form of for each
String str = "ewithd";
if (str.contains("e") || str.contains("d")) {
System.out.println("sucess");
} else
System.out.println("fail");
if you want to go with array then you can use foreach() too
char[] ch = str.toCharArray();
for (char c : ch) {
if (c == 'e' || c == 'd') {
System.out.println("success");
else
System.out.println("fail");
}
}
I have a String called "originalstring" which contains a sentence with mixed upper and lower case characters.
I simply want to flip the string so that if a character is a lowercase make it upper case and vice versa and return it.
I have tried this code, which returns the original string in upperCase:
for (int i = 0; i < originalString.length(); i++) {
char c = originalString.charAt(i);
if (Character.isUpperCase(c)) {
originalString += Character.toLowerCase(c);
}
if (Character.isLowerCase(c)) {
originalString += Character.toUpperCase(c);
}
}
return originalString;
You are adding characters to the original string. Also, this means that your for loop will never get to the end of the iteration of the for loop, because originalString.length() changes each loop also. It's an infinite loop.
Instead, create a StringBuilder that stores the converted characters as you're iterating over the original string. The convert it to a String and return it at the end.
StringBuilder buf = new StringBuilder(originalString.length());
for (int i = 0; i < originalString.length(); i++) {
char c = originalString.charAt(i);
if (Character.isUpperCase(c)) {
buf.append(Character.toLowerCase(c));
}
else if (Character.isLowerCase(c)) {
buf.append(Character.toUpperCase(c));
}
// Account for case: neither upper nor lower
else {
buf.append(c);
}
}
return buf.toString();
Common-lang provide a swapCase function, see the doc. Sample from the doc:
StringUtils.swapCase(null) = null
StringUtils.swapCase("") = ""
StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
And if you really want to do it by yourself, you can check the source of common-lang StringUtils
Instead of using existing utilities, you may try below conversion using boolean operation:
To upper case:
char upperChar = (char) (c & 0x5f)
To lower case:
char lowerChar = (char) (c ^ 0x20)
In your program:
StringBuilder result = new StringBuilder(originalString.length());
for (int i = 0; i < originalString.length(); i++) {
char c = originalString.charAt(i);
if (Character.isUpperCase(c)) {
result.append((char) (c ^ 0x20));
}
else if ((c >= 'a') && (c <= 'z')) {
result.append((char) (c & 0x5f));
}
else {
result.append(c);
}
}
System.out.println(result);