diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2024-07-16 14:37:03 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2024-07-16 14:37:03 -0700 |
commit | 75aea89bbccab9c7629510298c01115ccca08cc1 (patch) | |
tree | 76f7bf6d5ea62d53b63408b6237ccc12f9768a3e | |
parent | 7dbdc52b4351a44b5d5e18a2fa73ec2f2c16d4c2 (diff) | |
download | txr-75aea89bbccab9c7629510298c01115ccca08cc1.tar.gz txr-75aea89bbccab9c7629510298c01115ccca08cc1.tar.bz2 txr-75aea89bbccab9c7629510298c01115ccca08cc1.zip |
New functions: find-maxes and find-mins.
* eval.c (eval_init): New intrinsic functions find-maxes and
find-mins.
* lib.[ch] (find_maxes, find_mins): New function.
* tests/012/seq.tl: New tests.
* txr.1: Documented.
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | lib.c | 37 | ||||
-rw-r--r-- | lib.h | 2 | ||||
-rw-r--r-- | tests/012/seq.tl | 22 | ||||
-rw-r--r-- | txr.1 | 25 |
5 files changed, 86 insertions, 2 deletions
@@ -7794,8 +7794,10 @@ void eval_init(void) reg_fun(intern(lit("find-if"), user_package), func_n3o(find_if, 2)); reg_fun(intern(lit("rfind-if"), user_package), func_n3o(rfind_if, 2)); reg_fun(intern(lit("find-max"), user_package), func_n3o(find_max, 1)); + reg_fun(intern(lit("find-maxes"), user_package), func_n3o(find_maxes, 1)); reg_fun(intern(lit("find-max-key"), user_package), func_n3o(find_max_key, 1)); reg_fun(intern(lit("find-min"), user_package), func_n3o(find_min, 1)); + reg_fun(intern(lit("find-mins"), user_package), func_n3o(find_mins, 1)); reg_fun(intern(lit("find-min-key"), user_package), func_n3o(find_min_key, 1)); reg_fun(intern(lit("find-true"), user_package), func_n3o(find_true, 2)); reg_fun(intern(lit("multi-sort"), user_package), func_n3o(multi_sort, 2)); @@ -12055,6 +12055,38 @@ val find_max(val seq, val testfun_in, val keyfun_in) return nil; } +val find_maxes(val seq, val testfun_in, val keyfun_in) +{ + val self = lit("find-maxes"); + val testfun = default_arg(testfun_in, greater_f); + val keyfun = default_arg(keyfun_in, identity_f); + seq_iter_t iter; + val elem; + seq_build_t build; + + seq_iter_init(self, &iter, seq); + seq_build_init(self, &build, seq); + + if (seq_get(&iter, &elem)) { + val maxkey = funcall1(keyfun, elem); + + seq_add(&build, elem); + + while (seq_get(&iter, &elem)) { + val key = funcall1(keyfun, elem); + if (funcall2(testfun, key, maxkey)) { + maxkey = key; + seq_build_init(self, &build, seq); + seq_add(&build, elem); + } else if (!funcall2(testfun, maxkey, key)) { + seq_add(&build, elem); + } + } + } + + return seq_finish(&build); +} + val find_max_key(val seq, val testfun_in, val keyfun_in) { val self = lit("find-max-key"); @@ -12085,6 +12117,11 @@ val find_min(val seq, val testfun, val keyfun) return find_max(seq, default_arg(testfun, less_f), keyfun); } +val find_mins(val seq, val testfun, val keyfun) +{ + return find_maxes(seq, default_arg(testfun, less_f), keyfun); +} + val find_min_key(val seq, val testfun, val keyfun) { return find_max_key(seq, default_arg(testfun, less_f), keyfun); @@ -1400,8 +1400,10 @@ val rfind(val list, val key, val testfun, val keyfun); val find_if(val pred, val list, val key); val rfind_if(val pred, val list, val key); val find_max(val seq, val testfun, val keyfun); +val find_maxes(val seq, val testfun_in, val keyfun_in); val find_max_key(val seq, val testfun, val keyfun); val find_min(val seq, val testfun, val keyfun); +val find_mins(val seq, val testfun, val keyfun); val find_min_key(val seq, val testfun, val keyfun); val find_true(val pred, val list, val keyfun); val posqual(val obj, val list); diff --git a/tests/012/seq.tl b/tests/012/seq.tl index 45cf2b67..171ad300 100644 --- a/tests/012/seq.tl +++ b/tests/012/seq.tl @@ -464,6 +464,28 @@ [find-max-key '("alpha" "charlie" "aardvark" "bravo") less upcase-str] "AARDVARK" [find-max-key #H(() (a 1) (b 2) (c 3)) : cdr] 3) +(mtest + (find-maxes nil) nil + (find-maxes '(1 1 1 1 1)) (1 1 1 1 1) + (find-maxes '(2 1 1 1 1)) (2) + (find-maxes '(2 1 1 1 2)) (2 2) + (find-maxes '(2 1 2 1 2)) (2 2 2)) + +(mtest + (find-maxes #()) #() + (find-maxes '(1 1 1 1 1)) (1 1 1 1 1) + (find-maxes '(2 1 1 1 1)) (2) + (find-maxes '(2 1 1 1 2)) (2 2) + (find-maxes '(2 1 2 1 2)) (2 2 2)) + +(mtest + (find-maxes "") "" + (find-maxes "abracadabra") "rr" + (find-mins "abracadabra") "aaaaa") + +(test + (find-mins -10..11 : [callf * pppred ppred]) (2 3)) + (defvarl fn (do and (chr-isdigit @1) (not (chr-isdigit @2)))) @@ -37729,6 +37729,27 @@ is the one that is reported. See the notes under .code pos-max regarding duplicate maxima. +.coNP Functions @ find-maxes and @ find-mins +.synb +.mets (find-maxes < iterable >> [ testfun <> [ keyfun ]]) +.mets (find-mins < iterable >> [ testfun <> [ keyfun ]]) +.syne +.desc +The +.code find-maxes +and +.code find-mins +functions have the same argument conventions as, respectively, +.code find-max +and +.codn find-min . +These functions differ in that they return a sequence of all the elements of +.meta iterable +which maximize the value of +.metn keyfun . +The returned sequence is of the same kind as +.metn iterable . + .coNP Functions @ find-max-key and @ find-min-key .synb .mets (find-max-key < iterable [ testfun <> [ keyfun ]]) @@ -37736,9 +37757,9 @@ regarding duplicate maxima. .syne .desc The -.code find-min-key -and .code find-max-key +and +.code find-min-key functions have the same argument conventions as, respectively, .code find-max and |