i want to test if current char current is not ',', '-', '.' or ' '
Is there a shorter expression for:
if((current != ' ') || (current != '.') || ...)
any ideas?
EDIT:
I am just allowed to use the methods nextChar and getChar. I have to loop through the chars.
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class WoerterZaehlen {
public static void main(String[] args) {
int wordCount = 0;
/* Ab hier dürft ihr eigenen Code einfügen */
char previous = ' ';
while(hasNextChar()){
char current = getChar();
if(current != )
//if(((current == ' ') || (current == '.') || (current == ',')) && ((previous != ' ') && (previous != ','))){
// wordCount++;
//}
previous = current;
}
/* Ab hier dürft ihr nichts mehr ändern. */
System.out.println("Anzahl der Wörter: " + wordCount);
}
private static InputStreamReader reader;
private static int next = -1;
public static boolean hasNextChar() {
if(next != -1)
return true;
try {
if(reader == null)
reader = new InputStreamReader(new FileInputStream("textdatei.txt"));
next = reader.read();
} catch (IOException e) {
System.out.println("Datei wurde nicht gefunden.");
}
return next != -1;
}
public static char getChar() {
char c = (char) next;
next = -1;
return c;
}
}
Try
String prohibitedChars = ",-. ";
boolean isProhibited = prohibitedChars.indexOf('-') > -1;
I cleaned it up to appear a bit nice, but if you're really after short then all you need is:
",-. ".indexOf('-') > -1;
EDIT:
You can still use this approach even if you are limited to getChar() and hasNextChar()
while(hasNextChar()){
char current = getChar();
if (",-. ".indexOf(current) > -1) {
wordCount++;
}
previous = current;
}
BitSet unwantedChars=new BitSet();
unwantedChars.set('.');
unwantedChars.set(',');
unwantedChars.set('-');
unwantedChars.set(' ');
char current=',';
if(unwantedChars.get(current)) //true if unwanted char else false
{
//....
}
Using Google Guava:
CharMatcher unwantedChars=CharMatcher.anyOf("-,. ").precomputed();
unwantedChars.apply(',');//true if unwanted char else false
if you are not allowed to use String.indexOf like in:
if (" .,".indexOf(ch) != -1) {
/* do something */
} else {
/* do if none of the above */
}
use a switch like in
switch (ch) {
case ' ': case '.': case ',': /* do something */ break;
default: /* do if none of the above */ break;
}
(instead of saving the previous char, you could just use a boolean to indicate if the previous char was a word boundary or a legal word character)
If it is an entire string you are looping through you might want to consider using regular expressions.
An example of validating with regex:
Checking String for illegal characters using regular expression
The example is white-listing character rather than blacklisting. This would in most cases be the preferred option as there is far more legal character-ranges than illegal.
or if you wanted to be ridiculous put the chars in a static BitSet, and use isSet(current).
Unless this code is going to be executed millions of times, i'd stick with what you have, as code clarity is more important than unmeasurable performance gains.
since many provide other solutions i'll provide the one you would use without the limitations.
String prohibitedChars = ",-. ";
prohibitedChars.contains(char);
Related
I'm having a bit of trouble trying to create a recursive method that counts the number of periods and spaces in a string. I can do this pretty easily using iteration, but I'm still fairly new to the concept of recursion. Here's my code so far,
could anyone tell me where I'm going wrong?
public static int periodsAndSpaces(String s){ //option 3
if(s.length()<0){ //base case
return 0;
}
else if(s.charAt(0) == ' ' || s.charAt(0) == '.'){ //general case
return periodsAndSpaces(s.substring(1)) + 1;
}
return 0;
}
package com.test.demo;
public class Counter {
public static void main(String[] args) {
System.out.println(new Counter().countPeriodsAndSpaces(" test. . .a"));
}
int countPeriodsAndSpaces(String rs) {
if (rs == null || rs.isEmpty())
return 0;
char c = rs.charAt(0);
if (c == ' ' || c == '.')
return 1 + countPeriodsAndSpaces(rs.substring(1));
else
return countPeriodsAndSpaces(rs.substring(1));
}
}
// Output 6
New method with everyone's suggestions:
public static int periodsAndSpaces(String s){ //option 3
if(s.length()==0){ //base case
return 0;
}
else if(s.charAt(0) == ' ' || s.charAt(0) == '.'){
return periodsAndSpaces(s.substring(1)) + 1;
}
else{
return periodsAndSpaces(s.substring(1));
}
}
Method stops running when there are no more characters left in the string, and I've added another case for adding onto the sum of periods and spaces when the current char doesn't have either of these.
So this is a slightly different take on the age old rock, paper, scissors java example. In this situation, the user enters the input (that I'm assuming is valid, i.e. uses only combinations of R,P, & S, and has matching parenthesis, also no spaces) like for example, (R&S) the output is R because Rock beats Scissors, or ((R&S)&(P&R)) outputs P.
Now so far I have code (below) that can split the strings, iterate through and get the letters used into a list, because my idea was just to read from left to right, evaluating until I get to the end but at this point I'm stumped because what would be a good way to keep track of all the "previous" results. Would I need another empty list? Also using cases doesn't seem viable since the input can be long and also completely random combination of R,P, and S. Any advice is appreciated!
import java.util.ArrayList;
import java.util.Scanner;
public class RPS {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
str = str.replaceAll("\\(", "").replaceAll("\\)","");
String inputs[] = str.split("&");
ArrayList<Object> list = new ArrayList<>();
for (int i = 0; i < inputs.length; i++){
if (inputs[i].substring(0, 1).contains("R")) {
list.add(inputs[i]);
} else if (inputs[i].substring(0, 1).contains("S")) {
list.add(inputs[i]);
} else if (inputs[i].substring(0, 1).contains("P")) {
list.add(inputs[i]);
}
}
for (int i = 0; i < list.size(); i++){
if (list.contains("R") && list.contains("S")){ //ex. if the input was "(R&S)"
System.out.println("R");
break;
}
}
}
}
One way to solve this would be to write a recursive evaluate function. It would take a string as input, with the base case being a single character R, P, or S. Otherwise, it would split the string on the top-level ampersand, and recursively evaluate the string to the left and right of the ampersand, and use the returned characters to determine the result. The top-level ampersand could be found as the ampersand occurring not within a set of parentheses (not counting any outermost redundant parentheses if they exist).
For example, here's an implementation in Java.
import java.util.Stack;
public class RPS {
// Normalize string by removing surrounding parentheses that are redundant.
private static String normalize(String s) {
// First, count the number of leading open parentheses.
int leading = 0;
for (int i = 0; i < s.length(); ++i) {
if (s.charAt(i) != '(')
break;
++leading;
}
if (leading > 0) {
// For each closing parenthesis, compute the position of the
// matching opening parenthesis. The set of trailing parentheses
// paired with leading parentheses are redundant.
Stack<Integer> stack = new Stack<Integer>();
for (int i = 0; i < s.length(); ++i) {
char c = s.charAt(i);
if (c == '(') {
stack.push(i);
} else if (c == ')') {
int j = stack.pop();
if (j < leading && j + i + 1 == s.length())
return s.substring(j + 1, s.length() - j - 1);
}
}
}
return s;
}
private static char evaluate(String s) {
s = normalize(s);
// A single character evaluates to itself
if (s.length() == 1)
return s.charAt(0);
// Find the position of the top-level ampersand, which is the ampersand
// occurring outside matched pairs of parentheses.
int depth = 0;
int position = -1;
for (int i = 0; i < s.length(); ++i) {
char c = s.charAt(i);
if (c == '(')
depth += 1;
else if (c == ')')
depth -= 1;
else if (depth == 0 && c == '&') {
position = i;
break;
}
}
// Otherwise, split on the top-level ampersand and evaluate the left
// and right sides.
char left = evaluate(s.substring(0, position));
char right = evaluate(s.substring(position + 1));
// Return the winner
if (left == right)
return left;
switch (left) {
case 'R':
return right == 'P' ? 'P' : 'R';
case 'P':
return right == 'S' ? 'S' : 'P';
case 'S':
return right == 'R' ? 'R' : 'S';
default:
throw new RuntimeException();
}
}
public static void main(String[] args) {
System.out.println(evaluate("((R&S)&(P&R))"));
System.out.println(evaluate("(R&S)&(P&R)"));
System.out.println(evaluate("(R)"));
System.out.println(evaluate("((((R&P))&((S))))"));
System.out.println(evaluate("((R&S)&R)"));
System.out.println(evaluate("S"));
System.out.println(evaluate("(((R&P)&(S&P))&(P&R))"));
}
}
Output:
P
P
R
S
R
S
S
If you process your input and convert it to reverse polish notation, you can use a Stack to hold the values and the operators.
Here's what I mean. Take your simple input.
(R&S)
On a Stack, it would look like:
R
S
&
The stack should always start with two values and one operator.
Let's take your more complicated example.
((R&S)&(P&R))
On a Stack, it would look like:
R
S
&
P
R
&
&
You'd replace the RS& on the Stack with the result. Then you'd replace the PR& on the Stack with the result. The final result would be processed with the last & operator.
One way to solve this is to first parse the string into a tree where nodes are either 1) a character or 2) a group of children nodes representing items in parentheses. Then call a recursive evaluation function on the tree.
For example, here's an implementation in Java that has error checking and support for white spaces (which are ignored), followed by my initial prototype in Python, which is shorter, but does not include error checking nor support for white spaces.
Java
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
public class RPS {
private static class Node {
Character data = null;
List<Node> children = null;
}
private static Node parse(Queue<Character> tokens) {
// WARN: Destructively modifies input
char token = tokens.remove();
Node node = new Node();
if (token == '(') {
node.children = new ArrayList<Node>();
while (tokens.peek() != ')') {
node.children.add(parse(tokens));
}
char c = tokens.remove();
if (c != ')')
throw new RuntimeException();
} else if (token == ')') {
throw new RuntimeException();
} else {
node.data = token;
}
return node;
}
private static char _evaluate(Node tree) {
if (tree.data != null) {
return tree.data;
} else if (tree.children.size() == 1) {
return _evaluate(tree.children.get(0));
} else {
char left = _evaluate(tree.children.get(0));
if (!tree.children.get(1).data.equals('&'))
throw new RuntimeException();
char right = _evaluate(tree.children.get(2));
// Return the winner
if (left == right)
return left;
switch (left) {
case 'R':
return right == 'P' ? 'P' : 'R';
case 'P':
return right == 'S' ? 'S' : 'P';
case 'S':
return right == 'R' ? 'R' : 'S';
default:
throw new RuntimeException();
}
}
}
private static Set<Character> VALID_CHARS =
new HashSet<Character>() {{
add('(');
add(')');
add('&');
add('R');
add('P');
add('S');
}};
public static char evaluate(String s) {
Queue<Character> tokens = new LinkedList<Character>();
tokens.add('(');
for (int i = 0; i < s.length(); ++i) {
char c = Character.toUpperCase(s.charAt(i));
if (Character.isWhitespace(c))
continue;
if (!VALID_CHARS.contains(c))
throw new RuntimeException();
tokens.add(c);
}
tokens.add(')');
Node tree = parse(tokens);
char c = _evaluate(tree);
return c;
}
public static void main(String[] args) {
System.out.println(evaluate("((R&S)&(P&R))")); // P
System.out.println(evaluate("(R&S)&(P&R)")); // P
System.out.println(evaluate("( R )")); // R
System.out.println(evaluate("((((R&P))&((S))))")); // S
System.out.println(evaluate("((R&S)&R)")); // R
System.out.println(evaluate("S")); // S
System.out.println(evaluate("(((R&P)&(S&P))&(P&R))")); // S
}
}
Python
from collections import deque
from typing import Union
def parse(tokens: deque):
# WARN: Destructively modifies input
token = tokens.popleft()
if token == '(':
result = []
while tokens[0] != ')':
result.append(parse(tokens))
tokens.popleft() # closing ')'
return result
else:
return token
def _evaluate(tree: Union[list, str]):
if type(tree) != list:
return tree
elif len(tree) == 1:
return _evaluate(tree[0])
else:
left = _evaluate(tree[0])
right = _evaluate(tree[2])
pair = left + right
lookup = {
'RP': 'P', 'PR': 'P', 'PP': 'P',
'RS': 'R', 'SR': 'R', 'RR': 'R',
'PS': 'S', 'SP': 'S', 'SS': 'S',
}
return lookup[pair]
def evaluate(s: str):
tokens = deque(f'({s})')
tree = parse(tokens)
return _evaluate(tree)
# Example usage
print(evaluate('((R&S)&(P&R))')) # P
print(evaluate('(R&S)&(P&R)')) # P
print(evaluate('(R)')) # R
print(evaluate('((((R&P))&((S))))')) # S
print(evaluate('((R&S)&R)')) # R
print(evaluate('S')) # S
print(evaluate('(((R&P)&(S&P))&(P&R))')) # S
The rest of the code is working perfectly but I cannot figure out how to prevent punctuation from being translated.
public class PigLatintranslator
{
public static String translateWord (String word)
{
String lowerCaseWord = word.toLowerCase ();
int pos = -1;
char ch;
for (int i = 0 ; i < lowerCaseWord.length () ; i++)
{
ch = lowerCaseWord.charAt (i);
if (isVowel (ch))
{
pos = i;
break;
}
}
if (pos == 0 && lowerCaseWord.length () != 1) //translates if word starts with vowel
{
return lowerCaseWord + "way"; // Adding "way" to the end of string
}
else if (lowerCaseWord.length () == 1) //Ignores words that are only 1 character
{
return lowerCaseWord;
}
else if (lowerCaseWord.charAt(0) == 'q' && lowerCaseWord.charAt(1) == 'u')//words that start with qu
{
String a = lowerCaseWord.substring (2);
return a + "qu" + "ay";
}
else
{
String a = lowerCaseWord.substring (1);
String b = lowerCaseWord.substring (0,1);
return a + b + "ay"; // Adding "ay" at the end of the extracted words after joining them.
}
}
public static boolean isVowel (char ch) checks for vowel
{
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'y')
{
return true;
}
return false;
}
}
I need the translation to ignore punctuation. For example "Question?" should be translated to "estionquay?" (question mark still in the same position and not translated)
As Andreas said, if the function is expecting only one word, it should be the responsibility of the calling function to ensure there's no full sentence or punctuation being passed to it. With that said, if you require the translator to handle this, you need to find the index of the string where the punctuation or non-letter character occurs. I added in a main method to test the function:
public static void main(String[] args) {
System.out.println(translateWord("QUESTION?"));
}
I added a loop into the qu case to find the punctuation being input, the two checks are to see if the character at position i is inside the range of a - z. The sub-string then only goes to the point where the punctuation is found.
int i;
for (i = 0; i < lowerCaseWord.length(); i++) {
if(lowerCaseWord.charAt(i) > 'z' || lowerCaseWord.charAt(i) < 'a') {
break;
}
}
String a = lowerCaseWord.substring (2, i);
String b = lowerCaseWord.substring(i);
return a + "qu" + "ay" + b;
This may need some tweaking if you're worried about words with hyphens and whatnot but this should put across the basic idea.
Here's the output I received:
$javac PigLatintranslator.java
$java -Xmx128M -Xms16M PigLatintranslator
estionquay?
Basically I want to recursively get this:
“ pErHaPs I hAVe wRitten a Sentence LiKE this one “
To look like this:
“perhapsIHaveWrittenASentenceLikeThisOne”
n>0 of spaces before, between, and after each word
any assortment of upper-case and lower-case letters
ex: " lIkE ThIs"
What I think I understand:
Using string.charAt(i) to compare the specific character to a space
Using Character.isUpperCase() for case checking
What I don't understand:
How recursion will work to change the string since strings are immutable
What the base case will be
how to only uppercase the first letter of every word after the first word
EDIT:
This is what I have come up with after a few helpful hints:
`public static String toCamelCase(String str) {
if(str.length() == 1) {
if(str.charAt(0) == ' ') {
return "";
} else {
return str;
}
} else if(str.charAt(0) == ' ' && str.length() != 1) {
if(str.charAt(1) != ' ') {
return str.substring(1, 2).toUpperCase() + toCamelCase(str.substring(2, str.length()));
} else {
return toCamelCase(str.substring(1, str.length()));
}
} else if(str.charAt(0) != ' ' && str.length() != 1) {
if(str.charAt(1) != ' ') {
return str.substring(0,2).toLowerCase() + toCamelCase(str.substring(2, str.length()));
} else {
return str.substring(0,1).toLowerCase() + toCamelCase(str.substring(1, str.length()));
}
}
return str;
}`
Everything works except the first letter of the first word is also capitalized. How would I make the code exclude the first word when uppercasing first letters of words? Is this possible recursively?
There you go with your recursive implementation:
public String camelCase(String inputStr) {
String s = inputStr.toLowerCase();
String[] arr = s.split(" ");
s = arr[0];
return getCamelCased(s,1,arr);
}
private String getCamelCased(String s, int index, String[] arr) {
if(index >= arr.length)
return s;
String curr = arr[index++];
s += curr.length()==1?curr.toUpperCase():
(curr.toUpperCase.charAt(0)+curr.substring(1,curr.length()));
return getCamelCased(s,index,arr);
}
package edu.bsu.cs121.mamurphy;
import java.util.Stack;
public class Checker {
char openPara = '(';
char openBracket = '[';
char openCurly = '{';
char openArrow = '<';
char closePara = ')';
char closeBracket = ']';
char closeCurly = '}';
char closeArrow = '>';
public boolean checkString(String stringToCheck) {
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < stringToCheck.length(); i++) {
char c = stringToCheck.charAt(i);
if (c == openPara || c == openBracket || c == openCurly || c == openArrow) {
stack.push(c);
System.out.println(stack);
;
}
if (c == closePara) {
if (stack.isEmpty()) {
System.out.println("Unbalanced");
break;
} else if (stack.peek() == openPara) {
stack.pop();
} else if (stack.size() > 0) {
System.out.println("Unbalanced");
break;
}
}
if (c == closeBracket) {
if (stack.isEmpty()) {
System.out.println("Unbalanced");
break;
} else if (stack.peek() == openBracket) {
stack.pop();
} else if (stack.size() > 0) {
System.out.println("Unbalanced");
break;
}
}
if (c == closeCurly) {
if (stack.isEmpty()) {
System.out.println("Unbalanced");
break;
} else if (stack.peek() == openCurly) {
stack.pop();
} else if (stack.size() > 0) {
System.out.println("Unbalanced");
break;
}
}
if (c == closeArrow) {
if (stack.isEmpty()) {
System.out.println("Unbalanced");
break;
} else if (stack.peek() == openArrow) {
stack.pop();
} else if (stack.size() > 0) {
System.out.println("Unbalanced");
break;
}
}
}
return false;
}
}
I am currently trying to create a program where I check to see if a string is balanced or not. A string is balanced if and only if each opening character: (, {, [, and < have a matching closing character: ), }, ], and > respectively.
What happens is when checking through the string, if an opening character is found, it is pushed into a stack, and it checks to see if there is the appropriate closing character.
If there is a closing character before the opening character, then that automatically means that the string is unbalanced. Also, the string is automatically unbalanced if after going to the next character there is something still inside of the stack.
I tried to use
else if (stack.size() > 0) {
System.out.println("Unbalanced");
break;
}
as a way of seeing if the stack still had anything in it, but it still isn't working for me. Any advice on what to do?
For example, if the string input were ()<>{() then the program should run through like normal until it gets to the single { and then the code should realize that the string is unbalanced and output Unbalanced.
For whatever reason, my code does not do this.
The following logic is flawed (emphasis mine):
For example, if the string input were ()<>{() then the program should run through like normal until it gets to the single { and then the code should realize that the string is unbalanced and output Unbalanced.
In fact, the code can't conclude that the string is unbalanced until it has scanned the entire string and established that the { has no matching }. For all it knows, the full input could be ()<>{()} and be balanced.
To achieve this, you need to add a check that ensures that the stack is empty after the entire string has been processes. In your example, it would still contain the {, indicating that the input is not balanced.
I took a shot at answering this. My solutions returns true if the string is balanced and enforces opening/closing order (ie ({)} returns false). I started with your code and tried to slim it down.
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
public class mamurphy {
private static final char openPara = '(';
private static final char openBracket = '[';
private static final char openCurly = '{';
private static final char openArrow = '<';
private static final char closePara = ')';
private static final char closeBracket = ']';
private static final char closeCurly = '}';
private static final char closeArrow = '>';
public static void main(String... args) {
System.out.println(checkString("{}[]()90<>"));//true
System.out.println(checkString("(((((())))"));//false
System.out.println(checkString("((())))"));//false
System.out.println(checkString(">"));//false
System.out.println(checkString("["));//false
System.out.println(checkString("{[(<>)]}"));//true
System.out.println(checkString("{[(<>)}]"));//false
System.out.println(checkString("( a(b) (c) (d(e(f)g)h) I (j<k>l)m)"));//true
}
public static boolean checkString(String stringToCheck) {
final Map<Character, Character> closeToOpenMap = new HashMap<>();
closeToOpenMap.put(closePara, openPara);
closeToOpenMap.put(closeBracket, openBracket);
closeToOpenMap.put(closeCurly, openCurly);
closeToOpenMap.put(closeArrow, openArrow);
Stack<Character> stack = new Stack<>();
final char[] stringAsChars = stringToCheck.toCharArray();
for (int i = 0; i < stringAsChars.length; i++) {
final char current = stringAsChars[i];
if (closeToOpenMap.values().contains(current)) {
stack.push(current); //found an opening char, push it!
} else if (closeToOpenMap.containsKey(current)) {
if (stack.isEmpty() || closeToOpenMap.get(current) != stack.pop()) {
return false;//found closing char without correct opening char on top of stack
}
}
}
if (!stack.isEmpty()) {
return false;//still have opening chars after consuming whole string
}
return true;
}
}
Here's an alternate approach:
private static final char[] openParens = "[({<".toCharArray();
private static final char[] closeParens = "])}>".toCharArray();
public static boolean isBalanced(String expression){
Deque<Character> stack = new ArrayDeque<>();
for (char c : expression.toCharArray()){
for (int i = 0; i < openParens.length; i++){
if (openParens[i] == c){
// This is an open - put it in the stack
stack.push(c);
break;
}
if (closeParens[i] == c){
// This is a close - check the open is at the top of the stack
if (stack.poll() != openParens[i]){
return false;
}
break;
}
}
}
return stack.isEmpty();
}
It simplifies the logic to have two corresponding arrays of open and close symbols. You could also do this with even and odd positions in one array - ie. "{}<>", for example:
private static final char[] symbols = "[](){}<>".toCharArray();
public static boolean isBalanced(String expression){
Deque<Character> stack = new ArrayDeque<>();
for (char c : expression.toCharArray()){
for (int i = 0; i < symbols.length; i += 2){
if (symbols[i] == c){
// This is an open - put it in the stack
stack.push(c);
break;
}
if (symbols[i + 1] == c){
// This is a close - check the open is at the top of the stack
if (stack.poll() != symbols[i]){
return false;
}
break;
}
}
}
return stack.isEmpty();
}
Note that poll returns null if the stack is empty, so will correctly fail the equality comparison if we run out of stack.
For example, if the string input were ()<>{() then the program should run through like normal until it gets to the single { and then the code should realize that the string is unbalanced and output Unbalanced.
It is not clear by your example whether the boundaries can be nested like ([{}]). If they can, that logic will not work, as the whole string has to be consumed to be sure any missing closing-chars aren't at the end, and so, the string cannot be reliably deemed unbalanced at the point you indicate.
Here is my take on your problem:
BalanceChecker class:
package so_q33378870;
import java.util.Stack;
public class BalanceChecker {
private final char[] opChars = "([{<".toCharArray();
private final char[] edChars = ")]}>".toCharArray();
//<editor-fold defaultstate="collapsed" desc="support functions">
public boolean isOPChar(char c) {
for (char checkChar : opChars) {
if (c == checkChar) {
return true;
}
}
return false;
}
public boolean isEDChar(char c) {
for (char checkChar : edChars) {
if (c == checkChar) {
return true;
}
}
return false;
}
//NOTE: Unused.
// public boolean isBoundaryChar(char c) {
// boolean result;
// if (result = isOPChar(c) == false) {
// return isEDChar(c);
// } else {
// return result;
// }
// }
public char getOpCharFor(char c) {
for (int i = 0; i < edChars.length; i++) {
if (c == edChars[i]) {
return opChars[i];
}
}
throw new IllegalArgumentException("The character (" + c + ") received is not recognized as a closing boundary character.");
}
//</editor-fold>
public boolean isBalanced(char[] charsToCheck) {
Stack<Character> checkStack = new Stack<>();
for (int i = 0; i < charsToCheck.length; i++) {
if (isOPChar(charsToCheck[i])) {
//beginning char found. Add to top of stack.
checkStack.push(charsToCheck[i]);
} else if (isEDChar(charsToCheck[i])) {
if (checkStack.isEmpty()) {
//ending char found without beginning chars on the stack. UNBALANCED.
return false;
} else if (getOpCharFor(charsToCheck[i]) == checkStack.peek()) {
//ending char found matches last beginning char on the stack. Pop and continue.
checkStack.pop();
} else {
//ending char found, but doesn't match last beginning char on the stack. UNBALANCED.
return false;
}
}
}
//the string is balanced if and only if the stack is empty at the end.
return checkStack.empty();
}
public boolean isBalanced(String stringToCheck) {
return isBalanced(stringToCheck.toCharArray());
}
}
Main class (used for testing):
package so_q33378870;
public class main {
private static final String[] tests = {
//Single - Balanced.
"()",
//Single - Unbalanced by missing end.
"(_",
//Multiple - Balanced.
"()[]{}<>",
//Multiple - Unbalanced by missing beginning.
"()[]_}<>",
//Nested - Balanced.
"([{<>}])",
//Nested - Unbalanced by missing end.
"([{<>}_)",
//Endurance test - Balanced.
"the_beginning (abcd) divider (a[bc]d) divider (a[b{c}d]e) divider (a[b{c<d>e}f]g) the_end"
};
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
BalanceChecker checker = new BalanceChecker();
for (String s : tests) {
System.out.println("\"" + s + "\" is " + ((checker.isBalanced(s)) ? "BALANCED!" : "UNBALANCED!"));
}
}
}