समाधान एक आंशिक तर्क के साथ लैम्ब्डा फ़ंक्शन द्वारा परिभाषित ऑब्जेक्ट्स के आलसी, अनंत अनुक्रम के प्रतिनिधित्व के लिए FunctionalSequence
के रूप में बनाया जाएगा। समारोह पुनरावृत्त हो सकता है या नहीं। पुनरावृत्त मामले के लिए FunctionalSequence
कक्षा में प्रारंभ मान सेट करने के लिए initialize
विधि होगी।
ऐसे वर्ग की एक वस्तु की घोषणा तो दिखेगा:
FunctionalSequence<BigInteger> fiboSequence = new FunctionalSequence<>();
fiboSequence.
initialize(Stream.of(BigInteger.ONE,BigInteger.ONE)).
setSequenceFunction(
(i) ->
fiboSequence.get(i-2).add(fiboSequence.get(i-1))
);
सूचना, सवाल में पुनरावर्ती लैम्ब्डा उदाहरण के रूप में, हम वस्तु की घोषणा नहीं कर सकते हैं और एक ऑपरेटर में रिकर्सिवली यह परिभाषित करते हैं। घोषणा के लिए एक ऑपरेटर, परिभाषा के लिए दूसरा।
FunctionalSequence
वर्ग परिभाषा:
import java.util.Iterator;
import java.util.LinkedList;
import java.util.stream.Stream;
public class FunctionalSequence<T> implements Iterable<T>{
LinkedList<CountedFlighweight<T>> realList = new LinkedList<>();
StackOverflowingFunction<Integer, T> calculate = null;
public FunctionalSequence<T> initialize(Stream<T> start){
start.forEachOrdered((T value) ->
{
realList.add(new CountedFlighweight<>());
realList.getLast().set(value);
});
return this;
}
public FunctionalSequence<T> setSequenceFunction(StackOverflowingFunction<Integer, T> calculate){
this.calculate = calculate;
return this;
}
@Override
public Iterator<T> iterator() {
return new SequenceIterator();
}
public T get(int currentIndex) throws StackOverflowError{
if(currentIndex < 0) return null;
while (currentIndex >= realList.size()){
realList.add(new CountedFlighweight<T>());
}
try {
return (T) realList.get(currentIndex).get(calculate, currentIndex);
} catch (Exception e) {
return null;
}
}
public class SequenceIterator implements Iterator<T>{
int currentIndex;
@Override
public boolean hasNext() {
return true;
}
@Override
public T next() {
T result = null;
if (currentIndex == realList.size()){
realList.add(new CountedFlighweight<T>());
}
// here the StackOverflowError catching is a pure formality, by next() we would never cause StackOverflow
try {
result = realList.get(currentIndex).get(calculate, currentIndex);
} catch (StackOverflowError e) {
}
currentIndex++;
return result;
}
}
/**
* if known is false, the value of reference is irrelevant
* if known is true, and reference is not null, reference contains the data
* if known is true, and reference is null, that means, that the appropriate data are corrupted in any way
* calculation on corrupted data should result in corrupted data.
* @author Pet
*
* @param <U>
*/
public class CountedFlighweight<U>{
private boolean known = false;
private U reference;
/**
* used for initial values setting
*/
private void set(U value){
reference = value;
known = true;
}
/**
* used for data retrieval or function counting and data saving if necessary
* @param calculate
* @param index
* @return
* @throws Exception
*/
public U get(StackOverflowingFunction<Integer, U> calculate, int index) throws StackOverflowError{
if (! known){
if(calculate == null) {
reference = null;
} else {
try {
reference = calculate.apply(index);
} catch (Exception e) {
reference = null;
}
}
}
known = true;
return reference;
}
}
@FunctionalInterface
public interface StackOverflowingFunction <K, U> {
public U apply(K index) throws StackOverflowError;
}
}
के रूप में पुनरावर्ती क्रिया आसानी से StackOverflowError को पूरा कर सकता है, हम इतना है कि उस मामले में पूरे पुनरावर्ती अनुक्रम वास्तव में मुलाकात की किसी भी परिवर्तन और फेंक बिना वापस रोल होगा प्रत्यावर्तन व्यवस्थित करना चाहिए अपवाद।
FunctionalSequence के उपयोग तो दे सकता है:
// by iterator:
int index=0;
Iterator<BigInteger> iterator = fiboSequence.iterator();
while(index++<10){
System.out.println(iterator.next());
}
या तो:
static private void tryFibo(FunctionalSequence<BigInteger> fiboSequence, int i){
long startTime = System.nanoTime();
long endTime;
try {
fiboSequence.get(i);
endTime = System.nanoTime();
System.out.println("repeated timing for f("+i+")=" + (endTime-startTime)/1000000.+" ns");
} catch (StackOverflowError e) {
endTime = System.nanoTime();
//e.printStackTrace();
System.out.println("failed counting f("+i+"), time=" + (endTime-startTime)/1000000.+" ns");
}
}
पिछले समारोह निम्नलिखित तरीके से इस्तेमाल किया जा सकता:
tryFibo(fiboSequence, 1100);
tryFibo(fiboSequence, 100);
tryFibo(fiboSequence, 100);
tryFibo(fiboSequence, 200);
tryFibo(fiboSequence, 1100);
tryFibo(fiboSequence, 2100);
tryFibo(fiboSequence, 2100);
tryFibo(fiboSequence, 1100);
tryFibo(fiboSequence, 100);
tryFibo(fiboSequence, 100);
tryFibo(fiboSequence, 200);
tryFibo(fiboSequence, 1100);
यहाँ परिणाम (परीक्षण की जरूरतों के लिए ढेर 256K तक सीमित था):
1
1
2
3
5
8
13
21
34
55
failed counting f(1100), time=3.555689 ns
repeated timing for f(100)=0.213156 ns
repeated timing for f(100)=0.002444 ns
repeated timing for f(200)=0.266933 ns
repeated timing for f(1100)=5.457956 ns
repeated timing for f(2100)=3.016445 ns
repeated timing for f(2100)=0.001467 ns
repeated timing for f(1100)=0.005378 ns
repeated timing for f(100)=0.002934 ns
repeated timing for f(100)=0.002445 ns
repeated timing for f(200)=0.002445 ns
repeated timing for f(1100)=0.003911 ns
देखो, उसी सूचकांक के लिए f (i) की दोहराने योग्य कॉल व्यावहारिक रूप से कोई समय नहीं लेती - कोई पुनरावृत्ति नहीं किया गया था। हम StackOverflowError की वजह से एक बार में (1100) तक नहीं पहुंच सकते हैं। लेकिन हम एक बार एफ (200) तक पहुंचने के बाद, एफ (1100) पहुंच योग्य हो जाते हैं। हमने इसे बनाया!
शायद आप 'स्प्लिटरेटर.ऑफिंट' – fge
@fge बनाना चाहते हैं, मुझे अनुक्रमिक पहुंच की आवश्यकता नहीं है। यह एक सरणी की पीढ़ी के द्वारा आसान किया जा सकता है। – Gangnus
एक सरणी परिभाषा से आलसी नहीं है और अनंत भी नहीं हो सकती है; मुझे यकीन नहीं है कि आप परिणाम के रूप में क्या पूछ रहे हैं – fge