I made this code for extracting Polynomial coefficients and also evaluating equation in a point,and it is work.
but i want to modify that so the user can enter any shape of polynomial equation.
in my code you have to enter equation like this:
2*x^2+3*x^1+4
but i want :
2*x^5+1*x+6
also if there any term with same power , their coeffs must be added together.
Here is my code in java:
package Priest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
public class Equation {
private String Eq;
private final String[] C;
private int Deg;
private final String EqHolder;
public Equation(String Equation) {
this.Eq = Equation;
EqHolder = Equation;
Eq = Eq.replaceAll("[^0-9\\-\\.]+", " ");
Eq = Eq.replaceAll("-", " -");
this.C = Eq.split(" ");
}
public String SourceEquation() {
return EqHolder.toUpperCase().replaceAll("\\*", "").replaceAll("[a-zA-Z]", "\\*(X)").replaceAll("\\+", "\\ + ").replaceAll("\\-", "\\ - ");
}
public List<BigDecimal> CaptureCoeff() {
getDegree();
List<BigDecimal> Temp = new ArrayList<>();
for (String S : C) {
Temp.add(new BigDecimal(S));
}
int Location = Temp.indexOf(BigDecimal.valueOf(Deg));
List<BigDecimal> Coeffs = new ArrayList<>();
for (int Counter = Location - 1; Counter < Temp.size(); Counter += 2) {
Coeffs.add(Temp.get(Counter));
}
return Coeffs;
}
public int getDegree() {
int Degree = 0;
for (int Counter = 0; Counter < C.length; Counter += 2) {
if ((new Double(C[Counter])) != 0) {
Degree = new Integer(C[Counter + 1]);
this.Deg = Degree;
break;
}
}
return Degree;
}
public BigDecimal Evaluate(List<BigDecimal> Coefficients, double EvalPoint) {
BigDecimal Output = BigDecimal.ZERO;
for (int Index = 0; Index < Coefficients.size(); Index++) {
Output = Output.add(Coefficients.get(Index).multiply(BigDecimal.valueOf(EvalPoint).pow(Deg--)));
}
return Output;
}
}
and main class:
package Priest;
import java.math.RoundingMode;
public class MainClass {
public static void main(String[] args) {
long Start = System.nanoTime();
String Str = "3.1415x^5-12.6x^4+6x^3+12*x^2-6*x^1-0";
Equation E = new Equation(Str);
System.out.println("Equation is: " + E.SourceEquation());
System.out.println("Coefficients :" + E.CaptureCoeff());
System.out.println("Polynomial Degree: " + E.getDegree());
double Target = 47.784;
System.out.println("Equation # (X:" + Target + ")= " + E.Evaluate(E.CaptureCoeff(), Target).setScale(15, RoundingMode.HALF_UP));
System.out.println("Elapsed Time: " + String.format("%.20G", (System.nanoTime() - Start) / 1.0e6) + " ms.");
}
}
the output:
run:
Equation is: 3.1415*(X)^5 - 12.6*(X)^4 + 6*(X)^3 + 12*(X)^2 - 6*(X)^1 - 0
Coefficients :[3.1415, -12.6, 6, 12, -6, 0]
Polynomial Degree: 5
Equation # (X:47.784)= 717609084.382589022327914
Elapsed Time: 32.306242000000000000 ms.
BUILD SUCCESSFUL (total time: 0 seconds)
Let's go with the following equation String Str2 = "3.1415x^5+6x^2+12*x-5";
Here is the code that I have added upon your code in order to preprocess this equation and made it compatible to your actual logic so that It will treat it without any major change to your code.
To be totally accurate I had to change the following in your equation class:
public List<BigDecimal> CaptureCoeff() {
getDegree();
List<BigDecimal> Temp = new ArrayList<BigDecimal>();
for (String S : C) {
if (! "".equals(S.trim())) {
Temp.add(new BigDecimal(S));
}
}
So I have added the control to check that none of these S strings is trim - empty.
Here is my preprocessing code.
I have added a method called powerSplitt that allows to splitt the equation on the basis of the '^' char.
Then I created another method called generateNullCoeffPolynomeWithDegree that generate a monome in the form 0*X^k. And a similar one that generate all the similar intermediate monomes between the greater power and the lesser power
Example:
String str3 = generateAllNullCoeffPolynomesWithDegreeExclusiveBetween(5, 2);
System.out.println("all poly = " + str3);
will generate: all poly = 0*x^4+0*x^3
Then I created a buildPreProcessedPolynome that takes the initial equation and pre process it to produce one with the null monomes inside of it. And then I just gave it to your equation program and it could process it fine!!!
Here is the code and a call example all done in the MainClass
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
public class MainClass {
private static List<String> workList = new ArrayList<String>();
public static void powerSplitt(String equationText) {
char[] charsList = equationText.toCharArray();
boolean foundTargetChar = false;
int index = 0;
for (int i = 0; i < charsList.length; i++) {
index = i;
if (charsList[i] == '^') {
foundTargetChar = true;
break;
}
}
if (foundTargetChar) {
workList.add(equationText.substring(0, index));
if (index +1 < equationText.length()) {
powerSplitt(equationText.substring(index+1));
} else {
workList.add(equationText);
return;
}
} else {
workList.add(equationText);
}
}
public static String generateNullCoeffPolynomeWithDegree(int degree) {
return "0*x^" + degree;
}
public static String generateAllNullCoeffPolynomesWithDegreeExclusiveBetween(int startDegree, int endDegree) {
if (startDegree-endDegree <= 1) {
return "";
}
int index = 0;
StringBuilder builder = new StringBuilder();
for (int i = startDegree -1; i > endDegree; i--) {
if (index > 0) {
builder.append("+");
}
builder.append(generateNullCoeffPolynomeWithDegree(i));
index++;
}
return builder.toString();
}
public static String buildPreProcessedPolynome(String initialEquationText) {
workList.clear();
powerSplitt(initialEquationText);
StringBuilder resultBuilder = new StringBuilder();
assert workList.size() >= 3;
resultBuilder.append(workList.get(0));
for (int i = 1; i <= workList.size()-2; i++) {
int actualPower = Integer.parseInt( workList.get(i).substring(0,1));
int nextFoundPower = Integer.parseInt( workList.get(i+1).substring(0,1));
System.out.print("actual power = " + actualPower + " and next power = " + nextFoundPower);
System.out.println();
String additionalPolyParts = generateAllNullCoeffPolynomesWithDegreeExclusiveBetween(actualPower, nextFoundPower);
resultBuilder.append("^" + actualPower);
resultBuilder.append("+");
resultBuilder.append(additionalPolyParts);
resultBuilder.append(workList.get(i).substring(1));
}
resultBuilder.append("^" + workList.get(workList.size()-1));
return resultBuilder.toString();
}
public static void main(String[] args) {
workList.clear();
String Str2 = "3.1415x^5+6x^2+12*x-5";
powerSplitt(Str2);
for (String part: workList) {
System.out.println("PART:" + part);
}
System.out.println("-----------------");
long Start = System.nanoTime();
String str3 = generateAllNullCoeffPolynomesWithDegreeExclusiveBetween(5, 2);
System.out.println("all poly = " + str3);
String preprocessed = buildPreProcessedPolynome(Str2);
System.out.println("preprocessed = " + preprocessed);
System.out.println();
Equation E = new Equation(preprocessed);
System.out.println("Equation is: " + E.SourceEquation());
System.out.println("Coefficients :" + E.CaptureCoeff());
System.out.println("Polynomial Degree: " + E.getDegree());
double Target = 47.784;
System.out.println("Equation # (X:" + Target + ")= " + E.Evaluate(E.CaptureCoeff(), Target).setScale(15, RoundingMode.HALF_UP));
System.out.println("Elapsed Time: " + String.format("%.20G", (System.nanoTime() - Start) / 1.0e6) + " ms.");
}
}
And here is the produced results (I haved added some System.out.println to check the results of my methods calls. I just noticed I have to take into account the last constant as a monome of type K*X^0, but I will leave that to you):
PART:3.1415x
PART:5+6x
PART:2+12*x-5
all poly = 0*x^4+0*x^3
actual power = 5 and next power = 2
preprocessed = 3.1415x^5+0*x^4+0*x^3+6x^2+12*x-5
Equation is: 3.1415*(X)^5 + 0*(X)^4 + 0*(X)^3 + 6*(X)^2 + 12*(X) - 5
Coefficients :[3.1415, 0, 0, 6, 12]
Polynomial Degree: 5
Equation # (X:47.784)= 782631805.485054892561514
Elapsed Time: 18,441978000000000000 ms.
Related
I've just started learning java since last week. I'm using book called 'head first java' and i'm struggling with solving problems about ArrayList. Error says "The method setLocationCells(ArrayList) in the type DotCom is not applicable for the
arguments (int[])" and I haven't found the solution :( help me..!
enter image description here
This looks like a Locate & Conquer type game similar to the game named Battleship with the exception that this game is a single player game played with a single hidden ship in a single horizontal row of columnar characters. Rather simplistic but kind of fun to play I suppose. The hard part is to locate the hidden ship but once you've located it, conquering (sinking) it becomes relatively easy. I'm sure this isn't the games' intent since it is after all named "The Dot Com Game" but the analogy could be possibly helpful.
There are several issues with your code but there are two major ones that just can not be there for the game to work:
Issue #1: The call to the DotCom.setLocationCells() method:
The initial problem is located within the DotComGame class on code line 13 (as the Exception indicates) where the call is made to the DotCom.setLocationCells() method. As already mentioned in comments the wrong parameter type is passed to this method. You can not pass an int[] Array to the setLocationCell() method when this method contains a parameter signature that stipulates it requires an ArrayList object. The best solution in my opinion would be to satisfy the setLocationCells() method parameter requirement...supply an ArrayList to this method.
The reason I say this is because all methods within the DotCom class work with an established ArrayList and one of the tasks of one of these methods (the checkYourself() method) actually removes elements from the ArrayList which is easy to do from a collection but very cumbersome to do the same from an Array.
To fix this problem you will need to change the data type for the locations variable located within the DotComGame class. Instead of using:
int[] locations = {randomNum, randomNum + 1, randomNum + 2};
you should have:
ArrayList<Integer> locations = new ArrayList<>(
Arrays.asList(random, randomNum + 1, randomNum + 2));
or you could do it this way:
ArrayList<Integer> locations = new ArrayList<>();
locations.add(randomNum);
locations.add(randomNum + 1);
locations.add(randomNum + 2);
There are other ways but these will do for now. Now, when the call to the setLocationCells() method is made you ahouldn't get an exception this issue should now be resolved.
Issue #2: The call to the DotCom.checkYourself() method:
Again, this particular issue is located within the DotComGame class on code line 18 where the call is made to the DotCom.checkYourself() method. Yet another parameter data type mismatch. You are trying to pass a variable of type String (named guess) to this method whereas its signature stipulates that it requires an integer (int) value. That again is a no go.
To fix this problem you will need to convert the string numerical value held by the guess variable to an Integer (int) value. So instead of having this:
while(isAlive) {
String guess = helper.getUserInput("Enter a Number: ");
String result = theDotCom.checkYourself(guess);
// ... The rest of your while loop code ...
}
you should have something like:
while(isAlive) {
String guess = helper.getUserInput("Enter a Number: ");
/* Validate. Ensure guess holds a string representation
of a Integer numerical value. */
if (!guess.matches("\\d+")) {
System.err.println("Invalid Value (" + guess
+ ") Supplied! Try again...");
continue;
}
int guessNum = Integer.parseInt(guess);
String result = theDotCom.checkYourself(guessNum);
numOfGuesses++;
if (result.equals("kill")) {
isAlive = false;
System.out.println(numOfGuesses + " guesses!");
}
else if (result.equals("hit")) {
// Do Something If You Like
System.out.println("HIT!");
}
else {
System.out.println("Missed!");
}
}
Below is a game named Simple Battleship which I based off of your code images (please don't use images for code anymore - I hate using online OCR's ;)
BattleshipGame.java - The application start class:
import java.awt.Toolkit;
public class BattleshipGame {
public static int gameLineLength = 10;
public static void main(String[] args) {
GameHelper helper = new GameHelper();
Battleship theDotCom = new Battleship();
int score = 0; // For keeping an overall score
// Display About the game...
System.out.println("Simple Battleship Game");
System.out.println("======================");
System.out.println("In this game you will be displayed a line of dashes.");
System.out.println("Each dash has the potential to hide a section of a");
System.out.println("hidden Battleship. The size of this ship is randomly");
System.out.println("chosen by the game engine and can be from 1 to 5 sections");
System.out.println("(characters) in length. The score for each battle is based");
System.out.println("on the length of the game line that will be displayed to");
System.out.println("you (default is a minimum of 10 charaters). You now have");
System.out.println("the option to supply the game line length you want to play");
System.out.println("with. If you want to use the default then just hit ENTER:");
System.out.println();
// Get the desire game line length
String length = helper.getUserInput("Desired Game Line Length: --> ", "Integer", true, 10, 10000);
if (!length.isEmpty()) {
gameLineLength = Integer.parseInt(length);
}
System.out.println();
// Loop to allow for continuous play...
boolean alwaysReplay = true;
while (alwaysReplay) {
int numOfGuesses = 0;
/* Create a random ship size to hide within the line.
It could be a size from 1 to 5 characters in length. */
int shipSize = new java.util.Random().nextInt((5 - 1) + 1) + 1;
int randomNum = (int) (Math.random() * (gameLineLength - (shipSize - 1)));
int[] locations = new int[shipSize];
for (int i = 0; i < locations.length; i++) {
locations[i] = randomNum + i;
}
System.out.println("Destroy the " + shipSize + " character ship hidden in the");
System.out.println("displayed line below:");
System.out.println();
String gameLine = String.join("", java.util.Collections.nCopies(gameLineLength, "-"));
theDotCom.setLocationCells(locations);
// Play current round...
boolean isAlive = true;
while (isAlive == true) {
System.out.println(gameLine);
String guess = helper.getUserInput("Enter a number from 1 to " + gameLineLength
+ " (0 to quit): --> ", "Integer", 1, gameLineLength);
int idx = Integer.parseInt(guess);
if (idx == 0) {
System.out.println("Quiting with an overall score of: " + score + " ... Bye-Bye");
alwaysReplay = false;
break;
}
idx = idx - 1;
String result = theDotCom.checkYourself(idx);
numOfGuesses++;
System.out.println(result);
if (result.equalsIgnoreCase("kill")) {
Toolkit.getDefaultToolkit().beep();
isAlive = false;
/* Tally the score dependent upon the gameLineLength... */
if (gameLineLength <= 10) { score += 5; }
else if (gameLineLength > 10 && gameLineLength <= 20) { score += 10; }
else if (gameLineLength > 20 && gameLineLength <= 30) { score += 15; }
else if (gameLineLength > 30 && gameLineLength <= 40) { score += 20; }
else { score += 25; }
gameLine = gameLine.substring(0, idx) + "x" + gameLine.substring(idx + 1);
System.out.println(gameLine);
System.out.println(numOfGuesses + " guesses were made to sink the hidden ship.");
System.out.println("Your overall score is: " + (score < 0 ? 0 : score));
}
else if (result.equalsIgnoreCase("hit")) {
gameLine = gameLine.substring(0, idx) + "x" + gameLine.substring(idx + 1);
}
if (result.equalsIgnoreCase("miss")) {
score -= 1;
}
System.out.println();
}
// Play Again? [but only if 'alwaysReplay' holds true]
if (alwaysReplay) {
String res = helper.getAnything("<< Press ENTER to play again >>\n"
+ "<< or enter 'q' to quit >>");
if (res.equalsIgnoreCase("q")) {
System.out.println("Quiting with an overall score of: " + score + " ... Bye-Bye");
break;
}
System.out.println();
}
}
}
}
GameHelper.java - The GameHelper class:
import java.util.Scanner;
public class GameHelper {
private final Scanner in = new Scanner(System.in);
public String getUserInput(String prompt, String responseType, int... minMAX) {
int min = 0, max = 0;
if (minMAX.length == 2) {
min = minMAX[0];
max = minMAX[1];
}
if (minMAX.length > 0 && min < 1 || max < 1) {
throw new IllegalArgumentException("\n\ngetUserInput() Method Error! "
+ "The optional parameters 'min' and or 'max' can not be 0!\n\n");
}
String response = "";
while (response.isEmpty()) {
if (prompt.trim().endsWith("-->")) {
System.out.print(prompt);
}
else {
System.out.println(prompt);
}
response = in.nextLine().trim();
if (responseType.matches("(?i)\\b(int|integer|float|double)\\b")) {
if (!response.matches("-?\\d+(\\.\\d+)?") ||
(responseType.toLowerCase().startsWith("int") && response.contains("."))) {
System.err.println("Invalid Entry (" + response + ")! Try again...");
response = "";
continue;
}
}
// Check entry range value if the entry is to be an Integer
if (responseType.toLowerCase().startsWith("int")) {
int i = Integer.parseInt(response);
if (i != 0 && (i < min || i > max)) {
System.err.println("Invalid Entry (" + response + ")! Try again...");
response = "";
}
}
}
return response;
}
public String getUserInput(String prompt, String responseType, boolean allowNothing, int... minMAX) {
int min = 0, max = 0;
if (minMAX.length == 2) {
min = minMAX[0];
max = minMAX[1];
}
if (minMAX.length > 0 && min < 1 || max < 1) {
throw new IllegalArgumentException("\n\ngetUserInput() Method Error! "
+ "The optional parameters 'min' and or 'max' can not be 0!\n\n");
}
String response = "";
while (response.isEmpty()) {
if (prompt.trim().endsWith("-->")) {
System.out.print(prompt);
}
else {
System.out.println(prompt);
}
response = in.nextLine().trim();
if (response.isEmpty() && allowNothing) {
return "";
}
if (responseType.matches("(?i)\\b(int|integer|float|double)\\b")) {
if (!response.matches("-?\\d+(\\.\\d+)?") ||
(responseType.toLowerCase().startsWith("int") && response.contains("."))) {
System.err.println("Invalid Entry (" + response + ")! Try again...");
response = "";
continue;
}
}
// Check entry range value if the entry is to be an Integer
if (responseType.toLowerCase().startsWith("int")) {
int i = Integer.parseInt(response);
if (i != 0 && (i < min || i > max)) {
System.err.println("Invalid Entry (" + response + ")! Try again...");
response = "";
}
}
}
return response;
}
public String getAnything(String prompt) {
if (prompt.trim().endsWith("-->")) {
System.out.print(prompt);
}
else {
System.out.println(prompt);
}
return in.nextLine().trim();
}
}
Battleship.java - The Battleship class:
import java.util.ArrayList;
public class Battleship {
private ArrayList<Integer> locationCells;
public void setLocationCells(java.util.ArrayList<Integer> loc) {
locationCells = loc;
}
// Overload Method (Java8+)
public void setLocationCells(int[] loc) {
locationCells = java.util.stream.IntStream.of(loc)
.boxed()
.collect(java.util.stream.Collectors
.toCollection(java.util.ArrayList::new));
}
/*
// Overload Method (Before Java8)
public void setLocationCells(int[] loc) {
// Clear the ArrayList in case it was previously loaded.
locationCells.clear();
// Fill the ArrayList with integer elements from the loc int[] Array
for (int i = 0; i < loc.length; i++) {
locationCells.add(loc[i]);
}
}
*/
/**
* Completely removes one supplied Integer value from all elements
* within the supplied Integer Array if it exist.<br><br>
*
* <b>Example Usage:</b><pre>
*
* {#code int[] a = {103, 104, 100, 10023, 10, 140, 2065};
* a = removeFromArray(a, 104);
* System.out.println(Arrays.toString(a);
*
* // Output will be: [103, 100, 10023, 10, 140, 2065]}</pre>
*
* #param srcArray (Integer Array) The Integer Array to remove elemental
* Integers from.<br>
*
* #param intToDelete (int) The Integer to remove from elements within the
* supplied Integer Array.<br>
*
* #return A Integer Array with the desired elemental Integers removed.
*/
public static int[] removeFromArray(int[] srcArray, int intToDelete) {
int[] arr = {};
int cnt = 0;
boolean deleteIt = false;
for (int i = 0; i < srcArray.length; i++) {
if (srcArray[i] != intToDelete) {
arr[cnt] = srcArray[i];
cnt++;
}
}
return arr;
}
public String checkYourself(int userInput) {
String result = "MISS";
int index = locationCells.indexOf(userInput);
if (index >= 0) {
locationCells.remove(index);
if (locationCells.isEmpty()) {
result = "KILL";
}
else {
result = "HIT";
}
}
return result;
}
}
I am developing java application using Eclipse for text recognition from image using Asprise Library. In my maven project POM.xml file I have included this dependencies
<dependency>
<groupId>com.asprise.ocr</groupId>
<artifactId>java-ocr-api</artifactId>
<version>15.3.0.3</version>
</dependency>
The important jar files has already been downloaded to my project as it can be seen in the given picture. If i try to make an Ocr object i am getting this error.
Ocr cannot be resolved.
I am new to maven in Eclipse. I have no idea what is wrong in this. My complete code is shown here
package com.asprise;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import com.asprise.ocr.Ocr;
public class AspriseOCR {
static long startTime;
static long EndTime;
static double tPeriod;
static double ElapsedTime;
private static double totalTime = 0;
private static double correctImgs = 0;
static double averageTime = 0;
static double strMatch;
static double accuracy = 0;
public static void main(String[] args) {
try {
Ocr.setUp();
Ocr ocr = new Ocr();
ocr.startEngine("eng", Ocr.SPEED_FASTEST);
String groundTruthLine = "";
BufferedReader br = new BufferedReader(new FileReader("F:\\ground_truth.txt"));
int numOfImges = 100;
for (int i=1; i <=numOfImges; i++ )
{
System.out.println("\t\t\timg( " + i + ") \t\t\t" );
groundTruthLine = br.readLine();
String path2 = "F:\\img (" + i + ").png";
startTime = System.currentTimeMillis();
String recognizedText = ocr.recognize(new File[] {new File(path2)},
Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT);
EndTime = System.currentTimeMillis();
tPeriod = EndTime - startTime;
ElapsedTime = tPeriod/1000.0;
matchString(groundTruthLine, recognizedText, ElapsedTime);
System.out.println();
System.out.println();
System.out.println("***************************************************************************");
}
br.close();
System.out.println("Average Time " + ElapsedTime/numOfImges);
System.out.println("Average Accuracy " + (accuracy/numOfImges));
ocr.stopEngine();
}catch(Exception e)
{
}
}
private static void matchString(String groundTruth, String result, double elapsedTime) {
String replacedText = result.replaceAll("\n", "");
int gTruthLenth = groundTruth.length();
int detectedText = replacedText.length();
if (detectedText > (gTruthLenth * 2)) {
replacedText = replacedText.substring(0, gTruthLenth * 2);
}
strMatch = StringMatchingViaEditDist(replacedText, groundTruth, replacedText.length(), groundTruth.length());
double imgAccuracy = ((groundTruth.length() - strMatch)/ groundTruth.length());
System.out.println("Ground Truth :: " + groundTruth);
System.out.println("Returned Text :: " + replacedText );
System.out.println("Match Found :: " + imgAccuracy);
totalTime += elapsedTime;
accuracy = accuracy + imgAccuracy;
}
private static int min(int x,int y,int z)
{
if (x<y && x<z) return x;
if (y<x && y<z) return y;
else return z;
}
static int StringMatchingViaEditDist(String str1 , String str2 , int m ,int n)
{
// If first string is empty, the only option is to
// insert all characters of second string into first
if (m == 0) return n;
// If second string is empty, the only option is to
// remove all characters of first string
if (n == 0) return m;
// If last characters of two strings are same, nothing
// much to do. Ignore last characters and get count for
// remaining strings.
if (str1.charAt(m-1) == str2.charAt(n-1))
return StringMatchingViaEditDist(str1, str2, m-1, n-1);
// If last characters are not same, consider all three
// operations on last character of first string, recursively
// compute minimum cost for all three operations and take
// minimum of three values.
return 1 + min ( StringMatchingViaEditDist(str1, str2, m, n-1), // Insert
StringMatchingViaEditDist(str1, str2, m-1, n), // Remove
StringMatchingViaEditDist(str1, str2, m-1, n-1) // Replace
);
}
}
In my program, I have three variables: when one of these variables reaches 100, it must appear the words "variable came first to the finish line."
How do I organize the arrival of the second and third variable, so they come out like this:
variable1-arrived first
variable2-finished second
variable3 finished third
Help!
public Corsa(String name)
{
this.name = name;
System.out.println("Start: " + name);
System.out.println("---------------");
}
public void run()
{
while(finita == false)
{
try
{
avanza = (int) (Math.random()*20+1);
percorso = percorso + avanza;
System.out.println(name + " has path " + percorso + " meters");
if(percorso < 100)
{
System.out.println("---------------");
sleep = (int) (Math.random()*20+1);
Thread.sleep(sleep);
}
else
{
System.out.println("---------------");
System.out.println("---------------");
System.out.println(name + " came in first");
finita = true;
}
}
catch(InterruptedException e){}
Thread.yield();
}
}
}
I haven't tested this (so it might not even compile), but something like the following should work:
public class myRace
{
private int distance = 100;
private float offset = 20;
public int runners[3];
public void run()
{
// Set all runners to 0
for ( int i = 0; i < runners.length; i++ )
runners[i] = 0;
// Run the race and stop when at least 1 runner has reached the distance...
boolean finished = false;
while ( !finished )
{
for ( int i = 0; i < runners.length; i++ )
{
runners[i] += (int)((Math.random() * offset) + 1);
if ( runners[i] >= distance ) finished = true;
}
}
// Race finished now sort the runners
TreeMap<String, int> ranking = new TreeMap<String, int>();
for ( int i = 0; i < runners.length; i++ )
{
// A TreeMap is sorted on its key, not the value!
// The runners number is tagged on, just in case two runners have finished on the same distance.
String sortedKey = Integer.toString(runners[i]) + "." + Integer.toString(i);
ranking.put(sortedKey, i);
}
// Print the results
int pos = 1;
for ( Map.Entry entry : ranking.entrySet() )
{
String key = entry.getKey();
String distance = key.subString(0, key.indexOf(".")); // chop off the "." + runners number.
System.out.println("#" + pos + // position
"." + entry.getValue() + // who
", Distance = " + distance); // distance covered
pos++; // this does take in account whether multiple runners finished on the same distance.
}
}
}
I've got some problems with the topological sorting. It can find lops, but it counts some of the tasks (or "nodes" if you want to call it) several times. I think the problem is something with how I read or the Edge class, but I just can't see where it goes wrong. Any help would be really appreciated :)
enter code here
import java.util.*;
import java.io.*;
import java.lang.*;
class Task {
int id, time, staff;
int depA, depB;
String name;
int eStart, lStart;
Edge outEdge;
int cntPredecessors;
boolean visited;
Task(int id, String name, int time, int staff) {
this.id = id;
this.name = name;
this.time = time;
this.staff = staff;
visited = false;
}
public String getName() {
return name;
}
public String toString() {
return name;
}
}
class Edge {
Task id, name, time, staff;
Edge neste;
Task fra, til;
Edge(Task id) {
this.id = id;
}
}
class Input {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("enter a filename!");
System.exit(1);
} else if (args.length == 1) {
String fil = args[0]+".txt";
LesFraFil(fil);
// skrivUt();
topSort();
} else {
System.out.println("too many parameters, try again...");
}
}
static int antTask;
static Task[] ids;
static int tTid;
static void LesFraFil(String fil) {
int i = 0;
int j;
try {
String lest;
Scanner in = new Scanner(new FileReader(fil));
Edge til;
int counter = 0;
antTask = in.nextInt();
ids = new Task[antTask];
System.out.println(antTask);
while (in.hasNextLine()) {
lest = in.nextLine();
// hvis tom linje, så hopper den over
if(lest.trim().length() == 0) continue;
String split[] = lest.split("\\s+");
int id = Integer.parseInt(split[0]);
String act = split[1];
int tid = Integer.parseInt(split[2]);
int staff = Integer.parseInt(split[3]);
int depA = Integer.parseInt(split[4]);
tTid += tid;
ids[i] = new Task(id, act, tid, staff);
j = 4;
/*
* Lesingen av inputen skal avbrytes når den leser 0.
* j er den som holder på hvor langt vi er i split arrayet
* når den møter på 0
*/
while(split[j].compareTo("0") != 0) {
int tmp = Integer.parseInt(split[j])-1;
// System.out.println(tmp+1 + " Aktivitetens navn : " + act); //+ " tiden aktiviteten tar tid: " + tid + " avhengihet: " + split[j]);
j++;
if (ids[tmp] == null) {
ids[tmp] = new Task(id, act, tid, staff);
ids[tmp].visited = true;
}
ids[i].cntPredecessors++;
if(ids[tmp].outEdge == null) {
ids[tmp].outEdge = new Edge(ids[i]);
} else {
til = ids[tmp].outEdge;
while(til.neste != null) {
til = til.neste;
}
til.neste = new Edge(ids[i]);
}
}
counter++;
i++;
}
if (antTask == counter) {
System.out.println("Lesinga gikk som planlagt av fil: " + fil);
System.out.println("Total arbeidstid: " + tTid);// + antTask + " == " + counter );
} else {
System.out.println("Noe gikk galt avslutter!");
System.out.println(antTask + " || " + counter);
System.exit(2);
}
in.close();
} catch (Exception e) {
System.err.println("ERROR!" + e.getMessage());
}
}
static void skrivUt() {
for (Task sort : ids) {
System.out.print(sort.id + " " + sort.name);
Edge til = sort.outEdge;
while (til != null) {
System.out.print(" " + til.id.id);
til = til.neste;
}
System.out.println();
}
}
static void topSort() {
LinkedList<Task> list = new LinkedList<Task>();
ArrayList<Task> array = new ArrayList<Task>();
Task temp;
int count = 0;
int totalTime = 0;
// Legger taskene i lista
for (Task t : ids) {
if(t.cntPredecessors == 0) {
list.add(t);
totalTime += t.time;
// System.out.println(t);
t.visited = true;
}
}
for (Task t : ids) {
if(t.cntPredecessors == 1) {
list.add(t);
totalTime += t.time;
// System.out.println(t);
t.visited = true;
}
}
// går i evig løkke til lista er tom.
while (!list.isEmpty()) {
temp = list.pop(); // fjerner elementet fra lista
array.add(temp); // legger inn i arraylisten
count++;
// System.out.println(temp);
for(Edge til = temp.outEdge; til!=null;til=til.neste) {
til.id.cntPredecessors--;
if(til.id.cntPredecessors==0) {
list.add(til.id);
}
}
}
if(count < antTask) {
System.out.println("A loop has been found. Terminating...");
System.exit(0);
}
System.out.println("Topological sort: " + Arrays.toString(array.toArray()));// den sorterte "arraylisten"
System.out.println("Total time spend: " + totalTime);
}
} // End class Input
Here is an example of an input file
8
1 Build-walls 4 2 5 0
2 Build-roofs 6 4 1 0
3 Put-on-wallpapers 1 2 1 2 0
4 Put-on-tiles 1 3 2 0
5 Build-foundation 4 2 0
6 Make-floor 2 2 5 0
7 Put-carpet-floor 4 2 6 2 0
8 Move-in 4 4 3 7 0
The problem is with this loop (inside topSort()):
for (Task t : ids) {
if(t.cntPredecessors == 1) {
list.add(t);
totalTime += t.time;
// System.out.println(t);
t.visited = true;
}
}
You just need to remove it.
Reason: this loop adds to list nodes that have 1 incoming edge. Later (in the while loop), it is possible that for these nodes the cntPredecessors field will be decreased to 0 which will make them being pushed back onto list, thus counted twice.
In the future, please try to narrow down your code to something that contains less "noise", that is: the smallset (or nearly smallest) code that illustrates the problem. This will ease the understanding on potential answerers (not to mention that it may help you see the problem yourself).
I am creating a table of contents, and what I have is a Map of product numbers to pages. So an entry might look like this:
ABC123 => [59, 58, 57, 19, 36, 15, 33, 34, 13, 39, 11, 37, 38, 21, 20, 40, 63, 60, 45, 46, 22, 23, 24, 26, 3, 2, 10, 1, 7, 6, 5, 4, 8]
What I want to get from this is:
1-8,10,11,13,15,19-24,26,33,34,36-38,40,45,46,57-60
I can code this of course, but I figured that someone else has already solved this problem. My Googling has yielded naught.
I appreciate any help you can offer, as always!
You could collect the numbers into a sorted set and then iterate over the numbers.
Quick and dirty example:
SortedSet<Integer> numbers = new TreeSet<Integer>();
numbers.add( 1 );
numbers.add( 2 );
numbers.add( 3 );
numbers.add( 6 );
numbers.add( 7 );
numbers.add( 10 );
Integer start = null;
Integer end = null;
for( Integer num : numbers ) {
//initialize
if( start == null || end == null ) {
start = num;
end = num;
}
//next number in range
else if( end.equals( num - 1 ) ) {
end = num;
}
//there's a gap
else {
//range length 1
if( start.equals( end )) {
System.out.print(start + ",");
}
//range length 2
else if ( start.equals( end - 1 )) {
System.out.print(start + "," + end + ",");
}
//range lenth 2+
else {
System.out.print(start + "-" + end + ",");
}
start = num;
end = num;
}
}
if( start.equals( end )) {
System.out.print(start);
}
else if ( start.equals( end - 1 )) {
System.out.print(start + "," + end );
}
else {
System.out.print(start + "-" + end);
}
Yields: 1-3,6,7,10
Apache Commons has the IntRange type that you can use. Unfortunately I didn't find a good corresponding set of utilities to create them. Here's the basic approach you could use:
//create a list of 1-integer ranges
List<IntRange> ranges = new LinkedList<IntRange>();
for ( int pageNum : pageNums ) {
ranges.add(new IntRange(pageNum));
}
//sort the ranges
Collections.sort(ranges, new Comparator<IntRange>() {
public int compare(IntRange a, IntRange b) {
return Integer.valueOf(a.getMinimumInteger()).compareTo(b.getMinimumInteger());
}
});
List<IntRange> output = new ArrayList<IntRange>();
if ( ranges.isEmpty() ) {
return output;
}
//collapse consecutive ranges
IntRange range = ranges.remove(0);
while ( !ranges.isEmpty() ) {
IntRange nextRange = ranges.remove(0);
if ( range.getMaximumInteger() == nextRange.getMinimumInteger() - 1 ) {
range = new IntRange(range.getMinimumInteger(), nextRange.getMaximumInteger());
} else {
output.add(range);
range = nextRange;
}
}
output.add(range);
Alternatively you could skip the first step and create the ranges directly from the sorted list of page numbers.
Edit: A better description:
I had to deal with something similar to support a sorted collection of finite ranges, I used a mix of Google's Guava Range class and binary search to insert the element at the corresponding range or create a new singleton Range (A range with 1 element), eventually with more inserts the ranges have chances of expanding (Or shrinking/splitting in case of removal), removal is pretty fast because locating the corresponding range where the element is uses a binary search:
import com.google.common.collect.DiscreteDomains;
import com.google.common.collect.Lists;
import com.google.common.collect.Range;
import com.google.common.collect.Ranges;
import java.util.Collection;
import java.util.List;
public class IntRangeCollection
{
private int factor=10;
private List<Range<Integer>> rangeList=null;
public IntRangeCollection()
{
rangeList=Lists.newArrayListWithExpectedSize(1000);
}
public IntRangeCollection(final int size)
{
rangeList=Lists.newArrayListWithExpectedSize(size);
}
public IntRangeCollection(final int size, final int factor)
{
rangeList=Lists.newArrayListWithExpectedSize(size);
this.factor=factor;
}
protected IntRangeCollection(final List<Range<Integer>> rangeList)
{
this.rangeList=rangeList;
}
public static IntRangeCollection buildIntRangesCollectionFromArrays(final List<Integer[]> arrays)
{
final List<Range<Integer>> rangeList=Lists.newArrayListWithCapacity(arrays.size());
for(Integer[] range : arrays){
rangeList.add(range.length == 1 ? Ranges.singleton(range[0]) : Ranges.closed(range[0], range[1]));
}
return new IntRangeCollection(rangeList);
}
public boolean addElements(final Collection<Integer> elements)
{
boolean modified=false;
for(Integer element : elements){
modified=addElement(element) || modified;
}
return modified;
}
public boolean removeElements(final Collection<Integer> elements)
{
boolean modified=false;
for(Integer element : elements){
modified=removeElement(element) || modified;
}
return modified;
}
public boolean addElement(final Integer element)
{
final Range<Integer> elementRange=Ranges.singleton(element);
if(rangeList.isEmpty()){
rangeList.add(elementRange);
} else{
int
start=0, mid=0,
end=rangeList.size() - 1;
Range<Integer> midRange=null;
while(start<=end){
mid=(start + end) / 2;
midRange=rangeList.get(mid);
if(midRange.contains(element)){
return false;
} else if(testLinkable(midRange, element)){
rangeList.set(mid, midRange.span(elementRange));
if(mid>0){
final Range<Integer> a=rangeList.get(mid - 1);
if(testLinkable(a, midRange)){
rangeList.set(mid - 1, a.span(midRange));
rangeList.remove(mid);
mid--;
}
}
if(mid<rangeList.size() - 1){
final Range<Integer> b=rangeList.get(mid + 1);
if(testLinkable(midRange, b)){
rangeList.set(mid, midRange.span(b));
rangeList.remove(mid + 1);
}
}
return true;
} else if(midRange.lowerEndpoint().compareTo(element)<0){
start=mid + 1;
} else{
end=mid - 1;
}
}
//noinspection ConstantConditions
rangeList.add(midRange.lowerEndpoint().compareTo(element)<0 ? mid + 1 : mid, elementRange);
}
return true;
}
public boolean removeElement(final Integer element)
{
final Range<Integer> elementRange=Ranges.singleton(element);
if(rangeList.isEmpty()){
rangeList.add(elementRange);
} else{
int
start=0, mid,
end=rangeList.size() - 1;
while(start<=end){
mid=(start + end) / 2;
final Range<Integer> midRange=rangeList.get(mid);
if(midRange.contains(element)){
final Integer
lower=midRange.lowerEndpoint(),
upper=midRange.upperEndpoint();
if(lower.equals(upper)){
rangeList.remove(mid);
} else if(lower.equals(element)){
rangeList.set(mid, Ranges.closed(element + 1, upper));
} else if(upper.equals(element)){
rangeList.set(mid, Ranges.closed(lower, element - 1));
} else{
rangeList.set(mid, Ranges.closed(element + 1, upper));
rangeList.add(mid, Ranges.closed(lower, element - 1));
}
return true;
} else if(midRange.lowerEndpoint().compareTo(element)<0){
start=mid + 1;
} else{
end=mid - 1;
}
}
}
return false;
}
public List<Integer> getElementsAsList()
{
final List<Integer> result=Lists.newArrayListWithExpectedSize(rangeList.size() * factor);
for(Range<Integer> range : rangeList){
result.addAll(range.asSet(DiscreteDomains.integers()));
}
return result;
}
public List<Integer[]> getRangesAsArray()
{
final List<Integer[]> result=Lists.newArrayListWithCapacity(rangeList.size());
for(Range<Integer> range : rangeList){
final Integer
lower=range.lowerEndpoint(),
upper=range.upperEndpoint();
result.add(lower.equals(upper) ? new Integer[]{lower} : new Integer[]{lower,upper});
}
return result;
}
public int getRangesCount()
{
return rangeList.size();
}
private boolean testLinkable(final Range<Integer> range, final Integer element)
{
return Ranges.closed(range.lowerEndpoint() - 1, range.upperEndpoint() + 1).contains(element);
}
private boolean testLinkable(final Range<Integer> a, final Range<Integer> b)
{
return Ranges.closed(a.lowerEndpoint() - 1, a.upperEndpoint() + 1).isConnected(b);
}
#Override
public String toString()
{
return "IntRangeCollection{" +
"rangeList=" + rangeList +
'}';
}
public static void main(String[] args)
{
final int MAX_NUMBER=1000;
final long startMillis=System.currentTimeMillis();
final IntRangeCollection ranges=new IntRangeCollection();
for(int i=0; i<MAX_NUMBER; i++){
//noinspection UnsecureRandomNumberGeneration
ranges.addElement((int) (Math.random() * MAX_NUMBER));
}
System.out.println(MAX_NUMBER + " contained in " + ranges.rangeList.size() + " ranges done in " + (System.currentTimeMillis() - startMillis) + "ms");
System.out.println(ranges);
for(int i=0; i<MAX_NUMBER / 4; i++){
//noinspection UnsecureRandomNumberGeneration
ranges.removeElement((int) (Math.random() * MAX_NUMBER));
}
System.out.println(MAX_NUMBER + " contained in " + ranges.rangeList.size() + " ranges done in " + (System.currentTimeMillis() - startMillis) + "ms");
System.out.println(ranges);
}
}
You can use Arrays.sort() and find neighbouring duplicates/ranges. However I suspect TreeSet may be simpler to use.
This is a good example, it shows a simple way to accomplish this.