Към съдържанието

Javanacci — пълен код

Всеки клас в собствен файл. Пакет: bg.tu_varna.javanacci.


InvalidFibonacciPositionException.java — checked exception за отрицателна позиция

package bg.tu_varna.javanacci;
class InvalidFibonacciPositionException extends Exception {
private final long invalidPosition;
public InvalidFibonacciPositionException(long position) {
super("Позиция " + position + " е отрицателна; допустими стойности: [0, " + Long.MAX_VALUE + "]");
this.invalidPosition = position;
}
public long getInvalidPosition() {
return invalidPosition;
}
}

FibonacciRunnable.java — параметризиран интерфейс с метод run()

package bg.tu_varna.javanacci;
interface FibonacciRunnable<R> {
R run();
}

AbstractFibonacciMachine.java — абстрактна база с Comparable по позиция

package bg.tu_varna.javanacci;
import java.math.BigInteger;
abstract class AbstractFibonacciMachine implements Comparable<AbstractFibonacciMachine> {
protected final long position;
protected AbstractFibonacciMachine(long position) {
this.position = position;
}
public long getPosition() {
return position;
}
public abstract BigInteger run();
@Override
public int compareTo(AbstractFibonacciMachine other) {
return Long.compare(this.position, other.position);
}
}

FibonacciMachine.java — конкретна машина; глобален кеш, обхождане напред, AutoCloseable

package bg.tu_varna.javanacci;
import java.math.BigInteger;
import java.util.*;
import static java.math.BigInteger.ZERO;
import static java.math.BigInteger.ONE;
class FibonacciMachine extends AbstractFibonacciMachine
implements FibonacciRunnable<BigInteger>, AutoCloseable {
public static final long MAX_POSITION = Long.MAX_VALUE;
// Sorted map — enables floorKey(n) to find the highest cached position ≤ n
private static final NavigableMap<Long, BigInteger> CACHE = new TreeMap<>();
static {
CACHE.put(0L, ZERO);
CACHE.put(1L, ONE);
}
public FibonacciMachine(long position) throws InvalidFibonacciPositionException {
super(position);
if (position < 0) {
throw new InvalidFibonacciPositionException(position);
}
}
@Override
public BigInteger run() {
if (CACHE.containsKey(position)) {
return CACHE.get(position);
}
// Find highest cached position ≤ target, then iterate forward from there
Long startPos = CACHE.floorKey(position);
BigInteger prev = CACHE.get(startPos - 1);
BigInteger curr = CACHE.get(startPos);
for (long i = startPos + 1; i <= position; i++) {
BigInteger next = prev.add(curr);
CACHE.put(i, next);
prev = curr;
curr = next;
}
return CACHE.get(position);
}
@Override
public void close() {
System.out.println("FibonacciMachine[" + position + "] приключи.");
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof FibonacciMachine)) {
return false;
}
return this.position == ((FibonacciMachine) obj).position;
}
@Override
public int hashCode() {
return Long.hashCode(position);
}
@Override
public String toString() {
return "FibonacciMachine[" + position + "]";
}
}

Javanacci.java — оркестратор; приема масив от позиции или брой за произволни; имплементира Iterable

package bg.tu_varna.javanacci;
import java.math.BigInteger;
import java.util.*;
public class Javanacci implements Iterable<Javanacci.Result> {
public static class Result {
private final long position;
private final BigInteger value;
Result(long position, BigInteger value) {
this.position = position;
this.value = value;
}
public long getPosition() { return position; }
public BigInteger getValue() { return value; }
@Override
public String toString() {
return "fib(" + position + ") = " + value;
}
}
private final List<FibonacciMachine> machines;
public Javanacci(long[] positions) throws InvalidFibonacciPositionException {
machines = new ArrayList<>();
for (long pos : positions) {
machines.add(new FibonacciMachine(pos));
}
}
public Javanacci(int count) throws InvalidFibonacciPositionException {
machines = new ArrayList<>();
Random rng = new Random();
for (int i = 0; i < count; i++) {
machines.add(new FibonacciMachine((long) (rng.nextDouble() * 100)));
}
}
public List<Result> runAll() {
List<Result> results = new ArrayList<>();
Iterator<FibonacciMachine> it = machines.iterator();
while (it.hasNext()) {
FibonacciMachine machine = it.next();
results.add(new Result(machine.getPosition(), machine.run()));
}
Collections.sort(results, Comparator.comparingLong(Result::getPosition));
return results;
}
public static BigInteger runSingle(long position) throws InvalidFibonacciPositionException {
try (FibonacciMachine machine = new FibonacciMachine(position)) {
return machine.run();
}
}
@Override
public Iterator<Result> iterator() {
return runAll().iterator();
}
}

JavanacciDemo.java — входна точка; три сценария на употреба

package bg.tu_varna.javanacci;
import java.math.BigInteger;
class JavanacciDemo {
public static void main(String[] args) {
// 1. Explicit positions
try {
Javanacci jv = new Javanacci(new long[]{0, 1, 5, 10, 20, 50});
for (Javanacci.Result r : jv) {
System.out.println(r);
}
} catch (InvalidFibonacciPositionException | IllegalArgumentException e) {
System.err.println("Грешка: " + e.getMessage());
}
// 2. Random positions
try {
Javanacci jv = new Javanacci(5);
for (Javanacci.Result r : jv) {
System.out.println(r);
}
} catch (InvalidFibonacciPositionException e) {
System.err.println("Грешка: " + e.getMessage());
}
// 3. Single position via try-with-resources
try {
System.out.println("fib(100) = " + Javanacci.runSingle(100));
} catch (InvalidFibonacciPositionException e) {
System.err.println("Невалидна позиция: " + e.getInvalidPosition());
}
}
}