I'm trying to call a divide method that's overridden from an interface class. All similar methods (add, subtract, multiply) work just fine, except divide for some reason isn't found. Here's what I have below:
Arithmetic Interface class
public interface Arithmetic {
public Object add(Object obj);
public Object subtract(Object obj);
public Object multiply(Object obj);
public Object divide(Object obj);
}
Number class (Arithmetic methods are overridden below, divide being the last one)
public class Number implements Comparable,Arithmetic{
/**
* A string representing a non-negative number
*/
private String value;
/**
* An integer greater than or equals to 2.
*/
private int base;
/**
* - for negative numbers and otherwise null
*/
private char sign;
/**
* creates 0 base 2.
*/
public Number()
{
value = "0";
base = 2;
}
/**
* creates a number in a specified based using the specified parameters.
* #param num a string representing a non-negative number with digit
* written in uppercase letters.
* #param radix the base of the number
*/
public Number(String num, int radix) throws InvalidNumberException
{
String list = ".-0123456ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Boolean pars = false;
for (int i = 0; i < list.length(); i++) {
if (num.indexOf(list.charAt(i)) != -1) {
pars = true;
}
}
if (radix < 1 || radix > 35) {
throw new InvalidNumberException("Number invoked with a radix less than 1 or greater than 35.");
} else if ((num.indexOf(".") != num.lastIndexOf(".")) || (num.indexOf("-") != num.lastIndexOf("-"))) {
throw new InvalidNumberException("Number invoked with more than one dash or period in string.");
} else if (num.indexOf("-") != 0) {
throw new InvalidNumberException("Number invoked with dash not at beginning of string.");
} else if (num.indexOf(".") == num.length()) {
throw new InvalidNumberException("Number invoked with period at end of string.");
}
else if (pars == true) {
throw new InvalidNumberException("Number invoked with invalid character.");
}
Boolean test=false;
for (int i = 0; i < num.length(); i++) {
if ((num.charAt(i) != '-') || (num.charAt(i) != '.')) {
if (toValue(num.charAt(i)) >= radix) {
test=true;
throw new InvalidNumberException("Number invoked with digit greater or equal to radix.");
}
}
}
if(test==false){
value = num;
base = radix;
}
}
/**
* Converts a digit to its integer equivalent
* #param digit 0...9 or A...Z to be converted
* #return the integer equivalent of the specified digit.
*/
private int toValue(char digit)
{
return Character.getNumericValue(digit);
}
/**
* Converts this integer to its equivalent digit
* #param anInt an integer between 0-35
* #return the digit equivalent to an integer
*/
private char toDigit(int anInt)
{
if(anInt >= 0 && anInt <= 9)
return (char)(anInt + 48);
else if(anInt >= 10 && anInt <= 35)
return (char)(anInt + 55);
else
return (char)(-1);
}
/**
* converts a number to its decimal equivalent (double).
* #return the decimal equivalent of a number
*/
private double toDouble()
{
if (base == 10)
return Double.parseDouble(value);
int periodIndex = value.indexOf('.');
double base10Num = 0;
int i;
int radix = base;
String whole;
if (periodIndex >=0)
whole = value.substring(0, periodIndex);
else
whole = value;
int j=0;
int wholeLength = whole.length();
for (i=wholeLength-1; i>=0; i--)
base10Num = base10Num + toValue(whole.charAt(i))*(int)Math.pow(radix,wholeLength-i-1);
if (periodIndex >= 0)
{
String fract = value.substring(periodIndex+1,value.length());
int fractLength = fract.length();
for (i=0; i<fractLength; i++)
{
base10Num = base10Num + toValue(fract.charAt(i))*Math.pow(radix,-i-1);
}
}
if (sign == '-')
base10Num *= -1;
return base10Num;
}
/**
* converts a decimal number (double) to its equivalent representation
* in a given base.
* #param dec the decimal (base 10) number
* #radix the base to convert the number to.
* #return the equivalent number in the specified base
*/
private Number doubleToNumber(double dec, int radix)
{
if (radix == 10)
return new Number(Double.toString(dec),radix);
String numSign="";
if (dec < 0)
{
numSign = "-";
dec = -dec;
}
int whole = (int)dec;
double fract = dec - whole;
String numStr = "";
while (whole != 0)
{
numStr = toDigit(whole%radix) + numStr;
whole = whole / radix;
}
if (fract != 0)
{
numStr += ".";
int tolerance = 20;
int precision = 0;
while (precision < tolerance && fract != 0)
{
fract = fract * radix;
numStr += toDigit((int)(fract));
precision++;
fract = fract - (int)fract;
}
}
return new Number(numSign+numStr,radix);
}
/**
* Gives a string representation of this number in the
* format number[base].
* #return a string representation of this number
*/
#Override
public String toString()
{
return String.format("%s%s[%d]", this.sign, this.value, this.base);
}
#Override
public boolean equals(Object obj)
{
if (!(obj instanceof Number))
return false;
return (this.toDouble()==((Number)obj).toDouble());
}
#Override
public int compareTo(Object obj) throws IllegalArgumentException
{
if (!(obj instanceof Number))throw new IllegalArgumentException();
else if(this.toDouble()<((Number)obj).toDouble()) return -1;
else if(this.toDouble()>((Number)obj).toDouble()) return 1;
else return 0;
}
/**
* This method adds two numbers from two different objects
* #param obj the number of the object inputted from user
* #return a new added number object
*/
#Override
public Object add(Object obj) throws IllegalArgumentException {
if (!(obj instanceof Number)) {
throw new IllegalArgumentException();
} else if (this.base != ((Number) obj).base) {
throw new IllegalArgumentException();
} else {
return doubleToNumber((this.toDouble() + ((Number) obj).toDouble()), ((Number) obj).base);
}
}
/**
* This method subtracts two numbers from two different objects
* #param obj the number of the object inputted from user
* #return a new subtracted number object
*/
#Override
public Object subtract(Object obj) throws IllegalArgumentException {
if (!(obj instanceof Number)) {
throw new IllegalArgumentException();
} else if (this.base != ((Number) obj).base) {
throw new IllegalArgumentException();
} else {
return doubleToNumber((this.toDouble() - ((Number)obj).toDouble()), ((Number) obj).base);
}
}
/**
* This method multiplies two numbers from two different objects
* #param obj the number of the object inputted from user
* #return a new multiplied number object
*/
#Override
public Object multiply(Object obj) throws IllegalArgumentException{
if (!(obj instanceof Number)) {
throw new IllegalArgumentException();
} else if (this.base != ((Number) obj).base) {
throw new IllegalArgumentException();
} else {
return doubleToNumber(this.toDouble() * ((Number)obj).toDouble(), ((Number) obj).base);
}
}
/**
* This method divides two numbers from two different objects
* #param obj the number of the object inputted from user
* #return a new divided number object
*/
#Override
public Object divide(Object obj) throws IllegalArgumentException {
if (!(obj instanceof Number)) {
throw new IllegalArgumentException();
} else if (this.base != ((Number) obj).base) {
throw new IllegalArgumentException();
} else if (((Number) obj).toDouble() == 0) {
throw new IllegalArgumentException();
} else {
return doubleToNumber((this.toDouble() / ((Number) obj).toDouble()), ((Number) obj).base);
}
}
}
And finally my demo class, NumberDemo
public class NumberDemo
{
public static void main(String[] args)
{
Number a = new Number("12.25", 8);
Number b = new Number("13.75", 8);
System.out.println(a.toString() + " + " + b.toString() + " = " +
a.add(b));
a = new Number("ABC.75", 16);
b = new Number("18.5F", 16);
Number c = new Number("2.FB", 16);
System.out.println("(" + a.toString() + " - " + b.toString() + ") / " +
c.toString() + " = " + (a.subtract(b)).divide(c));
a = new Number("3.45", 9);
b = new Number("32.25", 9);
c = new Number("3.05", 9);
System.out.println(a.toString() + "(" + b.toString() + " + " +
c.toString() + " = " + a.multiply(b.add(c)));
a = new Number("10111.11", 2);
b = new Number("1100110.01", 2);
c = new Number("-101", 2);
System.out.println("(" + a.toString() + " - " + b.toString() + ") / " +
c.toString() + " = " + (a.subtract(b)).divide(c));
a = new Number("-5", 8);
b = new Number("5", 8);
System.out.println(a.toString() + " x " + b.toString() + " = " +
a.multiply(b));
a = new Number("-0.5", 8);
b = a;
System.out.println(a.toString() + " x " + b.toString() + " = " +
a.multiply(b));
}
}
When I call all the arithmetic methods, they appear to be called just fine, however calling divide brings me the error tooltip:
cannot find symbol
symbol: method divide(Number)
location: class Object
I can't seem to find the reason for this, can anyone spot it?
This is my first time using Stockoverflow, so please let me know if anything's apart from the format norm.
Related
Thank you for everyone who got me on my feet. However, My cutSplice method is inefficient. I need to be able to modify it easy so that i can do the reverse method.
developing a single Java class (LinkedDnaStrand) that uses a linked list of nodes to represent a strand of DNA that supports splicing. Each node in the list will contain a string of one or more nucleotides (A, C, G, or T). The class will be responsible for operations such as append() and cutSplice(), which model real-world restriction enzyme processing.
EX. tt will be replaced with cat. (Better LinkedDnaStrandTester)
package dnasplicing;
public class DnaSequenceNode {
public String dnaSequence;
public DnaSequenceNode previous;
public DnaSequenceNode next;
public DnaSequenceNode(String initialDnaSequence) {
dnaSequence = initialDnaSequence;
}
}
package dnasplicing;
public class LinkedDnaStrand implements DnaStrand {
int nodeCount = 0;
int appendCount = 0;
long nucleotideCount = 0;
String sequenceString;
DnaSequenceNode cursor, head, tail;
public LinkedDnaStrand(String dnaSequence) {
DnaSequenceNode newNode = new DnaSequenceNode(dnaSequence);
head = newNode;
cursor = head;
tail = head;
head.previous = null;
tail.previous = null;
sequenceString = dnaSequence;
nodeCount++;
}
public String toString() {
String result = "";
DnaSequenceNode n = head;
while (n != null) {
result += n.dnaSequence;
n = n.next;
}
return result;
}
#Override
public long getNucleotideCount() {
nucleotideCount = sequenceString.length();
return nucleotideCount;
}
#Override
public void append(String dnaSequence) {
if (dnaSequence != null && dnaSequence.length() > 0) {
tail.next = new DnaSequenceNode(dnaSequence);
tail.next.previous = tail;
tail = tail.next;
sequenceString += dnaSequence;
appendCount++;
nodeCount++;
}
}
#Override
public DnaStrand cutSplice(String enzyme, String splicee) {
boolean frontSplice = false;
boolean backSplice = false;
if (sequenceString.startsWith(enzyme)) {
frontSplice = true;
}
if (sequenceString.endsWith(enzyme)) {
backSplice = true;
}
String[] dnaParts = sequenceString.split(enzyme);
LinkedDnaStrand newLinkedStrand = null;
if (frontSplice == true) {
newLinkedStrand = new LinkedDnaStrand(splicee);
// newLinkedStrand.append(dnaParts[0]);
for (int i = 1; i < dnaParts.length; i++) {
newLinkedStrand.append(dnaParts[i]);
if (i < dnaParts.length - 1) {
newLinkedStrand.append(splicee);
}
}
} else {
newLinkedStrand = new LinkedDnaStrand(dnaParts[0]);
for (int index = 1; index < dnaParts.length; index++) {
newLinkedStrand.append(splicee);
newLinkedStrand.append(dnaParts[index]);
}
}
if (backSplice == true) {
newLinkedStrand.append(splicee);
}
// sequenceString = newLinkedStrand.toString();
return newLinkedStrand;
}
#Override
public DnaStrand createReversedDnaStrand() {
// TODO Auto-generated method stub
return null;
}
#Override
public int getAppendCount() {
// TODO Auto-generated method stub
return appendCount;
}
#Override
public DnaSequenceNode getFirstNode() {
return head;
}
#Override
public int getNodeCount() {
return nodeCount;
}
}
package dnasplicing;
public interface DnaStrand {
/**
* NOTE: Your LinkedDnaStrand class must have a constructor that takes one parameter: String dnaSequence. When the
* constructor completes, your linked list should have just one node, and it should contain the passed-in
* dnaSequence. For example, if the following line of code was executed:
*
* LinkedDnaStrand strand = new LinkedDnaStrand("GATTACA");
*
* Then strand's linked list should look something like (previous pointers not shown):
*
* first -> "GATTACA" -> null
*
* The first line of this constructor should look like:
*
* public LinkedDnaStrand(String dnaSequence) {
*/
/**
* #return The entire DNA sequence represented by this DnaStrand.
*/
public String toString();
/**
* Returns the number of nucleotides in this strand.
*
* #return the number of base-pairs in this strand
*/
public long getNucleotideCount();
/**
* Appends the given dnaSequence on to the end of this DnaStrand. appendCount is incremented. Note: If this
* DnaStrand is empty, append() should just do the same thing as the constructor. In this special case, appendCount
* is not incremented.
*
* #param dnaSequence
* is the DNA string to append
*/
public void append(String dnaSequence);
/**
* This method creates a <bold>new</bold> DnaStrand that is a clone of the current DnaStrand, but with every
* instance of enzyme replaced by splicee. For example, if the LinkedDnaStrand is instantiated with "TTGATCC", and
* cutSplice("GAT", "TTAAGG") is called, then the linked list should become something like (previous pointers not
* shown):
*
* first -> "TT" -> "TTAAGG" -> "CC" -> null
*
* <b>NOTE</b>: This method will only be called when the linke list has just one node, and it will only be called
* once for a DnaStrand. This means that you do not need to worry about searching for enzyme matches across node
* boundaries.
*
* #param enzyme
* is the DNA sequence to search for in this DnaStrand.
*
* #param splicee
* is the DNA sequence to append in place of the enzyme in the returned DnaStrand
*
* #return A <bold>new</bold> strand leaving the original strand unchanged.
*/
public DnaStrand cutSplice(String enzyme, String splicee);
/**
* Returns a <bold>new</bold> DnaStrand that is the reverse of this strand, e.g., if this DnaStrand contains "CGAT",
* then the returned DnaStrand should contain "TAGC".
*
* #return A <bold>new</bold> strand containing a reversed DNA sequence.
*/
public DnaStrand createReversedDnaStrand();
/**
*
* #return The number of times that the DnaStrand has been appended via a call to append() or during the cutSplice()
* operation. Note that the very first time that a DnaStrand is given a DNA sequence is not to be counted as
* an append.
*/
public int getAppendCount();
/**
* This is a utility method that allows the outside world direct access to the nodes in the linked list.
*
* #return The first DnaSequenceNode in the linked list of nodes.
*/
public DnaSequenceNode getFirstNode();
/**
* This is a utility method that allows the outside world to determine the number of nodes in the linked list.
*
* #return
*/
public int getNodeCount();
}
package sbccunittest;
import static java.lang.Math.*;
import static java.lang.System.*;
import static org.apache.commons.lang3.StringUtils.*;
import static org.junit.Assert.*;
import java.io.*;
import org.apache.commons.lang3.*;
import org.junit.*;
import dnasplicing.*;
// Updated 25-Feb-2016 at 6:10pm
public class LinkedDnaStrandTester {
static String ecoliSmall = "AGCTTTTCATTAGCCCGCAGGCAGCCCCACACCCGCCGCCTCCTGCACCGAGAGAGATGGAATAAAGCCCTTGAACCAGC";
static String ecor1 = "GAATTC"; // restriction enzyme
public static int totalScore = 0;
public static int extraCredit = 0;
public static InputStream defaultSystemIn;
public static PrintStream defaultSystemOut;
public static PrintStream defaultSystemErr;
public static String newLine = System.getProperty("line.separator");
public void testCutSplice() {
String enzyme = "GAT";
String splicee = "TTAAGG";
String[] strands = { "TTGATCC", "TCGATCTGATTTCCGATCC", "GATCTGATCTGAT" };
String[][] recombinants = { { "TT", "TTAAGG", "CC" },
{ "TC", "TTAAGG", "CT", "TTAAGG", "TTCC", "TTAAGG", "CC" },
{ "TTAAGG", "CT", "TTAAGG", "CT", "TTAAGG" } };
for (int ndx = 0; ndx < strands.length; ndx++) {
LinkedDnaStrand linkedStrand = new LinkedDnaStrand(strands[ndx]);
DnaStrand newlinkedStrand = linkedStrand.cutSplice(enzyme, splicee);
assertEquals("cutSplice(" + enzyme + ", " + splicee + ") failed at ndx = " + ndx, join(recombinants[ndx]),
newlinkedStrand.toString());
assertEquals("Append counts didn't match for ndx = " + ndx, recombinants[ndx].length - 1,
newlinkedStrand.getAppendCount());
// Verify that each node contains the correct DNA sequence
DnaSequenceNode node = newlinkedStrand.getFirstNode();
for (int nodeNdx = 0; nodeNdx < recombinants.length; nodeNdx++) {
assertNotNull("For strand " + ndx + ", there is no node at position " + nodeNdx, node);
assertEquals("For strand " + ndx + ", the sequences don't match at position " + nodeNdx,
recombinants[ndx][nodeNdx], node.dnaSequence);
node = node.next;
}
}
totalScore += 5;
}
/**
* Verifies that LinkedDnaStrand can model a cut and splice of (part of) the E Coli sequence using the ECoR1
* restriction enzyme and insulin as a splicee.
*/
#Test
public void testSpliceInsulinIntoEcoli() {
for (int testNumber = 1; testNumber <= 5; testNumber++) {
int startNdx = (int) (random() * 0.33 * ecoliSmall.length()); // Somewhere in the
// first third
int endNdx = ecoliSmall.length() - 1 - (int) (random() * 0.33 * ecoliSmall.length());
String ecoliPart = ecoliSmall.substring(startNdx, endNdx);
LinkedDnaStrand linkedStrand = new LinkedDnaStrand(ecoliPart);
SimpleDnaStrand simpleStrand = new SimpleDnaStrand(ecoliPart);
DnaStrand newL = linkedStrand.cutSplice(ecor1, insulin);
DnaStrand newS = simpleStrand.cutSplice(ecor1, insulin);
assertEquals(newS.toString(), newL.toString());
assertEquals(newS.getAppendCount(), newL.getAppendCount());
assertEquals(newS.getAppendCount(), newL.getNodeCount() - 1);
// Verify that the nodes exist
DnaSequenceNode node = newL.getFirstNode();
for (int ndx = 0; ndx < newL.getNodeCount(); ndx++) {
assertNotNull("There is no node at position " + ndx, node);
node = node.next;
}
}
totalScore += 10;
}
/**
* Verifies that LinkedDnaStrand can model a cut and splice efficiently.
*/
#Test
public void testSplicingTime() {
// First verify that the LinkedDnaStrand cutSplice works
int startNdx = (int) (random() * 0.33 * ecoliSmall.length()); // Somewhere in the first
// third
int endNdx = ecoliSmall.length() - 1 - (int) (random() * 0.33 * ecoliSmall.length());
String ecoliPart = ecoliSmall.substring(startNdx, endNdx);
LinkedDnaStrand linkedStrand = new LinkedDnaStrand(ecoliPart);
SimpleDnaStrand simpleStrand = new SimpleDnaStrand(ecoliPart);
String splicee = createRandomDnaSequence(1024 * 1024, 1024 * 1024);
DnaStrand newL = linkedStrand.cutSplice(ecor1, splicee);
DnaStrand newS = simpleStrand.cutSplice(ecor1, splicee);
assertEquals(newS.toString(), newL.toString());
assertEquals(newS.getAppendCount(), newL.getAppendCount());
// Now verify that it can cut and splice N times in less than T seconds
int numSplicings = 200;
double maxTime = 2.0;
double start = nanoTime();
for (int i = 0; i < numSplicings; i++)
newL = linkedStrand.cutSplice(ecor1, splicee);
double end = nanoTime();
double time = ((end - start) / 1e9);
// out.println("Time = " + time);
assertTrue("Time limit of " + maxTime + " seconds exceeded. Time to splice " + numSplicings + " times was "
+ time + " seconds.", time <= maxTime);
totalScore += 5;
}
/**
* Verifies that LinkedDnaStrand can create a new, reversed LinkedDnaStrand.
*/
#Test
public void testReverse() {
String dnaSequence = createRandomDnaSequence(50, 100);
String dnaToAppend = createRandomDnaSequence(5, 10);
int numTimesToAppend = (int) (random() * 10);
LinkedDnaStrand linkedStrand = new LinkedDnaStrand(dnaSequence);
SimpleDnaStrand simpleStrand = new SimpleDnaStrand(dnaSequence);
for (int ndx = 0; ndx < numTimesToAppend; ndx++) {
linkedStrand.append(dnaToAppend);
simpleStrand.append(dnaToAppend);
}
assertEquals(simpleStrand.toString(), linkedStrand.toString());
assertEquals(numTimesToAppend + 1, linkedStrand.getNodeCount());
LinkedDnaStrand rl = (LinkedDnaStrand) linkedStrand.createReversedDnaStrand();
// Verify that the original linked strand wasn't changed
DnaSequenceNode node = linkedStrand.getFirstNode();
int nodeNdx = 0;
while (node != null) {
assertEquals("Sequences don't match at node index " + nodeNdx, nodeNdx == 0 ? dnaSequence : dnaToAppend,
node.dnaSequence);
node = node.next;
nodeNdx++;
}
// Verify that the new strand string is reversed
assertEquals(simpleStrand.createReversedDnaStrand().toString(), rl.toString());
totalScore += 10;
// If the new strand has a reverse order of nodes and sequences within each node, give extra
// credit
int numNodes = linkedStrand.getNodeCount();
if (numNodes == rl.getNodeCount()) {
// Build array of reversed dna strings from original LinkedDnaStrand. Start at end of
// array and move toward
// start
node = linkedStrand.getFirstNode();
String[] reversedDnaSequences = new String[linkedStrand.getNodeCount()];
nodeNdx = numNodes - 1;
while (node != null) {
reversedDnaSequences[nodeNdx] = reverse(node.dnaSequence);
node = node.next;
nodeNdx--;
}
// Verify that the reversed list's nodes contain the same data as in the array
node = rl.getFirstNode();
nodeNdx = 0;
while (node != null) {
if (!node.dnaSequence.equals(reversedDnaSequences[nodeNdx]))
break;
node = node.next;
nodeNdx++;
}
if (nodeNdx == linkedStrand.getNodeCount())
extraCredit += 5;
}
}
private String[] createRandomDnaSequences(int numDnaSequences, int minLength, int maxLength) {
String[] dnaSequences = new String[numDnaSequences];
for (int ndx = 0; ndx < numDnaSequences; ndx++)
dnaSequences[ndx] = createRandomDnaSequence(minLength, maxLength);
return dnaSequences;
}
private String createRandomDnaSequence(int minLength, int maxLength) {
return RandomStringUtils.random((int) (random() * (maxLength - minLength) + minLength), "ACGT");
}
#BeforeClass
public static void beforeTesting() throws Exception {
totalScore = 0;
extraCredit = 0;
}
#AfterClass
public static void afterTesting() {
out.println("Estimated score (w/o late penalties, etc.) = " + totalScore);
out.println("Estimated extra credit (assuming on time submission) = " + extraCredit);
}
#Before
public void setUp() throws Exception {
defaultSystemIn = System.in;
defaultSystemOut = System.out;
defaultSystemErr = System.err;
}
#After
public void tearDown() throws Exception {
System.setIn(defaultSystemIn);
System.setOut(defaultSystemOut);
System.setErr(defaultSystemErr);
}
public void sendToStdinOfTestee(String message) {
System.setIn(new ByteArrayInputStream(message.getBytes()));
}
}
So I don't have some of the classes like the node class you are using so I cannot write the actual code but i will give you some pseudo code.
public String toString(){
String result = "";
Node n = start;
while(n != null){
string += n.data;
}
return result;
}
public long getNucleotideCount() {
long result = 0;
Node n = start;
while(n != null){
result += n.data.length();
}
return result;
}
public void append(String dnaSequence) {
end.next = new Node(dnaSequence);
end = end.next;
appendCount++;
}
public DnaStrand cutSplice(String enzyme, String splice) {
// For this I think it would be best to assemble into string then use replace
Node n = start;
String result = "";
while(n != null){
result += n.data;
}
result = result.replace(enzyme, splice)
return new DnaStrand(result);
}
The reverse method would be similar to cutSplice. Assemble to string, manipulate, then return new strand. If you need more help LMK.
I plan in JavaFX a new Game 'Number-Shape-System'. Basically its a little memory game where pictures are associated with numbers. So '2'='Swan', '5'='Hand(Fingers)' and so on. So the player see the exercise 'Swan + Fingers = ?'.
What I want is all possible mathematically operations following rules:
/*
* Generate all possible mathematical operations to the console with the numbers
* 0-12, where every result is (>= 0 && <= 12).
* - Mathematical operations are '+', '-', '*' and '/'.
* - The rule 'dot before line' shouldn't be used, instead the operations will
* be executed from left to right.
* - Every among result must be between (>= 0 && <= 12) and a whole number.
* - Only different numbers are allowed for the operations (an operation have
* 2 numbers). For example 2+3 is allowed, 3*3 not.
*
* A solution with recursive methods would be preferred. I want the output for
* the length 2-10.
*
* Example output with different length:
* - Length 3: 2+3(=5)*2(=10)
* - Length 5: 2+3(=5)*2(=10)+2(=12)/4(=3)
*/
I have prepared a example implementation, but I don't know how to convert it to a recursive functionality.
import java.util.ArrayList;
import java.util.List;
public class Generator {
private static final List<Double> numbers = new ArrayList<>();
private static final List<String> operations = new ArrayList<>();
static {
numbers.add(0.0);
numbers.add(1.0);
numbers.add(2.0);
numbers.add(3.0);
numbers.add(4.0);
numbers.add(5.0);
numbers.add(6.0);
numbers.add(7.0);
numbers.add(8.0);
numbers.add(9.0);
numbers.add(10.0);
numbers.add(11.0);
numbers.add(12.0);
operations.add("+");
operations.add("-");
operations.add("*");
operations.add("/");
}
private int lineCounter = 0;
public Generator() {
this.init();
}
private void init() {
}
public void generate() {
// Length 2 ###########################################################
boolean okay = false;
int lineCounter = 0;
StringBuilder sbDouble = new StringBuilder();
for (Double first : numbers) {
for (Double second : numbers) {
for (String operation : operations) {
if (first == second) {
continue;
}
if (operation.equals("/") && (first == 0.0 || second == 0.0)) {
continue;
}
double result = perform(first, operation, second);
okay = this.check(result, operation);
if (okay) {
++lineCounter;
sbDouble = new StringBuilder();
this.computeResultAsString(sbDouble, first, operation, second, result);
System.out.println(sbDouble.toString());
}
}
}
}
System.out.println("Compute with length 2: " + lineCounter + " lines");
// Length 2 ###########################################################
// Length 3 ###########################################################
okay = false;
lineCounter = 0;
sbDouble = new StringBuilder();
for (Double first : numbers) {
for (Double second : numbers) {
for (String operation1 : operations) {
if (first == second) {
continue;
}
if (operation1.equals("/") && (first == 0.0 || second == 0.0)) {
continue;
}
double result1 = perform(first, operation1, second);
okay = this.check(result1, operation1);
if (okay) {
for (Double third : numbers) {
for (String operation2 : operations) {
if (second == third) {
continue;
}
if (operation2.equals("/") && third == 0.0) {
continue;
}
double result2 = perform(result1, operation2, third);
okay = this.check(result2, operation2);
if (okay) {
++lineCounter;
sbDouble = new StringBuilder();
this.computeResultAsString(sbDouble, first, operation1, second, result1);
this.computeResultAsString(sbDouble, operation2, third, result2);
System.out.println(sbDouble.toString());
}
}
}
}
}
}
}
System.out.println("Compute with length 3: " + lineCounter + " lines");
// Length 3 ###########################################################
// Length 4 ###########################################################
okay = false;
lineCounter = 0;
sbDouble = new StringBuilder();
for (Double first : numbers) {
for (Double second : numbers) {
for (String operation1 : operations) {
if (first == second) {
continue;
}
if (operation1.equals("/") && (first == 0.0 || second == 0.0)) {
continue;
}
double result1 = perform(first, operation1, second);
okay = this.check(result1, operation1);
if (okay) {
for (Double third : numbers) {
for (String operation2 : operations) {
if (second == third) {
continue;
}
if (operation2.equals("/") && third == 0.0) {
continue;
}
double result2 = perform(result1, operation2, third);
okay = this.check(result2, operation2);
if (okay) {
for (Double forth : numbers) {
for (String operation3 : operations) {
if (third == forth) {
continue;
}
if (operation3.equals("/") && forth == 0.0) {
continue;
}
double result3 = perform(result2, operation3, forth);
okay = this.check(result3, operation3);
if (okay) {
++lineCounter;
sbDouble = new StringBuilder();
this.computeResultAsString(sbDouble, first, operation1, second, result1);
this.computeResultAsString(sbDouble, operation2, third, result2);
this.computeResultAsString(sbDouble, operation3, forth, result3);
System.out.println(sbDouble.toString());
}
}
}
}
}
}
}
}
}
}
System.out.println("Compute with length 4: " + lineCounter + " lines");
// Length 4 ###########################################################
}
private boolean check(double result, String operation) {
switch (operation) {
case "+":
case "-":
case "*": {
if (result > 0 && result <= 12) {
return true;
}
break;
}
case "/": {
if (
(Math.floor(result) == result)
&& (result >= 0 && result <= 12)
) {
return true;
}
break;
}
}
return false;
}
private double perform(double first, String operation, double second) {
double result = 0.0;
switch (operation) {
case "+": { result = first + second; break; }
case "-": { result = first - second; break; }
case "*": { result = first * second; break; }
case "/": { result = first / second; break; }
}
return result;
}
private void computeResultAsString(StringBuilder sbDouble, String operation, double second, double result) {
sbDouble.append(operation);
sbDouble.append(second);
sbDouble.append("(=");
sbDouble.append(result);
sbDouble.append(")");
}
private void computeResultAsString(StringBuilder sbDouble, double first, String operation, double second, double result) {
sbDouble.append(first);
sbDouble.append(operation);
sbDouble.append(second);
sbDouble.append("(=");
sbDouble.append(result);
sbDouble.append(")");
}
public static void main(String[] args) {
final Generator generator = new Generator();
generator.generate();
}
}
As you can see in your own code, for each increase in "length", you have to nest another block of the same code. With a dynamic length value, you can't do that.
Therefore, you move the block of code into a method, and pass in a parameter of how many more times it has to "nest", i.e. a remainingLength. Then the method can call itself with a decreasing value of remainingLength, until you get to 0.
Here is an example, using an enum for the operator.
public static void generate(int length) {
if (length <= 0)
throw new IllegalArgumentException();
StringBuilder expr = new StringBuilder();
for (int number = 0; number <= 12; number++) {
expr.append(number);
generate(expr, number, length - 1);
expr.setLength(0);
}
}
private static void generate(StringBuilder expr, int exprTotal, int remainingLength) {
if (remainingLength == 0) {
System.out.println(expr);
return;
}
final int exprLength = expr.length();
for (int number = 0; number <= 12; number++) {
if (number != exprTotal) {
for (Operator oper : Operator.values()) {
int total = oper.method.applyAsInt(exprTotal, number);
if (total >= 0 && total <= 12) {
expr.append(oper.symbol).append(number)
.append("(=").append(total).append(")");
generate(expr, total, remainingLength - 1);
expr.setLength(exprLength);
}
}
}
}
}
private enum Operator {
PLUS ('+', Math::addExact),
MINUS ('-', Math::subtractExact),
MULTIPLY('*', Math::multiplyExact),
DIVIDE ('/', Operator::divide);
final char symbol;
final IntBinaryOperator method;
private Operator(char symbol, IntBinaryOperator method) {
this.symbol = symbol;
this.method = method;
}
private static int divide(int left, int right) {
if (right == 0 || left % right != 0)
return -1/*No exact integer value*/;
return left / right;
}
}
Be aware that the number of permutations grow fast:
1: 13
2: 253
3: 5,206
4: 113,298
5: 2,583,682
6: 61,064,003
7: 1,480,508,933
I cant seem to figure out what's wrong with my code. I commented out the reduce() method to see if it would work with the unreduced fractions (I don't think my reduce() works) and for the first ones it does work, but when it gets to double digits and the later ones I cant figure out why it isn't working.
public class Rational implements Comparable<Rational> {
private int numerator, denominator;
public Rational() { numerator = 1; denominator = 1; }
public Rational(int num, int denom) { numerator = num; denominator = denom; }
public void setRational(int num, int denom) { setNumerator(num); setDenominator(denom); }
public void setNumerator(int num) { numerator = num; }
public void setDenominator(int denom) { denominator = denom; }
public int getNumerator() { return numerator; }
public int getDenominator() { return denominator; }
public void reduce() {
setNumerator(this.numerator / gcd(this.numerator, this.denominator));
setDenominator(this.denominator / gcd(this.numerator, this.denominator));
}
public int gcd(int num1, int num2) {
if (num2 == 0) return num1;
return gcd(num2,num1 % num2);
}
public Object clone() { return new Rational(getNumerator(), getDenominator()); }
public boolean equals(Object obj){ return this.compareTo((Rational)obj) == 0; }
public void add(Rational other) {
this.setNumerator( (this.getNumerator() * other.denominator ) + ( other.numerator * this.getDenominator() ));
this.setDenominator( this.getDenominator() * other.denominator );
//reduce();
}
public void sub(Rational other) {
numerator = ( this.getNumerator() * other.getDenominator() ) - ( other.getNumerator() * this.getDenominator() );
denominator = ( this.getDenominator() * other.getDenominator() );
//reduce();
}
public void mult(Rational other) {
numerator = ( this.getNumerator() * other.getNumerator() );
denominator = ( this.getDenominator() * other.getDenominator() );
//reduce();
}
public void div(Rational other) {
numerator = (this.getNumerator() * other.getDenominator());
denominator = (this.getDenominator() * other.getNumerator());
//reduce();
}
public int compareTo(Rational other) {
reduce();
other.reduce();
if ( this.getDenominator() < other.getDenominator() ) {
return -1;
}
else if ( this.getDenominator() == other.getDenominator() ) {
if( this.getNumerator() < other.getNumerator() ) {
return -1;
}
else if( this.getNumerator() > other.getNumerator() ) {
return 1;
}
else return 0;
}
else return 1;
}
public String toString() {
return this.numerator + "/" + this.denominator + "\n";
}
}
this is the runner
import static java.lang.System.out;
public class RationalRunner {
public static void main(String args[]) {
Rational test = new Rational();
out.println("test = " + test);
Rational newOne = new Rational(3, 4);
out.println("newOne = " + newOne);
out.println("test.equals(newOne) = " + test.equals(newOne));
newOne = (Rational) test.clone();
out.println("\n\nnewOne after test.clone() = " + newOne);
out.println("test.equals(newOne) = " + test.equals(newOne));
Rational rOne = new Rational(1, 2);
Rational rTwo = new Rational(2, 3);
out.println("1/2.equals(2/3) = " + rOne.equals(rTwo));
test.setRational(4, 6);
out.println("2/3.equals(4/6) = " + rTwo.equals(test));
out.println("\n\nrOne = " + rOne);
out.println("rTwo = " + rTwo);
out.println("rOne.compareTo(rTwo) = " + rOne.compareTo(rTwo));
out.println("rTwo.compareTo(rOne) = " + rTwo.compareTo(rOne));
rOne.add(rTwo);
out.println("\n\nrOne.add(rTwo) = " + rOne);
rOne.setRational(1, 2);
rTwo.setRational(1, 3);
rOne.add(rTwo);
out.println("\n\n1/2.add(1/3) = " + rOne);
rOne.setRational(4, 10);
rTwo.setRational(3, 5);
rOne.add(rTwo);
out.println("\n\n4/10.add(3/5) = " + rOne);
rOne.setRational(2, 10);
rTwo.setRational(3, 6);
rOne.add(rTwo);
out.println("\n\n2/10.add(3/6) = " + rOne);
//1/4 + 2/8 = 1/2
rOne.setRational(1, 4);
rTwo.setRational(2, 8);
out.println("\n\n1/4.equals(2/8) = " + rOne.equals(rTwo));
rOne.add(rTwo);
out.println("\n\n1/4.add(2/8) = " + rOne);
//1/6 + 2/8 = 5/12
rOne.setRational(1, 6);
rTwo.setRational(2, 8);
out.println("\n\n1/6.equals(2/8) = " + rOne.equals(rTwo));
rOne.add(rTwo);
out.println("\n\n1/6.add(2/8) = " + rOne);
}
}
For example, when you set one of them to 1/6 and 2/8, it comes up with 14/48 when it should be 20/48. I have tried retyping the add method and trying a different way, but it still comes out with the 14/48, im not sure why
As your example, when i comment out .equals() method, it return the correct value.
So, i check your .compareTo() method and find out, you reduce on raw data. It's means after compare, the value of rOne and rTwo was modified.
You should clone object and calculate on them
Rational num1 = new Rational(numerator, denominator);
Rational num2 = new Rational(other.getNumerator(), other.getDenominator());
I've correct them:
public int compareTo(Rational other) {
//Should create copy constructor
Rational num1 = new Rational(numerator, denominator);
Rational num2 = new Rational(other.getNumerator(), other.getDenominator());
num1.reduce();
num2.reduce();
if (num1.getDenominator() < num2.getDenominator()) {
return -1;
} else if (num1.getDenominator() == num2.getDenominator()) {
if (num1.getNumerator() < num2.getNumerator()) {
return -1;
} else if (num1.getNumerator() > num2.getNumerator()) {
return 1;
} else {
return 0;
}
} else {
return 1;
}
}
P/s: I just check with your example. So any calculator is wrong, you can correct on the same way.
Hi for one of my assignments I had to make an ackermann simulator in Java and I was having trouble. The assignment was to create three variations of the ackermann project, one regular, one recursive and one through a table lookup. well, I've done all that but the part that I'm struggling with is the creating a menu for it part. I'm not sure how to access each class when I select an option from the menu. do I need a main class for every single class or one for all of them? Here is my code and I guess my biggest question is how do I get user input when I select a version of the ackermann from the menu, thank you very much.
Here is my menu:
import java.util.Scanner;
public class AckMenu
{
public static void main(String [] args) throws InterruptedException
{
Scanner scan = new Scanner(System.in);
int choiceNumber = 0;
introduction();
while (choiceNumber != 4)
{
printMenuChoices();
choiceNumber = readChoiceNumber();
switch (choiceNumber)
{
case 1:
//
AckermannValue.Ack(3,3);
break;
case 2:
AckermannTrace.Ack(1,3);
break;
case 3:
AckermannTableLookup.getValue();
break;
default:
System.out.println("The game is over.");
choiceNumber = 4;
break;
}//switch
}//while
}
private static void introduction()
{
System.out.println("\n\n" +
" This program allows you to call the Ackermann function.");
System.out.println("\n\n" + "Please choose one of the versions of the Ackermann function.");
}
private static void printMenuChoices()
{
System.out.println(""+
"1) Ackermann Value.\n"+
"2) Ackermann Trace.\n"+
"3) Ackermann Table Lookup.\n"+
"4) Quit.");
}
private static int readChoiceNumber()
{
Scanner scan = new Scanner(System.in);
int choiceNumber;
String indent = " ";
System.out.println("please enter the number of the method you want to call");
choiceNumber = scan.nextInt();
while(choiceNumber < 1 || choiceNumber > 4)
{
System.out.println(indent + "the number must be 1 through 4");
System.out.println(indent + " please enter a proper choice. ");
choiceNumber = scan.nextInt();
}
return choiceNumber;
}
}
and my 3 methods, first the regular version with no recursion.
import java.util.Scanner;
public class AckermannValue {
//public static void AckMethod() throws InterruptedException {
//static int count = 0;
public static int Ack(int m, int n) {
if (m < 0 || n < 0) {
throw new IllegalArgumentException("Non-negative args only!");
}
if (m == 0)
{
//count++;
//System.out.println("count: " + count + " M: " + m + " N: " + n);
return n + 1;
}
else if (n == 0)
{
//count++;
// System.out.println("count: " + count + " M: " + m + " N: " + n);
return Ack(m-1, 1);
}
else {
//count++;
//System.out.println("count: " + count + " M: " + m + " N: " + n);
return Ack(m-1, Ack(m,n-1));
}
}
//public static void main (String args [] ) {
//System.out.println(Ack(3,7));
//}
}
//}
Recursive method
import java.util.Scanner;
public class AckermannTrace {
static int count = 0;
public static int Ack(int m, int n) {
if (m < 0 || n < 0) {
throw new IllegalArgumentException("Non-negative args only!");
}
if (m == 0)
{
count++;
System.out.println("count: " + count + " M: " + m + " N: " + n);
return n + 1;
}
else if (n == 0)
{
count++;
System.out.println("count: " + count + " M: " + m + " N: " + n);
return Ack(m-1, 1);
}
else {
count++;
System.out.println("count: " + count + " M: " + m + " N: " + n);
return Ack(m-1, Ack(m,n-1));
}
}
//public static void main (String args [] ) {
//System.out.println(Ack(3,7));
//}
}
The table lookup version of the ackermann
import java.util.Hashtable;
public class AckermannTableLookup {
/**
* The table containing the values of <i>Ackermann</i>'s function.
*/
private Hashtable<Integer, Hashtable<Integer, Integer>> table;
/**
* Constructs a new table, computing all values of <i>Ackermann</i>'s
* function <i>A(i, j)</i> that are <i>n</i> or less.
*
* #param n
* the maximum value of the new table
*/
public void AckermannTable(int n) {
// construct new table
table = new Hashtable<Integer, Hashtable<Integer, Integer>>();
// set first value
int i = 1;
int j = 2;
setValue(1, 1, 2);
while (true) {
int newValue = -1;
// compute next entry
if (i == 1) {
newValue = getValue(i, j - 1) * 2;
} else {
newValue = getValue(i - 1, getValue(i, j - 1));
}
if (newValue > n || newValue == -1) {
if (j == 1) {
// no single entry in this row - return
return;
} else {
// go to the next row
i++;
j = 1;
}
} else {
// save the computed value
setValue(i, j, newValue);
j++;
}
}
}
/**
* Returns the value of <i>Ackermann</i>'s function <i>A(i, j)</i>, if it
* is <i>n</i> or less, and <code>-1</code> otherwise.
*
* #param i
* the first parameter for <i>Ackermann</i>'s function
* #param j
* the second parameter for <i>Ackermann</i>'s function
* #return
* <i>A(i, j)</i>
*/
public int getValue(int i, int j) {
if (j == 0) {
return 2;
} else {
if (table.containsKey(i)) {
Hashtable<Integer, Integer> rowI = table.get(i);
if (rowI.containsKey(j)) {
return rowI.get(j);
} else {
return -1;
}
} else {
return -1;
}
}
}
/**
* Returns the inverse value of <i>Ackermann</i>'s function <i>A(m, n)</i>.
*
* #param m
* the first parameter for the inverse <i>Ackermann</i>'s function
* #param n
* the second parameter for the inverse <i>Ackermann</i>'s function
* #return
* the inverse of <i>A(m, n)</i>
*/
public int getInverse(int m, int n) {
if (n >= 4) {
int j = 0;
while (2 * getValue(m, j) <= n && getValue(m, j) != -1) {
j++;
}
return j - 1;
} else if (m >= n) {
int i = 1;
while (getValue(i, (int)Math.floor(m / n)) != -1) {
i++;
}
return i;
}
return -1;
}
/**
* Adds the passed value of <i>Ackermann</i>'s function <i>A(i, j)</i> to
* this table.
*
* #param i
* the first parameter for <i>Ackermann</i>'s function
* #param j
* the second parameter for <i>Ackermann</i>'s function
* #param value
* <i>A(i, j)</i>
*/
private void setValue(int i, int j, int value) {
if (!table.containsKey(i)) {
table.put(i, new Hashtable<Integer, Integer>());
}
Hashtable<Integer, Integer> rowI = table.get(i);
rowI.put(j, value);
}
}
Make sure all your classes are in the same package.
Then either make all your methods static to call them by their class names(in your lookup table class) OR
You just need to modify your switch statement.
Don't call the Ack by its classname. First create an object of its class and then call that function. For example in case1 :
AckermannValue object1 = new AckermannValue();
object1.Ack(3,3);
Now your program will run fine.
The goal of the program is to find the prime-numbers below a certain maximum.
the cancelNonPrimes() method acts like it's working (in the step-by-step debugger) but just does not write the false-values to the list...
public class Era2
{
int m;
int i;
boolean[] list;
/**
* Constructor for objects of class Era2
*/
public Era2(int max) {
m = max;
list = new boolean[m];
initialize();
}
/**
* Constructor for objects of class Era2 with standard-maximum-value = 25
*/
public Era2() {
m = 25;
list = new boolean[m];
initialize();
}
/**
* Method for initializing an object: all values to true except 0 and 1
*/
void initialize() {
while (i < m) {
setList(i, true);
i = i + 1;
}
setList(0, false);
setList(1, false);
}
/**
* Method for setting a bool to a number on the list
*/
void setList(int p, boolean b) {
list[p] = b;
}
/**
* Method for reading the entire list, printed in terminal
*/
void getList() {
for (int p = 0; p < m; p++){
if (readList(p) == true){
System.out.println(p + "true");
}
else {
System.out.println(p + "false");
}
}
}
/**
* Method for reading a specific shizl on the list
*/
boolean readList(int p) {
return list[p];
}
/**
* Method for setting all non-primes to false
*/
void cancelNonPrimes() {
i = 2;
while (i < m) {
if (readList(i) == true) {
int c = i;
int n = 2;
while (c < m) {
c = (i * n);
setList(c, false);
n = n + 1;
}
}
i = i + 1;
}
}
}