;;; File: ;;; unriffle.ss ;;; Author: ;;; Samuel A. Rebelsky ;;; Version: ;;; 1.1 of 20 September 2006 ;;; Summary: ;;; A collection of versions of the unriffle procedure (and some tests ;;; of those versions). ;;; History: ;;; At end ; +-----------------+------------------------------------------------- ; | Primary Methods | ; +-----------------+ ;;; Procedures: ;;; unriffle-v1 ;;; unriffle-v2 ;;; unriffle-v3 ;;; unriffle-v4 ;;; unriffle-v5 ;;; Parameters: ;;; lst, a (potentially empty) list ;;; Purpose: ;;; Split lst into two lists, one of the values at the even positions ;;; in lst, one at the odd positions. ;;; Produces: ;;; (evens odds), a list of two lists ;;; Preconditions: ;;; (none) ;;; Postconditions: ;;; Let n be (length lst) ;;; For all even i, s.t. 0 <= i < n ;;; (list-ref evens (/ i 2)) = (list-ref lst i) ;;; For all odd i, s.t., 0 <= i < n ;;; (list-ref odds (/ (- i 1) 2)) = (list-ref lst i) ;;; Practica: ;;; > (unriffle (list 'a 'b 'c 'd 'e 'f 'g 'h 'i)) ;;; ((a c e g i) (b d f h)) ;;; > (unriffle (list)) ;;; (() ()) ;;; > (unriffle (list 'a)) ;;; ((a) ()) ;;; > (unriffle (list 'b)) ;;; ((b) ()) ;;; > (unriffle (list 'a 'b)) ;;; ((a) (b)) (define unriffle-v1 (lambda (lst) (list (elements-in-even-positions-v1 lst) (elements-in-odd-positions-v1 lst)))) (define elements-in-even-positions-v1 (lambda (lst) (cond ((null? lst) null) ((null? (cdr lst)) lst) (else (cons (car lst) (elements-in-even-positions-v1 (cddr lst))))))) (define elements-in-odd-positions-v1 (lambda (lst) (if (or (null? lst) (null? (cdr lst))) null (cons (cadr lst) (elements-in-odd-positions-v1 (cddr lst)))))) (define unriffle-v2 (lambda (lst) (list (elements-in-even-positions-v2 lst) (elements-in-odd-positions-v2 lst)))) (define elements-in-even-positions-v2 (lambda (lst) (if (null? lst) null (cons (car lst) (elements-in-odd-positions-v2 (cdr lst)))))) (define elements-in-odd-positions-v2 (lambda (lst) (if (null? lst) null (elements-in-even-positions-v2 (cdr lst))))) (define unriffle-v3 (lambda (lst) (if (null? lst) ; We split the empty list into two empty lists (list null null) ; The recursive call will split the remainder into two ; lists, but the lists will be "backwards" (since the even ; positions in the list are the odd positions in its cdr, ; and the odd positions in the list are the even positions ; in its cdr). We'll use a helper to put the car back in ; and reverse the order (unriffle-v3-helper (car lst) (unriffle-v3 (cdr lst)))))) (define unriffle-v3-helper (lambda (val evens-odds) (list (cons val (cadr evens-odds)) (car evens-odds)))) (define unriffle-v4 (lambda (lst) (unriffle-v4-helper null null lst))) (define unriffle-v4-helper (lambda (evens odds remaining) (cond ; No elements remaining: We're done ((null? remaining) (list (reverse evens) (reverse odds))) ; One element remaining: It belongs in the evens ((null? (cdr remaining)) (list (reverse (cons (car remaining) evens)) (reverse odds))) ; Otherwise, strip off the first two values, adding them to evens ; and odds. (else (unriffle-v4-helper (cons (car remaining) evens) (cons (cadr remaining) odds) (cddr remaining)))))) (define unriffle-v5 (lambda (lst) (unriffle-v5-helper null null 0 lst))) (define unriffle-v5-helper (lambda (evens odds dropped remaining) (cond ; Base case: Nothing remaining. We're done. ((null? remaining) (list (reverse evens) (reverse odds))) ; If we've dropped an even number of values, ; so we add the next value to evens. ((even? dropped) (unriffle-v5-helper (cons (car remaining) evens) odds (+ 1 dropped) (cdr remaining))) ; Otherwise, we've dropped an odd number of values, ; so we add the next value to odds. (else (unriffle-v5-helper evens (cons (car remaining) odds ) (+ 1 dropped) (cdr remaining)))))) ; +---------+--------------------------------------------------------- ; | Testing | ; +---------+ ; Here's a nice, even length list to work with (define alphabet (list 'a 'b 'c 'd 'e 'f)) (define alphabet-evens (list 'a 'c 'e)) (define alphabet-odds (list 'b 'd 'f)) ; Here's an odd length list to work with (in case even length and ; odd length lists work differently) (define vowels (list #\a #\e #\i #\o #\u)) (define vowels-evens (list #\a #\i #\u)) (define vowels-odds (list #\e #\o)) (define check (lambda (expected found) (if (equal? expected found) (success expected found) (failure expected found)))) (define success (lambda (expected found) (display "OK") (newline))) (define failure (lambda (expected found) (display "Failed. Expected ") (display expected) (display " found ") (display found) (newline))) (define test-unriffle (lambda () (display "Checking unriffle-v1: ") (newline) (check null (car (unriffle-v1 null))) (check null (cadr (unriffle-v1 null))) (check alphabet-evens (car (unriffle-v1 alphabet))) (check alphabet-odds (cadr (unriffle-v1 alphabet))) (check vowels-evens (car (unriffle-v1 vowels))) (check vowels-odds (cadr (unriffle-v1 vowels))) (display "Checking unriffle-v2: ") (newline) (check null (car (unriffle-v2 null))) (check null (cadr (unriffle-v2 null))) (check alphabet-evens (car (unriffle-v2 alphabet))) (check alphabet-odds (cadr (unriffle-v2 alphabet))) (check vowels-evens (car (unriffle-v2 vowels))) (check vowels-odds (cadr (unriffle-v2 vowels))) (display "Checking unriffle-v3: ") (newline) (check null (car (unriffle-v3 null))) (check null (cadr (unriffle-v3 null))) (check alphabet-evens (car (unriffle-v3 alphabet))) (check alphabet-odds (cadr (unriffle-v3 alphabet))) (check vowels-evens (car (unriffle-v3 vowels))) (check vowels-odds (cadr (unriffle-v3 vowels))) (display "Checking unriffle-v4: ") (newline) (check null (car (unriffle-v4 null))) (check null (cadr (unriffle-v4 null))) (check alphabet-evens (car (unriffle-v4 alphabet))) (check alphabet-odds (cadr (unriffle-v4 alphabet))) (check vowels-evens (car (unriffle-v4 vowels))) (check vowels-odds (cadr (unriffle-v4 vowels))) (display "Checking unriffle-v5: ") (newline) (check null (car (unriffle-v5 null))) (check null (cadr (unriffle-v5 null))) (check alphabet-evens (car (unriffle-v5 alphabet))) (check alphabet-odds (cadr (unriffle-v5 alphabet))) (check vowels-evens (car (unriffle-v5 vowels))) (check vowels-odds (cadr (unriffle-v5 vowels))) )) ; +---------+--------------------------------------------------------- ; | History | ; +---------+ ; Tuesday, 19 September 2006 (v1) [Samuel A. Rebelsky] ; * Created. ; Wednesday, 20 September 2006 (v1.1) [Samuel A. Rebelsky] ; * Added file header. ; * Grouped testing into a procedure (tests ran automatically before) ; * Renamed the versions slightly. ; * Add v5 (using a counter)