2011-07-08 02:16:46 -07:00
|
|
|
/*
|
|
|
|
|
|
|
|
Idea: provide functions for 'exhaustive' and 'random' modification of vecs.
|
|
|
|
|
|
|
|
two functions, "return all edits" and "return a random edit" <-- leaning toward this model
|
|
|
|
or
|
|
|
|
two functions, "return the number of possible edits" and "return edit #n"
|
|
|
|
|
|
|
|
It would be nice if this could be data-driven, so the two functions could share information:
|
2011-08-12 06:37:25 -07:00
|
|
|
type vec_modifier = rec(fn (&<T> v, uint i) -> [T] fun, uint lo, uint di);
|
2011-08-04 16:20:53 -07:00
|
|
|
const [vec_modifier] vec_modifiers = ~[rec(fun=vec_omit, 0u, 1u), ...];
|
2011-07-08 02:16:46 -07:00
|
|
|
But that gives me "error: internal compiler error unimplemented consts that's not a plain literal".
|
|
|
|
https://github.com/graydon/rust/issues/570
|
|
|
|
|
2011-09-10 12:03:13 -07:00
|
|
|
vec_edits is not an iter because iters might go away.
|
2011-07-08 02:16:46 -07:00
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
use std;
|
2011-08-18 14:32:25 -07:00
|
|
|
import std::vec;
|
|
|
|
import std::vec::slice;
|
|
|
|
import std::vec::len;
|
2011-07-08 02:16:46 -07:00
|
|
|
import std::int;
|
|
|
|
|
2011-09-10 12:02:24 -07:00
|
|
|
fn vec_omit<@T>(v: &[T], i: uint) -> [T] {
|
2011-07-27 14:19:39 +02:00
|
|
|
slice(v, 0u, i) + slice(v, i + 1u, len(v))
|
|
|
|
}
|
2011-09-10 12:02:24 -07:00
|
|
|
fn vec_dup<@T>(v: &[T], i: uint) -> [T] {
|
2011-08-19 15:16:48 -07:00
|
|
|
slice(v, 0u, i) + [v[i]] + slice(v, i, len(v))
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2011-09-10 12:02:24 -07:00
|
|
|
fn vec_swadj<@T>(v: &[T], i: uint) -> [T] {
|
2011-08-19 15:16:48 -07:00
|
|
|
slice(v, 0u, i) + [v[i + 1u], v[i]] + slice(v, i + 2u, len(v))
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2011-09-10 12:02:24 -07:00
|
|
|
fn vec_prefix<@T>(v: &[T], i: uint) -> [T] { slice(v, 0u, i) }
|
|
|
|
fn vec_suffix<@T>(v: &[T], i: uint) -> [T] { slice(v, i, len(v)) }
|
2011-07-08 02:16:46 -07:00
|
|
|
|
2011-09-10 12:02:24 -07:00
|
|
|
fn vec_poke<@T>(v: &[T], i: uint, x: &T) -> [T] {
|
2011-08-19 15:16:48 -07:00
|
|
|
slice(v, 0u, i) + [x] + slice(v, i + 1u, len(v))
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2011-09-10 12:02:24 -07:00
|
|
|
fn vec_insert<@T>(v: &[T], i: uint, x: &T) -> [T] {
|
2011-08-19 15:16:48 -07:00
|
|
|
slice(v, 0u, i) + [x] + slice(v, i, len(v))
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2011-07-08 02:16:46 -07:00
|
|
|
|
|
|
|
// Iterates over 0...length, skipping the specified number on each side.
|
2011-07-27 14:19:39 +02:00
|
|
|
iter ix(skip_low: uint, skip_high: uint, length: uint) -> uint {
|
|
|
|
let i: uint = skip_low;
|
|
|
|
while i + skip_high <= length { put i; i += 1u; }
|
|
|
|
}
|
2011-07-08 02:16:46 -07:00
|
|
|
|
|
|
|
// Returns a bunch of modified versions of v, some of which introduce new elements (borrowed from xs).
|
2011-09-10 12:02:24 -07:00
|
|
|
fn vec_edits<@T>(v: &[T], xs: &[T]) -> [[T]] {
|
2011-08-19 15:16:48 -07:00
|
|
|
let edits: [[T]] = [];
|
2011-07-27 14:19:39 +02:00
|
|
|
let Lv: uint = len(v);
|
|
|
|
|
|
|
|
if Lv != 1u {
|
2011-09-10 12:12:44 -07:00
|
|
|
// When Lv == 1u, this is redundant with omit.
|
|
|
|
edits += [[]];
|
|
|
|
}
|
|
|
|
if Lv >= 3u {
|
|
|
|
// When Lv == 2u, this is redundant with swap.
|
|
|
|
edits += [vec::reversed(v)];
|
2011-08-19 15:16:48 -07:00
|
|
|
}
|
|
|
|
for each i: uint in ix(0u, 1u, Lv) { edits += [vec_omit(v, i)]; }
|
|
|
|
for each i: uint in ix(0u, 1u, Lv) { edits += [vec_dup(v, i)]; }
|
|
|
|
for each i: uint in ix(0u, 2u, Lv) { edits += [vec_swadj(v, i)]; }
|
|
|
|
for each i: uint in ix(1u, 2u, Lv) { edits += [vec_prefix(v, i)]; }
|
|
|
|
for each i: uint in ix(2u, 1u, Lv) { edits += [vec_suffix(v, i)]; }
|
2011-08-15 21:54:52 -07:00
|
|
|
|
|
|
|
for each j: uint in ix(0u, 1u, len(xs)) {
|
|
|
|
for each i: uint in ix(0u, 1u, Lv) {
|
2011-08-19 15:16:48 -07:00
|
|
|
edits += [vec_poke(v, i, xs[j])];
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2011-08-15 21:54:52 -07:00
|
|
|
for each i: uint in ix(0u, 0u, Lv) {
|
2011-08-19 15:16:48 -07:00
|
|
|
edits += [vec_insert(v, i, xs[j])];
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-08 02:16:46 -07:00
|
|
|
edits
|
|
|
|
}
|
|
|
|
|
|
|
|
// Would be nice if this were built in: https://github.com/graydon/rust/issues/424
|
2011-08-04 16:20:53 -07:00
|
|
|
fn vec_to_str(v: &[int]) -> str {
|
2011-07-27 14:19:39 +02:00
|
|
|
let i = 0u;
|
|
|
|
let s = "[";
|
|
|
|
while i < len(v) {
|
2011-08-19 15:16:48 -07:00
|
|
|
s += int::str(v[i]);
|
2011-07-27 14:19:39 +02:00
|
|
|
if i + 1u < len(v) { s += ", " }
|
2011-07-08 02:16:46 -07:00
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
ret s + "]";
|
|
|
|
}
|
|
|
|
|
2011-08-04 16:20:53 -07:00
|
|
|
fn show_edits(a: &[int], xs: &[int]) {
|
2011-07-08 02:16:46 -07:00
|
|
|
log_err "=== Edits of " + vec_to_str(a) + " ===";
|
2011-07-27 14:19:39 +02:00
|
|
|
let b = vec_edits(a, xs);
|
2011-08-19 15:16:48 -07:00
|
|
|
for each i: uint in ix(0u, 1u, len(b)) { log_err vec_to_str(b[i]); }
|
2011-07-08 02:16:46 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn demo_edits() {
|
2011-08-19 15:16:48 -07:00
|
|
|
let xs = [7, 8];
|
|
|
|
show_edits([], xs);
|
|
|
|
show_edits([1], xs);
|
|
|
|
show_edits([1, 2], xs);
|
|
|
|
show_edits([1, 2, 3], xs);
|
|
|
|
show_edits([1, 2, 3, 4], xs);
|
2011-07-08 02:16:46 -07:00
|
|
|
}
|
|
|
|
|
2011-08-04 16:20:53 -07:00
|
|
|
fn main() { demo_edits(); }
|