How would I replace a string like "Hello" with "Helko", only replacing the second L but not the first?
Use replaceAll with regular expression:
System.out.println("Hello".replaceAll("((?!^).*?|[^l]*l.*?)l","$1k"));
Simple Approach (based on excluding the second l):
Search for first index of l using indexOf and do another search for l but this time start searching from firstL + 1 which will lead to the second index l if exist!
Do a test if there is second l, If So Exclude the second l by using substring which take only the first part (start from zero till secondL) and second part (start from secondL+1 till the end), Concatenate them with k.
public static String removeSecondL(String str) {
int firstL = str.indexOf('l');
int secondL = str.indexOf('l', firstL+1);
if(secondL != -1) {
String firstPart = str.substring(0, secondL);
String secondPart = str.substring(secondL + 1);
return firstPart + 'k' + secondPart;
}
return str;
}
Tests:
public static void main(String[] args) {
System.out.println(removeSecondL("Hello")); // Helko
System.out.println(removeSecondL("lololo")); // lokolo
System.out.println(removeSecondL("no l")); // no l
}
Another Approach: Convert the String into a char array, and declare a variable lFound gonna look for the first occurrence of letter l, if it found next l will be converted to k and exit the loop by break.
String str = "Hello";
char[] chars = str.toCharArray();
boolean lFound = false;
for (int i = 0; i < chars.length; i++) {
if(lFound) {
if(chars[i] == 'l')
{
chars[i] = 'K';
break;
}
}else {
lFound = chars[i] == 'l'; //if(chars[i] == 'l') lFound = true;
}
}
System.out.println(chars); //HelKo
Lately, I turned to the conversation and I saw you writing:
I wanted to replace one instance of a character with another, like "aaaaa" with "aabaa", where only the third 'a' is replaced with 'b', but not the others.
Just follow second approach I posted with additional tests.
public static char[] removeSpecificChar(String str, char a, char b, int position) {
char[] chars = str.toCharArray();
int pos = 1;
for (int i = 0; i < chars.length; i++) {
if(pos == position) {
if(chars[i] == a)
{
chars[i] = b;
break;
}
}else {
pos += (chars[i] == a) ? 1 : 0;
}
}
return chars;
}
Test:
String str = "aaaaa";
System.out.println(removeSpecificChar(str, 'a', 'b', 3));
Print:
aabaa
Related
so I have task to double number of letter "a" every time it occurs in a string.
For example sentence "a cat walked on the road" , at the end must be "aa caaaat waaaaaaaalked on the roaaaaaaaaaaaaaaaa" . I had something like this on my mind but it doubles every charachter, not only "a".
public static void main(String[] args) {
String s = "a bear walked on the road";
String result = "";
int i = 0;
while(i<s.length()){
char a = s.charAt(i);
result = result + a + a;
i++;
}
System.out.println(result);
}
You need to check what the char a is (in your case, 'a'). Additionally, you do not repeat the characters more than twice in your code, hence not getting the answer you expected: result = result + a + a only adds 'a' twice, not giving you: "aa caaaat waaaaaaaalked...".
Here is the solution:
public static void main(String[] args) {
String s = "a bear walked on the road";
String result = "";
char lookingFor = 'a'; // Can change this to whatever is needed
int counter = 2;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == lookingFor) { // The current character is what we need to be repeated.
// Repeat the character as many times as counter is (each loop: 2, 4, 6, 8, ...)
for (int j = 0; j < counter; j++) {
result += lookingFor;
}
counter *= 2; // Double counter at every instance of 'a'
}
else { // The current char is not what we are looking for, so we just add it to our result.
result += s.charAt(i);
}
}
System.out.println(result);
}
The problems are:
you are doubling every character because you are not testing if it is an 'a' or not.
and you are not doubling the substitution each time.
Here is a modified version of your solution.
String s = "a bear walked on the road";
String result = "";
String sub = "aa";
int i = 0;
while(i<s.length()){
// get the character
char ch = s.charAt(i++);
//if it an a, append sub to result
// and double sub.
if (ch == 'a') {
result += sub;
sub += sub;
} else {
// otherwise, just append the character
result += ch;
}
}
Here is another way.
check each character and double the replacement each time an a is encountered.
String str = "a cat walked on the road";
StringBuilder sb = new StringBuilder();
String sub = "a";
for (String s : str.split("")) {
sb.append(s.equals("a") ? (sub += sub) : s);
}
System.out.println(sb);
prints
aa caaaat waaaaaaaalked on the roaaaaaaaaaaaaaaaad
Try this out:
public static void main(String[] args) {
char letterToSearch = 'a'
String myString = "a bear walked on the road";
StringBuilder result = new StringBuilder();
int occurrance = 0;
for (int i = 0; i < myString.length(); i++){
char currChar = myString.charAt(i);
if (currChar == letterToSearch){
occurrance+=1;
for (int j = 0; j < 2*occurrance; j++){
result.append(currChar);
}
} else {
result.append(currChar);
}
}
System.out.println(result);
}
The variable occurrance keeps track of how many as you have.
Can someone help me with algorith.
Basicaly if I have word Hello,I should take last letter and put in first position,then take penultimate letter and put it after second letter and so on,take third letter and put it in third position.
It should look like that:
Word:Hello
1)oHell
2)oHlel
This is my code which I have by right now.
public static String caesarAlgorithm(
String word) {
char[] arr = word.toCharArray();
int s=arr.length-1;
for (int i=0; i<arr.length/2; i++) {
char temp = arr[i];
char temp1=arr[i+1];
arr[i] = arr[s];
arr[i+1] = temp;
s--;
}
return new String(arr);
}
public static void main(String[] args) {
System.out.print(caesarAlgorithm("Sokolade"));
}
}
It should outpirnt in my case eSdoaklo
Thanks.
Put the result in a new String. That way, you won't have to handle the index shifting on each permutation.
public static String caesarAlgorithm(String word) {
char[] arr = word.toCharArray();
String result = "";
for (int i=0; i<arr.length/2; i++) {
// get the i-th letter from the end and put it in the result string
result += arr[arr.length-1-i]; // -1 because index starts at 0
// get the i-th letter from the begining and put it in the result string
result += arr[i];
}
if (arr.length%2 != 0) {
// in case the number of characters is odd, add the middle character to the end of the string
result += arr[arr.length%2+1];
}
return result;
}
Side Note:
The method name is missleading as it is not a ceasar cipher algorithm. With a caesar cipher, you change all of the character values with the same offset, but their index doesn't change.
This kind of problem has a natural recursive structure:
static String shake(String str, int n)
{
if(n == 0) return str;
String lastChar = str.substring(str.length()-1);
String firstChar = str.substring(0, 1);
String middle = str.substring(1, str.length()-1);
return lastChar + firstChar + shake(middle, n-1);
}
Called via the helper function:
static String shake(String str)
{
return shake(str, str.length()/2);
}
Test:
System.out.println(shake("Hello"));
System.out.println(shake("Sokolade"));
Output:
oHlel
eSdoaklo
public static String caesarAlgorithm(String word) {
StringBuilder builder = new StringBuilder();
int len = word.length();
int mid = len / 2;
int i = 0, j = len - 1;
while (i < mid && j > 0) {
builder.append(word.charAt(j--) + "").append(word.charAt(i++) + "");
}
if (len % 2 != 0)
builder.append(word.charAt(mid));
return builder.toString();
}
, output
oHlel
eSdoaklo
char [] text = {'H','e','l','L','o','H','e','l','L','o'};
char[] pat = {'H','e','?','l','o'}; //'?' stands for every possible sign
We can ignore if the letters are upper or lower case.
Now I need to output how often it occurs.
Output: He?lo is in HelLoHelLo 2x
I know that you can use string methods like "contain" but how can I consider the question mark ?
public int matchCount(char[] text, char[] pattern) {
int consecCharHits = 0, matchCount = 0;
for (int i = 0; i < text.length; i++) {
if (text[i] == pattern[consecCharHits] || '?' == pattern[consecCharHits]) { // if char matches
consecCharHits++;
if (consecCharHits == pattern.length) { // if the whole pattern matches
matchCount++;
i -= consecCharHits - 1; // return to the next position to be evaluated
consecCharHits = 0; // reset consecutive char hits
}
} else {
i -= consecCharHits;
consecCharHits = 0;
}
}
return matchCount;
}
The way I would naively implement it without thinking too much about it
create inputIndex and set it to 0
create matchIndex and set it to 0
iterate over the input by incrementing the inputIndex one by one
compare the char in the input at inputIndex with the char in the match at matchIndex
if they "match" increment the matchIndex by one - if they don't set matchIndex to 0
if the matchIndex equals to your pat length increment the actual count of matches by one and set matchIndex back to 0
Where I wrote "match" you need to implement your custom match logic, ignoring the case and considering everything a match if the pattern at this place is a ?.
#Test
public void match() {
char [] text = {'H','e','l','L','o','H','e','l','L','o'};
char[] pat = {'H','e','?','l','o'}; //'?' stands for every possible sign
printMatch(text, pat);
}
private void printMatch(char[] text, char[] pat) {
String textStr = new String(text);
String patStr = new String(pat);
final String regexPattern = patStr.replace('?', '.').toLowerCase();
final Pattern pattern = Pattern.compile(regexPattern);
final Matcher matcher = pattern.matcher(textStr.toLowerCase());
while (matcher.find()) {
System.out.println(patStr + " is in " + textStr );
}
}
What about this ?
static int countPatternOccurences (char [] text, char [] pat)
{
int i = 0;
int j = 0;
int k = 0;
while ( i < text.length)
{
int a = Character.getNumericValue(pat[j]);
int b = Character.getNumericValue(text[i]);
if (a == b || pat[j] =='?')
{
j++;
}
else
{
j=0;
//return 0;
}
if(j == pat.length)
{
k++;
j = 0;
}
i++;
}
return k; // returns occurrences of pat in text
}
I have this code that is supposed to do what the title said, reverse the order of characters without changing the order of the words:
package stackTests;
import java.util.Scanner;
import java.util.Stack;
public class StackTest
{
Stack<Character> stack;
public StackTest()
{
stack = new Stack<Character>();
}
public String reverseString(String str)
{
int start = 0;
int start2 = 0;
int size;
char space = ' ';
char[] cArr;
Scanner scan = new Scanner(str);
cArr = str.toCharArray();
for (; start < cArr.length; start++)
{
if(cArr[start] == space || start == cArr.length - 1)
{
for (; start2 < stack.size(); start++)
{
System.out.print(stack.pop());
}
}
else
{
stack.push(cArr[start]);
}
start2 = 0;
}
return str;
}
}
It works fine if I enter a single word like "Hello"--it will output "olleH"--but as soon as it gets more complicated than one word it starts to output some weird things."Hello my name is" outputs "ollehem". I'm really new to Stacks and this is my first time using them. I'm not sure if there is a logic error or improper use of Stacks.
you're not outputting original spaces, this is why you're seeing strange results
here is fixed version:
public static void reverseString(final String str) {
final Stack<Character> stack = new Stack<>();
for (int i = 0; i < str.length(); i++) {
final char c = str.charAt(i);
if (c == ' ') {
while (!stack.isEmpty())
System.out.print(stack.pop());
System.out.print(' ');
} else
stack.push(c);
}
while (!stack.isEmpty())
System.out.print(stack.pop());
}
another version without stack, with in-place replacement:
public static void reverseString(final String str) {
final char[] chars = str.toCharArray();
int start = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i] == ' ') {
reverse(chars, start, i - 1);
start = i + 1;
}
}
reverse(chars, start, chars.length - 1);
System.out.println(new String(chars));
}
private static void reverse(final char[] chars, int s, int e) {
while (s < e) {
final char t = chars[s];
chars[s] = chars[e];
chars[e] = t;
s++;
e--;
}
}
If you HAVE to use a stack, I would follow an algorithm like this:
String myString = "Hello World";
Stack<Character> stack = new Stack<Character>();
StringBuilder sb = new StringBuilder();
String[] splitString = myString.split(" ");
//Iterate through each word in the string
for(String s : splitString){
//Push each character of the word into LIFO stack
for(char c : s.toCharArray()){
stack.push(c);
}
//Build new string with reverse ordered characters
while(!stack.isEmpty()){
sb.append(stack.pop());
}
//Append a space as long as it's not the last word of the original string
if(!s.equals(splitString[splitString.length - 1]))
sb.append(" ");
}
//Print the new string
System.out.println(sb.toString());
I'm not sure efficiency matters to you, but this algorithm would work in linear time, where n is the number of characters in the string.
Here is how you can do it in-place without using any extra space (Not using stack):
public class ReverseWordsInplace {
public static void main(String[] args) {
reverseWords(new StringBuilder("This is a test"));
}
public static void reverseWords(StringBuilder s) {
StringBuilder str = new StringBuilder(s);
int startWordIndex = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == ' ' || str.length() - 1 == i) {
int x = 0;
int endWordIndex = str.charAt(i) == ' ' ? i - 1 : i;
while (endWordIndex - x > startWordIndex + x) {
char c1 = str.charAt(startWordIndex + x);
char c2 = str.charAt(endWordIndex - x);
str.setCharAt(startWordIndex + x, c2);
str.setCharAt(endWordIndex - x, c1);
x++;
}
startWordIndex = i + 1;
}
}
System.out.println(str);
}
}
Output:
sihT si a tset
I need to look at each word in an array, so I made a for loop with array[i] equaling String word, then I made another for loop that has an if statement that is changing word.charAt(i) with word.charAt(i+1) and changing word.charAt(i+1) = 'A'.
The objective is to 'encrypt' the word by checking if i is equal to 'A', and if it is then switching positions with i+1.
Here is my code:
for(int i = 0; i < unchangedFileInput.length; i++) {
String word = unchangedFileInput[i];
for(int v = 0; v < word.length();v++) {
if (word.charAt(v) == 'A'
&& word.charAt(v+1) != 'A'
&& word.length() > 1) {
char[] mywordChars = word.toCharArray();
temp = mywordChars[v+1];
mywordChars[v] = mywordChars[v+1];
mywordChars[v+1] = 'A';
word = String.valueOf(mywordChars);
} else {
System.out.println(word);
}
}
System.out.println(word);
}
unchangedFileInput is an array that has the values of:
AVACADO
CHICKEN
BACON
AARDVARK
This is what the final result should look like:
AVACADO = VACADAO
CHICKEN = UNCHANGED
BACON = BCAON
AARDVARK = ARADVRAK
NAAN = NANA
You need to check that you don't go past the array limit first. I created a test framework,
public static void main(String[] args) {
String[] unchangedFileInput = { "AVACADO", "CHICKEN", "BACON",
"AARDVARK", "NAAN" };
String[] changedFileInput = new String[unchangedFileInput.length];
for (int i = 0; i < unchangedFileInput.length; i++) {
changedFileInput[i] = transformName(unchangedFileInput[i]);
System.out.printf("%s = %s%n", unchangedFileInput[i],
changedFileInput[i]);
}
}
And then wrapped your code in a method (and just created a new String with a StringBuilder removing the array conversions),
private static String transformName(String in) {
StringBuilder sb = new StringBuilder();
for (int i = 0, len = in.length(); i < len; i++) {
char ch = in.charAt(i);
if (ch == 'A') {
if (i + 1 < in.length() && in.charAt(i + 1) != 'A') {
sb.append(in.charAt(i + 1));
i++;
}
}
sb.append(ch);
}
return sb.toString();
}
And I get your requested output,
AVACADO = VACADAO
CHICKEN = CHICKEN
BACON = BCAON
AARDVARK = ARADVRAK
NAAN = NANA
In order to achieve what you want you need to start the iteration from the end of the word to the beginning, otherwise, when you swap 'A' with the following character, you will have the 'A' again at the next iteration. If you start from the end, you will hit each 'A' only once.
Using this code
for(int v = 0; v < word.length();v++) {
if (word.charAt(v) == 'A' && word.charAt(v+1)
You will get an IndexOutOfBoundsException at the end of the String.
And if you are talking about the IndexOutOfBoundsException error!!
I suggested, v < word.length() - 1;