git @ Cat's Eye Technologies Arboretuum / rel_1_0_2008_0304 src / utils.scm
rel_1_0_2008_0304

Tree @rel_1_0_2008_0304 (Download .tar.gz)

utils.scm @rel_1_0_2008_0304raw · history · blame

;
; Utility functions used by forest-rewriting project
; Chris Pressey, late January 2006
;

; Copyright (c)2008 Cat's Eye Technologies.  All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
;
; 1. Redistributions of source code must retain the above copyright
;    notices, this list of conditions and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright
;    notices, this list of conditions, and the following disclaimer in
;    the documentation and/or other materials provided with the
;    distribution.
; 3. Neither the names of the copyright holders nor the names of their
;    contributors may be used to endorse or promote products derived
;    from this software without specific prior written permission. 
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
; ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES INCLUDING, BUT NOT
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
; FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
; COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
; ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
; POSSIBILITY OF SUCH DAMAGE.

;
; Sort a list using mergesort.
;
(define mergesort
  (lambda (lst gt-pred?)
    (cond ((null? lst)
            lst)
          ((null? (cdr lst))
            lst)
          (else
            (let* ((pair  (split lst '() '()))
                   (left  (mergesort (car pair) gt-pred?))
                   (right (mergesort (cdr pair) gt-pred?)))
                (merge left right gt-pred? '()))))))

;
; Yield a pair of lists, each containing roughly half the
; elements of the given list.
;
(define split
  (lambda (lst acc1 acc2)
    (cond
      ((null? lst)
        (cons (reverse acc1) (reverse acc2)))
      ((null? (cdr lst))
        (cons (reverse (append lst acc1)) (reverse acc2)))
      (else
        (let* ((left  (car lst))
               (right (cadr lst))
               (rest  (cddr lst)))
          (split rest (cons left acc1) (cons right acc2)))))))

;
; Given two sorted lists, return a sorted list that contains
; all of the elements from both lists.
;
(define merge
  (lambda (list1 list2 gt-pred? acc)
    (cond
      ((and (null? list1) (null? list2))
        (reverse acc))
      ((null? list1)
        (merge list1 (cdr list2) gt-pred? (cons (car list2) acc)))
      ((null? list2)
        (merge (cdr list1) list2 gt-pred? (cons (car list1) acc)))
      ((gt-pred? (car list1) (car list2))
        (merge list1 (cdr list2) gt-pred? (cons (car list2) acc)))
      (else
        (merge (cdr list1) list2 gt-pred? (cons (car list1) acc))))))

;
; Side-effect-free alternative to vector-set!
;
(define vector-store
  (lambda (vec index item)
    (let loop ((items (vector->list vec))
               (index index)
               (item  item)
               (acc   '()))
      (cond ((null? items)
              (list->vector (reverse acc)))
            ((zero? index)
              (loop (cdr items) (- index 1) item (cons item acc)))
            (else
              (loop (cdr items) (- index 1) item (cons (car items) acc)))))))

;
; Debugging output.
;
(define print
  (lambda list
    (for-each display list)))

(define println
  (lambda list
    (for-each display list)
    (newline)))

;
; Testing framework.
;
(define test
  (lambda (test-name proc expected)
    (print "Running test: " test-name "... ")
    (let ((result (proc)))
      (cond
        ((equal? result expected)
          (println "passed."))
        (else
          (println "FAILED!")
          (println "Expected: " expected)
          (println "Actual:   " result))))))