Two List Tasks
January 2, 2018
For the first exercise, we create the list of lists xss, then transpose the list and map sum over the transposed sub-lists:
> (define xss '((1 2 3 4) (2 3 4 5) (3 4 5 6))) > (map sum (apply map list xss)) (6 9 12 15)
The standard idiom for transposing a list of lists in Scheme is apply map list.
For the second exercise, we create the input list, write an auxiliary function that splits a list of k × m items into k lists of m items, then map sum over the sub-lists:
> (define xs '(1 2 3 4 2 3 4 5 3 4 5 6))
> (define (splits n xs)
(let loop ((xs xs) (zs (list)))
(if (null? xs) (reverse zs)
(call-with-values
(lambda () (split n xs))
(lambda (first rest)
(loop rest (cons first zs)))))))
> (map sum (splits 4 xs))
(10 14 18)
You can run the program at https://ideone.com/zRFVrs, where you will also see sum and split.
The answer to the first exercise could be simplified (in the eye of
this beholder) to:
(apply map + xss)
Another solution for the second exercise, using just R7RS Scheme.
(define input-201 '(1 2 3 4 2 3 4 5 3 4 5 6)) ;; Any trailing under-length segment is dropped. (define (segment-sum lst segment-length) (let f ((lst lst) (seg-len 0) (seg-sum 0) (res '())) (if (null? lst) (reverse res) (let ((slen (+ seg-len 1)) (ssum (+ seg-sum (car lst)))) (if (< slen segment-length) (f (cdr lst) slen ssum res) (f (cdr lst) 0 0 (cons ssum res))))))) (write (segment-sum input-201 4)) (newline)A Haskell version.
Here’s a solution in C.
/* list_tasks.c */ #include <stdio.h> void sum_arrays(int* arrays[], size_t k, size_t m, int* output) { for (size_t i = 0; i < m; ++i) { output[i] = 0; for (size_t j = 0; j < k; ++j) { output[i] += arrays[j][i]; } } } void sum_array(int* array, size_t k, size_t m, int* output) { for (size_t i = 0; i < k; ++i) { output[i] = 0; for (size_t j = 0; j < m; ++j) { output[i] += array[i*m + j]; } } } void print_array(int* array, int n) { printf("["); for (size_t i = 0; i < n; ++i) { if (i > 0) printf(", "); printf("%d", array[i]); } printf("]"); } int main(int argc, char* argv[]) { /* Task 1 */ { size_t k = 3; size_t m = 4; int array[] = { 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 }; int* arrays[3]; for (size_t i = 0; i < k; ++i) { arrays[i] = &array[i*m]; } int output[m]; sum_arrays(arrays, k, m, output); printf("Task 1:\n "); print_array(output, m); printf("\n"); } /* Task 2 */ { size_t k = 3; size_t m = 4; int array[] = {1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6}; int output[k]; sum_array(array, k, m, output); printf("Task 2:\n "); print_array(output, k); printf("\n"); } return 0; }Output:
@Rutger, your solution to the first task sums elements within the sublists, as opposed to summing corresponding elements across the sublists.
Here’s a minor update that zips the lists so that the sum is across sublists.
Here’s the updated version that also supports sublists of differing lengths, padding the shorter sublists with zeros at the end.