How to shorten (format) String output properly? - java

Simple questions as a beginner making big problems.
I want to shorten (format) a String to only show 1 decimal or 2. Unlucky it is a String not a double.
String getNumber = "6.000m";
I know there is a printf() function but as far I learned it is to print multiple string in a proper order.
How can I make the output to be with only one decimal or if it has more numbers which aren't 0?
6.000 m --> 6.0
4.900 m --> 4.9
4.750 m --> 4.75

I assume it is always "m" at the end with some optional whitespace in front of it. So I remove it first using a regex.
DecimalFormat is your friend to do the rest:
import java.text.DecimalFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Ff {
static Pattern numberPart=Pattern.compile("([0-9.]*)\\b*m");
static DecimalFormat df=new DecimalFormat("0.0#####");
public static String format(String input)
{
Matcher m=numberPart.matcher(input);
if(m.matches())
{
return df.format(Double.parseDouble(m.group(1)));
}
return null;
}
public static void main(String args[]) {
System.out.println(format("6.000m"));
System.out.println(format("4.900m"));
System.out.println(format("4.750m"));
}
}
and the output is:
6.0
4.9
4.75

You shouldn't use regex, because it is very hard to maintain.
As an example:
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-
\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")#(?:
(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-
5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|
[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\
[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
This is a part of some code to validate an email with a regex. Regexes were necessary back then when computers were slow, because regexes are fast. Nowadays you don't need them anymore and maintenance is key.
After using the test cases:
0.000 m -> 0.0
1.000 m -> 1.0
9.000 m -> 9.0
1.100 m -> 1.1
1.900 m -> 1.9
1.110 m -> 1.11
1.010 m -> 1.01
1.111 m -> 1.111
1.101 m -> 1.101
1.101m -> 1.101
I've come to this conclusion:
shortenGivenNumber(String wholeNumber); will be the Method you'll use to shorten your number. The other methods are there to make the main method more readable.
public class NumberShortener {
public String shortenGivenNumber(String wholeNumber) {
int endOfShortNumber = findEndOfNumber(wholeNumber);
String shortenedNumber = cutOutNumber(wholeNumber, endOfShortNumber);
return shortenedNumber;
}
private int findEndOfNumber(String numberWithZeroesAndM) {
int lastZero = findIndexOfZeroAfterNumber(numberWithZeroesAndM);
int endOfNumber = lastZero;
endOfNumber = handleNo0AtEndCase(numberWithZeroesAndM, lastZero, endOfNumber);
return endOfNumber;
}
private int findIndexOfZeroAfterNumber(String wholeNumber) {
int lastZero;
int searchIndex = 3;
boolean numberAfterZero;
do {
numberAfterZero = false;
lastZero = findNextIndexOfZero(wholeNumber, searchIndex);
numberAfterZero = isANumberAfterThisZero(wholeNumber, lastZero);
searchIndex++;
}while(numberAfterZero == true && valueExistsAtEnd(lastZero));
return lastZero;
}
private int findNextIndexOfZero(String wholeNumber, int searchIndex) {
return wholeNumber.indexOf("0", searchIndex);
}
private boolean isANumberAfterThisZero(String wholeNumber, int lastZero) {
boolean numberAfterZero = false;
for(int i = 1; i < 10; i++){
char characterAfterZero = getCharacterAfterZero(wholeNumber, lastZero);
char iAsChar = convertIntToChar(i);
if(isTheCharacterThisNumber(characterAfterZero, iAsChar)){
numberAfterZero = true;
}
}
return numberAfterZero;
}
private boolean valueExistsAtEnd(int lastZero) {
return lastZero != -1;
}
private int handleNo0AtEndCase(String wholeNumber, int lastZero, int endOfNumber) {
if(thisSignIsntAtEnd(lastZero)){
int indexOfSpace = getIndexOfSpace(wholeNumber);
endOfNumber = indexOfSpace;
endOfNumber = handleNoSpaceAtEndCase(wholeNumber, endOfNumber, indexOfSpace);
}
return endOfNumber;
}
private int getIndexOfSpace(String wholeNumber) {
return wholeNumber.indexOf(" ");
}
private int handleNoSpaceAtEndCase(String wholeNumber, int endOfNumber, int space) {
if(thisSignIsntAtEnd(space)) {
int indexOfM = getIndexOfM(wholeNumber);
endOfNumber = indexOfM;
}
return endOfNumber;
}
private int getIndexOfM(String wholeNumber) {
return wholeNumber.indexOf("m");
}
private char getCharacterAfterZero(String wholeNumber, int indexOfZero) {
int indexAfterZero = indexOfZero+1;
return wholeNumber.charAt(indexAfterZero);
}
private char convertIntToChar(int i) {
return (char) (i+48);
}
private String cutOutNumber(String wholeNumber, int endOfNumber) {
return wholeNumber.substring(0, endOfNumber);
}
private boolean isTheCharacterThisNumber(char characterAfterZero, char iAsChar) {
return characterAfterZero == iAsChar;
}
}
It always copies the first 3 characters(x.x). The first 0 (after the x.x), without any number following, will be used as the last index which indicates the end of the final number substring. If there are numbers over 0 until the end, it will use the space (1.123 m). If there isn't a space, it will use the m (1.123m).

Related

Calculator for metric distance from an expression that contains different scales

public enum Operator {
PLUS("+"),
MINUS("-");
private final String operator;
Operator(String operator) {
this.operator = operator;
}
public String getOperator() {
return operator;
}
public static Operator getByValue(String operator) {
for (Operator operatorEnum : Operator.values()) {
if (operatorEnum.getOperator().equals(operator)) {
return operatorEnum;
}
}
throw new IllegalArgumentException("Invalid value");
}
}
//////////
public enum MetricConvertor {
m(1000),
cm(10),
mm(1),
km(1000000),
dm(100);
private int scale;
MetricConvertor(int scale) {
this.scale = scale;
}
public int getScale() {
return scale;
}
}
/////////
public class Application {
public static void main(String[] args) {
int scale = MetricConvertor.valueOf("m").getScale();
}
I wan to create a calculator that is capable of computing a metric distance value from an expression that contains different scales and systems.
Output should be specified by the user.
Only Addition and subtraction is allowed.
Output is in lowest unit.
Expression: 10 cm + 1 m - 10 mm
Result: 1090 mm
I am stuck at this point, how can I add or substract the values for a list and convert them at the lowest scale sistem( eg above mm, but it can be dm if are added for example dm + m + km)
Here is solution
split each string by add/minus and add it to appropriate list
split number and metric in each list(can use matcher) and sum it
result = sumAdd - sumMinus(mm).
Please optimize it, because i don't have time to optimize this code, I need to go to bed :D
Result is in mm, so you have to get lowest metric and recaculate it(leave it to you).
private static int caculator(String exp) {
List<String> addList = new ArrayList<>();
List<String> minusList = new ArrayList<>();
int checkPoint = 0;
boolean op = true;//default first value is plus
// Split string with add/minus
for (int i = 1; i < exp.length(); i++) {
String s = exp.substring(i, i + 1);
if (Operator.PLUS.getOperator().equals(s)) {
checkOperator(addList, minusList, op, exp.substring(checkPoint, i).trim());
checkPoint = i + 1;
op = true;
continue;
}
if (Operator.MINUS.getOperator().equals(s)) {
checkOperator(addList, minusList, op, exp.substring(checkPoint, i).trim());
checkPoint = i + 1;
op = false;
continue;
}
}
// Add last string
checkOperator(addList, minusList, op, exp.substring(checkPoint).trim());
// Get sum each list
int sumAdd = sumList(addList);
int sumMinus = sumList(minusList);
return sumAdd - sumMinus;
}
//sum a list
private static int sumList(List<String> addList) {
int sum = 0;
for (String s: addList) {
String[] arr = s.split(" ");
int value = Integer.parseInt(arr[0]);
int scale = MetricConvertor.valueOf(arr[1]).getScale();
sum += value * scale;
}
return sum;
}
// check operator to put into approriate list
private static void checkOperator(List<String> addList, List<String> minusList, boolean op, String substring) {
if (op) {
addList.add(substring);
} else {
minusList.add(substring);
}
}

Polynomial program not working as expected

So I Created a class Term. This class represents a term of a polynomial such as 2x4 where 2 is coefficient and 4 is exponent of the
term.
Data members:-
int coefficient
int exponent
public class Term2 {
private int coefficient;
private int exponent;
public Term2() {
coefficient = 0;
exponent = 0;
}
public Term2(int coefficient, int exponent) {
this.coefficient = coefficient;
this.exponent = exponent;
}
public int getCoefficient() {
return coefficient;
}
public void setCoefficient(int coefficient) {
this.coefficient = coefficient;
}
public int getExponent() {
return exponent;
}
public void setExponent(int exponent) {
this.exponent = exponent;
}
}
then I Created another class called Polynomial. The internal representation of a polynomial is an array of Terms. The size of this array should be fixed. I
Provided a constructor for this class that will set all terms of a polynomial object as zero (where coefficient is 0 and exponent is 0).
then I created a funtion called
setTerm(int, int)
which Setting a term of a polynomial object. Each successive call of
this function should set next term of the polynomial object.
package javaapplication2;
import java.util.Scanner;
public class Polynomials {
private Term2 terms[];
private int valueLength = 0;
public Polynomials(int termSize) {
terms = new Term2[termSize];
for (int i = 0; i < terms.length; i++) {
terms[i] = new Term2(0, 0);
}
}
public void setTerm(int c, int e) {
if (valueLength >= terms.length) {
System.out.println("big");
return;
}
terms[valueLength++] = new Term2(c, e);
if (e > 0) {
for (int i = 0; i < terms.length; i++) {
terms[i] = new Term2(c, e);
}
}
}
public static void main(String[] args) {
int n;
System.out.println("Enter the number of terms : ");
Scanner in = new Scanner(System.in);
n = in.nextInt();
Polynomials p = new Polynomials(n);
p.setTerm(2, 3);
Term2 t = new Term2();
}
}
STUCKED
is the code structure is correct as I am not able to get the expected output in addtion i also want to achieve the two below funtionality
1.sort() ñ to arrange the terms in ascending order of exponents.
Provide a function to print a polynomial object
please suggest me the best solution
OUTPUT
run:
Enter the number of terms :
2
BUILD SUCCESSFUL (total time: 3 seconds)
The arrray is a too complicated data structure here. (Besides if (e > 0) { ... } messes things up.)
Either a Map from exponent to Term2 or to the coefficient.
public class Polynomials {
private SortedMap<Integer, Term2> termsByExponent = new TreeMap<>();
public Polynomials() {
}
public void setTerm(int c, int e) {
termsByExponent.put(e, new Term2(c, e));
}
/**
* #param exp the exponent (not the index).
*/
public Term2 getTerm(int exp) {
return termsByExponent.computeIfAbsent(exp, e -> new Term2(0, e));
}
public Term2 getTermByIndex(int i) {
return termsByExponent.values().get(i);
}
public int size() {
return map.size();
}
#Override
public String toString() {
return termsByExponent.values().stream()
.map(t -> String.format("%s%d.x^%d",
t.getCoefficient() >= 0 ? "+" : "", // Minus already there.
t.getCoefficient(),
t.getExponent()))
.collect(Collectors.join(""))
.replaceFirst("\\.x\\^0\\b", "")
.replaceFirst("\\^1\\b", "");
}
}

Java variable with rest of substraction

I've got 2 integer values, e.g. a = 10 and b = 20.
Now i want to substract them: a - b, but as a result i don't want to have negative values, so in this example i want the result 0 and a new integer variable with the rest (10 here).
Two more examples:
Input: a=40, b=20; Expected Output:20
input: a=25 b=50 Expected Output: 0 and a new int var = 25
How to do this in java without external libraries?
From what I understand, you want a variable to be holding the result if the result is greater than or equal to 0. Otherwise, that variable should hold 0 and another variable will hold a positive value of the result.
If this is the case, consider the following code snippet:
int result = a -b;
int otherVariable = 0;
if (result < 0) {
otherVariable = -result;
result = 0;
}
int aMinusB = a-b;
int output = Math.max(aMinusB,0);
int rest = aMinusB < 0 ? Math.abs(aMinusB) : 0;
https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html
There are two ways to solve this problem: -
First: -
If you don't want to create a method to return this value and only to display it, then you can do it by printing out the results of if-else block in the code below within the function itself.
Second: -
If you want to use the result somewhere else, go for an object based approach: -
// Main class
public class SubtractWithRest {
public static void main(String[] args) {
SubtractResultWithRest subtractResultWithRest = new SubtractResultWithRest();
subtraction(10, 20, subtractResultWithRest);
System.out.println("Result: " + subtractResultWithRest.getResult());
System.out.println("Rest: " + subtractResultWithRest.getRest());
}
private static void subtraction(int num1, int num2, SubtractResultWithRest subtractResultWithRest) {
if (num2 > num1) {
subtractResultWithRest.setResult(0);
subtractResultWithRest.setRest(num2 - num1);
} else {
subtractResultWithRest.setResult(num1 - num2);
}
}
}
// Object class
public class SubtractResultWithRest {
private int result;
private int rest = 0;
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public int getRest() {
return rest;
}
public void setRest(int rest) {
this.rest = rest;
}
}

How to calculate value of math expression and check user answer?

Any help or advice would be greatly appreciated. I'm dooing a simple game which generates ten different, random questions. The questions can be composed from 2, 3 or 4 integers.Something like this: 552 − 4 − 101, 102 / 3 / 3, 589 − 281, 123 + 56 + 2.
The question will be displayed in a textview and then the user can take a guess, entering values into an edittext and then upon clicking a key on a custom keypad, it will check the answer, and then display the next question until it reaches 10 questions. I have a problem with imputing the answer from the code i have. No matter what i do here i cant input the answer to the randomly generated expression.
public enum Operator {
PLUS("+"), MINUS("-"), MULTIPLIER("*"), DIVIDER("/");
private String displayValue;
private Operator(String displayValue) {
this.displayValue = displayValue;
}
public String getDisplayValue() {
return displayValue;
}}
public class Question{
private List<QuestionElement> questionElements;
public Question(int sizeOfQuestionElemets) {
questionElements = new ArrayList<QuestionElement>(sizeOfQuestionElemets);
}
public void addElement(QuestionElement questionElement) {
questionElements.add(questionElement);
}
public List<QuestionElement> getElements() {
return questionElements;
}
public int size() {
return questionElements.size();
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (QuestionElement questionElement : questionElements) {
sb.append(questionElement);
}
return sb.toString().trim();
}
}
public class QuestionElement {
private int value;
private Operator operator;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Operator getOperator() {
return operator;
}
public void setOperator(Operator operator) {
this.operator = operator;
}
#Override
public String toString() {
return value + (operator == null ? "" : " " + operator.getDisplayValue()) + " ";
}
}
public class RandomQuestions {
static QuestionElement q = new QuestionElement();
private static final int NUMBER_OF_QUESTIONS = 10;
private static final int MIN_QUESTION_ELEMENTS = 2;
private static final int MAX_QUESTION_ELEMENTS = 2;
private static final int MIN_QUESTION_ELEMENT_VALUE = 1;
private static final int MAX_QUESTION_ELEMENT_VALUE = 20;
private final Random randomGenerator = new Random();
public List<Question> getGeneratedRandomQuestions() {
List<Question> randomQuestions = new ArrayList<>(NUMBER_OF_QUESTIONS);
int randomQuestionElementsCapacity = getRandomQuestionElementsCapacity();
Question question = new Question(randomQuestionElementsCapacity);
for (int j = 0; j < randomQuestionElementsCapacity; j++) {
boolean isLastIteration = j + 1 == randomQuestionElementsCapacity;
QuestionElement questionElement = new QuestionElement();
questionElement.setValue(getRandomQuestionElementValue());
questionElement.setOperator(isLastIteration ? null
: Operator.values()[randomGenerator.nextInt(Operator.values().length)]);
question.addElement(questionElement);
}
randomQuestions.add(question);
return randomQuestions;
}
private int getRandomQuestionElementsCapacity() {
return getRandomIntegerFromRange(MIN_QUESTION_ELEMENTS, MAX_QUESTION_ELEMENTS);
}
private int getRandomQuestionElementValue() {
return getRandomIntegerFromRange(MIN_QUESTION_ELEMENT_VALUE, MAX_QUESTION_ELEMENT_VALUE);
}
private int getRandomIntegerFromRange(int min, int max) {
return randomGenerator.nextInt(max - min + 1) + min;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
RandomQuestions questionGenerator = new RandomQuestions();
List<Question> randomQuestions = questionGenerator.getGeneratedRandomQuestions();
for (Question question : randomQuestions) {
System.out.println(""+ question+"=?");
int answer = input.nextInt();
if (answer == q.getValue()) {
System.out.println("CORRECT");
}else{
System.err.println("STILL NOT WORKING");
}
}
}
}
In your main() you are printing question, reading an answer from the user and then comparing the answer to q.getValue(). q is a question element that is not related to question and always has value 0. So the trick is to answer 0 no matter what the question is, then the program will print CORRECT. :-)
I haven’t found anywhere in your code where you are calculating the correct value of the math expression. This would probably be a good first step towards checking whether the user has indeed entered the correct result.
Calculating the correct result is not really trivial if we insist on taking operator precedence into account. 4 + 3 * 2 should be 10 (not 14). I believe that reading about the Shunting-yard algorithm should get you some of the way. It’s an algorithm for parsing a math expression, which is only the first step towards calculating its value, but still a first step.
I suggest that the object-oriented approach will be that the Question object knows how to check an answer. Here is an implementation of the algorithm, simplified to the four operators, but extended to actually do the calculation:
public boolean checkAnswer(int answer) {
// calculate correct answer
// use shunting yard algorithm
Deque<Integer> outputQueue = new ArrayDeque<>();
Deque<Operator> operatorStack = new ArrayDeque<>();
for (QuestionElement element : questionElements) {
outputQueue.push(element.getValue());
Operator op = element.getOperator();
if (op != null) {
while (!operatorStack.isEmpty() && op.getPrecedence() <= operatorStack.peek().getPrecedence()) {
int operand2 = outputQueue.pop();
int operand1 = outputQueue.pop();
outputQueue.push(operatorStack.pop().apply(operand1, operand2));
}
operatorStack.push(op);
}
}
while (!operatorStack.isEmpty()) {
int operand2 = outputQueue.pop();
int operand1 = outputQueue.pop();
outputQueue.push(operatorStack.pop().apply(operand1, operand2));
}
int result = outputQueue.pop();
assert outputQueue.isEmpty();
return answer == result;
}
You notice that I have put some new demands on your Operator enum too. It has a precedence. And the + operator must know how to do addition (through its apply method), and similarly for the other operators:
PLUS("+", 1) {
#Override
public int apply(int operand1, int operand2) {
return operand1 + operand2;
}
},
// etc.
public abstract int apply(int operand1, int operand2);
and so on. 1 is the precedence; * and / have higher precedence, for example 2.
Now in main() you just need to write:
if (question.checkAnswer(answer)) {
If you decide to explain to the user that strict left-to-right evaluation is applied, it’s getting somewhat simpler:
public boolean checkAnswer(int answer) {
// calculate correct answer
// do left to right calculation
int result = questionElements.get(0).getValue();
for (int elementIndex = 1; elementIndex < questionElements.size(); elementIndex++) {
Operator op = questionElements.get(elementIndex - 1).getOperator();
result = op.apply(result, questionElements.get(elementIndex).getValue());
}
return answer == result;
}
The operators still need to have the apply method, but they no longer need the precedence.

Recreate valueOf(double d) in Java's String class

I made an object, MyString. I can't figure out how to recreate valueOf(double d). I recreated valueOf for integers. Just to make it easier I limited the amount of decimal places to 8. How can I recreate valueOf(double d)?
public class MyString {
private char[] a;
public MyString(String s) {
this.a = s.toCharArray();
}
public MyString(char[] a) {
this.a = a;
}
public String toString() {
return new String(a);
}
public int length() {
return a.length;
}
public char charAt(int i) {
return a[i];
}
public static MyString valueOf(int i) {
int digits = (int)(Math.log10(i)+1);
char[] b = new char[digits];
for (int j = 0; j < digits; j++) {
b[j] = (char) (48 + i / 10);
i = i % 10;
if (i < 10) {
b[j + 1] = (char)(48 + i);
break;
}
}
MyString ms = new MyString(b);
return ms;
}
public static MyString valueOf(double d) {
char[] d1 = new char[digits];
//Take each digit of the number and enter it into the array
MyString ms = new MyString(d1);
return ms;
}
public static void main(String[] args) {
}
}
I assume you are doing this for fun... so here is the approach I took. You have valueOf(int i) already, so why not basically reuse that function. Just take the double and keep multiplying it by 10 until you have an int. Keep track of where the decimal place goes, then you basically call your valueOf(int i) but also include the decimal point.
I had trouble running your code so I re-did valueOf(int i) then created valueOf(int i, int decimalSpot), passing in -1 or 0 for the decimal spot then it's an integer value and don't use a decimal place.
Anyway, here is what I came up with. It's late, so probably not the cleanest code, but should give you a proof of concept.
public class MyString {
private char[] a;
public MyString(String s) {
this.a = s.toCharArray();
}
public MyString(char[] a) {
this.a = a;
}
public String toString() {
return new String(a);
}
public int length() {
return a.length;
}
public char charAt(int i) {
return a[i];
}
public static MyString valueOf(int i) {
return MyString.valueOf(i,-1);
}
public static MyString valueOf(double d) {
int decimalPlace = 0;
while (d != (int)d)
{
decimalPlace++;
d = d*10;
}
return MyString.valueOf((int)d,decimalPlace);
}
public static MyString valueOf(int i, int decimalSpot) {
int index=0;
int digits = (int)(Math.log10(i)+1);
int stringLength=digits;
if (decimalSpot == 0) decimalSpot=-1; // Don't return 1234. - just return 1234
if (decimalSpot != -1)
{
// Include an extra spot for the decimal
stringLength++;
}
char[] b = new char[stringLength];
for (int j = digits-1; j >= 0; j--) {
int power = (int) Math.pow(10,j);
int singleDigit = (int) Math.floor(i/power);
i = i - power*singleDigit;
b[index++] = (char) (48 + singleDigit);
if (decimalSpot==j)
{
b[index++] = '.';
}
}
MyString ms = new MyString(b);
return ms;
}
public static void main(String[] args) {
MyString ms = MyString.valueOf(12345);
System.out.println(ms);
ms = MyString.valueOf(12345.12313);
System.out.println(ms);
}
}
Rather than trying to solve this problem for every possible source datatype you should be just concentrating on constructing your class from a String. Then all you have to do is delegate this method and all the others you haven't done yet to the corresponding String method in each case, take the resulting String, and construct your object with that String.

Categories

Resources