File: perm.l

package info (click to toggle)
euslisp 9.27%2Bdfsg-7
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 55,344 kB
  • sloc: ansic: 41,162; lisp: 3,339; makefile: 256; sh: 208; asm: 138; python: 53
file content (93 lines) | stat: -rw-r--r-- 2,308 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
;;;; Permutation and Combination
;; It is a bad idea to generate permutations recursively, since stack over-
;; flows soon.  Use of permutation generator class is recommended.
;;
;; Aug/16/1991 (c) Toshihiro MATSUI, Electrotechnical Laboratory
;;

   

(defun list-permutation (x)
 (labels ((perm2 (a bb cc dd)
	   (cond ((null cc) (cons  (append bb (list a)) dd))
		 (t (perm2 a (append bb (list (car cc)))
			     (cdr cc) 
			     (cons (append bb (list a) cc) dd) )
		     ))) )
    (cond ((null x) nil)
	  ((null (cdr x)) (list x))
	  (t 
	     (mapcan
		#'(lambda (y) (perm2 (car x) nil y nil))
		(list-permutation (cdr x)))))) )


;; permutaion generator
;; sending :next returns a new permutaion of a list in turn
;;
(defclass permutation :super propertied-object
		      :slots (mlist sub-permutation a b c count))

(defmethod permutation
 (:next ()
    (if (null c)
        (if sub-permutation
	    (if (null b)
	        (setq c (send sub-permutation :next))
	        (return-from :next
		   (prog1 (nconc b (list a)) (setq b nil count (1+ count)))) )
	    (return-from :next
		   (if (null b)
			(setq count (1+ count) b mlist)
			 nil ))  ) )
    (if (null c)
	nil
	(prog1 (append b (cons a nil) c)
	       (setq b (nconc b (list (car c)))
		     c (rest c)
		     count (1+ count)))) )
 (:all (&aux x r)
    (while (setq x (send self :next))
	(push x r))
    r)
 (:reset ()
    (if sub-permutation (send sub-permutation :reset))
    (setq a (car mlist)
	  b nil
	  c nil
	  count 0))
 (:init (l)
    (setq mlist l)
    (when (cdr l)
	(setq sub-permutation (instance permutation :init (cdr mlist))))
    (send self :reset)
    self))

;;****************************************************************
;; combination
;;
;; (combi list r) generates all the combination list which is composed of
;; r-elements in the list.
;; (combi2 list) is a spcecial case of the combination and equivalent to
;; (combi list 2), but more efficient.

(defun combi (lst r)
   (cond ((= r 1) (mapcar #'list lst))
	 (t  (mapcon
		#'(lambda (y)
			(mapcar #'(lambda (z) (cons (car y) z))
				(combi (cdr y) (1- r))))
		lst))))

(defun combi2 (lst)
    (mapcon 
	#'(lambda (x)
		(mapcar #'(lambda (y) (list (car x) y))
			(cdr x)))
	 lst))

(defmacro docombi (A B &rest forms)
   `(dolist ,A
	(dolist ,B . ,forms)))