1 ;; The first three lines of this file were inserted by DrScheme. They record metadata
2 ;; about the language level of this file in a form that our tools can easily process.
3 #reader(lib "" "lang")((modname 17.6.5) (read-case-sensitive #t) (teachpacks ((lib "" "teachpack" "htdp") (lib "" "teachpack" "htdp") (lib "" "teachpack" "htdp") (lib "" "teachpack" "htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "" "teachpack" "htdp") (lib "" "teachpack" "htdp") (lib "" "teachpack" "htdp") (lib "" "teachpack" "htdp")))))
4 ;A list-of-names is either
5 ;1. empty or
6 ;2. (cons s lon)
7 ;where s is a symbol and lon is a list-of-names.
8 ;
9 ;A list-of-list-of-names is either
10 ;1. empty, or
11 ;2. (cons lon lolon)
12 ;where lon is a list-of-names and lolon is a list-of-list-of-names.
14 ;gift-pick : list-of-names -> list-of-names
15 ;Given names, return a randomly picked re-arrangement of list-of-names where not a single name is found in an identical position in the new list as in alon.
17 (define (gift-pick names)
18 (random-pick
19 (non-same names (arrangements names))))
21 ;random-pick : list-of-list-of-names -> list-of-names
22 ;Given a-lolon, pick one list-of-names randomly.
24 (define (random-pick a-lolon)
25 (pick-nth a-lolon (+ 1 (random (length a-lolon)))))
27 ;pick-nth : list-of-list-of-names N[>=1] -> list-of-names
28 ;Given a-lolon, pick the n-th list-of-names. The first list-of-names has an index of 1.
30 (define (pick-nth a-lolon n)
31 (cond
32 [(empty? a-lolon) (error 'pick-nth "Unexpected error")]
33 [(= n 1) (first a-lolon)]
34 [(> n 1) (pick-nth (rest a-lolon) (sub1 n))]))
36 ;non-same : list-of-names list-of-list-of-names -> list-of-list-of-names
37 ;Given a-lon and a-lolon, return all list-of-names within a-lolon for those list-of-names where not a single name occupies the same position in the index as in a-lon.
39 (define (non-same a-lon a-lolon)
40 (cond
41 [(empty? a-lolon) empty]
42 [(no-common-index? (first a-lolon) a-lon) (append (list (first a-lolon))
43 (non-same a-lon (rest a-lolon)))]
44 [else (non-same a-lon (rest a-lolon))]))
46 ;no-common-index? : list-of-names list-of-names -> boolean
47 ;Given lon1 and lon2, return true if not a single name occupies the same index in lon1 and lon2. False otherwise.
48 ;ASSUMPTION: Both lists are of the same length.
50 (define (no-common-index? lon1 lon2)
51 (cond
52 [(empty? lon1) true]
53 [(symbol=? (first lon1) (first lon2)) false]
54 [else (no-common-index? (rest lon1) (rest lon2))]))
56 ;arrangements : list-of-names -> list-of-list-of-names
57 ;Given names (a list-of-names), return all permutations of the names.
59 (define (arrangements names)
60 (cond
61 [(empty? names) (list empty)]
62 [else (insert-in-lolon (first names) (arrangements (rest names)))]))
64 ;insert-in-lolon : symbol list-of-list-of-names -> list-of-list-of-names
65 ;Given a-symbol and a-lolon, insert a-symbol into every position in each list-of-names element within a-lolon to return a new list-of-list-of-names.
67 (define (insert-in-lolon a-symbol a-lolon)
68 (cond
69 [(empty? a-lolon) empty]
70 [(cons? a-lolon)
71 (append (insert-name a-symbol (first a-lolon) (length (first a-lolon)))
72 (insert-in-lolon a-symbol (rest a-lolon)))]))
74 ;insert-name : symbol list-of-names N[>=0] -> list-of-list-of-names
75 ;Given a-symbol, insert it into every position in names starting at the n-th position, continuing to the very beginning of the list-of-names (n=0), to return a list-of-list-of-names.
77 (define (insert-name a-symbol names n)
78 (cond
79 [(= n 0) (list (insert-name-at-posn a-symbol names n))]
80 [(cons? names) (append (list (insert-name-at-posn a-symbol names n))
81 (insert-name a-symbol names (sub1 n)))]
82 [(empty? names) (error 'insert-name "unexpected error")]))
84 ;insert-name-at-posn : symbol list-of-names N[>=0] -> list-of-names
85 ;Given a-symbol (symbol), names (list-of-names), and n (N[>=0]), insert a-symbol into names at the n-th position and return the list-of-names.
87 (define (insert-name-at-posn a-symbol names n)
88 (cond
89 [(= n 0) (append (list a-symbol) names)]
90 [(cons? names) (append (list (first names))
91 (insert-name-at-posn a-symbol (rest names) (sub1 n)))]
92 [(empty? names) (error 'insert-name-at-posn "list too short")]))