; linked list exercises
(define (split n xs)
(let loop ((n n) (xs xs) (zs '()))
(if (or (zero? n) (null? xs))
(values (reverse zs) xs)
(loop (- n 1) (cdr xs) (cons (car xs) zs)))))
(define-syntax list-match
(syntax-rules ()
((_ expr (pattern fender ... template) ...)
(let ((obj expr))
(cond ((list-match-aux obj pattern fender ...
(list template)) => car) ...
(else (error 'list-match "pattern failure")))))))
(define-syntax list-match-aux
(lambda (stx)
(define (underscore? x)
(and (identifier? x) (free-identifier=? x (syntax _))))
(syntax-case stx (quote quasiquote)
((_ obj pattern template)
(syntax (list-match-aux obj pattern #t template)))
((_ obj () fender template)
(syntax (and (null? obj) fender template)))
((_ obj underscore fender template)
(underscore? (syntax underscore))
(syntax (and fender template)))
((_ obj var fender template)
(identifier? (syntax var))
(syntax (let ((var obj)) (and fender template))))
((_ obj (quote datum) fender template)
(syntax (and (equal? obj (quote datum)) fender template)))
((_ obj (quasiquote datum) fender template)
(syntax (and (equal? obj (quasiquote datum)) fender template)))
((_ obj (kar . kdr) fender template)
(syntax (and (pair? obj)
(let ((kar-obj (car obj)) (kdr-obj (cdr obj)))
(list-match-aux kar-obj kar
(list-match-aux kdr-obj kdr fender template))))))
((_ obj const fender template)
(syntax (and (equal? obj const) fender template))))))
(define (task1a xs)
(append (filter even? xs) (filter odd? xs)))
(display (task1a '(1 2 3 4 5 6 7 8 9))) (newline)
(define (task1b xs)
(let loop ((xs xs) (evens (list)) (odds (list)))
(cond ((null? xs) (append (reverse evens) (reverse odds)))
((even? (car xs)) (loop (cdr xs) (cons (car xs) evens) odds))
(else (loop (cdr xs) evens (cons (car xs) odds))))))
(display (task1b '(1 2 3 4 5 6 7 8 9))) (newline)
(define (task2a xs)
(let loop ((xs xs) (odds (list)) (evens (list)))
(cond ((null? xs) (append (reverse odds) (reverse evens)))
((null? (cdr xs)) (append (reverse (cons (car xs) odds)) (reverse evens)))
(else (loop (cddr xs) (cons (car xs) odds) (cons (cadr xs) evens))))))
(display (task2a '(1 2 3 4 5 6 7 8 9))) (newline)
(define (task2b xs)
(let loop ((xs xs) (odds (list)) (evens (list)))
(list-match xs
(() (append (reverse odds) (reverse evens)))
((a) (loop (list) (cons a odds) evens))
((a b . xs) (loop xs (cons a odds) (cons b evens))))))
(display (task2b '(1 2 3 4 5 6 7 8 9))) (newline)
(define (task3 xs)
(call-with-values
(lambda () (split (quotient (length xs) 2) (sort xs <)))
(lambda (los his)
(let loop ((his his) (los los) (xs (list)))
(cond ((null? his) xs)
((null? los) (cons (car his) xs))
(else (loop (cdr his) (cdr los) (cons (car los) (cons (car his) xs)))))))))
(display (task3 '(1 2 3 4 5 6 7 8 9))) (newline)
(display (task3 '(1 2 3 4 5 6 7 8))) (newline)