1 /// Algorithms for doing calculations on a range.
2 module tern.algorithm.iteration;
3 
4 import tern.traits;
5 import tern.object : loadLength;
6 import tern.functional;
7 
8 public:
9 /**
10  * Calculates the distance between `comparer` and `comparee`.
11  *
12  * Params:
13  *  comparee = The string to calculate from.
14  *  comparee = The string to calculate against.
15  *
16  * Returns:
17  *  The distance between `comparer` and `comparee`.
18  *
19  * Remarks:
20  *  `A` and `B` must both be string types.
21  */
22 size_t levenshteinDistance(A, B)(A comparer, B comparee) pure nothrow
23     if (isString!A && isString!B)
24 {
25     auto m = comparer.length + 1;
26     auto n = comparee.length + 1;
27 
28     size_t[] dp;
29 
30     dp.length = n;
31 
32     foreach (j; 0..n)
33         dp[j] = j;
34 
35     size_t diag;
36     size_t top;
37     size_t left;
38 
39     foreach (i; 1..m)
40     {
41         diag = i - 1;
42         top = i;
43 
44         foreach (j; 1..n)
45         {
46             left = dp[j];
47             int cost = (comparer[i - 1] == comparee[j - 1]) ? 0 : 1;
48             dp[j] = top + 1;
49 
50             if (dp[j - 1] + 1 < dp[j])
51                 dp[j] = dp[j - 1] + 1;
52 
53             if (diag + cost < dp[j])
54                 dp[j] = diag + cost;
55 
56             diag = left;
57             top = dp[j];
58         }
59     }
60 
61     return dp[n - 1];
62 }
63 
64 /**
65  * Calculates the difference between `comparer` and `comparee`.
66  *
67  * Params:
68  *  comparee = The range to calculate from.
69  *  comparee = The range to calculate against.
70  *
71  * Returns:
72  *  The difference between `comparer` and `comparee`.
73  */
74 size_t difference(A, B)(A comparer, B comparee)
75     if (isIndexable!A && isIndexable!B)
76 {
77     size_t ret = comparer.loadLength - comparee.length;
78     foreach (i; 0..comparee.loadLength)
79     {
80         if (i >= comparer.length)
81             return ret;
82 
83         if (comparee[i] != comparer[i])
84             ret++;
85     }
86     return ret;
87 }
88 
89 /**
90  * Calculates the sum of all values in `range`.
91  *
92  * Params:
93  *  range = The range to sum.
94  *
95  * Returns:
96  *  The sum of all values in `range`.
97  */
98 ElementType!T sum(T)(T range)
99     if (isForward!T && isIntegral!(ElementType!T))
100 {
101     ElementType!T sum;
102     foreach (u; range)
103         sum += u;
104     return sum;
105 }
106 
107 /**
108  * Calculates the mean of all values in `range`.
109  *
110  * Params:
111  *  range = The range to mean.
112  *
113  * Returns:
114  *  The mean of all values in `range`.
115  */
116 ElementType!T mean(T)(T range)
117     if (isIndexable!T && isIntegral!(ElementType!T))
118 {
119     return range.sum / range.loadLength;
120 }
121 
122 /**
123  * Folds all values in `range` based on a predicate.
124  *
125  * Params:
126  *  F = The function to use for folding.
127  *  range = The range to fold.
128  *
129  * Returns:
130  *  Return value of `F` after folding.
131  */
132 auto fold(alias F, T)(T range)
133     if (isIndexable!T && isCallable!F)
134 {
135     return range.plane!(F, () => true);
136 }
137 
138 /**
139  * Creates an array of all unique values in `range`.
140  *
141  * Params:
142  *  range = The range to search for uniques in.
143  *
144  * Returns:
145  *  An array of all unique values in `range`.
146  */
147 ElementType!T[] uniq(T)(T range)
148     if (isIndexable!T)
149 {
150     bool[ElementType!T] ret;
151     foreach (u; range)
152     {
153         if (u !in ret)
154             ret[u] = true;
155     }
156     return ret.keys;
157 }
158 
159 /**
160  * Gets the last value in `range` that abides by `F`, or the default value of `T`.
161  *
162  * Params:
163  *  F = The function predicate.
164  *  range = The range to be predicated.
165  *
166  * Returns:
167  *  The last value in `range` that abides by `F`, or the default value of `T`.
168  */
169 ElementType!T lastOrDefault(alias F, T)(T range)
170     if (isIndexable!T && isCallable!F)
171 {
172     auto ret = range.filter!F;
173     return ret.length == 0 ? T.init : ret[$-1];
174 }
175 
176 /**
177  * Gets the first value in `range` that abides by `F`, or the default value of `T`.
178  *
179  * Params:
180  *  F = The function predicate.
181  *  range = The range to be predicated.
182  *
183  * Returns:
184  *  The first value in `range` that abides by `F`, or the default value of `T`.
185  */
186 ElementType!T firstOrDefault(alias F, T)(T range)
187     if (isIndexable!T && isCallable!F)
188 {
189     auto ret = range.filter!F;
190     return ret.length == 0 ? T.init : ret[0];
191 }
192 
193 /**
194  * Concats `range` to itself `iter` times.
195  *
196  * Params:
197  *  range = The range to repeat.
198  *  iter = The number of iterations to repeat.
199  *
200  * Returns:
201  *  The new repeated form of `range`.
202  */
203 T repeat(T)(T range, size_t iter)
204 {
205     T ret = range;
206     foreach (i; 0..iter)
207         ret ~= range;
208     return ret;
209 }
210 
211 /**
212  * Creates a `size_t[][]` holding every indices combination of a range of `length`.
213  *
214  * Params:
215  *  length = Length of hypothetical range to derive combinations from.
216  *
217  * Returns:
218  *  `size_t[][]` containing every indices combination of a range of `length`.
219  */
220 size_t[][] combinations(size_t length) pure nothrow
221 {
222     size_t[][] ret;
223     foreach (i; 0..(1 << length)) 
224     {
225         size_t[] combination;
226         foreach (j; 0..length) 
227         {
228             if (i & (1 << j))
229                 combination ~= j;
230         }
231         ret ~= combination;
232     }
233     return ret;
234 }