3 Idea: provide functions for 'exhaustive' and 'random' modification of vecs.
5 two functions, "return all edits" and "return a random edit" <-- leaning toward this model
7 two functions, "return the number of possible edits" and "return edit #n"
9 It would be nice if this could be data-driven, so the two functions could share information:
10 type vec_modifier = rec(fn (&T[] v, uint i) -> T[] fun, uint lo, uint di);
11 const vec_modifier[] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...];
12 But that gives me "error: internal compiler error unimplemented consts that's not a plain literal".
13 https://github.com/graydon/rust/issues/570
15 vec_edits is not an iter because iters might go away and:
16 https://github.com/graydon/rust/issues/639
18 vec_omit and friends are not type-parameterized because:
19 https://github.com/graydon/rust/issues/640
25 import std::ivec::slice;
26 import std::ivec::len;
29 //fn vec_reverse(&T[] v) -> T[] { ... }
31 fn vec_omit [T] (&T[] v, uint i) -> T[] { slice(v, 0u, i) + slice(v, i+1u, len(v)) }
32 fn vec_dup [T] (&T[] v, uint i) -> T[] { slice(v, 0u, i) + ~[v.(i)] + slice(v, i, len(v)) }
33 fn vec_swadj [T] (&T[] v, uint i) -> T[] { slice(v, 0u, i) + ~[v.(i+1u), v.(i)] + slice(v, i+2u, len(v)) }
34 fn vec_prefix [T] (&T[] v, uint i) -> T[] { slice(v, 0u, i) }
35 fn vec_suffix [T] (&T[] v, uint i) -> T[] { slice(v, i, len(v)) }
37 fn vec_poke [T] (&T[] v, uint i, &T x) -> T[] { slice(v, 0u, i) + ~[x] + slice(v, i+1u, len(v)) }
38 fn vec_insert [T] (&T[] v, uint i, &T x) -> T[] { slice(v, 0u, i) + ~[x] + slice(v, i, len(v)) }
40 // Iterates over 0...length, skipping the specified number on each side.
41 iter ix(uint skip_low, uint skip_high, uint length) -> uint { let uint i = skip_low; while (i + skip_high <= length) { put i; i += 1u; } }
43 // Returns a bunch of modified versions of v, some of which introduce new elements (borrowed from xs).
44 fn vec_edits[T](&T[] v, &T[] xs) -> T[][] {
45 let T[][] edits = ~[];
48 if (Lv != 1u) { edits += ~[~[]]; } // When Lv == 1u, this is redundant with omit
49 //if (Lv >= 3u) { edits += ~[vec_reverse(v)]; }
51 for each (uint i in ix(0u, 1u, Lv)) { edits += ~[vec_omit (v, i)]; }
52 for each (uint i in ix(0u, 1u, Lv)) { edits += ~[vec_dup (v, i)]; }
53 for each (uint i in ix(0u, 2u, Lv)) { edits += ~[vec_swadj (v, i)]; }
54 for each (uint i in ix(1u, 2u, Lv)) { edits += ~[vec_prefix(v, i)]; }
55 for each (uint i in ix(2u, 1u, Lv)) { edits += ~[vec_suffix(v, i)]; }
57 for each (uint j in ix(0u, 1u, len(xs))) {
58 for each (uint i in ix(0u, 1u, Lv)) { edits += ~[vec_poke (v, i, xs.(j))]; }
59 for each (uint i in ix(0u, 0u, Lv)) { edits += ~[vec_insert(v, i, xs.(j))]; }
65 // Would be nice if this were built in: https://github.com/graydon/rust/issues/424
66 fn vec_to_str(&int[] v) -> str {
71 if (i + 1u < len(v)) {
79 fn show_edits(&int[] a, &int[] xs) {
80 log_err "=== Edits of " + vec_to_str(a) + " ===";
81 auto b = vec_edits(a, xs);
82 for each (uint i in ix(0u, 1u, len(b))) {
83 log_err vec_to_str(b.(i));
91 show_edits(~[1,2], xs);
92 show_edits(~[1,2,3], xs);
93 show_edits(~[1,2,3,4], xs);