Discussion:
How do i get multiple Min() values?
(too old to reply)
HenHanna
2024-07-12 09:49:41 UTC
Permalink
How do i get multiple Min() values?

e.g. for Y = (x-2)*(x-3) for x in range(-10,10)
the min Y is hit twice


print( min( ((x-2)*(x-3), (x, (x-2, x-3)))
for x in range(-10,10) ) )



is this easy in Scheme(Gauche) ?
HenHanna
2024-07-12 19:00:22 UTC
Permalink
Post by HenHanna
How do i get multiple Min() values?
          e.g.      for   Y = (x-2)*(x-3)   for x in range(-10,10)
                                   the min Y is hit twice
print(  min( ((x-2)*(x-3),  (x, (x-2, x-3)))
                                           for x in range(-10,10) ) )
is this easy in Scheme(Gauche) ?
if the Min() is going to check all of the Candidate values,
it could (at least) tell us how many times the Min value was seen!
Kaz Kylheku
2024-07-15 12:27:58 UTC
Permalink
Post by HenHanna
Post by HenHanna
How do i get multiple Min() values?
          e.g.      for   Y = (x-2)*(x-3)   for x in range(-10,10)
                                   the min Y is hit twice
print(  min( ((x-2)*(x-3),  (x, (x-2, x-3)))
                                           for x in range(-10,10) ) )
is this easy in Scheme(Gauche) ?
if the Min() is going to check all of the Candidate values,
it could (at least) tell us how many times the Min value was seen!
I decided to add something like this to TXR Lisp.

It will appear in 296.

This is the TXR Lisp interactive listener of TXR 295.
Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet.
When transferring between containers, do not siphon TXR by mouth.
1> (find-mins -10..11 : [callf * pppred ppred])
(2 3)
2> (find-mins (vec-seq -10..11) : [callf * pppred ppred])
#(2 3)
3> (find-mins "abracadabra")
"aaaaa"
4> (find-maxes "abracacabra")
"rr"

I works with any less-like function, assuming equality
when it’s neither true that x is less than y, nor that
y is less than x.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Madhu
2024-07-16 15:45:55 UTC
Permalink
Post by Kaz Kylheku
Post by HenHanna
Post by HenHanna
How do i get multiple Min() values?
You just need the count of the min value. you don't really need
"multiple min() values". right?
Post by Kaz Kylheku
Post by HenHanna
Post by HenHanna
e.g. for Y = (x-2)*(x-3) for x in range(-10,10)
the min Y is hit twice
print( min( ((x-2)*(x-3), (x, (x-2, x-3)))
for x in range(-10,10) ) )
is this easy in Scheme(Gauche) ?
if the Min() is going to check all of the Candidate values,
it could (at least) tell us how many times the Min value was seen!
I decided to add something like this to TXR Lisp.
It will appear in 296.
This is the TXR Lisp interactive listener of TXR 295.
Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet.
When transferring between containers, do not siphon TXR by mouth.
1> (find-mins -10..11 : [callf * pppred ppred])
(2 3)
2> (find-mins (vec-seq -10..11) : [callf * pppred ppred])
#(2 3)
3> (find-mins "abracadabra")
"aaaaa"
4> (find-maxes "abracacabra")
"rr"
I works with any less-like function, assuming equality
when it's neither true that x is less than y, nor that
y is less than x.
Ugh. One would think it is be trivial in CL to track the min-count as a
wrapper around (reduce #'min list)

but the REDUCE spec makes it hairy to get edge cases right (where the
input is an empty list or singleton list).

(defun hen-min (list &aux (min-count 1))
"LIST is a list of numbers. Return the MIN of the list. Second
return value is the count of the MIN in the given LIST"
(values (reduce (lambda (&optional a b)
(when a
(prog1 (min a b)
(cond ((< b a) (setq min-count 1))
((= b a) (incf min-count))))))
list)
(if (endp list) 0 min-count)))

It still reads nicer without any [???]
Madhu
2024-07-16 16:43:46 UTC
Permalink
Post by Madhu
Post by Kaz Kylheku
Post by HenHanna
Post by HenHanna
How do i get multiple Min() values?
You just need the count of the min value. you don't really need
"multiple min() values". right?
Post by Kaz Kylheku
Post by HenHanna
Post by HenHanna
e.g. for Y = (x-2)*(x-3) for x in range(-10,10)
the min Y is hit twice
print( min( ((x-2)*(x-3), (x, (x-2, x-3)))
for x in range(-10,10) ) )
is this easy in Scheme(Gauche) ?
if the Min() is going to check all of the Candidate values,
it could (at least) tell us how many times the Min value was seen!
I decided to add something like this to TXR Lisp.
It will appear in 296.
This is the TXR Lisp interactive listener of TXR 295.
Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet.
When transferring between containers, do not siphon TXR by mouth.
1> (find-mins -10..11 : [callf * pppred ppred])
(2 3)
2> (find-mins (vec-seq -10..11) : [callf * pppred ppred])
#(2 3)
3> (find-mins "abracadabra")
"aaaaa"
4> (find-maxes "abracacabra")
"rr"
I works with any less-like function, assuming equality
when it's neither true that x is less than y, nor that
y is less than x.
Ugh. One would think it is
trivial in CL to track the min-count as a
wrapper around (reduce #'min list)
but the REDUCE spec makes it hairy to get edge cases right (where the
input is an empty list or singleton list).
(defun hen-min (list &aux (min-count 1))
"LIST is a list of numbers. Return the MIN of the list. Second
return value is the count of the MIN in the given LIST"
(values (reduce (lambda (&optional a b)
(when a
(prog1 (min a b)
(cond ((< b a) (setq min-count 1))
((= b a) (incf min-count))))))
list)
(if (endp list) 0 min-count)))
It still reads nicer without any [???]
Hen may have fallen into the "list comprehension sytnax" in constructing
the example he posted. But this is just a tar pit, which lets you lose
focus of the problem at hand (by inventing new problems)

in common lisp HEN-MAX has been extended MAX to return a second return
value with counts. This is the simplest abstraction to construct
solutions which require counts of MIN, and is sufficient for common
lisp, without the need to invent a new language feature or inventing new
syntax.

while CL has several generator libraries (which I haven't really used
seriously yet), in plain CL Hen's motivating example above would look
like this:

(loop for x from -10 to 10
collect (* (- x 2) (- x 3)) into A
collect x into B
collect (- x 2) into C
collect (- x 3) into D
finally (return (destructuring-bind (a b c d)
(mapcar (lambda (x)
(multiple-value-list (hen-min x)))
(list a b c d))
(values
(destructuring-bind (a b c d)
(mapcar 'car (list a b c d))
`(,a (,b (,c ,d))))
(destructuring-bind (a b c d)
(mapcar 'cadr (list a b c d))
`(,a (,b (,c ,d))))))))

;; => (0 (-10 (-12 -13))),
;; (2 (1 (1 1)))


The first value returns the minimum in the "compehended invented "tuple
structure, the second value returns the counts in the same structure.
Nuno Silva
2024-07-17 09:58:20 UTC
Permalink
Post by Madhu
Post by HenHanna
How do i get multiple Min() values?
You just need the count of the min value. you don't really need
"multiple min() values". right?
I'm thinking it depends on what kind of entities you are comparing, if
you are using some comparison function to determine what the multiple
minima are, isn't it possible to have multiple minima which are
different objects one might want to see as multiple values, and not
something that can be duplicated from a single copy?

Sure, you could optimize for numbers, but that'd make it less flexible
too?
--
Nuno Silva
B. Pym
2024-07-13 12:56:23 UTC
Permalink
Post by HenHanna
How do i get multiple Min() values?
e.g. for Y = (x-2)*(x-3) for x in range(-10,10)
the min Y is hit twice
print( min( ((x-2)*(x-3), (x, (x-2, x-3)))
for x in range(-10,10) ) )
is this easy in Scheme(Gauche) ?
Gauche Scheme

(use gauche.collection) ;; fold2

(define (min-by fn lst)
(if (null? lst)
(values '() #f)
(fold2
(lambda (x best worth)
(let ((score (fn x)))
(cond ((< score worth) (values (list x) score))
((= score worth) (values (cons x best) worth))
(#t (values best worth)))))
(take lst 1) (fn (car lst))
(cdr lst))))

(min-by (lambda(x) (* (- x 2) (- x 3))) (lrange -10 11))

===>
(3 2)
0
HenHanna
2024-07-13 18:06:04 UTC
Permalink
Post by B. Pym
Post by HenHanna
How do i get multiple Min() values?
e.g. for Y = (x-2)*(x-3) for x in range(-10,10)
the min Y is hit twice
print( min( ((x-2)*(x-3), (x, (x-2, x-3)))
for x in range(-10,10) ) )
is this easy in Scheme(Gauche) ?
Gauche Scheme
(use gauche.collection) ;; fold2
(define (min-by fn lst)
(if (null? lst)
(values '() #f)
(fold2
(lambda (x best worth)
(let ((score (fn x)))
(cond ((< score worth) (values (list x) score))
((= score worth) (values (cons x best) worth))
(#t (values best worth)))))
(take lst 1) (fn (car lst))
(cdr lst))))
(min-by (lambda(x) (* (- x 2) (- x 3))) (lrange -10 11))
===>
(3 2)
0
Thank you... i think Python and Scheme(Gauche) should give
me this by default:

a list(collection) of all the
( key1 "data1" ... etc )
( key2 "data2" ... etc ) ...

for which the Min key value was seen.
B. Pym
2024-07-13 19:11:07 UTC
Permalink
Post by B. Pym
Post by HenHanna
How do i get multiple Min() values?
e.g. for Y = (x-2)*(x-3) for x in range(-10,10)
the min Y is hit twice
print( min( ((x-2)*(x-3), (x, (x-2, x-3)))
for x in range(-10,10) ) )
is this easy in Scheme(Gauche) ?
Gauche Scheme
(use gauche.collection) ;; fold2
(define (min-by fn lst)
(if (null? lst)
(values '() #f)
(fold2
(lambda (x best worth)
(let ((score (fn x)))
(cond ((< score worth) (values (list x) score))
((= score worth) (values (cons x best) worth))
(#t (values best worth)))))
(take lst 1) (fn (car lst))
(cdr lst))))
(min-by (lambda(x) (* (- x 2) (- x 3))) (lrange -10 11))
===>
(3 2)
0
(use gauche.collection) ;; fold2

(define (min-max-by fn lst)
(define (use compare x score best worth)
(cond ((compare score worth) (list (list x) score))
((= score worth) (list (cons x best) worth))
(#t (list best worth))))
(if (null? lst)
(values (list '() #f) (list '() #f))
(let ((initial (list (take lst 1) (fn (car lst)))))
(fold2
(lambda (x mini maxi)
(let ((score (fn x)))
(values
(apply use < x score mini)
(apply use > x score maxi))))
initial initial
(cdr lst)))))

(min-max-by (lambda(x) (* (- x 2) (- x 3))) (lrange -10 11))

===>
((3 2) 0)
((-10) 156)
B. Pym
2024-08-15 03:33:46 UTC
Permalink
Post by B. Pym
Post by HenHanna
How do i get multiple Min() values?
e.g. for Y = (x-2)*(x-3) for x in range(-10,10)
the min Y is hit twice
print( min( ((x-2)*(x-3), (x, (x-2, x-3)))
for x in range(-10,10) ) )
is this easy in Scheme(Gauche) ?
Gauche Scheme
(use gauche.collection) ;; fold2
(define (min-by fn lst)
(if (null? lst)
(values '() #f)
(fold2
(lambda (x best worth)
(let ((score (fn x)))
(cond ((< score worth) (values (list x) score))
((= score worth) (values (cons x best) worth))
(#t (values best worth)))))
(take lst 1) (fn (car lst))
(cdr lst))))
(min-by (lambda(x) (* (- x 2) (- x 3))) (lrange -10 11))
===>
(3 2)
0
newLISP

(define (min-by fun lst)
(let (accum '() best 0 score 0)
(dolist (x lst)
(setf score (fun x))
(cond ((or (empty? accum) (< score best))
(setf best score)
(setf accum (list x)))
((= score best) (push x accum))))
(list accum best)))

(min-by (fn(n) (- (abs (* 10 n)))) '(0 9 2 2 -9 3))
===>
((-9 9) -90)

Loading...