0
|
1 package fj.test;
|
|
2
|
|
3 import fj.F;
|
|
4 import fj.data.Option;
|
|
5 import static fj.data.Option.some;
|
|
6
|
|
7 import static java.lang.Math.max;
|
|
8 import static java.lang.Math.min;
|
|
9 import java.util.Random;
|
|
10
|
|
11 /**
|
|
12 * A random number generator.
|
|
13 *
|
|
14 * @version %build.number%
|
|
15 */
|
|
16 public final class Rand {
|
|
17 private final F<Option<Long>, F<Integer, F<Integer, Integer>>> f;
|
|
18 private final F<Option<Long>, F<Double, F<Double, Double>>> g;
|
|
19
|
|
20 private Rand(final F<Option<Long>, F<Integer, F<Integer, Integer>>> f, final F<Option<Long>, F<Double, F<Double, Double>>> g) {
|
|
21 this.f = f;
|
|
22 this.g = g;
|
|
23 }
|
|
24
|
|
25 /**
|
|
26 * Randomly chooses a value between the given range (inclusive).
|
|
27 *
|
|
28 * @param seed The seed to use for random generation.
|
|
29 * @param from The minimum value to choose.
|
|
30 * @param to The maximum value to choose.
|
|
31 * @return A random value in the given range.
|
|
32 */
|
|
33 public int choose(final long seed, final int from, final int to) {
|
|
34 return f.f(some(seed)).f(from).f(to);
|
|
35 }
|
|
36
|
|
37 /**
|
|
38 * Randomly chooses a value between the given range (inclusive).
|
|
39 *
|
|
40 * @param from The minimum value to choose.
|
|
41 * @param to The maximum value to choose.
|
|
42 * @return A random value in the given range.
|
|
43 */
|
|
44 public int choose(final int from, final int to) {
|
|
45 return f.f(Option.<Long>none()).f(from).f(to);
|
|
46 }
|
|
47
|
|
48 /**
|
|
49 * Randomly chooses a value between the given range (inclusive).
|
|
50 *
|
|
51 * @param seed The seed to use for random generation.
|
|
52 * @param from The minimum value to choose.
|
|
53 * @param to The maximum value to choose.
|
|
54 * @return A random value in the given range.
|
|
55 */
|
|
56 public double choose(final long seed, final double from, final double to) {
|
|
57 return g.f(some(seed)).f(from).f(to);
|
|
58 }
|
|
59
|
|
60 /**
|
|
61 * Randomly chooses a value between the given range (inclusive).
|
|
62 *
|
|
63 * @param from The minimum value to choose.
|
|
64 * @param to The maximum value to choose.
|
|
65 * @return A random value in the given range.
|
|
66 */
|
|
67 public double choose(final double from, final double to) {
|
|
68 return g.f(Option.<Long>none()).f(from).f(to);
|
|
69 }
|
|
70
|
|
71 /**
|
|
72 * Gives this random generator a new seed.
|
|
73 *
|
|
74 * @param seed The seed of the new random generator.
|
|
75 * @return A random generator with the given seed.
|
|
76 */
|
|
77 public Rand reseed(final long seed) {
|
|
78 return new Rand(new F<Option<Long>, F<Integer, F<Integer, Integer>>>() {
|
|
79 public F<Integer, F<Integer, Integer>> f(final Option<Long> old) {
|
|
80 return new F<Integer, F<Integer, Integer>>() {
|
|
81 public F<Integer, Integer> f(final Integer from) {
|
|
82 return new F<Integer, Integer>() {
|
|
83 public Integer f(final Integer to) {
|
|
84 return f.f(some(seed)).f(from).f(to);
|
|
85 }
|
|
86 };
|
|
87 }
|
|
88 };
|
|
89 }
|
|
90 }, new F<Option<Long>, F<Double, F<Double, Double>>>() {
|
|
91 public F<Double, F<Double, Double>> f(final Option<Long> old) {
|
|
92 return new F<Double, F<Double, Double>>() {
|
|
93 public F<Double, Double> f(final Double from) {
|
|
94 return new F<Double, Double>() {
|
|
95 public Double f(final Double to) {
|
|
96 return g.f(some(seed)).f(from).f(to);
|
|
97 }
|
|
98 };
|
|
99 }
|
|
100 };
|
|
101 }
|
|
102 });
|
|
103 }
|
|
104
|
|
105 /**
|
|
106 * Constructs a random generator from the given functions that supply a range to produce a
|
|
107 * result.
|
|
108 *
|
|
109 * @param f The integer random generator.
|
|
110 * @param g The floating-point random generator.
|
|
111 * @return A random generator from the given functions that supply a range to produce a result.
|
|
112 */
|
|
113 public static Rand rand(final F<Option<Long>, F<Integer, F<Integer, Integer>>> f, final F<Option<Long>, F<Double, F<Double, Double>>> g) {
|
|
114 return new Rand(f, g);
|
|
115 }
|
|
116
|
|
117
|
|
118 private static final F<Long, Random> fr = new F<Long, Random>() {
|
|
119 public Random f(final Long x) {
|
|
120 return new Random(x);
|
|
121 }
|
|
122 };
|
|
123
|
|
124 /**
|
|
125 * A standard random generator that uses {@link Random}.
|
|
126 */
|
|
127 public static final Rand standard = new Rand(new F<Option<Long>, F<Integer, F<Integer, Integer>>>() {
|
|
128 public F<Integer, F<Integer, Integer>> f(final Option<Long> seed) {
|
|
129 return new F<Integer, F<Integer, Integer>>() {
|
|
130 public F<Integer, Integer> f(final Integer from) {
|
|
131 return new F<Integer, Integer>() {
|
|
132 public Integer f(final Integer to) {
|
|
133 final int f = min(from, to);
|
|
134 final int t = max(from, to);
|
|
135 return f + seed.map(fr).orSome(new Random()).nextInt(t - f + 1);
|
|
136 }
|
|
137 };
|
|
138 }
|
|
139 };
|
|
140 }
|
|
141 }, new F<Option<Long>, F<Double, F<Double, Double>>>() {
|
|
142 public F<Double, F<Double, Double>> f(final Option<Long> seed) {
|
|
143 return new F<Double, F<Double, Double>>() {
|
|
144 public F<Double, Double> f(final Double from) {
|
|
145 return new F<Double, Double>() {
|
|
146 public Double f(final Double to) {
|
|
147 final double f = min(from, to);
|
|
148 final double t = max(from, to);
|
|
149 return seed.map(fr).orSome(new Random()).nextDouble() * (t - f) + f;
|
|
150 }
|
|
151 };
|
|
152 }
|
|
153 };
|
|
154 }
|
|
155 });
|
|
156 }
|