Analyzing a string of characters - java

I have a string of characters "AAABBB" that I need to parse into a character array in java. I then need to test for "As" and "Bs" only. I can use the following code to work most of the time but when there is a letter that is not an "A" or "B" it may still return true.
StringBuilder a = new StringBuilder();
StringBuilder b = new StringBuilder();
boolean L1 = false;
for (char ch: line.toCharArray()){
ch = L1Stack.peek();
if (ch == 'A'){
a.append(L1Stack.pop());
}
if (ch =='B'){
b.append(L1Stack.pop());
}
}
if(a.length() == b.length()){
L1 = true;
}
return L1;
}
When it reads a line like "ABCBA" it still returns true.
I added this statement
if(ch !='A' || ch !='B')
break;
but then it makes them all false.

This will do what you expected
StringBuilder a = new StringBuilder();
StringBuilder b = new StringBuilder();
boolean L1 = false;
for (char ch: line.toCharArray()){
ch = L1Stack.peek();
if (ch == 'A'){
a.append(L1Stack.pop());
}
else if (ch =='B'){
b.append(L1Stack.pop());
} else {
return false;
}
}
if(a.length() == b.length()){
L1 = true;
}
return L1;
}
I have changed the the this part:
else if (ch =='B'){
b.append(L1Stack.pop());
} else {
return false;
}
If not A and not B is in the string the function returns false

I do not whether using stack was mandatory, yet you could accomplish this in easier way like this
Code:
String s = "AAAACCCAAABBBBBCCAAAACA";
StringBuilder result = new StringBuilder();
String[] sToArray = s.split("");
for (String sIndex : sToArray) {
switch (sIndex) {
case "A":
result.append("A ");
break;
case "B":
result.append("B ");
break;
default:
continue;
}
}
for (String v : result.toString().split(" ")) {
System.out.print(v);
}
output:
AAAAAAABBBBBAAAAA

It would be better to use less memory and objects, if you won't be needing the As and Bs:
int checker = 0;
for (char ch: line.toCharArray()){
ch = L1Stack.peek();
if (ch == 'A'){
L1Stack.pop();
checker++;
}
if (ch =='B'){
L1Stack.pop();
checker--;
}
}
if(checker == 0){
return true;
}
return false;

Related

Code running to slow to pass . Can't figure out why

I have to solve this exercise and I am pretty new to coding. The task is:
In this problem, the input to your program is an array of N characters, each of which is either (, ), [ or ], and your program must return true if the parentheses are properly matched, and false if they are not.
The code works and solves all the tests correct, but it is to slow to pass overall and I can't figure out why. What can I do to improve the speed of the code? Thank in advance.
public class Dyck {
public boolean checkParentheses(ArrayList<Character> input) {
Stack<Character> s = new Stack<>();
Stack<Character> s2 = new Stack<>();
for(var c : input){
s.add(0, c);
}
Character c2;
Character c = s.pop();
if (c != ')' && c != ']') {
s2.add(c);
}
var size = s.size();
for (int i = 0; i < size; ++i) {
c = s.pop();
if (c == '[' || c == '(') {
s2.add(c);
}
if (c == ')') {
if (s2.isEmpty()) {
return false;
}
c2 = s2.pop();
if (c2 != '(') {
return false;
}
}
if (c == ']') {
if (s2.isEmpty()) {
return false;
}
c2 = s2.pop();
if (c2 != '[') {
return false;
}
}
}
if (s.isEmpty() && s2.isEmpty()) {
return true;
}
return false;
}

Java AWS Serverless Lambda [duplicate]

I am using Jackson version 2.4.3 for converting my complex Java object into a String object, so below is what I'm getting in output. The output is like below (Fyi - I just printed some part of the output)
"{\"FirstName\":\"John \",\"LastName\":cena,\"salary\":7500,\"skills\":[\"java\",\"python\"]}";
Here is my code (PaymentTnx is a complex Java object)
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
String lpTransactionJSON = mapper.writeValueAsString(paymentTxn);
I don't want to see \ slashes in my JSON string. What do I need to do to get a string like below:
"{"FirstName":"John ","LastName":cena,"salary":7500,"skills":["java","python"]}";
String test = "{\"FirstName\":\"John \",\"LastName\":cena,\"salary\":7500,\"skills\":[\"java\",\"python\"]}";
System.out.println(StringEscapeUtils.unescapeJava(test));
This might help you.
I have not tried Jackson. I just have similar situation.
I used org.apache.commons.text.StringEscapeUtils.unescapeJson but it's not working for malformed JSON format like {\"name\": \"john\"}
So, I used this class. Perfectly working fine.
https://gist.githubusercontent.com/jjfiv/2ac5c081e088779f49aa/raw/8bda15d27c73047621a94359492a5a9433f497b2/JSONUtil.java
// BSD License (http://lemurproject.org/galago-license)
package org.lemurproject.galago.utility.json;
public class JSONUtil {
public static String escape(String input) {
StringBuilder output = new StringBuilder();
for(int i=0; i<input.length(); i++) {
char ch = input.charAt(i);
int chx = (int) ch;
// let's not put any nulls in our strings
assert(chx != 0);
if(ch == '\n') {
output.append("\\n");
} else if(ch == '\t') {
output.append("\\t");
} else if(ch == '\r') {
output.append("\\r");
} else if(ch == '\\') {
output.append("\\\\");
} else if(ch == '"') {
output.append("\\\"");
} else if(ch == '\b') {
output.append("\\b");
} else if(ch == '\f') {
output.append("\\f");
} else if(chx >= 0x10000) {
assert false : "Java stores as u16, so it should never give us a character that's bigger than 2 bytes. It literally can't.";
} else if(chx > 127) {
output.append(String.format("\\u%04x", chx));
} else {
output.append(ch);
}
}
return output.toString();
}
public static String unescape(String input) {
StringBuilder builder = new StringBuilder();
int i = 0;
while (i < input.length()) {
char delimiter = input.charAt(i); i++; // consume letter or backslash
if(delimiter == '\\' && i < input.length()) {
// consume first after backslash
char ch = input.charAt(i); i++;
if(ch == '\\' || ch == '/' || ch == '"' || ch == '\'') {
builder.append(ch);
}
else if(ch == 'n') builder.append('\n');
else if(ch == 'r') builder.append('\r');
else if(ch == 't') builder.append('\t');
else if(ch == 'b') builder.append('\b');
else if(ch == 'f') builder.append('\f');
else if(ch == 'u') {
StringBuilder hex = new StringBuilder();
// expect 4 digits
if (i+4 > input.length()) {
throw new RuntimeException("Not enough unicode digits! ");
}
for (char x : input.substring(i, i + 4).toCharArray()) {
if(!Character.isLetterOrDigit(x)) {
throw new RuntimeException("Bad character in unicode escape.");
}
hex.append(Character.toLowerCase(x));
}
i+=4; // consume those four digits.
int code = Integer.parseInt(hex.toString(), 16);
builder.append((char) code);
} else {
throw new RuntimeException("Illegal escape sequence: \\"+ch);
}
} else { // it's not a backslash, or it's the last character.
builder.append(delimiter);
}
}
return builder.toString();
}
}
With Jackson do:
toString(paymentTxn);
with
public String toString(Object obj) {
try (StringWriter w = new StringWriter();) {
new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true).writeValue(w, obj);
return w.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
This here is not valid JSON:
"{"FirstName":"John ","LastName":cena,"salary":7500,"skills":["java","python"]}";
This here is valid JSON, specifically a single string value:
"{\"FirstName\":\"John \",\"LastName\":cena,\"salary\":7500,\"skills\":[\"java\",\"python\"]}";
Given that you're calling writeValueAsString, this is the correct behaviour. I would suggest writeValue, perhaps?

setCharAt method not working as expected inside for loop (Java)

I am trying to develop a method to reverse the vowels in a string. For this, I have developed my own small stack. I am iterating backwards through the string twice, once to populate the stack with each vowel I locate, the second time to replace the vowel with the vowel stored at the top of the stack. I have added a bunch of print statements to determine where this is failing and it seems to be failing at the setCharAt method. For testing purposes, I provide a string aeiou and I am expecting to get back uoiea. The chars are getting replaced during each iteration, but unfortunately, they don't stay that way. As of the next iteration, the chars that were replaced on the previous iteration return to what they were before. As a result, I am getting back ueiou, where only the first character in the string is as expected (and the third which is a noop). Here is my code. Any tips are appreciated.
import java.util.*;
public class Solution {
static String result;
static class StackOfVowels {
static Node top;
public StackOfVowels() {
Node top = null;
}
static class Node {
Node next = null;
char vowel = '\0';
Node(char value) {
this.vowel = value;
}
}
public void push(char item) {
Node node = new Node(item);
if (top == null) {
top = node;
}
else {
node.next = top;
top = node;
}
}
public char top() {
if (top == null) throw new EmptyStackException();
return top.vowel;
}
public void pop() {
int result = -1;
if (top != null) {
result = top.vowel;
top = top.next;
}
}
}
public static String reverseVowels(String s) {
StackOfVowels stackOfVowels = new StackOfVowels();
for(int i = s.length()-1; i >= 0; i--) {
char c = s.charAt(i);
if ((c == 'a') || (c == 'e') || (c == 'i') || (c == 'o') || (c == 'u')) {
System.out.println("Initial sequence of iterations identified vowel: " + c);
stackOfVowels.push(c);
System.out.println("Pushed to stack, current top is: " + stackOfVowels.top());
}
}
for(int j = s.length()-1; j >= 0; j--) {
char b = s.charAt(j);
if ((b == 'a') || (b == 'e') || (b == 'i') || (b == 'o') || (b == 'u')) {
System.out.println("Second sequence of iterations identified vowel: " + b);
StringBuilder newstr = new StringBuilder(s);
char d = stackOfVowels.top();
System.out.println("Variable d set to top of: " + stackOfVowels.top());
newstr.setCharAt(j, d);
result = newstr.toString();
System.out.println("Here is the new string: " + result);
stackOfVowels.pop();
System.out.println("Stack was popped");
}
}
return result;
}
public static void main(String[] args) {
String s = "aeiou";
reverseVowels(s);
System.out.println("Final result: " + result);
}
}
A slight improvement (debatable) on #Elliot answer is to create the StringBuilder with the original String and only replace when necessary
String vowels = new StringBuilder(s.replaceAll("[^AEIOUaeiou]", ""))
.reverse().toString();
StringBuilder sb = new StringBuilder(s);
for (int i = 0, p = 0; i < s.length(); i++) {
switch (Character.toLowerCase(s.charAt(i))) {
// Note that these fall-through...
case 'a': case 'e': case 'i': case 'o': case 'u':
sb.setCharAt(i, vowels.charAt(p++));
break;
default:
break;
}
}
return sb.toString();
You generate always a new StringBuilder in your second loop with StringBuilder newstr = new StringBuilder(s);
But you always use ´s´ and not ´result´ to build your new StringBuilder.
It would be better anyways to not create a new Object of StringBuilder in each Iteration.
Also it is confusing that your methode has a return value, which is never used.
Following methode should work:
public static String reverseVowels(String s) {
StackOfVowels stackOfVowels = new StackOfVowels();
for(int i = s.length()-1; i >= 0; i--) {
char c = s.charAt(i);
if ((c == 'a') || (c == 'e') || (c == 'i') || (c == 'o') || (c == 'u')) {
System.out.println("Initial sequence of iterations identified vowel: " + c);
stackOfVowels.push(c);
System.out.println("Pushed to stack, current top is: " + stackOfVowels.top());
}
}
StringBuilder result_builder = new StringBuilder(s);
for(int j = s.length()-1; j >= 0; j--) {
char b = s.charAt(j);
if ((b == 'a') || (b == 'e') || (b == 'i') || (b == 'o') || (b == 'u')) {
System.out.println("Second sequence of iterations identified vowel: " + b);
char d = stackOfVowels.top();
System.out.println("Variable d set to top of: " + stackOfVowels.top());
result_builder.setCharAt(j, d);
stackOfVowels.pop();
System.out.println("Stack was popped");
}
}
result = result_builder.toString();
return result_builder.toString();
}
I would approach the problem a little differently, first I would use a regular expression to remove all consonants from the String to create a String of vowels. Then I would iterate through the characters of the String, using StringBuilder to build the output (passing consonants through, but replacing vowels using the vowels String previously created). Like,
public static String reverseVowels(String s) {
// Match all consonants, and remove them. Reverse that String.
String vowels = new StringBuilder(s.replaceAll("[^AEIOUaeiou]", ""))
.reverse().toString();
StringBuilder sb = new StringBuilder();
for (int i = 0, p = 0; i < s.length(); i++) {
switch (Character.toLowerCase(s.charAt(i))) {
// Note that these fall-through...
case 'a': case 'e': case 'i': case 'o': case 'u':
sb.append(vowels.charAt(p++));
break;
default:
sb.append(s.charAt(i));
}
}
return sb.toString();
}
This is one of the places that switch and fall-through behavior can be taken advantage of.
And if you're using Java 8+, you could express the same with an IntStream and map the characters; like
String vowels = new StringBuilder(s.replaceAll("[^AEIOUaeiou]", ""))
.reverse().toString();
int[] counter = new int[1]; // <-- A bit of a kludge really.
return IntStream.range(0, s.length()).mapToObj(i -> {
switch (Character.toLowerCase(s.charAt(i))) {
case 'a': case 'e': case 'i': case 'o': case 'u':
return Character.toString(vowels.charAt(counter[0]++));
default:
return Character.toString(s.charAt(i));
}
}).collect(Collectors.joining());

Translating a regex into a more basic code

How can I write the below code without using regex?
public static boolean validateCode(String code){
boolean hasAtLeastOneNumber = Pattern.compile("[0-9].*[0-9]")
.matcher(code).find();
boolean hasAtLeastTwoLetters = Pattern.compile("[a-zA-Z].*[a-zA-Z]")
.matcher(code).find();
boolean hasAtLeastOneHyphen = Pattern.compile("-")
.matcher(code).find();
}
How about
public static boolean validateCode2(String code) {
int numbers = 0, letters = 0, hyphens = 0;
for (char c : code.toCharArray()) {
if (Character.isDigit(c)) numbers++;
if (Character.isAlphabetic(c)) letters++;
if (c=='-') hyphens++;
}
return numbers>=2 && letters>=2 && hyphens>=1;
}
For hasAtLeastOneNumber:
for (char c : code.toCharArray()) {
if (Character.isDigit(c)) {
return true;
}
return false;
For hasAtLeastTwoLetters:
int numFound = 0;
for (char c : code.toCharArray()) {
if (Character.isLetter(c)) {
numFound++;
if (numFound >= 2) {
return true;
}
}
}
return false;
For hasAtLeastOneHyphen:
for (char c : code.toCharArray()) {
if (c == '-') {
return true;
}
}
return false;
If you don't want to use toCharArray, you could use:
for (int i=0; i<code.length(); i++) {
char c = code.charAt(i);
// do the rest of the test here
}
That's basically equivalent to using toCharArray except that it's slightly more confusing: someone who looks at the code would need to take a second or two to figure it out. With toCharArray it's obvious what you're doing.
You can loop through the string and test it for ranges of characters. See an example on IDEONE, or ask me if you need an explanation.
import java.util.*;
import java.lang.*;
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
System.out.println(validarCodigo("No-numbers"));
System.out.println(validarCodigo("1-A"));
System.out.println(validarCodigo("This 1 Matches -- :-)"));
}
public static boolean validarCodigo(String codigo) {
int i;
char[] chars = codigo.toCharArray();
char current;
boolean tieneAlmenosUnNumero = false;
boolean tieneAlmenosDosLetras = false;
boolean tieneAlmenosUnGuion = false;
// Check for at least one number
for (i=0; i<chars.length; i++) {
current = chars[i];
if (current >= '0' && current <= '9') {
tieneAlmenosUnNumero = true;
break;
}
}
// Check for at least two letters
int found = 0;
for (i=0; i<chars.length; i++) {
current = chars[i];
boolean lower = current >= 'a' && current <= 'z';
boolean upper = current >= 'A' && current <= 'Z';
if (lower || upper) found++;
if (found == 2){
tieneAlmenosDosLetras = true;
break;
}
}
// Check for at least one hyphen
for (i=0; i<chars.length; i++) {
current = chars[i];
if (current == '-') {
tieneAlmenosUnGuion = true;
break;
}
}
return tieneAlmenosUnNumero && tieneAlmenosDosLetras && tieneAlmenosUnGuion;
}
}

Recognizing negative values when converting infix to postfix

This is my class:
import java.io.*;
import java.util.*;
import java.lang.*;
import java.util.Scanner;
import java.util.List;
import java.util.Stack;
/**
*
* #author rtibbetts268
*/
public class InfixToPostfix
{
/**
* Operators in reverse order of precedence.
*/
private static final String operators = "_-+/*";
private static final String operands = "0123456789x";
public String xToValue(String postfixExpr, String x)
{
char[] chars = postfixExpr.toCharArray();
StringBuilder newPostfixExpr = new StringBuilder();
for (char c : chars)
{
if (c == 'x')
{
newPostfixExpr.append(x);
}
else
{
newPostfixExpr.append(c);
}
}
return newPostfixExpr.toString();
}
public String convert2Postfix(String infixExpr)
{
char[] chars = infixExpr.toCharArray();
StringBuilder in = new StringBuilder(infixExpr.length());
for (int i : chars)
{
if (infixExpr.charAt(i) == '-')
{
if (isOperand(infixExpr.charAt(i+1)))
{
if (i != infixExpr.length())
{
if (isOperator(infixExpr.charAt(i-1)))
in.append('_');
}
else
{
in.append(infixExpr.charAt(i));
}
}
else
{
in.append(infixExpr.charAt(i));
}
}
else
{
in.append(infixExpr.charAt(i));
}
}
chars = in.toString().toCharArray();
Stack<Character> stack = new Stack<Character>();
StringBuilder out = new StringBuilder(in.toString().length());
for (char c : chars)
{
if (isOperator(c))
{
while (!stack.isEmpty() && stack.peek() != '(')
{
if (operatorGreaterOrEqual(stack.peek(), c))
{
out.append(stack.pop());
}
else
{
break;
}
}
stack.push(c);
}
else if (c == '(')
{
stack.push(c);
}
else if (c == ')')
{
while (!stack.isEmpty() && stack.peek() != '(')
{
out.append(stack.pop());
}
if (!stack.isEmpty())
{
stack.pop();
}
}
else if (isOperand(c))
{
out.append(c);
}
}
while (!stack.empty())
{
out.append(stack.pop());
}
return out.toString();
}
public int evaluatePostfix(String postfixExpr)
{
char[] chars = postfixExpr.toCharArray();
Stack<Integer> stack = new Stack<Integer>();
for (char c : chars)
{
if (isOperand(c))
{
stack.push(c - '0'); // convert char to int val
}
else if (isOperator(c))
{
int op1 = stack.pop();
int op2 = stack.pop();
int result;
switch (c) {
case '*':
result = op1 * op2;
stack.push(result);
break;
case '/':
result = op2 / op1;
stack.push(result);
break;
case '+':
result = op1 + op2;
stack.push(result);
break;
case '-':
result = op2 - op1;
stack.push(result);
break;
}
}
}
return stack.pop();
}
private int getPrecedence(char operator)
{
int ret = 0;
if (operator == '_')
{
ret = 0;
}
if (operator == '-' || operator == '+')
{
ret = 1;
}
else if (operator == '*' || operator == '/')
{
ret = 2;
}
return ret;
}
private boolean operatorGreaterOrEqual(char op1, char op2)
{
return getPrecedence(op1) >= getPrecedence(op2);
}
private boolean isOperator(char val)
{
return operators.indexOf(val) >= 0;
}
private boolean isOperand(char val)
{
return operands.indexOf(val) >= 0;
}
}
In it I change infix expressions to postfix expressions with the method convert2Postfix()
There is a small section in it at the very beginning where I am rewriting the string input with all negative numbers having a '_' infront of them instead of a "-". It doesn't work.
ex: change -4 to _4
What do I need to do to make this work?
You have a number of errors here, here is the first one:
for (int i : chars)
chars is converted to the corresponding int. For example if chars contains one single character 'A':
char [] chars = new char[1];
chars[0] = 'A';
for(int i: chars){
System.out.println(i); //You will have a '65' here
}
What you really mean is probably:
for (int i=0;i<chars.length;++i)
This is also wrong:
if (isOperator(infixExpr.charAt(i-1)))
It should be :
if (isOperator(infixExpr.charAt(i)))
Then there is a problem in the way you put and remove elements in the stack.
After all this changes you should also do this:
return out.reverse().toString();
instead of :
return out.toString();
Here is what I ended up with: http://pastebin.com/2TLqPUsH
(Change the name of the classes of course)

Categories