Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.iml
.idea/
/out/
41 changes: 41 additions & 0 deletions src/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import factorial.FactorialCalculator;
import fibonacci.FibonacciSequencePrinter;
import numbersWriter.NumbersWriterInWords;

public class Main {

public static void main(String args[]) {
tests();
}

private static void tests() {
// test Fibonacci's number sequence
FibonacciSequencePrinter fibonacciSequencePrinter = new FibonacciSequencePrinter(10);
fibonacciSequencePrinter.print();
System.out.println("--------------------------------------------------");
fibonacciSequencePrinter.setLengthOfSequence(200);
fibonacciSequencePrinter.print();

System.out.println("==================================================");

// test factorial calculator
int testFactorialCalculateArray[] = {5, 50};
FactorialCalculator factorialCalculator = new FactorialCalculator();
for (int x : testFactorialCalculateArray) {
System.out.println("Factorial of " + x + " is "
+ factorialCalculator.calculate(x));
}

System.out.println("==================================================");

// test writing number in words
long[] testWriteInWordsArray = {4587l, -505l, 1000000000000001l, 30,
-1234567890l, 5278234857329573485l, 30109005l, 0};
NumbersWriterInWords numbersWriterInWords = new NumbersWriterInWords();
for (long number : testWriteInWordsArray) {
System.out.print("\nNumber " + number + " read as: ");
numbersWriterInWords.printNumberInWords(number);
}
}

}
79 changes: 79 additions & 0 deletions src/factorial/FactorialCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package factorial;

import java.math.BigInteger;

/**
* Class for calculating factorials
* @version 1.0
* @author Morhun N.
*/
public class FactorialCalculator {

/** the point of transition from long to BigInteger */
private static final long TRANSITION_POINT = 20;

/**
* Calculates factorial function.
* If result can be placed in {@code long} its used,
* otherwise {@code BigInteger} is used.
* @param arg factorial function argument
* @return factorial of argument
*/
public Number calculate(int arg) {
return factorialFactory(arg).calculate(arg);
}

private Factorial<?> factorialFactory(int arg) {
if (arg < 0) {
throw new IllegalArgumentException("Factorial argument must be non negative");
}
Factorial<?> factorial;
if (arg < TRANSITION_POINT) {
factorial = new FactorialLong();
} else {
factorial = new FactorialBigInteger();
}
return factorial;
}

private abstract class Factorial<T extends Number> {

public Number calculate(int arg) {
T result = initResult();
for (int counter = 1; counter <= arg; counter++) {
result = nextIteration(result, counter);
}
return result;
}

protected abstract T initResult();
protected abstract T nextIteration(T currentResult, int currentIterator);
}

private class FactorialLong extends Factorial<Long> {

@Override
protected Long initResult() {
return 1l;
}

@Override
protected Long nextIteration(Long currentResult, int currentIterator) {
return currentResult * currentIterator;
}
}

private class FactorialBigInteger extends Factorial<BigInteger> {

@Override
protected BigInteger initResult() {
return BigInteger.ONE;
}

@Override
protected BigInteger nextIteration(BigInteger currentResult, int currentIterator) {
return currentResult.multiply(BigInteger.valueOf(currentIterator));
}
}

}
67 changes: 67 additions & 0 deletions src/fibonacci/FibonacciSequencePrinter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package fibonacci;

import java.math.BigInteger;

/**
* Class for printing first n members of Fibonacci's sequence
* @version 1.0
* @author Morhun N.
*/
public class FibonacciSequencePrinter {

/** the point of transition from long to BigInteger */
private static final long TRANSITION_POINT = 92;

private long lengthOfSequence;

public FibonacciSequencePrinter(long lengthOfSequence) {
setLengthOfSequence(lengthOfSequence);
}

public void setLengthOfSequence(long lengthOfSequence) {
if (lengthOfSequence < 2) {
throw new IllegalArgumentException("Fibonacci's sequence must have at least two members!");
}
this.lengthOfSequence = lengthOfSequence;
}

/**
* Prints sequence of fibonacci's numbers to {@code lengthOfSequence}
*/
public void print() {
// print two first Fibonacci's numbers
System.out.println("1 : 1");
System.out.println("2 : 1");
// print rest
if (lengthOfSequence < TRANSITION_POINT) {
printUsingLong();
} else {
printUsingBigInteger();
}
}

private void printUsingLong() {
long prev1 = 1;
long prev2 = 1;
long current;
for (long counter = 3; counter <= lengthOfSequence; counter++) {
current = prev1 + prev2;
prev2 = prev1;
prev1 = current;
System.out.println(counter + " : " + current);
}
}

private void printUsingBigInteger() {
BigInteger prev1 = BigInteger.ONE;
BigInteger prev2 = BigInteger.ONE;
BigInteger current;
for (long counter = 3; counter <= lengthOfSequence; counter++) {
current = prev1.add(prev2);
prev2 = prev1;
prev1 = current;
System.out.println(counter + " : " + current);
}
}

}
163 changes: 163 additions & 0 deletions src/numbersWriter/NumbersWriterInWords.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package numbersWriter;

import java.util.ArrayList;
import java.util.List;

/**
* Class for generating {code String} from number
* @version 1.0
* @author Morhun N.
*/
public class NumbersWriterInWords {

private static final int MAXIMAL_NUMBER_OF_GROUPS = 7; // long can not contain more
private static final String GROUP_NAMES[] = {
"",
"thousand",
"million",
"milliard",
"billion",
"billiard",
"trillion"
};
private static final String DIGITS[] = {
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
};
private static final String DOZENS[] = {
"",
"ten",
"twenty",
"thirty",
"forty",
"fifty",
"sixty",
"seventy",
"eighty",
"ninety"
};
private static final String NUMBERS_FROM_10_TO_19[] = {
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen"
};
private static final String MINUS_WORD = "minus";
private static final String HUNDRED_WORD = "hundred";
private static final String AND_WORD = "and";

/**
* Writes specified number in words
* @param number number for writing in words
* @return specified number in words
*/
public String getNumberInWords(long number) {
if (number == 0l) {
return DIGITS[0];
}

List<String> result = new ArrayList<>();
if (number < 0) {
result.add(MINUS_WORD);
number = - number;
}

int groups[] = divideNumberOnGroups(number);
for (int i = MAXIMAL_NUMBER_OF_GROUPS - 1; i >= 0; i--) {
if (groups[i] != 0) {
result.addAll(getGroupInWords(groups[i], i));
}
}

return joinList(result);
}

/**
* Prints into console specified number in words
* @param number number for printing
*/
public void printNumberInWords(long number) {
System.out.print(getNumberInWords(number));
}

/**
* Divides number on groups of three digits
* @param number number for dividing on groups
* @return array of groups of specified number
*/
private int[] divideNumberOnGroups(long number) {
int groups[] = new int[MAXIMAL_NUMBER_OF_GROUPS];
for (int i = 0; i < MAXIMAL_NUMBER_OF_GROUPS && number != 0l; i++) {
groups[i] = (int) (number % 1000);
number /= 1000;
}
return groups;
}

/**
* Forming a group of three digits and adds corresponding to this group suffix
* If group is empty (all numbers are zeros) then returns empty list
* @param group group of three digits
* @param groupNumber sequence number of group
* @return formed group with corresponding suffix
*/
private List<String> getGroupInWords(int group, int groupNumber) {
List<String> result = new ArrayList<>(5);

int hundreds = group / 100;
int tensAndUnits = group % 100;

if (hundreds != 0) {
result.add(DIGITS[hundreds]);
result.add(HUNDRED_WORD);
}
if (tensAndUnits != 0) {
if (hundreds != 0) {
result.add(AND_WORD);
}

if (tensAndUnits < 10) {
result.add(DIGITS[tensAndUnits]);
} else if (tensAndUnits < 20) {
result.add(NUMBERS_FROM_10_TO_19[tensAndUnits - 10]);
} else {
int dozens = tensAndUnits / 10;
int units = tensAndUnits % 10;
result.add(DOZENS[dozens]);
if (units != 0) {
result.add(DIGITS[units]);
}
}
}

if (! result.isEmpty()) {
result.add(GROUP_NAMES[groupNumber]);
}

return result;
}

/**
* Joins string list into one string with whitespace as separator
* @param list string list for joining into one string
* @return joined into string list
*/
private String joinList(List<String> list) {
return String.join(" ", list);
}

}