Recursive algorithm stops working after certain depth - java

I was exploring Fork/Join framework and its possible speed benefits through factorial counting, when discovered that my sequential recursive algorithm breaks at a certain point. To be precise, when I try to count 46342! the result from RecursiveCounter is wrong, but before that value it is always right and is the same that result from ParallelCounter and LoopCounter. Does anyone have an idea why that may happen?
Here are the classes:
RecursiveCounter:
public class RecursiveCounter implements FactorialCounter, RangeFactorialCounter {
#Override
public BigInteger count(int number) {
return count(1, number);
}
#Override
public BigInteger count(int from, int to) {
int middle = (from + to) >> 1;
BigInteger left;
BigInteger right;
if (middle - from > 1)
left = count(from, middle);
else
left = new BigInteger(String.valueOf(from * middle));
if (to - (middle + 1) > 1)
right = count(middle + 1, to);
else
right = to == middle + 1 ? new BigInteger(String.valueOf(to)) : new BigInteger(String.valueOf((middle + 1) * to));
return left.multiply(right);
}
}
LoopCounter:
public class LoopCounter implements FactorialCounter, RangeFactorialCounter {
#Override
public BigInteger count(final int number) {
return count(1, number);
}
#Override
public BigInteger count(final int from, final int to) {
BigInteger result = new BigInteger("1");
for (int i = from; i < to + 1; i++) {
result = result.multiply(new BigInteger(String.valueOf(i)));
}
return result;
}
}
A RecursiveTask for ParallelCounter:
public class FactorialTask extends RecursiveTask<BigInteger> {
private static final int THRESHOLD = 1000;
private RangeFactorialCounter iterativeCounter = new LoopCounter();
private Integer firstVal;
private Integer lastVal;
public FactorialTask(Integer from, Integer to) {
super();
this.firstVal = from;
this.lastVal = to;
}
#Override
protected BigInteger compute() {
return count(firstVal, lastVal);
}
private BigInteger count(int from, int to) {
int middle = (from + to) >> 1;
if (to - from > THRESHOLD) {
List<FactorialTask> tasks = Arrays.asList(new FactorialTask(from, middle), new FactorialTask(middle + 1, to));
tasks.forEach(RecursiveTask::fork);
return tasks.stream()
.map(RecursiveTask::join)
.map(BigInteger.class::cast)
.reduce(new BigInteger("1"), BigInteger::multiply);
} else {
return (from != to) ? countSequential(from, to) : new BigInteger(String.valueOf(from));
}
}
private BigInteger countSequential(int from, int to) {
return iterativeCounter.count(from, to);
}
}

In RecursiveCounter, from * middle and (middle + 1) * to might overflow, you need use BigInteger to manipulate them:
...
left = BigInteger.valueOf(from).multiply(BigInteger.valueOf(middle));
...
right = to == middle + 1 ? BigInteger.valueOf(to) : BigInteger.valueOf(to).multiply(BigInteger.valueOf(middle + 1));
Then you can get the same result in RecursiveCounter and LoopCounter:
LoopCounter loopCounter = new LoopCounter();
RecursiveCounter recursiveCounter = new RecursiveCounter();
BigInteger loopResult = loopCounter.count(46342);
BigInteger recursiveResult = recursiveCounter.count(46342);
System.out.println(loopResult.equals(recursiveResult)); // true

This happens because of numeric overflow of an int, not because of recursive depth, which is nicely controlled by your algorithm, which needs O(log2n) stack frames for recursion.
The overflow happens here:
new BigInteger(String.valueOf((middle + 1) * to))
When to is high, this value can overflow int. Specifically, when middle approaches to in the second "leg" of recursive invocations, you multiply 46341 by 46342, which yields -2147432674 due to an overflow (demo).
You can fix this by using only BigInteger for "payload" multiplication, i.e.
BigInteger.valueOf(middle+1).multiply(BigInteger.valueOf(to))

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", "");
}
}

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.

Null Pointer Exception in LinkedList Hash Table

So I'm creating a hash table with LinkedLists using the multiplication method. As an instance variable I define the LinkedList "T" that I'll be using, and in the constructor of the class I specify the size of T. However, every time I run my Driver testing class, I get NullPointerExceptions on everything I try to reference anything in T[]. Am I overlooking something? I've spent over an hour trying to figure it out.
ChainedHashTable class:
public class ChainedHashTable
{
private LinkedList<Integer>[] T;
private int m;
private double A;
public ChainedHashTable(int n)
{
for (m = 1; m < n; m *= 2);
T = new LinkedList[m];
Random random = new Random();
int s = random.nextInt(Integer.MAX_VALUE);
A = (s * 1.00) / Integer.MAX_VALUE;
}
public void insert(Integer key)
{
T[hash(key)].add(Integer.valueOf(key));
}
public void delete(int key)
{
T[hash(key)].remove(Integer.valueOf(key));
}
public Integer search(int key)
{
int n = T[hash(key)].indexOf(key);
if (n == -1)
return -1;
else
return T[hash(key)].get(n);
}
private int hash(int key)
{
System.out.println((int)(m * ((key * A) % 1)));
return (int)(m * ((key * A) % 1));
}
public void printTable()
{
for (int i = 0; i < T.length; i++)
{
System.out.println("index: " + i + " " + T[i]);
}
}
}
Driver class:
public class Driver
{
public static void main(String[] args)
{
ChainedHashTable test1 = new ChainedHashTable(20);
test1.printTable();
test1.insert(4);
test1.insert(54);
test1.insert(6);
test1.insert(3);
test1.insert(26);
test1.insert(54);
test1.insert(11);
test1.insert(10);
test1.insert(76);
test1.insert(42);
test1.insert(41);
test1.insert(32);
test1.insert(87);
test1.insert(76);
test1.insert(72);
test1.insert(57);
test1.insert(29);
test1.insert(16);
test1.insert(92);
test1.insert(64);
test1.printTable();
}
}
You are creating an array of references to type LinkedList and setting them to their initial state, which is null.
T = new LinkedList[m];
T now is an array of the computed size m. You need to initialize the objects inside of the array.
T = new LinkedList[m];
for (int i = 0; i < m; i++) {
T[i] = new LinkedList<>();
}

Java - Suitable data structure for search interval [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Does an open-ended interval implementation exist for Java?
I'm new to Java and i would like to know what is the best data structure and how can i search through that data structure for my case:
I have int intervals eg: 10-100, 200-500, 1000-5000 and for each interval i have a value 1, 2, 3, 4.
I would like to know how can i save all those intervals and their values in a data structure and how can i search through that data structure to return the value for the specific interval.
Eg. if i search 15, that is in interval 10-100, i would like to return 1.
Thank you
Use TreeMap, which is NavigableMap (Java 6 or higher).
Suppose you have entries key->value (10->1, 100->1, 200->2, 500->2, 1000->3, 5000->3)
floorEntry(15) will return 10->1
ceilingEntry(15) will return 100->1
With this you can determine the interval number of 15, which is 1.
You can also determine if a number is between intervals.
Edit: added example
TreeMap<Integer, Integer> map = new TreeMap<Integer, Integer>();
map.put(10, 1);
map.put(100, 1);
map.put(200, 2);
map.put(500, 2);
map.put(1000, 3);
map.put(5000, 3);
int lookingFor = 15;
int groupBelow = map.floorEntry(lookingFor).getValue();
int groupAbove = map.ceilingEntry(lookingFor).getValue();
if (groupBelow == groupAbove) {
System.out.println("Number " + lookingFor + " is in group " + groupBelow);
} else {
System.out.println("Number " + lookingFor +
" is between groups " + groupBelow + " and " + groupAbove);
}
I would use this approach:
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class IntervalsTest {
#Test
public void shouldReturn1() {
Intervals intervals = new Intervals();
intervals.add(1, 10, 100);
intervals.add(2, 200, 500);
int result = intervals.findInterval(15);
assertThat(result, is(1));
}
#Test
public void shouldReturn2() {
Intervals intervals = new Intervals();
intervals.add(1, 10, 100);
intervals.add(2, 200, 500);
int result = intervals.findInterval(201);
assertThat(result, is(2));
}
}
class Range {
private final int value;
private final int lowerBound;
private final int upperBound;
Range(int value, int lowerBound, int upperBound) {
this.value = value;
this.lowerBound = lowerBound;
this.upperBound = upperBound;
}
boolean includes(int givenValue) {
return givenValue >= lowerBound && givenValue <= upperBound;
}
public int getValue() {
return value;
}
}
class Intervals {
public List<Range> ranges = new ArrayList<Range>();
void add(int value, int lowerBound, int upperBound) {
add(new Range(value, lowerBound, upperBound));
}
void add(Range range) {
this.ranges.add(range);
}
int findInterval(int givenValue) {
for (Range range : ranges) {
if(range.includes(givenValue)){
return range.getValue();
}
}
return 0; // nothing found // or exception
}
}
If your intervals are mutually exclusive, a sorted map (java.util.TreeMap) using a comparator on the last member of the interval, and using firstKey on a tailMap on the searched item should work fine.
If the intervals may overlap, you need a segment tree (http://en.wikipedia.org/wiki/Segment_tree), of which there's no implementation in the standard library.
Use hashmap (fast, more memory) or List (slower, little memory). I provide you both solutions below:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class Interval {
private int begin;
private int end;
// 1, 2, 3, 4
private int value;
public Interval(int begin, int end, int value) {
this.begin = begin;
this.end = end;
this.value = value;
}
public int getBegin() {
return begin;
}
public void setBegin(int begin) {
this.begin = begin;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public boolean contains(int number) {
return (number > begin - 1) && (number < end + 1);
}
}
public class IntervalSearch {
// more memory consuming struct, fastest
Map<Integer, Interval> intervalMap = new HashMap<Integer, Interval>();
// less memory consuming, little slower
List<Interval> intervalList = new ArrayList<Interval>();
private boolean fastMethod = true;
public IntervalSearch(boolean useFastMethod) {
this.fastMethod = useFastMethod;
}
public Integer search(int number) {
return fastMethod ? searchFast(number) : searchSlow(number);
}
private Integer searchFast(int number) {
return intervalMap.get(number).getValue();
}
private Integer searchSlow(int number) {
for (Interval ivl : intervalList) {
if (ivl.contains(number)) {
return ivl.getValue();
}
}
return null;
}
public void addInterval(Integer begin, Integer end, Integer value) {
Interval newIvl = new Interval(begin, end, value);
if (fastMethod) {
addIntervalToMap(newIvl);
} else {
addIntervalToList(newIvl);
}
}
private void addIntervalToList(Interval newIvl) {
intervalList.add(newIvl);
}
private void addIntervalToMap(Interval newIvl) {
for (int i = newIvl.getBegin(); i < newIvl.getEnd() + 1; i++) {
intervalMap.put(i, newIvl);
}
}
public boolean isFastMethod() {
return fastMethod;
}
}
Your question is not entirely clear, particularly what you mean by the values 1, 2, 3, 4. But if you want a data structure that holds the limits of an interval, and checks if a number is within them, then make one! Like this:
public class Interval {
int low;
int high;
public Interval(int low, int high) {
this.low = low;
this.high = high;
}
public boolean intervalContains(int value) {
return ((value >= low) && (value <= high));
}
}
And use it:
Interval theInterval = new Interval(10,100);
System.out.print(theInterval.contains(15)); // prints "true"

Categories

Resources