i.e. create sub-sequences beginning whenever the value decreases.
However, I am not having much luck (being pretty new to LISP). My attempt was to use a loop with two collect statements, collecting each number into one until its value decreases compared to the last one, which then gets collected into another, then reset. Something like this:
(loop for num in seq when (and (not (null subseq)) (<= num (car (last subseq))) collect subseq into answer and do (setf subseq nil) collect num into subseq finally (return answer))
But, subseq never seems to get reset, and it seems that there are references at work as the return value contains multiple copies of the original sequence.
Would someone kindly be able to offer some advice or a nudge in the right direction?
> i.e. create sub-sequences beginning whenever the value decreases.
> However, I am not having much luck (being pretty new to LISP). My > attempt was to use a loop with two collect statements, collecting each > number into one until its value decreases compared to the last one, > which then gets collected into another, then reset. Something like > this:
> (loop > for num in seq > when (and (not (null subseq)) (<= num (car (last subseq))) > collect subseq into answer and > do (setf subseq nil) > collect num into subseq > finally (return answer))
> But, subseq never seems to get reset, and it seems that there are > references at work as the return value contains multiple copies of the > original sequence.
> Would someone kindly be able to offer some advice or a nudge in the > right direction?
> Best, > Scott
(defun collect-sublists (list) (flet ((collect-sublist () (loop for element = (pop list) while element collect element while (and list (<= element (first list)))))) (loop for sublist = (collect-sublist) while sublist collect sublist)))
> (defun collect-sublists (list) > (flet ((collect-sublist () > (loop for element = (pop list) > while element collect element > while (and list > (<= element (first list)))))) > (loop for sublist = (collect-sublist) > while sublist collect sublist)))
Nearly 15 minutes passed since you posted your solution, and William James still didn’t show his Ruby one-liner that outperforms the Lisp solution by a factor of 20 (speedwise). ;-)
On Dec 7, 7:49 pm, "jos...@corporate-world.lisp.de" <jos...@corporate-
world.lisp.de> wrote: > (defun collect-sublists (list) > (flet ((collect-sublist () > (loop for element = (pop list) > while element collect element > while (and list > (<= element (first list)))))) > (loop for sublist = (collect-sublist) > while sublist collect sublist)))
Thanks for the quick response! This does exactly what I need, although I will certainly have to look at it closely to see exactly how.
Scott wrote: > On Dec 7, 7:49 pm, "jos...@corporate-world.lisp.de" <jos...@corporate- > world.lisp.de> wrote:
>>(defun collect-sublists (list) >> (flet ((collect-sublist () >> (loop for element = (pop list) >> while element collect element >> while (and list >> (<= element (first list)))))) >> (loop for sublist = (collect-sublist) >> while sublist collect sublist)))
> Thanks for the quick response! This does exactly what I need, although > I will certainly have to look at it closely to see exactly how.
Nonsense! Your request was:
> Would someone kindly be able to offer some advice or a nudge in the > right direction?
You received an alternative solution that did not identify why your solution was not working. No advice, no nudge.
As Lao Tzu might have said, "The subseq you can setf is not the true subseq".
i dunno if this one is faster (it might be because it uses CL library functions, but theoretically it won't matter for "sufficiently smart compiler"), but Rainer's one is at least order of magnitude easier to read/understand, and algorithmically it is same O(N).
On Dec 8, 12:32 pm, "Alex Mizrahi" <udode...@users.sourceforge.net> wrote:
> Rainer's one is at least order of magnitude easier > to read/understand, and algorithmically it is same O(N).
That is true, although I was kind of hoping he might open the link and keep reading after not understanding the function (Rainer's is in there somewhere, I believe). :-P
André Thieme wrote: > jos...@corporate-world.lisp.de schrieb:
>> (defun collect-sublists (list) >> (flet ((collect-sublist () >> (loop for element = (pop list) >> while element collect element >> while (and list >> (<= element (first list)))))) >> (loop for sublist = (collect-sublist) >> while sublist collect sublist)))
> Nearly 15 minutes passed since you posted your solution, and William > James still didn’t show his Ruby one-liner that outperforms the Lisp > solution by a factor of 20 (speedwise). ;-)
> André
Chubby Ruby, My Dear Hubby, I love you dear, But can't you hear, I'm talking lisp, ... takin' all the risk.
André Thieme wrote: > jos...@corporate-world.lisp.de schrieb:
> > (defun collect-sublists (list) > > (flet ((collect-sublist () > > (loop for element = (pop list) > > while element collect element > > while (and list > > (<= element (first list)))))) > > (loop for sublist = (collect-sublist) > > while sublist collect sublist)))
"We don't need no stinkin' loops!"
Ruby:
list = [0,1,2,3] * 3
def collect_sublists list, prev=nil, accum=[[]] return accum if not element = list.first if prev and element < prev accum << [element] else accum[-1] << element end collect_sublists( list[1..-1], element, accum ) end
p collect_sublists( list )
# This could be slower if getting the last element in a list # is expensive.
def collect_sublists_2 list, accum=[[]] return accum if not element = list.first if accum != [[]] and accum[-1][-1] > element accum << [element] else accum[-1] << element end collect_sublists_2( list[1..-1], accum ) end
> Nearly 15 minutes passed since you posted your solution, and William > James still didn’t show his Ruby one-liner that outperforms the Lisp > solution by a factor of 20 (speedwise). ;-)
> André
Ruby is about the slowest "scripting language". JavaScript is faster.
SpiderMonkey and jslibs:
LoadModule('jsstd')
list = [0,1,2,3,0,1,2,3,1,2,3]
function collect_groups( list, prev, accum ) { accum = accum || [[]] var element = list[0] if ( typeof element == "undefined" ) return accum if (prev && element < prev) accum.push( [element] ) else accum.slice(-1)[0].push( element ) return collect_groups( list.slice(1), element, accum )
> André Thieme wrote: > > jos...@corporate-world.lisp.de schrieb:
> > > (defun collect-sublists (list) > > > (flet ((collect-sublist () > > > (loop for element = (pop list) > > > while element collect element > > > while (and list > > > (<= element (first list)))))) > > > (loop for sublist = (collect-sublist) > > > while sublist collect sublist)))
> "We don't need no stinkin' loops!"
> Ruby:
> list = [0,1,2,3] * 3
> def collect_sublists list, prev=nil, accum=[[]] > return accum if not element = list.first > if prev and element < prev > accum << [element] > else > accum[-1] << element > end > collect_sublists( list[1..-1], element, accum ) > end
anonymous.c.lis...@gmail.com wrote: > On Dec 7, 9:47 pm, Scott <jsam...@gmail.com> wrote: > > On Dec 7, 7:49 pm, "jos...@corporate-world.lisp.de" > > <jos...@corporate-
> > world.lisp.de> wrote: > > > (defun collect-sublists (list) > > > (flet ((collect-sublist () > > > (loop for element = (pop list) > > > while element collect element > > > while (and list > > > (<= element (first list)))))) > > > (loop for sublist = (collect-sublist) > > > while sublist collect sublist)))
> > Thanks for the quick response! This does exactly what I need, > > although I will certainly have to look at it closely to see exactly > > how.
jos...@corporate-world.lisp.de wrote: > On Dec 8, 1:08 am, Scott <jsam...@gmail.com> wrote: > > Hi All,
> > I am trying to process a sequence like:
> > (0 1 2 3 0 1 2 3 0 1 2 3)
> > and produce:
> > ((0 1 2 3)(0 1 2 3)(0 1 2 3))
> > i.e. create sub-sequences beginning whenever the value decreases.
> > However, I am not having much luck (being pretty new to LISP). My > > attempt was to use a loop with two collect statements, collecting > > each number into one until its value decreases compared to the last > > one, which then gets collected into another, then reset. Something > > like this:
> > (loop > > for num in seq > > when (and (not (null subseq)) (<= num (car (last subseq))) > > collect subseq into answer and > > do (setf subseq nil) > > collect num into subseq > > finally (return answer)) ...
> (defun collect-sublists (list) > (flet ((collect-sublist () > (loop for element = (pop list) > while element collect element > while (and list > (<= element (first list)))))) > (loop for sublist = (collect-sublist) > while sublist collect sublist)))
JavaScript (SpiderMonkey):
function clump(a){ var c=[[a[0]]] a.reduce(function(p,x){x<p ? c.push([x]) : c.slice(-1)[0].push(x) return x}) return c }
> > On Dec 8, 1:08 am, Scott <jsam...@gmail.com> wrote: > > > Hi All,
> > > I am trying to process a sequence like:
> > > (0 1 2 3 0 1 2 3 0 1 2 3)
> > > and produce:
> > > ((0 1 2 3)(0 1 2 3)(0 1 2 3))
> > > i.e. create sub-sequences beginning whenever the value decreases.
> > > However, I am not having much luck (being pretty new to LISP). My > > > attempt was to use a loop with two collect statements, collecting > > > each number into one until its value decreases compared to the last > > > one, which then gets collected into another, then reset. Something > > > like this:
> > > (loop > > > for num in seq > > > when (and (not (null subseq)) (<= num (car (last subseq))) > > > collect subseq into answer and > > > do (setf subseq nil) > > > collect num into subseq > > > finally (return answer)) > ...
> > (defun collect-sublists (list) > > (flet ((collect-sublist () > > (loop for element = (pop list) > > while element collect element > > while (and list > > (<= element (first list)))))) > > (loop for sublist = (collect-sublist) > > while sublist collect sublist)))
> JavaScript (SpiderMonkey):
> function clump(a){ > var c=[[a[0]]] > a.reduce(function(p,x){x<p ? c.push([x]) : c.slice(-1)[0].push(x) > return x}) > return c }
(define-modify-macro b! (&rest args) nconc) (defun clump (l &aux r) (reduce (lambda (a b) (if (> b a) (b! (car (last r)) (list b)) (b! r (list (list b)))) b) l :initial-value (car l)) r)