Generator/Exponential

Generator/Exponential
You are encouraged to solve this task according to the task description, using any language you may know.

A generator is an executable entity (like a function or procedure) that contains code that yields a sequence of values, one at a time, so that each time you call the generator, the next value in the sequence is provided.
Generators are often built on top of coroutines or objects so that the internal state of the object is handled “naturally”.
Generators are often used in situations where a sequence is potentially infinite, and where it is possible to construct the next value of the sequence with only minimal state.

Task description

Create a function that returns a generation of the m'th powers of the positive integers starting from zero, in order, and without obvious or simple upper limit. (Any upper limit to the generator should not be stated in the source but should be down to factors such as the languages natural integer size limit or computational time/size).

Use it to create a generator of:

Squares.

Cubes.

Create a new generator that filters all cubes from the generator of squares.

Drop the first 20 values from this last generator of filtered results then show the next 10 values

Note that this task requires the use of generators in the calculation of the result.

To modify the internal state, the function uses an access parameter.
For a different approach, see the Random packages of the Ada compiler, which use the so-called "Rosen trick".
With the next release of Ada 2012 functions are allowed to have in-out parameters, which would solve this problem, too.
You could also use procedures instead of functions.

PAR(# run each generator in a different thread ## Thread 1 ## FOR VALUE next exclude IN # gen exclude(# ) DO ###(VALUE next exclude)VOID:(DOWN get next exclude; exclude := next exclude;IF candidate <= exclude THENUP have next excludeELSEUP get next excludeFI# OD #)),# Thread 2 ## FOR VALUE next candidate IN # gen candidate(# ) DO ###(VALUE next candidate)VOID:( candidate := next candidate;IF initialise exclude ORF candidate > exclude THENUP get next exclude;DOWN have next exclude;# wait for result # initialise exclude :=FALSEFI;IF candidate < exclude THEN yield(candidate)FI# OD #))));

libco is a tiny library that adds cooperative multithreading, also known as coroutines, to the C language.
Its co_switch(x) function pauses the current cothread and resumes the other cothread x.

This example provides next64() and yield64(), to generate 64-bit integers. next64() switches to a generator.
Then the generator passes some 64-bit integer to yield64(), which switches to the first cothread, where next64() returns this 64-bit integer.

In Clojure, the role that generator functions take in some other languages
is generally filled by sequences. Most of the functions that produce sequences
produce lazy sequences, many of the standard functions deal with sequences,
and their use in Clojure is extremely idiomatic.
Thus we can define squares and cubes as lazy sequences:

E does not provide coroutines on the principle that interleaving of execution of code should be explicit to avoid unexpected interactions. However, this problem does not especially require them. Each generator here is simply a function that returns the next value in the sequence when called.

Alternatively, generators can be implemented in Go with goroutines and channels.
There are tradeoffs however, and often one technique is a significantly better choice.

Goroutines can run concurrently, but there is overhead associated with thread scheduling and channel communication. Flow control is also different.
A generator implemented as a closure is a function with a single entry point fixed at the beginning.
On repeated calls, execution always starts over at the beginning and ends when a value is returned.
A generator implemented as a goroutine, on the other hand, "returns" a value by sending it on a channel, and then the goroutine continues execution from that point.
This allows more flexibility in structuring code.

The downside of this approach is that it is computing independent sequences. And for the "uncubicalSquares" verb, it is removing some elements from that sequence. So you must estimate how many values to generate. However, this can be made transparent to the user with a simplistic estimator:

jq is a purely functional language and so does not have generators
with state. To generate a sequence of values one-by-one therefore
requires a "next-value" function, the input of which must include
relevant state information. For convenience, a counter is usually
included. For generating i^m, therefore, we would have:

# Generate all the values in the sequence i^3 less than 100:[0,0] | recurse(next_power(3) | if .[1] < 100 then . else empty end) | .[1]

An aside on streams

Since the release of version jq 1.4, enhancements for processing
streams of values have been added, notably "foreach" and "limit".
If your version of jq has these enhancements, then it is often
preferable to use them in conjunction with functions that emit streams of values rather than the "next-value" functions that are the focus of this page.

# gen_filter($g1, $g2) generates everything returned from $g1 that# is not also returned from $g2. Both $g1 and $g2 must be references# to subroutines that generate numbers in increasing order. gen_filter# creates and returns an anonymous subroutine.sub gen_filter {my($g1,$g2)=@_;my$v1;my$v2=$g2->();returnsub{for(;;){$v1=$g1->();$v2=$g2->()while$v1>$v2;return$v1unless$v1==$v2;}};}

In Python, any function that contains a yield statement becomes a generator. The standard libraries itertools module provides the following functions used in the solution: count, that will count up from zero; and islice, which will take a slice from an iterator/generator.

Code was added to support listing of a specified number of values, the default is 0 (zero).
The generators lie dormant until a request is made (illustrated by the calling of "TELL" to display some values).
A lot of unnecessary iterator calls could be eliminated (and making the program a lot faster) if a check would be made to
determine if a value has been emitted (essentially, this would be using memoization and would be easy to implement).

The REXX program can handle any numbers, not just positive integers; one only need to increase the size of the DIGITS if
more digits are needed for extra-large numbers.

This first solution cheats and uses only one generator! It has three iterators powers(2), powers(3) and squares_without_cubes, but the only generator runs powers(3).

An iterator is a Ruby method that takes a block parameter, and loops the block for each element. So powers(2) { |i| puts "Got #{i}" } would loop forever and print Got 0, Got 1, Got 4, Got 9 and so on. Starting with Ruby 1.8.7, one can use Object#enum_for to convert an iterator method to an Enumerator object. The Enumerator#next method is a generator that runs the iterator method on a separate coroutine. Here cubes.next generates the next cube number.

If we change both programs to drop the first 1_000_020 values (output: [1000242014641, 1000244014884, 1000246015129, 1000248015376, 1000250015625, 1000252015876, 1000254016129, 1000256016384, 1000258016641, 1000260016900]), then the one-generator solution runs much faster than the three-generator solution on a machine with MRI 1.9.2.

Tcl implements generators in terms of coroutines.
If these generators were terminating, they would finish by doing return -code break so as to terminate the calling loop context that is doing the extraction of the values from the generator.

For this task, generators are overkill and overweight,
and lazy infinite squences can be used.
There is no real change to the algorithms (since generators are lazy sequences),
it just has been rewritten in a more functional style.