Loop is not resetting? - java

Belowe is code that checks for matching parentheses to see if they are nested properly. It seems really simple, but I don't understand why i does not reset to 0 once a nested match is found. Any guidance would be much appreciated.
String testString = "{}()[] ";
char [] openParenthesis = {'(','{','['};
char [] closeParenthesis = {')','}',']'};
ArrayList<Character> characterList = new ArrayList<Character>();
for(char c : testString.toCharArray())
{
characterList.add(c);
System.out.println("This is what is added to the list Arraylist: " + c);
}
System.out.println();
for(int i = 0; i < characterList.size()-1; i++)
{
System.out.println("1st Loop: " +characterList.get(i));
System.out.println("1st Loop: " + characterList.get(i + 1));
System.out.println("1st Loop: " + i);
System.out.println();
for(int j = 0; j < openParenthesis.length; j++)
{
if (characterList.get(i) == openParenthesis[j])
{
if(characterList.get(i + 1) == closeParenthesis[j])
{
System.out.println("Nested Match");
System.out.println(characterList.get(i));
System.out.println(characterList.get(i + 1));
System.out.println();
characterList.remove(i);
characterList.remove(i + 1);
i = 0;
}
}
}
}

First off all you are removing the wrong spots in the ArrayList.
Because it is an ArrayList characterList.remove(i); will move everything over to the left one spot, so then the next like characterList.remove(i+1); removes the one to the right of where you want.
You also need to add a break in the openParenthesis loop so you can start the search over at the beginning of the array if you find a match.
You also need to change the i = 0 to i = -1 because it increments it to one BEFORE it starts the next iteration of the for loop.
Finally, you should be using .equals() instead of == because the ArrayList returns a Character object instead of a char.
Here is what I came up with:
for (int i = 0; i < characterList.size() - 1; i++) {
System.out.println("1st Loop: " + characterList.get(i));
System.out.println("1st Loop: " + characterList.get(i + 1));
System.out.println("1st Loop: " + i);
System.out.println();
for (int j = 0; j < openParenthesis.length; j++) {
if (characterList.get(i).equals(openParenthesis[j])) {
if (characterList.get(i + 1).equals(closeParenthesis[j])) {
System.out.println("Nested Match");
System.out.println(characterList.get(i));
System.out.println(characterList.get(i + 1));
System.out.println();
characterList.remove(i);
characterList.remove(i);
i = -1;
break;
}
}
}
}
This code has fixed all the errors mentioned above and should run correctly.

Obviously because of the i++ in for loop i equal to 1. if you really want to set 0 for i again. use i=-1;

Your for loop increments i by one AFTER the body of the loop is completed.
Thus, you set i=0, you exit the body of the loop, i++ is called, and you enter the loop body once more with i ==1.

Well it depends on what your testString is. I tested it with value foo() and loop did go inside if(characterList.get(i + 1) == closeParenthesis[j]) condition.
However there is a problem in your code where you have:
characterList.remove(i);
characterList.remove(i + 1);
Which will result in java.lang.IndexOutOfBoundsException since i+1 location has become invalid (out of range) after deleting ith element. It should be other way round:
characterList.remove(i + 1);
characterList.remove(i);
Also instead of i=0; you need to set it to: i = -1;
And more importantly break out of inner for loop by calling break.
So your code in the end should look like this:
i = -1;
break;
See working demo: http://ideone.com/DfGJ2m

I guess you could have used a stack data structure and using a process similar to http://www.geeksforgeeks.org/check-for-balanced-parentheses-in-an-expression/

When you store a character in a list, java autoboxes it to a Character. You cannot use the == operator to compare two Characters for equality, but must use the .equals() method, as this code demonstrates:
Character aOne = new Character('a');
Character aTwo = new Character('a');
if(aOne == aTwo)
{
System.out.println("aOne and aTwo == operator says they are equal");
}
else
{
System.out.println("aOne and aTwo == operator says they are NOT equal");
}
if(aOne.equals(aTwo))
{
System.out.println("aOne and aTwo .equals operator says they are equal");
}
Code prints out:
aOne and aTwo == operator says they are NOT equal
aOne and aTwo .equals operator says they are equal

Related

Finding duplicated or repeated character in a string and return the number of repeation in Java

I have created a Java program to find duplicated character in a String and tell how many times this character is duplicated.
I have created two arrays with the same characters, and two for loops that compare the first element of the first array with all characters in the second array,and so as for the second element,
Here is my code:
Scanner console=new Scanner(System.in);
char[] array=console.next().toCharArray();
char[] array2=array;
int count=0;
char m;
for (int i=0; i<array.length; i++) {
for (int j=0; j<array2.length; j++) {
if (array[i]==array2[j]) {
count=count+1;
} // end if
} //end loop inner
if ( count>=2) {
System.out.println(array[i]+" is duplicated "+count+" times!");
} // end 2nd if
count=0;
} //end outer loop
an example of my output is:
aabb
a is duplicated 2 times!
a is duplicated 2 times!
b is duplicated 2 times!
b is duplicated 2 times!
As you can see my problem is that if a character is repeated two times it prints two lines saying its duplicated two times, and i know the reason behind this but i dont know how to solve it!. I dont want to use hashmap, because until now i have only studied if/else, loops, and lately something about arrays, so if your answer lies among this subjects thanks!
You may use an Object (here a String) to keep track of the already encountered characters.
Scanner console=new Scanner(System.in);
char[] array=console.next().toCharArray();
char[] array2=array;
int count=0;
char m;
String memoryString = "";
for (int i=0; i<array.length; i++) {
for (int j=0; j<array2.length; j++) {
if (memoryString.contains(String.valueOf(array[i])) break;
if (array[i]==array2[j]){
count=count+1;
}
} //end loop inner
memoryString+=array[i]
if (count>=2) {
System.out.println(array[i]+" is duplicated "+count+" times!");
}
count=0;
} //end outer loop
you could instead loop through all the possible characters and see how many of them exist in the string (assuming you are ok with using a string instead of an array of characters):
while(!str.isEmpty())
{
int count = 0;
char c = str.charAt(0);
while(str.indexOf(c) != -1)
{
str = str.replaceFirst(String.valueOf(c), "");
count++;
}
System.out.println("number of " + c + " " + count);
}
Edit: do to the backlash against my (poor) assumption and using a 256 limit on the number of chars, i reworked it a bit. hope this is a bit better!
Here is how you could do this (Assuming ASCII charset):
public static void main(String[] args) {
Scanner console=new Scanner(System.in);
char[] array=console.next().toCharArray();
int[] counts = new int[255];
for(char c : array) {
counts[c]++;
}
for(int i = 0; i < 255; i++){
if (counts[i] > 1)
System.out.println("duplicated char: " + (char)i + ", " + counts[i] + "times");
}
}
The logic is:
Create an array of integers to keep track of counts of each input character
Loop through each character in the string and increment the count. The index of counts array will be the ascii value of the character.
Do a one pass through the counts array to figure out which characters have counts more than 2 and print them.

Getting java.lang.ArrayIndexOutOfBoundsException, looked, cannot find an example thats the same

I am writing a "tweet checker" code for my AP Computer Science Class. The code is supposed to check that the length of the tweet is within the 140 character limit and, if so, prints the amount of hashtags, #, and links used. I am using the .split method to put all the characters into an array, and then I am accessing the array with for loops to find the specific characters.
I keep encountering a java.lang.ArrayIndexOutOfBoundsException, which I know means that I am trying to access a nonexistent element in my string, such as element 46 for an array of 46 characters, but I do not know what the exact problem is here. I got harped on last time for not "looking hard enough" but I have searched for over 2 hours on only this subject, and I am simply a high school student.
I appreciate all the help.
import java.util.Scanner;
import java.lang.Math;
class Main{
public static void main(String[] args)
{
Scanner scan = new Scanner (System.in);
System.out.println("Please enter a tweet:");
String tweet = scan.nextLine();
int length = tweet.length ();
String[] tweetArray = tweet.split ("");
int c = 0;
int d = 0;
int e = 0;
int i = 0;
if (length > 140)
System.out.println("Excess Characters: " + (length - 140));
else
{
System.out.println("Length Correct");
for (i = 0; i < length; i++)
{
if (tweetArray[i].equals("#"))
{
if(!tweetArray[i+1].equals(" "))
{
c++;
}
}
}
System.out.println("Number of Hastags: " + c);
for (i = 0; i < length; i++)
{
if (tweetArray[i].equals("#"))
{
if(!tweetArray[i+1].equals(" "))
{
d++;
}
}
}
System.out.println("Number of Attributions: " + d);
for (i = 0; i < length; i++)
{
if((tweetArray[i].equals("h")) || (tweetArray[i].equals("H")))
{
if(tweetArray[i+1].equals("t") || tweetArray[i+1].equals("T"))
{
if(tweetArray[i+2].equals("t") || tweetArray[i+2].equals("T"))
{
if(tweetArray[i+3].equals("p") || tweetArray[i+3].equals("P"))
{
if(tweetArray[i+4].equals(":"))
{
if(tweetArray[i+5].equals("/"))
{
if(tweetArray[i+6].equals("/"))
{
if(!tweetArray[i+7].equals(" "))
{
e++;
}
}
}
}
}
}
}
}
}
System.out.println("Number of Links: " + e);
}
}
}
In your for loop, i correctly iterates from 0 to the maximum length. However you have code such as:
tweetArray[i+1]
...
tweetArray[i+7]
that will fail once i reaches (or gets close to) its maximum. That is, you are referencing past the end of the array.
In general, if you need to check something about the next character, you need to check that it exists first (as you only know that the current character exists).
You may wish to review your whole approach though. There does not appear to be any need to split your string into characters. You could instead use string based functions to count the number of # characters or check for the presence of a string (eg. http://). Check out the API.

Not able to understand string permutation Java code

I have this working code to print string permutations without repetitions, but not able to wrap my head around how is it working as in logic. Any suggestions will be really helpful.
private static void permutation(String input, String sofar) {
if (input.equals("")) {
System.out.println(count + " " + sofar);
count++;
}
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (input.indexOf(c, i + 1) != -1)
continue;
permutation(input.substring(0, i) + input.substring(i + 1), sofar+c);
}
}
Function call:
String input = "ABBCD";
permutation(input, "");
for (int i = 0; i < input.length(); i++) {
The above for loop is doing the magic
Input ABCD
Iterations
input: BCD sofar: A .... recursion goes on
input: ACD sofar: B ....
input: ABD sofar: C ....
input: ABC sofar: D .....
Hope this helps
Just remember that recursion is usually a stop condition, and an attempt to solve a smaller problem using the recursive call, under the assumption that the recursion works.
I've commented the code so you can replace that with your copy to keep track of what it's doing when you get back to it. Add your own comments once you understand as they'll help you follow what happens:
Part 1: The basic condition / stop condition:
if (input.equals("")) {
System.out.println(count + " " + sofar);
count++;
}
This part stops the recursion and returns a result, the base case being an empty string, which has a single permutation that is also an empty string.
Part 2: Iterating smaller problems.
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
// ...
permutation(input.substring(0, i) + input.substring(i + 1), sofar+c);
}
This part uses the recursive call on a smaller (by one character) string, to solve the problem. It calls the same string omitting a character it prepends to whatever following results it generates. We know the call generates all permutations (that's our assumption). So we now know what the recursion does.
Part 2.1: The de-duplicating "if":
This is probably the trickiest part here...
if (input.indexOf(c, i + 1) != -1)
continue;
Let's figure this out. What it means, is: "try and find a character the same as the one selected, and if one exists, skip this iteration and it's generated solutions".
Think of a word like "ABBA" it will skip the first "A" and "B", but not the last ones. Why? Well, since order of similar characters does not matter (if we tag the character A1 B1 B2 A2, and now replace them: A2 B2 B1 A1, this is still the same word, so there is only one permutation for words like "AA", since A1 A2 is the same as A2 A1.
Taking the last characters is easier, since we don't need to maintain a list of the characters we already used in this iteration.
The full code with basic comments:
private static void permutation(String input, String sofar) {
if (input.equals("")) {
// this is the stop condition
// the only permutation of "" is ""
System.out.println(count + " " + sofar);
// this counts how many permutations were outputted.
count++;
}
for (int i = 0; i < input.length(); i++) {
// this loop basically means "take every
// possible character, and append permutations of all
// other characters to it.
char c = input.charAt(i);
if (input.indexOf(c, i + 1) != -1)
// this makes sure we only take a single "A" or "B"
// character in words like "ABBA", since selecting
// the same character would create duplicates
continue;
// this creates a new string without the selected character
// and under the assumption the recursion works
// appends all permutations of all other characters
// to it
permutation(input.substring(0, i) + input.substring(i + 1), sofar+c);
}
}
if (input.equals("")) {
System.out.println(count + " " + sofar);
count++;
}
This step is passed as the input is not "". Note that you could simply use input.empty() here. The only thing to remember here is that count have not been incremented.
for (int i = 0; i < input.length(); i++) {
This will, loop over all character of the input
char c = input.charAt(i);
if (input.indexOf(c, i + 1) != -1)
This check if the next character is equal to the current one, if it does then it will jump directly to the next iteration(the next character) using the continue keyword.
If it does not, then it will recall the method (We call that recursivity), passing in the string without the current char. But giving it back to sofar.
permutation(input.substring(0, i) + input.substring(i + 1), sofar+c);
Now in the case where input is empty,
The count of non-distinct character will be printed + all these character.

Picking out parentheses out of a String in Java

I am new to Java and trying to finish a program that will read a statement by the user and and scan to see if the amount of LEFT parenthesis match the RIGHT. The person who started the program created a stack but never made any use of it so I left it alone since I'm not very good with stacks. However, I was able to create a loop to to go through every character in the String to find the parenthesis, compare them, then print out if they are even or not. However I am having trouble with the while loop that goes through the String to find all parentheses. It's not working for some reason and I don't understand why. Any explanation on how to make this work will be greatly appreciated.
import java.util.*
public class ParenMatch
{
public static void main (String[] args)
{
Stack s = new Stack();
String line; // the string of characters to be checked
Scanner scan = new Scanner(System.in);
System.out.println ("\nParenthesis Matching");
System.out.print ("Enter a parenthesized expression: ");
line = scan.nextLine();
char parenline[] = new char[line.length()];
int x;
while(x < parenline.length) {
parenline[x] = line.charAt(x);
x++;
}
int l,r,i,morel,morer = 0;
while (i > parenline.length) {
if (parenline[i] == "(" )
l++;
if (line.charAt(i) == ")")
r++;
i++;
}
if (l > r) {
morel = l-r;
System.out.println("There are " +morel+ " more left parentheses than right");
}
if (r > l) {
morer = r-l;
System.out.println("There are " +morer+ " more right parentheses then left");
}
if (r == l) {
System.out.println("The amount of left and right parentheses are even.");
}
}
}
You need to initialize x so for example.
int x = 0;
You cannot increment an uninitialized variable.
Also to define parenline instead of looping and adding the char at the locations in the string just using one of the strings native methods:
char parenline[] = line.toCharArray();
Sorry if i explained this badly.
You had following mistakes:
not initializing
using double quote instead of single quote
checking whether i is greather than parenline.length
This is the correct code block:
int x=0;
...
int l,r,i,morel,morer;
l=r=i=morel=morer= 0;
while (i < parenline.length) {
if (parenline[i] == '(' )
l++;
if (line.charAt(i) == ')')
r++;
i++;
}
I made some changes to your code, it works fine.
However, the approach using Stack is better because allows you not only see if the amout of parenthesis is equal, but to see if the expression is correct. For example, if you have something like that: (x+y))+(x-(y+x) then your program can't tell that this is an incorrect expression because the amount of opening and closing parenthesis is equal.
import java.util.*;
public class Stackpr {
public static void main (String[] args)
{
String line; // the string of characters to be checked
Scanner scan = new Scanner(System.in);
System.out.println ("\nParenthesis Matching");
System.out.print ("Enter a parenthesized expression: ");
line = scan.nextLine();
int l = 0;
int r = 0;
for (int i = 0; i < line.length(); i++){
if (line.charAt(i) == '(')
l++;
else if (line.charAt(i) == ')')
r++;
}
if (l > r)
System.out.println("There are " + (l-r) + " more left parentheses than right");
else if (l < r)
System.out.println("There are " + (r - l)+ " more right parentheses then left");
else
System.out.println("The amount of left and right parentheses are even.");
}
}

Compare two Strings letter by letter

Well, I have two strings to compare and check letter by letter if they match, and if hits a '-' i need to count how many '-' there's in sequence and put them in a group as if they were only one char and count how many T and C there in this group of '-'. The output should be like 2.1T and 2.2C and the other one 5.2C.
String dna1 = "TC---CA--";
String dna2 = "TCTCCCACC";
char[] dnaChar = dna1.toCharArray(), dna2Char = dna2.toCharArray();
int cont = 0;
int letters = 0;
for (int i = 0; i < dnaChar.length; i++) {
if (dnaChar[i] != dna2Char[i]) {
int mut = i + 1;
if (dna1.charAt(i) == '-') {
cont++;
mut -= cont;
if (dna2.charAt(i) == 'C') {
letters++;
}
System.out.println(mut + "." + letters + dna2.charAt(i));
} else {
letters = 0;
cont = 0;
mut += 1;
System.out.println("" + dna1.charAt(i) + " " + mut + " " + dna2.charAt(i));
}
}
}
The output
2.0T
2.1C
2.2C
4.3C
4.4C
And what i want 2.1T 2.2C 5.2C
The output that you expect will never be obtained from your above code.. Because in your if construct will be executed every time you encounter a '-' in your first string.. And hence you will have 5 outputs, not 3..
Second, to get what you need, you will have to do some extra work here..
First When you encounter a '-' in your 1st String, you need to store the corresponding character from your second String into some variable.. Because you need it to check for continuous characters.
Second, each time to get a '-', check the current character with the last character matched for the previous '-'. If it is the same, increase the count by 1,
If it is not the same, just print what you want.. and reset your count to 0
As soon as you encounter the character which not '-' in your first string, print the current character and the count value, and reset them..
You can try to code according to the steps I have mentioned..
*PS: - For any problem you get to code, you should first write down the steps you should follow to solve it on paper. Then convert it to code step-by-step. It will be easier to understand the problem and solve it also..

Categories

Resources