tag:blogger.com,1999:blog-300497552009-06-18T01:11:05.402+09:00Functional Programming MemoPersonal memorandum for studying functional language, but other topics might be included. Written in Japanese (Shift-JIS Encoding).Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.comBlogger82125tag:blogger.com,1999:blog-30049755.post-31276507007753778782009-05-31T22:54:00.003+09:002009-06-01T00:31:05.558+09:00[Scala] S-99: Ninety-Nine Scala Problems (P01-28)<a href="http://aperiodic.net/phil/scala/s-99/">S-99: Ninety-Nine Scala Problems</a>のList編(P01-P28)の抄訳です。<br /><ul><br /><li>アスタリスクの数は難易度です。</li><br /><li>効率も大事ですが、エレガントな回答を求めます。可能ならばより簡潔で、計算量が少なく、末尾再帰になっている回答を作りましょう。</li><br /><li>Scalaの組み込み関数を使ってもOKです。が、使わないほうが勉強になります。</li><br /><li>答えが知りたければ、元の英語文書の各問題のリンクをクリックして下さい。</li><br /></ul><br /><br />P01 (*) リストの最後の要素を求めよ。<br /><code><br />scala&gt; last(List(1, 1, 2, 3, 5, 8))<br />res0: Int = 8<br /></code><br /><br />P02 (*) リストの最後から二番目の要素を求めよ。<br /><code><br />scala&gt; penultimate(List(1, 1, 2, 3, 5, 8))<br />res0: Int = 5<br /></code><br /><br />P03 (*) リストのn番目の要素を求めよ。但しリストの最初の要素は0番目とする。<br /><code><br />scala&gt; nth(2, List(1, 1, 2, 3, 5, 8))<br />res0: Int = 2<br /></code><br /><br />P04 (*) リストの要素の数を求めよ。<br /><code><br />scala&gt; length(List(1, 1, 2, 3, 5, 8))<br />res0: Int = 6<br /></code><br /><br />P05 (*) リストを逆順にせよ。<br /><code><br />scala&gt; reverse(List(1, 1, 2, 3, 5, 8))<br />res0: List[Int] = List(8, 5, 3, 2, 1, 1)<br /></code><br /><br />P06 (*) リストが回文になっているか調べよ。<br /><code><br />scala&gt; isPalindrome(List(1, 2, 3, 2, 1))<br />res0: Boolean = true<br /></code><br /><br />P07 (**) ネストされたリスト構造を平坦化せよ。<br /><code><br />scala&gt; flatten(List(List(1, 1), 2, List(3, List(5, 8))))<br />res0: List[Any] = List(1, 1, 2, 3, 5, 8)<br /></code><br /><br />P08 (**) リスト要素の連続した重複物を除去せよ。もしリストの要素で繰り返し要素が含まれていたならば要素一つに置き換えよ。要素の順序は変えてはならない。<br /><code><br />scala&gt; compress(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))<br />res0: List[Symbol] = List('a, 'b, 'c, 'a, 'd, 'e)<br /></code><br /><br />P09 (**) 連続した重複物を子リストに纏めよ。もしリストの要素が繰り返し要素ならば、別々の子リストに分割せよ。<br /><code><br />scala&gt; pack(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))<br />res0: List[List[Symbol]] = List(List('a, 'a, 'a, 'a), List('b), List('c, 'c), List('a, 'a), List('d), List('e, 'e, 'e, 'e))<br /></code><br /><br />P10 (*) リストをランレングス・エンコードせよ。P09の結果を用いていわゆるランレングス・エンコーディングによるデータ圧縮法を実装せよ。連続した重複要素はタプル(N,E)にエンコードされる。但しNは要素Eの重複数。<br /><code><br />scala&gt; encode(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))<br />res0: List[(Int, Symbol)] = List((4,'a), (1,'b), (2,'c), (2,'a), (1,'d), (4,'e))<br /></code><br /><br />P11 (*) 修正ランレングス・エンコーディング。P10の結果を修正し、もし要素に重複が無ければ単に要素を結果にコピーせよ。重複している要素だけを(N,E)の形に変換せよ。<br /><code><br />scala&gt; encodeModified(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))<br />res0: List[Any] = List((4,'a), 'b, (2,'c), (2,'a), 'd, (4,'e))<br /></code><br /><br />P12 (**) ランレングス・エンコードされたリストをデコードせよ。P10の仕様で生成されたランレングス・エンコードされたリストを元の圧縮されていないものに戻せ。<br /><code><br />scala&gt; decode(List((4, 'a), (1, 'b), (2, 'c), (2, 'a), (1, 'd), (4, 'e)))<br />res0: List[Symbol] = List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)<br /></code><br /><br />P13 (**) リストのランレングス・エンコーディング(直接解法)。いわゆるランレングス・エンコーディングを直接実装せよ。すなわち(P09のpackの様な)自分で書いた他のメソッドを使ってはならない。直接書く事。<br /><code><br />scala&gt; encodeDirect(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))<br />res0: List[(Int, Symbol)] = List((4,'a), (1,'b), (2,'c), (2,'a), (1,'d), (4,'e))<br /></code><br /><br />P14 (*) リスト要素を重複させよ。<br /><code><br />scala&gt duplicate(List('a, 'b, 'c, 'c, 'd))<br />res0: List[Symbol] = List('a, 'a, 'b, 'b, 'c, 'c, 'c, 'c, 'd, 'd)<br /></code><br /><br />P15 (**) 指定した個数、リスト要素を重複させよ。<br /><code><br />scala&gt; duplicateN(3, List('a, 'b, 'c, 'c, 'd))<br />res0: List[Symbol] = List('a, 'a, 'a, 'b, 'b, 'b, 'c, 'c, 'c, 'c, 'c, 'c, 'd, 'd, 'd)<br /></code><br /><br />P16 (**) 毎N番目の要素を除去せよ。<br /><code><br />scala&gt; drop(3, List('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k))<br />res0: List[Symbol] = List('a, 'b, 'd, 'e, 'g, 'h, 'j, 'k)<br /></code><br /><br />P17 (*) リストを二つに分割せよ。前半の長さは与えられるものとする。結果はタプルで返す。<br /><code><br />scala&gt; split(3, List('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k))<br />res0: (List[Symbol], List[Symbol]) = (List('a, 'b, 'c),List('d, 'e, 'f, 'g, 'h, 'i, 'j, 'k))<br /></code><br /><br />P18 (**) リストのスライスを抽出せよ。二つの添字 i と j が与えられたとき、スライスとは元のリストの i 番目の要素を含むが j 番目の要素を含まないリストである。要素は0番目から始まるとする。<br /><code><br />scala&gt; slice(3, 7, List('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k))<br />res0: List[Symbol] = List('d, 'e, 'f, 'g)<br /></code><br /><br />P19 (**) リストの要素をn個左ローテートせよ。<br /><code><br />scala&gt; rotate(3, List('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k))<br />res0: List[Symbol] = List('d, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'a, 'b, 'c)<br /><br />scala&gt; rotate(-2, List('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k))<br />res1: List[Symbol] = List('j, 'k, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i)<br /></code><br /><br />P20 (*) リストのk番目の要素を除去せよ。除去されたリストと除去した要素をタプルで返せ。要素は0番目から始まるとする。<br /><code><br />scala&gt; removeAt(1, List('a, 'b, 'c, 'd))<br />res0: (List[Symbol], Symbol) = (List('a, 'c, 'd),'b)<br /></code><br /><br />P21 (*) リストの指定された場所に要素を追加せよ。<br /><code><br />scala&gt; insertAt('new, 1, List('a, 'b, 'c, 'd))<br />res0: List[Symbol] = List('a, 'new, 'b, 'c, 'd)<br /></code><br /><br />P22 (*) 与えられた範囲の整数のリストを作れ。<br /><code><br />scala&gt; range(4, 9)<br />res0: List[Int] = List(4, 5, 6, 7, 8, 9)<br /></code><br /><br />P23 (**) リストから指定された数だけ値をランダムに選択せよ。(ヒント:P20を使え)<br /><code><br />scala&gt; randomSelect(3, List('a, 'b, 'c, 'd, 'f, 'g, 'h))<br />res0: List[Symbol] = List('e, 'd, 'a)<br /></code><br /><br />P24 (*) ロト:1〜Mからn個の異なるランダムな値を選べ。<br /><code><br />scala&gt; lotto(6, 49)<br />res0: List[Int] = List(23, 1, 17, 33, 21, 37)<br /></code><br /><br />P25 (*) 要素のランダムな順列を作成せよ。(ヒント:P23を使え)<br /><code><br />scala&gt; randomPermute(List('a, 'b, 'c, 'd, 'e, 'f))<br />res0: List[Symbol] = List('b, 'a, 'd, 'c, 'e, 'f)<br /></code><br /><br />P26 (**) n要素数のリストからk個の異なるオブジェクトを取り出す組み合わせを生成せよ。12人から3人の委員会を作る方法は何通りだろうか?答えは C(12,3)=220通り(C(n,k)はよく知られた二項係数)である。数学者にとってはこれで十分であるが、我々は本当に全ての解を生成したい。<br /><code><br />scala&gt; combinations(3, List('a, 'b, 'c, 'd, 'e, 'f))<br />res0: List[List[Symbol]] = List(List('a, 'b, 'c), List('a, 'b, 'd), List('a, 'b, 'e), ...<br /></code><br /><br />P27 (**) 集合の要素を、互いに素な部分集合に纏めよ。<br />a) 9人の人をそれぞれ2,3,4人の3グループに纏める方法は何通りか?全ての組み合わせを生成する関数を書け。<br /><code><br />scala&gt; group3(List("Aldo", "Beat", "Carla", "David", "Evi", "Flip", "Gary", "Hugo", "Ida"))<br />res0: List[List[List[String]]] = List(List(List(Aldo, Beat), List(Carla, David, Evi), List(Flip, Gary, Hugo, Ida)), ...<br /></code><br />b) 上の問題を一般化してグループの大きさのリストを与えるとグループのリストを与える様にせよ。グループメンバーの順列は求めていない、すなわち((Aldo,Beat),...)は((Beat,Aldo),...)と同じ解である。しかし、((Aldo,Beat),(Carla,David),...)は((Carla,David),(Aldo,Beat),...)と異なる解である。<br /><code><br />scala&gt; group(List(2, 2, 5), List("Aldo", "Beat", "Carla", "David", "Evi", "Flip", "Gary", "Hugo", "Ida"))<br />res0: List[List[List[String]]] = List(List(List(Aldo, Beat), List(Carla, David), List(Evi, Flip, Gary, Hugo, Ida)), ...<br /></code><br />この組み合わせ問題に関して知りたければ離散数学の良い本で「多項係数」について調べよ。<br />P28 (**) リストのリストを長さでソートせよ。<br />a) 要素がリストであるリストを考える。そのリストの要素を長さでソートする、すなわち短いリストを前に、長いリストを後にする。<br /><code><br />scala&gt; lsort(List(List('a, 'b, 'c), List('d, 'e), List('f, 'g, 'h), List('d, 'e), List('i, 'j, 'k, 'l), List('m, 'n), List('o)))<br />res0: List[List[Symbol]] = List(List('o), List('d, 'e), List('d, 'e), List('m, 'n), List('a, 'b, 'c), List('f, 'g, 'h), List('i, 'j, 'k, 'l))<br /></code><br />b) 次に同様にリストを長さでソートするが、今回は長さの頻度でソートする。すなわち稀な長さのものを前に、頻度の高い長さのものを後ろにする。例の場合、長さ4と1のリストはただ1度しか現れない。3番目と4番目は長さ3のリスト2つである。最後に3つの最も頻度の高い長さ2のリストが現れる。<br /><code><br />scala&gt; lsortFreq(List(List('a, 'b, 'c), List('d, 'e), List('f, 'g, 'h), List('d, 'e), List('i, 'j, 'k, 'l), List('m, 'n), List('o)))<br />res1: List[List[Symbol]] = List(List('i, 'j, 'k, 'l), List('o), List('a, 'b, 'c), List('f, 'g, 'h), List('d, 'e), List('d, 'e), List('m, 'n))<br /></code><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3127650700775377878?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-81809084455000827682009-05-22T01:01:00.003+09:002009-05-22T01:07:20.699+09:00[Scala] Sudoku in Scala<a href="http://d.hatena.ne.jp/HHa/20090422/1240354191">Scalaユーザ会5/22(金)19:00-21:00@新宿三井ビル3</a>で話をする予定の「Scalaで数独を解く」話です。<br /><br /><a href="http://homepage.mac.com/takashi_miyamoto/scala/ScalaSudoku.pdf">ScalaSudoku.pdf</a> : プレゼン資料<br /><a href="http://homepage.mac.com/takashi_miyamoto/scala/Sudoku.scala">Sudoku.scala</a> : ソースコード<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8180908445500082768?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-4717276442368685822009-05-20T00:00:00.005+09:002009-05-20T00:29:19.785+09:00[Joke] Translation of "A Brief, Incomplete, and Mostly Wrong History of Programming Languages"<a href="http://james-iry.blogspot.com/2009/05/brief-incomplete-and-mostly-wrong.html">A Brief, Incomplete, and Mostly Wrong History of Programming Languages</a>の翻訳です。面白かったので翻訳してみました。<br /><br /><b>「簡潔で不完全でほとんど間違っているプログラミング言語の歴史」</b><br /><br />1801 - Joseph Marie Jacquardが、織機にパンチカードで命令することで、タペストリーに「hello, world」を織り込んだ。(しかし)末尾再帰やコンカレンシーの欠如、あるいは適切に大文字が使用されていないため、当時のRedditerたちは感銘を覚え無かった。<br /><br />1842 - Ada Lovelaceが最初のプログラムを書いた。その過程に於いて、コードを走らせる実際のコンピュータを持っていないという些細な困難に妨げられた。後のエンタープライズアーキテクトたちは、UMLでプログラムする為に、彼女のテクニックを再習得した。<br /><br />1936 - Alan Turingが、(将来に亘る)全てのプログラミング言語を発明した。しかし彼がその特許をとる前に、英国情報部は彼を007にするために強制徴募した。<br /><br />1936 - Alonzo Churchもまた、(将来に亘る)全てのプログラミング言語をさらにうまく発明した。彼のλ算法はC言語に十分似ていない為に無視された。この批判は、当時まだCが発明されていないという事実にも関わらず生じた。<br /><br />1940年代 - 結線とスイッチによって様々な「コンピュータ」が「プログラム」された。「タブ vs 空白」の論戦を避けるために、技術者たちはこの方式を採用した。<br /><br />1957 - John BackusとIBMがFORTRANを作った。IBMにもFORTRANにも面白いところは何も無い。青いネクタイを着用せずFORTRANを書くのは文法エラーである。<br /><br />1958 - John McCarthyとPaul GrahamがLISPを発明する。戦後の戦略的括弧備蓄の枯渇による高コストの為、LISPは決してポピュラーにはならなかった[1]。ポピュラーでは無いにも関わらず、LISP (今では "Lisp" あるいは時には "Arc") は「再帰と他人を見下すことなどの重要なアルゴリズム技法」に於ける影響度の高い言語であり続けている。<br /><br />1959 - L. Ron Hubbardとの賭けに負けた後に、Grace Hopperを含む何人かのサディスト達が「大文字化された定型文志向言語」 (Capitalization Of Boilerplate Oriented Language = COBOL) を発明する。後に、Hooper提督のCOBOLの業績に対する見当外れで性差別的な報復として、Rubyコンファレンスでは嫌女性的題材が取り上げられる。<br /><br />1964 - John KemenyとThomas Kurtzが、非計算機科学者の為の非構造化プログラミング言語であるBASICを作った。<br /><br />1965 - KemenyとKurtzはGO TO 1964.<br /><br />1970 - Guy SteeleとGerald SussmanがSchemeを作った。彼らの著作は「Lambda the Ultimate」の一連の論文をもたらし、「究極の台所用品ラムダ」にその頂点を迎えた。この論文はロングランの基礎となったが、深夜のインフォマーシャルとしては究極的に失敗であった。Javaがラムダを持たないことによってラムダをポピュラーにするまでラムダは比較的目立たないところへと左遷された。<br /><br />1970 - Niklaus Wirthが手続き型言語のPascalを作った。Pascalは直ちに批難されたが、"x := x + y"という構文を、より親しみやすいC的な"x = x + y"の代わりに使用したためであった。この批判は、当時まだCが発明されていないという事実にも関わらず生じた。<br /><br />1972 - Dennis Ritchieは前後を同時に撃つことの出来る強力な銃を発明した。発明のもたらした多くの死者及び障害者に満足することなく、彼はCとUnixを発明した。<br /><br />1972 - Alain Colmerauerは論理型言語Prologをデザインした。彼の目標は二歳児の知性を持った言語を作ることであった。全てのクエリに「No」と答えるPrologセッションを示すことによって、目標に達したことを証明した。<br /><br />1973 - Robin MilnerはM&M型理論に基づく言語のMLを作った。MLの子供として形式仕様意味論を持つSMLが生まれた。形式意味論の形式意味論を質問されてMilnerの頭は爆発した。ML一家の他の良く知られた言語にはOCaml, F#, Visual Basicがある。<br /><br />1980 - Alan kayはSmalltalkを作り、用語「オブジェクト指向」を発明した。その意味を聞かれると彼は「Smalltalkのプログラムは単にオブジェクトである」と答えた。オブジェクトは何から作られるのかを聞かれると彼は「オブジェクトだ」と答えた。再度質問されると彼は云った。「だからさ、下の下まで全部オブジェクトなんだってば。亀にたどり着くまでは。」<br /><br />1983 - Bjarne Stroustrupは耳にしたもの全てをCにねじ止めすることでC++を作った。その結果、言語は非常に複雑になり、プログラムをSkynet人工知能でコンパイルするために未来へ送らねばならなかった。ビルド時間は犠牲となった。Skynetがサービスを提供し続けた動機は依然としてはっきりしないが、未来からの広報担当はオーストリア訛りで単調に「気にするようなことは何も無い、ベイビー」と云った。Skynetはバッファーオーバーランを飾り立てたものに過ぎないという推測もある。<br /><br />1986 - Brad CoxとTom LoveがObjective-Cを作り、アナウンスした。「この言語はCのメモリ安全性とSmalltalkの素晴らしい実行速度が結びついたものです。」現代の歴史家たちは二人が失読症であったと疑っている。<br /><br />1987 - Larry Wallが眠気を催し、キーボードに額をぶつけた。目を覚ましたとき、Larry Wallのモニターの上の文字列はランダムなのではなく、神が預言者Larry Wallにデザインすることを欲しているプログラミング言語のサンプルプログラムだと悟った。Perlが生まれた。<br /><br />1990 - Simon Peyton-Jones, Paul Hudak, Philip Wadler, Ashton Kutcher そして「動物の倫理的扱いを求める人々の会」からなる委員会は、純粋非正格関数型言語Haskell を作った。副作用を制御するためモナドを使用する複雑さの為、Haskellは抵抗を受けた。Wadler は批判を和らげるために説明した。「モナドは自己準同系ファンクタの圏のモノイドなんだ。何か問題が?」<br /><br />1991 - オランダ人プログラマのGuido van Rossumが謎の手術の為にアルゼンチンへと旅行した。頭部に大きな傷を負って帰国し、Pythonを発明し、多数の賛同者によって終身独裁者に任じられ、世界に対して「あることをするのにひとつしかやり方がない」と報じた。ポーランドは神経質になっている。<br /><br />1995 - 「Mad Matz」こと、まつもとゆきひろは、漠然とした特定されない終末を避けるためにRubyを作ったが、その終末においてはオーストラリアはモヒカン戦士とティナ=ターナーが支配する砂漠となる。その言語は後にRuby on Railsと、真の発明者David Heinemeier Hanssonによって改名された。[まつもとがRubyと呼ばれる言語を発明した云々は実際には起きておらず、この記事の次の改訂時に削除されるべきだ - DHH].<br /><br />1995 - Brendan Eichはプログラミング言語設計で起きた全ての失敗について読み、自分でも幾つか発明し、LiveScriptを作成した。後にその言語は、Javaの人気に肖る為、JavaScriptと改名された。後になっても、皮膚病の人気に肖る為にECMAScriptと改名された。<br /><br />1996 - James GoslingはJavaを発明した。Javaは比較的冗長で、ガベージコレクションをし、クラスベースで、静的型付けで、シングルディスパッチで、単一実装継承と複数インタフェース継承のオブジェクト指向な言語である。SunはJavaの新規性を宣伝した。<br /><br />2001 - Anders HejlsbergがC#を発明した。C#は比較的冗長で、ガベージコレクションをし、クラスベースで、静的型付けで、シングルディスパッチで、単一実装継承と複数インタフェース継承のオブジェクト指向の言語である。MicrosoftはC#の新規性を宣伝した。<br /><br />2003 - 酔っ払ったMartin Oderskyは誰かのピーナツバターが別の人のチョコレートにくっつくというReeseのピーナツバターカップのCMを見て着想を得た。彼はオブジェクト指向と関数型言語の作り上げたものを統合する言語Scalaを作った。これを見た両派閥とも激怒し、それぞれ直ちに聖戦を宣告した。<br /><br />Footnotes<br /><br />1. 計算機科学にとっては幸運なことに、中括弧と山括弧の供給は潤沢であった。<br />2. <a href="http://www.theregister.co.uk/2006/01/11/exception_handling/">Catch as catch can - Verity Stob</a><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-471727644236868582?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-22176120967689296952009-05-03T22:33:00.003+09:002009-05-03T23:07:22.330+09:00[Scala] Jersey with Scala + JettyJersey は JAX-RS (Java API for RESTful Web Service)のreference実装です。<br />これをScalaで動かしてみます。<br /><br />1. Libraries : Jetty 6.1.17. Jersey 1.0.3 を使用しました。下記をEclipseプロジェクトのreference librariesに登録<br /><br />Jetty : jetty-XX.jar, jetty-util-XX.jar, servlet-api-XX.jar<br />Jersey : jsr311-api-XX.jar, jersey-core-XX.jar, jersey-server-XX.jar, asm-XX.jar<br /><br />2. test.jersey.JerseyTest.scala : メインルーチンです<br /><pre><br />package test.jersey<br /><br />import javax.servlet.ServletException<br />import javax.servlet.http.HttpServlet<br />import javax.servlet.http.HttpServletRequest<br />import javax.servlet.http.HttpServletResponse<br /><br />import org.mortbay.jetty.Server<br />import org.mortbay.jetty.nio.SelectChannelConnector<br />import org.mortbay.jetty.servlet.Context<br />import org.mortbay.jetty.servlet.ServletHolder<br /><br />import com.sun.jersey.spi.container.servlet.ServletContainer<br /> <br />object JerseyTest {<br /> def main(args: Array[String]) {<br /> val server = new Server(8080)<br /> val connector = new SelectChannelConnector()<br /> server.addConnector(connector)<br /> <br /> val holder:ServletHolder = new ServletHolder(classOf[ServletContainer])<br /> holder.setInitParameter(<br /> "com.sun.jersey.config.property.resourceConfigClass",<br /> "com.sun.jersey.api.core.PackagesResourceConfig")<br /> holder.setInitParameter(<br /> "com.sun.jersey.config.property.packages",<br /> "test.jersey.resource")<br />// URLをクラスにマッピングする為のpackage名<br /><br /> val context = new Context(server, "/", Context.SESSIONS)<br /> context.addServlet(holder, "/*")<br /> <br /> server.start()<br /> server.join()<br /> }<br />}<br /></pre><br /><br />3. test.jersey.resource : /helloworld に対応するリソース<br /><pre><br />package test.jersey.resource<br /><br />import javax.ws.rs.GET<br />import javax.ws.rs.Produces<br />import javax.ws.rs.Path<br /><br />@Path("/helloworld")<br />class HelloWorldResource {<br /> @GET<br /> @Produces(Array("text/plain"))<br /> def getMessage:String = "Hello, World"<br />}<br /></pre><br /><br />4. テスト<br />Eclipseでtest.jersey.JerseyTest をアプリケーションとして実行させます。<br /><pre><br />2009-05-03 22:56:18.064::INFO: Logging to STDERR via org.mortbay.log.StdErrLog<br />2009-05-03 22:56:18.123::INFO: jetty-6.1.17<br />2009-05-03 22:56:18.205::INFO: Started SocketConnector@0.0.0.0:8080<br />2009-05-03 22:56:18.226::INFO: Started SelectChannelConnector@0.0.0.0:55736<br /></pre><br />次いでアクセス<br /><pre><br />% telnet localhost 8080<br />Trying 127.0.0.1...<br />Connected to localhost.<br />Escape character is '^]'.<br />GET /helloworld HTTP/1.0<br /><br />HTTP/1.1 200 OK<br />Content-Type: text/plain<br />Server: Jetty(6.1.17)<br /><br />Hello, WorldConnection closed by foreign host.<br />% <br /></pre><br /><br /><pre><br />2009/05/03 22:57:08 com.sun.jersey.api.core.PackagesResourceConfig init<br />情報: Scanning for root resource and provider classes in the packages:<br /> test.jersey.resource<br />2009/05/03 22:57:08 com.sun.jersey.api.core.PackagesResourceConfig init<br />情報: Root resource classes found:<br /> class test.jersey.resource.HelloWorldResource<br />2009/05/03 22:57:08 com.sun.jersey.api.core.PackagesResourceConfig init<br />情報: Provider classes found:<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2217612096768929695?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-72911498216813539652009-05-03T02:21:00.003+09:002009-05-03T02:38:14.455+09:00[Scala] Scala Servlet with Jetty6Jetty + ScalaでServletを書いてみました。<br /><br />1. Projectの作成<br />Eclipseで普通にScala Projectを作ります。<br />ScalaServletという名前のScala Projectを作りました。<br /><br />2. Jetty6 の入手<br />JettyのサイトからJetty6を入手します。私がダウンロードしたのはJetty 6.1.17でした。<br />zipを解凍し、jetty-6.1.17.jar, jetty-util-6.1.17.jar, servlet-api-2.5-20081211.jar をプロジェクトにimportします。<br /><br />3. ソースを書く<br />パッケージtest.jettyを作って、下記の様なJettyTest.scalaというファイルを作成します<br /><pre><br />package test.jetty<br /><br />import javax.servlet.ServletException<br />import javax.servlet.http.HttpServlet<br />import javax.servlet.http.HttpServletRequest<br />import javax.servlet.http.HttpServletResponse<br /><br />import org.mortbay.jetty.Server<br />import org.mortbay.jetty.nio.SelectChannelConnector<br />import org.mortbay.jetty.servlet.ServletHandler<br /><br />object JettyTest {<br /><br /> def main(args: Array[String]) {<br /> val server = new Server(8080)<br /> val connector = new SelectChannelConnector()<br /> server.addConnector(connector)<br /> <br /> val handler = new ServletHandler()<br /> handler.addServletWithMapping(HelloServlet.getClass, "/")<br /> server.addHandler(handler)<br /> <br /> server.start()<br /> server.join()<br /> }<br />}<br /><br />object HelloServlet extends HttpServlet {<br /> override def doGet(req:HttpServletRequest, resp:HttpServletResponse) {<br /> val out = resp.getWriter<br /> resp.setContentType("text/html")<br /> out.println("&lt;html&gt;&lt;body&gt;Hello, World!&lt;/body&gt;&lt;/html&gt;")<br /> }<br />}<br /></pre><br /><br />4.サーバ起動<br />上記のJettyTest.scalaを普通にScala Applicationとして起動します。<br />コンソールに下記の様に表示されます。<br /><pre><br />2009-05-03 02:20:29.316::INFO: Logging to STDERR via org.mortbay.log.StdErrLog<br />2009-05-03 02:20:29.358::INFO: jetty-6.1.17<br />2009-05-03 02:20:29.392::INFO: Started SocketConnector@0.0.0.0:8080<br />2009-05-03 02:20:29.413::INFO: Started SelectChannelConnector@0.0.0.0:52134<br /></pre><br /><br />5.アクセス<br />ブラウザからhttp://localhost:8080/で確認してもOKですがコンソールから確認。<br /><pre><br />% telnet localhost 8080<br />Trying ::1...<br />telnet: connect to address ::1: Connection refused<br />Trying fe80::1...<br />telnet: connect to address fe80::1: Connection refused<br />Trying 127.0.0.1...<br />Connected to localhost.<br />Escape character is '^]'.<br />GET / HTTP/1.0<br /><br />HTTP/1.1 200 OK<br />Content-Type: text/html; charset=iso-8859-1<br />Content-Length: 40<br />Server: Jetty(6.1.17)<br /><br />&lt;html&gt;&lt;body&gt;Hello, World!&lt;/body&gt;&lt;/html&gt;<br />Connection closed by foreign host.<br />% <br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-7291149821681353965?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-86333997133759228602009-04-18T22:28:00.004+09:002009-04-18T23:05:22.353+09:00[Event] Type-Level Programming Meeting<a href="http://atnd.org/events/451">型レベルプログラミングの会</a><br /><br />定員がすぐいっぱいになってしまって会場参加は出来ず、自宅からustreamで拝聴。<br />発表された皆さん、どれも興味深い話でした。ありがとうございます。<br /><br /><ul><br /><li>Scala : Scalaの型プログラミングの話は前にも聞かせて頂いたような気がするけど、更に話題が広がっていたような。</li><br /><li>C++ : 定番ではありながら、私はC++は経験が少ないので興味深く聞けました。</li><br /><li>Haskell : フォロー出来ない話も多かったですが勉強になりました。勉強すべき事、多いなぁ。</li><br /><li>D : 型プログラミングの為のような言語ですね。興味深い。</li><br /><li>依存型プログラミング : プレゼン資料が大変面白いというか芸達者というか。April Foolの予告のGirardの逆理の話では無かった。</li><br /><li>G'Caml : 存在を始めて知りました。OCaml関係も色々あるなぁ。</li><br /></ul><br /><br />この手の勉強会に参加すると、今まで知らなかったことがいっぱいあると判り、もっと勉強しなくちゃ、と思う。<br />日々の仕事は非技術的な作業ばかりが増えているので、知的好奇心の刺激の為にもこの手の勉強会に積極的に参加しないと。<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8633399713375922860?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-30642886767575736332009-04-05T19:00:00.001+09:002009-04-05T19:06:41.567+09:00[Coq] Coq'Art Chap.2Interactive Theorem Proving and Program Development; Coq'Art: The Calculus of Inductive Constructions の Chapter 2 です。<br /><br />この章では概ね次の4つが語られているように見えます。<br /><br />(1) Coq のコマンド<br /><br />下記の様なコマンドがあります。<br /><br />★<code>Require Import</code> <i>library</i><code>.</code><br />ライブラリをロードして environment に追加する。<br /><i>library</i>としては、<code>Arith, ZArith, Bool</code>などがある。<br /><br />★<code>Open Scope</code> <i>scope名</i><code>.</code><br />Scope は notation を interprete する規則。例えば<code>Z_scope</code>を指定すると各種演算子記号が Z の演算のものと判断される。<br /><br />★<code>Print Scope</code> <i>scope名</i><code>.</code><br />Scopeで定義された notation の一覧を得る。<br /><br />★<code>Check</code> <i>term</i><code>.</code><br /><i>term</i>のtypeを表示させる。<br /><br />★<code>Parameter</code> <i>t:A</i><code>.</code><br /><i>t:A</i>を environment に追加する。environmentはglobalなもの。<br /><br />★<code>Section</code> <i>id</i><code>.</code><br /><pre>  ...</pre><br /> <code>End</code> <i>id</i><code>.</code><br />localなblockを作る。<br /><br />★<code>Variable</code> <i>t:A</i><code>.</code><br /><i>t:A</i>を context に追加する。contextはlocal。なので、<code>Section...End</code>の範囲内で有効。<br /><br />(2) Inference Rules<br /><br />様々な推論規則があります。<br /><br /><pre><br /> (x,A)∈E∪Γ<br />Var ------------ x:identifier<br /> E,Γ |- x:A<br /><br /> E,Γ|- e_1:A->B E,Γ|- e_2:A<br />App ------------------------------ 関数適用<br /> E,Γ|- e_1 e_2:B<br /> <br /> E,Γ|- e:A_1 -> A_2 -> ... -> A_n -> B E,Γ|- e_i:A_i (i=1,...,n) <br />App* -------------------------------------------------------------------<br /> E,Γ|- e e_1 ... e_n:B<br /> <br /> E,Γ|- t_1:A E,Γ::(v:=t_1) |- t_2:B<br />Lam -------------------------------------- λ式<br /> E,Γ|- fun v:A => e:A->B<br /> <br /> E,Γ|- t_1:A E,Γ::(v:=t_1) |- t_2:B<br />Let-in -------------------------------------- let<br /> E,Γ|- let v:=t_1 in t_2:B<br /> <br /> E,Γ|- A:Set E,Γ|- B:Set<br />Prod-Set --------------------------<br /> E,Γ|- A->B:Set<br /><br /> E,Γ|- t:A E,Γ|- A ≦_{beta delta iota zeta} B<br />Conv --------------------------<br /> E,Γ|- t:B<br /></pre><br /><br />(3) Eval<br /><br />★cvb : call-by-value (cbvでなくlazyで遅延評価)<br /><br />★delta-reduction : t ==> t{v/t'}。tのidentifier vをその定義t'で置換。<br /><br />★beta-reduction : (fun v:T => e_1) e2 ==> e_1{v/e_2}。λ式を簡約。<br /><br />★zeta-reduction : let v := e_1 in e_2 ==> e_2{v/e_1}。letを簡約。<br /><br />★iota-reduction : 帰納的な処理で詳しくはChap.6でということで後回し。nat,Zは帰納的な定義なので計算する時はiota-reductionが必須。<br /><br />★compute = cvb iota beta zeta delta の略<br /><br />★<code>Eval compute in (....).</code> : <code>...</code>を実際に計算する。<br /><br />Reductionに関する性質<ul><br /><li>strong normalization : reductionはfinite<br /><li>confluence : t |> t_1, t |> t_2 ならば、あるt_3があって、t_1 |> t_3 かつ t_2 |> t_3。<br /></ul><br /><br />(4) Universe<br /><br />typeもtermだとすると、typeのtypeがあるはず。それをsortという。<br />CoqではSetというデフォルトのsortが定義されている。<br />更にその上の無限の階層まで考えるようだが、CoqではType(i)は全部ひっくるめてTypeにしてしまう様子。<br /><pre><br />Level 0 : 具体的な項とか関数。O, S, trinomial,...<br />Level 1 : データの型。nat, nat->nat, ...<br />Level 2 : ソート。Set<br />Level 3 : Type(0)<br /> :<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3064288676757573633?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-14126610590760470762009-03-29T21:48:00.002+09:002009-03-29T21:54:50.765+09:00[Coq] Coq'Art Reading in Tokyo ?ところで東京近辺でSpringerのCoq本<a href="http://www.labri.fr/perso/casteran/CoqArt/index.html">Interactive Theorem Proving and Program Development. Coq'Art: The Calculus of Inductive Constructions</a>に興味のある人っています?<br />何人かいるようならば読書会でもとか思うのですが。なお、私は素人で型理論の専門家とかではありません。なので他人に教える程の知識は無く、一緒に勉強する感じになってしまいますが。<br />逆に既に本を読んでいるとかで、私が参加しても構わないグループとかありましたら声をかけて下さい。<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-1412661059076047076?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-34044683896995696572009-03-29T21:08:00.004+09:002009-03-29T21:47:34.472+09:00[Coq] Coq'Art Chap.1<a href="http://www.labri.fr/perso/casteran/CoqArt/index.html">Interactive Theorem Proving and Program Development; Coq'Art: The Calculus of Inductive Constructions</a>を読み始める事にしました。<br /><br />Chap.1ではinsertion sortを例にしてCoqの解説が行われています。そこで、Appendixのinsertion sortのコードをCoqIdeに入力してみました。実際に証明が自分で出来る様になるのは将来の課題として、とりあえずCoqでの開発の流れを追ってみます。<br />なお証明自体は<a href="http://www.labri.fr/perso/casteran/CoqArt/horizon/SRC/insertionv8.v">insertionv8.v</a>にあります。<br /><br />まず、list Zがソートされた状態を定義する<code>sorted : list Z -> Prop</code>を定義します。こんな感じです。<br /><pre><br />Inductive sorted : list Z -> Prop :=<br /> | sorted0 : sorted nil<br /> | sorted1 : forall z:Z, sorted (z :: nil)<br /> | sorted2 : forall (z1 z2:Z) (l:list Z), <br /> z1 <= z2 -> sorted (z2 :: l) -> sorted (z1 :: z2 :: l).<br /></pre><code>sorted</code>は定義なのでこれ自体は証明の対象ではありません。<br /><br />これを用いて、<pre><br />Theorem sorted_inv : <br /> forall (z:Z) (l:list Z), sorted (z :: l) -> sorted l.<br /></pre>を証明します。<br /><br />次いで、並べ替えであることを示す<code>equiv</code>を定義します。まず、リストのなかの出現数を示す<pre><br />Fixpoint nb_occ (z:Z) (l:list Z) {struct l} : nat :=<br /> match l with<br /> | nil => 0%nat<br /> | (z' :: l') =><br /> match Z_eq_dec z z' with<br /> | left _ => S (nb_occ z l')<br /> | right _ => nb_occ z l'<br /> end<br /> end.<br /></pre>を定義します。この<code>nb_occ</code>は定義なので証明しません。<br /><br />これを使って、<pre><br />Definition equiv (l l':list Z) := forall z:Z, nb_occ z l = nb_occ z l'<br /></pre>を定義します。これ自体も証明しません。<br /><br /><code>nb_occ, equiv</code>の定義から、下記の補題を証明します。<pre><br />Lemma equiv_refl : <br /> forall l:list Z, equiv l l.<br />Lemma equiv_sym : <br /> forall l l':list Z, equiv l l' -> equiv l' l.<br />Lemma equiv_trans : <br /> forall l l' l'':list Z, equiv l l' -> equiv l' l'' -> equiv l l''.<br />Lemma equiv_cons : <br /> forall (z:Z) (l l':list Z), equiv l l' -> equiv (z :: l) (z :: l').<br />Lemma equiv_perm : <br /> forall (a b:Z) (l l':list Z), equiv l l' -> equiv (a :: b :: l) (b :: a :: l').<br /></pre><br /><br />次いで、実際にinsertion sortを行う関数<code>aux : Z -> list Z -> list Z</code>を定義します。<pre><br />Fixpoint aux (z:Z) (l:list Z) {struct l} : list Z :=<br /> match l with<br /> | nil => z :: nil<br /> | cons a l' =><br /> match Z_le_gt_dec z a with<br /> | left _ => z :: a :: l'<br /> | right _ => a :: (aux z l')<br /> end<br /> end.<br /></pre><br /><br /><code>aux</code>がinsertion sortの性質を持っている事を示す補題、つまりauxの結果がequivであること、sortedであることを証明します。<pre><br />Lemma aux_equiv : <br /> forall (l:list Z) (x:Z), equiv (x :: l) (aux x l).<br />Lemma aux_sorted : <br /> forall (l:list Z) (x:Z), sorted l -> sorted (aux x l).<br /></pre><br /><br />最後に、<code>sort:list Z -> list Z</code>を定義というか、sortされた出力の存在を証明します。<pre><br />Definition sort : forall l:list Z, {l' : list Z | equiv l l' /\ sorted l'}.<br /></pre><br />証明を追いきれてないのですが、どうも<code>exists (aux a l')</code>の様に、実例を示して存在を証明するみたいに<code>aux</code>を使っているようです。<br /><br />----<br /><br /><code>sorted, nb_occ, equiv</code>は定義なので証明の対象ではありません。<br /><code>aux, sort</code>は成果物として得る、証明済みのプログラムです。<code>sort</code>を満たす具体的な<code>l'</code>の値として<code>aux</code>を使った式を与えます。その値が<code>l'</code>の条件を満たす事は<code>aux_equiv, aux_sorted</code>から保証されます。<br /><br />一般的に<ul><br /><li>仕様を表す様な述語(X -> Prop)を書く。仕様に関する補題も証明しておく。<br /><li>解を与える様な関数を書く。<br /><li>その関数の出力が仕様を満たす事を証明する。<br /></ul>とかすれば良い様に見えます。<br /><br />----<br /><br />ある程度、この本を読み終わった後で、またこのプログラムを振り返ってみたいと思います。<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-3404468389699569657?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-84060360194760068832008-12-27T15:34:00.004+09:002008-12-27T16:13:39.542+09:00[Haskell][RWH] Chapter 1RWHのChapter 1を読む。<br /><br /><ul><br /><li>not equalは<code>!=</code>ではなく<code>/=</code>。</li><br /><li>temporary definitionを<code>let</code>で。例えば、<code>ghci> <b>let e = exp 1</b></code>とか。</li><br /><li><code>ghci> <b>:info []</b></code>とかすれば、[]の情報が調べられる。</li><br /><li><code>ghci> <b>:set +t</b></code>で型情報を表示する。解除は<code><b>:unset +t</b></code>。<code><b>:type it</b></code>でunsetしても簡単に調べられる。</li><br /><li><code>it</code>で前の計算結果を参照出来る。</li><br /></ul><br /><br />簡単にHaskellのプログラムを書くにはinteractを使えば良いらしい。<br />main = interact f 但し、fはString -> Stringな関数。これで標準入力から読んで標準出力に書けば良い。<br /><code><br />% cat WC.hs<br />main = interact wordCount<br /> where wordCount input = show (length (lines input)) + "\n"<br />%<br /><br />Prelude> :info interact<br />interact :: (String -> String) -> IO () -- Defined in System.IO<br /></code><br />実行は<br /><code>% runghc WC.hs < quux.txt</code><br /><br />Exerciseはとりあえずこんな感じ?<br /><pre><br />main = interact wordCount<br /> where wordCount input = numLines input ++ "\t" ++ numWords input ++ "\t" ++ numChars input ++ "\n"<br /> numLines input = show (length (lines input))<br /> numWords input = show (length (words input))<br /> numChars input = show (length input)<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8406036019476006883?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-25229215539238454272008-12-04T23:07:00.003+09:002008-12-04T23:13:36.505+09:00[Scala] map and flatMap on scala.Function1<a href="http://blog.tmorris.net/scalafunction1-lacking/">scala.Function1 lacking</a> @ λ Tony’s blog λ<br /><br />Scalaの関数の型の scala.Function1 にもっと便利な機能を、という話。<br />mapはともかくflatMapをこうやって定義するのか、というのはなんか勉強になったので、メモ代わりに。<br />同様に S combinator というのも自分ではなんか巧く使えないものなので参考になるなぁ、と。on は普通に便利かも。<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2522921553923845427?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-54430129073920213862008-12-04T22:56:00.005+09:002008-12-04T23:06:45.840+09:00[Misc] These days...Project Eulerはその後も細々と解いてはいるのだが、いちいち解法をblogに書くのが面倒になって更新をさぼってました。あと1問でLevel 2なんだけどなー。<br /><br /> あと、<a href="http://cappuccino.jp/scala-ja/?Scala%CA%D9%B6%AF%B2%F1%A1%F7%B4%D8%C5%EC-2">Scala勉強会@関東2</a>の準備が忙しかったりとか。仕事でのプレゼンは勿論あるけど、私的な勉強会でのプレゼンはこれが始めてで、なんていうか仕事とは別の緊張感がありますね。つまり仕事と違って、「実は自分は良く解ってなくて外しているんじゃないかしらん」みたいな不安とか。<br /><br />そういえばそろそろReal World Haskellの発売ですね。東京近辺で興味がある人がいれば是非とも読書会とか検討しません?<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5443012907392021386?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-49438875802666617842008-10-20T01:16:00.002+09:002008-10-20T01:24:14.579+09:00[Project Euler] Problem 22<a href="http://projecteuler.net/index.php?section=problems&id=22">Problem 22</a><br /><br /> この問題では、入力データをコードに直接貼付けず、ファイルから読み込むようにする必要がある。<br /> ファイルからデータをどう読み込むかだが、scala.io.Source.fromFile("filename").getLines で行単位で読み込めるイテレータを生成するので、それを使うのが楽だと思う。(本当はそういう目的のライブラリでは無い様にも思うのだが...。)<br /> names.txt がどこに置かれているのかというと、Eclipse上のプロジェクトProjectEuler下の、srcの下の、パッケージP020の下に、names.txtが置かれているので、filenameとしては"src/P020/names.txt"になった。<pre><br />object P022 {<br /> def main(args:Array[String]) {<br /> val line:String = scala.io.Source.fromFile("src/P020/names.txt").getLines.next<br /> val names1:List[String] = line.split(",").map{s =&gt; s.substring(1, s.size-1)}.toList<br /> val names2:List[(String,Int)] = names1.sort{(a,b) =&gt; a.compareTo(b)&lt;0}.zipWithIndex.map{t =&gt; (t._1, t._2+1)}<br /> println(names2.head) // (AARON,1)<br /> def f(t:Tuple2[String,Int]):Int = t match {<br /> case (s,i) =&gt; i * s.toCharArray.map{c =&gt; c-'A'+1}.foldLeft(0)(_+_)<br /> }<br /> println(f(names2.head)) // (AARON,1)<br /> println(names2.map(f).foldLeft(0)(_+_))<br /> }<br />}<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-4943887580266661784?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-50607112987551834452008-10-20T00:25:00.002+09:002008-10-20T00:41:13.080+09:00[Project Euler] Problem 21<a href="http://projecteuler.net/index.php?section=problems&id=21">Problem 21</a><br /><br />素数リストとかは過去の問題のを使い回し。<pre><br />object P021 {<br /> val initPrimes:List[Int] = List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, <br /> 31, 37, 41, 43, 47, 53, 59, 61, 67, <br /> 71, 73, 79, 83, 89, 97, 101)<br /> def primes(init:List[Int]):List[Int] = {<br /> def min(a:Int, b:Int) = if (a&lt;b) a else b<br /> def sq(a:Int) = a*a<br /> init ::: List.range(init.last+1, min(100000,sq(init.last))).filter{x =&gt; init.forall{x%_!=0}}<br /> }<br /> val primeList:List[Int] = primes(primes(initPrimes))<br /> def factors(n:Int):List[Tuple2[Int,Int]] = {<br /> def g(n:Int, p:Int, c:Int):Tuple2[Int,Int] = if (n%p==0) g(n/p, p, c+1) else Tuple2(n,c)<br /> def f(n:Int, ps:List[Int], ts:List[Tuple2[Int,Int]]):List[Tuple2[Int,Int]] = (n,ps) match {<br /> case (1,_) =&gt; ts<br /> case (_,Nil) =&gt; error("n="+n)<br /> case (_, a::as) if n%a==0 =&gt; {<br /> val z = g(n,a,0)<br /> f(z._1, as, Tuple2(a,z._2)::ts)<br /> }<br /> case (_, a::as) =&gt; f(n, as, ts)<br /> }<br /> f(n, primeList, Nil)<br /> }<br /> def sumDiv(ts:List[Tuple2[Int,Int]]):Int = {<br /> def pow(a:Int, b:Int):Int = b match {<br /> case 0 =&gt; 1<br /> case _ =&gt; pow(a,b-1)*a<br /> } <br /> def f(t:Tuple2[Int,Int]):Int = {<br /> List.range(0, t._2 +1).map{pow(t._1, _)}.foldLeft(0)(_+_)<br /> }<br /> ts.map(f).foldLeft(1)(_*_)<br /> }<br /> def sumDivisors(n:Int):Int = sumDiv(factors(n))-n<br /> def main(args:Array[String]) {<br /> println(sumDivisors(220))<br /> println(sumDivisors(284))<br /> val l = List.range(2,10000).filter{a =&gt; {<br /> val b=sumDivisors(a)<br /> val c=sumDivisors(b)<br /> val r=(a!=b)&amp;&amp;(a==c)<br /> if (r) println(a+"&lt;-&gt;"+b)<br /> r<br /> }}<br /> println(l)<br /> println(l.foldLeft(0)(_+_))<br /> }<br />}<br /></pre><br />---<br /> ここまでProject Eulerを解いてきて思ったのだが、組み込みライブラリとか言語仕様で、<ul><br /><li>アノテーションを付けるだけで関数の値をメモ化してくれる。<br /><li>とりあえず1,000,000以下の素数は予め計算されている。<br /><li>内部でIntの計算が桁溢れしたら勝手にLong -> BigInt と桁を増やしてくれるような数値型。<br /><li>素因数分解も組み込み関数で用意されている。<br /></ul>とかだと、かなり楽が出来るのになぁ...。<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5060711298755183445?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-27200280969807938562008-10-19T12:03:00.001+09:002008-10-19T12:05:10.006+09:00[Project Euler] Problem 20<a href="http://projecteuler.net/index.php?section=problems&id=20">Problem 20</a><br /><br />BigIntegerを使うだけ。<pre><br />object P020 {<br /> def main(args:Array[String]) {<br /> def fact(n:Int):BigInt = n match {<br /> case 0 =&gt; new BigInt(java.math.BigInteger.ONE)<br /> case _ =&gt; new BigInt(java.math.BigInteger.valueOf(n))*fact(n-1)<br /> }<br /> val r = fact(100).toString.toCharArray.map{c =&gt; c-'0'}.foldLeft(0)(_+_)<br /> println(r)<br /> }<br />}<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2720028096980793856?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-8380257867371257052008-10-19T11:54:00.002+09:002008-10-19T11:57:45.157+09:00[Project Euler] Problem 19<a href="http://projecteuler.net/index.php?section=problems&id=19">Problem 19</a><br /><br />難しくは無いはずなんだが、1900を1990と入力していたtypoの為でなかなか正解に辿り着けなかった。<pre><br />object P019 {<br /> def isLeap(y:Int):Boolean = y match {<br /> case _ if y%400==0 =&gt; true<br /> case _ if y%100==0 =&gt; false<br /> case _ if y%4==0 =&gt; true<br /> case _ =&gt; false<br /> }<br /> def daysOfMonth(y:Int, m:Int):Int = m match {<br /> case 9 =&gt; 30<br /> case 4 =&gt; 30<br /> case 6 =&gt; 30<br /> case 11 =&gt; 30<br /> case 2 =&gt; if (isLeap(y)) 29 else 28<br /> case _ =&gt; 31<br /> }<br /> def daysInYear(y:Int):Int = if (isLeap(y)) 366 else 365<br /> def daysFrom1Jan1900(year:Int, month:Int, day:Int):Int =<br /> List.range(1900,year).map{y =&gt; daysInYear(y)}.foldLeft(0)(_+_) +<br /> List.range(1,month).map{m =&gt; daysOfMonth(year,m)}.foldLeft(0)(_+_) +<br /> (day-1)<br /> val day0Jan1900:Int = daysFrom1Jan1900(1900,1,0) // Sunday<br /> def dayOfTheWeek(year:Int, month:Int, day:Int):Int = (daysFrom1Jan1900(year,month,day)-day0Jan1900)%7<br /> def main(args:Array[String]) {<br /> println(dayOfTheWeek(1901,1,1))<br /> println(dayOfTheWeek(2000,12,1))<br /> println(<br /> (for(y &lt;- List.range(1901,2001); m &lt;- List.range(1,13))<br /> yield dayOfTheWeek(y,m,1)).filter{_==0}.size)<br /> }<br />}<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-838025786737125705?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-90181107690702558652008-10-19T10:51:00.002+09:002008-10-19T10:57:22.897+09:00[Project Euler] Problem 18<a href="http://projecteuler.net/index.php?section=problems&id=18">Problem 18</a><br /><br />n段目では、(n-1)段目で左右を選ぶ選択で大きな方を選ぶ、というのを再帰的にやれば良いが、計算時間を減らす為に、Problem 15と同様にメモ化する。<pre><br />import scala.collection.mutable.HashMap<br />object P018 {<br /><br /> val input:Array[String] = Array(<br />"75",<br />"95 64",<br />...中略...<br />"63 66 04 68 89 53 67 30 73 16 69 87 40 31",<br />"04 62 98 27 23 09 70 98 73 93 38 53 60 04 23") // y=0<br /> val data:Array[Array[Int]] = input.map{s =&gt; s.split(" ").map{x =&gt; x.toInt}}<br /> val height = input.size<br /> def value(x:Int,y:Int):Int = data(height-1-y)(x)<br /> val map:HashMap[Tuple2[Int,Int],Int] = new HashMap()<br /> def search(x:Int,y:Int):Int = map.get(Tuple2(x,y)) match {<br /> case Some(x) =&gt; x<br /> case None =&gt; (x,y) match {<br /> case (_,0) =&gt; {<br /> val v = value(x,y)<br /> map.put(Tuple2(x,y),v)<br /> v<br /> }<br /> case _ =&gt; {<br /> val s0 = value(x,y)<br /> val s1 = search(x,y-1)<br /> val s2 = search(x+1,y-1)<br /> val v = if (s1&gt;s2) s0+s1 else s0+s2<br /> map.put(Tuple2(x,y),v)<br /> v<br /> }<br /> }<br /> }<br /> def main(args:Array[String]) {<br /> println(search(0,height-1))<br /> }<br />}<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-9018110769070255865?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-58507237412454390482008-10-19T10:08:00.002+09:002008-10-19T10:12:33.521+09:00[Project Euler] Problem 17<a href="http://projecteuler.net/index.php?section=problems&id=17">Problem 17</a><br /><br />綴りが間違っていると正解が出ないので、念のために数詞を調べ直したりとか、英語を使ってない我々にはそれだけで敷居が高い問題。<br />この手の問題を解く時は、match-case構文を便利だと特に感じる。<pre><br />object P017 {<br /><br /> val digitOne:List[String] = List("", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine")<br /> val teens:List[String] = List("", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen")<br /> val digitTen:List[String] = List("", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety")<br /> def toEnglish(n:Int):String = n match {<br /> case 1000 =&gt; "one thousand"<br /> case _ if (n/100 != 0) =&gt; digitOne(n/100)+" hundred" + (if (n%100==0) "" else " and "+toEnglish(n%100))<br /> case _ if (10&lt;n)&amp;&amp;(n&lt;20) =&gt; teens(n-10)<br /> case _ =&gt; Tuple2(n/10, n%10) match {<br /> case (a,0) =&gt; digitTen(a)<br /> case (0,b) =&gt; digitOne(b)<br /> case (a,b) =&gt; digitTen(a)+"-"+digitOne(b)<br /> }<br /> }<br /> def countLetter(s:String) = s.split("[ -]").map{s =&gt; s.length}.foldLeft(0)(_+_)<br /> def main(args:Array[String]) {<br /> /*<br /> println(List(1,9,10,11,19,20,21,99).map{x =&gt; Tuple3(x,toEnglish(x),countLetter(toEnglish(x)))})<br /> println(List(100,101,110,111,120,121,199).map{x =&gt; Tuple2(x,toEnglish(x))})<br /> println(List(200,201,210,211,299).map{x =&gt; Tuple2(x,toEnglish(x))})<br /> println(List(900,901,910,911,999,1000).map{x =&gt; Tuple2(x,toEnglish(x))})<br /> */<br /> println(List(342,115).map{x =&gt; Tuple3(x,toEnglish(x),countLetter(toEnglish(x)))})<br /> println(List.range(1,1001).map{x =&gt; countLetter(toEnglish(x))}.foldLeft(0)(_+_))<br /> }<br />}<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5850723741245439048?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-3362075707176208682008-10-19T09:11:00.001+09:002008-10-19T09:13:20.593+09:00[Project Euler] Problem 16<a href="http://projecteuler.net/index.php?section=problems&id=16">Problem 16</a><br /><br />java.math.BigIntegerを使うだけ。<pre><br />object P016 {<br /> def main(args:Array[String]) {<br /> val v2 = new BigInt(java.math.BigInteger.valueOf(2L))<br /> val r = v2.pow(1000).toString.toCharArray.map{c => c-'0'}.foldLeft(0)(_+_)<br /> println(r)<br /> }<br />}</pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-336207570717620868?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-24883700075376042252008-10-19T08:59:00.001+09:002008-10-19T09:03:02.718+09:00[Project Euler] Problem 15<a href="http://projecteuler.net/index.php?section=problems&id=15">Problem 15</a><br /><br />これも計算機を使わないで解いた方が速い問題。<br />n x n grid で考えると、2n ステップの中から n 個右を選ぶということだから、<br />_{2n}C_n を計算すればいい。つまり、(2n)! / (n!)^2 。<br /><br />もうちょっと計算機っぽく考えると、nx x ny のグリッドの場合、最初に右に行くか下に行くかで、<br />f(nx,ny) = f(xn-1,ny) + f(xn,ny-1)<br />但し、<br />f(0,_) = f(_,0) = 1<br />を解けば良いが、最初の式は実は _nC_r = _{n-1}C_r + _{n-1}C_{r-1} の事である。<br />実際にはこのままではf(nx,ny)回の関数呼び出しが発生するので、メモ化する。<pre><br />import scala.collection.mutable.HashMap<br />import java.math.BigInteger<br /><br />object P015 {<br /> val map:HashMap[Tuple2[Int,Int],Long] = new HashMap()<br /> def f(nx:Int, ny:Int):Long = map.get(Tuple2(nx,ny)) match {<br /> case Some(x) =&gt; x<br /> case None =&gt; {<br /> val z:Long = (nx,ny) match {<br /> case (0,_) =&gt; 1<br /> case (_,0) =&gt; 1<br /> case (x,y) =&gt; f(x-1,y) + f(x,y-1)<br /> }<br /> val zz = map.put(Tuple2(nx,ny),z)<br /> z<br /> }<br /> }<br /> def main(args:Array[String]) {<br /> println(f(20,20))<br /> println(40L/20*39*38/19*37*36/18*35*34/17*33*32/16*31*30/15*29*28/14*27*26/13*25*24/12*23*22/11*21/10/9/8/7/6/5/4/3/2/1)<br /> }<br />}<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2488370007537604225?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-66034675803889537472008-10-19T02:01:00.002+09:002008-10-19T02:07:24.329+09:00[Project Euler] Problem 14<a href="http://projecteuler.net/index.php?section=problems&id=14">Problem 14</a><br /><br /> 有名なCollatz問題。最初はListを使っていたのだがOutOfMemoryになるので普通に命令型っぽいプログラムになっている。<pre><br />object P014 {<br /> def collatz(n:Long):Int = {<br /> def f(n:Long, c:Int):Int = {<br /> if (n==1L) c<br /> else if (n%2L==0) f(n/2, c+1)<br /> else f(3L*n+1, c+1)<br /> }<br /> f(n,1)<br /> }<br /> def mx(a:Tuple2[Long,Int], b:Tuple2[Long,Int]):Tuple2[Long,Int] = if (a._2 &gt; b._2) a else b<br /> def maxLength(m:Int):Tuple2[Long,Int] = {<br /> var ts:Tuple2[Long,Int] = Tuple2(0L,0)<br /> for(x &lt;- List.range(1, m)) {<br /> val c:Int = collatz(x)<br /> if (ts._2 &lt; c) {ts = Tuple2(x,c)}<br /> }<br /> ts<br /> }<br /> def main(args:Array[String]) {<br /> println(collatz(13L))<br /> println(maxLength(1000000))<br /> }<br />}<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-6603467580388953747?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-84723314738630715612008-10-19T01:17:00.001+09:002008-10-19T01:20:14.774+09:00[Project Euler] Problem 13<a href="http://projecteuler.net/index.php?section=problems&id=13">Problem 13</a><br /><br />文字列 -> BigInt の変換をして和を取るだけ。<pre><br />import java.math.BigInteger<br /><br />object P013 {<br /> val input:Array[String] = Array(<br />"37107287533902102798797998220837590246510135740250",<br /> ...中略...<br />"53503534226472524250874054075591789781264330331690")<br /> def main(args:Array[String]) {<br /> val sum:BigInt = input.map{s =&gt; new BigInt(new BigInteger(s))}.foldLeft(new BigInt(BigInteger.ZERO))(_+_)<br /> println(sum)<br /> println(sum.toString.substring(0,10))<br /> }<br />}<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-8472331473863071561?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-29458282430808233272008-10-19T00:57:00.003+09:002008-10-19T10:57:56.928+09:00[Project Euler] Problem 12<a href="http://projecteuler.net/index.php?section=problems&id=12">Problem 12</a><br /><br /> 最初に素数列を作成するのに結構時間がかかる気がする。今回は最初10000以下の素数のリストを作り、エラーが出たので30000まで作った。<br /> 約数の数は素因数分解して各素数の指数から求められるのを使う。<pre><br />object P012 {<br /> val maxRange = 30000<br /> def primes(init:List[Int]):List[Int] = {<br /> def min(a:Int, b:Int) = if (a&lt;b) a else b<br /> def sq(a:Int) = a*a<br /> init ::: List.range(init.last+1, min(maxRange,sq(init.last))).filter{x =&gt; init.forall{x%_!=0}}<br /> }<br /> val primeList = primes(primes(List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, <br /> 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101)))<br /> val emptyFactors = primeList.map{x =&gt; 0}<br /> def factor(n:Int):List[Int] = {<br /> def f(x:Int, fs:List[Int], ps:List[Int]):List[Int] = (x,fs,ps) match {<br /> case (1,_,_) =&gt; fs<br /> case (_,Nil,_) =&gt; error("fs empty:x="+x)<br /> case (_,_,Nil) =&gt; error("ps empty:x="+x)<br /> case (y,a::as,b::bs) if y%b==0 =&gt; f(y/b, (a+1)::as, ps)<br /> case (y,a::as,b::bs) =&gt; a::f(y,as,bs)<br /> }<br /> f(n, emptyFactors, primeList)<br /> }<br /> def numFactors(n:Int):Int = factor(n).foldLeft(1){(a,b) =&gt; a*(b+1)}<br /> def triangle(n:Int):Int = n*(n+1)/2<br /> def main(args:Array[String]) {<br /> println(primeList.length)<br /> println(numFactors(28))<br /> val t:Tuple3[Int,Int,Int] =<br /> Stream.range(1,maxRange).map{x =&gt; Tuple3(x,triangle(x),numFactors(triangle(x)))}.filter{x =&gt; x._3&gt;500}.head<br /> println(t)<br /> println(factor(triangle(t._1)).zip(primeList).filter{t =&gt; t._1 != 0}.map{x =&gt; x._2+"^"+x._1})<br /> }<br />}<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-2945828243080823327?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-51957189350336418622008-10-18T23:08:00.002+09:002008-10-18T23:12:09.934+09:00[Project Euler] Problem 11<a href="http://projecteuler.net/index.php?section=problems&id=11">Problem 11</a><br /><br />表をArray[Array[Int]]に変換、4つの並びを(x,y)のTuple2のListとして表現し、全組み合わせ ( List[List[Tuple2[Int,Int]]]) から積が最大になるものを選択する。<pre><br />object P011 {<br /> val input:Array[String] = Array(<br />"08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08",<br />"49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00",<br />"81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65",<br />"52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91",<br />"22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80",<br />"24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50",<br />"32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70",<br />"67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21",<br />"24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72",<br />"21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95",<br />"78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92",<br />"16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57",<br />"86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58",<br />"19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40",<br />"04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66",<br />"88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69",<br />"04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36",<br />"20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16",<br />"20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54",<br />"01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48")<br /> val table:Array[Array[Int]] = input.map{x =&gt; x.split(" ").map{_.toInt}}<br /> def v(x:Int, y:Int):Int = table(y)(x)<br /> val xscan:List[List[Tuple2[Int,Int]]] = <br /> for(y &lt;- List.range(0,20); x0 &lt;- List.range(0,20-4)<br /> ) yield for(x &lt;- List.range(x0, x0+4)) yield (x,y)<br /> val yscan:List[List[Tuple2[Int,Int]]] = <br /> for(x &lt;- List.range(0,20); y0 &lt;- List.range(0,20-4)<br /> ) yield for(y &lt;- List.range(y0, y0+4)) yield (x,y)<br /> val diagscan1 = <br /> for(x0 &lt;- List.range(0,20-4); y0 &lt;- List.range(0,20-4)<br /> ) yield for(i &lt;- List.range(0,4)) yield (x0+i, y0+i)<br /> val diagscan2 = <br /> for(x0 &lt;- List.range(0,20-4); y0 &lt;- List.range(0,20-4)<br /> ) yield for(i &lt;- List.range(0,4)) yield (x0+3-i, y0+i)<br /> def f(ps:List[Tuple2[Int,Int]]):Long = ps.foldLeft(1L){(a,t) =&gt; a * v(t._1,t._2)}<br /> val result = (xscan ::: yscan ::: diagscan1 ::: diagscan2).sort{(a,b) =&gt; f(a)&gt;f(b)}.head<br /> def main(args:Array[String]) {<br /> println(result)<br /> println(result.map{t =&gt; v(t._1,t._2)})<br /> println(f(result))<br /> }<br />}<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-5195718935033641862?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0tag:blogger.com,1999:blog-30049755.post-7636944951886474192008-10-18T22:16:00.002+09:002008-10-18T23:07:55.722+09:00[Project Euler] Problem 10<a href="http://projecteuler.net/index.php?section=problems&id=10">Problem 10</a><br /><br /> 2000000以下の素数を得るには1415以下の素数が判れば良く、1415以下の素数を得るには37以下の素数が判れば良く、37以下の素数を知るには7以下の素数が2,3,5,7であることを知っていればOKである。<br /> という訳で、エラトステネスの篩を三段重ねにしてみた。<pre><br />object P010 {<br /> def main(args:Array[String]) {<br /> val maxRange = 2000000<br /> def primes(init:List[Int]):List[Int] = {<br /> def min(a:Int, b:Int) = if (a&lt;b) a else b<br /> def sq(a:Int) = a*a<br /> init ::: List.range(init.last+1, min(maxRange,sq(init.last))).filter{x =&gt; init.forall{x%_!=0}}<br /> }<br /> println(new java.util.Date())<br /> val ps1 = List(2,3,5,7)<br /> val ps2 = primes(ps1)<br /> println(ps2.last)<br /> val ps3 = primes(ps2)<br /> println(ps3.last)<br /> val ps4 = primes(ps3)<br /> println(ps4.last)<br /> println(ps4.foldLeft(0L)(_+_))<br /> println(new java.util.Date())<br /> }<br />}<br /></pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30049755-763694495188647419?l=study-func-prog.blogspot.com'/></div>Takashihttp://www.blogger.com/profile/15445314693808242249noreply@blogger.com0