diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2014-02-10 05:12:14 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2014-02-10 05:12:14 -0800 |
commit | 2fccb10283aae350ced4db70fcddcc95e59e503a (patch) | |
tree | a062189edc6051bcec7145857703dca6e9dfc9f6 | |
parent | 13fa06edcfa454ec0f0bb5ae6fb51c968f5dcdfd (diff) | |
download | txr-2fccb10283aae350ced4db70fcddcc95e59e503a.tar.gz txr-2fccb10283aae350ced4db70fcddcc95e59e503a.tar.bz2 txr-2fccb10283aae350ced4db70fcddcc95e59e503a.zip |
Relaxed behavior: don't throw errors for impossible permutations,
but return an empty list.
* eval.c (perm_init_common): Do not throw error; return a nil
state if permutation length exceeds sequence length.
(perm_vec, perm_list, perm_str): Check for null return from
perm_init_common and return empty list.
(k_conses): Do not throw error; return empty list.
(comb_list_gen_fun): Check for nil value out of k_conses.
(comb): For vectors and strings, check length against k and
return nil if necessary. For lists, comb_list_gen_fun handles it.
* txr.1: Section order rearranged, and updated.
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | eval.c | 46 | ||||
-rw-r--r-- | txr.1 | 66 |
3 files changed, 78 insertions, 50 deletions
@@ -1,5 +1,21 @@ 2014-02-10 Kaz Kylheku <kaz@kylheku.com> + Relaxed behavior: don't throw errors for impossible permutations, + but return an empty list. + + * eval.c (perm_init_common): Do not throw error; return a nil + state if permutation length exceeds sequence length. + (perm_vec, perm_list, perm_str): Check for null return from + perm_init_common and return empty list. + (k_conses): Do not throw error; return empty list. + (comb_list_gen_fun): Check for nil value out of k_conses. + (comb): For vectors and strings, check length against k and + return nil if necessary. For lists, comb_list_gen_fun handles it. + + * txr.1: Section order rearranged, and updated. + +2014-02-10 Kaz Kylheku <kaz@kylheku.com> + * eval.c (rcomb_while_fun, rcomb_gen_fun_common, rcomb_list_gen_fun, rcomb_list, rcomb_vec_gen_fun, rcomb_vec, rcomb_str_gen_fun, rcomb_str, rcomb): New static functions. @@ -2287,20 +2287,18 @@ static val perm_init_common(val p, val k_null) uses_or2; val n = length(p); val k = or2(k_null, n); - val state = vector(three, nil); - val c = vector(k, zero); - if (gt(k, n)) - uw_throwf(numeric_error_s, - lit("perm: permutation length ~s exceeds sequence length ~s"), - k, n, nao); - - *vecref_l(state, zero) = p; - *vecref_l(state, one) = k; - *vecref_l(state, two) = c; - *vecref_l(c, negone) = negone; - - return state; + if (gt(k, n)) { + return nil; + } else { + val state = vector(three, nil); + val c = vector(k, zero); + *vecref_l(state, zero) = p; + *vecref_l(state, one) = k; + *vecref_l(state, two) = c; + *vecref_l(c, negone) = negone; + return state; + } } static void perm_vec_gen_fill(val out, cnum i, val v) @@ -2324,6 +2322,8 @@ static val perm_vec(val p, val k) return cons(vector(zero, nil), nil); } else { val state = perm_init_common(p, k); + if (!state) + return nil; return generate(func_f0(state, perm_while_fun), func_f0(state, perm_vec_gen_fun)); } @@ -2353,6 +2353,8 @@ static val perm_list(val p, val k) return cons(nil, nil); } else { val state = perm_init_common(vector_list(p), k); + if (!state) + return nil; return generate(func_f0(state, perm_while_fun), func_f0(state, perm_list_gen_fun)); } @@ -2380,6 +2382,8 @@ static val perm_str(val p, val k) return cons(string(L""), nil); } else { val state = perm_init_common(vector_list(list_str(p)), k); + if (!state) + return nil; return generate(func_f0(state, perm_while_fun), func_f0(state, perm_str_gen_fun)); } @@ -2422,12 +2426,7 @@ static val k_conses(val list, val k) for (; consp(iter) && gt(i, zero); iter = cdr(iter), i = minus(i, one)) ptail = list_collect(ptail, iter); - if (i != zero) - uw_throwf(numeric_error_s, - lit("comb: permutation length ~s exceeds sequence length ~s"), - k, length(list), nao); - - return out; + return (i != zero) ? nil : out; } static val comb_while_fun(val state) @@ -2469,8 +2468,9 @@ static val comb_list_gen_fun(val state) static val comb_list(val list, val k) { val state = nreverse(k_conses(list, k)); - return generate(func_f0(state, comb_while_fun), - func_f0(state, comb_list_gen_fun)); + return state ? generate(func_f0(state, comb_while_fun), + func_f0(state, comb_list_gen_fun)) + : nil; } static val comb_vec_gen_fun(val state) @@ -2534,12 +2534,16 @@ static val comb(val seq, val k) case VEC: if (k == zero) return cons(vector(zero, nil), nil); + if (gt(k, length(seq))) + return nil; return comb_vec(seq, k); case STR: case LSTR: case LIT: if (k == zero) return cons(string(L""), nil); + if (gt(k, length(seq))) + return nil; return comb_str(seq, k); default: type_mismatch(lit("comb: ~s is not a sequence"), seq, nao); @@ -7869,6 +7869,37 @@ cached inside <promise> and returned, becoming the return value of the force function call. If the force function is invoked additional times on the same promise, the cached value is retrieved. +.SS Function perm + +.TP +Syntax: + + (perm <seq> [<len>]) + +.TP +Description: + +The rperm function returns a lazy list which consists of all +length <len> permutations of formed by items taken from <seq>. +The permutations do not use any element of <seq> more than once. + +Argument <len>, if present, must be a positive integer, and <seq> must be a +sequence. + +If <len> is not present, then its value defaults to the length of <seq>: +the list of the full permutations of the entire sequence is returned. + +The permutations in the returned list are sequences of the same kind as <seq>. + +If <len> is zero, then a list containing one permutation is returned, and that +permutations is of zero length. + +If <len> exceeds the length of <seq>, then an empty list is returned, +since it is impossible to make a single non-repeating permutation that +requires more items than are available. + +The permutations are lexicographically ordered. + .SS Function rperm .TP @@ -7909,34 +7940,8 @@ Examples: (rperm '(0 1 2) 2) -> ((0 0) (0 1) (0 2) (1 0) (1 1) (1 2) (2 0) (2 1) (2 2)) -.SS Function perm - -.TP -Syntax: - - (perm <seq> [<len>]) - -.TP -Description: - -The rperm function returns a lazy list which consists of all -length <len> permutations of formed by items taken from <seq>. -The permutations do not use any element of <seq> more than once. -Argument <len>, if present, must be a positive integer no greater -than the length of <seq>, and <seq> must be a sequence. - -If <len> is not present, then its value defaults to the length of <seq>: -the list of the full permutations of the entire sequence is returned. - -The permutations in the returned list are sequences of the same kind as <seq>. - -If <len> is zero, then a list containing one permutation is returned, and that -permutations is of zero length. - -The permutations are lexicographically ordered. - -.SS Functions comb and rcomb +.SS Function comb .TP Syntax: @@ -7952,14 +7957,17 @@ length <len> non-repeating combinations formed by taking items taken from element of <seq> more than once. If <seq> contains no duplicates, then the combinations contain no duplicates. -Argument <len> must be a nonnegative integer no greater than the length of -<seq>, and <seq> must be a sequence. +Argument <len> must be a nonnegative integer, and <seq> must be a sequence. The combinations in the returned list are sequences of the same kind as <seq>. If <len> is zero, then a list containing one combination is returned, and that permutations is of zero length. +If <len> exceeds the length of <seq>, then an empty list is returned, +since it is impossible to make a single non-repeating combination that +requires more items than are available. + The combinations are lexicographically ordered. .SS Function rcomb |