Say I have a string, and I want to change the second "a" in that string to an "e".
String elephant = "elaphant";
I tried using String.replace(), but that replaces all the a's in the string, returning "elephent".
elephant.replace("a", "e");
Is there any loop or method I can use to accomplish this? Thank you all.
You could convert it to a char array, switch out the desired letter, then convert it back to String?
String elephant = "elaphant";
int index = -1;
int count = 0;
while(count < 2) {
index = elephant.indexOf("a", index+1);
count++;
}
if(index >= 0 && index < elephant.length()) {
char[] tmp = elephant.toCharArray();
tmp[index] = "e";
elephant = new String(tmp);
}
Or if you prefer StringBuilder
StringBuilder sbTemp = new StringBuilder(elephant);
sbTmp = sbTmp.replace(index, index+1, "e");
elephant = sbTmp.toString();
You need to get the index of the first occurrence of a letter.
Try using the indexOf method.
int myIndex = elephant.indexOf('a');
Once you have the index, use StringBuilder to replace the value. Something like:
StringBuilder sb = new StringBuilder(elephant);
sb[index] = myIndex;
elephant = sb.ToString();
Code:
String elephant = "elaphant";
//convert the string to array of string
String[] sp = elephant.split("");
int countA = 0;
boolean seenTwice = false;
String result = "";
for (int i = 0; i < sp.length; i++) {
//count number of times that a has been seen
if (sp[i].equals("a")) {
countA++;
}
// if a has been seen twice and flag seenTwice has not been see
if (countA == 2 && !seenTwice) {
result += "e";
seenTwice = true;
} else {
result += sp[i];
}
}
System.out.println(result);
Output:
elaphent
Related
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 am working on question 1.5 from the book Cracking The Coding interview. The problem is to take a string "aabcccccaaa" and turn it into a2b1c5a3.
If the compressed string is not smaller than the original string, then return the original string.
My code is below. I used an ArrayList because I would not know how long the compressed string would be.
My output is [a, 2, b, 1, c, 5], aabc, []. When the program gets to the end of string, it doesn't have a character to compare the last character too.
import java.util.*;
import java.io.*;
public class stringCompression {
public static void main(String[] args) {
String a = "aabcccccaaa";
String b = "aabc";
String v = "aaaa";
check(a);
System.out.println("");
check(b);
System.out.println("");
check(v);
}
public static void check(String g){
ArrayList<Character> c = new ArrayList<Character>();
int count = 1;
int i = 0;
int h = g.length();
for(int j = i + 1; j < g.length(); j++)
{
if(g.charAt(i) == g.charAt(j)){
count++;
}
else {
c.add(g.charAt(i));
c.add((char)( '0' + count));
i = j;
count = 1;
}
}
if(c.size() == g.length()){
System.out.print(g);
}
else{
System.out.print(c);
}
}
}
In the last loop you're not adding the result to the array. When j = g.length() still needs to add the current char and count to the array. So you could check the next value of j before increment it:
for(int j = i + 1; j < g.length(); j++)
{
if(g.charAt(i) == g.charAt(j)){
count++;
}
else {
c.add(g.charAt(i));
c.add((char)( '0' + count));
i = j;
count = 1;
}
if((j + 1) = g.length()){
c.add(g.charAt(i));
c.add((char)( '0' + count));
}
}
I would use a StringBuilder rather than an ArrayList to build your compressed String. When you start compressing, the first character should already be added to the result. The count of the character will be added once you've encountered a different character. When you've reached the end of the String you should just be appending the remaining count to the result for the last letter.
public static void main(String[] args) throws Exception {
String[] data = new String[] {
"aabcccccaaa",
"aabc",
"aaaa"
};
for (String d : data) {
System.out.println(compress(d));
}
}
public static String compress(String str) {
StringBuilder compressed = new StringBuilder();
// Add first character to compressed result
char currentChar = str.charAt(0);
compressed.append(currentChar);
// Always have a count of 1
int count = 1;
for (int i = 1; i < str.length(); i++) {
char nextChar = str.charAt(i);
if (currentChar == nextChar) {
count++;
} else {
// Append the count of the current character
compressed.append(count);
// Set the current character and count
currentChar = nextChar;
count = 1;
// Append the new current character
compressed.append(currentChar);
}
}
// Append the count of the last character
compressed.append(count);
// If the compressed string is not smaller than the original string, then return the original string
return (compressed.length() < str.length() ? compressed.toString() : str);
}
Results:
a2b1c5a3
aabc
a4
You have two errors:
one that Typo just mentioned, because your last character was not added;
and another one, if the original string is shorter like "abc" with only three chars: "a1b1c1" has six chars (the task is "If the compressed string is not smaller than the original string, then return the original string.")
You have to change your if statement, ask for >= instead of ==
if(c.size() >= g.length()){
System.out.print(g);
} else {
System.out.print(c);
}
Use StringBuilder and then iterate on the input string.
private static string CompressString(string inputString)
{
var count = 1;
var compressedSb = new StringBuilder();
for (var i = 0; i < inputString.Length; i++)
{
// Check if we are at the end
if(i == inputString.Length - 1)
{
compressedSb.Append(inputString[i] + count.ToString());
break;
}
if (inputString[i] == inputString[i + 1])
count++;
else
{
compressedSb.Append(inputString[i] + count.ToString());
count = 1;
}
}
var compressedString = compressedSb.ToString();
return compressedString.Length > inputString.Length ? inputString : compressedString;
}
I am having difficulties with my method returning true. It is a boolean method that takes two words and tries to see if one can be turned into the other by transposing two neighboring letters. I have had no troubles getting the false boolean. When the code gets to the for loop with an if statement in it it runs fine but does not return true when the if statement is satisfied. For some reason it continues through the for loop. For example, when comparing "teh" and "the" when the loop hits 1 the if statement is satisfied but does not return true, the for lo
public static boolean transposable(String word1, String word2)
{
ArrayList<Character> word1char = new ArrayList<Character>();
ArrayList<Character> word2char = new ArrayList<Character>();
int word1length = word1.length();
int word2length = word2.length();
int count = 0;
String w1 = word1.toUpperCase();
String w2 = word2.toUpperCase();
if(word1length != word2length)
{
return false;
}
for(int i = 0; i < word1length; i++)
{
char letter1 = w1.charAt(i);
word1char.add(letter1);
char letter2 = w2.charAt(i);
word2char.add(letter2);
}
for(int i = 0; i < word1length; i++)
{
char w1c = word1char.get(i);
char w2c = word2char.get(i);
if(w1c == w2c)
{
count++;
}
}
if(count < word1length - 2)
{
return false;
}
for(int i = 0; i < word1length; i++)
{
char w1c = word1char.get(i);
char w2c = word2char.get(i+1);
if(w1c == w2c)
{
return true;
}
}
return false;
}
op just keeps running. What am I doing wrong?
As pointed out in the comments this doesn't seem to be the easiest way around this problem. Here is a solution which tries to follow your logic and includes the use of toUpperCase() and ArrayLists.
Going over your code it looks like you were getting a bit lost in your logic. This is because you had one method trying to do everything. Break things down into smaller methods and you also will benefit by not having to repeat code and it keeps things much cleaner. The code below is tested with Java8 (although there is no reason why this should not work with Java 7).
public static void main(String args[]) {
String word1 = "Hello";
String word2 = "Hlelo";
transposable(word1, word2);
}
private static boolean transposable(String word1, String word2) {
// Get an ArrayList of characters for both words.
ArrayList<Character> word1CharacterList = listOfCharacters(word1);
ArrayList<Character> word2CharacterList = listOfCharacters(word2);
boolean areWordsEqual;
// Check that the size of the CharacterLists is the same
if (word1CharacterList.size() != word2CharacterList.size()) {
return false;
}
// check to see if words are equal to start with
areWordsEqual = checkIfTwoWordsAreTheSame(word1CharacterList, word2CharacterList);
System.out.print("\n" + "Words are equal to be begin with = " + areWordsEqual);
if (!areWordsEqual) {
/*
This loop i must start at 1 because you can't shift an ArrayList index of 0 to the left!
Loops through all the possible combinations and checks if there is a match.
*/
for (int i = 1; i < word1CharacterList.size(); i++) {
ArrayList<Character> adjustedArrayList = shiftNeighbouringCharacter(word2CharacterList, i);
areWordsEqual = checkIfTwoWordsAreTheSame(word1CharacterList, adjustedArrayList);
System.out.print("\n" + "Loop count " + i + " words are equal " + areWordsEqual + word1CharacterList + adjustedArrayList.toString());
if (areWordsEqual) {
break;
}
}
}
return areWordsEqual;
}
// takes in a String as a parameter and returns an ArrayList of Characters in the order of the String parameter.
private static ArrayList<Character> listOfCharacters(String word) {
ArrayList<Character> wordCharacters = new ArrayList<Character>();
String tempWord = word.toUpperCase();
for (int wordLength = 0; wordLength < tempWord.length(); wordLength++) {
Character currentCharacter = tempWord.charAt(wordLength);
wordCharacters.add(currentCharacter);
}
return wordCharacters;
}
// takes in two character arrayLists, and compares each index character.
private static boolean checkIfTwoWordsAreTheSame(ArrayList<Character> characterList1, ArrayList<Character> characterList2) {
// compare list1 against list two
for (int i = 0; i < characterList1.size(); i++) {
Character currentCharacterList1 = characterList1.get(i);
Character currentCharacterList2 = characterList2.get(i);
if (!currentCharacterList1.equals(currentCharacterList2)) {
return false;
}
}
return true;
}
// this method takes in an ArrayList of characters and the initial index that we want to shift one place to the left.
private static ArrayList<Character> shiftNeighbouringCharacter(ArrayList<Character> characterListToShift, int indexToShiftLeft) {
ArrayList<Character> tempCharacterList = new ArrayList<Character>();
int indexAtLeft = indexToShiftLeft - 1;
// fill the new arrayList full of nulls. We will have to remove these nulls later before we can add proper values in their place.
for (int i = 0; i < characterListToShift.size(); i++) {
tempCharacterList.add(null);
}
//get the current index of indexToShift
Character characterOfIndexToShift = characterListToShift.get(indexToShiftLeft);
Character currentCharacterInThePositionToShiftTo = characterListToShift.get(indexAtLeft);
tempCharacterList.remove(indexAtLeft);
tempCharacterList.add(indexAtLeft, characterOfIndexToShift);
tempCharacterList.remove(indexToShiftLeft);
tempCharacterList.add(indexToShiftLeft, currentCharacterInThePositionToShiftTo);
for (int i = 0; i < characterListToShift.size(); i++) {
if (tempCharacterList.get(i) == null) {
Character character = characterListToShift.get(i);
tempCharacterList.remove(i);
tempCharacterList.add(i, character);
}
}
return tempCharacterList;
}
Hope this helps. If you are still struggling then follow along in your debugger. :)
I have 2 strings :
first= "BSNLP"
second = "PBN" (or anything that user enters).
Requirement is , O/P should return me the string with only those characters in first but not in second.
Eg. in this case O/P is SL
Eg2.
first = "ASDR"
second = "MRT"
, o/p = "ASD"
For this, the coding I have developed:
String one = "pnlm";
String two ="bsnl";
String fin = "";
for(int i =0; i<one.length();i++)
{
for(int j=0;j<two.length();j++)
{
//System.out.print(" "+two.charAt(j));
if(one.charAt(i) == two.charAt(j))
{
fin+=one.charAt(i);
}
}
}
ch=removeDuplicates(fin);
System.out.print(" Ret ::"+fin);
System.out.println("\n Val ::"+ch);
CH gives me the string with equal characters, but using this logic i cant get the unequal characters.
Can anyone please help?
You can use the Set interface to add all the second array of character so you can check it there later.
sample:
String one = "ASDR";
String two ="MRT";
StringBuilder s = new StringBuilder();
Set<Character> set = new HashSet<>();
for(char c : two.toCharArray())
set.add(c); //add all second string character to set
for(char c : one.toCharArray())
{
if(!set.contains(c)) //check if the character is not one of the character of second string
s.append(c); //append the current character to the pool
}
System.out.println(s);
result:
ASD
I have simple exchange your logic, see:
String one = "pnlm";
String two = "bsnl";
String fin = "";
int cnt;
for (int i = 0; i < one.length(); i++) {
cnt = 0; // zero for no character equal
for (int j = 0; j < two.length(); j++) {
// System.out.print(" "+two.charAt(j));
if (one.charAt(i) == two.charAt(j)) {
cnt = 1; // ont for character equal
}
}
if (cnt == 0) {
fin += one.charAt(i);
}
}
System.out.print(" Ret ::" + fin);
o/p: Ret ::pm.
public static void main(String[] args)
{
String one = "ASDR";
String two ="MRT";
String fin = unique(one, two);
System.out.println(fin);
}
private static String unique(final String one,
final String two)
{
final List<Character> base;
final Set<Character> toRemove;
final StringBuilder remaining;
base = new ArrayList<>(one.length());
toRemove = new HashSet<>();
for(final char c : one.toCharArray())
{
base.add(c);
}
for(final char c : two.toCharArray())
{
toRemove.add(c);
}
base.removeAll(toRemove);
remaining = new StringBuilder(base.size());
for(final char c : base)
{
remaining.append(c);
}
return (remaining.toString());
}
Iterate over the first string
For each character, check if the second string contains it
If it doesn't, add the caracter to a StringBuilder
Return stringBuilder.toString()
Please help me to identify my mistakes in this code. I am new to Java. Excuse me if I have done any mistake. This is one of codingbat java questions. I am getting Timed Out error message for some inputs like "xxxyakyyyakzzz". For some inputs like "yakpak" and "pakyak" this code is working fine.
Question:
Suppose the string "yak" is unlucky. Given a string, return a version where all the "yak" are removed, but the "a" can be any char. The "yak" strings will not overlap.
public String stringYak(String str) {
String result = "";
int yakIndex = str.indexOf("yak");
if (yakIndex == -1)
return str; //there is no yak
//there is at least one yak
//if there are yaks store their indexes in the arraylist
ArrayList<Integer> yakArray = new ArrayList<Integer>();
int length = str.length();
yakIndex = 0;
while (yakIndex < length - 3) {
yakIndex = str.indexOf("yak", yakIndex);
yakArray.add(yakIndex);
yakIndex += 3;
}//all the yak indexes are stored in the arraylist
//iterate through the arraylist. skip the yaks and get non-yak substrings
for(int i = 0; i < length; i++) {
if (yakArray.contains(i))
i = i + 2;
else
result = result + str.charAt(i);
}
return result;
}
Shouldn't you be looking for any three character sequence starting with a 'y' and ending with a 'k'? Like so?
public static String stringYak(String str) {
char[] chars = (str != null) ? str.toCharArray()
: new char[] {};
StringBuilder sb = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == 'y' && chars[i + 2] == 'k') { // if we have 'y' and two away is 'k'
// then it's unlucky...
i += 2;
continue; //skip the statement sb.append
} //do not append any pattern like y1k or yak etc
sb.append(chars[i]);
}
return sb.toString();
}
public static void main(String[] args) {
System.out.println(stringYak("1yik2yak3yuk4")); // Remove the "unlucky" strings
// The result will be 1234.
}
It looks like your programming assignment. You need to use regular expressions.
Look at http://www.vogella.com/articles/JavaRegularExpressions/article.html#regex for more information.
Remember, that you can not use contains. Your code maybe something like
result = str.removeall("y\wk")
you can try this
public static String stringYak(String str) {
for (int i = 0; i < str.length(); i++) {
if(str.charAt(i)=='y'){
str=str.replace("yak", "");
}
}
return str;
}