I have been building a simple formula calculator and have gotten stuck with addition and subtraction. As you should know, when calculating an equation, you follow the arithmetic rules of precedence, i.e. brackets, order: power functions, division, multiplication, addition and subtraction. The problem is that addition and subtraction are given equal priority, so therefore you can read it from left to right. Here is my code so far:
{
ArrayList<String> equation = java.util.Arrays.asList({"2","-","2","+","5"});
while(equation.contains("+")){
addMe(equation);
}
while(equation.contains("-")){
minusMe(equation);
}
}
public static void addMe(ArrayList<String> numberList){
for (int i = 0, n = numberList.size(); i < n; i++) {
String value = (String) numberList.get(i);
if(value.equals("+")){
String wordBefore = (String) numberList.get(i-1);
String wordAfter = (String) numberList.get(i+1);
System.out.println("This is the word before " + wordBefore);
System.out.println("This is the word after " + wordAfter);
double doubleFromBefore = Double.parseDouble(wordBefore);
double doubleFromAfter = Double.parseDouble(wordAfter);
double answer = doubleFromBefore + doubleFromAfter;
System.out.println("This is the answer: " + answer);
String stringAnswer = String.valueOf(answer);
String newNum2 = value.replace(value, stringAnswer);
numberList.set(i,newNum2);
numberList.remove(i-1);
numberList.remove(i);
break;
}
}
}
The minusMe method is exactly the same as the addMe method except with "-" in relevant places. The problem I am having is getting the equation read from left to right one item at a time and either doing the add or subtract method. Ideally I think I need to combine my 2 while loops with an iterator, to solve the problem but my attempts haven't worked. Any idea as to if this will solve my problem? If so please provide amended loop.
Regards
Have a look at this
java.uti.ArrayList<String> equation = java.util.Arrays.asList({"2","-","2","+","5"});
java.util.Iterator<String> equIterator = equation.iterator();
int result = 0;
int multiplier = 1;
while(equIterator.hasNext()){
String operandOrOperator = equIterator.next();
if(operandOrOperator.equals("+")){
multiplier=1;
}else if(operandOrOperator.equals("-")){
multiplier=-1;
}else if(operandOrOperator.equals("*")){
result*=Integer.parseInt(equIterator.next()); // Assuming that next element will be there always after operator.
}else{
result+=(multiplier * Integer.parseInt(operandOrOperator));
}
}
System.out.println("Final result : " + result);
You are doing this all wrong. You need to use at least a recursive-descent expression parser, or Dijkstra's shunting-yard algorithm, maybe even a parser generator if this is going to grow into some kind of a language. You will find all these things via a web search.
Related
Hellow everyone,
I'm using Weka Java API for predictions. I was able to get the expected and actual behavior from the java code. But now what i wanted is to get the 'prediction margin' information from final results. From GUI, i can manage, but i wanted is a Java solution. appreciate if any one can help.What i wanted to get is the below highlighted information using java.
Below code shows the code i'm using as of now to predict actual/predicted.
for (int i = 0; i < testDataSet.numInstances(); i++) {
double actualClass = testDataSet.instance(i).classValue();
String actual = testDataSet.classAttribute().value((int) actualClass);
Instance newInst = testDataSet.instance(i);
double preJ48 = tree.classifyInstance(newInst);
String predictionString = testDataSet.classAttribute().value((int) preJ48);
System.out.println("Actual : " + actual + " Prediction : " + predictionString);
}
############################# Solution i found as below ##########
J48 tree = new J48();
tree.buildClassifier(trainDataSet);
double a = eval.evaluateModelOnceAndRecordPrediction(tree, testDataSet.instance(0));
eval.evaluateModel(tree, testDataSet, plainText);
for (String line : predsBuffer.toString().split("\n")) {
String[] linesplit = line.split("\\s+");
// If there's an error(error flag "+"), the length of linesplit is 6, otherwise 5
System.out.println("linesplit "+linesplit.length);
int id;
String expectedValue, classification;
double probability;
if (line.contains("+")) {
probability = Double.parseDouble(linesplit[5]);
System.out.println("Its Minus "+probability);
} else {
probability = Double.parseDouble(linesplit[4]);
System.out.println("Its Plus "+probability);
}
}
The prediction margin that you are referring to gets generated by the weka.gui.explorer.ClassifierErrorsPlotInstances class. Check the variables probActual and probNext in its process method.
This margin is simply the difference between the probability for the actual class label and the highest probability of the label that isn't the actual class label.
You can use the distributionForInstance method of your classifier to obtain the class distribution array and then determine these two probabilities to calculate the margin for the prediction.
QUESTION:
How can I read the string "d6+2-d4" so that each d# will randomly generate a number within the parameter of the dice roll?
CLARIFIER:
I want to read a string and have it so when a d# appears, it will randomly generate a number such as to simulate a dice roll. Then, add up all the rolls and numbers to get a total. Much like how Roll20 does with their /roll command for an example. If !clarifying {lstThen.add("look at the Roll20 and play with the /roll command to understand it")} else if !understandStill {lstThen.add("I do not know what to say, someone else could try explaining it better...")}
Info:
I was making a Java program for Dungeons and Dragons, only to find that I have come across a problem in figuring out how to calculate the user input: I do not know how to evaluate a string such as this.
I theorize that I may need Java's eval at the end. I do know what I want to happen/have a theory on how to execute (this is more so PseudoCode than Java):
Random rand = new Random();
int i = 0;
String toEval;
String char;
String roll = txtField.getText();
while (i<roll.length) {
check if character at i position is a d, then highlight the numbers
after d until it comes to a special character/!aNumber
// so if d was found before 100, it will then highlight 100 and stop
// if the character is a symbol or the end of the string
if d appears {
char = rand.nextInt(#);
i + #'s of places;
// so when i++ occurs, it will move past whatever d# was in case
// d# was something like d100, d12, or d5291
} else {
char = roll.length[i];
}
toEval = toEval + char;
i++;
}
perform evaluation method on toEval to get a resulting number
list.add(roll + " = " + evaluated toEval);
EDIT:
With weston's help, I have honed in on what is likely needed, using a splitter with an array, it can detect certain symbols and add it into a list. However, it is my fault for not clarifying on what else was needed. The pseudocode above doesn't helpfully so this is what else I need to figure out.
roll.split("(+-/*^)");
As this part is what is also tripping me up. Should I make splits where there are numbers too? So an equation like:
String[] numbers = roll.split("(+-/*^)");
String[] symbols = roll.split("1234567890d")
// Rough idea for long way
loop statement {
loop to check for parentheses {
set operation to be done first
}
if symbol {
loop for symbol check {
perform operations
}}} // ending this since it looks like a bad way to do it...
// Better idea, originally thought up today (5/11/15)
int val[];
int re = 1;
loop {
if (list[i].containsIgnoreCase(d)) {
val[]=list[i].splitIgnoreCase("d");
list[i] = 0;
while (re <= val[0]) {
list[i] = list[i] + (rand.nextInt(val[1]) + 1);
re++;
}
}
}
// then create a string out of list[]/numbers[] and put together with
// symbols[] and use Java's evaluator for the String
wenton had it, it just seemed like it wasn't doing it for me (until I realised I wasn't specific on what I wanted) so basically to update, the string I want evaluated is (I know it's a little unorthodox, but it's to make a point; I also hope this clarifies even further of what is needed to make it work):
(3d12^d2-2)+d4(2*d4/d2)
From reading this, you may see the spots that I do not know how to perform very well... But that is why I am asking all you lovely, smart programmers out there! I hope I asked this clearly enough and thank you for your time :3
The trick with any programming problem is to break it up and write a method for each part, so below I have a method for rolling one dice, which is called by the one for rolling many.
private Random rand = new Random();
/**
* #param roll can be a multipart roll which is run and added up. e.g. d6+2-d4
*/
public int multiPartRoll(String roll) {
String[] parts = roll.split("(?=[+-])"); //split by +-, keeping them
int total = 0;
for (String partOfRoll : parts) { //roll each dice specified
total += singleRoll(partOfRoll);
}
return total;
}
/**
* #param roll can be fixed value, examples -1, +2, 15 or a dice to roll
* d6, +d20 -d100
*/
public int singleRoll(String roll) {
int di = roll.indexOf('d');
if (di == -1) //case where has no 'd'
return Integer.parseInt(roll);
int diceSize = Integer.parseInt(roll.substring(di + 1)); //value of string after 'd'
int result = rand.nextInt(diceSize) + 1; //roll the dice
if (roll.startsWith("-")) //negate if nessasary
result = -result;
return result;
}
import java.math.BigInteger;
public class ProjectEuler {
public static void main(String[] args) {
BigInteger bi = new BigInteger("600851475143");
int div = 7;
while (bi.compareTo(new BigInteger("1")) != 0) {
while (bi.mod(new BigInteger(div + "")).compareTo(new BigInteger("0")) == 0) {
bi = bi.divide(new BigInteger(div + ""));
}
div += 2;
}
System.out.println("" + div);
}
}
I was just looking over one of the basic but famous problems of "What is the largest prime factor of the number 600851475143". I found this solution different, i have a couple of questions on how this works.
The first condition checks whether the number equals 1 or not. From there i am not able to understand the rest of the code.
new BigInteger(div +""). why do we concatenate + "" here?
How is the div = 7 decided?
The author decided to "hard-code" his knowledge of the number itself to decide that the first three primes are not among the divisors
The first condition checks whether the number equals 1 or not. From there i am not able to understand the rest of the code.
The rest of the code looks like this in "regular" integers:
while (bi % div == 0) {
bi /= div;
}
div += 2;
new BigInteger(div +"") why do we concatenate + "" here
That is a short way of making an object a String. BigInteger has a parameter that takes String, so the alternative to this approach would be calling Integer.toString(div).
Note that this is not the most efficient solution: one could speed this up by observing that you could stop trying to divide when you reach the square root of the original number, because you can be sure that the next divisor will be the number itself.
How is the div = 7 decided?
Probably the author noticed that the number isn't divisible by 2 nor 3 nor 5. To know how the author did this, he/she should have known this rules: Divisibility Rules and Tests
The first condition checks whether the number equals 1 or not. From there i am not able to understand the rest of the code.
The author is making sure that the number is not BigInteger("1") since it's dividing the number and storing the results in bi in the loop iterations. Note this:
bi = bi.divide(new BigInteger(div + ""));
new BigInteger(div +""). why do we concatenate + "" here?
It uses the BigInteger(String) constructor. The author n̶a̶i̶v̶e̶l̶y̶ makes a new String by adding the int with an empty String.
I have developed a program that solves kinematic equations in elementary physics. To solve, one needs 3 out of a possible 5 variables. There are 10 different combinations of what 3 variables are known. I coded 10 scenarios similar to the two blocks of code below
// If we have acceleration, final velocity, and initial velocity
if (varEntered[0] == true && varEntered[1] == true && varEntered[2] == true)
{
double acceleration = knownVariables[0]; //Setting acceleration
double finalVelocity = knownVariables[1]; //Setting finalVelocity
double initVelocity = knownVariables[2]; //Setting initVelocity
double time = ((finalVelocity - initVelocity)/acceleration); //Finding time using an equation
double distance = ((finalVelocity + initVelocity)*((0.5)*time)); //Finding distance using an equation
System.out.println("The time is " + time + " seconds"); //Printing time
System.out.println("The distance is " + distance + " meters"); //Printing distance
}
//If we have distance, final velocity, initial velocity
if (varEntered[3] == true && varEntered[1] == true && varEntered[2] == true)
{
//Known variables
double distance = knownVariables[3]; //Acceleration
double finalVelocity = knownVariables[1]; //Final Velocity
double initVelocity = knownVariables[2]; //Initial Velocity
// Unknown variables
double time = (distance/((0.5)*(finalVelocity + initVelocity))); //Time
double acceleration = ((finalVelocity - initVelocity)/time); //Acceleration
System.out.println("The time is " + time + " meters/second"); //Printing time
System.out.println("The acceleration is " + acceleration + " meters/second^2"); //Printing distance
}
These seem very similar, but are different scenarios. As a programming beginner, I am wondering if the algorithm I use can be modified to shorten the code. If any more info is needed I will be more than happy to provide.
You should define a function that accepts three numbers and performs the general calculation.
For a starter, try this tutorial. Then you can call your function twice, each time with different sets of variables.
I would use a Map and do something like this (warning: pseudocode):
import java.util.HashMap;
import java.util.Map;
Map<String,double> map=new HashMap<String, double>();
Initialize the map with all the values that are known, e.g.:
map.put("initVelocity", 0.35);
Then you can define the following function:
void calculateValues(Map<double,String> map){
if( map.containsKey("initVelocity") && map.containsKey("finalVelocity") && map.containsKey("acceleration")){
map.put("time",((map.get("finalVelocity") - map.get("initVelocity")/map.get("acceleration"));
}
add all the other algorithms here in the same way!!!
}
This function takes the values that are already defined in the HashMap and tries to calculate the missing parameters. It will often be necessary to call it multiple times on a map until all parameters are set. You could do something like:
while( the map has not all values set){
calculateValues(map);
}
Also, you could make sure (by adding this condition to the if-statements) that any of the algorithms is called only if the resulting values are not set yet. But don't worry too much about that.
From what I noticed, it seems each variable is associated with a number. You can eliminate all the possible scenarios completely and have if conditions on each of the five variables; through this identify the 3 variables first and initialize the local variables. They are independent of each other when assigned, so there's no reason to make that many combinations. This will shorten the code by a lot.
The next step is to shorten the number of combinations you have. The best thing I can think of is finding out the two values you need to compute and using the formulas, in other words another block of if else statements. Here's what the code would look like:
//initialize all to 0
double acceleration = 0;
double distance = 0;
double finalVelocity = 0;
double initVelocity = 0;
double time = 0;
//place the proper values for each
if (varEntered[0] == true){
acceleration = knownVariables[0];
}
if (varEntered[1] == true){
finalVelocity = knownVariables[1];
}
if (varEntered[2] == true){
initVelocity = knownVariables[2];
}
if (varEntered[3] == true){
distance = knownVariables[3];
}
if (varEntered[4] == true){
time = knownVariables[4];
}
// now you have 10 cases
if(varEntered[0] == false && varEntered[1] == false){
//use the formulas here
} else if (varEntered[0] == false && varEntered[2] == false){
//use other formula here
}// repeat for the next 8, with each time you change the condition and formulas
//like you have it. Also, I noticed that you missed the else in your conditionals;
//it is more efficient if you use if-else clauses when only one should execute every time you run the code.
Hope this helps.
Feel free to copy this out, fill the rest and try it out.
If you're careful with your dependencies, you can get away with 5 cases with 1 calculation each instead of 10 cases with 2 calculations each. To do this, you have to make sure that no two variables directly depend on each other. If that were to happen, then you would be out of luck when both of the variables are unknown.
One way to do this is to take your list of variables and calculate each variable in terms of the following three (wrapping around when you reach the end of the list), as in the following example. In this example, solveAll takes an array of doubles with the unknowns set to Double.MAX_VALUE, and it sets the unknowns to the correct values. (If there are more than two unknowns, you'll get an infinite recursion.)
// Really should use enum instead of constant ints, and an EnumMap instead of an array.
public final static int ACCELERATION = 0;
public final static int FINALVELOCITY = 1;
public final static int INITVELOCITY = 2;
public final static int DISTANCE = 3;
public final static int TIME = 4;
private double[] vars;
public void solveAll(double[] vars) {
this.vars = vars;
for (int i=ACCELERATION; i<=TIME; i++) {
get(i);
}
}
private double get(int v) {
if (vars[v] != Double.MAX_VALUE) {
return vars[v];
}
switch (v) {
case ACCELERATION:
return (vars[ACCELERATION] = (get(FINALVELOCITY)*get(FINALVELOCITY) - get(INITVELOCITY)*get(INITVELOCITY)) / (2*get(DISTANCE)));
case FINALVELOCITY:
return (vars[FINALVELOCITY] = 2*get(DISTANCE)/get(TIME) - get(INITVELOCITY));
case INITVELOCITY:
return (vars[INITVELOCITY] = get(DISTANCE)/get(TIME) - get(ACCELERATION)*get(TIME)/2);
case DISTANCE:
return (vars[DISTANCE] = (get(FINALVELOCITY) - get(ACCELERATION)*get(TIME)/2) * get(TIME));
case TIME:
return (vars[TIME] = (get(FINALVELOCITY) - get(INITVELOCITY)) / get(ACCELERATION));
}
return Double.MAX_VALUE; // Bad variable index
}
for (a = 0; a < filename; a++) {
Map<Double,String> m = new HashMap<Double,String>();
String pre = "abc";
String post = ".txt";
for (int ii = 0; ii < 11; ii++) {
m.put(similarityScore[a],pre + a + post + '\n');
}
SortedSet<Double> set = new TreeSet<Double>(m.keySet());
for (Double d : set) {
System.out.println(d + " " + m.get(d));
}
}
Output :
0.5773502691896258 abc0.txt
0.5773502691896258 abc1.txt
0.5773502691896258 abc2.txt
NaN abc3.txt
0.5773502691896258 abc4.txt
NaN abc5.txt
NaN abc6.txt
NaN abc7.txt
NaN abc8.txt
0.5773502691896258 abc9.txt
NaN abc10.txt
This code should be able to sort the double values. But it displays the output on top. What happen ?
The problem is almost certainly NaN.
This is, as the name suggests, not a realy number, and behaves very strangely in terms of comparisons. Is NaN greater than, equal to, or less than 0.5773502691896258? It could be any of those results, and isn't even required to be consistent within a single execution of the program. NaN is not even equal to itself, which says something about how preconceptions of the laws of equality, and strong ordering, go out of the window when NaN is involved.
So the fix is not to use a non-numeric and expect Double.compareTo() to do what you want with it. Depending on what NaN means when returned from similarityScore(), there are several approaches you could take. If it means that it's not a match at all, you could have that method return a Double (rather than a double), return null in these cases, and then only add non-null results to the map. If these results should be displayed anyway, then perhaps you could use a result of 0.0 or -1.0, assuming that's less than any "real" similarity score. If you want something more finessed, then returning something as pure and straightforward as a primitive double is likely going to be the problem, and you may need to return your own (simple) domain class instead.
As an aside - why on earth do you create and populate a HashMap, then use a TreeSet to get the iteration order over the keys? If you simply create m as a TreeMap<Double, String> you get exactly the iteration order you want, so can just iterate overm.entrySet()`. It's clearer, more idiomatic (thus more understandable), and more efficient, so there's no reason not to do this.
for (int ii = 0; ii < 11; ii++) {
m.put(similarityScore[a],pre + a + post + '\n');
}
This puts the same value into the map 11 times - you're not referencing ii inside the loop.
for (Double d : set) {
System.out.println(d + " " + m.get(d));
}
This prints the single entry in the map.
You do the above for values 0..filename - Adding a value to the map several times, then printing it and restarting with a new map.
Map<Double,String> m = new HashMap<Double,String>();
for (a = 0; a < filename; a++) {
String pre = "abc";
String post = ".txt";
m.put(similarityScore[a],pre + a + post + '\n');
}
SortedSet<Double> set = new TreeSet<Double>(m.keySet());
for (Double d : set) {
System.out.println(d + " " + m.get(d));
}
This creates a map, populates it with values for 0..filename, then prints it sorted. You'll still have issues with NaN which isn't really sortable.
Map<Double,String> m = new TreeMap<Double,String>();
for (a = 0; a < filename; a++) {
String pre = "abc";
String post = ".txt";
m.put(similarityScore[a],pre + a + post + '\n');
}
for (Double d : m.keySet()) {
System.out.println(d + " " + m.get(d));
}
And this uses a TreeMap - No need for the intermediate Set
For any Collection to sort, the type of the value on which you are sorting should be same. And should implement comparable interface.
In your case you have NaN and Double values to sort.
Your loop means you're sorting for each filename separately. You'll need to pull the sorting out of the loop to get those values sorted. (Ooops, #Eric beat me to it.)