[racket] Calculating cumulative sum of the list

1,009 views
Skip to first unread message

Alexandr M

unread,
Jan 22, 2015, 8:59:41 AM1/22/15
to us...@racket-lang.org
Hello,

I am trying to replicate functionality of this code in Python:

https://gist.github.com/m-blog/22b7c5d31b3839ffba50#file-cumsum-py

in Racket without usage of any libraries.

What would the most optimal / concise way to do it in Racket?

Thank you.

--
Best regards,
Alex

Jens Axel Søgaard

unread,
Jan 22, 2015, 9:17:33 AM1/22/15
to Alexandr M, racket
Something like this perhaps:

(define (cumulative-sums xs)
(rest (reverse (for/fold ([sums '(0)]) ([x xs])
(cons (+ (first sums) x) sums)))))

Or

(define (cumulative-sums xs)
(define s 0)
(for/list ([x xs])
(set! s (+ s x))
s))

> ____________________
> Racket Users list:
> http://lists.racket-lang.org/users
>

--
--
Jens Axel Søgaard

____________________
Racket Users list:
http://lists.racket-lang.org/users

Pierpaolo Bernardi

unread,
Jan 22, 2015, 9:23:01 AM1/22/15
to Alexandr M, users
Here's a straightforward way:

(define (cumulative-sum list)
(let loop ([list list] [acc 0])
(if (null? list)
list
(let ([s (+ (first list) acc)])
(cons s (loop (rest list) s))))))

Matthias Felleisen

unread,
Jan 22, 2015, 9:38:16 AM1/22/15
to Alexandr M, us...@racket-lang.org

#lang racket

;; [Listof Number] -> [Listof Number]
;; given (a b c ...) produce (a (+ a b) (+ a b c) ...)
(define (cumulative-sum l #;"final private:" [so-far 0])
(cond
[(empty? l) '()]
[else (define next (+ so-far (first l)))
(cons next (cumulative-sum (rest l) next))]))

(module+ main
(cumulative-sum '(1 2 3)))

;; The comments are HtDP-style, but the optional entry parameter is not available in the teaching languages.

Jack Firth

unread,
Jan 22, 2015, 2:06:46 PM1/22/15
to Matthias Felleisen, racket users list
If you're using all of racket, here's a way to do it with heavy usage of higher order functions

#lang racket

(define (cumulative-sum xs)
  (map (curry foldl + 0)
           (build-list (length xs)
                           (compose (curry take xs)
                                            add1))))

Matthias Felleisen

unread,
Jan 22, 2015, 2:26:02 PM1/22/15
to Jack Firth, racket users list

Consider the performance implications.

William James

unread,
Jan 22, 2015, 2:42:43 PM1/22/15
to us...@racket-lang.org
(require srfi/1)

(unfold-right null? (curry apply +) cdr (reverse '(1 3 5 7)))
===>
'(1 4 9 16)


--------------------------------------------
On Thu, 1/22/15, Alexandr M <rus...@gmail.com> wrote:

Subject: [racket] Calculating cumulative sum of the list
To: us...@racket-lang.org
Date: Thursday, January 22, 2015, 7:53 AM
-----Inline Attachment Follows-----

Jack Firth

unread,
Jan 22, 2015, 4:28:20 PM1/22/15
to Matthias Felleisen, racket users list
Add memoization to fix that

(define (memo f)
  (let ([cache (make-hash)])
    (lambda xs
      (hash-ref! cache xs (thunk (apply f xs))))))

(define (cumulative-sum xs)
  (map (memo (curry foldl + 0))
           (build-list (length xs)
                           (compose (curry take xs)
                                            add1))))

Jack Firth

unread,
Jan 22, 2015, 4:34:23 PM1/22/15
to Matthias Felleisen, racket users list
Scratch that, naive memoization doesn't fix it. Will tinker with this more out of curiosity

William James

unread,
Jan 22, 2015, 7:21:19 PM1/22/15
to us...@racket-lang.org
Here's a way using map-accum in Gauche.

(use gauche.collection)

(define (cumulative-sums xs)
(map-accum (lambda (x sum) (values (+ x sum) (+ x sum))) 0 xs))

(cumulative-sums '(1 3 5 7))
===>
(1 4 9 16)


--------------------------------------------
On Thu, 1/22/15, Alexandr M <rus...@gmail.com> wrote:

Subject: [racket] Calculating cumulative sum of the list
To: us...@racket-lang.org
Date: Thursday, January 22, 2015, 7:53 AM

-----Inline Attachment Follows-----

Matthias Felleisen

unread,
Jan 22, 2015, 7:39:31 PM1/22/15
to users list

NOTE TO EVERYONE: The OP asked for "without usage of any libraries".
I am sure that sooner or later we will find a library so that we
can say (require lib/cumulative) cumulative-sum.

William James

unread,
Jan 22, 2015, 8:39:21 PM1/22/15
to us...@racket-lang.org
Using recursion:

(define (cum-sums xs)
(let run ((xs xs) (sum 0))
(if (null? xs) '()
(let ((sum (+ sum (car xs))))
(cons sum (run (cdr xs) sum))))))

Using map:

(define (cum-sums xs)
(define sum 0)
(define (add x) (set! sum (+ sum x)) sum)
(map add xs))

> (cum-sums '(1 3 5 7))
'(1 4 9 16)

--------------------------------------------
On Thu, 1/22/15, Alexandr M <rus...@gmail.com> wrote:

Subject: [racket] Calculating cumulative sum of the list
To: us...@racket-lang.org
Date: Thursday, January 22, 2015, 7:53 AM

Michael Wilber

unread,
Jan 22, 2015, 8:43:00 PM1/22/15
to us...@racket-lang.org
Here's one way, but it's not tail-recursive:

racket@> (define (cumsum lst [so-far 0])
(match lst
['() '()]
[(cons first rest)
(cons (+ so-far first)
(cumsum rest (+ so-far first)))]))

racket@> (cumsum '(1 3 5 7))
'(1 4 9 16)

Neil Toronto

unread,
Jan 22, 2015, 9:24:22 PM1/22/15
to us...@racket-lang.org
Well, there is always the amazing math library. But somehow, the author
of `math/base` forgot to include a `sums` function!

There *is* a `flvector-sums` in `math/flonum`, which operates only on
flonums. If you can believe this, the documentation for that function
even *gives example code* for computing cumulative sums!

Stupid git.

Neil ⊥

Matthias Felleisen

unread,
Jan 22, 2015, 9:40:27 PM1/22/15
to Neil Toronto, us...@racket-lang.org

:-)
Reply all
Reply to author
Forward
0 new messages