summaryrefslogtreecommitdiff
path: root/base/src/main/java/bjc/utils/funcutils/FuncUtils.java
blob: 2c65876072dd0c89cd040b932f05469e5c0b64f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package bjc.utils.funcutils;

import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.UnaryOperator;

/**
 * Utility things for functions.
 *
 * @author ben
 */
public class FuncUtils {
	/**
	 * Convert a binary function into a unary function that returns a function.
	 *
	 * @param <A>
	 *             The initial type of the function.
	 *
	 * @param <B>
	 *             The intermediate type of the function.
	 *
	 * @param <C>
	 *             The terminal type of the function.
	 *
	 * @param func
	 *             The function to transform.
	 *
	 * @return The function transformed into a unary function returning a function.
	 */
	public static <A, B, C> Function<A, Function<B, C>> curry2(
			final BiFunction<A, B, C> func)
	{
		return arg1 ->
			arg2 ->
				func.apply(arg1, arg2);
	}

	/**
	 * Do the specified action the specified number of times.
	 *
	 * @param nTimes
	 *               The number of times to do the action.
	 *
	 * @param cons
	 *               The action to perform.
	 */
	public static void doTimes(
			final int nTimes,
			final Consumer<Integer> cons) 
	{
		for (int i = 0; i < nTimes; i++) cons.accept(i);
	}

	/**
	 * Return an operator that executes until it converges.
	 * 
	 * @param <T> The type the operator is on.
	 *
	 * @param op
	 *                 The operator to execute.
	 *
	 * @param maxTries
	 *                 The maximum amount of times to apply the function in an
	 *                 attempt to cause it to converge.
	 *
	 * @return The requested operator.
	 */
	public static <T> UnaryOperator<T> converge(final UnaryOperator<T> op,
			final int maxTries) 
	{
		return converge(op, Object::equals, maxTries);
	}

	/**
	 * Return an operator that executes until it converges.
	 * 
	 * @param <T> The type the operator is on.
	 *
	 * @param op
	 *                  The operator to execute.
	 * @param converged
	 *                  The predicate to execute to check if the function has
	 *                  converged.
	 *
	 * @param maxTries
	 *                  The maximum amount of times to apply the function in an
	 *                  attempt to cause it to converge.
	 *
	 * @return The requested operator.
	 */
	public static <T> UnaryOperator<T> converge(
			final UnaryOperator<T> op,
			final BiPredicate<T, T> converged,
			final int maxTries) 
	{
		return val -> {
			T newVal = op.apply(val);
			T oldVal = newVal;

			int tries = 0;

			do {
				oldVal = newVal;
				newVal = op.apply(newVal);

				tries += 1;
			} while (!converged.test(newVal, oldVal) && tries < maxTries);

			return newVal;
		};
	}
}