Write a function that splits an integer list into two parts such that the difference of the sum of the two parts is the smallest among all possible splits.
$ cat sl.rkt #lang racket (define (diff a b) (abs (- a b))) (define (split-list l) (let ((sum (apply + l))) (let loop ((left '()) (right l) (min-diff (abs sum)) (min-left '()) (min-right l) (left-sum 0) (right-sum sum)) (if (null? right) (cons (reverse min-left) min-right) (let* ((x (car right)) (lsum (+ left-sum x)) (rsum (- right-sum x)) (df (diff lsum rsum)) (l (cons x left)) (r (cdr right))) (if (< df min-diff) (loop l r df l r lsum rsum) (loop l r min-diff min-left min-right lsum rsum))))))) (require rackunit) (check-equal? (split-list '()) '(())) (check-equal? (split-list '(1 1)) '((1) 1)) (check-equal? (split-list '(2 7 3 1 4)) '((2 7) 3 1 4)) (check-equal? (split-list '(1 2 4 7 3)) '((1 2 4) 7 3)) (check-equal? (split-list '(-5 5)) '(() -5 5)) (define (check-min-diff-split lst) (let* ((split (split-list lst)) (l-split (car split)) (r-split (cdr split)) (min-diff (diff (apply + l-split) (apply + r-split)))) (let loop ((right lst) (left-sum 0) (right-sum (apply + lst))) (if (< (diff left-sum right-sum) min-diff) (raise-user-error 'check-min-diff-split "split difference isn't a minimum\n ~a + ~a = ~a\n ~a + ~a = ~a" l-split r-split min-diff (take lst (- (length lst) (length right))) right (diff left-sum right-sum)) (unless (null? right) (let ((x (car right))) (loop (cdr right) (+ left-sum x) (- right-sum x)))))))) (define (test lst) (for-each check-min-diff-split (permutations lst))) (test '(1 1)) (test '(2 7 3 1 4)) (test '(-5 5)) (test '(0 1 2 3 4 5 6 7 8)) $ mzscheme sl.rkt $