I try to bundle elements of a list serially as sums of a specific
quantity.
For instance as sums of 1: '( (.75 .25) (.50 .25 .25) (.25 .25 .25 .
25))
Can anybody help me?
mahatGma wrote:
> I try to bundle elements of a list serially as sums of a specific
> quantity.
> For instance as sums of 1: '( (.75 .25) (.50 .25 .25) (.25 .25 .25 .25))
> Can anybody help me?
You haven't done a very good job of explaining what
you're trying to accomplish, but you might start by
using exact instead of inexact numbers:
'( (3/4 1/4) (1/2 1/4 1/4) (1/4 1/4 1/4 1/4))
Remember: Only you can prevent roundoff errors.
Will
William James <·········@yahoo.com> writes:
> On Feb 22, 3:50 pm, Pascal Bourguignon <····@informatimago.com> wrote:
>> mahatGma <········@gmail.com> writes:
>> > I try to bundle elements of a list serially as sums of a specific
>> > quantity.
>> > For instance as sums of 1: '( (.75 .25) (.50 .25 .25) (.25 .25 .25 .
>> > 25))
>> > Can anybody help me?
>>
>> It doesn't look like you're thinking too much...
>>
>> (defun find-compositions (op- op< op0 target tokens)
>> (cond
>> ((endp tokens)
>> '())
>> ((or (funcall op< (funcall op- target (first tokens)) op0))
>> (find-compositions op- op< op0 target (rest tokens)))
>> ((funcall op< op0 (funcall op- target (first tokens)))
>> (append (mapcar (lambda (subcomposition) (cons (first tokens) subcomposition))
>> (find-compositions op- op< op0 (funcall op- target (first tokens))
>> (rest tokens)))
>> (find-compositions op- op< op0 target (rest tokens))))
>> (t
>> (append (list (list (first tokens)))
>> (find-compositions op- op< op0 target (rest tokens))))))
>>
>> (find-compositions (function -) (function <) 0
>> 100/100 '(75/100 25/100 25/100 50/100 25/100 25/100))
>> --> ((3/4 1/4) (3/4 1/4) (3/4 1/4) (3/4 1/4) (1/4 1/4 1/2) (1/4 1/4 1/4 1/4) (1/4 1/2 1/4)
>> (1/4 1/2 1/4) (1/4 1/2 1/4) (1/4 1/2 1/4) (1/2 1/4 1/4))
>
> A Ruby way:
>
> class Array
> def group_till &block
> a = [[]]
> self.each{|x|
> a << [] if block[ a[-1] ]
> a[-1] << x }
> a
> end
> end
>
> p [0.75,0.25,0.50,0.25,0.25,0.25,0.25,0.25,0.25].
> group_till{|a| a.inject(0){|s,x| s+x} >= 1.0 }
>
> --> [[0.75, 0.25], [0.5, 0.25, 0.25], [0.25, 0.25, 0.25, 0.25]]
Now try:
(defun explode (symbol)
;; too bad we lost this function between LISP 1.5 and CL... ;-)
(map 'list (lambda (ch) (intern (string ch))) (string symbol)))
(defun strict-subsetp (a b)
(and (subsetp a b) (not (subsetp b a))))
(find-compositions (function set-difference)
(function strict-subsetp)
'()
'(a e i o u y)
(mapcar (function explode)
'(you cannot really appreciate dilbert
unless you read it in the original
klingon)))
-->
(((Y O U) (C A N N O ...) (R E A L L ...) (A P P R E ...))
((Y O U) (C A N N O ...) (R E A L L ...) (D I L B E ...))
((Y O U) (C A N N O ...) (R E A L L ...) (U N L E S ...) (Y O U) ...)
((Y O U) (C A N N O ...) (R E A L L ...) (U N L E S ...) (Y O U) ...)
((Y O U) (C A N N O ...) (R E A L L ...) (U N L E S ...) (Y O U) ...) ...)
>> If you don't want duplicates:
>>
>> (remove-duplicates (find-compositions (function -) (function <) 0
>> 100/100 '(75/100 25/100 25/100 50/100 25/100 25/100))
>> :test (lambda (a b) (and (subsetp a b :test (function =))
>> (subsetp b a :test (function =)))))
>
> Use .uniq.
.uniq doesn't take an equal predicate as argument, so you just cannot
use it.
(remove-duplicates
(find-compositions (function set-difference)
(function strict-subsetp)
'()
'(a e i o u y)
(mapcar (function explode)
'(you cannot really appreciate dilbert
unless you read it in the original
klingon)))
:test (lambda (a b)
(and (subsetp a b :test (function equal))
(subsetp b a :test (function equal)))))
-->
(((C A N N O ...) (R E A L L ...) (A P P R E ...) (D I L B E ...)
(U N L E S ...))
((C A N N O ...) (R E A L L ...) (A P P R E ...) (D I L B E ...) (Y O U))
((C A N N O ...) (R E A L L ...) (A P P R E ...) (U N L E S ...))
((C A N N O ...) (R E A L L ...) (A P P R E ...) (Y O U))
((C A N N O ...) (R E A L L ...) (D I L B E ...) (U N L E S ...)) ...)
<humour>Please don't polute this professionnal programming language
newsgroup with your toy language. We've got serrious stuff to do
here.</humour>
--
__Pascal Bourguignon__ http://www.informatimago.com/
"You cannot really appreciate Dilbert unless you read it in the
original Klingon"
On Feb 23, 6:03 am, Pascal Bourguignon <····@informatimago.com> wrote:
> William James <·········@yahoo.com> writes:
> > Use .uniq.
>
> .uniq doesn't take an equal predicate as argument, so you just cannot
> use it.
Ruby's Array#uniq:
%w(truth is no defense)
==>["truth", "is", "no", "defense"]
%w(truth is no defense).map{|s| s.split("").map{|c| c.to_sym}}
==>[[:t, :r, :u, :t, :h], [:i, :s], [:n, :o],
[:d, :e, :f, :e, :n, :s, :e]]
%w(truth is no defense).map{|s| s.split("").map{|c| c.to_sym}}.
flatten
==>[:t, :r, :u, :t, :h, :i, :s, :n, :o, :d, :e, :f, :e,
:n, :s, :e]
%w(truth is no defense).map{|s| s.split("").map{|c|
c.to_sym}}.flatten.uniq
==>[:t, :r, :u, :h, :i, :s, :n, :o, :d, :e, :f]
>
> (remove-duplicates
> (find-compositions (function set-difference)
> (function strict-subsetp)
> '()
> '(a e i o u y)
> (mapcar (function explode)
> '(you cannot really appreciate dilbert
> unless you read it in the original
> klingon)))
> :test (lambda (a b)
> (and (subsetp a b :test (function equal))
> (subsetp b a :test (function equal)))))
> -->
> (((C A N N O ...) (R E A L L ...) (A P P R E ...) (D I L B E ...)
> (U N L E S ...))
> ((C A N N O ...) (R E A L L ...) (A P P R E ...) (D I L B E ...) (Y O U))
> ((C A N N O ...) (R E A L L ...) (A P P R E ...) (U N L E S ...))
> ((C A N N O ...) (R E A L L ...) (A P P R E ...) (Y O U))
> ((C A N N O ...) (R E A L L ...) (D I L B E ...) (U N L E S ...)) ...)
>
> <humour>Please don't polute this professionnal programming language
> newsgroup with your toy language. We've got serrious stuff to do
> here.</humour>
I am not unmoved by your cry for mercy. And you're right: it
really isn't fair for a man armed with a samurai sword to
engage in combat with one who has only a flint knife.
William James <·········@yahoo.com> writes:
> On Feb 23, 6:03 am, Pascal Bourguignon <····@informatimago.com> wrote:
>> William James <·········@yahoo.com> writes:
>
>> > Use .uniq.
>>
>> .uniq doesn't take an equal predicate as argument, so you just cannot
>> use it.
>
> Ruby's Array#uniq:
>
> %w(truth is no defense)
> ==>["truth", "is", "no", "defense"]
> %w(truth is no defense).map{|s| s.split("").map{|c| c.to_sym}}
> ==>[[:t, :r, :u, :t, :h], [:i, :s], [:n, :o],
> [:d, :e, :f, :e, :n, :s, :e]]
> %w(truth is no defense).map{|s| s.split("").map{|c| c.to_sym}}.
> flatten
> ==>[:t, :r, :u, :t, :h, :i, :s, :n, :o, :d, :e, :f, :e,
> :n, :s, :e]
> %w(truth is no defense).map{|s| s.split("").map{|c|
> c.to_sym}}.flatten.uniq
> ==>[:t, :r, :u, :h, :i, :s, :n, :o, :d, :e, :f]
>
>>
>> (remove-duplicates
>> (find-compositions (function set-difference)
>> (function strict-subsetp)
>> '()
>> '(a e i o u y)
>> (mapcar (function explode)
>> '(you cannot really appreciate dilbert
>> unless you read it in the original
>> klingon)))
>> :test (lambda (a b)
>> (and (subsetp a b :test (function equal))
>> (subsetp b a :test (function equal)))))
>> -->
>> (((C A N N O ...) (R E A L L ...) (A P P R E ...) (D I L B E ...)
>> (U N L E S ...))
>> ((C A N N O ...) (R E A L L ...) (A P P R E ...) (D I L B E ...) (Y O U))
>> ((C A N N O ...) (R E A L L ...) (A P P R E ...) (U N L E S ...))
>> ((C A N N O ...) (R E A L L ...) (A P P R E ...) (Y O U))
>> ((C A N N O ...) (R E A L L ...) (D I L B E ...) (U N L E S ...)) ...)
Here, I use REMOVE-DUPLICATES to remove duplicate sets. To do that, I
give it a :test parameter which is a set-equal function defined as an
anonymous function that consider sets of elements that have as
equivalence relationship EQUAL.
We know (or assume) that Ruby's Array#uniq is generic (it will use the
equal method of the objects in the array). But if you want to use it
on a different equal function, you cannot. Therefore, the 'unique'
algorithm implemented by uniq cannot be reused in all situations,
while that algorithm implemented by remove-duplicates can. More code
reuse with 'functional' languages than 'OO' languages ;-)
>> <humour>Please don't polute this professionnal programming language
>> newsgroup with your toy language. We've got serrious stuff to do
>> here.</humour>
>
> I am not unmoved by your cry for mercy. And you're right: it
> really isn't fair for a man armed with a samurai sword to
> engage in combat with one who has only a flint knife.
--
__Pascal Bourguignon__
On Feb 25, 4:10 am, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
>
> Here, I use REMOVE-DUPLICATES to remove duplicate sets. To do that, I
> give it a :test parameter which is a set-equal function defined as an
> anonymous function that consider sets of elements that have as
> equivalence relationship EQUAL.
>
> We know (or assume) that Ruby's Array#uniq is generic (it will use the
> equal method of the objects in the array). But if you want to use it
> on a different equal function, you cannot. Therefore, the 'unique'
> algorithm implemented by uniq cannot be reused in all situations,
> while that algorithm implemented by remove-duplicates can. More code
> reuse with 'functional' languages than 'OO' languages ;-)
Let's define an Array method that accepts an anonymous function.
If this function returns the same result for two elements of the
array, we have a duplicate.
class Array
def unique
inject([]){|a,x|
a.any?{|n| yield(n)==yield(x)} ? a : a << x }
end
end
In the example below, if m and n are two elements of the array,
one is a duplicate if (m mod 5) = (n mod 5).
p [3,4,5,9,10,12,13,15].unique{|x| x % 5 }
---> [3, 4, 5, 12]
--
Use this [sword] for me, if I rule well; if not, against me.
--- Trajan
On Feb 26, 12:22 pm, William James <·········@yahoo.com> wrote:
> On Feb 25, 4:10 am, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>
>
>
> > Here, I use REMOVE-DUPLICATES to remove duplicate sets. To do that, I
> > give it a :test parameter which is a set-equal function defined as an
> > anonymous function that consider sets of elements that have as
> > equivalence relationship EQUAL.
>
> > We know (or assume) that Ruby's Array#uniq is generic (it will use the
> > equal method of the objects in the array). But if you want to use it
> > on a different equal function, you cannot. Therefore, the 'unique'
> > algorithm implemented by uniq cannot be reused in all situations,
> > while that algorithm implemented by remove-duplicates can. More code
> > reuse with 'functional' languages than 'OO' languages ;-)
>
> Let's define an Array method that accepts an anonymous function.
> If this function returns the same result for two elements of the
> array, we have a duplicate.
>
> class Array
> def unique
> inject([]){|a,x|
> a.any?{|n| yield(n)==yield(x)} ? a : a << x }
> end
> end
>
> In the example below, if m and n are two elements of the array,
> one is a duplicate if (m mod 5) = (n mod 5).
>
> p [3,4,5,9,10,12,13,15].unique{|x| x % 5 }
>
> ---> [3, 4, 5, 12]
>
> --
> Use this [sword] for me, if I rule well; if not, against me.
> --- Trajan
This much faster version is from the Ruby newsgroup.
module Enumerable
def uniq_by
h = {}; inject([]) {|a,x| h[yield(x)] ||= a << x}
end
end