Package squidpony.squidmath
Class MoonwalkRNG
java.lang.Object
squidpony.squidmath.AbstractRNG
squidpony.squidmath.MoonwalkRNG
- All Implemented Interfaces:
Serializable
,IRNG
,IStatefulRNG
,RandomnessSource
,SkippingRandomness
,StatefulRandomness
public class MoonwalkRNG extends AbstractRNG implements IStatefulRNG, SkippingRandomness, Serializable
An IRNG implementation that allows the extra functionality of a StatefulRandomness and a SkippingRandomness, as well
as allowing reverse-lookup of the state that produced a long using the static
Internally, this is like
The name comes from the ability of this generator to easily go in reverse, like the moonwalk dance move, including
Created by Tommy Ettinger on 4/14/2018.
inverseNextLong(long)
method,
and distance checks between two generated numbers with the static distance(long, long)
method. A task this
might be useful for could be simple obfuscation that is hard to undo unless you know the starting state, like this:
- take a sequence of numbers or characters and a MoonwalkRNG with a given starting state,
- modify each item in the sequence with a random but reversible change such as a bitwise XOR
with a number produced by the MoonwalkRNG (such as by
nextInt()
), - on a later run, take the modified sequence and a MoonwalkRNG with the same starting state (but no direct
access to the starting sequence), and skip ahead by the length of the sequence with
skip(long)
, - starting at the end of the sequence, apply the reverse change to the items with numbers generated
backwards by MoonwalkRNG with
previousInt()
(such as a XOR if the number was originally modified with a XOR or an addition if it was originally modified with a subtraction), - when the full sequence has been reversed, you now have the original sequence again.
Internally, this is like
StatefulRNG
if it always used LightRNG
and allowed access to LightRNG's
skip() method as well as the reverse lookup and distance methods that aren't in LightRNG but are allowed by it.
The name comes from the ability of this generator to easily go in reverse, like the moonwalk dance move, including
previousLong()
and skip(long)
for advancing backwards, but also inverseNextLong(long)
to
go from output back to state.
Created by Tommy Ettinger on 4/14/2018.
- See Also:
- Serialized Form
-
Constructor Summary
Constructors Constructor Description MoonwalkRNG()
Default constructor; uses a random seed.MoonwalkRNG(long seed)
Constructs a MoonwalkRNG with the given seed as-is; any seed can be given.MoonwalkRNG(CharSequence seedString)
String-seeded constructor; uses a platform-independent hash of the String (it does not use String.hashCode) as a seed for this RNG. -
Method Summary
Modifier and Type Method Description MoonwalkRNG
copy()
Creates a copy of this MoonwalkRNG; it will generate the same random numbers, given the same calls in order, as this MoonwalkRNG at the point copy() is called.static long
distance(long out1, long out2)
Returns the number of steps (where a step is equal to one call to most random number methods in this class) needed to go from receiving out1 from a MoonwalkRNG'snextLong()
method to receiving out2 from another call.boolean
equals(Object o)
long
getState()
Get the current internal state of the StatefulRandomness as a long.int
hashCode()
static long
inverseNextLong(long out)
Given the output of a call tonextLong()
asout
, this finds the state of the MoonwalkRNG that produce that output.int
next(int bits)
Get up to 32 bits (inclusive) of random output; the int this produces will not require more thanbits
bits to represent.boolean
nextBoolean()
Get a random bit of state, interpreted as true or false with approximately equal likelihood.double
nextDouble()
Gets a random double between 0.0 inclusive and 1.0 exclusive.float
nextFloat()
Gets a random float between 0.0f inclusive and 1.0f exclusive.int
nextInt()
Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive).long
nextLong()
Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive).int
previousInt()
Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive), but advances the state "backwards," such that callingnextInt()
alternating with this method will return the same pair of numbers for as long as you keep alternating those two calls.long
previousLong()
Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive), but advances the state "backwards," such that callingnextLong()
alternating with this method will return the same pair of numbers for as long as you keep alternating those two calls.void
setState(long state)
Set the current internal state of this StatefulRandomness with a long; all longs are allowed.long
skip(long advance)
Advances or rolls back the SkippingRandomness' state without actually generating each number.Serializable
toSerializable()
Gets a view of this IRNG in a way that implementsSerializable
, which may simply be this IRNG if it implements Serializable as well as IRNG.String
toString()
Methods inherited from class squidpony.squidmath.AbstractRNG
between, between, between, getRandomElement, getRandomElement, getRandomElement, nextDouble, nextFloat, nextInt, nextLong, nextSignedInt, nextSignedLong, randomOrdering, randomOrdering, randomPortion, shuffle, shuffle, shuffle, shuffle, shuffleInPlace, shuffleInPlace, swap
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
Methods inherited from interface squidpony.squidmath.IRNG
between, between, between, getRandomElement, getRandomElement, getRandomElement, nextDouble, nextFloat, nextInt, nextLong, nextSignedInt, nextSignedLong, randomOrdering, randomOrdering, randomPortion, shuffle, shuffle, shuffle, shuffle, shuffleInPlace, shuffleInPlace
-
Constructor Details
-
MoonwalkRNG
public MoonwalkRNG()Default constructor; uses a random seed. -
MoonwalkRNG
Constructs a MoonwalkRNG with the given seed as-is; any seed can be given.- Parameters:
seed
- any long
-
MoonwalkRNG
String-seeded constructor; uses a platform-independent hash of the String (it does not use String.hashCode) as a seed for this RNG.- Parameters:
seedString
- any CharSequence, such as a String or StringBuilder; if null this will use the seed 0
-
-
Method Details
-
next
Get up to 32 bits (inclusive) of random output; the int this produces will not require more thanbits
bits to represent.- Specified by:
next
in interfaceIRNG
- Specified by:
next
in interfaceRandomnessSource
- Specified by:
next
in classAbstractRNG
- Parameters:
bits
- an int between 1 and 32, both inclusive- Returns:
- a random number that fits in the specified number of bits
-
nextInt
Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive).- Specified by:
nextInt
in interfaceIRNG
- Specified by:
nextInt
in classAbstractRNG
- Returns:
- a 32-bit random int.
-
nextLong
Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive).- Specified by:
nextLong
in interfaceIRNG
- Specified by:
nextLong
in interfaceRandomnessSource
- Specified by:
nextLong
in classAbstractRNG
- Returns:
- a 64-bit random long.
-
previousInt
Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive), but advances the state "backwards," such that callingnextInt()
alternating with this method will return the same pair of numbers for as long as you keep alternating those two calls. This can be useful withskip(long)
when it advances ahead by a large amount and you want to step backward to reverse another set of forward-advancing number generations that had been done by other code.- Returns:
- a 32-bit random int.
-
previousLong
Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive), but advances the state "backwards," such that callingnextLong()
alternating with this method will return the same pair of numbers for as long as you keep alternating those two calls. This can be useful withskip(long)
when it advances ahead by a large amount and you want to step backward to reverse another set of forward-advancing number generations that had been done by other code.- Returns:
- a 64-bit random long.
-
nextBoolean
Get a random bit of state, interpreted as true or false with approximately equal likelihood.
This implementation uses a sign check and is able to avoid some calculations needed to get a full int or long.- Specified by:
nextBoolean
in interfaceIRNG
- Specified by:
nextBoolean
in classAbstractRNG
- Returns:
- a random boolean.
-
nextDouble
Gets a random double between 0.0 inclusive and 1.0 exclusive. This returns a maximum of 0.9999999999999999 because that is the largest double value that is less than 1.0 .- Specified by:
nextDouble
in interfaceIRNG
- Specified by:
nextDouble
in classAbstractRNG
- Returns:
- a double between 0.0 (inclusive) and 0.9999999999999999 (inclusive)
-
nextFloat
Gets a random float between 0.0f inclusive and 1.0f exclusive. This returns a maximum of 0.99999994 because that is the largest float value that is less than 1.0f .- Specified by:
nextFloat
in interfaceIRNG
- Specified by:
nextFloat
in classAbstractRNG
- Returns:
- a float between 0f (inclusive) and 0.99999994f (inclusive)
-
copy
Creates a copy of this MoonwalkRNG; it will generate the same random numbers, given the same calls in order, as this MoonwalkRNG at the point copy() is called. The copy will not share references with this MoonwalkRNG.- Specified by:
copy
in interfaceIRNG
- Specified by:
copy
in interfaceRandomnessSource
- Specified by:
copy
in interfaceStatefulRandomness
- Specified by:
copy
in classAbstractRNG
- Returns:
- a copy of this IRNG
-
toSerializable
Gets a view of this IRNG in a way that implementsSerializable
, which may simply be this IRNG if it implements Serializable as well as IRNG.
For implementors: It is suggested to return anRNG
initialized by callingRNG(long)
withnextLong()
if you are unable to save the current state of this IRNG and the caller still needs something saved. This won't preserve the current state or the choice of IRNG implementation, however, so it is simply a last resort in case you don't want to throw an exception.- Specified by:
toSerializable
in interfaceIRNG
- Specified by:
toSerializable
in classAbstractRNG
- Returns:
- a
Serializable
view of this IRNG or a similar one; may bethis
-
skip
Advances or rolls back the SkippingRandomness' state without actually generating each number. Skips forward or backward a number of steps specified by advance, where a step is equal to one call tonextLong()
, and returns the random number produced at that step. Negative numbers can be used to step backward, or 0 can be given to get the most-recently-generated long fromnextLong()
.- Specified by:
skip
in interfaceSkippingRandomness
- Parameters:
advance
- Number of future generations to skip over; can be negative to backtrack, 0 gets the most-recently-generated number- Returns:
- the random long generated after skipping forward or backwards by
advance
numbers
-
getState
Get the current internal state of the StatefulRandomness as a long.- Specified by:
getState
in interfaceStatefulRandomness
- Returns:
- the current internal state of this object as a long
-
setState
Set the current internal state of this StatefulRandomness with a long; all longs are allowed.- Specified by:
setState
in interfaceStatefulRandomness
- Parameters:
state
- a 64-bit long; this can be any long, even 0
-
toString
-
equals
-
hashCode
-
inverseNextLong
Given the output of a call tonextLong()
asout
, this finds the state of the MoonwalkRNG that produce that output. If you set the state of a MoonwalkRNG withsetState(long)
to the result of this method and then callnextLong()
on it, you should get backout
.
This isn't as fast asnextLong()
, but both run in constant time. Some random number generators take more than constant time to reverse, so one was chosen for this class that would still be efficient (LightRNG
).
This will not necessarily work if out was produced by a generator other than a MoonwalkRNG, or if it was produced with the boundedAbstractRNG.nextLong(long)
method by any generator.- Parameters:
out
- a long as produced bynextLong()
, without changes- Returns:
- the state of the RNG that will produce the given long
-
distance
Returns the number of steps (where a step is equal to one call to most random number methods in this class) needed to go from receiving out1 from a MoonwalkRNG'snextLong()
method to receiving out2 from another call. This number can be used withskip(long)
to move a MoonwalkRNG forward or backward by the desired distance.- Parameters:
out1
- a long as produced bynextLong()
, without changesout2
- a long as produced bynextLong()
, without changes- Returns:
- the number of calls to
nextLong()
that would be required to go from producing out1 to producing out2; can be positive or negative, and can be passed toskip(long)
-