2014年12月12日金曜日

クリスマスの歌

今年もクリスマスが近付いた. 最近の私にそういう機会はないが, 以前はクリスマスキャロルに誘われて聞きにいったりした.

そこで歌われる歌の中に, On the first day of Christmas,... で始まる歌がある. 出典によって文句や順番が多少違ったりするが, 大体はこうだ.

On the 1st day of Christmas,
my true love sent to me:
a Partridge in a Pear Tree.

On the 2nd day of Christmas,
my true love sent to me:
2 Turtle Doves
and a Partridge in a Pear Tree.

クリスマスの1日目, 私の恋人は
ナシの木の1羽のヤマウズラをくれた.

クリスマスの2日目, 私の恋人は
2羽のヤマバトと
ナシの木の1羽のヤマウズラをくれた.
つまり
クリスマスのn日目, 私の恋人は
n個のなにか, 
n-1個のなにか,
...
2羽のヤマバトと
ナシの木の1羽のヤマウズラをくれた.
と12日目まで続く.

結構規則的なので, 記号処理プログラムで生成するのが簡単であり, その昔Snobol 4の手引き書に出ていたのを覚えている. さらにこの歌詞をAlgol 68での階乗のプログラムにしたという話もあるが(The Most Contrived Factorial Program, Allgol Bulletin 42 (1978)), それはまたいつか書くこともあろう.

私自身はエディタのTecoで書いたことがあった. (bit Vo. 14, No. 10, 1982) 最近のことだが, GPMでも書いてみた. いろいろ苦労したが, 超絶技巧な技を利用. それについてもまたいつか書きたい.

TecoとかGPMのようなプリミティブなプログラム言語とは別に, Schemeで書くとどうなるか. やはり超簡単の単であった. 以下の通り.
(define a '
("12 Drummers Drumming\n"
 "11 Pipers Piping\n"
 "10 Lords a Leaping\n"
 "9 Ladies Dancing\n"
 "8 Maids a Milking\n"
 "7 Swans a Swimming\n"
 "6 Geese a Laying\n"
 "5 Golden Rings\n"
 "4 Colly Birds\n"
 "3 French Hens\n"
 "2 Turtle Doves\nand "
 "a Partridge in a Pear Tree.\n"))
(define b '
("12th" "11th" "10th" "9th" "8th" "7th" 
 "6th" "5th" "4th" "3rd" "2nd" "1st"))
(do ((i 11 (- i 1))) ((< i 0))
(display (string-append
"\nOn the " (list-ref b i) 
" day of Christmas,\nmy true love sent to me:\n"
(apply string-append (list-tail a i)))))
ところで私は何となく贈りものの数を1+2+...+12=78だと思っていたが, ヤマウズラは12日間贈り, 2羽のヤマバトは11日間贈るので, 総計は1*12+2*11+3*10+...+12*1だったらしい. 丁度途中の6*7+7*6のところで折り返すから,1*12+2*11+3*10+4*9+5*8+6*7まで計算し2倍する.

4*9+5*8+6*7は簡単かもしれない.


赤の枠が5*8, 緑の枠が4*9. 青の枠が6*7である. 青の斜線部分を左に1だけ移動し, 赤枠内に移動すると, 緑の斜線部分と合せて赤枠の面積マイナス1になり, 緑の残り部分と青の残り部分も赤枠-1になるから, 5*8*3-2=118だ.

1*12+2*11+3*10も同様に2*11*3-2=64. 全体は(118+64)*2=364だ. 1年の日数に1日足りないのか.

0 件のコメント: