I am trying to convert an expression given as a String into an Integer. For ex. if given "1+5*5" the method should return "26". I started writing the code only for solving a multiplication, however, when I run it there is not an output
public static void operationS(ArrayList<String> m)
{
for (int i=0; i<m.size(); i++)
{
while ( (m.get(i)).contains("*"))
{
int x = ((m.get(i)).indexOf("*"));
char A=((m.get(i)).charAt(x-1));
char B= ((m.get(i)).charAt(x+1));
int r= Character.getNumericValue(A)*Character.getNumericValue(B);
String numberAsString = Integer.toString(r);
if(x==1 && (m.get(i)).length()==3)
{
m.set(i, numberAsString);
}
if(x==1 && (m.get(i)).length()>3)
{
String n = numberAsString+((m.get(i)).substring(x+2));
m.set(i, n);
}
else
{
String k= ((m.get(i)).substring(0,x-1))+numberAsString+((m.get(i)).substring(x+2));
}
}
}
for (int u=0;u<m.size();u++)
{
System.out.println (m.get(u));
}
}
Since I cannot import any libraries, my plan of action was replacing the String every time an operation was completed.
I plan on using the same loop for adding, subtracting and dividing
Consider parsing your expression. You can probably use an Prefix, Infix, or Postfix notation and parsing to evaluate the input expression.
I came across an article that can help you in understanding how to achieve this:
http://www.sunshine2k.de/coding/java/SimpleParser/SimpleParser.html
The article basically talks about different approaches to solve this problem.
I personally liked the recursive approach. So if you understand recursion, you can choose that.
But if you have a requirement to use only a loop, you may prefer one of the other approaches.
Update: Adding a sample piece of code implementing recursion based on the article linked above.
static final char[] ops = { '-', '+', '*', '/'};
static double evaluate(String s){
for(char op: ops) {
if(s.contains(String.valueOf(op))){
String op1 = s.substring(0, s.indexOf(op));
String op2 = s.substring(s.indexOf(op) + 1, s.length());
switch(op) {
case '-': return evaluate(op1) - evaluate(op2);
case '+': return evaluate(op1) + evaluate(op2);
case '*': return evaluate(op1) * evaluate(op2);
case '/': return evaluate(op1) / evaluate(op2);
}
}
}
/* at this point there is no operator in the term anymore, just a number */
return (convertToDouble(s));
}
private static double convertToDouble(String s) {
return Double.parseDouble(s);
}
Try this.
static String replaceAll(CharSequence cseq, String regex, Function<MatchResult, String> replacement) {
Matcher matcher = Pattern.compile(regex).matcher(cseq);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String replaced = replacement.apply(matcher.toMatchResult());
matcher.appendReplacement(sb, Matcher.quoteReplacement(replaced));
}
matcher.appendTail(sb);
return sb.toString();
}
static int toInt(String s) {
return Integer.parseInt(s);
}
And
String input = "1 + 5 * 5";
String output = input;
while (true) {
String r = replaceAll(output, "(\\d+)\\s*\\*\\s*(\\d+)",
m -> "" + (toInt(m.group(1)) * toInt(m.group(2))));
if (r.equals(output)) break;
output = r;
}
while (true) {
String r = replaceAll(output, "(\\d+)\\s*\\+\\s*(\\d+)",
m -> "" + (toInt(m.group(1)) + toInt(m.group(2))));
if (r.equals(output)) break;
output = r;
}
System.out.println(input + " -> " + output);
result:
1 + 5 * 5 -> 26
Related
I'm trying to create a method that would create an equation for me, as a String.
For example, this method would create:
String formula = "5 + 3";
then another method will solve it.
I don't really know how to create the string. Should i use concat?
Thanks for all the help.
public static String getEquation() {
for(int i=0;i<7;i++){
int rand = rng.nextInt(5);
switch (rand) {
case 0:
operator = "+";
break;
case 1:
operator = "-";
break;
case 2:
operator = "*";
break;
case 3:
operator = "/";
break;
case 4:
operator = "(";
break;
case 5:
operator = ")";
}
}
return formula;
}
Wrote something up really quick, I think this should get you going. You'd have to handle the cases for parentheses though. I didn't account for that.
import java.util.Random;
public class Test {
static Random randomGenerator = new Random();
static String operators = "+-*/P"; //p = parentheses pair
public static char getRandomOperator() {
return operators.charAt(randomGenerator.nextInt(operators.length()));
}
public static int getRandomNumber() {
return randomGenerator.nextInt(100);
}
public static String createEquation() {
//Just for proof of concept, let's do 3 operators
String equation = "";
int numOfOperators = 3;
char operator = ' ';
for (int i = 0; i < numOfOperators; i++) {
equation += getRandomNumber();
equation += getRandomOperator();
}
equation += getRandomNumber();
return equation;
}
public static void main(String[] args) {
String equation = createEquation();
System.out.println(equation);
}
}
I may have time later and come back and address the parentheses issue. For now I just print 'P' where parentheses should be handled.
EDIT
Updated it to handle parentheses. I'm going to paste it down here in case you want to keep it as the old way. Also did a couple tweaks here and there. Note that I didn't handle it matching an exact number of operators when it comes to parenthesis. Which means that if all the open parenthesis weren't closed by the time the loop is done grabbing operators then I append extra parenthesis at the end. Which can result in more than 7 operators. You should probably add logic to either treat a pair of parenthesis as 1 operator or 1 parenthesis as a single operator. Enjoy.
import java.util.Random;
public class Test {
static Random randomGenerator = new Random();
static String operators = "+-*/()";
static int opeatorStringLength = operators.length();
public static char getRandomOperator() {
return operators.charAt(randomGenerator.nextInt(opeatorStringLength));
}
public static int getRandomNumber() {
return randomGenerator.nextInt(100);
}
public static String appendToEquation(String equation, String value1, String value2) {
String temp = equation;
temp += value1;
temp += value2;
return temp;
}
public static String createEquation(int numOfOperators) {
String equation = "";
char operator;
int operand;
int openParenCounter = 0;
for (int i = 0; i < numOfOperators; i++) {
operator = getRandomOperator();
operand = getRandomNumber();
if (operator == '(') {
openParenCounter++;
equation = appendToEquation(equation, Character.toString(operator), Integer.toString(operand));
} else if (operator == ')') {
if (openParenCounter == 0) { //Can't start off with a close parenthesis
openParenCounter++;
equation = appendToEquation(equation, "(", Integer.toString(operand));
} else {
openParenCounter--;
equation = appendToEquation(equation, Integer.toString(operand), Character.toString(operator));
}
} else {
equation = appendToEquation(equation, Integer.toString(operand), Character.toString(operator));
}
}
equation += getRandomNumber();
while (openParenCounter > 0) {
equation += ")";
openParenCounter--;
}
return equation;
}
public static void main(String[] args) {
String equation;
equation = createEquation(7); //The argument passed is the number of operators to use
System.out.println(equation);
}
}
How can i read equations from txt file and get these equations coefficients for ex. 3.2x-5.6y=10 is in txt file and i need 3.2 ,-5.6 and 10 for making graph gui program.
I tried bufferedreader but i cant get coefficients.
BufferedReader reader = null;
reader = new BufferedReader(new FileReader("input.txt"));
String line = reader.readLine();
Here is the solution.
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
/*
* Constructor just for test
*/
Test()
{
Equation equation = getMembers("-3.2x - 5.6y + 34 = -10");
System.out.print("Left members: ");
for(EquationMember m : equation.leftMembers)
System.out.print(m + " ");
System.out.print("\nRight members: ");
for(EquationMember m : equation.rightMembers)
System.out.print(m + " ");
}
/*
* Main method
*/
public static void main(String args[])
{
new Test();
}
/*
* Transforms a strings representation of an equation into an Equation class
*/
Equation getMembers(String equationString)
{
Equation equation = new Equation();
String eq = equationString.replace(" ", "");
char[] charArray = eq.toCharArray();
boolean isLeft = true;
String lastMember = "";
for(int i = 0; i < charArray.length; i++)
{
if(charArray[i] == '-' || charArray[i] == '+' || charArray[i] == '=')
{
if(lastMember.length() > 0)
{
EquationMember m = new EquationMember();
m.constant = Float.parseFloat(match("([-+]?[\\d\\.]+)[A-Za-z]?", lastMember, 1));
m.variable = match("[\\d\\.]+([A-Za-z]?)", lastMember, 1);
if(isLeft)
equation.leftMembers.add(m);
else
equation.rightMembers.add(m);
}
lastMember = charArray[i] == '=' ? "" : String.valueOf(charArray[i]);
}
else
{
lastMember += charArray[i];
}
if(charArray[i] == '=')
{
isLeft = false;
}
}
EquationMember m = new EquationMember();
m.constant = Float.parseFloat(match("([-+]?[\\d\\.]+)[A-Za-z]?", lastMember, 1));
m.variable = match("[\\d\\.]+([A-Za-z]?)", lastMember, 1);
equation.rightMembers.add(m);
return equation;
}
/*
* Performs a regex match
*/
String match(String regexp, String text, int group)
{
Pattern p1 = Pattern.compile(regexp);
Matcher m1 = p1.matcher(text);
if(m1.find())
return m1.group(group);
else
return null;
}
/*
* Class that represents a single member inside an equation
*/
class EquationMember
{
float constant;
String variable;
public String toString()
{
return constant + "" + variable;
}
}
/*
* Class that represents an entire equation
*/
class Equation
{
ArrayList<EquationMember> leftMembers;
ArrayList<EquationMember> rightMembers;
Equation()
{
leftMembers = new ArrayList<EquationMember>();
rightMembers = new ArrayList<EquationMember>();
}
}
}
Use Scanner object. You can use it to parse a line with RegExp or any other tools you want.
You mentioned split, so why not split the string on anything that's not a number?
final String s = "3.2x-5.6y=10";
String[] result = s.split("([^\\d\\.\\+\\-])+");
System.out.println(Arrays.toString(result));
// [3.2, -5.6, 10]
That regex isn't optimal for the general case of numbers (consider 123,456 or invalid input +24-.2), but that can be fixed depending on the requirements.
What this doesn't do is match the variable to the coefficent, but you stated that you only need the values.
I have the following problem.
The recursive method public static String doSomeMagic("Test") should return:
TTeesstt
TTeess
TTee
TT
I've implemented this behaviour already like this:
public static String rowFunction(String s) {
String toReturn = new String();
if (!s.isEmpty()) {
toReturn = String.valueOf(s.charAt(0));
toReturn += toReturn + rowFunction(s.substring(1));
}
return toReturn;
}
public static String doSomeMagic(String s) {
String toReturn = new String();
if (!s.isEmpty()) {
toReturn = rowFunction(s) + "\n" + doSomeMagic(s.substring(0, s.length() - 1));
}
return toReturn;
}
How can one achieve this with just one function? Any ideas?
I noticed you wanted to do this without a loop and in one function call. You can probably clean this up a lot more. Here it is:
public static String doSomeMagic(String s) {
if (!s.isEmpty()) {
StringBuffer sb = new StringBuffer();
return sb.append(s.replaceAll("(\\S)", "$1$1"))
.append("\n")
.append(doSomeMagic( s.replaceAll(".$", "") )
.toString();
}
return "";
}
To do it in one function, just iterate over the string rather than calling another recursive function.
public static String doSomeMagic(String s) {
String doubled = new String();
if (s.length() == 0) return s;
for(int i=0;i<s.length();i++)
doubled += s.substring(i,i+1) + s.substring(i,i+1)
return doubled + "\n" + doSomeMagic(s.substring(0, s.length()-1));
}
Quick solution could be like
testMethod(string ip){
if(ip.length()==1){
ip=ip.toUppercase();
}
For(int i=0;i<ip.length()-1;i++){
System.out.print(ip.charAt(i)+""+ip.charAt(i));
}
if(ip.length()>1){
System. out. println();
testMethod(ip.substring(1));
}
}
Haven't tested it... But should work fairly
When converting code from C++ to Java, what is an easy way to convert the std::string methods like find_last_of(), find_last_not_of, etc?
These C++ methods find an index of any of a set of characters.
Java's String class provides indexOf() and lastIndexOf(), but these find an index of a character or a string, not any of a set of characters.
For example, the code below finds the last character that is not ASCII whitespace.
size_t pos = myString.find_last_not_of( " \t\n\r" );
One option is to use Guava's CharMatcher class.
Here are tested conversions for each of the single-argument find_*_of() methods.
public int findFirstOf( String sequence, String str ) {
return CharMatcher.anyOf( str ).indexIn( sequence );
}
public int findFirstNotOf( String sequence, String str ) {
return CharMatcher.anyOf( str ).negate().indexIn( sequence );
}
public int findLastOf( String sequence, String str ) {
return CharMatcher.anyOf( str ).lastIndexIn( sequence );
}
public int findLastNotOf( String sequence, String str ) {
return CharMatcher.anyOf( str ).negate().lastIndexIn( sequence );
}
Other answers welcomed. [I couldn't find anything for find_last_not_of() in Java when searching on stackoverflow and elsewhere. And I missed CharMatcher the first time I searched through Guava for corresponding functionality. I'd like to document this easy conversion for future use.]
If you like regex, you can give the below equivalents a shot. This might not be the most efficient method, but certainly worth considering, if you don't want to use any 3rd party library (Given that, there are no equivalent methods in String class in Java).
P.S: - If you are comfortable with 3rd party library, then I wouldn't suggest using regex for this task, as this might soon become difficult to extend as per requirement.
So, this is just another option :
public int findFirstOf( String sequence, String str ) {
String regex = "^[^" + Pattern.quote(str) + "]*";
int index = sequence.length() - sequence.replaceAll(regex, "").length();
return index == sequence.length() ? -1 : index;
}
public int findFirstNotOf( String sequence, String str ) {
String regex = "^[" + Pattern.quote(str) + "]*";
int index = sequence.length() - sequence.replaceAll(regex, "").length();
return index == sequence.length() ? -1 : index;
}
public int findLastOf( String sequence, String str ) {
String regex = "[^" + Pattern.quote(str) + "]*$";
return sequence.replaceAll(regex, "").length() - 1;
}
public int findLastNotOf( String sequence, String str ) {
String regex = "[" + Pattern.quote(str) + "]*$";
return sequence.replaceAll(regex, "").length() - 1;
}
I haven't tested above methods. You can do the test, and compare the results with the corresponding method you have got, and see if this works. Please get back, if this doesn't work.
As far as 3rd party library is concerned, you also have Apache Commons, StringUtils class, with following methods:
StringUtils#indexOfAny()
StringUtils#indexOfAnyBut()
StringUtils#lastIndexOfAny()
static int findFirstNotOf(String searchIn, String searchFor, int searchFrom) {
boolean found;
char c;
int i;
for (i = searchFrom; i < searchIn.length(); i++) {
found = true;
c = searchIn.charAt(i);
System.out.printf("s='%s', idx=%d\n",c,searchFor.indexOf(c));
if (searchFor.indexOf(c) == -1) {
found = false;
}
if (!found) {
return i;
}
}
return i;
}
static int findLastNotOf(String searchIn, String searchFor, int searchFrom) {
boolean found;
char c;
int i;
for ( i = searchFrom; i>=0; i--) {
found = true;
c = searchIn.charAt(i);
System.out.printf("s='%s', idx=%d\n",c,searchFor.indexOf(c));
if (searchFor.indexOf(c) == -1)
found = false;
if (!found) return i;
}
return i;
}
public static void main(String[] args){
String str = "look for non-alphabetic characters...";
int found = findFirstNotOf(str,"abcdefghijklmnopqrstuvwxyz ",0);
if (found!=str.length()) {
System.out.print("The first non-alphabetic character is " + str.charAt(found));
System.out.print(" at position " + found + '\n');
}
found = findLastNotOf(str,"abcdefghijklmnopqrstuvwxyz ",str.length()-1);
if (found>=0) {
System.out.print("The last non-alphabetic character is " + str.charAt(found));
System.out.print(" at position " + found + '\n');
}
str = "Please, erase trailing white-spaces \n";
String whitespaces = " \t\f\n\r";
found = findLastNotOf(str,whitespaces,str.length()-1);
if (found!=str.length()-1)
str = str.substring(0,found+1);
else
str = ""; // str is all whitespace
System.out.printf('['+ str +"]\n");
}
I need to produce fixed length string to generate a character position based file. The missing characters must be filled with space character.
As an example, the field CITY has a fixed length of 15 characters. For the inputs "Chicago" and "Rio de Janeiro" the outputs are
" Chicago"
" Rio de Janeiro".
Since Java 1.5 we can use the method java.lang.String.format(String, Object...) and use printf like format.
The format string "%1$15s" do the job. Where 1$ indicates the argument index, s indicates that the argument is a String and 15 represents the minimal width of the String.
Putting it all together: "%1$15s".
For a general method we have:
public static String fixedLengthString(String string, int length) {
return String.format("%1$"+length+ "s", string);
}
Maybe someone can suggest another format string to fill the empty spaces with an specific character?
Utilize String.format's padding with spaces and replace them with the desired char.
String toPad = "Apple";
String padded = String.format("%8s", toPad).replace(' ', '0');
System.out.println(padded);
Prints 000Apple.
Update more performant version (since it does not rely on String.format), that has no problem with spaces (thx to Rafael Borja for the hint).
int width = 10;
char fill = '0';
String toPad = "New York";
String padded = new String(new char[width - toPad.length()]).replace('\0', fill) + toPad;
System.out.println(padded);
Prints 00New York.
But a check needs to be added to prevent the attempt of creating a char array with negative length.
This code will have exactly the given amount of characters; filled with spaces or truncated on the right side:
private String leftpad(String text, int length) {
return String.format("%" + length + "." + length + "s", text);
}
private String rightpad(String text, int length) {
return String.format("%-" + length + "." + length + "s", text);
}
For right pad you need String.format("%0$-15s", str)
i.e. - sign will "right" pad and no - sign will "left" pad
See my example:
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("================================");
for(int i=0;i<3;i++)
{
String s1=sc.nextLine();
Scanner line = new Scanner( s1);
line=line.useDelimiter(" ");
String language = line.next();
int mark = line.nextInt();;
System.out.printf("%s%03d\n",String.format("%0$-15s", language),mark);
}
System.out.println("================================");
}
}
The input must be a string and a number
example input : Google 1
String.format("%15s",s) // pads left
String.format("%-15s",s) // pads right
Great summary here
import org.apache.commons.lang3.StringUtils;
String stringToPad = "10";
int maxPadLength = 10;
String paddingCharacter = " ";
StringUtils.leftPad(stringToPad, maxPadLength, paddingCharacter)
Way better than Guava imo. Never seen a single enterprise Java project that uses Guava but Apache String Utils is incredibly common.
You can also write a simple method like below
public static String padString(String str, int leng) {
for (int i = str.length(); i <= leng; i++)
str += " ";
return str;
}
The Guava Library has Strings.padStart that does exactly what you want, along with many other useful utilities.
Here's a neat trick:
// E.g pad("sss","00000000"); should deliver "00000sss".
public static String pad(String string, String pad) {
/*
* Add the pad to the left of string then take as many characters from the right
* that is the same length as the pad.
* This would normally mean starting my substring at
* pad.length() + string.length() - pad.length() but obviously the pad.length()'s
* cancel.
*
* 00000000sss
* ^ ----- Cut before this character - pos = 8 + 3 - 8 = 3
*/
return (pad + string).substring(string.length());
}
public static void main(String[] args) throws InterruptedException {
try {
System.out.println("Pad 'Hello' with ' ' produces: '"+pad("Hello"," ")+"'");
// Prints: Pad 'Hello' with ' ' produces: ' Hello'
} catch (Exception e) {
e.printStackTrace();
}
}
Here is the code with tests cases ;) :
#Test
public void testNullStringShouldReturnStringWithSpaces() throws Exception {
String fixedString = writeAtFixedLength(null, 5);
assertEquals(fixedString, " ");
}
#Test
public void testEmptyStringReturnStringWithSpaces() throws Exception {
String fixedString = writeAtFixedLength("", 5);
assertEquals(fixedString, " ");
}
#Test
public void testShortString_ReturnSameStringPlusSpaces() throws Exception {
String fixedString = writeAtFixedLength("aa", 5);
assertEquals(fixedString, "aa ");
}
#Test
public void testLongStringShouldBeCut() throws Exception {
String fixedString = writeAtFixedLength("aaaaaaaaaa", 5);
assertEquals(fixedString, "aaaaa");
}
private String writeAtFixedLength(String pString, int lenght) {
if (pString != null && !pString.isEmpty()){
return getStringAtFixedLength(pString, lenght);
}else{
return completeWithWhiteSpaces("", lenght);
}
}
private String getStringAtFixedLength(String pString, int lenght) {
if(lenght < pString.length()){
return pString.substring(0, lenght);
}else{
return completeWithWhiteSpaces(pString, lenght - pString.length());
}
}
private String completeWithWhiteSpaces(String pString, int lenght) {
for (int i=0; i<lenght; i++)
pString += " ";
return pString;
}
I like TDD ;)
Apache common lang3 dependency's StringUtils exists to solve Left/Right Padding
Apache.common.lang3 provides the StringUtils class where you can use the following method to left padding with your preferred character.
StringUtils.leftPad(final String str, final int size, final char padChar);
Here, This is a static method and the parameters
str - string needs to be pad (can be null)
size - the size to pad to
padChar the character to pad with
We have additional methods in that StringUtils class as well.
rightPad
repeat
different join methods
I just add the Gradle dependency here for your reference.
implementation 'org.apache.commons:commons-lang3:3.12.0'
https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.12.0
Please see all the utils methods of this class.
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html
GUAVA Library Dependency
This is from jricher answer. The Guava Library has Strings.padStart that does exactly what you want, along with many other useful utilities.
This code works great.
String ItemNameSpacing = new String(new char[10 - masterPojos.get(i).getName().length()]).replace('\0', ' ');
printData += masterPojos.get(i).getName()+ "" + ItemNameSpacing + ": " + masterPojos.get(i).getItemQty() +" "+ masterPojos.get(i).getItemMeasure() + "\n";
Happy Coding!!
public static String padString(String word, int length) {
String newWord = word;
for(int count = word.length(); count < length; count++) {
newWord = " " + newWord;
}
return newWord;
}
This simple function works for me:
public static String leftPad(String string, int length, String pad) {
return pad.repeat(length - string.length()) + string;
}
Invocation:
String s = leftPad(myString, 10, "0");
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
int s;
String s1 = sc.next();
int x = sc.nextInt();
System.out.printf("%-15s%03d\n", s1, x);
// %-15s -->pads right,%15s-->pads left
}
}
}
Use printf() to simply format output without using any library.