Archive for 2013年4月|Monthly archive page

projecteuler4(続き)...または、組み合わせの求め方

 さて、問題4 の続きです。
 三桁の数同士を掛け算して、最大の回文数を求めるために、最初に回文数を用意します。

(setq digit 3
       max-num (pow 10 digit)
       numbers (sequence (pow 10 (- digit 1)) (- max-num 1))
       strings1 (map string numbers)
       strings2 (map reverse strings1)
       palindromes (map int (map append strings1 strings2)))

 palindromes の中に回文数が小さい順に入っています。それを newLISP 組込関数 reverse を使って順を逆にして、大きい順から一個一個、三桁の数同士の掛け算になるかどうかを確認します。
 そのために、例えば 906609 を newLISP 組込関数 factor で因数分解すると、

> (factor 906609)
(3 11 83 331)
> 

 このままでは、三桁の数同士の掛け算になるかどうか判りません。4つの数値を組み合わせて、二つの掛け算にする必要があります。
 その組み合わせは、

((3 11 83) (331))
((3 11 331) (83))
((3 11) (83 331))
((3 83 331) (11))
((3 83) (11 331))
((3 331) (11 83))
((3) (11 83 331))

 の7通り、リスト (3 11 83 331) の位置で表すと、

(0 0 0 1)
(0 0 1 0)
(0 0 1 1)
(0 1 0 0)
(0 1 0 1)
(0 1 1 0)
(0 1 1 1)

 と、こんな感じ。お気づきでしょうか、この組み合わせ方を binary counting と言うそうです。ここまで来れば、あとは実装するだけ。それが、前回紹介したコードになります。実行時間は早いはず、わずか 94 個目で解答にたどり着くわけですから(笑)。

 以上、如何でしょうか?

projecteuler4...または、newLISP の繰り返し構文

 projecteuler も5回目。前回はちょっと飛びましたが、今回は順当(笑)に問題4。三桁の数同士を掛け算して、最大の回文数を求めるというもの。
 これをで力技でやると、

(let (lst)
  (for (i 100 999)
    (for (j i 999)
      (let (str (string (* i j)))
        (if (and (= 6 (length str))
                 (= (0 3 str) (reverse (3 3 str))))
          (push str lst -1))
      )
    )
  )
  ((sort lst) -1)
)

 こんな感じ。newLISP には組込で for がありますから楽です。
 組込関数string は引数を文字列に変換します。
 掛け算した結果が6桁なら、文字列にも暗黙のインデックス機能(Implicit indexing)が使えるので、前半と後半を分け、比較します。
 同じなら、変数 lst に入れておいて、最後に組込関数 sort で並べ替えます。この関数は数値でも文字列でもなんでも並べ替えます。
 そして、最後の値(文字列)を取り出せば、答えに 906609 が得られます。
 まっ、これで終了ですが、もう一つ解答例を、

(define-macro (memoize mem-func func) 
  (set (sym mem-func mem-func) 
    (letex (f func  c mem-func) 
      (lambda () 
        (or (context c (string (args))) 
            (context c (string (args)) (apply f (args))))))))
(define (make-sublist lst)
  (let (res '(()()))
    (dolist (x lst)
      (push $idx (if x (res 0) (res 1)) -1))
  res))
(memoize divide2 (lambda (n)
  (let (res)
    (for (x 1 (- (/ (pow 2 n) 2) 1))
      (let (lst (bits x true))
        (push (if (< (length lst) n) (append lst (dup nil (- n (length lst)))) lst)
              res -1))
    )
  (map make-sublist res))))
(define (judge numbers digit)
  (letn (max-num (pow 10 digit)
         sublist (divide2 (length numbers))
         res)
    (dolist (x sublist res)
      (let (n1 (apply * (select numbers (x 0)))
            n2 (apply * (select numbers (x 1))))
        (if (and (< n1 max-num) (< n2 max-num)) (push (list n1 n2) res)))
     )
    res
  ))
(letn (digit 3
       max-num (pow 10 digit)
       numbers (sequence (pow 10 (- digit 1)) (- max-num 1))
       strings1 (map string numbers)
       strings2 (map reverse strings1)
       palindromes (map int (map append strings1 strings2))
       res)
  (dolist (x (reverse palindromes) res)
    (let (primes (factor x))
      (when (< (apply max primes) max-num)
        (if (judge primes digit) (setq res x)))))
  res
)

 コードは長いですが、実行時間は二桁早くなります。
 やっているのは、最初に回文数のリストを作って、大きい方から三桁同士の掛け算になるかどうかを判定するというもの。
 解説は、、、次回に。

 以上、如何でしょうか?

projecteuler13...または、newLISP v.10.4.8 の紹介

 今日の projecteuler は、いきなり13番目です。
 これには理由があります。問題13 は 50 桁の整数 100個の足し算なのです。newLISP の整数は 64ビットですから、せいぜい19桁が限度なので全然足りなのですが、朗報です。
 v.10.4.8 から整数の桁数に制限がなくなります。それでも、newLISP自体 300Kバイト未満って、Lutz氏凄すぎ。
 さて、正にこの問題にうってつけの v.10.4.8 を使って、解いてみましょう。
 まずは、50 桁の整数 100個を変数 data に入れます。

newLISP v.10.4.8 on Win32 IPv4/6 libffi, execute 'newlisp -h' for options.

>
(setq data (map eval-string (parse [text]
37107287533902102798797998220837590246510135740250
46376937677490009712648124896970078050417018260538
74324986199524741059474233309513058123726617309629
91942213363574161572522430563301811072406154908250
23067588207539346171171980310421047513778063246676
89261670696623633820136378418383684178734361726757
28112879812849979408065481931592621691275889832738
44274228917432520321923589422876796487670272189318
47451445736001306439091167216856844588711603153276
70386486105843025439939619828917593665686757934951
62176457141856560629502157223196586755079324193331
64906352462741904929101432445813822663347944758178
92575867718337217661963751590579239728245598838407
58203565325359399008402633568948830189458628227828
80181199384826282014278194139940567587151170094390
35398664372827112653829987240784473053190104293586
86515506006295864861532075273371959191420517255829
71693888707715466499115593487603532921714970056938
54370070576826684624621495650076471787294438377604
53282654108756828443191190634694037855217779295145
36123272525000296071075082563815656710885258350721
45876576172410976447339110607218265236877223636045
17423706905851860660448207621209813287860733969412
81142660418086830619328460811191061556940512689692
51934325451728388641918047049293215058642563049483
62467221648435076201727918039944693004732956340691
15732444386908125794514089057706229429197107928209
55037687525678773091862540744969844508330393682126
18336384825330154686196124348767681297534375946515
80386287592878490201521685554828717201219257766954
78182833757993103614740356856449095527097864797581
16726320100436897842553539920931837441497806860984
48403098129077791799088218795327364475675590848030
87086987551392711854517078544161852424320693150332
59959406895756536782107074926966537676326235447210
69793950679652694742597709739166693763042633987085
41052684708299085211399427365734116182760315001271
65378607361501080857009149939512557028198746004375
35829035317434717326932123578154982629742552737307
94953759765105305946966067683156574377167401875275
88902802571733229619176668713819931811048770190271
25267680276078003013678680992525463401061632866526
36270218540497705585629946580636237993140746255962
24074486908231174977792365466257246923322810917141
91430288197103288597806669760892938638285025333403
34413065578016127815921815005561868836468420090470
23053081172816430487623791969842487255036638784583
11487696932154902810424020138335124462181441773470
63783299490636259666498587618221225225512486764533
67720186971698544312419572409913959008952310058822
95548255300263520781532296796249481641953868218774
76085327132285723110424803456124867697064507995236
37774242535411291684276865538926205024910326572967
23701913275725675285653248258265463092207058596522
29798860272258331913126375147341994889534765745501
18495701454879288984856827726077713721403798879715
38298203783031473527721580348144513491373226651381
34829543829199918180278916522431027392251122869539
40957953066405232632538044100059654939159879593635
29746152185502371307642255121183693803580388584903
41698116222072977186158236678424689157993532961922
62467957194401269043877107275048102390895523597457
23189706772547915061505504953922979530901129967519
86188088225875314529584099251203829009407770775672
11306739708304724483816533873502340845647058077308
82959174767140363198008187129011875491310547126581
97623331044818386269515456334926366572897563400500
42846280183517070527831839425882145521227251250327
55121603546981200581762165212827652751691296897789
32238195734329339946437501907836945765883352399886
75506164965184775180738168837861091527357929701337
62177842752192623401942399639168044983993173312731
32924185707147349566916674687634660915035914677504
99518671430235219628894890102423325116913619626622
73267460800591547471830798392868535206946944540724
76841822524674417161514036427982273348055556214818
97142617910342598647204516893989422179826088076852
87783646182799346313767754307809363333018982642090
10848802521674670883215120185883543223812876952786
71329612474782464538636993009049310363619763878039
62184073572399794223406235393808339651327408011116
66627891981488087797941876876144230030984490851411
60661826293682836764744779239180335110989069790714
85786944089552990653640447425576083659976645795096
66024396409905389607120198219976047599490197230297
64913982680032973156037120041377903785566085089252
16730939319872750275468906903707539413042652315011
94809377245048795150954100921645863754710598436791
78639167021187492431995700641917969777599028300699
15368713711936614952811305876380278410754449733078
40789923115535562561142322423255033685442488917353
44889911501440648020369068063960672322193204149535
41503128880339536053299340368006977710650566631954
81234880673210146739058568557934581403627822703280
82616570773948327592232845941706525094512325230608
22918802058777319719839450180888072429661980811197
77158542502016545090413245809786882778948721859617
72107838435069186155435662884062257473692284509516
20849603980134001723930671666823555245252804609722
53503534226472524250874054075591789781264330331690[/text])))

(37107287533902102798797998220837590246510135740250L 463769376774900097126481248
96970078050417018260538L
 74324986199524741059474233309513058123726617309629L 919422133635741615725224305
63301811072406154908250L
 23067588207539346171171980310421047513778063246676L 892616706966236338201363784
18383684178734361726757L
 28112879812849979408065481931592621691275889832738L 442742289174325203219235894
22876796487670272189318L
 47451445736001306439091167216856844588711603153276L 703864861058430254399396198
28917593665686757934951L
 62176457141856560629502157223196586755079324193331L 649063524627419049291014324
45813822663347944758178L
 92575867718337217661963751590579239728245598838407L 582035653253593990084026335
68948830189458628227828L
 80181199384826282014278194139940567587151170094390L 353986643728271126538299872
40784473053190104293586L
 86515506006295864861532075273371959191420517255829L 716938887077154664991155934
87603532921714970056938L
 54370070576826684624621495650076471787294438377604L 532826541087568284431911906
34694037855217779295145L
 36123272525000296071075082563815656710885258350721L 458765761724109764473391106
07218265236877223636045L
 17423706905851860660448207621209813287860733969412L 811426604180868306193284608
11191061556940512689692L
 51934325451728388641918047049293215058642563049483L 624672216484350762017279180
39944693004732956340691L
 15732444386908125794514089057706229429197107928209L 550376875256787730918625407
44969844508330393682126L
 18336384825330154686196124348767681297534375946515L 803862875928784902015216855
54828717201219257766954L
 78182833757993103614740356856449095527097864797581L 167263201004368978425535399
20931837441497806860984L
 48403098129077791799088218795327364475675590848030L 870869875513927118545170785
44161852424320693150332L
 59959406895756536782107074926966537676326235447210L 697939506796526947425977097
39166693763042633987085L
 41052684708299085211399427365734116182760315001271L 653786073615010808570091499
39512557028198746004375L
 35829035317434717326932123578154982629742552737307L 949537597651053059469660676
83156574377167401875275L
 88902802571733229619176668713819931811048770190271L 252676802760780030136786809
92525463401061632866526L
 36270218540497705585629946580636237993140746255962L 240744869082311749777923654
66257246923322810917141L
 91430288197103288597806669760892938638285025333403L 344130655780161278159218150
05561868836468420090470L
 23053081172816430487623791969842487255036638784583L 114876969321549028104240201
38335124462181441773470L
 63783299490636259666498587618221225225512486764533L 677201869716985443124195724
09913959008952310058822L
 95548255300263520781532296796249481641953868218774L 760853271322857231104248034
56124867697064507995236L
 37774242535411291684276865538926205024910326572967L 237019132757256752856532482
58265463092207058596522L
 29798860272258331913126375147341994889534765745501L 184957014548792889848568277
26077713721403798879715L
 38298203783031473527721580348144513491373226651381L 348295438291999181802789165
22431027392251122869539L
 40957953066405232632538044100059654939159879593635L 297461521855023713076422551
21183693803580388584903L
 41698116222072977186158236678424689157993532961922L 624679571944012690438771072
75048102390895523597457L
 23189706772547915061505504953922979530901129967519L 861880882258753145295840992
51203829009407770775672L
 11306739708304724483816533873502340845647058077308L 829591747671403631980081871
29011875491310547126581L
 97623331044818386269515456334926366572897563400500L 428462801835170705278318394
25882145521227251250327L
 55121603546981200581762165212827652751691296897789L 322381957343293399464375019
07836945765883352399886L
 75506164965184775180738168837861091527357929701337L 621778427521926234019423996
39168044983993173312731L
 32924185707147349566916674687634660915035914677504L 995186714302352196288948901
02423325116913619626622L
 73267460800591547471830798392868535206946944540724L 768418225246744171615140364
27982273348055556214818L
 97142617910342598647204516893989422179826088076852L 877836461827993463137677543
07809363333018982642090L
 10848802521674670883215120185883543223812876952786L 713296124747824645386369930
09049310363619763878039L
 62184073572399794223406235393808339651327408011116L 666278919814880877979418768
76144230030984490851411L
 60661826293682836764744779239180335110989069790714L 857869440895529906536404474
25576083659976645795096L
 66024396409905389607120198219976047599490197230297L 649139826800329731560371200
41377903785566085089252L
 16730939319872750275468906903707539413042652315011L 948093772450487951509541009
21645863754710598436791L
 78639167021187492431995700641917969777599028300699L 153687137119366149528113058
76380278410754449733078L
 40789923115535562561142322423255033685442488917353L 448899115014406480203690680
63960672322193204149535L
 41503128880339536053299340368006977710650566631954L 812348806732101467390585685
57934581403627822703280L
 82616570773948327592232845941706525094512325230608L 229188020587773197198394501
80888072429661980811197L
 77158542502016545090413245809786882778948721859617L 721078384350691861554356628
84062257473692284509516L
 20849603980134001723930671666823555245252804609722L 535035342264725242508740540
75591789781264330331690L)
> 

 長いのはご容赦ください。数値の末尾に L が付いているのは、桁数に制限のない大整数(big integers)です。
 組込関数 parse は、newLISP 内部解析ルールに従って、文字列を切り分けてくれる便利な関数です。切り分けのキーとなる文字を正規表現で指定することもできます。組込関数eval-stringは、万能関数evalと同じ動作を文字列に対して行ないます。これを使って、50桁の数値を大整数(big integers)にしています。
 あとは簡単、dataの和を取ります。

> (apply + data 2)
5537376230390876637302048746832985971773659831892672L
> 

 組込関数 apply 第三引数の 2 は畳み込み(reduce)用変数で、演算子 + が二変数で動作するよう設定します。というのも、大整数(big integers)同士の演算は二変数である必要があるからです。
 せっかく、52桁の答えを得たのに、問題13 が求めているのは、和の最初の 10 桁だけ。
 従って、解答は、

> (0 10 (string (apply + data 2)))
"5537376230"
> 

 となります。もったいない、、、(笑)

 以上、如何でしょうか?

P.S.
 こちらに、v.10.4.8 の日本語併記のマニュアル(newlisp_manual-10408.zip)があります。興味のある方はどうぞ。

newLISP マニュアル・アップデート v.10.4.5 rev 2013-04-07

 newLISP のマニュアルrev 2013-04-07 に変更されました。

 4/2、4/7と変更がありましたが、どちらもちょっとした修正。
 ここでアップデートの連絡をするまでもないのですが、新たに追加された次の例は紹介しておきたかったので、、、

(define (make-adder n)
     (letex (n n) (lambda (x) (+ x n)))

 仕様から考えれば当たり前なのですが、これを見るまで気づきませんでした(汗)。
 こういう気づかされる例が載っているのが、 newLISP のマニュアル、知ってるつもりの関数も目を通すと思いがけない発見があったりします。ぜひ、ご一読を(笑)。

 さて、newLISP マニュアル & リファレンス の日本語訳、現在のバージョンは v.10.4.5 です。

こちらから newlisp_manual-10405 をダウンロードして下さい。

 目次も含め日本語併記にしてあります。

 いつものように、間違いやおかしな点が有りましたら、こちらの blog までご一報下さい。

 以上、如何でしょうか?

projecteuler3...または、newLISP で素因数分解するには

 3回目の projecteuler は、newLISP には簡単な問題。
 というのも、問題3は 600851475143 を素因数分解して、最大の素数を求めるというもの。
 例題の 13195 を素因数分解すると 5, 7, 13, 29 が得られます。
 これを newLISP でやると、

> (factor 13195)
(5 7 13 29)
> 

 組込関数 factor は引数の整数を素因数分解するという、この問題のためにあるような関数!しかも、600851475143 は

> (bits 600851475143)
"1000101111100101100010011110101011000111"
> (length (bits 600851475143))
40
> 

 高々40ビット、64ビット整数の newLISP の敵ではありません(笑)。関数 bits も newLISP 組込で、引数の整数を二進数の文字列に変換してくれる便利な関数です。
 従って、問題3の解答は、

> (factor 600851475143)
(71 839 1471 6857)
> ((factor 600851475143) -1)
6857
> 

 となります。

 以上、如何でしょうか?