Comment detail

トランプの和と積のパズル (Nested Flatten)
関数名や変数名がややこしくなってロジックが見えにくくなってきたので、日本語で行くことにしました。 1〜13程度では大した事はありませんが、カードの値域が広くなるとメモ化が威力を発揮します。
  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
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
(use srfi-1)

(define *カードの数リスト* (iota 13 1)) ;'(1 2 3 4 5 6 7 8 9 10 11 12 13)
(define *Aに教える数の算出法* *) ;(lambda (x y) (* x y)))
(define *Bに教える数の算出法* +) ;(lambda (x y) (+ x y)))

(define (組合せを作る 1 2)
  (let ((Aの数 (*Aに教える数の算出法* 1 2))
		(Bの数 (*Bに教える数の算出法* 1 2)))
	(define (dispatch m)
	  (case m
		((1) 1)
		((2) 2)
		((Aの数) Aの数)
		((Bの数) Bの数)
		((xy?) (<= 1 2))
		(else 'ignored)))
	dispatch))

(define 全ての組合せ
  (filter (lambda (組合せ) [組合せ'xy?])
		  (apply append
				 (map (lambda (1)
						(map (lambda (2) (組合せを作る 1 2))
							 *カードの数リスト*))
					  *カードの数リスト*))))

(define (メモ化版 f)
  (let ((memo '()))
	(lambda (arg) 
	  (let ((found (assoc arg memo)))
		(if found
			(cdr found)
			(let ((value (f arg)))
			  (set! memo (cons (cons arg value) memo))
			  value))))))
;(define (メモ化版 f) f) ; ← メモ化しないならコメントを外す

;(define (Aの数から考えられる組合せ Aの数)
;  (filter (lambda (組合せ) (= Aの数 [組合せ'Aの数]))
;		  全ての組合せ))
(define Aの数から考えられる組合せ
  (メモ化版 (lambda (Aの数)
			  (filter (lambda (組合せ) (= Aの数 [組合せ'Aの数]))
					  全ての組合せ)) ))

;(define (Bの数から考えられる組合せ Bの数)
;  (filter (lambda (組合せ) (= Bの数 [組合せ'Bの数]))
;		  全ての組合せ))
(define Bの数から考えられる組合せ
  (メモ化版 (lambda (Bの数)
			  (filter (lambda (組合せ) (= Bの数 [組合せ'Bの数]))
					  全ての組合せ)) ))

;(define (Aの数から組合せを一つに絞り込める? Aの数)
;  (= 1 (length (Aの数から考えられる組合せ Aの数))))
(define Aの数から組合せを一つに絞り込める?
  (メモ化版 (lambda (Aの数)
			  (= 1 (length (Aの数から考えられる組合せ Aの数)))) ))

;(define (Bの数から組合せを一つに絞り込める? Bの数)
;  (= 1 (length (Bの数から考えられる組合せ Bの数))))
(define Bの数から組合せを一つに絞り込める?
  (メモ化版 (lambda (Bの数)
			  (= 1 (length (Bの数から考えられる組合せ Bの数)))) ))

;
; 4つの条件
;
(define (Aの数からは組合せを一つに絞り込めない? Aの数)
  (not (Aの数から組合せを一つに絞り込める? Aの数)))

(define (Bの数からは組合せを一つに絞り込めないがAにも分からないだろうという事はBに言える? Bの数)
  (and (not (Bの数から組合せを一つに絞り込める? Bの数))
	   (let ((Bの数から考えられる全てのAの数
			  (map (lambda (組合せ) [組合せ'Aの数]) (Bの数から考えられる組合せ Bの数))))
		 (let ((Bの数から考えられる全てのAの数の中で、Aが聞いたらすぐに組合せを一つに絞り込めてしまうもの
				(filter (lambda (Aの数) (Aの数から組合せを一つに絞り込める? Aの数)) Bの数から考えられる全てのAの数)))
		   (null? Bの数から考えられる全てのAの数の中で、Aが聞いたらすぐに組合せを一つに絞り込めてしまうもの) ))))

(define (Aには分からないとBの数から予測できるのならAは絞り込める? Aの数)
  (let1 可能な組合せ
		(filter (lambda (組合せ) (Bの数からは組合せを一つに絞り込めないがAにも分からないだろうという事はBに言える? [組合せ'Bの数]))
				(Aの数から考えられる組合せ Aの数))
		(= 1 (length 可能な組合せ)) ))

(define (Aには分からないとBの数から予測できるのならAは絞り込めるというのならBも絞り込める? Bの数)
  (let1 可能な組合せ
		(filter (lambda (組合せ) (Aには分からないとBの数から予測できるのならAは絞り込める? [組合せ'Aの数]))
				(Bの数から考えられる組合せ Bの数))
		(= 1 (length 可能な組合せ)) ))

;
; 4つの条件を満たす組合せを表示
;
(define (4つの条件を満たす? ある組合せ)
  (let ((Aの数 [ある組合せ'Aの数])
		(Bの数 [ある組合せ'Bの数]))
	(and (Aの数からは組合せを一つに絞り込めない? Aの数)
		 (Bの数からは組合せを一つに絞り込めないがAにも分からないだろうという事はBに言える? Bの数)
		 (Aには分からないとBの数から予測できるのならAは絞り込める? Aの数)
		 (Aには分からないとBの数から予測できるのならAは絞り込めるというのならBも絞り込める? Bの数))))

(for-each (lambda (組合せ) (print [組合せ'1] "," [組合せ'2]))
		  (filter 4つの条件を満たす? 全ての組合せ))

Index

Feed

Other

Link

Pathtraq

loading...