Git Product home page Git Product logo

synthia's Introduction

Synthia: synthesize data structures in Java

Synthia logo

Build Status

YouTube video

Synthia is a flexible generator of data structures. With Synthia, it is possible to generate numbers, strings, lists, sentences from a predefined grammar, random walks in a finite-state machine, or any other user-defined object. More importantly, all these basic "generators" can be combined to create complex structures and behaviors.

Synthia comes with a library of dozens of code examples illustrating what can be done with it. Among other things can be used to generate test inputs for fuzzing, create a test stub that provides more flexible responses than simple "canned answers", or create a semi-realistic simulation of a system's output, such as a log.

Among the features in Synthia:

  • All sources of "choice" in the various generators are passed as arguments in the form of Picker objects. Pickers can be random, but they can also do something else, such as always returning the same value (special type Contstant), or cycling through a user-defined list of values (special type Playback). Users can define their own pickers, and they can return any type of object, not just numbers.
  • The outputs of pickers can be wrapped into a Record object, which remembers the successive values they produce. These values can be replayed through a Playback picker. Since generators make choices only through pickers, this makes it possible to regenerate any random object. This feature is useful e.g. for debugging, by running a program on a specific input causing a failure.

Examples

Here are simple examples of the basic building blocks to synthesize things with Synthia. The Examples folder has more complex examples, such as simulating multiple users visiting a web site.

Generate primitive objects

The ca.uqac.lif.synthia.random package provides basic Picker objects that can generate primitive values selected with a uniform probability distribution.

RandomInteger ri = new RandomInteger(2, 10); // uniform random int between 2 and 10
RandomFloat rf = new RandomFloat(); // uniform random float between 0 and 1
RandomBoolean rb = new RandomBoolean(0.7); // coin toss returning true 7 out of 10 times

All random pickers implement methods setSeed() (to specify the starting seed of their internal random source) and reset() (to reset their internal random source to the initial seed value), making it possible to reproduce the random sequences they generate.

Random strings can also be generated (using RandomStringUtils from Apache Commons Lang in the background):

// Generate strings of length 10
RandomString rs1 = new RandomString(new Constant(10));
// Generates strings of length randomly selected in the interval 2-10
RandomString rs2 = new RandomString(new RandomInteger(2, 10));

This last example shows that the input to a Picker may itself be another Picker. For rs2, the length of the string is determined by the result of a random pick in the interval [2,10].

Similarly, the Tick picker generates an increasing sequence of numbers:

Tick t1 = new Tick(10, 1);
Tick t2 = new Tick(new RandomInteger(5, 15), new RandomFloat(0.5, 1.5));

Here, t1 will generate a sequence starting at 10 and incrementing by 1 on every call to pick() --that is, this object is completely deterministic. In contrast, t2 wil generate a sequence starting at a randomly selected value between 5 and 15, and incrementing each time by a randomly selected value between 0.5 and 1.5.

Generate a string from generated parts

The StringPattern picker can produce character strings where some parts are determined by the output of other pickers.

StringPattern pat = new StringPattern(
  "{$0} {$1} - Source: {$2}, Destination: {$3}, Duration: {$4}",
  new Tick(),
  new Freeze<String>(new RandomString(new RandomInteger(3, 6))), 
  new Freeze<String>(new IpAddressProvider(new RandomInteger(0, 256))), 
  new IpAddressProvider(new RandomInteger(0, 256)),
  new RandomInteger(10, 1000)));
for (int i = 0; i < 10; i++)
  System.out.println(gp.pick());

Produces an output like:

0.73096776 3dF - Source: 187.212.61.155, Destination: 187.212.61.155, Duration: 340
1.5624087 3dF - Source: 187.212.61.155, Destination: 163.79.140.29, Duration: 368
1.8029451 3dF - Source: 187.212.61.155, Destination: 152.200.85.64, Duration: 689

Notice the use of the Freeze picker: it asks for the input of another picker once, and then returns that value forever.

Generate sequences from a Markov chain

A Markov chain is a stochastic model describing a sequence of possible events. In the following example, we define a Markov chain by creating states (numbers 0-4), associate each state with a Picker object (here all pickers generate a different string), and set the probabilities of transitioning from a state to another.

Tick tick = new Tick(0, new Enumerate<Integer>(1, 2, 1));
MarkovChain<String> mc = new MarkovChain<String>(new RandomFloat());
mc.add(0, new Constant<String>(""));
mc.add(1, new Constant<String>("START"));
mc.add(2, new StringPattern("{$0},A", tick));
mc.add(3, new StringPattern("{$0},B", tick));
mc.add(4, new StringPattern("{$0},C", tick));
mc.add(0, 1, 1).add(1, 2, 0.9).add(1, 4, 0.1)
  .add(2, 3, 1).add(3, 2, 0.7).add(3, 4, 0.3)
  .add(4, 4, 1);
for (int i = 0; i < 8; i++)
	System.out.println(mc.pick());

Note how the generators for states 2-3-4 share the same tick source, ensuring that each string contains an incrementing "timestamp". The Markov chain created by this block of code looks like this:

Markov chain

The program produces an output like this one:

START
1.0,A
3.0,B
4.0,A
5.0,B
7.0,C
8.0,C

Generate sentences from a grammar

Synthia can produce randomly generated expressions from a formal grammar contained in an instance of a Bullwinkle BNF parser.

BnfParser parser = ... // A Bullwinkle parser for an arbitrary grammar
GrammarSentence p = new GrammarSentence(parser, new RandomIndex());
for (int i = 0; i < 10; i++)
  System.out.println(gp.pick());

With the grammar defined here, you get an output that looks like:

The funny old grey fox plays with the ugly big brown siamese .  
The young white cats play with the ugly small old grey siamese .
The grey birds watch the ugly old brown bird .
...

Building Synthia

The library is structured using the AntRun build scripts. Please see the AntRun Readme file for instructions on compiling.

Generating the Javadoc

The documentation for this repository is generated by Doxygen. The configuration file Doxyfile contains the appropriate settings for reading the source files and generating HTML in the docs folder. On the command line, you should be able to run:

$ doxygen Doxyfile

However, these files must be post-processed a little. Run the PHP script post-process.php afterwards. When re-generating the documentation, it may also be wise to first wipe the contents of the docs folder.

It is not recommended to use javadoc to generate the HTML documentation. Several features (such as cross-referenced source code) will be missing from the output.

About the name

Synthia is a play on "synthesizing" data structures.

About the authors

Synthia is being developed by all the folks of Laboratoire d'informatique formelle at Université du Québec à Chicoutimi, Canada. The project lead is Sylvain Hallé, professor at Université du Québec à Chicoutimi, Canada.

synthia's People

Contributors

map555 avatar sylvainhalle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

map555

synthia's Issues

Create interface `EnumerativePicker`

This interface should extend Picker by adding one method:

  • isDone which takes no argument and returns a Boolean

This interface will be used to signal that this picker exhaustively enumerates all values from a set.

Clean-up ListPicker

The current ListPicker is not well-named. It receives an array of pickers, and produces a set of values. There is no list there!

  • Rename into ArrayPicker
  • Modify its pick method so that it returns an array and not a set

Remove `RelativePicker`

It is definitely not an appropriate way to handle this idea. Delete the interface from the project.

Create `RandomTrim`

A combination of RandomPrefix and RandomSuffix. This picker first calculates a prefix of the string, and on this prefix, then calculates a suffix and returns the resulting string.

RandomTrim p = new RandomTrim("foobarbaz", new RandomFloat());

Possible outputs:

  • oobar
  • arbaz
  • oba
  • etc.

Refactor `RandomInteger` and `RandomFloat`

A new formulation of #12.

  • Modify the declaration of RandomInteger so that it implements RelativePicker<Integer> (see #28)
  • Implement method getPicker(x) such that it returns a new instance of RandomInteger, but with the upper bound of its interval set to x. If x is equal to or lower than the existing lower bound, return a NothingPicker<Integer> instead.

Then do the same thing for RandomFloat.

Refactor tests for JUnit 4 instead of 5

Many tests have been written using the classes provided by JUnit version 5 (the latest). That is not a problem in itself, but the standardized build script used in all projects at LIF requires JUnit 4. Continuous integration (i.e. Travis) will break until tests are converted to JU4.

Reasons for not upgrading to JU5 include:

  • Adding support for JU5 would require a nontrivial rewrite of that part of the script, which would then need to be back-propagated to the 30+ other projects that use it (this is not just a matter of swapping files for the newer version). No time for that at the moment.
  • Some features supported for JU4 are still not implemented for JU5 (such as code coverage reports). This is the definitive deal breaker.

The good news is that converting tests to JU4 is mostly a matter of changing the imports at the beginning of a test class.

  • org.junit.jupiter.api.Assertions.* becomes org.junit.Assert.*
  • org.junit.jupiter.api.Testbecomes org.junit.Test

and that's about it.

Task: make these modifications to all test classes.

Create ListPicker

This task depends on #26 being done first.

The goal is to create a new class called ListPicker<T>.

public class ListPicker<T> implements Picker<List<T>> {...}

Note the particular type of this picker: it is a picker that returns elements whose type is List<T>.

Its constructor receives two pickers:

  • One Picker<T> p1 to generate list elements
  • One Picker<Integer> p2 to decide on how many elements to generate

Upon a call to pick, the ListPicker first asks p2 for a list length k, then calls p1 k times and returns an ArrayList<T> made of the k elements obtained from p1.

Optimize method shrink of ElementPicker

Instead of returning the generic PickSmallerComparable, it could return another ElementPicker with larger values being removed from the possible choices (and probabilities readjusted accordingly).

Create a few SmallerX

In the relative package (see #11), implement a few simple RelativePicker:

  • SmallerInteger: given an integer i, picks an integer in the interval [0, i-1]
  • SmallerString: given a string s, picks a string shorter than s

Create `PickIfSmaller<T>`

This is an abstract class that descends from PickIf<T>. Its constructor takes a single argument, which is a RelativePicker<T>; let us call it rp.

The implementation of method pick should override that of PickIf and work as follows:

  1. Call pick on the rp to obtain an element e.
  2. Call select with element e. If the method returns false, go back to step 1 and try again. If the method returns true:
    2.1 Overwrite the RelativePicker with a new one, obtained by calling rp = rp.getPicker(e);
    2.2 Return e

The end result is that, every time PickIfSmaller is called, it returns an element for which select returns true, and which is smaller than the previous one.

Create `RandomPrefix`

Like RandomSubstring (#31), but this time, the picker returns a prefix of the original string of randomly selected length. The Picker<Boolean> is replaced by a Picker<Integer>.

RandomPrefix p = new RandomPrefix("foobarbaz", new RandomInteger());

Possible outputs of p.pick():

  • foobarb
  • f
  • foobarbaz
  • The empty string
  • etc.

Upon a call to getPicker(s), the class returns a new instance of RandomPrefix using s as the string for its constructor. If s is the empty string, it returns an instance of NothingPicker instead.

Improvements to existing unit tests

  • Unit tests should not write output to the console. This requires manual intervention by developers to verify the output printed on the console to check if the test ran successfully or not, which defeats the purpose of automated testing in a continuous integration environment such as Travis.
  • A few tests are needlessly long. An example is GaussianFloatTest.sameValuesSameSeed(), which tests 10,000 pairs of pickers for their first 10,000 values each. This amounts to 200 million calls to pick(), which is probably overkill in the context, and makes that single test case last for almost 10 seconds. This is especially important since every build in the Travis platform consumes credits based on execution time. Reduce to 100 repetitions.
  • In that same test, the seed for the pickers is itself picked at random. This makes the test case susceptible to being non reproducible: re-running a failing test may result in a passing test, and vice versa, due to the chance of picking different seeds each time. It would be preferable to randomly pick a list of seeds, then hard-code that list into the test so that the state of each execution is identical. (Same for other tests that do the same thing.)

Create `RandomSublist`

This is the equivalent of RandomSubstring (#31), but for lists.

public class RandomSublist<T> implements RelativePicker<List<T>> {...}

Its constructor receives four arguments:

  • A list of elements of type T
  • A Picker<Boolean> whose role is similar to that in RandomSubstring
  • A second Picker<Boolean> whose use will be described below
  • A RelativePicker<T>, which will be called to reduce list elements

Example of a constructor call:

List<String> my_list = Arrays.asList("portez", "ce", "whisky", "au", "vieux", "juge");
RandomSublist<String> p = new RandomSublist<String>(my_list, 
  new RandomBoolean(), new RandomBoolean(),
  new RandomPrefix(null, new RandomFloat());

On a call to pick, the class iterates over each element of the list passed to its constructor. On each element, the class performs two coin flips with the Picker<Boolean>:

  1. The first is like for RandomSubstring, to decide if the element is included or not
  2. If the coin flip decides the element is to be included, a second coin flip occurs with the second Boolean picker, this time to decide if the element should be added to the output as is, or be first passed to the RelativePicker<T>.

If the answer is no, the element is added to the output list without modification. If the answer is yes, what is added to the list is rather the result of rp.getPicker(e).pick(), where rp is the relative picker passed to the class' constructor (third parameter).

The end result is that RandomSublist generates a list that contains a subset of the original list, and where each element may be "smaller" than the corresponding element of that list.

For the constructor given above, here are examples of possible outputs:

  • ["por", "whisk", "a", "juge"]
  • ["p", "ce", "ju"]
  • ["portez", "", "j"]

The interesting feature of this picker is that how elements are reduced depends on the RelativePicker<T>. In the example above, we used a RandomPrefix, and so the elements of the list are prefixes of the originals. If we change the constructor call to this:

List<String> my_list = Arrays.asList("portez", "ce", "whisky", "au", "vieux", "juge");
RandomSublist<String> p = new RandomSublist<String>(my_list, 
  new RandomBoolean(), new RandomBoolean(),
  new RandomSubstring(null, new RandomBoolean());

then possible outputs of the picker are all of the above, and also:

  • ["prtz", "ce", "why", "a", "jge"]
  • ["e", "e", "wk", "au", "ue"]
  • etc.

Create `RelativePicker<T>`

First, create new package ca.uqac.lif.synthia.relative.

In this package, create an interface that extends Picker<T> with a method:

public T pick(T element);

The goal is to pick an element relative to some relationship with another element.

Create `PickIf`

This picker is an abstract class. Its constructor receives another Picker<T>, and has an abstract method:

protected abstract boolean select(T element);

Its method pick calls pick on its underlying picker, and then passes the element to select; if the method returns true, the element is returned. If it returns false, another element is asked to the underlying picker. The process repeats as long as an element is accepted by select.

Create `AllPickers`

Create a picker that implements EnumerativePicker, and which produces as its output an array of values coming from other EnumerativePickers.

The constructor should receive a variable number of EnumerativePickers. Upon every call to pick, it returns an array with a distinct combination of values from each inner picker.

Example:

AllPickers a = new AllPickers(new AllBooleans(), new AllBooleans());

(See #8 for AllBooleans)

Successive calls to a.pick() should return:

{false, false}
{false, true}
{true, false}
{true, true}

From this point on, calls to a.isDone() should return true, and any further call to a.pick() should throw a NoMoreElementsException.

Create `RandomSuffix`

Mirror image of RandomPrefix (#32), this time for suffixes of the string.

RandomSuffix p = new RandomSuffix("foobarbaz", new RandomFloat());

Examples of calls to p.pick():

  • baz
  • oobarbaz
  • The empty string
  • etc.

Implement a new PNRG

The PNRG provided by the Java API (Random) cannot be "duplicated with state", as is the case with most objects in the Synthia library. This causes problems for Pickers using Random internally, but for which we expect this functionality to work.

Consider this example:

Random r = new Random(42);
r.nextInt(); r.nextInt();

At this point, how do you get a clone r2 that will produce the same sequence of numbers as r from its current state? You cannot simply write r2 = new Random(42), as r2 will produce the same sequence as r, but from its initial state --which is not what we want.

What is expected here is a class DuplicableRandom that implements the Duplicable interface, so that calling r.duplicate(true) produces a distinct copy of r that carries over its current internal state.

Alas, we cannot simply descend from Random and implement method duplicate, as the internal state is in a private member field (see for example the OpenJDK implementation of Random):

https://github.com/openjdk/jdk/blob/a8a2246158bc53414394b007cbf47413e62d942e/src/java.base/share/classes/java/util/Random.java#L86
https://github.com/openjdk/jdk/blob/a8a2246158bc53414394b007cbf47413e62d942e/src/java.base/share/classes/java/util/Random.java#L535
https://github.com/openjdk/jdk/blob/a8a2246158bc53414394b007cbf47413e62d942e/src/java.base/share/classes/java/util/Random.java#L536

Proposed solution: create DuplicableRandom by copying/renaming OpenJDK's Random, and implement method duplicate by copying to the new instance the values of the three fields mentioned above.

(And then write the appropriate unit tests to make sure it behaves as we want.)

Create `RandomSubstring`

This class implements RelativePicker<String>. Its constructor receives an input string, and a Picker<Boolean>, such as this:

RandomSubstring p = new RandomSubstring("foobarbaz", new RandomBoolean());

Upon a call to pick, this picker produces a random substring of the original string. It does so by iterating over each character, and deciding on a coin flip (using the Boolean picker) if the character should be included or not. Examples of possible outputs for the picker defined above:

  • foobar
  • oobrbz
  • oob
  • etc.

Upon a call to getPicker(s), this picker returns a new RandomSubstring and passing it the string s.

Parcel shipment example

A map is represented by a rectangular grid of m x n points (A,B) located at integer coordinates. H (C) of these points are selected as hubs --cities of greater importance, and their position (x,y) is selected (D).

Every time a new package shipment is started

For each new package, an ID i is selected (E). The source and destination are selected as follows:

  • A source for this package is selected by first choosing a hub (F), and then selecting an (x,y) coordinate relative to the hub (G).

  • For the destination, a decision is made as to whether the package is to be shipped near or far (H).

    • If near, a destination is picked relative to the same hub as the source, with the exception of the source (J).
    • If far, another hub is first selected (with the exception of the source's hub, I), and an (x,y) coordinate is selected with respect to that hub (J).

At each time step of the simulation

A number of new shipments to be started is selected (K). These shipments are instantiated as explained above.

Then, for each active shipment:

  • A decision is made whether the shipment will move in this simulation step (L).
  • If so, a next position among its immediate neighboring (x,y) coordinates is selected (M). The package is moved to that cell.
  • Any package that reaches its destination is considered handled, and is removed from the set of active shipments.

Structure

This problem contains 13 degrees of freedom, which can be symbolized by pickers:

A. Size of the grid (x axis) [integer]
B. Size of the grid (y axis) [integer]
C. Selection of the number of hubs [integer]
D. Selection of the (x,y) position of a hub [(integer,integer)]
E. Selection of the package's ID [string]
F. Source hub selection [hub]
G. (x,y) selection with respect to first hub [(integer,integer)]
H. Near/far destination [Boolean]
I. Destination hub selection [hub]
J. (x,y) selection with respect to destination hub [(integer,integer)]
K. Number of new active shipments at each time step [integer]
L. Decision on whether a package moves in a simulation step [Boolean]
M. Selection of the next coordinate for a package [(integer,integer)]

Add stopping conditions to `PickIf`

Currently, PickIf may run into an infinite loop if the condition that evaluates the events returns false on everything. The purpose of this task is to add a failsafe mechanism to specify when PickIf has the right to stop.

Maximum number of iterations

A first mechanism to stop PickIf is to specify a maximum number of iterations, similar to the trials parameter of JUnit-Quickcheck.

  • Create a new exception type called GiveUpException.
  • Add an internal member field which, if positive, contains the maximum number of iterations that PickIf should try finding a satisfying element (if negative, PickIf should behave as currently and keep trying forever). If the maximum number of iterations is reached, throw a GiveUpException.
  • Add an alternate constructor where the number of iterations can be specified.
  • Make sure that duplicate transfers this number to copies of the class.

This behavior is specific to each call to pick. The iteration counter restarts from 0 on the next call to pick.

Discard ratio

The second mechanism is to specify what is called the discard ratio: the percentage of generated elements that are rejected by the underlying condition. This also mirrors a similar condition in JUnit-Quickcheck (https://pholser.github.io/junit-quickcheck/site/0.8.2/usage/constraining.html, see bottom of document).

  • Add an internal float member field which, if positive, contains the maximum fraction of generated objects that is allowed to be rejrected by the underlying condition.
  • Make sure that duplicate transfers this field to copies of the class.
  • Add two internal int member fields which count the number of objects generated, and the number of objects rejected. If the ratio exceeds the discard ratio, throw a GiveUpException.

This behavior is based on the whole history of the object: the discard ratio is the number of elements returned so far, divided by the number of events generated since the object was created. This ratio is reset only on a call to the picker's reset method.

Restructure project

The goal of this issue is to restructure the project so that it is made of multiple sub-projects, each having their own build script and generating their own JAR file when compiled. An existing repository called Petit Poucet is already structured in such a way and can be used as an example.

This repository has a Source folder, and multiple "project" folders. Each of them has a pair of files build.xml and config.xml to build them individually. In addition, the parent Source folder has another build.xml file, whose task is to call the build scripts of each folder. It can therefore be seen as a "super-build script".

Refactoring

  • Change folders such that the current folder CoreTest/src becomes Core/srctest, yielding:
Source
  + Core
    + src
    + srctest
    + dep
    + lib

Clean-up of super-build script

  • Modify project name (Synthia) and JAR filename (synthia-core.jar)
  • Modify/delete lines 31-51 that refer to folders that do not exist in Synthia (such as Functions and Examples)

Random has strange behavior

The class ca.uqac.lif.synthia.random.generators.Random has very predictable behavior depending on its seed. Consider:

Random r = new Random();
r.setSeed(X);
System.out.println(r.nextInt(4));

This code prints:

  • 1 if X is in [0,4]
  • 2 if X is in [5,255] U [320,383] U [512,1000]
  • 3 if X is in [256,299] U [302,319]

In other words, large ranges of successive seeds produce the same first number, and in the first 1,000 seeds, 2 is over-represented (it is the first number about 800 times).

Bitmap generator

Create a new extension (synthia-bitmap.jar) that could generate random 4-connected and 8-connected binary images according to various algorithms.

Write unit tests for existing basic classes

Some sources of inspiration...

For most pickers:

  • For each class, make sure that a duplicate obtained without copying state (i.e. calling duplicate(false)) restarts its sequence from the beginning of the original
  • For each class, make sure that a duplicate obtained with copying state (i.e. calling duplicate(true)) continues producing the same values as the original from that point (this case is expected to fail in the current implementation of a few classes, because of #5)

For Constant pickers:

  • Observe that they produce the expected constant

For Playback:

  • Observe that it produces the expected sequence
  • If loop is set to false, observe that it throws a NoMoreElementException after producing the last element of the list (see #3)

For pickers based on random generators:

  • For each class, make sure that two pickers with the same seed produce the same events (loop for the first few events to make sure)

For pickers producing numbers within an interval (and implementations of IndexPicker):

  • For each class, observe that the values are indeed in the interval
  • For the PrismPicker and the HyperspherePicker, make sure that the values in each dimension are within their specified bounds

For pickers producing a string of given length:

  • For each class, observe that the string length is indeed in the interval

For pickers

For AffineTransform:

  • Observe that it produces the expected output value from an expected input (hint: use a Constant or a Playback so that you control what it receives)

For Once:

  • Make sure it produces only one event, and output an NoMoreElementException after that (see #3)

For Tick:

  • Observe that each successive output increments by the expected value (hint: use a Constant or a Playback for its parameters, so that you control what it receives)

For Record:

  • Observe that the values it records are indeed those it receives
  • Make sure that reset wipes these values and makes the recording start anew
  • Check that getCount returns the expected value

For SetPicker and ArrayPicker:

  • Make sure that the set contains exactly one value produced by each picker every time (hint: use pickers with disjoint images to distinguish them)

For StringPattern:

  • Check that the produced string has the expected pattern (hint: use a Constant or a Playback for its parameters, so that you control what it receives)

For Freeze:

  • Make sure it always returns the first value produced by the underlying picker
  • Make sure that resets cancels this (i.e. it outputs a new value. Hint: use a Playback to control what the picker receives)

For ElementPicker:

  • Check that the choice respects the set probabilities (check this partially by setting the probability to 1 for an element, and 0 for the others)

Add "scramble" option to `AllBooleans` and `AllIntegers`

For these classes, add a new version of the constructor which receives a Picker<Float>. When the constructor is instantiated with this picker, it is used to output its values in a random order, with the Picker<Float> controlling this randomness.

(This of course depends on #8 being completed first.)

Add new code examples

Other examples will come

This is more an "exercise to solve" than a "task to execute", so I omit some details on purpose. A few hints:

  • Create a descendant of PickIfSmaller object. The implementation of abstract method select should correspond to the primality check.
  • Create a main method that instantiates this object, call pick a few times on it and prints the values it returns.

Create `AllElements`

Yet another exhaustive picker, which this time enumerates all the elements of a collection --a set, a list or an array-- with and without the scramble option.

Example:

AllElements<Integer> p1 = new AllElements<Integer>(true, 3, 1, 4, 5); // true is the scramble flag

Set<String> set = new HashSet<String>();
set.add("a"); set.add("b"); set.add("c");
AllElements<String> p2 = new AllElements<String>(set);

Hint: implement as a descendant of Playback.

Create `NothingPicker<T>`

This is a class that implements Picker<T> and RelativePicker<T>. All it does on its call to pick is to throw a NoMoreElementException.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.