getting a multi decimal number from a string [duplicate] - java

This question already has answers here:
Comparing version number strings (major, minor, revision, beta)
(3 answers)
Closed 7 years ago.
For one of my projects i would like to get a version from a string which has multiple decimals, is it possible to convert it into a multi decimal point double or is it not possible. I would like to use this to see if it is more than the previous one, which would also have multiple decimals.
What I am using at the moment is
if (!vers.equalsIgnoreCase(plugin.getDescription().getVersion())) { // Do stuff
But I would like to make it so I can do
if (vers > plugin.getDescription().getVersion()) { // do stuff
vers is equal to 1.0.1, and the plugin.getDescription().getVersion() is equal to 1.0.2
thanks!

You could implement this way, if you assume all the portions are numbers.
public static int compareVersions(String vers1, String vers2) {
String[] v1 = vers1.split("\\.");
String[] v2 = vers2.split("\\.");
for (int i = 0; i < v1.length && i < v2.length; i++) {
int i1 = Integer.parseInt(v1[i]);
int i2 = Integer.parseInt(v2[i]);
int cmp = Integer.compare(i1, i2);
if (cmp != 0)
return cmp;
}
return Integer.compare(v1.length, v2.length);
}
and
System.out.println(compareVersions("1.0.1", "1.0.2"));
System.out.println(compareVersions("1.0.1", "1.0"));
System.out.println(compareVersions("1.0.2", "1.0.10"));
prints
-1
1
-1
A more complex version supports letters inside versions
public static int compareVersions(String vers1, String vers2) {
String[] v1 = vers1.split("\\.");
String[] v2 = vers2.split("\\.");
for (int i = 0; i < v1.length && i < v2.length; i++) {
String [] w1 = v1[i].split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
String [] w2 = v2[i].split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
for(int j=0;j<w1.length&&j<w2.length;j++) {
try {
int i1 = Integer.parseInt(w1[j]);
int i2 = 0;
try {
i2 = Integer.parseInt(w2[j]);
} catch (NumberFormatException e) {
return -1;
}
int cmp = Integer.compare(i1, i2);
if (cmp != 0)
return cmp;
} catch (NumberFormatException e) {
try {
Integer.parseInt(w2[j]);
return +1;
} catch (NumberFormatException e1) {
int cmp = w1[j].compareTo(w2[j]);
if (cmp != 0)
return cmp;
}
}
}
int cmp = Integer.compare(w1.length, w2.length);
if (cmp != 0)
return cmp;
}
return Integer.compare(v1.length, v2.length);
}
and
System.out.println(compareVersions("1.0.2", "1.0.2a"));
System.out.println(compareVersions("1.0.2b", "1.0.2a"));
System.out.println(compareVersions("1.8.0_66", "1.8.0_65"));
System.out.println(compareVersions("1.7.0_79", "1.8.0_65"));
prints
-1
1
1
-1

It seems that you would like to compare versions. Or to take decisions based on some string represented version. If the plugin.getDescription().getVersion() is a String, then you should be able to use a simple String comparison to establish the order between versions. Something like this should work:
String pluginVersion=plugin.getDescription().getVersion();
if (ensureValidVersion(pluginVersion)
&& compareVersions(vers,pluginVersion)>0) {
// do staff is vers is greater then plugin version
}
ensureValidVersion method will validate if you have a valid version number representation. And compareVersions will do a comparison for each version subcomponent.

Assuming you have a version number of the following form: x.y.z
You can use a similiar approach as suggested by Viacheslav Vedenin:
String versionNumber = "1.3.45";
String[] singleParts = versionNumbers.split(".");
int[] versionParts = new int[singleParts.length];
for(int i=0; i<singleParts.length; i++) {
versionParts[i] = Integer.parseInt(singleParts[i]);
}
Now you have an array of the single parts of your version number. To compare it to a previous one you could do as follow:
public static boolean isGreater(int[] firstVersion, int[] secondVersion) {
if(secondVersion.length > firstVersion.length) {
return false;
}else {
if(firstVersion.length > secondVersion.length) {
return true;
}else {
for(int k=0; k< firstVersion.length; k++) {
int v1 = firstVersion[k];
int v2 = secondVersion[k];
if(v1 < v2) {
return true;
}
}
return false;
}
}
}

If you want to compare versions using the equality/inequality operators (==, <, >, <=, and >=), you have two options.
Use a language like C++ that supports operator overloading
Set a limit on the length for each string in major.minor.build and convert each version to an integer before comparing them. For example, if the limit on each of them is 3 (i.e. the longest version you can have is abc.def.ghi), then you can just use build + minor * 10^3 + major * 10^6.
Alternatively, you can just implement Comparable<Version> and have a nice OOP solution.
public class Example {
static class Version implements Comparable<Version> {
private int major;
private int minor;
private int build;
public Version(String s) {
final String[] split = s.split("\\.");
major = Integer.parseInt(split[0]);
minor = Integer.parseInt(split[1]);
build = Integer.parseInt(split[2]);
}
public int getMajor() {
return major;
}
public int getMinor() {
return minor;
}
public int getBuild() {
return build;
}
#Override
public int compareTo(Version v) {
if (getMajor() < v.getMajor()) {
return -1;
} else if (getMajor() > v.getMajor()) {
return 1;
} else {
if (getMinor() < v.getMinor()) {
return -1;
} else if (getMinor() > v.getMinor()) {
return 1;
} else {
if (getBuild() < v.getBuild()) {
return -1;
} else if (getBuild() > v.getBuild()) {
return 1;
} else {
return 0;
}
}
}
}
}
public static void main(String[] args) {
String s1 = "1.0.1";
String s2 = "1.0.2";
compare(s1, s2);
compare(s1, s1);
compare(s2, s2);
compare(s2, s1);
}
private static void compare(String s1, String s2) {
Version v1 = new Version(s1);
Version v2 = new Version(s2);
final int compareTo = v1.compareTo(v2);
if (compareTo == -1) {
System.out.println(s1 + " was released before " + s2);
} else if (compareTo == 0) {
System.out.println(s1 + " is the same as " + s2);
} else {
System.out.println(s1 + " was released after " + s2);
}
}
}
Output:
1.0.1 was released before 1.0.2
1.0.1 is the same as 1.0.1
1.0.2 is the same as 1.0.2
1.0.2 was released after 1.0.1

String[] numbers = version.split(".");
String[] numbers2 = version2.split(".");
int index = numbers.length-1;
while(numbers[index] != "."){
index--;
}
String lastnumber = version.substring(index+1, numbers.length];
index = numbers2.length-1;
while(numbers2[index] != "."){
index--;
}
String lastnumber2 = version.substring(index+1, numbers2.length];
if(lastnumber > lastnumber2){
//later version
}else{
//use the same thing to check the other numbers
}

Related

How to convert string in a txt document to code? [duplicate]

I have a string like the following:
String str = "4*5";
Now I have to get the result of 20 by using the string.
I know in some other languages the eval() function will do this.
How can I do this in Java?
You can use the ScriptEngine class and evaluate it as a Javascript string.
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
Object result = engine.eval("4*5");
There may be a better way, but this one works.
There is no standard Java class or method that will do what you want. Your options include:
Select and use some third-party expression evaluation library. For example JEL or any of the half dozen libraries listed here.
Wrap the expression in the Java source code for a class with an eval method, send that to the Java compiler, and then load the resulting compiled class.
Use some scripting language that can be called from Java as an expression evaluator. Possibilities include Javascript1, BeanShell, and so on. A JSR 223 compliant scripting language implementation can be called via the Scripting API.
Write your own expression evaluator from scratch.
The first approach is probably simplest. The second and third approaches are a potential security risk if you get the expression to be evaluated from an untrusted user. (Think code injection.)
1 - Javascript in Java SE is a moving target. From Java 6, a version of Mozilla's Rhino Javascript implementation was bundled with Java SE. The in Java 8, it was superseded by Nashorn. In Java 11, Nashorn was deprecated, and finally dropped from the core codebase. As of 2021, both Rhino and Nashorn are being maintained as separate (non-Oracle) products, and Oracle's GraalVM has its own Javascript implementation.
There are very few real use cases in which being able to evaluate a String as a fragment of Java code is necessary or desirable. That is, asking how to do this is really an XY problem: you actually have a different problem, which can be solved a different way.
First ask yourself, where did this String that you wish to evaluate come from? Did another part of your program generate it, or was it input provided by the user?
Another part of my program generated it: so, you want one part of your program to decide the kind of operation to perform, but not perform the operation, and a second part that performs the chosen operation. Instead of generating and then evaluating a String, use the Strategy, Command or Builder design pattern, as appropriate for your particular case.
It is user input: the user could input anything, including commands that, when executed, could cause your program to misbehave, crash, expose information that should be secret, damage persistent information (such as the content of a database), and other such nastiness. The only way to prevent that would be to parse the String yourself, check it was not malicious, and then evaluate it. But parsing it yourself is much of the work that the requested evalfunction would do, so you have saved yourself nothing. Worse still, checking that arbitrary Java was not malicious is impossible, because checking that is the halting problem.
It is user input, but the syntax and semantics of permitted text to evaluate is greatly restricted: No general purpose facility can easily implement a general purpose parser and evaluator for whatever restricted syntax and semantics you have chosen. What you need to do is implement a parser and evaluator for your chosen syntax and semantics. If the task is simple, you could write a simple recursive-descent or finite-state-machine parser by hand. If the task is difficult, you could use a compiler-compiler (such as ANTLR) to do some of the work for you.
I just want to implement a desktop calculator!: A homework assignment, eh? If you could implement the evaluation of the input expression using a provided eval function, it would not be much of a homework assignment, would it? Your program would be three lines long. Your instructor probably expects you to write the code for a simple arithmetic parser/evaluator. There is well known algorithm, shunting-yard, which you might find useful.
With Java 9, we get access to jshell, so one can write something like this:
import jdk.jshell.JShell;
import java.lang.StringBuilder;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Eval {
public static void main(String[] args) throws IOException {
try(JShell js = JShell.create(); BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
js.onSnippetEvent(snip -> {
if (snip.status() == jdk.jshell.Snippet.Status.VALID) {
System.out.println("➜ " + snip.value());
}
});
System.out.print("> ");
for (String line = br.readLine(); line != null; line = br.readLine()) {
js.eval(js.sourceCodeAnalysis().analyzeCompletion(line).source());
System.out.print("> ");
}
}
}
}
Sample run:
> 1 + 2 / 4 * 3
➜ 1
> 32 * 121
➜ 3872
> 4 * 5
➜ 20
> 121 * 51
➜ 6171
>
Slightly op, but that's what Java currently has to offer
I could advise you to use Exp4j. It is easy to understand as you can see from the following example code:
Expression e = new ExpressionBuilder("3 * sin(y) - 2 / (x - 2)")
.variables("x", "y")
.build()
.setVariable("x", 2.3)
.setVariable("y", 3.14);
double result = e.evaluate();
No, you can not have a generic "eval" in Java (or any compiled language). Unless you're willing to write a Java compiler AND a JVM to be executed inside of your Java program.
Yes, you can have some library to evaluate numeric algebraic expressions like the one above - see this thread for discussion.
As previous answers, there is no standard API in Java for this.
You can add groovy jar files to your path and groovy.util.Eval.me("4*5") gets your job done.
A fun way to solve your problem could be coding an eval() function on your own!
I've done it for you!
You can use FunctionSolver library simply by typing FunctionSolver.solveByX(function,value) inside your code. The function attribute is a String which represents the function you want to solve, the value attribute is the value of the independent variable
of your function (which MUST be x).
If you want to solve a function which contains more than one independent variable, you can use FunctionSolver.solve(function,values) where the values attribute is an HashMap(String,Double) which contains all your independent attributes (as Strings) and their respective values (as Doubles).
Another piece of information: I've coded a simple version of FunctionSolver, so its supports only Math methods which return a double value and which accepts one or two double values as fields (just use FunctionSolver.usableMathMethods() if you're curious) (These methods are: bs, sin, cos, tan, atan2, sqrt, log, log10, pow, exp, min, max, copySign, signum, IEEEremainder, acos, asin, atan, cbrt, ceil, cosh, expm1, floor, hypot, log1p, nextAfter, nextDown, nextUp, random, rint, sinh, tanh, toDegrees, toRadians, ulp). Also, that library supports the following operators: * / + - ^ (even if java normally does not support the ^ operator).
One last thing: while creating this library I had to use reflections to call Math methods. I think it's really cool, just have a look at this if you are interested in!
That's all, here it is the code (and the library):
package core;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
public abstract class FunctionSolver {
public static double solveNumericExpression (String expression) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
return solve(expression, new HashMap<>());
}
public static double solveByX (String function, double value) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
HashMap<String, Double> values = new HashMap<>();
values.put("x", value);
return solveComplexFunction(function, function, values);
}
public static double solve (String function, HashMap<String,Double> values) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
return solveComplexFunction(function, function, values);
}
private static double solveComplexFunction (String function, String motherFunction, HashMap<String, Double> values) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
int position = 0;
while(position < function.length()) {
if (alphabetic.contains(""+function.charAt(position))) {
if (position == 0 || !alphabetic.contains(""+function.charAt(position-1))) {
int endIndex = -1;
for (int j = position ; j < function.length()-1 ; j++) {
if (alphabetic.contains(""+function.charAt(j))
&& !alphabetic.contains(""+function.charAt(j+1))) {
endIndex = j;
break;
}
}
if (endIndex == -1 & alphabetic.contains(""+function.charAt(function.length()-1))) {
endIndex = function.length()-1;
}
if (endIndex != -1) {
String alphabeticElement = function.substring(position, endIndex+1);
if (Arrays.asList(usableMathMethods()).contains(alphabeticElement)) {
//Start analyzing a Math function
int closeParenthesisIndex = -1;
int openedParenthesisquantity = 0;
int commaIndex = -1;
for (int j = endIndex+1 ; j < function.length() ; j++) {
if (function.substring(j,j+1).equals("(")) {
openedParenthesisquantity++;
}else if (function.substring(j,j+1).equals(")")) {
openedParenthesisquantity--;
if (openedParenthesisquantity == 0) {
closeParenthesisIndex = j;
break;
}
}else if (function.substring(j,j+1).equals(",") & openedParenthesisquantity == 0) {
if (commaIndex == -1) {
commaIndex = j;
}else{
throw new IllegalArgumentException("The argument of math function (which is "+alphabeticElement+") has too many commas");
}
}
}
if (closeParenthesisIndex == -1) {
throw new IllegalArgumentException("The argument of a Math function (which is "+alphabeticElement+") hasn't got the closing bracket )");
}
String functionArgument = function.substring(endIndex+2,closeParenthesisIndex);
if (commaIndex != -1) {
double firstParameter = solveComplexFunction(functionArgument.substring(0,commaIndex),motherFunction,values);
double secondParameter = solveComplexFunction(functionArgument.substring(commaIndex+1),motherFunction,values);
Method mathMethod = Math.class.getDeclaredMethod(alphabeticElement, new Class<?>[] {double.class, double.class});
mathMethod.setAccessible(true);
String newKey = getNewKey(values);
values.put(newKey, (Double) mathMethod.invoke(null, firstParameter, secondParameter));
function = function.substring(0, position)+newKey
+((closeParenthesisIndex == function.length()-1)?(""):(function.substring(closeParenthesisIndex+1)));
}else {
double firstParameter = solveComplexFunction(functionArgument, motherFunction, values);
Method mathMethod = Math.class.getDeclaredMethod(alphabeticElement, new Class<?>[] {double.class});
mathMethod.setAccessible(true);
String newKey = getNewKey(values);
values.put(newKey, (Double) mathMethod.invoke(null, firstParameter));
function = function.substring(0, position)+newKey
+((closeParenthesisIndex == function.length()-1)?(""):(function.substring(closeParenthesisIndex+1)));
}
}else if (!values.containsKey(alphabeticElement)) {
throw new IllegalArgumentException("Found a group of letters ("+alphabeticElement+") which is neither a variable nor a Math function: ");
}
}
}
}
position++;
}
return solveBracketsFunction(function,motherFunction,values);
}
private static double solveBracketsFunction (String function,String motherFunction,HashMap<String, Double> values) throws IllegalArgumentException{
function = function.replace(" ", "");
String openingBrackets = "([{";
String closingBrackets = ")]}";
int parenthesisIndex = 0;
do {
int position = 0;
int openParenthesisBlockIndex = -1;
String currentOpeningBracket = openingBrackets.charAt(parenthesisIndex)+"";
String currentClosingBracket = closingBrackets.charAt(parenthesisIndex)+"";
if (contOccouranceIn(currentOpeningBracket,function) != contOccouranceIn(currentClosingBracket,function)) {
throw new IllegalArgumentException("Error: brackets are misused in the function "+function);
}
while (position < function.length()) {
if (function.substring(position,position+1).equals(currentOpeningBracket)) {
if (position != 0 && !operators.contains(function.substring(position-1,position))) {
throw new IllegalArgumentException("Error in function: there must be an operator following a "+currentClosingBracket+" breacket");
}
openParenthesisBlockIndex = position;
}else if (function.substring(position,position+1).equals(currentClosingBracket)) {
if (position != function.length()-1 && !operators.contains(function.substring(position+1,position+2))) {
throw new IllegalArgumentException("Error in function: there must be an operator before a "+currentClosingBracket+" breacket");
}
String newKey = getNewKey(values);
values.put(newKey, solveBracketsFunction(function.substring(openParenthesisBlockIndex+1,position),motherFunction, values));
function = function.substring(0,openParenthesisBlockIndex)+newKey
+((position == function.length()-1)?(""):(function.substring(position+1)));
position = -1;
}
position++;
}
parenthesisIndex++;
}while (parenthesisIndex < openingBrackets.length());
return solveBasicFunction(function,motherFunction, values);
}
private static double solveBasicFunction (String function, String motherFunction, HashMap<String, Double> values) throws IllegalArgumentException{
if (!firstContainsOnlySecond(function, alphanumeric+operators)) {
throw new IllegalArgumentException("The function "+function+" is not a basic function");
}
if (function.contains("**") |
function.contains("//") |
function.contains("--") |
function.contains("+*") |
function.contains("+/") |
function.contains("-*") |
function.contains("-/")) {
/*
* ( -+ , +- , *- , *+ , /- , /+ )> Those values are admitted
*/
throw new IllegalArgumentException("Operators are misused in the function");
}
function = function.replace(" ", "");
int position;
int operatorIndex = 0;
String currentOperator;
do {
currentOperator = operators.substring(operatorIndex,operatorIndex+1);
if (currentOperator.equals("*")) {
currentOperator+="/";
operatorIndex++;
}else if (currentOperator.equals("+")) {
currentOperator+="-";
operatorIndex++;
}
operatorIndex++;
position = 0;
while (position < function.length()) {
if ((position == 0 && !(""+function.charAt(position)).equals("-") && !(""+function.charAt(position)).equals("+") && operators.contains(""+function.charAt(position))) ||
(position == function.length()-1 && operators.contains(""+function.charAt(position)))){
throw new IllegalArgumentException("Operators are misused in the function");
}
if (currentOperator.contains(function.substring(position, position+1)) & position != 0) {
int firstTermBeginIndex = position;
while (firstTermBeginIndex > 0) {
if ((alphanumeric.contains(""+function.charAt(firstTermBeginIndex))) & (operators.contains(""+function.charAt(firstTermBeginIndex-1)))){
break;
}
firstTermBeginIndex--;
}
if (firstTermBeginIndex != 0 && (function.charAt(firstTermBeginIndex-1) == '-' | function.charAt(firstTermBeginIndex-1) == '+')) {
if (firstTermBeginIndex == 1) {
firstTermBeginIndex--;
}else if (operators.contains(""+(function.charAt(firstTermBeginIndex-2)))){
firstTermBeginIndex--;
}
}
String firstTerm = function.substring(firstTermBeginIndex,position);
int secondTermLastIndex = position;
while (secondTermLastIndex < function.length()-1) {
if ((alphanumeric.contains(""+function.charAt(secondTermLastIndex))) & (operators.contains(""+function.charAt(secondTermLastIndex+1)))) {
break;
}
secondTermLastIndex++;
}
String secondTerm = function.substring(position+1,secondTermLastIndex+1);
double result;
switch (function.substring(position,position+1)) {
case "*": result = solveSingleValue(firstTerm,values)*solveSingleValue(secondTerm,values); break;
case "/": result = solveSingleValue(firstTerm,values)/solveSingleValue(secondTerm,values); break;
case "+": result = solveSingleValue(firstTerm,values)+solveSingleValue(secondTerm,values); break;
case "-": result = solveSingleValue(firstTerm,values)-solveSingleValue(secondTerm,values); break;
case "^": result = Math.pow(solveSingleValue(firstTerm,values),solveSingleValue(secondTerm,values)); break;
default: throw new IllegalArgumentException("Unknown operator: "+currentOperator);
}
String newAttribute = getNewKey(values);
values.put(newAttribute, result);
function = function.substring(0,firstTermBeginIndex)+newAttribute+function.substring(secondTermLastIndex+1,function.length());
deleteValueIfPossible(firstTerm, values, motherFunction);
deleteValueIfPossible(secondTerm, values, motherFunction);
position = -1;
}
position++;
}
}while (operatorIndex < operators.length());
return solveSingleValue(function, values);
}
private static double solveSingleValue (String singleValue, HashMap<String, Double> values) throws IllegalArgumentException{
if (isDouble(singleValue)) {
return Double.parseDouble(singleValue);
}else if (firstContainsOnlySecond(singleValue, alphabetic)){
return getValueFromVariable(singleValue, values);
}else if (firstContainsOnlySecond(singleValue, alphanumeric+"-+")) {
String[] composition = splitByLettersAndNumbers(singleValue);
if (composition.length != 2) {
throw new IllegalArgumentException("Wrong expression: "+singleValue);
}else {
if (composition[0].equals("-")) {
composition[0] = "-1";
}else if (composition[1].equals("-")) {
composition[1] = "-1";
}else if (composition[0].equals("+")) {
composition[0] = "+1";
}else if (composition[1].equals("+")) {
composition[1] = "+1";
}
if (isDouble(composition[0])) {
return Double.parseDouble(composition[0])*getValueFromVariable(composition[1], values);
}else if (isDouble(composition[1])){
return Double.parseDouble(composition[1])*getValueFromVariable(composition[0], values);
}else {
throw new IllegalArgumentException("Wrong expression: "+singleValue);
}
}
}else {
throw new IllegalArgumentException("Wrong expression: "+singleValue);
}
}
private static double getValueFromVariable (String variable, HashMap<String, Double> values) throws IllegalArgumentException{
Double val = values.get(variable);
if (val == null) {
throw new IllegalArgumentException("Unknown variable: "+variable);
}else {
return val;
}
}
/*
* FunctionSolver help tools:
*
*/
private static final String alphabetic = "abcdefghilmnopqrstuvzwykxy";
private static final String numeric = "0123456789.";
private static final String alphanumeric = alphabetic+numeric;
private static final String operators = "^*/+-"; //--> Operators order in important!
private static boolean firstContainsOnlySecond(String firstString, String secondString) {
for (int j = 0 ; j < firstString.length() ; j++) {
if (!secondString.contains(firstString.substring(j, j+1))) {
return false;
}
}
return true;
}
private static String getNewKey (HashMap<String, Double> hashMap) {
String alpha = "abcdefghilmnopqrstuvzyjkx";
for (int j = 0 ; j < alpha.length() ; j++) {
String k = alpha.substring(j,j+1);
if (!hashMap.containsKey(k) & !Arrays.asList(usableMathMethods()).contains(k)) {
return k;
}
}
for (int j = 0 ; j < alpha.length() ; j++) {
for (int i = 0 ; i < alpha.length() ; i++) {
String k = alpha.substring(j,j+1)+alpha.substring(i,i+1);
if (!hashMap.containsKey(k) & !Arrays.asList(usableMathMethods()).contains(k)) {
return k;
}
}
}
throw new NullPointerException();
}
public static String[] usableMathMethods () {
/*
* Only methods that:
* return a double type
* present one or two parameters (which are double type)
*/
Method[] mathMethods = Math.class.getDeclaredMethods();
ArrayList<String> usableMethodsNames = new ArrayList<>();
for (Method method : mathMethods) {
boolean usable = true;
int argumentsCounter = 0;
Class<?>[] methodParametersTypes = method.getParameterTypes();
for (Class<?> parameter : methodParametersTypes) {
if (!parameter.getSimpleName().equalsIgnoreCase("double")) {
usable = false;
break;
}else {
argumentsCounter++;
}
}
if (!method.getReturnType().getSimpleName().toLowerCase().equals("double")) {
usable = false;
}
if (usable & argumentsCounter<=2) {
usableMethodsNames.add(method.getName());
}
}
return usableMethodsNames.toArray(new String[usableMethodsNames.size()]);
}
private static boolean isDouble (String number) {
try {
Double.parseDouble(number);
return true;
}catch (Exception ex) {
return false;
}
}
private static String[] splitByLettersAndNumbers (String val) {
if (!firstContainsOnlySecond(val, alphanumeric+"+-")) {
throw new IllegalArgumentException("Wrong passed value: <<"+val+">>");
}
ArrayList<String> response = new ArrayList<>();
String searchingFor;
int lastIndex = 0;
if (firstContainsOnlySecond(""+val.charAt(0), numeric+"+-")) {
searchingFor = alphabetic;
}else {
searchingFor = numeric+"+-";
}
for (int j = 0 ; j < val.length() ; j++) {
if (searchingFor.contains(val.charAt(j)+"")) {
response.add(val.substring(lastIndex, j));
lastIndex = j;
if (searchingFor.equals(numeric+"+-")) {
searchingFor = alphabetic;
}else {
searchingFor = numeric+"+-";
}
}
}
response.add(val.substring(lastIndex,val.length()));
return response.toArray(new String[response.size()]);
}
private static void deleteValueIfPossible (String val, HashMap<String, Double> values, String function) {
if (values.get(val) != null & function != null) {
if (!function.contains(val)) {
values.remove(val);
}
}
}
private static int contOccouranceIn (String howManyOfThatString, String inThatString) {
return inThatString.length() - inThatString.replace(howManyOfThatString, "").length();
}
}
Writing your own library is not that hard as u might thing. Here is link for Shunting-yard algorithm with step by step algorithm explenation. Although, you will have to parse the input for tokens first.
There are 2 other questions wich can give you some information too:
Turn a String into a Math Expression?
What's a good library for parsing mathematical expressions in java?
As there are many answers, I'm adding my implementation on top of eval() method with some additional features like support for factorial, evaluating complex expressions etc.
package evaluation;
import java.math.BigInteger;
import java.util.EmptyStackException;
import java.util.Scanner;
import java.util.Stack;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class EvalPlus {
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("This Evaluation is based on BODMAS rule\n");
evaluate();
}
private static void evaluate() {
StringBuilder finalStr = new StringBuilder();
System.out.println("Enter an expression to evaluate:");
String expr = scanner.nextLine();
if(isProperExpression(expr)) {
expr = replaceBefore(expr);
char[] temp = expr.toCharArray();
String operators = "(+-*/%)";
for(int i = 0; i < temp.length; i++) {
if((i == 0 && temp[i] != '*') || (i == temp.length-1 && temp[i] != '*' && temp[i] != '!')) {
finalStr.append(temp[i]);
} else if((i > 0 && i < temp.length -1) || (i==temp.length-1 && temp[i] == '!')) {
if(temp[i] == '!') {
StringBuilder str = new StringBuilder();
for(int k = i-1; k >= 0; k--) {
if(Character.isDigit(temp[k])) {
str.insert(0, temp[k] );
} else {
break;
}
}
Long prev = Long.valueOf(str.toString());
BigInteger val = new BigInteger("1");
for(Long j = prev; j > 1; j--) {
val = val.multiply(BigInteger.valueOf(j));
}
finalStr.setLength(finalStr.length() - str.length());
finalStr.append("(" + val + ")");
if(temp.length > i+1) {
char next = temp[i+1];
if(operators.indexOf(next) == -1) {
finalStr.append("*");
}
}
} else {
finalStr.append(temp[i]);
}
}
}
expr = finalStr.toString();
if(expr != null && !expr.isEmpty()) {
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
try {
System.out.println("Result: " + engine.eval(expr));
evaluate();
} catch (ScriptException e) {
System.out.println(e.getMessage());
}
} else {
System.out.println("Please give an expression");
evaluate();
}
} else {
System.out.println("Not a valid expression");
evaluate();
}
}
private static String replaceBefore(String expr) {
expr = expr.replace("(", "*(");
expr = expr.replace("+*", "+").replace("-*", "-").replace("**", "*").replace("/*", "/").replace("%*", "%");
return expr;
}
private static boolean isProperExpression(String expr) {
expr = expr.replaceAll("[^()]", "");
char[] arr = expr.toCharArray();
Stack<Character> stack = new Stack<Character>();
int i =0;
while(i < arr.length) {
try {
if(arr[i] == '(') {
stack.push(arr[i]);
} else {
stack.pop();
}
} catch (EmptyStackException e) {
stack.push(arr[i]);
}
i++;
}
return stack.isEmpty();
}
}
Please find the updated gist anytime here. Also comment if any issues are there. Thanks.
There are some perfectly capable answers here. However for non-trivial script it may be desirable to retain the code in a cache, or for debugging purposes, or even to have dynamically self-updating code.
To that end, sometimes it's simpler or more robust to interact with Java via command line. Create a temporary directory, output your script and any assets, create the jar. Finally import your new code.
It's a bit beyond the scope of normal eval() use in most languages, though you could certainly implement eval by returning the result from some function in your jar.
Still, thought I'd mention this method as it does fully encapsulate everything Java can do without 3rd party tools, in case of desperation. This method allows me to turn HTML templates into objects and save them, avoiding the need to parse a template at runtime.
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
class Calculate {
public static void main(String[] args) {
String strng = "8*-2*3*-1*10/2+6-2";
String[] oparator = {"+","-","*","/"};
List<String> op1 = new ArrayList<>();
String[] x = strng.split("");
int sayac=0;
for (String i : x) {
sayac ++;
for (String c : oparator) {
if (i.equals(c)) {
try {
int j = Integer.parseInt(strng.substring(0, sayac - 1));
op1.add(strng.substring(0, sayac - 1));
op1.add(c);
strng = strng.substring(sayac);
sayac = 0;
}catch (Exception e)
{
continue;
}
}
}
}
op1.add(strng);
ListIterator<String> it = op1.listIterator();
List<List> newlist = new ArrayList<>() ;
while (it.hasNext()) {
List<String> p= new ArrayList<>();
p.add(String.valueOf(it.nextIndex()));
p.add(it.next());
newlist.add(p);
}
int sayac2=0;
String oparatorvalue = "*";
calculate(sayac2,newlist,oparatorvalue);
String oparatorvalue2 = "/";
calculate(sayac2,newlist,oparatorvalue2);
String oparatorvalue3 = "+";
calculate(sayac2,newlist,oparatorvalue3);
String oparatorvalue4 = "-";
calculate(sayac2,newlist,oparatorvalue4);
System.out.println("Result:"+newlist.get(0).get(1));
}
private static void calculate(int sayac2, List<List> newlist, String oparatorvalue) {
while (sayac2<4){
try{
for (List j : newlist) {
if (j.get(1) == oparatorvalue) {
Integer opindex = newlist.indexOf(j);
Object sayi1 = newlist.get(opindex - 1).get(1);
Object sayi2 = newlist.get(opindex + 1).get(1);
int sonuc=0;
if (oparatorvalue.equals("*")){
sonuc = Integer.parseInt(sayi1.toString()) * Integer.parseInt(sayi2.toString());
}
if (oparatorvalue.equals("/")){
sonuc = Integer.parseInt(sayi1.toString()) / Integer.parseInt(sayi2.toString());
}
if (oparatorvalue.equals("+")){
sonuc = Integer.parseInt(sayi1.toString()) + Integer.parseInt(sayi2.toString());
}
if (oparatorvalue.equals("-")){
sonuc = Integer.parseInt(sayi1.toString()) - Integer.parseInt(sayi2.toString());
}
newlist.remove(opindex - 1);
newlist.remove(opindex - 1);
newlist.remove(opindex - 1);
List<String> sonuclist = new ArrayList<>();
sonuclist.add(String.valueOf(opindex - 1));
sonuclist.add(String.valueOf(sonuc));
newlist.add(opindex - 1, sonuclist);
}}}
catch (Exception e){
continue;
}
sayac2++;}
}
}
If you do not want to import heavy scripting library, you can use SimpleExpressionEvaluator directly into your code
Usage:
Expression.eval("1+2").asString(); // returns "3.0"
Expression.eval("1+2").asInt(); // returns 3
Expression.eval("2>3").asString(); // returns "false"
Expression.eval("2>3").asBoolean(); // returns false
Expression.eval("(3>2)||((2<4)&&(2>1))").asString(); // returns "true"
With variables:
HashMap<String, Object> st = new HashMap<String, Object>();
st.put("a",1);
st.put("b",2);
st.put("c",3);
st.put("d",4);
Expression.eval("a+b", st).asInt(); // or simply asString()
Expression.eval("a>b",st).asBoolean(); // or simply asString()
Expression.eval("(c>b)||((b<d)&&(b>a))",st).asBoolean(); // or simply asString()
Expression.eval("(c>2)||((2<d)&&(b>1))",st).asBoolean(); // or simply asString()
Using ExpressionBuilder:
Expression.expressionBuilder().putSymbol("a",2).putSymbol("b",3).build("(b>a)").evaluate()
The following resolved the issue:
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String str = "4*5";
System.out.println(engine.eval(str));

Check whether a given String is palindrome or not without using any library without loop

I was asked in an interview to write code to check if a given string is a palindrome or can be a palindrome by altering some character without using a library function. Here is my Approach
import java.util.Scanner;
public class Palindrom {
static int temp=0;
static char[] cArr;
static boolean chackPotentialPalindrom(char[] cAr){
cArr=cAr;
if(cArr!=null){
char current=cArr[0];
for(int i=1;i<cArr.length;i++){
if(current==cArr[i]){
cArr=removeElement(i);
chackPotentialPalindrom(cArr);
break;
}
}
if(cAr.length==2){
if(cAr[0]==cAr[1]){
cArr=null;
}}
if(temp==0 && cArr!=null){
temp=1;
cArr=removeFirstElement(cArr);
chackPotentialPalindrom(cArr);
}
}
if(cArr==null){
return true;
}else{
return false;
}
}
static char[] removeFirstElement(char[] cAr){
cArr=cAr;
if(cArr!=null){
if(cArr.length >1){
char[] cArrnew=new char[cArr.length-1];
for(int j=1,k=0;j<cArr.length;j++,k++){
cArrnew[k]=cArr[j];
}
return cArrnew;
} else {
return null;
}
} else {
return null;
}
}
static char[] removeElement(int i){
if(cArr.length>2){
char[] cArrnew=new char[cArr.length-2];
for(int j=1,k=0;j<cArr.length;j++,k++){
if(i!=j){
cArrnew[k]=cArr[j];
}else{
k-=1;
}
}
return cArrnew;}
else{
return null;
}
}
public static void main(String[] args) {
Scanner scn=new Scanner(System.in);
while(true){
temp=0;
String s=scn.next();
char[] arr=s.toCharArray();
System.out.println(chackPotentialPalindrom(arr));
}
}
}
Any tips to optimize this code?I could not write this in an interview as they have given a pen and paper to code.It took 3 hrs for me to write this. Can I be a developer?
Title says "without loop" but you need to check all symbol pairs, so using recursion, as you have tried, looks reasonable. But you don't check and use results of recursive calls.
Pseudocode might look like (note we don't need to change source data or extract substring):
Edit to provide possibility to alter one char
boolean checkPotentialPalindrom(char[] cAr, start, end, altcnt){
if (end <= start)
return true
if (cAr[start] != cAr[end])
altcnt = altcnt + 1
if (altcnt > 1)
return false
return checkPotentialPalindrom(cAr, start + 1, end - 1, altcnt)
}
and make the first call with arguments 0, len(cAr-1), 0
Answering to your first question..You have to use recursion to solve this problem. Here is my approach.
public boolean isPalindrom(char[] str, int start, int end) {
if (end <= start)
return true;
if (str[start] != str[end] || arraySize(str) <= 1)
return false;
return isPalindrom(str, start + 1, end - 1);
}
public int arraySize(char[] str) {
int count = 0;
for (char i : str) {
count++;
}
return count;
}
You have tried to implement this algorithm using loops and you can simplify it like this
public boolean isPalindroms(char[] str) {
int diffCount = 0;
int left = 0;
int right = arraySize(str) - 1;
while (right > left) {
if (str[right--] != str[left++]) {
diffCount++;
}
}
return (diffCount < 2);
}
public int arraySize(char[] str) {
int count = 0;
for (char i : str) {
count++;
}
return count;
}
The answer for the second question that you have ask is definitely you can be a good developer. Computer programming is a Craft. Not Some Kind of Rocket Science. You have to master it by crafting it.
using recursive function
calling with left=0 and right = arr.length-1
public static boolean isPalindrom(char[] arr, int left, int right){
if(arr[left++] != arr[right--])
return false;
if(left < right)
isPalindromss(arr, left++, right--);
return true;
}
if you have to use while loop, you can simplify it like following
public boolean isPalindrom(char[] arr){
int left=0;
int right = arr.length-1;
while(left < right){
if(arr[left++] == arr[right--])
continue;
return false;
}
return true;
}
Using StringBuilder, We can do it
public static boolean isPalindrom(String str, int len){
StringBuilder sb= new StringBuilder(str);
if((len > 1) & !(sb.substring(0,len/2 + 1).equals(sb.reverse().substring(0,len/2 + 1))))
return false;
return true;
}
function palin(input, leftIdx = 0, rightIdx = input.length - 1) {
if (leftIdx >= rightIdx) return true;
if (input[leftIdx] != input[rightIdx]) return false;
return palin(input, leftIdx + 1, rightIdx - 1);
}
const testCases = {
air: false,
airia: true,
caria: false,
a: true,
bb: true,
bcdb: false,
zzaaaaz: false,
};
Object.keys(testCases).forEach(test =>
console.log("Test: ", test, " is palindrome: ", palin(test), testCases[test])
);

Helper Method won't work when called from other method, but will from main

I have a helper method that I am calling from another method in the same class. When I test it from main, it works fine. But as soon as I use it in the other class, it doesn't work at all. I cannot figure out what is wrong.
This is the helper method:
private boolean checkStack(Stack<String> stack,String check) {
System.out.println(stack);
System.out.println(check);
Stack<String> jump = new Stack<String>();
int count = 0;
String temp = "";
while (!stack.empty()) {
temp = stack.pop();
if (check == temp) {
count++;
}
jump.push(temp);
}
while (!jump.empty()) {
temp = jump.pop();
stack.push(temp);
}
System.out.println(count);
if (count != 0) {
return true;
} else {
return false;
}
}
I will test it from main like so:
pathSoFar.push("00");
pathSoFar.push("01");
pathSoFar.push("20");
pathSoFar.push("23");
System.out.println(pathSoFar);
String checkfor = "20";
System.out.println(test01.checkStack(pathSoFar,checkfor));
But it wont work when I call it from another method:
for (String n : possibleSpots) {
System.out.println();
String check = n;
if (!checkStack(pathSoFar, n)) {
pathSoFar.push(n);
String x = ""+n.charAt(0);
String y = ""+n.charAt(1);
int nextRow = Integer.parseInt(x);
int nextCol = Integer.parseInt(y);
System.out.println(nextRow + "" + nextCol + " = next move.");
if (findPath(wordToFind, pathSoFar, nextRow, nextCol)) {
return true;
}
} else{}
}
This is the method header if that helps:
private boolean findPath(String wordToFind, Stack<String> pathSoFar, int row, int col) {
possibleSpots can contain either String literals or String objects.
The problem lies in the following line
if (check == temp)
Change it to
if (check.equals(temp))
String matching is done with == which will work only for String literals.
That is the reason why it worked for you in one case and it does not work in another case.
To know the difference check the below link:
What is the difference between == vs equals() in Java?

CombSort implementation in java

I am using Comb Sort to sort out a given array of Strings. The code is :-
public static int combSort(String[] input_array) {
int gap = input_array.length;
double shrink = 1.3;
int numbOfComparisons = 0;
boolean swapped=true;
//while(!swapped && gap>1){
System.out.println();
while(!(swapped && gap==1)){
gap = (int)(gap/shrink);
if(gap<1){
gap=1;
}
int i = 0;
swapped = false;
String temp = "";
while((i+gap) < input_array.length){
numbOfComparisons++;
if(Compare(input_array[i], input_array[i+gap]) == 1){
temp = input_array[i];
input_array[i] = input_array[i+gap];
input_array[i+gap] = temp;
swapped = true;
System.out.println("gap: " + gap + " i: " + i);
ArrayUtilities.printArray(input_array);
}
i++;
}
}
ArrayUtilities.printArray(input_array);
return numbOfComparisons;
}
The problem is that while it sorts many arrays , it gets stuck in an infinite loop for some arrays, particularly small arrays. Compare(input_array[i], input_array[i+gap]) is a small method that returns 1 if s1>s2, returns -1 if s1
try this version. The string array is changed to integer array (I guess you can change it back to string version). The constant 1.3 is replaced with 1.247330950103979.
public class CombSort
{
private static final int PROBLEM_SIZE = 5;
static int[] in = new int[PROBLEM_SIZE];
public static void printArr()
{
for(int i=0;i<in.length;i++)
{
System.out.print(in[i] + "\t");
}
System.out.println();
}
public static void combSort()
{
int swap, i, gap=PROBLEM_SIZE;
boolean swapped = false;
printArr();
while ((gap > 1) || swapped)
{
if (gap > 1)
{
gap = (int)( gap / 1.247330950103979);
}
swapped = false;
for (i = 0; gap + i < PROBLEM_SIZE; ++i)
{
if (in[i] - in[i + gap] > 0)
{
swap = in[i];
in[i] = in[i + gap];
in[i + gap] = swap;
swapped = true;
}
}
}
printArr();
}
public static void main(String[] args)
{
for(int i=0;i<in.length;i++)
{
in[i] = (int) (Math.random()*PROBLEM_SIZE);
}
combSort();
}
}
Please find below implementation for comb sort in java.
public static void combSort(int[] elements) {
float shrinkFactor = 1.3f;
int postion = (int) (elements.length/shrinkFactor);
do {
int cursor = postion;
for(int i=0;cursor<elements.length;i++,cursor++) {
if(elements[i]>elements[cursor]) {
int temp = elements[cursor];
elements[cursor] = elements[i];
elements[i] = temp;
}
}
postion = (int) (postion/shrinkFactor);
}while(postion>=1);
}
Please review and let me know your's feedback.

Sort String with possible numbers in it

I've got the following possible addresses as string (not sorted):
"road 21"
"road 1"
"road 186"
"road +21 / 23"
"road +21 / 19"
"another road 21"
"another road 1"
and I want to be able to sort them as (so not on the default String sorting way):
another road 1
another road 21
road 1
road 21
road +21 / 19
road +21 / 23
road 186
How should I do this? I probably have to use a custom comparator, but how should I split the String?
I implemented this in Java and I know it looks weird at first.
If you have any questions feel free to ask me
public class SpecialComparator implements Comparator<String> {
#Override
public int compare(String arg0, String arg1) {
// TODO Auto-generated method stub
String []words1=arg0.split(" ");
String [] words2 = arg1.split(" ");
int i = 0;
if (words1[i].hashCode()>words2[i].hashCode()){
return 1;
}
else if (words1[i].hashCode()<words2[i].hashCode()){
return -1;
}
else if (words1[i].hashCode()==words2[i].hashCode())
return compare(arg0.substring(i+1, arg0.length()), arg1.substring(i+1,arg1.length()));
else if (i == Math.min(words1.length,words2.length)-1 && Math.min(words1.length,words2.length) == words1.length){
return -1;
}
else if (i == Math.min(words1.length,words2.length)-1 && Math.min(words1.length,words2.length) == words2.length){
return 1;
}
else if (i == Math.min(words1.length,words2.length)-1 && words1.length == words2.length){
return 0;
}
else{
return 0;
}
}
public static void main (String[] args){
ArrayList<String> input = new ArrayList<String>();
SpecialComparator a = new SpecialComparator();
input.add("road 21");
input.add("road 1");
input.add("road 186");
input.add("road +21 / 23");
input.add("road +21 / 19");
input.add("another road 21");
input.add("another road 1");
Collections.sort(input,a);
for (String ans : input){
System.out.println(ans);
}
}
}
Your format seems to be :
{name}
{number}
optional slash character
Optional second {number}.
Hence, I would create an object representing this format with those attributes:
public class MyInput {
private String name;
private Integer firstNumber;
private Integer secondNumber;
}
Then parse your input file to create a List<MyInput>.
Finally, you create a custom Comparator can call Collections.sort(yourList, yourCustomComparator)
This issue seems to crop up alot. I have been using Martin Pools NaturalOrderCompartor. You can easily port it into your code.
https://github.com/paour/natorder/blob/master/NaturalOrderComparator.java
it is little bit nasty, but this is my solution for your problem
List<String> list = Arrays.asList("road 21", "road 1", "road 186",
"road +21 / 23", "road +21 / 19", "another road 21",
"another road 1");
Collections.sort(list, new Comparator<String>() {
Integer toNumber(String string) {
try {
return Integer.parseInt(string);
} catch (NumberFormatException e) {
return null;
}
}
#Override
public int compare(String o1, String o2) {
String[] left = o1.split("\\s+");
String[] right = o2.split("\\s+");
for (int i = 0; i < Math.min(left.length, right.length); i++) {
String ls = left[i];
String rs = right[i];
Integer li = toNumber(ls);
Integer ri = toNumber(rs);
if (li != null && ri != null
&& li.intValue() != ri.intValue()) {
return li.intValue() - ri.intValue();
} else if (li != null && ri == null) {
return 1;
} else if (li == null && ri != null) {
return -1;
} else if (li == null && ri == null){
int compared = ls.compareToIgnoreCase(rs);
if (compared != 0) {
return compared;
}
}
}
return left.length - right.length;
}
});
but if you are ok with changing your structure, then go with solution proposed by Arnaud Denoyelle
You can also try following comparator :
class MyComparator implements Comparator<String> {
#Override
public int compare(String o1, String o2) {
o1 = o1.replace("+", "");
o2 = o2.replace("+", "");
String[] a1 = o1.split(" ");
String[] a2 = o2.split(" ");
int length = (a1.length > a2.length) ? a2.length : a1.length;
for (int i = 0; i < length; i++) {
if (!a1[i].equalsIgnoreCase(a2[i])) {
if (!isIntegerRegex(a1[i]) || !isIntegerRegex(a2[i])) {
return o1.compareTo(o2);
}
int f = Integer.parseInt(a1[i]);
int s = Integer.parseInt(a2[i]);
return f - s;
}
}
return a1.length - a2.length;
}
public boolean isIntegerRegex(String str) {
return str.matches("^[0-9]+$");
}
}
And call it:
public String[] sortStrings(String[] input) {
Arrays.sort(input, new MyComparator());
return input;
}

Categories