I am attempting to read this .txt file into my program (as an improvement over manual input) and i am having trouble converting my methods to accept the input txt file. i get a arrayindexoutofboundsexception on line "infix[--pos]='\0';"
class Functions {
void postfix(char infix[], char post[]) {
int position, und = 1;
int outposition = 0;
char topsymb = '+';
char symb;
Stack opstk = new Stack();
opstk.top = -1;
for (position = 0; (symb = infix[position]) != '\0'; position++) {
if (isoperand(symb))
post[outposition++] = symb;
else {
if (opstk.isempty() == 1)
und = 1;
else {
und = 0;
topsymb = opstk.pop();
}
while (und == 0 && precedence(topsymb, symb) == 1) {
post[outposition++] = topsymb;
if (opstk.isempty() == 1)
und = 1;
else {
und = 0;
topsymb = opstk.pop();
}
}// end while
if (und == 0)
opstk.push(topsymb);
if (und == 1 || (symb != ')'))
opstk.push(symb);
else
topsymb = opstk.pop();
}// end else
}// end for
while (opstk.isempty() == 0)
post[outposition++] = opstk.pop();
post[outposition] = '\0';
}// end postfix function
int precedence(char topsymb, char symb) {
/* check precedence and return 0 or 1 */
if (topsymb == '(')
return 0;
if (symb == '(')
return 0;
if (symb == ')')
return 1;
if (topsymb == '$' && symb == '$')
return 0;
if (topsymb == '$' && symb != '$')
return 1;
if (topsymb != '$' && symb == '$')
return 0;
if ((topsymb == '*' || topsymb == '/') && (symb != '$'))
return 1;
if ((topsymb == '+' || topsymb == '-') && (symb == '-' || symb == '+'))
return 1;
if ((topsymb == '+' || topsymb == '-') && (symb == '*' || symb == '/'))
return 0;
return 1;
} /* end precedence function */
private boolean isoperand(char symb) {
/* Return 1 if symbol is digit and 0 otherwise */
if (symb >= '0' && symb <= '9')
return true;
else
return false;
}/* end isoperand function */
}
public class Driver {
public static void main(String[] args) throws IOException {
Functions f = new Functions();
char infix[] = new char[80];
char post[] = new char[80];
int pos = 0;
char c;
System.out.println("\nEnter an expression is infix form : ");
try {
BufferedReader in = new BufferedReader(new FileReader("infix.txt"));
String str;
while ((str = in.readLine()) != null) {
infix = str.toCharArray();
}
in.close();
} catch (IOException e) {
}
infix[--pos] = '\0';
System.out.println("The original infix expression is : ");
for (int i = 0; i < pos; i++)
System.out.print(infix[i]);
f.postfix(infix, post);
System.out.println("\nThe postfix expression is : ");
for (int i = 0; post[i] != '\0'; i++)
System.out.println(post[i]);
}
}
Do should never ever do like this:
try {
...
} catch (IOException e) {
}
You loose some essential information about your code-running.
At lease you should print the stack trace to follow the investigation:
e.printStackTrace();
You may have a FileNotFound exception.
In addition you try to index your array to -1 in infix[--pos], pos is set to 0 before this statement.
1) Totally aside, but I think line in main should read:System.out.println("\nEnter an expression in infix form : ");
2) As well, i agree about the catch statement. You already have narrowed it down to being an IOExcpetion, but you can find so much more info out by printing wither of the following inside the catch
System.err.println(e.getMessage()); or e.printStackTrace()
Now to answer your question. You are initializing pos to the value 0, but the you are doing a PREINCREMENT on the line infix[--pos] = '\0'; so pos becomes -1 (clearly outside the scope of the array bounddaries).
I think you want to change that to a post increment infix[pos--] = '\0';. Perhaps?
And yes, your code DOES Look like C...
Related
This code is written when I was trying to solve the problem on Leet code(the link to the problem is given below), which performs the balancing parenthesis but failing for the condition ([}}]) could anyone help me.
Thank you.
problem link---> https://leetcode.com/problems/valid-parentheses/
import java.util.*;
public class expressionValidation
{
public static void main(String[] args)
{
try (Scanner sc = new Scanner(System.in))/*trying to avoid any kind of exceptions*/
{
String str = sc.nextLine();
String exp = "";/*new string to modify the given expression*/
int l = str.length();
for(int i=0;i<l;i++)
{
if(str.charAt(i)=='{'||str.charAt(i)=='('||str.charAt(i)=='['||str.charAt(i)=='}'||str.charAt(i)==']'||str.charAt(i)==')')
{
exp+=str.substring(i,i+1);/*newly modified string afterstrong text removing everything except brackets'(' '[' '{' ' }' ']' ')'*/
}
}
stack ob = new stack();
System.out.println(ob.isValid(exp)?"Balanced":"NOT Balanced");
}
}
}
## The following is the stack class
class stack
{
boolean isValid(String exp)
{
int l =exp.length();
if(l%2!=0)
return false;
Stack<Character> st = new Stack<Character>();
for(int i=0;i<l;i++)
{
if(exp.charAt(i)=='{' ||exp.charAt(i)=='(' ||exp.charAt(i)=='[' ) {
st.push(exp.charAt(i));
}
else if(exp.charAt(i)=='}' && !(st.isEmpty()) && st.peek()=='{') {
st.pop();
}
else if(exp.charAt(i)==')' && !(st.isEmpty()) && st.peek()=='(') {
st.pop();
}
else if(exp.charAt(i)==']' && !(st.isEmpty()) && st.peek()=='[') {
st.pop();
}
String str = st.toString();
System.out.println(str);
}
return st.isEmpty();
}
}
My LeetCode submission :-
public boolean isValid(String s) {
Stack<Character> sc = new Stack<>();
for(int i =0;i<s.length();i++){
char ch = s.charAt(i);
if(ch == '(' || ch == '{' || ch == '['){
sc.push(ch);
}else if(ch == ')'){
if(!sc.isEmpty() && sc.peek() == '('){
sc.pop();
}else{
return false;
}
}else if(ch == '}'){
if(!sc.isEmpty() && sc.peek() == '{'){
sc.pop();
}else{
return false;
}
}else if(ch == ']'){
if(!sc.isEmpty() && sc.peek() == '['){
sc.pop();
}else{
return false;
}
}
}
if(sc.isEmpty()){
return true;
}else{
return false;
}
}
Try this.
boolean isValid(String s) {
int max = s.length(), index = 0;
char[] stack = new char[max];
for (int i = 0; i < max; ++i) {
char c = s.charAt(i);
switch (c) {
case '(': stack[index++] = ')'; break;
case '[': stack[index++] = ']'; break;
case '{': stack[index++] = '}'; break;
default:
if (index <= 0 || stack[--index] != c)
return false;
break;
}
}
return index == 0;
}
When you encounter } and the following condition fails
else if(exp.charAt(i)=='}' && !(st.isEmpty()) && st.peek()=='{') {
you should already produce an error, but you just silently ignore the incoming } and continue the iteration. So all unpaired closing parenthesis/brackets are just silently removed from your input. Instead of ([}}]) you analyze ([]) which is a balanced string, so you get no error.
Same is true for other closing characters as well.
I am trying to solve this CSES problem: Grid Paths. You are given a string of length 48, and you have to find the amount of paths such that you traverse all of the grid and end up at the lower left corner.
I believe I have pruned the search to the best of my ability, as according to this book: CP Handbook (Look in the pruning the search category), the best optimization for this type of problem is to prevent your path from closing yourself off, and I have already implemented this. The time limits for this specific problem are tight, and although I have basically solved this problem, I am still failing 1-2 test cases because my solution takes around 1.01 seconds instead of being below the 1 second time limit.
Finally, I just wanted to know if there were any cool micro-optimizations I could use to marginally enhance the speed of my java code, so I could actually pass all of the test cases for this problem.
import java.io.*;
public class GridPaths {
public static class FastIO {
InputStream dis;
byte[] buffer = new byte[1 << 17];
int pointer = 0;
public FastIO(String fileName) throws Exception {
dis = new FileInputStream(fileName);
}
public FastIO(InputStream is) {
dis = is;
}
int nextInt() throws Exception {
int ret = 0;
byte b;
do {
b = nextByte();
} while (b <= ' ');
boolean negative = false;
if (b == '-') {
negative = true;
b = nextByte();
}
while (b >= '0' && b <= '9') {
ret = 10 * ret + b - '0';
b = nextByte();
}
return (negative) ? -ret : ret;
}
long nextLong() throws Exception {
long ret = 0;
byte b;
do {
b = nextByte();
} while (b <= ' ');
boolean negative = false;
if (b == '-') {
negative = true;
b = nextByte();
}
while (b >= '0' && b <= '9') {
ret = 10 * ret + b - '0';
b = nextByte();
}
return (negative) ? -ret : ret;
}
Integer[] readArray(int n) throws Exception {
Integer[] a = new Integer[n];
for (int i = 0; i < n; i++) a[i] = nextInt();
return a;
}
byte nextByte() throws Exception {
if (pointer == buffer.length) {
dis.read(buffer, 0, buffer.length);
pointer = 0;
}
return buffer[pointer++];
}
String next() throws Exception {
StringBuilder ret = new StringBuilder();
byte b;
do {
b = nextByte();
} while (b <= ' ');
while (b > ' ') {
ret.appendCodePoint(b);
b = nextByte();
}
return ret.toString();
}
}
static char[] board;
static boolean[][] visited = new boolean[7][7];
static int ans = 0;
public static boolean works(int i, int j) {
//makes sure that current spot is on the 7x7 grid and is not visited
return (i >= 0 && i<=6 && j>=0 && j<=6 && !visited[i][j]);
}
public static void solve(int i, int j, int steps) {
if (i == 6 && j == 0) {
if (steps == 48) ans++; //all spots of the grid have to be visited in order to be counted as part of the answer
return;
}
visited[i][j] = true;
//you are given ? characters in the input string, and those mean that you have to try out all 4 combinations (U,D,L,R)
if (board[steps] == '?' || board[steps] == 'L') {
//second condition of the second if statement checks if the spot directly ahead of the current spot is blocked, and if it is, the left and right spots cannot both be unvisited or else you will not continue searching
if (works(i,j-1) && !(!works(i,j-2) && works(i+1,j-1) && works(i-1,j-1))) {
solve(i, j - 1, steps + 1);
}
}
if (board[steps] == '?' || board[steps] == 'R') {
if (works(i,j+1) && !(!works(i,j+2) && works(i+1,j+1) && works(i-1,j+1))) {
solve(i, j + 1, steps + 1);
}
}
if (board[steps] == '?' || board[steps] == 'U') {
if (works(i-1,j) && !(!works(i-2,j) && works(i-1,j+1) && works(i-1,j-1))) {
solve(i - 1, j, steps + 1);
}
}
if (board[steps] == '?' || board[steps] == 'D') {
if (works(i+1,j) && !(!works(i+2,j) && works(i+1,j+1) && works(i+1,j-1))) {
solve(i + 1, j, steps + 1);
}
}
visited[i][j] = false;
}
public static void main(String[] args) throws Exception {
FastIO in = new FastIO(System.in);
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
board = in.next().toCharArray();
solve(0,0,0);
out.println(ans);
out.close();
}
}
Note: I am already using one of the fastest, if not the fastest, ways to receive input in Java, so I do not believe I can actually improve upon that.
I've been playing around with this. In addition to using a standard mechanism for reading the input file (which I suggested in a comment), you can gain a little time in the search alg itself by doing two things:
Break the case board[steps] == '?' off from the other cases. So check for board[steps] == '?' first, and just try all four directions in that case. Otherwise (the else case for if (board[steps] == '?'), just check for U/D/L/R. Since for most steps, the character will be '?', you save having to make the U/D/L/R tests most of the time.
Look up the character to be tested once, with c = board[steps],and then use c in each test instead of board[steps].
Doing these two things saved about 5% it seems. I was doing 100 reps of the solve and timing with System.currentTimeMillis(). I know there are more accurate ways of timing, but this was good enough to see a definite improvement even though the times jumped around quite a bit trial to trial. The best I ever saw in each case was 3600 millis for 100 iterations as originally written vs 3400 millis with the improvements.
My guess is that it's mostly the first change that matters. I'd expect the compiler to be doing the second already, but I didn't try the two optimizations independently.
I also solved this problem in java (AC), and here is how I did it
public static char[] defaultPath;
public static boolean[][] isUsed;
public static int counter = 0;
public static void solve(int indexChar, int indexRow, int indexColumn) {
if (indexRow == 8 && indexColumn == 2) {
if (indexChar == 48) {
counter++;
}
}else {
// Find correct way: 'D', 'U', 'L', 'R'
char correctWay = '?';
// (1) (1)
// 0 1 or 1 0
// 1 1
if ((isUsed[indexRow+1][indexColumn+1] || isUsed[indexRow+1][indexColumn-1])
&& isUsed[indexRow+2][indexColumn] && !isUsed[indexRow+1][indexColumn]) {
correctWay = 'D';
}
// 1 1
// 0 1 or 1 0
// (1) (1)
else if ((isUsed[indexRow-1][indexColumn+1] || isUsed[indexRow-1][indexColumn-1])
&& !isUsed[indexRow-1][indexColumn] && isUsed[indexRow-2][indexColumn]) {
correctWay = 'U';
}
// 1 0 (1) or 1
// 1 1 0 (1)
else if ((isUsed[indexRow+1][indexColumn-1] || isUsed[indexRow-1][indexColumn-1])
&& !isUsed[indexRow][indexColumn-1] && isUsed[indexRow][indexColumn-2]) {
correctWay = 'L';
}
//(1) 0 1 or 1
// 1 (1) 0 1
else if ((isUsed[indexRow+1][indexColumn+1] || isUsed[indexRow-1][indexColumn+1])
&& !isUsed[indexRow][indexColumn+1] && isUsed[indexRow][indexColumn+2]) {
correctWay = 'R';
}
// Check input path (default path)
char c = defaultPath[indexChar];
if (c == '?') {
if (correctWay == '?') {
// 'D'
if (!isUsed[indexRow+1][indexColumn]) {
isUsed[indexRow+1][indexColumn] = true;
solve(indexChar+1, indexRow+1, indexColumn);
isUsed[indexRow+1][indexColumn] = false;
}
// 'U'
if (!isUsed[indexRow-1][indexColumn]) {
isUsed[indexRow-1][indexColumn] = true;
solve(indexChar+1, indexRow-1, indexColumn);
isUsed[indexRow-1][indexColumn] = false;
}
// 'L'
if (!isUsed[indexRow][indexColumn-1]) {
isUsed[indexRow][indexColumn-1] = true;
solve(indexChar+1, indexRow, indexColumn-1);
isUsed[indexRow][indexColumn-1] = false;
}
// 'R'
if (!isUsed[indexRow][indexColumn+1]) {
isUsed[indexRow][indexColumn+1] = true;
solve(indexChar+1, indexRow, indexColumn+1);
isUsed[indexRow][indexColumn+1] = false;
}
}else {
if (correctWay == 'D') {
isUsed[indexRow+1][indexColumn] = true;
solve(indexChar+1, indexRow+1, indexColumn);
isUsed[indexRow+1][indexColumn] = false;
}else if (correctWay == 'U') {
isUsed[indexRow-1][indexColumn] = true;
solve(indexChar+1, indexRow-1, indexColumn);
isUsed[indexRow-1][indexColumn] = false;
}else if (correctWay == 'L') {
isUsed[indexRow][indexColumn-1] = true;
solve(indexChar+1, indexRow, indexColumn-1);
isUsed[indexRow][indexColumn-1] = false;
}else if (correctWay == 'R') {
isUsed[indexRow][indexColumn+1] = true;
solve(indexChar+1, indexRow, indexColumn+1);
isUsed[indexRow][indexColumn+1] = false;
}
}
}else {
if (c == correctWay || correctWay == '?') {
if (c == 'D' && !isUsed[indexRow+1][indexColumn]) {
isUsed[indexRow+1][indexColumn] = true;
solve(indexChar+1, indexRow+1, indexColumn);
isUsed[indexRow+1][indexColumn] = false;
}else if (c == 'U' && !isUsed[indexRow-1][indexColumn]) {
isUsed[indexRow-1][indexColumn] = true;
solve(indexChar+1, indexRow-1, indexColumn);
isUsed[indexRow-1][indexColumn] = false;
}else if (c == 'L' && !isUsed[indexRow][indexColumn-1]) {
isUsed[indexRow][indexColumn-1] = true;
solve(indexChar+1, indexRow, indexColumn-1);
isUsed[indexRow][indexColumn-1] = false;
}else if (c == 'R' && !isUsed[indexRow][indexColumn+1]) {
isUsed[indexRow][indexColumn+1] = true;
solve(indexChar+1, indexRow, indexColumn+1);
isUsed[indexRow][indexColumn+1] = false;
}
}
}
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
defaultPath = scanner.next().toCharArray();
isUsed = new boolean[11][11];
for (int i = 0; i < 11; i++) {
isUsed[0][i] = true;
isUsed[1][i] = true;
isUsed[9][i] = true;
isUsed[10][i] = true;
isUsed[i][0] = true;
isUsed[i][1] = true;
isUsed[i][9] = true;
isUsed[i][10] = true;
}
isUsed[2][2] = true;
isUsed[8][1] = false;
isUsed[9][2] = false;
solve(0, 2, 2);
System.out.println(counter);
scanner.close();
}
private DSAQueue parseInfixToPostfix(String equation) {
String result = "";
char operator = ' ';
DSAStack stack = new DSAStack();
DSAQueue queue = new DSACircular();
for (int i = 0; i < equation.length(); i++) {
char c = equation.charAt(i);
if (Character.isLetterOrDigit(c)) {
result += c;
}
else if (c == '(') {
stack.push(c);
}
else if (c == ')') {
while (!stack.isEmpty() && stack.top() != '(') {
result += stack.pop();
}
if (!stack.isEmpty() && stack.top() != '(') {
result = "Invalid expression";
}
else {
stack.pop();
}
}
else { //when meets operator
while (!stack.isEmpty() && (precedenceOf(c) <= precedenceOf((char) stack.top()))) {
if (stack.top() == '(') {
result = "Invalid expression";
}
result += stack.pop();
}
stack.push(c);
}
}
while (!stack.isEmpty()) {
if (stack.top() == '(') {
result = "Invalid";
}
result += stack.pop();
}
queue.enqueue(result);
return queue;
}
Above is my code for converting infix to postfix. The example i used is "4+2" and what i got is:
Pushed: 43
Popped: 43
Enqueued: 4243
i dont know why it automatically converted "+" to 43, but i want to store the operator as the operator like "+" in the queue. Is it possible? Or is there an error? because i cant find out what the error is. thank you
This question already has an answer here:
What is a StringIndexOutOfBoundsException? How can I fix it?
(1 answer)
Closed 3 years ago.
I am setting up a method that turn a infix string into a postfix equation with a custom LinkStack.
I have tried to to check if the charAt(i) was null and a if statement to check if i is greater than exp.length() but neither worked.
public static String infixToPostfix(String exp)
{
// make variable
String result = new String("");
int temp = 0;
LinkedStack stack = new LinkedStack();
for (int i = 0; i<exp.length(); ++i)
{
char c = exp.charAt(i);
if(Character.isDigit(c))
{
int n = 0;
//extract the characters and store it in num
while(Character.isDigit(c))
{
n = n*10 + (int)(c-'0');
i++;
c = exp.charAt(i); //exception occurs
System.out.println(n);
}
i--;
//push the number in stack
stack.push(n);
//System.out.println(stack.size() + ", Stack size");
}
// If ( push it to the stack.
if (c == '(')
stack.push(c);
// If ) pop and output from the stack
// until an '(' is encountered.
else if (c == ')')
{
while (!stack.isEmpty() && stack.peek() != '(')
result += stack.pop();
if (!stack.isEmpty() && stack.peek() != '(')
return "Invalid Expression"; // invalid expression
else
stack.pop();
}
else // an operator is encountered
{
while (!stack.isEmpty() && pre(c) <= pre((char) stack.peek()))
result += stack.pop();
stack.push(c);
}
}
// pop all the operators from the stack
while (!stack.isEmpty())
result += stack.pop();
String temp2 = stack.print();
System.out.println(temp2);
return result;
}
I expect the output to be 469 645 + if the input is 496+645 but the actual output is java.lang.StringIndexOutOfBoundsException: String index out of range: 7.
while(Character.isDigit(c))
{
n = n*10 + (int)(c-'0');
i++;
c = exp.charAt(i); //exception occurs
System.out.println(n);
}
You aren't length checking here, so you readily parse right off the end of the string.
while(i < exp.length() && Character.isDigit(c))
{
n = n*10 + (int)(c-'0');
if (++i < exp.length()) {
c = exp.charAt(i); //exception occurs
}
System.out.println(n);
}
Note: I'd cache the length because of how many times you use it, but that's not the cause of your problem.
Note, however, that this is cleaner code style:
public class Foo {
public static void main(String[] args) {
String myString = "12345";
int index = 0;
for (char c: myString.toCharArray()) {
System.out.printf("Char at %d == %c\n", index, c);
++index;
}
}
}
Notice the for-loop. I didn't do your calculations or break out or anything, but this is a cleaner way.
You can also do...
for (int index = 0; index < exp.length(); ++index) {
char c = exp.charAt(index);
if (!Character.isDigit(c)) {
break;
}
// Do other stuff here.
}
There are a variety of other ways to structure your code. Your while loop is awkward.
I've been having trouble with this assignment:
Given a string, replace the first occurrence of 'a' with "x", the second occurrence of 'a' with "xx" and the third occurrence of 'a' with "xxx". After the third occurrence, begin the replacement pattern over again with "x", "xx", "xxx"...etc.; however, if an 'a' is followed by more than 2 other 'a' characters in a row, then do not replace any more 'a' characters after that 'a'.
No use of the replace method is allowed.
aTo123X("ababba") → "xbxxbbxxx"
aTo123X("anaceeacdabnanbag") → "xnxxceexxxcdxbnxxnbxxxg"
aTo123X("aabaaaavfaajaaj") → "xxxbxxxaaavfaajaaj"
aTo123X("pakaaajaaaamnbaa") → "pxkxxxxxxjxxaaamnbaa"
aTo123X("aaaak") → "xaaak"
My code's output is with a's included, x's added but not the correct amount of x's.
public String aTo123X(String str) {
/*
Strategy:
get string length of the code, and create a for loop in order to find each individual part of the String chars.check for a values in string and take in pos of the a.
if one of the characters is a
replace with 1 x, however, there aren't more than 2 a's immediately following first a and as it keeps searching through the index, add more x's to the original string, but set x value back to 1 when x reaches 3.
if one of characters isn't a,
leave as is and continue string.
*/
String xVal = "";
String x = "x";
String output = "";
for (int i = 0; i < str.length(); i++){
if( str.charAt(i) == 'a'){
output += x;
str.substring(i+1, str.length());
}
output += str.charAt(i);
}
return output;
}
This is the code that does the same. I've commented the code to explain what it does
public class ReplaceChar {
public static void main(String... args){
String[] input =new String[]{"ababba","anaceeacdabnanbag","aabaaaavfaajaaj"};
StringBuilder result = new StringBuilder();
for (int i= 0; i < input.length;i++){
result.append(getReplacedA(input[i]));
result.append("\n");
}
System.out.println(result);
}
private static String getReplacedA(String withA){
// stringBuilder for result
StringBuilder replacedString = new StringBuilder();
// counting the number of time char 'a' occurred in String for replacement before row of 'aaa'
int charACount = 0;
// get the first index at which more than two 'aa' occurred in a row
int firstIndexOfAAA = withA.indexOf("aaa") + 1;
// if 'aaa' not occurred no need to add the rest substring
boolean addSubRequired = false;
// if the index is 0 continue till end
if (firstIndexOfAAA == 0)
firstIndexOfAAA = withA.length();
else
addSubRequired = true;
char[] charString = withA.toCharArray();
//Replace character String[] array
String[] replace = new String[]{"x","xx","xxx"};
for(int i = 0; i < firstIndexOfAAA; i++){
if (charString[i] == 'a'){
charACount++;
charACount = charACount > 3 ? 1 : charACount ;
// add the number x based on charCount
replacedString.append(replace[charACount - 1]);
}else{
replacedString.append(charString[i]);
}
}
// if the String 'aaa' has been found previously add the remaining subString
// after that index
if (addSubRequired)
replacedString.append(withA.substring(firstIndexOfAAA));
// return the result
return replacedString.toString();
}
}
Output:
xbxxbbxxx
xnxxceexxxcdxbnxxnbxxxg
xxxbxxxaaavfaajaaj
EDIT : Some Improvement You can make for some corner cases in the getReplacedA() function:
Check if char 'a' is there or not in the String if not just return the String No need to do anything further.
Use IgnoreCase to avoid the uppercase or lowercase possibility.
Firstly, string is immutable, so the below statement does nothing
str.substring(i+1, str.length());
I guess you wanted to do:
str = str.substring(i+1, str.length());
However, even after fix that, your program still doesn't work. I can't really comprehend your solution. 1) you are not detecting more than 3 a's in a row. 2) you are not appending "xx" or "xxx" at all
Here is my version, works for me so far:
public static void main(String[] args) {
System.out.println(aTo123X("ababba")); // "xbxxbbxxx"
System.out.println(aTo123X("anaceeacdabnanbag")); // "xnxxceexxxcdxbnxxnbxxxg"
System.out.println(aTo123X("aabaaaavfaajaaj")); // "xxxbxxxaaavfaajaaj"
}
public static String aTo123X(String str) {
String output = "";
int aOccurrence = 0;
String[] xs = {"x", "xx", "xxx"};
for (int i = 0; i < str.length(); ++i) {
if (str.charAt(i) == 'a') {
output += xs[aOccurrence % 3]; // append the x's depending on the number of a's we have seen, modulus 3 so that it forms a cycle of 3
if (i < str.length() - 3 && str.charAt(i + 1) == 'a' && str.charAt(i + 2) == 'a' && str.charAt(i + 3) == 'a') {//if an 'a' is followed by more than 2 other 'a' characters in a row
output += str.substring(i + 1);
break;
} else {
++aOccurrence; // increment the a's we have encountered so far
}
} else {
output += str.charAt(i); // append the character if it is not a
}
}
return output;
}
public class NewClass {
public static void main(String[] args) {
System.out.println(aTo123X("ababba")); // "xbxxbbxxx"
System.out.println(aTo123X("anaceeacdabnanbag")); // "xnxxceexxxcdxbnxxnbxxxg"
System.out.println(aTo123X("aabaaaavfaajaaj")); //xxxbxxxaaavfaajaaj
}
public static String aTo123X(String str) {
String output = "";
int aCount = 0;
int inRow = 0;
for (int i = 0; i < str.length();) {
if (str.charAt(i) == 'a') {
if (inRow <= 1) {
inRow++;
aCount++;
if (aCount == 1) {
output += "x";
} else if (aCount == 2) {
output += "xx";
} else {
output += "xxx";
aCount = 0;
}
boolean multiple = ((i + 1) < str.length()) && (str.charAt(i + 1) == 'a')
&& ((i + 2) < str.length()) && (str.charAt(i + 2) == 'a');
if (multiple) {
i++;
while (i < str.length()) {
output += str.charAt(i++);
}
return output;
}
} else {
output += str.charAt(i);
}
} else {
output += str.charAt(i);
inRow = 0;
}
i++;
}
return output;
}
}
I am pointing out problems in your code in form of comments in the code itself.
public String aTo123X(String str) {
//You are not using xVal variable in your code, hence it's obsolete
String xVal = "";
//You don't need x variable as you can simply use string concatenation
String x = "x";
String output = "";
for (int i = 0; i < str.length(); i++) {
/**
* Here, in "if" block you have not implmented any logic to replace the 2nd and
* 3rd occurence of 'a' with 'xx' and 'xxx' respectively. Also, substring() returns
* the sub-string of a string but you are not accepting that string anywhere, and
* you need not even use sub-string as "for" loop will cycle through all the
* characters in the string. If use sub-string method you code will only process
* alternative characters.
*/
if( str.charAt(i) == 'a') {
output += x;
str.substring(i+1, str.length());
}
/**
* Because of this statement a's are also returned, because this statement gets
* in both scenarios, whether the current character of string is a or not.
* But, this statement should get executed only when current character of the
* string is 'a'. So, in terms of coding this statement gets executed no matter
* "if" loop is executed or not, but it should get executed only when "if" loop
* is not executed. So, place this statement in else block.
*/
output += str.charAt(i);
}
return output;
}
I have implemented the logic for you. Here is Solution for your problem, just copy and run it. It passes all the specified test cases.
public String aTo123X(String str) {
String output = "";
int count = 1;
boolean flag = true;
for (int i = 0; i < str.length(); i++) {
if(str.charAt(i) == 'a' && flag == true) {
switch(count) {
case 1: output += "x";
count++;
break;
case 2: output += "xx";
count++;
break;
case 3: output += "xxx";
count = 1;
break;
}
if ((str.charAt(i+1) == 'a' && str.charAt(i+2) == 'a') == true) {
flag = false;
}
}
else {
output += str.charAt(i);
}
}
return output;
}
I use Map To store where to replace
public static void main(String[] args) {
System.out.println(aTo123X("ababba"));//xbxxbbxxx
System.out.println(aTo123X("anaceeacdabnanbag"));//xnxxceexxxcdxbnxxnbxxxg
System.out.println(aTo123X("aabaaaavfaajaaj"));//xxxbxxxaaavfaajaaj
}
public static String aTo123X(String str){
String res = "";
int nthReplace = 1; //Integer to store the nth occurence to replace
//Map to store [key == position of 'a' to replace]
//[value == x or xx or xxx]
Map<Integer, String> toReplacePos = new HashMap<>();
//The loop to know which 'a' to replace
for (int i = 0; i < str.length(); i++) {
if(str.charAt(i) == 'a'){
toReplacePos.put(i, nthReplace % 3 == 1 ? "x": (nthReplace % 3 == 2 ? "xx": "xxx"));
nthReplace++;
//Break if an 'a' is followed by more than 2 other 'a'
try {
if((str.charAt(i+1) == 'a')
&& (str.charAt(i+2) == 'a')
&& (str.charAt(i+3) == 'a')){
break;
}
} catch (StringIndexOutOfBoundsException e) {
}
}
}
//Do the replace
for (int i = 0; i < str.length(); i++) {
res += toReplacePos.containsKey(i) ? toReplacePos.get(i) : str.charAt(i);
}
return res;
}
I have edited my answer. This one is giving the correct solution:
public static void main (String[] args) throws InterruptedException, IOException, JSONException {
System.out.println(aTo123X("ababba")); //xbxxbbxxx
System.out.println(aTo123X("anaceeacdabnanbag")); //xnxxceexxxcdxbnxxnbxxxg
System.out.println(aTo123X("aabaaaavfaajaaj")); //xxxbxxxaaavfaajaaj
}
public static String aTo123X(String str) {
String x = "x";
String xx = "xx";
String xxx = "xxx";
int a = 1;
int brek = 0;
String output = "";
for (int i = 0; i < str.length(); i++) {
if(str.charAt(i) == 'a' && a == 1) {
output += x;
str.substring(i+1, str.length());
a = 2;
try {
if(str.charAt(i+1) == 'a' && str.charAt(i+2) == 'a')
brek += 1;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if(str.charAt(i) == 'a' && a == 2) {
output += xx;
str.substring(i+1, str.length());
a = 3;
try {
if(str.charAt(i+1) == 'a' && str.charAt(i+2) == 'a')
brek += 1;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if(str.charAt(i) == 'a' && a == 3) {
output += xxx;
str.substring(i+1, str.length());
a = 1;
try {
if(str.charAt(i+1) == 'a' && str.charAt(i+2) == 'a')
brek += 1;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
output += str.charAt(i);
brek = 0;
}
if(brek>0) {
output += str.substring(i+1);
break;
}
}
return output;
}