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
Related
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'm building a simple program in Java that finds letters in strings and replaces them with a number, but I'm having trouble finding a method that will allow me to check for the exact specific character. There are plenty for digits and letters in general.
As my for loop stands now, it just replaces the letter everywhere, irregardless of whether it is within the range specified by start and end.
Any help would be appreciated.
String str = "A.A.A.A.A.A.A.A";
int start = 3;
int end = 9;
for (int i = start; i < end; i++) {
if (Character.isLetter(str.charAt(i)) {
str = str.replaceAll("A", "9");
return str;
Expected Output:
A.A.9.9.9.A.A.A
Actual Output:
9.9.9.9.9.9.9.9
In your code, you have
str = str.replaceAll("A", "9");
This will replace all the occurrences of A to 9
Instead of your approach, you should
1.Convert the string to a char array
char[] charArray = str.toCharArray();
2.Then replace each occurrence of character with a number
if (Character.isLetter(charArray[i])){
//Character Found
charArray[i] = '9';
}
3. Convert it back to string using
str = String.valueOf(charArray);
Modified Code:
String str = "A.A.A.A.A.A.A.A";
int start = 3;
int end = 9;
//Converting String to char array
char[] charArray = str.toCharArray();
for (int i = start; i < end; i++) {
if (Character.isLetter(charArray[i])){
//Character Found
charArray[i] = '9';
}
}
//Converting Back to String
str = String.valueOf(charArray);
System.out.println(charArray);
System.out.println(str);
Compare for character equality and then use string builder to replace the specified character
//Use of StringBuffer preferred over String as String are immutable
StringBuilder sb = new StringBuilder(str);
// -1 to start as index start from 0
for (int i = start-1; i < end; i++) {
char currentChar = currentString.charAt(i);
if (currentChar == "A") {
sb.setCharAt(i, '9');
}
}
return sb.toString();
I'd do it that way. Cut out the string to isolate the part you want to act on, do your replace ans stitch it all back together :
String str = "A.A.A.A.A.A.A.A";
int startIndex = 3;
int endIndex = 9;
String beginning = str.substring(0, startIndex);
String middle = str.substring(startIndex, endIndex);
String end = str.substring(endIndex);
middle = middle.replaceAll("A", "9");
String result = beginning + middle + end;
System.out.println(result);
Prints out :
A.A.9.9.9.A.A.A
EDIT:
As suggested in the comments, you could do it in one line
String str = "A.A.A.A.A.A.A.A";
int startIndex = 3;
int endIndex = 9;
String result =
str.substring(0, startIndex) +
str.substring(startIndex, endIndex).replaceAll("A", "9") +
str.substring(endIndex);
Here is an example using substrings to let you choose what portion of the string you want to test
int start = 3;
int end = 9;
String str = "A.A.A.A.A.A.A.A";
String startStr = str.substring(0,start);
String endStr = str.substring(end);
String newStr="";
char temp=' ';
for (int i = start; i < end; i++) {
temp = str.charAt(i);
if (temp=='A')
newStr+="9";
else
newStr += temp;
}
return(startStr + newStr + endStr);
You are replacing all the match found in the string and not specifying the index that needs to be replaced.
Use the StringBuffer replace method like below:
public static void main(String[] args) {
String str = "AAAAAAAA";
int start = 3;
int end = 9;
str = replaceBetweenIndexes(str, start, end, "9"); // AAA999AA
str = replaceBetweenIndexes("ABCD6EFG", start, end, "3"); // ABC363FG
}
public static String replaceBetweenIndexes(String str, int start, int end, String replaceWith) {
StringBuffer strBuf = new StringBuffer(str);
for (int i = start; i < end; i++) {
if (Character.isLetter(strBuf.charAt(i)) {
strBuf.replace(i, i+1, replaceWith);
}
}
return strBuf.toString();
}
I have a class called encryptionwhich represents a String that my user enters in the main, which is then encrypted by my .encryptMessage() method. I want to have the characters of the alphabet be turned into their corresponding int values and vice versa with the int values. I thought my method would do this properly but it is not outputting in that way.
Question: How can I fix this method to make the alphabet chars output as their corresponding int values and vice versa? (i.e. a = 1, b = 2, 1 = a, 2 = b, etc)
public class Encryption {
private String message;
public Encryption(String message) {
this.message = message;
}
public String encryptMessage()
{
char messageChar = 0;
for (int i = 0; i < message.length(); i++)
{
messageChar = message.charAt(i);
messageChar = Character.toUpperCase(messageChar);
if (Character.isLetter(messageChar))
{
int charValue = Character.getNumericValue(messageChar);
message += charValue;
}
else if (Character.isDigit(messageChar))
{
int messageVal = 0;
messageChar = (char) messageVal;
message += (char) messageVal;
}
}
return message;
}
}
Character.getNumericValue does not return the numeric value you think it is.
The java.lang.Character.getNumericValue(char ch) returns the int value
that the specified Unicode character represents. For example, the
character '\u216C' (the roman numeral fifty) will return an int with a
value of 50.
Here a snippet that would work
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-96);
}
This one would work for Capital letters
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);
}
Note that these two snippets are stolen from How to get numeric position of alphabets in java?
I wrote the following code but similar characters are always in the same case. What's wrong in this code and How can this problem be solved??
private void genBTActionPerformed(java.awt.event.ActionEvent evt) {
String str = new String(strTF.getText());
int n = str.length();
char ch;
int i;
for(i = 0; i < n; i++) {
if(i % 2 == 0) {
ch = Character.toLowerCase(str.charAt(i));
str = str.replace(str.charAt(i), ch);
} else {
ch = Character.toUpperCase(str.charAt(i));
str = str.replace(str.charAt(i), ch);
}
}
jumTF.setText(str);
}
Unlike what its name says, .replace() replaces characters/CharSequences in the whole input. The difference with .replaceAll() is that it takes literals as arguments and not regexes/regex replacements strings (and that it has an overload taking two chars as arguments). That is the second worst misnamed method of the String class after matches().
Moreover you create a new String on each character you replace, so you have n+1 strings for a n character long string. Do it like this instead:
final char[] chars = str.toCharArray();
final int len = chars.length;
char c;
for (int i = 0; i < len; i++) {
c = chars[i];
chars[i] = i % 2 == 0
? Character.toLowerCase(c)
: Character.toUpperCase(c);
}
jumTF.setText(new String(chars));
In your program you were using replace() which replaces characters/CharSequences in the whole input what you need to do is
Put the string into an array.
Iterate over said array.
convert that array back into string
private void genBTActionPerformed(java.awt.event.ActionEvent evt) {
String str = new String(strTF.getText());
char [] chr= str.toCharArray();
int n = chr.length;
char ch;
int i;
for(i = 0; i < n; i++) {
if(i % 2 == 0) {
ch = Character.toLowerCase(chr[i]);
chr[i]=ch;
} else {
ch = Character.toUpperCase(chr[i]);
chr[i]=ch;
}
}
jumTF.setText(new String(chr)); }
hope this will help you :)
Since String are immutable in java , you can use StringBuilder or StringBuffer to solve this problem
StringBuilder str=new StringBuilder(inputString);
You can use your own logic just with slight change instead of using
str = str.replace(str.charAt(i), ch);//since it replaces in whole string
Use
str.setCharAt(i,ch);
So your final Program looks like this :
for(i = 0; i < n; i++) {
if(i % 2 == 0) {
ch = Character.toLowerCase(str.charAt(i));
str.setCharAt(i,ch);
} else {
ch = Character.toUpperCase(str.charAt(i));
str.setCharAt(i,ch);
}
}
Suppose InputString is : stackoverflow
then output is : sTaCkOvErFlOw
Scanner _in = new Scanner(System.in);
System.out.println("Enter an Equation of variables");
String _string = _in.nextLine();
char[] cArray = _string.toCharArray();
I want to remove the symbols "+,=" and I want to remove any repeating variables.
so far I have:
for(int i = 0; i < cArray.length; i++){
if(cArray[i].equals(+)|| cArray[i].equals(=)){
cArray[i] = null;
}
}
However, I dont know how to condence the array to remove any gaps and I don't know how to remove repeating characters, I think I am making this harder than it needs to be
You can use:
_string.replaceAll("[+,=]","");
This sounds like a good use for regular expressions:
String result = _string.replaceAll("[+=]", "");
Here, the [+=] is a character class that consists of + and =. You can add other characters as required.
Try the next:
public static void main(String[] args) {
String input = "a+a+b=c+d-a";
char[] cArray = input.replaceAll("[-+=]", "") // gaps
.replaceAll("(.)(?=.*\\1)", "") // repeating
.toCharArray();
System.out.println(Arrays.toString(cArray));
}
Output:
[b, c, d, a]
Or you can se another array, like this:
Scanner in = new Scanner(System.in);
String s = in.nextLine();
char [] cArray = s.toCharArray();
int count = 0;
char [] cArray2 = new char[cArray.length];
for (int i = 0; i < cArray.length; i++){
if (cArray[i] != '+' || cArray[i] != '='){
cArray2[count++] = cArray[i];
}
}
for (int i = 0; i < count; i++){
boolean repeated = false;
for (int j = i + 1; j < count; j++){
if (cArray2[i] == cArray2[j]){
repeated = true;
break;
}
}
if (!repeated){
//do what you want
}
}
You can extend LinkedHashSet (Which enforces uniqueness and retains order). Override the add() function to not accept any characters that you don't want to use. Then put the contents in a char array.
public static char[] toCharArray(String str) {
// Here I am anonymously extending LinkedHashSet
Set<Character> characters = new LinkedHashSet<Character>() {
// Overriding the add method
public boolean add(Character character) {
if (!character.toString().matches("[\\+=]")) {
// character is not '+' or '='
return super.add(character);
}
// character is '+' or '='
return false;
}
};
// Adding characters from str to the set.
// Duplicates, '+'s, and '='s will not be added.
for (int i = 0; i < str.length(); i++) {
characters.add(str.charAt(i));
}
// Put Characters from set into a char[] and return.
char[] arrayToReturn = new char[characters.size()];
int i = 0;
for (Character c : characters) {
arrayToReturn[i++] = c;
}
return arrayToReturn;
}