年齢あてパズル on EmacsLisp

たまたま以下のパズルを見かけて、忙しかったのでといてみた:


2人の金髪の女性が通り沿いのカフェで座っていた。最初の女性は、彼女には3人の娘達がいると言った。3人の娘達の年齢を、それぞれ全て掛け合わせると36になること、それぞれ全て加えると、丁度、(そこからみえる)通りの向こう側の家の番号になるのだと言った。2番目の金髪の女性は、それだけの情報では3人の娘達のそれぞれの年齢は判らないと応えた。すると最初の女性はそのことを肯定し、さらに情報を付け加えて『一番上の娘は美しい青い目をしているのよ』と応じた。すると2番目の女性は3人の娘達のそれぞれの年齢が判ったと言う。あなたにも判る筈だがどうですか?
最初は封筒裏で何とかなるかと思ったが、組み合わせが多くて面倒くさくなったので *scratch* での計算だ。何しろ編集しながらの計算なので、途中結果がすべて保全されているわけじゃないが、ご容赦:

; 2を3つの非負の整数に分ける方法。これは面倒くさいので天下り的
(setq ss '((0 1 1) (1 0 1) (1 1 0) (2 0 0) (0 2 0) (0 0 2)))

; べき乗のリストのリストを作る
(defun ppow (b ss)
  (mapcar '(lambda (s) 
	     (mapcar '(lambda (f) 
			(expt b f)) 
		     s))
	  ss))
ppow
(ppow 3 ss) ; テスト。うまくいってる
((1 3 3) (3 1 3) (3 3 1) (9 1 1) (1 9 1) (1 1 9))

; 年齢の組み合わせの可能性を求めようと思ったけど..
; mapcar* (zipWith相当) だとうまくいかん。直積にしなきゃ..
(mapcar* '(lambda (f2s f3s) (mapcar* '* f2s f3s)) (ppow 2 ss) (ppow 3 ss))
((1 6 6) (6 1 6) (6 6 1) (36 1 1) (1 36 1) (1 1 36))

; リストの直積。以前書いたものから
(defun list-product (&rest lists)
  (if (null lists) '(())
    (let ((list0 (car lists))
	  (prod (apply #'list-product (cdr lists))))
      (apply #'append 
	     (mapcar #'(lambda (elem)
			 (mapcar #'(lambda (seq)
					   (cons elem seq))
				 prod))
		     list0)))))

; 2のべきと3のべきの直積を求めて
(setq combs (list-product (ppow 2 ss) (ppow 3 ss)))

; 一応長さ確認 
(length combs)
36

; ありうる年齢の組み合わせを求める。でも重複ありだからまだみにくい
(setq years 
  (mapcar* '(lambda (comb) (sort (mapcar* '* (car comb) (cadr comb)) '<=)) combs))

; listの listを sortするために。最初は elispに closureがないのわすれて
; defunして、"cmpなんて知らん" っていわれてしまった
(defmacro list-cmp (cmp)
  `(lambda (l0 l1)
     (let ((r 0))
       (while (and l0 l1 (= (setq r (funcall ,cmp (car l0) (car l1))) 0))
	 (setq l0 (cdr l0) l1 (cdr l1)))
       r)))
(funcall (list-cmp '-) '() '()) ; 当然テスト。
0

; sort | uniq。uniqは mewにそれらしきものがあったので拝借。
(mew-uniq-list 
 (sort years '(lambda (ys0 ys1) (< (funcall (list-cmp '-) ys0 ys1) 0))))

; あるうる可能性がわかったので、それを cut&yankして sumを求めてみる
(mapcar (lambda (ys) (apply '+ ys)) 
 '((1 1 36) (1 2 18) (1 3 12) (1 4 9) (1 6 6) (2 2 9) (2 3 6) (3 3 4)))
(38 21 16 14 13 13 11 10)

つまり、番号を教えてもらってもわからなかったんだから、その番号は 13だ。で、「一番上の娘」という表現ができるには、上が双子じゃ駄目。よって2,2,9が正解。

いや、でももしかして上の二人は年は同じでも 10ヶ月違いとかいうことも考えられるじゃないか。その場合、1,6,6でもありえる。よって問題に不備があるともいえる。われながら重箱の隅だ。

追記: よく見ると次の日の日記で解答がしてあって、俺とおんなじことを突っ込んでるのであった。みんな同じだなあ。

さらに深読みしてあって、生き別れ説とか..これはよくわからん :-)