java replace correct number into letter - java

Well, this is my first time get here.
I'm trying to figure out the correct way to replace number into letter.
In this case, I need two steps.
First, convert letter to number. Second, restore number to word.
Words list: a = 1, b = 2, f = 6 and k = 11.
I have word: "b a f k"
So, for first step, it must be: "2 1 6 11"
Number "2 1 6 11" must be converted to "b a f k".
But, I failed at second step.
Code I've tried:
public class str_number {
public static void main(String[] args){
String word = "b a f k";
String number = word.replace("a", "1").replace("b","2").replace("f","6").replace("k","11");
System.out.println(word);
System.out.println(number);
System.out.println();
String text = number.replace("1", "a").replace("2","b").replace("6","f").replace("11","k");
System.out.println(number);
System.out.println(text);
}
}
Result:
b a f k
2 1 6 11
2 1 6 11
b a f aa
11 must be a word "k", but it's converted to "aa"
What is the right way to fix this?
Or do you have any other ways to convert letter to number and vice versa?
Thank you.

It would be good to write methods for conversion between number and letter format. I would write some code like this and use it generally instead of hard coding replace each time.
public class test {
static ArrayList <String> letter = new ArrayList<String> ();
static ArrayList <String> digit = new ArrayList<String> ();
public static void main(String[] args) {
createTable();
String test="b a f k";
String test1="2 1 6 11";
System.out.println(letterToDigit(test));
System.out.println(digitToLetter(test1));
}
public static void createTable()
{
//Create all your Letter to number Mapping here.
//Add all the letters and digits
letter.add("a");
digit.add("1");
letter.add("b");
digit.add("2");
letter.add("c");
digit.add("3");
letter.add("d");
digit.add("4");
letter.add("e");
digit.add("5");
letter.add("f");
digit.add("6");
letter.add("g");
digit.add("7");
letter.add("h");
digit.add("8");
letter.add("i");
digit.add("9");
letter.add("j");
digit.add("10");
letter.add("k");
digit.add("11");
letter.add("l");
digit.add("12");
letter.add("m");
digit.add("13");
letter.add("n");
digit.add("14");
letter.add("o");
digit.add("14");
letter.add("p");
digit.add("15");
//Carry so on till Z
}
public static String letterToDigit(String input)
{
String[] individual = input.split(" ");
String result="";
for(int i=0;i<individual.length;i++){
if(letter.contains(individual[i])){
result+=Integer.toString(letter.indexOf(individual[i])+1)+ " ";
}
}
return result;
}
public static String digitToLetter(String input)
{
String[] individual = input.split(" ");
String result="";
for(int i=0;i<individual.length;i++){
if(digit.contains(individual[i])){
result+=letter.get(digit.indexOf(individual[i])) + " ";
}
}
return result;
}
}

I would actually not use replace in this case.
A more generic solution would be to simply convert it to a char and subtract the char a from it.
int n = word.charAt(0) - 'a' + 1;
This should return an int with the value you are looking for.
If you want this to be an string you can easily do
String s = Integer.parseInt(word.charAt(0) - 'a' + 1);
And as in your case you are doing a whole string looping through the length of it and changing all would give you the result
String s = "";
for(int i = 0; i < word.length(); i++) {
if(s.charAt(i) != ' ') {
s = s + Integer.toString(word.charAt(i) - 'a' + 1) + " ";
}
}
and then if you want this back to an String with letters instead
String text = "";
int temp = 0;
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) == ' ') {
text = text + String.valueOf((char) (temp + 'a' - 1));
temp = 0;
} else if {
temp = (temp*10)+Character.getNumericValue(s.charAt(i));
}
}

You can just reverse the replacement:
String text = number.replace("11","k").replace("2","b").replace("6","f").replace("1","a");
Simplest solution IMO.
When adding other numbers, first replace these with two digits, then these with one.

Replace this:
String text = number.replace("1", "a").replace("2","b").replace("6","f").replace("11","k");
By this:
String text = number.replace("11","k").replace("1", "a").replace("2","b").replace("6","f");
Right now, the first replace you're doing: ("1", "a")
is invalidating the last one: ("11","k")

I think you would need to store the number as an array of ints. Otherwise, there is no way of knowing if 11 is aa or k. I would create a Map and then loop over the characters in the String. You could have one map for char-to-int and one for int-to-char.
Map<Character,Integer> charToIntMap = new HashMap<Character,Integer>();
charToIntMap.put('a',1);
charToIntMap.put('b',2);
charToIntMap.put('f',6);
charToIntMap.put('k',11);
Map<Integer,Character> intToCharMap = new HashMap<Integer,Character>();
intToCharMap.put(1,'a');
intToCharMap.put(2,'b');
intToCharMap.put(6,'f');
intToCharMap.put(11,'k');
String testStr = "abfk";
int[] nbrs = new int[testStr.length()];
for(int i = 0; i< testStr.length(); i++ ){
nbrs[i] = charToIntMap.get(testStr.charAt(i));
}
StringBuilder sb = new StringBuilder();
for(int num : nbrs){
sb.append(num);
}
System.out.println(sb.toString());
//Reverse
sb = new StringBuilder();
for(int i=0; i<nbrs.length; i++){
sb.append(intToCharMap.get(nbrs[i]));
}
System.out.println(sb.toString());

This failed because the replace("1", "a") replaced both 1s with a characters. The quickest fix is to perform the replace of all the double-digit numbers first, so there are no more double-digit numbers left when the single-digit numbers get replaced.
String text = number.replace("11","k").replace("1", "a").
replace("2","b").replace("6","f");

Related

Randomise each element of String from inside? [duplicate]

This question already has answers here:
Randomize the letters in the middle of the word, while keeping the first and last letters unchanged
(5 answers)
Closed 10 months ago.
I am trying to change the place of characters in a string. The first and last have to stay like they are.
For example:
String str = "String test print out";
The output should be for example:
Sirntg tset pirnt out
The first and last character of each word have to stay the rest have to change randomly:
Here is the code I already did, I tried to split the element of the string in an array and split them, but it's not working:
import java.util.*;
public class Main
{
public static void main(String[] args) {
String str = "String test out";
String[] words = str.split("\\s");
Random rnd = new Random();
ArrayList<Integer> digitList = new ArrayList<Integer>();
for(int j = 0;0<=words[].length();j++){
int lst = words[j].length();
char first = words[j].charAt(0);
char last = words[j].charAt(words[j].length() - 1);
for(int i =1, random = 0; i < words[j].length()-1; i++){
do{
random = rnd.nextInt(words[j].length()-2)+1;
}while(digitList.contains(random));
digitList.add(random);
System.out.print(words[j].charAt(random));
}
}
}
}
You could make use of some nifty functionality in Java's collection framework:
public static void main(String[] args) {
String str = "String test out";
for (String word : str.split("\\s")) {
List<Character> chars = word.chars()
.mapToObj(e -> (char) e)
.collect(Collectors.toList());
// shuffle the letters in the word, except for the first one and last one
Collections.shuffle(chars.subList(1, chars.size() - 1));
String shuffledWord = chars.stream()
.map(String::valueOf)
.collect(Collectors.joining());
System.out.println(shuffledWord);
}
}
Here is a really efficient way to do it. Instead of splitting, changing strings and merging them back together, create a single StringBuilder and use a Pattern to go through each word, scramble them and then return the string.
/** This pattern matches a word, and group 1 excludes the first and last letter. */
static final Pattern WORD = Pattern.compile("\\b\\w(\\w{2,})\\w\\b");
public String scrambleWords(String input) {
Random random = new Random();
StringBuilder s = new StringBuilder(input);
Matcher m = WORD.matcher(input);
while (m.find()) {
int start = m.start(1);
int end = m.end(1);
for (int i = start; i + 1 < end; i++) {
int j = random.nextInt(i + 1, end);
char c1 = s.charAt(i);
char c2 = s.charAt(j);
s.setCharAt(i, c2);
s.setCharAt(j, c1);
}
}
return s.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?

How to count string from last 3rd comma in Java?

I am using String s="abc,def,hi,hello,lol"
By using Java, how we can split the string from the last 3rd comma and get the string and string count?
Need Output as:
,hi,hello,lol
And the count is 13.
Can you please guide me to better code?
Below is my code, but it removes String from the last 3rd comma.
String s ="abc,def,hi,hello,lol";
String[] split = s.split(",");
String newStr = "";
for(int i = 0 ; i < split.length -3 ; i++){
newStr += split[i] + ",";
}
newStr = newStr.substring(0, newStr.length() - 1);
System.out.println(newStr);
Look at String class API.
You can use lastIndexOf(String str, int fromIndex), substring(int beginIndex) and length() methods.
Follow below steps:
Call lastIndexOf 3 times and note down the return value.
Use substring to get string from this index.
Use length to get count.
Try this one,
String data ="abc,def,hi,hello,lol";
StringBuilder sb = new StringBuilder(data);
sb.reverse();
data= sb.toString();
List<String> split = new ArrayList<String>();
int startIndex = 0;
int n = 0;
for (int i = data.indexOf(',') + 1; i > 0; i = data.indexOf(',', i) + 1, n++) {
if (n % 3 == 2) {
split.add(data.substring(startIndex, i ));
startIndex = i;
}
}
split.add(data.substring(startIndex));
for(String s : split)
{
sb = new StringBuilder(s);
s = sb.reverse().toString();
System.out.println(s+" : "+s.length());
}
output :
,hi,hello,lol : 13
abc,def : 7
This one arrives at the answer in only two statements:
public static void main(String[] args) {
String s = "abc,def,hi,hello,lol";
String[] pieces = s.split("(?=,)"); // split using positive lookahead
String answer = (pieces.length < 3) ? "": // check if not enough pieces
Arrays.stream(pieces).skip(pieces.length - 3).collect(Collectors.joining());
System.out.format("Answer = \"%s\"%n", answer);
System.out.format("Count = %d%n", answer.length());
}
I split at the position before each comma using positive lookahead, because if you use a simple split(",") then your program would fail for strings that end with comma.
String output = s.substring(s.indexOf(",", 6));
System.out.println(" string from last 3rd comma -> "+ output +"\n and count -> "+ output.length() );
console output:
string from last 3rd comma -> ,hi,hello,lol and count -> 13

A function that display the same text with two letters reversed

I'm trying to make an encryptor.What i want it to do:
Get the text i enter and reverse the first two letters of every word
and then display it again.
I have tried a lot of ways.This is the last one i've tried:
private void TranslateToEf(){
String storage = Display.getText();
String[] arr = storage.split("\\W+");
for ( String ss : arr) {
char c[] = ss.toCharArray();
char temp = c[0];
c[0] = c[1];
c[1] = temp;
String swappedString = new String(c);
Display.appendText(swappedString + " ");
}
}
You may want to consider maintaining all the delimiters lost from the first String.split("\\W+") so they can be included in the final result. I would do that with a String.split("\\w+")
You may also want to consider that when you swap the first two letters, if the first letter is capital it becomes lowercase and the second letter becomes uppercase. Otherwise, just do a direct swap.
Code sample:
public static void main(String[] args) throws Exception {
String data = "Hello;World! My name is John. I write code.";
String[] words = data.split("\\W+");
String[] delimiters = data.split("\\w+");
int delimiterIndex = 0;
StringBuilder sb = new StringBuilder();
for (String word : words) {
if (word.length() < 2) {
sb.append(word);
} else {
char firstLetter = word.charAt(0);
char secondLetter = word.charAt(1);
if (Character.isUpperCase(firstLetter)) {
// Swap the first two letters and change casing
sb.append(Character.toUpperCase(secondLetter))
.append(Character.toLowerCase(firstLetter));
} else {
// Swap the first two letters
sb.append(secondLetter)
.append(firstLetter);
}
// Append the rest of the word past the first two letters
sb.append(word.substring(2));
}
// Append delimiters
if (delimiterIndex < delimiters.length) {
// Skip blank delimiters if there are any
while (delimiters[delimiterIndex].isEmpty()) {
delimiterIndex++;
}
// Append delimiter
sb.append(delimiters[delimiterIndex++]);
}
}
data = sb.toString();
// Display result
System.out.println(data);
}
Results:
Ehllo;Owrld! Ym anme si Ojhn. I rwite ocde.
public class Encrypto {
public static void main(String[] args) {
String input="Hello World";
String [] word = input.split(" ");
// System.out.println(word[0]);
String encryWord="";
for(int i=0;i<word.length;i++){
if (word[i].length() > 0) {
String tmp0 = String.valueOf(word[i].charAt(1));
String tmp1 = String.valueOf(word[i].charAt(0));
encryWord += tmp0.toLowerCase() + tmp1.toLowerCase() + word[i].substring(2) + " ";
}else{
encryWord +=word[i];
}
}
System.out.println(encryWord);
}
}
I think answer is more helpful for you
There are a few problems.
Declare zz outside the loop if you want to use it outside.
Append zz on every iteration. Not just assign it.
Something like this,
private void TranslateToEf(){
String storage = Display.getText();
String[] arr = storage.split("\\W+");
String zz = "";
for ( String ss : arr) {
char c[] = ss.toCharArray();
char temp = c[0];
c[0] = c[1];
c[1] = temp;
String swappedString = new String(c);
String b= " ";
zz += swappedString + b;
}
Display.setText(zz + " ");
}
You are splitting with non-word (\W+) characters, but replacing it only with a space " ". This could alter the string with special characters.
Not sure what exactly you are looking for but i little modification in your code see if this suits your needs
String storage = "Test test t";
String[] arr = storage.split("\\W+");
String abc = "";
for ( String ss : arr) {
if(ss.length() > 1)
{
char c[] = ss.toCharArray();
char temp = c[0];
c[0] = c[1];
c[1] = temp;
String swappedString = new String( c );
String b = " ";
String zz = swappedString + b;
abc = abc + zz;
}else{
abc = abc + ss;
}
}
System.out.println(abc);
In Java strings are immutable. You can't modify them "on the fly", you need to reassign them to a new instance.
Additionally, you are setting the last display text to zz, but zz is a local variable to your loop, and therefore it gets re-instantiated with every iteration. In other words, you would be assigning to display only the last word!
Here is what you have to do to make it work:
String storage = Display.getText();
String[] arr = storage.split("\\W+");
String[] newText = new String[arr.length];
for ( int i = 0; i<arr.length; i++) {
String original = arr[i];
String modified = ((char) original.charAt(1)) + ((char) original.charAt(0)) + original.substring(2);
newText[i] = modified;
}
//Join with spaces
String modifiedText = Arrays.asList(newText).stream().collect(Collectors.join(" "));
Display.setText(modifiedText);
Note that:
1) We are assuming all strings have at least 2 chars
2) that your splitting logic is correct. Can you think some edge cases where your regexp fails?

Replace " " of a string with "%20" - Complexity issue, which of the two below mentioned should be preferred?

Converting it to char array and then concatenating it back replacing spaces with "%20".
OR
Dividing string into substrings with "white space" as the "separator" and just combining the strings with "%20" between them.
For eg:
Str = "This is John Shaw "
(There are as many extra spaces at the end as there are spaces in the string)
expected outcome:
"This%20is%20John%20Shaw"
Is it not this ?
txt = txt.replaceAll(" ", "%20");
Let me know if I understood it wrong.
By replaceAll method of the String class as follow.
String str = "This is John Shaw ";
str = str.replaceAll(" ", "%20");
Output
This%20is%20John%20Shaw%20
You can write both algorithms with a complexity O(n) where n is the number of characters in the String but there are much better algorithms to do that.
By the way I wrote an example that show you the computing time, one method is faster than the other but they are both, as I said, O(n)
public class ComplexityTester
{
//FIRST METHOD
public static String replaceSpacesArray(String str)
{
str = str.trim(); // leading and trailing whitespaces omitted
char[] charArray = str.toCharArray();
String result = "";
for(int i = 0; i<charArray.length; i++) // it replaces spaces with %20
{
if(charArray[i] == ' ') //it's a space, replace it!
result += "%20";
else //it's not a space, add it!
result += charArray[i];
}
return result;
}
//SECOND METHOD
public static String replaceSpacesWithSubstrings(String str)
{
str = str.trim(); // leading and trailing whitespaces omitted
String[] words = new String[5]; //array of strings, to add substrings
int wordsSize = 0; //strings in the array
//From the string to an array of substrings
//(the words separated by spaces of the string)
int indexFrom = 0;
int indexTo = 1;
while(indexTo<=str.length())
{
if(wordsSize == words.length) //if the array is full, resize it!
words = resize(words);
//we reach the end of the sting, add the last word to the array!
if(indexTo == str.length())
{
words[wordsSize++] = str.substring(indexFrom, indexTo++);
}
else if(str.substring(indexTo-1,indexTo).equals(" "))//it's a space
{
//we add the last word to the array
words[wordsSize++] = str.substring(indexFrom, indexTo-1);
indexFrom = indexTo; //update the indices
indexTo++;
}
else //it's a character not equal to space
{
indexTo++; //update the index
}
}
String result = "";
// From the array to the result string
for(int i = 0; i<wordsSize; i++)
{
result += words[i];
if(i+1!=wordsSize)
result += "%20";
}
return result;
}
private static String[] resize(String[] array)
{
int newLength = array.length*2;
String[] newArray = new String[newLength];
System.arraycopy(array,0,newArray,0,array.length);
return newArray;
}
public static void main(String[] args)
{
String example = "The Java Tutorials are practical guides "
+"for programmers who want to use the Java programming "
+"language to create applications. They include hundreds "
+"of complete, working examples, and dozens of lessons. "
+"Groups of related lessons are organized into \"trails\"";
String testString = "";
for(int i = 0; i<100; i++) //String 'testString' is string 'example' repeted 100 times
{
testString+=example;
}
long time = System.currentTimeMillis();
replaceSpacesArray(testString);
System.out.println("COMPUTING TIME (ARRAY METHOD) = "
+ (System.currentTimeMillis()-time));
time = System.currentTimeMillis();
replaceSpacesWithSubstrings(testString);
System.out.println("COMPUTING TIME (SUBSTRINGS METHOD) = "
+ (System.currentTimeMillis()-time));
}
}

Categories