• Re: walk through list and add all n'th item

    From B. Pym@21:1/5 to All on Fri Jul 19 03:17:36 2024
    Wow: loop macro rulez, somehow..
    just one correction:
    (loop for (a b c d) on (list 1 2 3 4 5 6 7 8) by #'cddddr
    sum a into a-sum
    sum b into b-sum
    sum c into c-sum
    sum d into d-sum
    finally (return (list a-sum b-sum c-sum d-sum)))
    Yeah, i might consider this code as beautiful
    olivier

    Gauche Scheme

    (use gauche.lazy)
    (use util.match)

    (define data (lrange 1 57))

    (match (lslices data 4)
    [((a b c d) ...)
    (map (cut fold + 0 <>)
    (list a b c d))])

    (378 392 406 420)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to B. Pym on Fri Jul 19 17:22:43 2024
    On 2024-07-19, B. Pym <[email protected]> wrote:
    Wow: loop macro rulez, somehow..
    just one correction:
    (loop for (a b c d) on (list 1 2 3 4 5 6 7 8) by #'cddddr
    sum a into a-sum
    sum b into b-sum
    sum c into c-sum
    sum d into d-sum
    finally (return (list a-sum b-sum c-sum d-sum)))
    Yeah, i might consider this code as beautiful
    olivier

    Gauche Scheme

    (use gauche.lazy)
    (use util.match)

    (define data (lrange 1 57))

    (match (lslices data 4)
    [((a b c d) ...)
    (map (cut fold + 0 <>)
    (list a b c d))])

    (378 392 406 420)

    Wrong answer: you silently cut off 57 because it wasn't followed by
    three more numbers, resulting in 378 rather than 435.

    (flow 1..58 (tuples 4 @1 0) transpose (mapcar sum))
    (435 392 406 420)

    Or, if we want to exclude the short tuple:

    (flow 1..58 (tuples 4) (remove-if (lopip len (< 4))) transpose (mapcar sum))
    (378 392 406 420)


    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @[email protected]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From B. Pym@21:1/5 to B. Pym on Wed Aug 14 23:38:04 2024
    B. Pym wrote:

    Wow: loop macro rulez, somehow..
    just one correction:
    (loop for (a b c d) on (list 1 2 3 4 5 6 7 8) by #'cddddr
    sum a into a-sum
    sum b into b-sum
    sum c into c-sum
    sum d into d-sum
    finally (return (list a-sum b-sum c-sum d-sum)))
    Yeah, i might consider this code as beautiful
    olivier

    Gauche Scheme

    (use gauche.lazy)
    (use util.match)

    (define data (lrange 1 57))

    (match (lslices data 4)
    [((a b c d) ...)
    (map (cut fold + 0 <>)
    (list a b c d))])

    (378 392 406 420)


    newLISP

    (define data (sequence 1 56))

    (map (curry apply +) (transpose (explode data 4)))

    ===>
    (378 392 406 420)


    Another way.

    ;; Using "apply" for "reduce". The 3rd argument tells
    ;; apply how many items to process at a time.
    (apply
    (fn (sums) (map + sums $args))
    (cons '(0 0 0 0) data)
    5)

    --->
    (378 392 406 420)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to B. Pym on Fri Aug 30 17:02:59 2024
    On 2024-08-30, B. Pym <[email protected]> wrote:
    I'm just wondering if there is a lispier way to scan once through a
    list and add each n'th item with n+constant.
    Like kind of apply a list through a vector..
    In my approach i just used the loop macro:
    (defparameter vals '(1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1
    2 3 4 5 6 7 8))
    ...
    CL-USER> (sum-values vals)
    (4 8 12 16 20 24 28 32)

    Can you do better? (i hope you do and I am prepared to bear the shame)

    I see that you ask to "scan once" but still feel awfully
    tempted to reblock the data

    CL-USER> (defun batch (list size)
    (if (endp list)
    '()
    (cons (subseq list 0 size)
    (batch (nthcdr size list) size))))
    BATCH

    CL-USER> (batch vals 8)

    ((1 2 3 4 5 6 7 8) (1 2 3 4 5 6 7 8) (1 2 3 4 5 6 7 8) (1 2 3 4 5 6 7 8))

    CL-USER> (defun add (list)
    (reduce (lambda(u v)(mapcar #'+ u v)) list))
    ADD

    CL-USER> (add (batch vals 8))
    (4 8 12 16 20 24 28 32)

    Mark Wooding wrote:

    Or you could just do it the easy way:

    (defun sum-every-softcore (period list)
    (loop with sums = (make-array period :initial-element 0)
    for item in list
    for i = 0 then (mod (1+ i) period)
    do (incf (aref sums i) item)
    finally (return (coerce sums 'list))))

    Gauche Scheme

    (use srfi-42) ;; do-ec

    (define (sum-every-nth n nlist)
    (rlet1 result (make-vector n 0)
    (do-ec (:list x (index i) nlist)
    (inc! (vector-ref result (mod i n)) x))))

    (define vals '(1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1
    2 3 4 5 6 7 8))

    (sum-every-nth 8 vals)

    #(4 8 12 16 20 24 28 32)

    This is the TXR Lisp interactive listener of TXR 296.
    Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet.
    TXR Lisp environments use genuine Saskatchewan sealskin bindings.
    (flow '(1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8)
    (tuples 8)
    transpose
    (mapcar sum))
    (4 8 12 16 20 24 28 32)

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @[email protected]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From B. Pym@21:1/5 to Mark Wooding on Fri Aug 30 16:42:30 2024
    I'm just wondering if there is a lispier way to scan once through a
    list and add each n'th item with n+constant.
    Like kind of apply a list through a vector..
    In my approach i just used the loop macro:
    (defparameter vals '(1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1
    2 3 4 5 6 7 8))
    ...
    CL-USER> (sum-values vals)
    (4 8 12 16 20 24 28 32)

    Can you do better? (i hope you do and I am prepared to bear the shame)

    I see that you ask to "scan once" but still feel awfully
    tempted to reblock the data

    CL-USER> (defun batch (list size)
    (if (endp list)
    '()
    (cons (subseq list 0 size)
    (batch (nthcdr size list) size))))
    BATCH

    CL-USER> (batch vals 8)

    ((1 2 3 4 5 6 7 8) (1 2 3 4 5 6 7 8) (1 2 3 4 5 6 7 8) (1 2 3 4 5 6 7 8))

    CL-USER> (defun add (list)
    (reduce (lambda(u v)(mapcar #'+ u v)) list))
    ADD

    CL-USER> (add (batch vals 8))
    (4 8 12 16 20 24 28 32)

    Mark Wooding wrote:

    Or you could just do it the easy way:

    (defun sum-every-softcore (period list)
    (loop with sums = (make-array period :initial-element 0)
    for item in list
    for i = 0 then (mod (1+ i) period)
    do (incf (aref sums i) item)
    finally (return (coerce sums 'list))))

    Gauche Scheme

    (use srfi-42) ;; do-ec

    (define (sum-every-nth n nlist)
    (rlet1 result (make-vector n 0)
    (do-ec (:list x (index i) nlist)
    (inc! (vector-ref result (mod i n)) x))))

    (define vals '(1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1
    2 3 4 5 6 7 8))

    (sum-every-nth 8 vals)

    #(4 8 12 16 20 24 28 32)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From B. Pym@21:1/5 to B. Pym on Wed Aug 6 14:31:16 2025
    B. Pym wrote:

    I'm just wondering if there is a lispier way to scan once through a
    list and add each n'th item with n+constant.
    Like kind of apply a list through a vector..
    In my approach i just used the loop macro:
    (defparameter vals '(1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1
    2 3 4 5 6 7 8))
    ...
    CL-USER> (sum-values vals)
    (4 8 12 16 20 24 28 32)

    Can you do better? (i hope you do and I am prepared to bear the shame)

    I see that you ask to "scan once" but still feel awfully
    tempted to reblock the data

    CL-USER> (defun batch (list size)
    (if (endp list)
    '()
    (cons (subseq list 0 size)
    (batch (nthcdr size list) size))))
    BATCH

    CL-USER> (batch vals 8)

    ((1 2 3 4 5 6 7 8) (1 2 3 4 5 6 7 8) (1 2 3 4 5 6 7 8) (1 2 3 4 5 6 7 8))

    CL-USER> (defun add (list)
    (reduce (lambda(u v)(mapcar #'+ u v)) list))
    ADD

    CL-USER> (add (batch vals 8))
    (4 8 12 16 20 24 28 32)

    Mark Wooding wrote:

    Or you could just do it the easy way:

    (defun sum-every-softcore (period list)
    (loop with sums = (make-array period :initial-element 0)
    for item in list
    for i = 0 then (mod (1+ i) period)
    do (incf (aref sums i) item)
    finally (return (coerce sums 'list))))

    Gauche Scheme

    (use srfi-42) ;; do-ec

    (define (sum-every-nth n nlist)
    (rlet1 result (make-vector n 0)
    (do-ec (:list x (index i) nlist)
    (inc! (vector-ref result (mod i n)) x))))

    (define vals '(1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1
    2 3 4 5 6 7 8))

    (sum-every-nth 8 vals)

    #(4 8 12 16 20 24 28 32)

    (define (sum-every-nth n nlist)
    (let ((result (make-vector n 0))
    (i (gmki 0 1 n)))
    (dolist (x nlist) (inc! (~ result (i)) x))
    result))

    (define vals '(1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1
    2 3 4 5 6 7 8))

    (sum-every-nth 8 vals)
    ===>
    #(4 8 12 16 20 24 28 32)

    Given:

    ;; Make an index generator.
    (define (gmki :optional (start 0) (step #f) (m #f))
    (let ((i start)
    (s step)
    (m m))
    (if m
    (lambda () (begin0 (mod i m) (inc! i s)))
    (if s
    (lambda () (begin0 i (inc! i s)))
    (lambda () (begin0 i (inc! i)))))))

    --
    [T]he problem is that lispniks are as cultish as any other devout group and basically fall down frothing at the mouth if they see [heterodoxy].
    --- Kenny Tilton
    The good news is, it's not Lisp that sucks, but Common Lisp. --- Paul Graham

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)