麻雀プログラムの基本 あがりの形を得る

Gaucheの例。append-map による深さ優先探索

(use srfi-1)

(define (delete-elt x l)
  (let ([index (list-index (lambda (p) (eq? p x)) l)])
    (and index (call-with-values
		   (lambda () (split-at l index))
		 (lambda (x xs) (append x (cdr xs)))))))

(define (delete-elts x l)
  (cond 
    ((null? x) l)
    ((delete-elt (car x) l) => (lambda (y) (delete-elts (cdr x) y)))
    (else #f)))

(define (pi-l->mentu-lol pi-l)
  (let loop ((l pi-l)
	     (res '()))
    (if (null? l)
        (list (reverse res))
	(append-map (lambda (mentu)
		      (let ([new-l (delete-elts mentu l)])
			(if new-l
			    (loop new-l (cons mentu res))
			    '())))
		    (let ([pi (car l)])
		      (list (list pi (+ pi 1) (+ pi 2)) (list pi pi pi) (list pi pi)))))))

(for-each print (pi-l->mentu-lol '(2 2 2 3 3 3 3 4 4 4 4 5 5 5)))

問題は、(2 2 2 3 3 3 3 4 4 4 4 5 5 5)
出力は、

((2 3 4) (2 3 4) (2 3 4) (3 4 5) (5 5))
((2 3 4) (2 2) (3 4 5) (3 4 5) (3 4 5))
((2 3 4) (2 2) (3 4 5) (3 3) (4 4) (5 5))
((2 3 4) (2 2) (3 3 3) (4 4 4) (5 5 5))
((2 3 4) (2 2) (3 3) (3 4 5) (4 4) (5 5))
((2 2 2) (3 4 5) (3 3 3) (4 4 4) (5 5))
((2 2 2) (3 3 3) (3 4 5) (4 4 4) (5 5))
((2 2 2) (3 3) (3 3) (4 4) (4 4) (5 5 5))
((2 2) (2 3 4) (3 4 5) (3 4 5) (3 4 5))
((2 2) (2 3 4) (3 4 5) (3 3) (4 4) (5 5))
((2 2) (2 3 4) (3 3 3) (4 4 4) (5 5 5))
((2 2) (2 3 4) (3 3) (3 4 5) (4 4) (5 5))

重複があるが、容易に取り除けるだろう。コードの見やすさのためにその処理は省略した。

昨日のを入力してみると、こうなる。

((1 2 3) (1 2 3) (1 2 3) (1 2 3) (9 9))
((1 2 3) (1 2 3) (1 1) (2 2) (3 3) (9 9))
((1 2 3) (1 1 1) (2 2 2) (3 3 3) (9 9))
((1 2 3) (1 1) (1 2 3) (2 2) (3 3) (9 9))
((1 1 1) (1 2 3) (2 2 2) (3 3 3) (9 9))
((1 1) (1 2 3) (1 2 3) (2 2) (3 3) (9 9))
((1 1) (1 1) (2 2) (2 2) (3 3) (3 3) (9 9))