Generate Data Points for Graph from an equation - java

I don't want to solve an equation and my question is not about Graphs and Trees Data Structures. I am trying to generate Data Points for graph from an equation given by user. I want efficient algorithm, easy to use and easy to maintain data structures. I have two solutions in mind
1: This is trivial and I have seen in many Applications.
String expr = "2*x+3*x";
Evaluator evaluator = new Evaluator();//I have this class
for (int i = start; i < end; i += step)
{
evaluator.setConstant("x", i);
double ans = evaluator.evaluate(expr);
}
This is very slow because each time every step is repeated like tokenzing, verifying, conversion to RPN, preparing stacks and queues and at last result calculation. The possible solution to this problem is somehow caching all stacks and queues but after that a comparison would be required between current expression and previous expression to use last stored state.
2: Currently I am developing second solution. The purpose of this is efficiency and would be used in Symbolic calculation in future.
So far my implementation
Variable.java
import java.text.DecimalFormat;
public class Variable
{
private final double pow;
private final double coefficient;
private final String symbol;
public Variable(String symbol)
{
this.symbol = symbol;
this.pow = 1.0;
this.coefficient = 1.0;
}
public Variable(String symbol, double coefficient, double pow)throws IllegalArgumentException
{
if (coefficient == 0.0)throw new IllegalArgumentException("trying to create variable with coefficient 0");
if (pow == 0.0)throw new IllegalArgumentException("trying to create variable with exponent 0");
this.symbol = symbol;
this.pow = pow;
this.coefficient = coefficient;
}
public final String getSymbol()
{
return this.symbol;
}
public final double getPow()
{
return this.pow;
}
public final double getCoefficient()
{
return this.coefficient;
}
#Override
public String toString()
{
StringBuilder builder = new StringBuilder();
DecimalFormat decimalFormat = new DecimalFormat("#.############");
if (coefficient != 1.0)builder.append(decimalFormat.format(this.coefficient));
builder.append(this.symbol);
if (this.pow != 1.0)builder.append("^").append(decimalFormat.format(this.pow));
return builder.toString();
}
/*
* Stub Method
* Generate some unique hash code
* such that chances of key collision
* become less and easy to identify
* variables with same power and same
* symbol*/
#Override
public int hashCode()
{
return 0;
}
}
Equation.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
public class Equation
{
private final ArrayList<Boolean> operations;
private final HashMap<String, Variable> variableHashMap;
private int typesOfVariables;
public Equation(Variable variable)
{
this.variableHashMap = new HashMap<>();
this.operations = new ArrayList<>();
this.typesOfVariables = 1;
this.variableHashMap.put(variable.getSymbol(), variable);
}
/*Stub Method*/
public void addVariable(Variable variable, boolean multiply)
{
/*
* Currently not covering many cases
* 1: Add two variables which have same name
* and same pow.
* 2: variable which are wrapped inside functions e.g sin(x)
* and many other.*/
if (multiply && variableHashMap.containsKey(variable.getSymbol()))
{
Variable var = variableHashMap.get(variable.getSymbol());
Variable newVar = new Variable(var.getSymbol(), var.getCoefficient() * variable.getCoefficient(), var.getPow() + variable.getPow());
/*
* Collision chances for variables with same name but
* with different powers*/
this.variableHashMap.replace(var.getSymbol(), newVar);
}
else
{
++this.typesOfVariables;
this.variableHashMap.put(variable.getSymbol(), variable);
}
this.operations.add(multiply);
}
/*Stub Method
*Value for every variable at any point will be different*/
public double solveFor(double x)
{
if (typesOfVariables > 1)throw new IllegalArgumentException("provide values for all variables");
Iterator<HashMap.Entry<String, Variable>> entryIterator = this.variableHashMap.entrySet().iterator();
Variable var;
double ans = 0.0;
if (entryIterator.hasNext())
{
var = entryIterator.next().getValue();
ans = var.getCoefficient() * Math.pow(x, var.getPow());
}
for (int i = 0; entryIterator.hasNext(); i++)
{
var = entryIterator.next().getValue();
if (this.operations.get(i))ans *= var.getCoefficient() * Math.pow(x, var.getPow());
else ans += var.getCoefficient() * Math.pow(x, var.getPow());
}
return ans;
}
#Override
public String toString()
{
StringBuilder builder = new StringBuilder();
Iterator<HashMap.Entry<String, Variable>> entryIterator = this.variableHashMap.entrySet().iterator();
if (entryIterator.hasNext())builder.append(entryIterator.next().getValue().toString());
Variable var;
for (int i = 0; entryIterator.hasNext(); i++)
{
var = entryIterator.next().getValue();
if (this.operations.get(i))builder.append("*").append(var.toString());
else builder.append(var.toString());
}
return builder.toString();
}
}
Main.java
class Main
{
public static void main(String[] args)
{
try
{
long t1 = System.nanoTime();
Variable variable = new Variable("x");
Variable variable1 = new Variable("x", -2.0, 1.0);
Variable variable2 = new Variable("x", 3.0, 4.0);
Equation equation = new Equation(variable);
equation.addVariable(variable1, true);//2x+x
equation.addVariable(variable2, true);
for (int i = 0; i < 1000000; i++)equation.solveFor(i);//Calculate Million Data Points
long t2 = System.nanoTime();
System.out.println((t2-t1)/1000/1000);
System.out.println(equation.toString());
}
catch (Exception e)
{
System.out.println("Error: " + e.getMessage());
}
}
}
Am I going in right direction?
Is there any commonly used Algorithm for this problem?
My main goal is efficiency, code cleanness and code maintainability.
Note: I am not native English speaker so please ignore any grammatical mistake.
Thanks.

I do not see any problem with your first code. Yes may be at every step your code "repeat like tokenzing, verifying, conversion to RPN, preparing stacks and queues and at last result calculation", but in the end all of this is just linear number of steps. So I fail to see how it can make it really slow.
One of the biggest screens I have seen was 2560x1440 pixels, which means that most of the time you would need less than 2500 points to draw your graph there.
If you point is code cleanness and code maintainability, then most probably a code consisting of 5 lines is better than the code consisting of 200.

Related

Issues with Kattis "0-1 Sequences" Solution

Since last night I have been working very hard trying to write a solution to the problem "0-1 Sequences" (https://open.kattis.com/problems/sequences) on Kattis. At this point, I am at my wits end. I keep getting the wrong answer on the third test case, and I've tried everything I can possibly think of to fix my code. I'm fairly certain that the formula I am using to compute the result is correct, and I haven't been able to find an example where it gives the wrong answer. I suspect the issue is something to do with how I am calculating the modulus, but I've written and rewritten the relevant parts of the code and I am still failing each time. Below is my code (sorry in advance, I've been working like a madman with not much regard for writing "nice" code).
import java.util.*;
import java.util.ArrayList;
public class oneZeroSequences {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
//leading zero's have no effect on the number of inversions,
//and we therefore get rid of them all right off the bat.
while(s.charAt(0)=='0'){
s=s.substring(1);
if(s.length()==0){
System.out.println(0);
System.exit(0);
}
}
System.out.println(findSum(s));
System.exit(0);
}
public static long findSum(String s) {
int m=1000000007;
long res = 0;
//if passed an empty string, the sum of inversions is obviously 0
if(s.length()==0){
return 0;
}
while(s.charAt(0)=='0'){
s=s.substring(1);
if(s.length()==0){
return 0;
}
}
//if the first character of the string is a question mark, we handle the case
//where that question mark is 1 first, and then remove the question mark since
//leading 0's have no effect on inversions.
while(s.charAt(0)=='?'){
res+=findSum("1"+s.substring(1))%m;
s=s.substring(1);
if(s.length()==0){
return res%m;
}
}
ArrayList<Integer> qArray = new ArrayList<Integer>();
int start=0;
int found;
//here we construct an array of the indices of question marks in the string
while(true){
found=s.indexOf('?', start);
if(found==-1){
break;
}
qArray.add(found);
start=found+1;
}
ArrayList<Integer> zeroArray = new ArrayList<Integer>();
start=0;
found=0;
//here we construct an array of the indices of 0's in the string
while(true){
found=s.indexOf('0', start);
if(found==-1){
break;
}
zeroArray.add(found);
start=found+1;
}
long k = qArray.size();
long a = zeroArray.size();
long zeroSum = sumArrayList(zeroArray);
long qSum = sumArrayList(qArray);
Double dres = 0.0;
//the formula for sum of inversions is as follows:
//2^k*(zeroSum) + 2^(k-1)*(qSum) - (a^2-a)*2^(k-1) - (2a-1)*2^(k-2) - (k^2+k)*2^(k-3)
//the following lines of code apply this formula, taking the modulus at each step.
if(k>=3){
res += (expBySquaringMod(2, k)*(zeroSum%m))%m;
//res=(res%m+m)%m;
res +=((expBySquaringMod(2, k-1))*(qSum%m))%m;
//res=(res%m+m)%m;
res -= ((((((a%m)*(a%m))%m)-a%m)%m)*expBySquaringMod(2,k-1))%m;
//res=(res%m+m)%m;
res -= (((((2*a-1)%m)*(k%m))%m)*expBySquaringMod(2,k-2))%m;
//res=(res%m+m)%m;
res-= (((((k%m)*(k%m))%m+k%m)%m)*expBySquaringMod(2, k-3))%m;
//res=(res%m+m)%m;
return res%m;
}
//the expBySquaringMod function will give incorrect
//results for negative exponents, hence the following code.
dres += ((Math.pow(2,k))*(zeroSum%m))%m;
dres=(dres%m+m)%m;
dres +=((Math.pow(2,k-1))*(qSum%m))%m;
dres=(dres%m+m)%m;
dres -= (((((a%m)*(a%m))%m-a%m)%m)*(Math.pow(2,k-1)))%m;
dres=(dres%m+m)%m;
dres -=((((2*a-1)%m*(k%m)%m)*(Math.pow(2,k-2))))%m;
dres=(dres%m+m)%m;
dres-=((((k%m)*(k%m)%m+k%m))%m*(Math.pow(2,k-3)))%m;
dres=(dres%m+m)%m;
res+=dres.intValue()%m;
return res%m;
}
public static int sumArrayList(ArrayList<Integer> list) {
int res = 0;
for(int d : list) {
res+=d;
}
return res;
}
//this function was written to deal with the massive powers of two required for the solution
public static long expBySquaringMod(int base, long exp) {
int m=1000000007;
long res=1;
if(exp%2==0) {
for(int i=0; i<exp/2;i++) {
res=(res*base*base)%m;
}
} else{
res=base;
for(int i=0; i<exp/2;i++) {
res=(res*base*base)%m;
}
}
return res;
}
}
Any help will be greatly appreciated. This problem has been causing me a lot of distress.

How to iterate to find the lowest value

Struggling to understand where I went wrong with the iteration at the get best fare method
The array holds [5.77, 2.44, 2.35] and should return the second index, however it seems that it is stuck at the double lowestPrice = lowestPriceRide[0];
I thought that maybe I was putting the return out of scope, but it didn't work.
> import java.lang.*;
import java.util.Arrays;
public class TransitCalculator {
double numberOfDays = 0.0;
double numberOfRides = 0.0;
double pricePerRide = 2.75;
double pricePerWeek = 33.00;
double priceUnlimited = 127.00;
double perRide = 0.00;
public TransitCalculator(double days, double rides){
numberOfDays = days;
numberOfRides = rides;
}
public double unlimited7Price(){
double numOfWeeks = Math.ceil(numberOfDays/7) ; // Math.ceil will return the largest integer that is divisble without a remainder //
double totalPrice = numOfWeeks * pricePerWeek;
return totalPrice / numberOfRides;
}
public double[] getRidePrices(){ // 28/06/2020 Sunday. Math is verified.
double perRide = pricePerRide * numberOfRides / numberOfDays;
double perWeek = unlimited7Price();
double unlimited = priceUnlimited / numberOfRides;
double ridePrices[]; // Declared Array //
ridePrices = new double[] {perRide, perWeek, unlimited}; // New array, with added elements. Could be a mistake since I failed to declare elements//
return ridePrices;
}
public String getBestFare(){ // Error in the iteration and lowest value find! //
double lowestPriceRide[];
lowestPriceRide = getRidePrices();
double lowestPrice = lowestPriceRide[0];
for(int i = 0; i< lowestPriceRide.length; i++) {
if (lowestPrice < lowestPriceRide[i]) {
lowestPriceRide[i] = lowestPrice;
}
}
if(lowestPrice == lowestPriceRide[0]){
System.out.println("You should take the 'Pay per Ride' option in our NYC transit");
}
else if(lowestPrice == lowestPriceRide[1]){
System.out.println("You should take the 'Weekly Unlimited' plan in our NYC Transit");
}
else if(lowestPrice == lowestPriceRide[2]){
System.out.println("You should take the Unlimited ride plan in our NYC Transit");
}
return "at " + lowestPrice + "$ per Ride";
}
public static void main(String[] args){
TransitCalculator test = new TransitCalculator(26, 54);
System.out.println(test.getBestFare()); //
}
}
You are not setting the right value; currently, you set the element in the array to the lowest price instead of setting the lowest price to the element of the array. You also compare against the wrong value; you should check that the current array element is less than the best price, instead of the other way around.
Change
if(lowestPrice < lowestPriceRide[i])
lowestPriceRide[i] = lowestPrice;
To
if(lowestPriceRide[i] < lowestPrice)
lowestPrice = lowestPriceRide[i];
See the updated code in action here.
Note that it is unnecessary to import java.lang, as the package is implicitly imported.
The problem is in your if condition:
if (lowestPrice < lowestPriceRide[i]) {
lowestPriceRide[i] = lowestPrice;
}
You need to see if the current lowestPriceRide[i] is less than the already existing lowestPrice then update your existing lowestPrice. So the condition would be now:
if (lowestPriceRide[i] < lowestPrice) {
lowestPrice = lowestPriceRide[i];
}
This should be your comparison for lowest price :
double lowestPrice = lowestPriceRide[0];
for(int i = 0; i< lowestPriceRide.length; i++) {
if (lowestPriceRide[i] < lowestPrice) {
lowestPrice = lowestPriceRide[i];
}
}

Custom LinkedList implementation to store terms of a polynomial

For a homework assignment I'm working on you're required to create a custom LinkedList data structure to hold the terms of a polynomial. I'm having a problem at the moment with my constructor adding terms to the data structure because it needs to accept a string like "5.2 3 2.1 2" (which would be the equivalent of 5.2^3 + 2.1^2) and store it in the my custom LinkedList. Some of the requirements include that terms cannot have coefficients of zero, exponents must be integers, and coefficients can be either integers or doubles. When I trace the program using my IDE's debugger what I've seen is that for some reason valid coefficients are getting caught on the clause that I've marked with a "#" and the reference to the head of my list (the Term first variable) doesn't seem to be getting additional variables from the inputted string linked to it properly. Any help you can give would be much appreciated, thanks in advance. There are many required methods but this the relevant code for the problem I'm experiencing:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Polynomial
{
// instance variables
private Term first;
private int numTerms;
/**
* Constructor for objects of class Polynomial
*/
public Polynomial(String s)
{
Pattern whiteSpace = Pattern.compile(" ");
String[] poly = whiteSpace.split(s);
double coefficient;
int exponent;
if(poly.length % 2 == 1) {
throw new IllegalArgumentException();
}
first = new Term(); // dummy variable so that checking the first term specially is unnecessary
for(int term = 0; term < poly.length; term += 2) {
if(poly[term].matches("[\\-][0-9]||[0-9]||[0-9][\\.][0-9]||[\\-][0-9][\\.][0-9]")) {
coefficient = Double.parseDouble(poly[term]);
if(poly[term + 1].matches("[0-9]")) {
exponent = Integer.parseInt(poly[term++]);
} else {
throw new IllegalArgumentException(); //#
}
numTerms++;
this.addTerm(coefficient, exponent);
}
}
}
public void addTerm(double coef, int exp)
{
if(coef == 0) {
throw new IllegalArgumentException();
}
Term pointer = first;
while(pointer.next != null) {
if(exp == pointer.next.exponent) {
if(coef + pointer.next.coefficient == 0) {
pointer.next = pointer.next.next;
numTerms--;
} else {
pointer.next.coefficient += coef;
break;
}
} else if(pointer.next.exponent < exp) {
Term newTerm = new Term(coef, exp, pointer.next.next);
pointer.next = newTerm;
numTerms++;
break;
}
pointer = pointer.next;
}
}
private class Term {
double coefficient;
int exponent;
Term next;
Term() {
next = null;
}
Term(double coef, int exp, Term nextTerm) {
coefficient = coef;
exponent = exp;
next = nextTerm;
}
}`
You do not need regex to check for validity ParseXXX() takes care of that. If parsing fails, an Exception is thrown and then you can simply throw IllegalArgumentException
for (int term = 0; term < poly.length - 1; term += 2) {
try {
coefficient = Double.parseDouble(poly[term]);
exponent = Integer.parseInt(poly[term + 1]);
numTerms++;
this.addTerm(coefficient, exponent);
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
}
}
Moreover, using regex = "[0-9]" means only a single digit exponent. You might want to change it to "[0-9]+"

How to proccess blocking time of a simulated queue in java for an M/M/2 system?

hello guys for simulating the queue blocking time for an M/M/1 I came up with this very solution, but it is not Object-oriented unfortunately, also the problem is I want to simulate it with M/M/2 system,for instance I initialized lambda with 19 and mu with 20 just for ease up the calculation any solution, hint, code example will be greatly appreciated.
public class Main {
public static void main(String[] args) {
final int MAX_ENTITY = 100000;
final int SYSTEM_CAPACITY = 5;
final int BUSY = 1;
final int IDLE = 0;
double lambda = 19, mu = 20;
int blocked = 0;
int queue_length = 0;
int server_state = IDLE;
int entity = 0;
double next_av = getArivalRand(lambda);
double next_dp = next_av + getDeparturedRand(lambda);
while (entity <= MAX_ENTITY) {
//Arrival
if (next_av <= next_dp) {
entity++;
if (server_state == IDLE) {
server_state = BUSY;
} else if (queue_length < SYSTEM_CAPACITY - 1) {
queue_length++;
} else {
blocked++;
}
next_av += getArivalRand(lambda);
} // Departure
else if (queue_length > 0) {
queue_length--;
next_dp = next_dp + getDeparturedRand(mu);
} else {
server_state = IDLE;
next_dp = next_av + getDeparturedRand(mu);
}
}
System.out.println("Blocked Etity:" + blocked + "\n");
}
public static double getArivalRand(double lambda) {
return -1 / lambda * Math.log(1 - Math.random());
}
public static double getDeparturedRand(double mu) {
return -1 / mu * Math.log(1 - Math.random());
}
}
EDIT:
check here if u don't know about the queue theory
oh boy you're code needs serious refactoring in order to achieve M/M/2.
I created a gist file here which I think implements what you wanted,
In the gist file I created a Dispatcher class for balancing two queues in two servers and also I've simulated it with two seeds, it is much more Object-Oriented approach,
here is an example code from gist file which is for balancing load of
the tasks
if (server1.getQueueLength() < server2.getQueueLength())
currentServer = server1;
else if (server1.getQueueLength() > server2.getQueueLength())
currentServer = server2;
else if (currentServer == server1)
currentServer = server2;
else
currentServer = server1;

iterating over list containing objects of another class

I am studying Java and I have an assignment to do. Here are the requirements.
There are two classes
Runner
MarathonAdmin
We have to create a runners list which holds the instances of Runner class
and have to assign values to instances name, age and agegroup taken from another txt file.
In another part there is requirement that create random numbers between 90 to 180 inclusive and iterate over each runner and assign random number value to runner's time instance.
I am stuck in last part. I am not getting how to iterate over each runner in runners list. I am including code I have done so far.
I need help with runMarathon() method whose requirement states
Write a public method for the MarathonAdmin class called runMarathon() that takes no arguments and returns no value. The method should iterate over runners, and for each runner generate a random number between 90 and 180 (inclusive) which should be used to set the time (in minutes) for that runner.
import java.util.*;
import java.io.*;
import ou.*;
import java.util.Random;
/**
* Write a description of class MarathonAdmin here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class MarathonAdmin
{
// instance variables - replace the example below with your own
private List<Runner> runners;
private String ageGroup;
private String age;
private Random randomNumber;
private String result;
String ageRunner;
String ageGrouprunners;
Scanner lineScanner;
int ans;
Runner runnerobj = new Runner();
/**
* Constructor for objects of class MarathonAdmin
*/
public MarathonAdmin()
{
// initialise instance variables
runners = new ArrayList<>();
}
/**
* An example of a method - replace this comment with your own
*
* #param y a sample parameter for a method
* #return the sum of x and y
*/
public void readInRunners()
{
String pathName = OUFileChooser.getFilename();
File aFile = new File(pathName);
String nameRunner;
BufferedReader bufferedFileReader = null;
try
{
bufferedFileReader = new BufferedReader(new FileReader(aFile));
String currentLine = bufferedFileReader.readLine();
while ( currentLine != null)
{
lineScanner = new Scanner(currentLine);
lineScanner.useDelimiter(",");
nameRunner = lineScanner.next();
ageRunner = lineScanner.next();
ageGrouprunners = result;
int size = runners.size();
if (Integer.parseInt(ageRunner) < 18)
{
result = "junior";
System.out.println(currentLine +" category" + " : Junior");
}
if (Integer.parseInt(ageRunner) > 55)
{
result = "senior";
System.out.println(currentLine +" category"+ " : Senior");
}
if (Integer.parseInt(ageRunner) > 18 && Integer.parseInt(ageRunner) < 55)
{
result = "standard";
System.out.println(currentLine +" category"+ " : Standard");
}
Runner runnerobj = new Runner();
runnerobj.setName(nameRunner);
runnerobj.setAgeGroup(ageGrouprunners);
System.out.println(runnerobj); //rough test
runners.add(runnerobj);
currentLine = bufferedFileReader.readLine();
}
}
catch (Exception anException)
{
System.out.println("Error: " + anException);
}
finally
{
try
{
bufferedFileReader.close();
}
catch (Exception anException)
{
System.out.println("Error: " + anException);
}
}
}
public void runMarathon()
{
int size = runners.size();
for ( int runnersIndex = 0; runnersIndex <= size; runnersIndex ++ )
{
this.randomNumber = new Random();
ans = randomNumber.nextInt(190 - 80 +1 ) + 90 ;
System.out.println(ans);
String runnerTime;
for( String nameRunner :)
{
}
}
}
}
Your call to .nextInt() is not going to give you the range you expect because the calculation is wrong. You also don't need to do a calculation - just provide the upper bound.
The way you've set up your loop with the runnersIdx, all you need to do is access the runner with the index. See the documentation for List since that's what you used (List<Runner>).
Whenever you're learning a programming language, you'll want to bookmark the documentation website and reference it frequently. The docs for java 7 are here: http://docs.oracle.com/javase/7/docs/api/
You may also find the Java Tutorials to be helpful.
Your loop in runMarathon() function. You'll want to retrieve each runner from your List and assign a time.
for ( int runnersIndex = 0; runnersIndex <= size; runnersIndex ++ ) {
this.randomNumber = new Random();
ans = randomNumber.nextInt(190 - 80 +1 ) + 90 ;
Runner runner = runners.get(runnersIndex);
runner.setTime(ans); //make sure you create the getters/setters for this value
}

Categories

Resources