So i have a program where i want to replace specific characters in the program with other letters. However, when i run this program, it seems to keep reverting the changed characters back. This is the code so far:
public static String changeSample(String sample) {
for (int i = 0; i < sample.length(); i++) {
if (sample.charAt(i) == 'A') {
sample = sample.replace(sample.charAt(i), 'B');
continue;
}
else if (sample.charAt(i) == 'B') {
sample = sample.replace(sample.charAt(i), 'A');
continue;
}
}
return sample;
Is there a way that i can iterate through each character in the string and then check if it is either an A, B, C, D, E, or F and change it to its complimentary letter, i.e. A to B, B to A, C to D, D to C, E to F, F to E.
replace() will return a new String where ALL occurrences of a particular character are changed, not just a character at a particular position. So your problem is that the repeated replace() statements are effectively modifying the values back and forth.
Because a String is immutable, you cannot simply replace its characters with others dynamically. So, convert your code to use a StringBuilder instead.
StringBuilder buildSample = new StringBuilder();
buildSample.append(sample);
Now you can use setCharAt() instead of replace() to change the character at one position at a time.
buildSample.setCharAt(i, 'A');
At the end, you can return buildSample.toString().
As for changing each letter A to F to its complement, if only these six letters are required, a hard-coded function with a switch statement would do. Otherwise you can use a function like complementaryLetter() below, which returns the complement after checking the ASCII value of the character. This will work for all characters. You can add code to handle invalid cases, for non-character input.
A complete working code:
public class Replace {
public static void main(String[] args) {
String s1 = "ABCDEFA";
System.out.println(s1);
s1 = changeSample(s1);
System.out.println(s1);
}
public static char complementaryLetter(char letter) {
char retChar = 'A';
if ((int) letter % 2 == 0)
retChar = (char) ((int)letter - 1);
else
retChar = (char) ((int) letter + 1);
return retChar;
}
public static String changeSample(String sample) {
StringBuilder buildSample = new StringBuilder();
buildSample.append(sample);
for (int i = 0; i < sample.length(); i++) {
buildSample.setCharAt(i, complementaryLetter(sample.charAt(i)));
}
return buildSample.toString();
}
}
Related
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.
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.
I am trying to figure out how to write a method that will remove letters in a
string based on another string. The method would end up like so:
removeLetter("file", "fe")
The only thing that should be returned is the string "il". So far I have something like this:
public class h
{
public static void main(String[] args)
{
String a="file";
String b="fe";
char letter;
int i;
int j;
for (letter = 'a'; letter <= 'z'; letter++)
{
for (i=0; i < a.length()-1; i++)
{
for (j=0; j < b.length()-1; j++) // This is the loop i get stuck on
{
char r = b.charAt(j);
char s = a.charAt(i);
if ( letter == r && letter == s);
System.out.print(r + " " + s);
}
}
}
}
}
I know the bottom part is wrong but I am not sure where to go from here.
You can do this with a regular expression:
a.replaceAll("[" + b + "]", "")
This works by constructing a character class like [fe], and replacing characters which match that with the empty string.
Of course, this is a bit of a hack, in that you can easily choose b such that it won't yield a valid regular expression. However, if you know that b will only ever contain letters, this would work.
Here's a pretty simple nested array using a flag boolean :
public static void main(String[] args) {
String a = "file";
String b = "f";
String c = "";
StringBuilder sb = new StringBuilder();
boolean contains;
for (int i = 0 ; i < a.length() ; i++){
contains = false;
for (int j = 0 ; j < b.length() ; j++){
if (a.charAt(i) == b.charAt(j)) contains = true;
}
if (!contains) sb.append(a.charAt(i));
}
System.out.println(sb);
}
It checks every char of the first word with the chars of the second and changes the flag to true if the char is contained in both.
If it is not the case, the char of the first word is added to the new String, if the contrary, nothing happens and we continue to the next char of the first String.
Let's remove all the vowels of this word : Supercalifragilisticexpialidocious
String a = "Supercalifragilisticexpialidocious";
String b = "aeiou";
Here's the output :
Sprclfrglstcxpldcs
Take the example:
System.out.println("Hello Uni\u03C0");
System.out.println("Hello Esc \\");
this gives something like
Hello Uniπ
Hello Esc \
Is there a way where I can give different values to 03C0 and \ during different iterations in a loop?
for example
something like
System.out.format("Hello Esc \%c",'\\');
System.out.format("Hello Esc \%c",'\"');
I know this will give compiler error. I want to know how this can be done.
For example, I would like to print a different unicode character (say from \u0000 to \u00C3) in each iteration of a loop.
For example, I have this function that returns the 4 digit hexadecimal value of an integer:
public static String hexa(int a)
{
int x=a;
String b= String.format("%x",x);
if(b.length() == 1)
{
b="000"+b;
}
if(b.length() == 2)
{
b="00"+b;
}
if(b.length() == 3)
{
b="0"+b;
}
return b;
}
Now I would like to join \u with hexa(i) to get different unicode character for different i
You don't even have to convert the integer to hex string. Leave it as an integer and use Character.toChars()
StringBuilder sb = new StringBuilder();
sb.append(Character.toChars(0x03C0));
System.out.println(sb.toString());
Further example showing a for loop:
public static void main(String [] args) {
String lineSeparator = System.lineSeparator();
StringBuilder sb = new StringBuilder();
for(int i = 0x03C0; i < 0x03D0; i++) {
sb.append(Character.toChars(i)).append(lineSeparator);
}
System.out.println(sb.toString());
}
Output:
π
ρ
ς
σ
τ
υ
φ
χ
ψ
ω
ϊ
ϋ
ό
ύ
ώ
Ϗ
One last clarification:
System.out.println(Character.toChars(0x03C0)[0] == '\u03C0');
Output:
true
Example without StringBuilder:
String foo = "";
for(char c : Character.toChars(0x03C0)) {
foo += c;
}
System.out.println(foo);
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.