permute.scm 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. (declare (usual-integrations))
  21. ;;; Generates a list of all permutations of a list of distinct elements.
  22. (define (permutations lst)
  23. (if (null? lst)
  24. '(())
  25. (apply append
  26. (map (lambda (item)
  27. (map (lambda (perm) (cons item perm))
  28. (permutations (delete item lst))))
  29. lst))))
  30. (define (combinations lst p)
  31. (cond ((= p 0) '(()))
  32. ((null? lst) '())
  33. (else (append (map (lambda (rest)
  34. (cons (car lst) rest))
  35. (combinations (cdr lst) (- p 1)))
  36. (combinations (cdr lst) p)))))
  37. #|
  38. (pp (combinations '(a b c d e) 3))
  39. ((a b c)
  40. (a b d)
  41. (a b e)
  42. (a c d)
  43. (a c e)
  44. (a d e)
  45. (b c d)
  46. (b c e)
  47. (b d e)
  48. (c d e))
  49. |#
  50. ;;; Returns the number of interchanges required to generate the
  51. ;;; permuted list from the original list.
  52. (define (list-interchanges permuted-list original-list)
  53. (let lp1 ((plist permuted-list) (count 0))
  54. (if (null? plist)
  55. count
  56. (let ((bigger (cdr (member (car plist) original-list)))
  57. (rest (cdr plist)))
  58. (let lp2 ((l rest) (increment 0))
  59. (if (null? l)
  60. (lp1 rest
  61. (fix:+ count increment))
  62. (lp2 (cdr l)
  63. (if (not (member (car l) bigger))
  64. (fix:+ increment 1)
  65. increment))))))))
  66. (define (split-permutations original-list list-of-permutations cont)
  67. ;; cont = (lambda (even-permutations odd-permutations) ... )
  68. (let lp ((perms list-of-permutations) (evens '()) (odds '()))
  69. (if (null? perms)
  70. (cont evens odds)
  71. (let ((sig (list-interchanges (car perms) original-list)))
  72. (if (even? sig)
  73. (lp (cdr perms) (cons (car perms) evens) odds)
  74. (lp (cdr perms) evens (cons (car perms) odds)))))))
  75. ;;; Returns the number of interchanges required to generate the
  76. ;;; permuted list of numbers from an ordered list.
  77. (define (permutation-interchanges permuted-list)
  78. (let lp1 ((plist permuted-list) (count 0))
  79. (if (null? plist)
  80. count
  81. (let ((first (car plist))
  82. (rest (cdr plist)))
  83. (let lp2 ((l rest) (increment 0))
  84. (if (null? l)
  85. (lp1 rest
  86. (fix:+ count increment))
  87. (lp2 (cdr l)
  88. (if (int:> (car l) first)
  89. increment
  90. (fix:+ increment 1)))))))))
  91. ;;; Given a permutation (represented as a list of numbers),
  92. ;;; and a list to be permuted, construct the list so permuted.
  93. (define (permute permutation lst)
  94. (map (lambda (p)
  95. (list-ref lst p))
  96. permutation))
  97. ;;; Given a short list and a comparison function, to sort the list by
  98. ;;; the comparison, returning the original list, the sorted list, the
  99. ;;; permutation procedure and the inverse permutation procedure
  100. ;;; developed by the sort.
  101. (define (sort-and-permute ulist <? cont)
  102. ;; cont = (lambda (ulist slist perm iperm) ...)
  103. (let* ((n
  104. (length ulist))
  105. (lsource
  106. (map list ulist (iota n)))
  107. (ltarget
  108. (sort lsource
  109. (lambda (x y) (<? (car x) (car y)))))
  110. (sorted (map car ltarget))
  111. (perm (map cadr ltarget))
  112. (iperm
  113. (make-initialized-list n
  114. (lambda (i) (list-index-of i perm)))))
  115. (cont ulist
  116. sorted
  117. (lambda (l) (permute perm l))
  118. (lambda (l) (permute iperm l)))))
  119. #|
  120. ;;; For example
  121. (sort-and-permute '(0 2 0 0 1 2 0 0) <
  122. (lambda (unsorted sorted permuter unpermuter)
  123. (list unsorted sorted (permuter unsorted) (unpermuter sorted))))
  124. #|
  125. ((0 2 0 0 1 2 0 0)
  126. (0 0 0 0 0 1 2 2)
  127. (0 0 0 0 0 1 2 2)
  128. (0 2 0 0 1 2 0 0))
  129. |#
  130. |#
  131. ;;; Sometimes we want to permute some of the elements of a list, as follows:
  132. ;;; (subpermute '((1 . 4) (4 . 2) (2 . 3) (3 . 1)) '(a b c d e))
  133. ;;; ;Value 6: (a e d b c)
  134. (define (subpermute the-map lst)
  135. (let* ((n (length lst)))
  136. (let lp ((i 0) (source lst) (answer '()))
  137. (if (fix:= i n)
  138. (reverse answer)
  139. (let ((entry (assoc i the-map)))
  140. (if (not entry)
  141. (lp (fix:+ i 1)
  142. (cdr source)
  143. (cons (car source) answer))
  144. (lp (fix:+ i 1)
  145. (cdr source)
  146. (cons (list-ref lst (cdr entry)) answer))))))))
  147. ;;; FBE: factorial is also defined in kernel/numeric.scm. Therefore
  148. ;;; we rename the version defined here to int:factorial and use it in
  149. ;;; this file.
  150. ;; (define (factorial n)
  151. ;; (if (int:< n 2)
  152. ;; 1
  153. ;; (int:* n (factorial (int:- n 1)))))
  154. ;; (define number-of-permutations factorial)
  155. ;; (define (number-of-combinations n k)
  156. ;; (int:quotient (factorial n)
  157. ;; (int:* (factorial (int:- n k))
  158. ;; (factorial k))))
  159. ;; (define (permutation-parity permuted-list original-list)
  160. ;; (if (same-set? permuted-list original-list)
  161. ;; (if (even? (list-interchanges permuted-list original-list))
  162. ;; +1
  163. ;; -1)
  164. ;; 0))
  165. (define (int:factorial n)
  166. (if (int:< n 2)
  167. 1
  168. (int:* n (int:factorial (int:- n 1)))))
  169. (define number-of-permutations int:factorial)
  170. (define (number-of-combinations n k)
  171. (int:quotient (int:factorial n)
  172. (int:* (int:factorial (int:- n k))
  173. (int:factorial k))))
  174. (define (permutation-parity permuted-list original-list)
  175. (if (same-set? permuted-list original-list)
  176. (if (even? (list-interchanges permuted-list original-list))
  177. +1
  178. -1)
  179. 0))