Skip to content

Commit df553b6

Browse files
committed
add missing (schemepunk sort) procedures
1 parent f6c1ae1 commit df553b6

File tree

2 files changed

+129
-2
lines changed

2 files changed

+129
-2
lines changed

polyfills/132-extras.scm

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
;; Extra SRFI 132 procedures, copied from Chibi Scheme
2+
3+
(define (list-delete-neighbor-dups eq ls)
4+
(let lp ((ls ls) (res '()))
5+
(cond ((null? ls) (reverse res))
6+
((and (pair? res) (eq (car res) (car ls))) (lp (cdr ls) res))
7+
(else (lp (cdr ls) (cons (car ls) res))))))
8+
9+
(define (list-delete-neighbor-dups! eq ls)
10+
(if (pair? ls)
11+
(let lp ((ls (cdr ls)) (start ls))
12+
(cond ((null? ls) (set-cdr! start '()))
13+
((eq (car start) (car ls)) (lp (cdr ls) start))
14+
(else (set-cdr! start ls) (lp (cdr ls) ls)))))
15+
ls)
16+
17+
(define (vector-delete-neighbor-dups eq vec . o)
18+
(if (zero? (vector-length vec))
19+
vec
20+
(let ((ls (if (and (pair? o) (pair? (cdr o)))
21+
(vector->list vec (car o) (cadr o))
22+
(apply vector->list vec o))))
23+
(list->vector (list-delete-neighbor-dups eq ls)))))
24+
25+
(define (vector-delete-neighbor-dups! eq vec . o)
26+
(let ((start (if (pair? o) (car o) 0))
27+
(end (if (and (pair? o) (pair? (cdr o))) (cadr o) (vector-length vec))))
28+
(cond
29+
((<= end start) start)
30+
(else
31+
(let lp ((i (+ start 1))
32+
(fill (+ start 1)))
33+
(cond
34+
((>= i end) fill)
35+
((eq (vector-ref vec (- i 1)) (vector-ref vec i)) (lp (+ i 1) fill))
36+
(else
37+
(if (> i fill)
38+
(vector-set! vec fill (vector-ref vec i)))
39+
(lp (+ i 1) (+ fill 1)))))))))
40+
41+
;; Median of 3 (good in practice, use median-of-medians for guaranteed
42+
;; linear time).
43+
(define (choose-pivot < vec left right)
44+
(let* ((mid (quotient (+ left right) 2))
45+
(a (vector-ref vec left))
46+
(b (vector-ref vec mid))
47+
(c (vector-ref vec right)))
48+
(if (< a b)
49+
(if (< b c) mid (if (< a c) right left))
50+
(if (< a c) left (if (< b c) right mid)))))
51+
52+
;; Partitions around elt and returns the resulting median index.
53+
(define (vector-partition! < vec left right pivot)
54+
(define (swap! i j)
55+
(let ((tmp (vector-ref vec i)))
56+
(vector-set! vec i (vector-ref vec j))
57+
(vector-set! vec j tmp)))
58+
(let ((elt (vector-ref vec pivot)))
59+
(swap! pivot right)
60+
(let lp ((i left)
61+
(j left))
62+
(cond
63+
((= i right)
64+
(swap! i j)
65+
j)
66+
((< (vector-ref vec i) elt)
67+
(swap! i j)
68+
(lp (+ i 1) (+ j 1)))
69+
(else
70+
(lp (+ i 1) j))))))
71+
72+
;; Permutes vec in-place to move the k smallest elements as ordered by
73+
;; < to the beginning of the vector (unsorted). Returns the nth smallest.
74+
(define (vector-select! less vec k . o)
75+
(let* ((left (if (pair? o) (car o) 0))
76+
(k (+ k left)))
77+
(if (not (<= 0 k (vector-length vec)))
78+
(error "k out of range" vec k))
79+
(let select ((left left)
80+
(right (- (if (and (pair? o) (pair? (cdr o)))
81+
(cadr o)
82+
(vector-length vec))
83+
1)))
84+
(if (>= left right)
85+
(vector-ref vec left)
86+
(let* ((pivot (choose-pivot less vec left right))
87+
(pivot-index (vector-partition! less vec left right pivot)))
88+
(cond
89+
((= k pivot-index)
90+
(vector-ref vec k))
91+
((< k pivot-index)
92+
(select left (- pivot-index 1)))
93+
(else
94+
(select (+ pivot-index 1) right))))))))
95+
96+
(define (vector-separate! < vec k . o)
97+
(apply vector-select! < vec k o)
98+
(if #f #f))
99+
100+
(define (vector-find-median! < vec knil . o)
101+
(vector-sort! < vec) ; required by SRFI 132
102+
(let* ((len (vector-length vec))
103+
(mid (quotient len 2))
104+
(mean (if (pair? o) (car o) (lambda (a b) (/ (+ a b) 2)))))
105+
(cond
106+
((zero? len) knil)
107+
((odd? len) (vector-ref vec mid))
108+
(else (mean (vector-ref vec (- mid 1)) (vector-ref vec mid))))))
109+
110+
(define (vector-find-median < vec knil . o)
111+
(let* ((vec (vector-copy vec))
112+
(len (vector-length vec))
113+
(mid (quotient len 2))
114+
(mean (if (pair? o) (car o) (lambda (a b) (/ (+ a b) 2)))))
115+
(cond
116+
((zero? len) knil)
117+
(else
118+
(vector-separate! < vec mid)
119+
(cond
120+
((odd? len) (vector-ref vec mid))
121+
(else (mean (vector-ref vec (- mid 1)) (vector-ref vec mid))))))))

sort.sld

+8-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
list-sort! vector-sort!
99
list-stable-sort! vector-stable-sort!
1010
list-merge
11-
list-merge!)
11+
list-merge!
12+
list-delete-neighbor-dups vector-delete-neighbor-dups
13+
list-delete-neighbor-dups! vector-delete-neighbor-dups!
14+
vector-find-median vector-find-median!
15+
vector-select! vector-separate!)
1216

1317
(cond-expand
1418
((and (not chicken) (or (library (scheme sort)) (library (srfi 132))))
@@ -33,4 +37,6 @@
3337
(define vector-sort list-sort)
3438
(define vector-stable-sort list-stable-sort)
3539
(define vector-sort! list-sort!)
36-
(define vector-stable-sort! list-stable-sort!)))))
40+
(define vector-stable-sort! list-stable-sort!))
41+
42+
(include "polyfills/132-extras.scm"))))

0 commit comments

Comments
 (0)