1 名前:営利利用に関するLR審議中@詳細は自治スレへ mailto:sage [2012/04/07(土) 21:26:47.61 ] 一般的には、オブジェクト指向型言語が優勢でが 一部には関数型言語を崇拝している人もいます どちらが上なのか、この際はっきりさせましょう 前スレ toro.2ch.net/test/read.cgi/tech/1331328955/
494 名前:デフォルトの名無しさん mailto:sage [2012/04/17(火) 12:02:41.83 ] >>493 Pythonも同じ方針のやつ import threading fbdata = threading.local() def fb(x, cnd, msg): if isinstance(x, int): fbdata.m = n = x s = "" else: n = fbdata.m s = x if cnd(n): return s + msg elif s <> "": return s else: return n def fizz(n): return fb(n, lambda n: n%3==0, "Fizz") def buzz(n): return fb(n, lambda n: n%5==0, "Buzz") def gizz(n): return fb(n, lambda n: n%7==0, "Gizz") assert fizz(1) == 1 assert fizz(3) == "Fizz" assert buzz(fizz(1)) == 1 assert buzz(fizz(3)) == "Fizz" assert buzz(fizz(5)) == "Buzz" assert buzz(fizz(15)) == "FizzBuzz" assert gizz(buzz(fizz(105))) == "FizzBuzzGizz" assert buzz(gizz(fizz(105))) == "FizzGizzBuzz"
495 名前:デフォルトの名無しさん mailto:sage [2012/04/18(水) 13:10:30.34 ] っていうか問題どこだよ
496 名前:デフォルトの名無しさん mailto:sage [2012/04/18(水) 13:31:40.56 ] スレタイに惹かれて開いたけどゴミスレだった・・・
497 名前:デフォルトの名無しさん mailto:sage [2012/04/19(木) 02:49:08.33 ] $t = sub { my $f = shift; sub { my $x = shift; $f->($f->($x)) } }; $rst = $t->($t)->($t)->($t)->( sub{ my $x = shift; $x + 1 })->(0); print $rst, "\n";
498 名前:デフォルトの名無しさん mailto:sage [2012/04/19(木) 09:02:56.87 ] 同じくRubyも。 ケチがついた、オープンクラス、メソッドチェーン、リフレクションは無しで require 'test/unit' def fb(x, cnd, msg) th = Thread.current x.kind_of?(Integer) ? (th[:m] = n = x; s = "") : (n = th[:m]; s = x) cnd[n] ? s + msg : !s.empty? ? s : n end def fizz(n); fb(n, proc{ |n| n%3==0 }, "Fizz") end def buzz(n); fb(n, proc{ |n| n%5==0 }, "Buzz") end def gizz(n); fb(n, proc{ |n| n%7==0}, "Gizz") end class FizzBuzzQuizTest < Test::Unit::TestCase def test_fbq assert_equal( fizz(1), 1 ) assert_equal( fizz(3), "Fizz" ) assert_equal( buzz(fizz(1)), 1 ) assert_equal( buzz(fizz(3)), "Fizz" ) assert_equal( buzz(fizz(5)), "Buzz" ) assert_equal( buzz(fizz(15)), "FizzBuzz" ) assert_equal( gizz(buzz(fizz(105))), "FizzBuzzGizz" ) assert_equal( buzz(gizz(fizz(105))), "FizzGizzBuzz" ) end end
499 名前:デフォルトの名無しさん mailto:sage [2012/04/19(木) 09:53:30.31 ] リフレクションやらスレッドローカルやら組み込みクラス汚染やら使った クソみたいな実装が出てくる出題だったけど 言語比較に役立つ何かは得られましたか?
500 名前:デフォルトの名無しさん mailto:sage [2012/04/19(木) 10:07:54.14 ] あるときは数値またあるときは文字列を返すような関数は 動的型であれ作るもんじゃないという幼稚園児並みの洞察が得られました
501 名前:デフォルトの名無しさん mailto:sage [2012/04/19(木) 10:43:06.55 ] >>499 「数値と文字列の組」と「数値または文字列」の違いが不明瞭だった。 リフレクションや継承で二つのクラスを一組にしたいのか、 それとも一つのクラスを数種類に分けたいのか明示されていなかった。
502 名前:デフォルトの名無しさん mailto:sage [2012/04/19(木) 10:53:45.22 ] どうしてもスレッドローカル変数が必要になったとき 関数的にはどう記述したらいいのかよかったら教えてください。
503 名前:デフォルトの名無しさん mailto:sage [2012/04/19(木) 11:37:33.00 ] そもそもスレッド自体が処理系に依存した、言語パラダイムとは関係ない概念だから、 関数型的にもオブジェクト指向的にも、どう記述したらいいかとか答えようがない。
504 名前:デフォルトの名無しさん mailto:sage [2012/04/19(木) 12:23:49.22 ] Readerモナドでグローバル変数っぽいことをするには どうすればいいのでしょうか。たとえば、状態をfizzとかbuzzから (引数として渡すことなしに)参照したり更新したりしたいのです。
505 名前:デフォルトの名無しさん mailto:sage [2012/04/19(木) 12:50:34.08 ] ttp://www.haskell.org/haskellwiki/Thread-local_storage いまんとこHaskellからTLSを使う、「これ」といった定番はないようだ
506 名前:デフォルトの名無しさん mailto:sage [2012/04/19(木) 12:58:07.14 ] 個人的に、関数型でスレッドとかハードに近い領域の制御はしたくないな。
507 名前:デフォルトの名無しさん mailto:sage [2012/04/19(木) 13:20:53.20 ] >>504 それは基本的にStateモナドの領域。 Readerモナドの中で、さらにサブルーチン的に他のReaderモナドを呼び出す時に、 一時的に書き換えたように見せかけたい、っていう場合ならばlocal関数が使えるけど。 Readerモナドで更新したいって、読み取り専用変数に書き込みたいって言ってるのと同じ事なのはわかってるよな…?
508 名前:デフォルトの名無しさん mailto:sage [2012/04/19(木) 17:54:57.76 ] Reader (s -> a) -> (a -> s -> b) -> s -> b Writer (a,s) -> (a -> (b,s)) -> (b,s) State (s -> (a,s)) -> (a -> s -> (b,s)) -> s -> (b,s)
509 名前:デフォルトの名無しさん mailto:sage [2012/04/20(金) 11:54:43.80 ] >>500 あるときは a またあるときは m a m a -> (a -> m b) -> m b
510 名前:デフォルトの名無しさん mailto:sage [2012/04/20(金) 17:52:20.76 ] なんつーか、FizzBuzzしたいんならHQ9F+使えばいんじゃね?
511 名前:デフォルトの名無しさん mailto:sage [2012/04/20(金) 22:29:27.34 ] お題出していい?
512 名前:デフォルトの名無しさん mailto:sage [2012/04/20(金) 22:55:07.28 ] ・コンソール上で動く、カード(つーてもただの数字を表示するだけだが)を使ったミニゲーム ・1〜9のカードを各4枚ずつ用意、それをシャッフルして「ストック」とする ・ストックから7枚のカードを引く ・引いたカードの中から、プレイヤーは合計が15になるように数枚を選んで捨てる (選ばせ方はプログラマが考える、ギブアップ手段も用意) ・捨てなかったカードと合わせて再び7枚になるか、もしくはストックが空になるまでストックからカードを引く ・また15になるように捨てる ・引いては捨ててを繰り返し、ストックと手札が共に空になったらおめでとう的な言葉を吐いて終了
513 名前:デフォルトの名無しさん mailto:sage [2012/04/20(金) 23:16:37.51 ] つまらない。
514 名前:デフォルトの名無しさん mailto:sage [2012/04/21(土) 01:27:35.30 ] >>512 Squeak Smalltalk で。 | ui stock player | ui := UIManager default. stock := (1 to: 9) gather: [:each | Array new: 4 withAll: each]. stock := stock shuffled asOrderedCollection. player := (stock removeFirst: 7) asOrderedCollection. [ | choice | [ | input | input := ui request: player asSortedArray asString, 'から合計が15になるようにチョイス'. choice := input subStrings collect: #asInteger. choice ifEmpty: [(ui confirm: 'ギブアップ?') ifTrue: [^self] ifFalse: [choice := {nil}]]. (choice allSatisfy: #isInteger) and: [choice sum = 15] and: (player includesAllOf: choice) and: [choice asSet allSatisfy: [:card | (player occurrencesOf: card) >= (choice occurrencesOf: card)]] ] whileFalse. player removeAll: choice. player addAll: (stock removeFirst: (choice size min: stock size)). player notEmpty] whileTrue. ui inform: 'おめでとう!'
515 名前:デフォルトの名無しさん mailto:sage [2012/04/21(土) 02:46:31.71 ] >>514 なぜこの人は今どきSmalltalkの末裔を使っているのか理由をうかがいたいので おしえてくださいです
516 名前:デフォルトの名無しさん mailto:sage [2012/04/22(日) 01:52:01.88 ] # Ruby版、指定は半角空白区切り、EOFでギブアップ class CardNotFoundException < RuntimeError; end def remove_cards(specs, tableau) specs.each do |spec| if idx = tableau.find_index{|card| card == spec } then tableau.delete_at idx else raise CardNotFoundException.new(spec.to_s) end end end stock = ((1..9).to_a * 4).shuffle tableau = [] until tableau.empty? && stock.empty? tableau.push stock.pop until tableau.size >= 7 || stock.empty? printf "stock=%d tableau=%p\n? ", stock.size, tableau k = gets or exit specs = k.chomp.split(' ').map{|s| s == 'giveup' ? exit : s.to_i } begin remove_cards specs,tableau.dup if (total = specs.inject{|result,n| result + n }) == 15 then remove_cards specs,tableau else puts "total(#{total}) not equal to 15" end rescue CardNotFoundException => e puts "not found `#{e}'." end end puts 'Congraturations !'
517 名前:デフォルトの名無しさん mailto:sage [2012/04/22(日) 02:31:25.32 ] >>514 をRubyに翻訳してみた版 stock = ([*1..9]*4).shuffle player = stock.shift(7) loop do choice = nil loop do puts player.sort.inspect + "から合計が15になるようにチョイス" choice = gets.split(/[, ]/).map(&:to_i) choice.delete(0) if choice.empty? puts "ギブアップ?[Y/n]" !(gets=="n\n") ? exit : choice = [0] end break if choice.all?(&:integer?) and choice.reduce(&:+) == 15 and choice.uniq.all?{ |card| player.count(card) >= choice.count(card) } end choice.each{ |e| player.delete_at(player.index(e)) } player += stock.shift([choice.size, stock.size].min) break if player.empty? end puts "おめでとう!"
518 名前:デフォルトの名無しさん mailto:sage [2012/04/22(日) 12:27:13.72 ] Squeakは入れたことあるが(てか今も入ってるけど)何をどうしたらいいのか判らん >>514 のコードをどこに入力して、どう実行したら動くんだ?
519 名前:デフォルトの名無しさん mailto:sage [2012/04/22(日) 17:54:43.65 ] >>518 1. sourceforge.jp/projects/squeak-ja/ から Squeak4.2-ja-all-in-one.zip を入手して展開。 2. 同梱 ReadMe-ja.txt などを参考に手元のOSでなんとか起動までこぎつける。無印VMでも新CogVMでもOK。 3. 「ツール」メニューから「ワークスペース」を選択してスクリプトなどのお試し実行用ウインドウを開く。 4. >>514 の | ui stock player | から ui inform: 'おめでとう!' をコピーして 3 のウインドウにペースト。 5. 改めて alt(Macならcmd)+a やマウスドラッグで全選択してから、alt(同cmd)+d で実行。 6. うまく動作すると入力欄がポップアップするので、そこに数字をでスペースなどで区切ってタイプ。 7. 「了解(s)」ボタンクリック(あるいはリターンキー)で入力決定。以降はこれの繰り返し。空決定でギブアップ。 ざっと調べた感じ最新の日本語化版である 4.2ja にこだわらなくても 3.9以降であれば動作するようです。 ただし公式英語版などでは日本語が化けますので適宜英語などに置き換えてからペーストしてください。 日本語版であってもペースト時にエラーがでるようならそのときの対処も同様です。
520 名前:デフォルトの名無しさん mailto:sage [2012/04/22(日) 21:05:31.50 ] // F#で入出力以外の副作用なし let rec input hands = printfn "合計が15になるように捨てるカードをスペース区切りで指定(ギブアップの場合は指定なし)" match System.Console.ReadLine() with | "" -> None | inp -> try let discardCount = inp.Split([|' '|]) |> Seq.map int |> Seq.countBy id |> Map.ofSeq let handCount = hands |> Seq.countBy id |> Map.ofSeq if discardCount |> Map.exists (fun n c -> defaultArg (Map.tryFind n handCount) 0 < c) || discardCount |> Map.toSeq |> Seq.sumBy ((<||) (*)) |> (<>) 15 then input hands else handCount |> Map.map (fun n c -> c - defaultArg (Map.tryFind n discardCount) 0) |> Map.toList |> List.collect (fun (n, c) -> List.replicate c n) |> Some with _ -> input hands let rec play hands stocks = if (hands, stocks) = ([], []) then printfn "おめでとう!" else let cards = stocks |> Seq.truncate (7 - List.length hands) |> Seq.toList let nowHands, nextStocks = hands @ cards, (stocks |> Seq.skip cards.Length |> Seq.toList) nowHands |> Seq.sort |> Seq.map string |> String.concat " " |> printf "手札 : %s, " printfn "山札の残り枚数 : %d" nextStocks.Length match input nowHands with Some nextHands -> play nextHands nextStocks | None -> () let random = System.Random() [for i in 1 .. 9 do yield! List.replicate 4 i] |> List.sortBy (fun _ -> random.Next()) |> play []
521 名前:デフォルトの名無しさん mailto:sage [2012/04/23(月) 00:28:55.28 ] >>519 ありがと。何か前に入れたバージョンでやってみたら「[ | input |」の行の左に「Period or right bracket expected ->」とか出たけど、実行の仕方自体は判ったから色々試してみる。
522 名前:デフォルトの名無しさん mailto:sage [2012/04/23(月) 00:33:02.59 ] ああ、インデントを一旦削って入れ直したら動いたわ。thx
523 名前:デフォルトの名無しさん mailto:sage [2012/04/23(月) 07:26:59.30 ] あ、動的にいたスモールトーカーだ。よろしく!
524 名前:デフォルトの名無しさん mailto:sage [2012/04/24(火) 12:35:28.99 ] 日本語でおk
525 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 13:12:07.32 ] お題: コンウェイのライフゲームで、 配列の配列(あるいはリストのリスト)で表わされた格子を受け取り 次世代を返す関数lifeを定義せよ。 life([ [0,1,1,1,0], [0,1,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]]) #=> [ [0,1,1,0,0], [0,1,0,1,0], [0,0,0,0,0], [0,0,0,0,0], [0,0,1,0,0]] また作成した同関数を用いて、500x500のランダムな状態の格子の 500世代目を算出するのにかかった時間(無理なら、算出可能な 世代数とその時間)を計測して示せ。
526 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 13:54:49.01 ] くだらん
527 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 14:03:57.26 ] Java8でラムダ式が言語仕様に入るようだね javaもマルチパラダイム化が進むな OOPLが関数型言語の特徴の一部を取り込む中 スレタイの通り言語比較した場合 「副作用の有無」が一番重要なんじゃないかと思ったけどどうだろう? 機能を取り込むことはあっても無くすことはしないだろうから 副作用の有無が、開発速度や可読性、保守性にどのように影響してくるか・・・ と考えても良いお題は思いつかないんだけどね
528 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 15:26:58.18 ] Javaって今でも組み込み型以外は参照型でしか扱えないの? 関数型言語使うようになってから、nullを持たない参照型とか、イミュータブルな値型がいかに重要か思い知った。 しかも、イミュータブルな値型を基本として、nullを持った参照オブジェクト型、nullを持たない参照オブジェクト型って形で扱えないと厳しい。 これは言語仕様として取り込まれていないとどうしようもない。 そういう意味では、C++は結構惜しいところまで行ってたと思う。
529 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 16:37:33.03 ] C++にはpure virtual function callというのがあって、仮想関数がnullを持つ。 値型でも仮想関数があったら元も子もない。 仮想関数をやめてswitchを使う覚悟がないと厳しい。 関数型言語のパターンマッチはswitchと同じ方式だ。
530 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 16:43:26.43 ] >>528 関数型言語はむしろ全てが参照型とも言えるんだが
531 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 17:35:29.26 ] >>525 Squeak Smalltalk (4.2-ja w/CogVM), 1.8GHz Core i7で5分弱。 life := [:ary2d | | sum survivs | sum := ary2d * 0. #(-1 0 1) do: [:dx | #(-1 0 1) do: [:dy | sum := sum + ((ary2d collect: [:row | row flipRotated: dx*2]) flipRotated: dy*2)]]. survivs := #(3 4) collect: [:alive | sum collect: [:row | row collect: [:cell | (cell = alive) asBit]]]. survivs first + (survivs second * ary2d)]. life value: #( (0 1 1 1 0) (0 1 0 0 0) (0 0 1 0 0) (0 0 0 0 0) (0 0 0 0 0)). "=> #( (0 1 1 0 0) (0 1 0 1 0) (0 0 0 0 0) (0 0 0 0 0) (0 0 1 0 0)) " cells := (1 to: 500) collect: [:row | (1 to: 500) collect: [:cell | #(0 1) atRandom]]. [500 timesRepeat: [cells := life value: cells]] timeToRun "=> 267282(msec) "
532 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 20:45:17.23 ] >>531 をRubyに翻訳してみた版。1.9だが50世代に4分以上かかってしまう。 翻訳の手間を省くのにArray#*,#+を置き換えちゃったのが足を引っ張ったか? require "benchmark" class Array def *(x); zip(x.kind_of?(Array)?x:Array.new(size,x)).map{|e|e.reduce(&:*)} end def +(x); zip(x.kind_of?(Array)?x:Array.new(size,x)).map{|e|e.reduce(&:+)} end end def life(ary2d) sum = ary2d * 0 (-1..1).each{ |dx| (-1..1).each{ |dy| sum += ary2d.map{ |row| row.rotate(dx) }.rotate(dy) } } survivs = [3,4].map{ |alive| sum.map{ |row| row.map{ |cell| (cell == alive)?1:0 } } } survivs.first + (survivs.last * ary2d) end p life([ [0,1,1,1,0], [0,1,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]]) #=> [[0,1,1,0,0],[0,1,0,1,0],[0,0,0,0,0],[0,0,0,0,0],[0,0,1,0,0]] cells = (1..500).map{ (1..500).map{ [0,1].sample } } p Benchmark.measure{ 50.times{ cells = life(cells) } }
533 名前:デフォルトの名無しさん mailto:sage [2012/04/25(水) 22:15:29.46 ] 1.6GHz Core i5で2分 import qualified Data.Vector.Unboxed as V import qualified Data.List as L import System.Random.Mersenne data Lattice = Lattice! Int Int (V.Vector Int) (!) (Lattice m n v) (i,j) = v V.! (n * mod i m + mod j n) next b i j = case (sum xs, b ! (i,j)) of (3, _) -> 1 (4, 1) -> 1 (_, _) -> 0 where xs = [b ! ((i+m),(j+n)) | m <- [-1,0,1], n <- [-1,0,1]] updateBoard board@(Lattice m n v) = Lattice m n $! V.fromList [next board i j | i <- [0..m-1], j <- [0..n-1]] randomBoard rs x y = Lattice x y $ V.fromList $ take (x * y) rs main = do rs <- newMTGen Nothing >>= randoms let board = randomBoard (map (`mod` 2) rs) 500 500 print $ L.foldl' (\x _ -> updateBoard x) board [1..500]
534 名前:533 mailto:sage [2012/04/25(水) 22:20:37.27 ] instance Show Lattice where show (Lattice m n v) = concat $ snd $ L.mapAccumL (\i x -> if i == n-1 then (0, show x ++ "\n") else (i+1, show x)) 0 $ V.toList v lattice xss = Lattice n m $ V.fromList $ concat xss where n = length xss m = length (concat xss) `div` n > updateBoard $ lattice [[0,1,1,1,0], [0,1,0,0,0], [0,0,1,0,0], [0,0,0,0,0], [0,0,0,0,0]] # 出力 01100 01010 00000 00000 00100
535 名前:デフォルトの名無しさん mailto:sage [2012/04/26(木) 20:54:15.37 ] (_, _) (`mod` 2) (\x _ ->
536 名前:デフォルトの名無しさん mailto:sage [2012/04/26(木) 20:56:38.97 ] 最近Lispさんを見かけないけどもう廃れちゃったの?
537 名前:デフォルトの名無しさん mailto:sage [2012/04/26(木) 21:25:38.01 ] 言語仕様を共通にするというトレンドは終わった 個別の実装は始まってなかった
538 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 01:17:14.79 ] Rで life <- function(ary2d) { sum <- rbind(ary2d[ncol(ary2d),], ary2d[-ncol(ary2d),]) + ary2d + rbind(ary2d[-1,], ary2d[1,]) sum <- cbind(sum[,nrow(sum)], sum[,-nrow(sum)]) + sum + cbind(sum[,-1], sum[,1]) ifelse(sum == 3 | (ary2d == 1 & sum == 4), 1, 0) }
539 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 08:45:31.15 ] >>536 2chで世間が判った気になり始めたら色々ヤバイな。
540 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 10:14:19.97 ] >>538 500x500 500世代で測ったら 1.8GHz Core i7 で 68秒だった。けっこう速いね。
541 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 11:00:18.10 ] ライフゲームで関数型とオブジェクト指向の何を比較したいんだろう? >>525 は次世代を返す関数としてるけどオブジェクト指向側は lg = new lifegame(500,500); for(i=0;i<500;i++)lg.life(); console(lg); って感じでいいの? そうしないと関数型 vs 手続き型みたいなことになるよね
542 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 11:37:20.76 ] 例えばF#とC#を比較したら関数型言語と手続き型言語の比較になる 本物のOOは言語に依存しない 関数型言語と対立するようなOOは偽物
543 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 12:00:12.21 ] >>541 ライフゲームは単純だけどパラダイムの特徴をかろうじて出せるくらいの規模はあるんじゃない? お題にあるlifeという関数名(メソッド名)にこだわらなくていいと思うよ。 要は小さな例での正常動作と、500x500セル 500世代(必要なら50世代とかに軽減して) にどのくらいかかるかが示せていればOKかと。
544 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 12:17:25.49 ] >>543 規模の大きさは良いと思うけど、 データの破壊的操作ができると有利な御題のほうが 違いが出て良いと思った Haskellで配列使ったバージョン import Data.Array life ary = array ((1,1),(x,y)) [((i,j), f i j) | i <- [1..x], j <- [1..y]] where (x,y) = snd $ bounds ary f i j = let n = sum [ary ! (g x (i+a), g y (j+b)) | a <- [-1,0,1], b <- [-1,0,1]] in if n == 3 || (n == 4 && ary ! (i,j) == 1) then 1 else 0 g x i = if i < 1 then x else if i > x then 1 else i
545 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 14:36:04.79 ] javascriptで書いてみた。破壊的操作有りで。 ソースの長さ汚さは勘弁してください。 ideone.com/xNY9J ※↑は5秒制限のため500回でなく1回だけ lg.life(500); console.log("life500:" + (new Date()-st) + " msec"); に書き換えてから windows版node.js(pen4 2.6GHz)でやったら30秒くらいだった。 >node.exe life.js 0,1,1,1,0 0,1,0,0,0 0,0,1,0,0 0,0,0,0,0 0,0,0,0,0 --------------- 0,1,1,0,0 0,1,0,1,0 0,0,0,0,0 0,0,0,0,0 0,0,1,0,0 --------------- create :39 msec life500:29794 msec
546 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 20:27:45.31 ] てきとーにCで書いてみた 500回はさすがに秒数制限に引っかかったけど、50回で0.69秒 ideone.com/a7mH5
547 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 22:35:14.09 ] F# 2.6GHz Core2Duo 500世代で2分57秒 let life (field : int[,]) = let height, width = field.GetLength 0, field.GetLength 1 field |> Array2D.mapi (fun y x c -> let s = seq { y - 1 .. y + 1 } |> Seq.sumBy (fun y' -> seq { x - 1 .. x + 1 } |> Seq.sumBy (fun x' -> field.[(y' + height) % height , (x' + width) % width])) match s, field.[y, x] with 4, 1 | 3, _ -> 1 | _ -> 0)
548 名前:デフォルトの名無しさん mailto:sage [2012/04/27(金) 22:37:08.83 ] 手続き型言語F#で書くと>>547 と同じ環境で500世代9秒 let life (field : int[,]) = let height, width = field.GetLength 0, field.GetLength 1 let result = Array2D.zeroCreate height width for y = 0 to height - 1 do for x = 0 to width - 1 do let mutable s = 0 for y' = y - 1 to y + 1 do for x' = x - 1 to x + 1 do s <- s + field.[(y' + height) % height, (x' + width) % width] result.[y, x] <- match s, field.[y, x] with 4, 1 | 3, _ -> 1 | _ -> 0 result
549 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 00:03:43.28 ] OOPならセルごとにオブジェクトで、と思ったが、 仕様が全状態の配列から配列への変換なのね。
550 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 00:54:50.29 ] >>549 べつにこだわらなくてもいいでしょ。組みやすいように組めば。 要は小さな例での動作確認出力結果と、 500x500セル 500世代(必要なら50世代とかに軽減して)の計測結果を示せればOK。
551 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 04:39:34.80 ] まあ出題者が関数的なアタマなんだろう
552 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 06:37:42.91 ] セルごとにオブジェクトとかねぇよww
553 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 07:45:09.18 ] 問題領域がどこかわかれば何処をオブジェクトにしたら良いか分かるよ
554 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 09:32:38.01 ] なかなか面白いじゃないか。 オブジェクト指向で設計されたライフゲーム、頼む。
555 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 09:44:59.90 ] この題じゃ>>541 くらいにしかならんだろ オブジェクト指向をどういうもんだと思ってんだよw
556 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 10:37:13.10 ] セル毎にオブジェクトか、面白そうだしちょっとやってみるかな
557 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 10:51:25.73 ] セル毎にオブジェクトってこんなの?(コードはPython) class Cell(object): def __init__(self, alive): self.neighborhood = [] self.alive = alive def evaluate(self): s = sum(x.alive for x in self.neighborhood) self._alive = 1 if s == 3 or (s == 4 and self.alive == 1) else 0 def update(self): self.alive = self._alive 全部は長いのでこっち ideone.com/3WKkG
558 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 11:05:27.26 ] 8coreのXeonマシンでOpenMP使ってCのコードを並列化したら 500*500の500世代で1秒切ったわw
559 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 12:11:25.24 ] >>557 他スレで遊んでる内に作られてしまった…
560 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 12:13:20.34 ] >>552 ライフゲームは生物が単純だから変に思えるかもしれないけど、 これがゲームのキャラクターと考えればごく普通の考え方。 ライフゲームはどの生物も同じ能力だけど、セルがオブジェクトなら 実際の生物みたく、オブジェクトごとに能力を変えることだって出来る というかそういうゲームがあったね。 マルチプレイヤー・ネットワーク・ゲームTerrarium www.atmarkit.co.jp/fdotnet/wwebserv/wwebserv010/wwebserv010-001.html > プレイヤーは各自プログラミングした動物を持ち寄り、フィールド上で動物同士を戦わせる。
561 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 12:23:40.64 ] やっぱりオブジェクト指向だと規模が大きくなる。 逆に言えば、規模が大きい場合は オブジェクト指向が有利ってことか。
562 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 12:42:19.17 ] 大規模で全貌の把握がしづらいものを 個々人では把握できないままでも比較的扱いやすいのがOOPLだと思ってる
563 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 12:57:03.02 ] 全体を統一しづらい規模になると言語は一つではなくなる Objective-C++/CLIのような状態
564 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 16:19:14.44 ] >セルがオブジェクトなら >実際の生物みたく、オブジェクトごとに能力を変えることだって出来る 大抵のOOPLにはマルチメソッドすらないのに、 良くそんな大口たたけるな。
565 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 16:24:25.86 ] 無いのはマルチメソッドを実現するための言語仕様であって、 マルチメソッド自体は実装できるからね。
566 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 16:25:24.90 ] >>564 突然何言い出してんのこの子(´・ω・`)
567 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 16:28:06.39 ] ホーミングミサイルの話でボコボコにされたやつだ。 気にすんな
568 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 18:10:20.59 ] >>565 関数型言語でも実装できる パラダイムじゃなく言語間の比較スレなんだから そんなこと言っても意味ない
569 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 18:15:28.58 ] >>561 仮に「OOPだと規模が大きくなる」が真だとしても そこから「規模が大きいとOOPは有利」は導けない
570 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 18:53:58.34 ] 静的型付けの割に簡潔に書けて、かつ型チェックも厳しくやってほしい こういうニーズに関数型言語が応えてるから使ってるだけで、 関数型言語使ってる奴が皆OOを嫌ってるわけでも 設計レベルで使わないわけでもないんよ 争いは不毛だ
571 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 19:06:33.77 ] > 静的型付けの割に簡潔に書けて、かつ型チェックも厳しくやってほしい なんとなくC#を思いだしたけどC#で書く人いないね
572 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 19:31:55.12 ] 争わなかったらスレの存在意義がないだろ
573 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 20:25:37.43 ] >>571 C#のジェネリックってダックタイピングできないんでしょ?簡潔かなぁ。
574 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 20:41:49.41 ] >>560 ライフゲームのセルっていう文脈だからねぇよって言ったわけで ゲームのキャラクターのオブジェクト化まで否定はしてねぇよw >>564 またホーミングの子www
575 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 21:39:52.98 ] >>570 Scalaがそう。 静的言語で、簡潔に書けることを 証明した言語。
576 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 21:45:24.53 ] >>575 このスレでまだ一回もScala出て来てないぞ ライフゲームで良いからコードで証明してみてくれ
577 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 23:03:24.87 ] 「Scalaは簡潔に書けると証明した」=>「じゃあチョット書いてみて」=> 逃亡 どんなコントだよwww
578 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 23:11:10.96 ] ん? Scala知らないの?
579 名前:デフォルトの名無しさん mailto:sage [2012/04/28(土) 23:31:57.42 ] Scala待ちの間にw、Squeak Smalltalkでセルがオブジェクト版。(要クラスブラウザ) 細かい違いを無視すれば Python の >>557 とほぼ同じ方針。 Object subclass: #Cell instanceVariableNames: 'neighbors next' Cell >> setBit: int neighbors := OrderedCollection with: int Cell >> collectNeighborsAt: pos in: array2D neighbors addAll: (#(-1 0 1) gather: [:dx | #(-1 0 1) collect: [:dy | (array2D atWrap: (pos y + dy)) atWrap: (pos x + dx)]]); remove: self Cell >> calcNext next := (neighbors inject: 0 into: [:sum :neigh | sum + neigh value]) caseOf: {[3]->[1]. [4]->[self value]} otherwise: [0] Cell >> update neighbors at: 1 put: next Cell >> value ^neighbors first Cell >> printOn: stream self value printOn: stream Cell class >> newWith: bitInt ^self new setBit: bitInt; yourself Cell class >> newLatticeFrom: array2D | lattice | lattice := array2D collect: [:row | row collect: [:bit | Cell newWith: bit]]. ^lattice doWithIndex: [:row :y | row doWithIndex: [:cell :x | cell collectNeighborsAt: x@y in: lattice]]; yourself Cell class >> updateLattice: array2D ^array2D do: [:row | row do: #calcNext]; do: [:row | row do: #update] | lattice | lattice := Cell newLatticeFrom: {{0. 1. 1. 1. 0}. {0. 1. 0. 0. 0}. {0. 0. 1. 0. 0}. {0. 0. 0. 0. 0}. {0. 0. 0. 0. 0}}. Cell updateLattice: lattice. "=> {{0. 1. 1. 0. 0}. {0. 1. 0. 1. 0}. {0. 0. 0. 0. 0}. {0. 0. 0. 0. 0}. {0. 0. 1. 0. 0}} "
580 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 00:22:22.02 ] 純粋な関数型言語って、参照するたびに値が変化する変数みたいなのは作れるの? たとえば乱数とか、参照した時点の現在時刻を値として持ってる変数とか
581 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 00:31:18.37 ] >557をscalaでベタ移植してみた。 case class Cell(var alive:Int) { var neighborhood = List[Cell]() var alive_ = 0 def evaluate() { val s = neighborhood.map(_.alive).sum alive_ = if(s == 3 || s == 4 && alive == 1) 1 else 0 } def update() { alive = alive_ } } case class Board(val lattice:List[List[Int]]) { val cells = lattice.map(_.map(x => Cell(x))) val m = lattice.size; val n = lattice(0).size for(i <- 0 until m; j <- 0 until n; k <- -1 to 1; l <- -1 to 1) cells(i)(j).neighborhood ::= cells((i+k+m)%m)((j+l+n)%n) def life() { cells.foreach(_.foreach(_.evaluate)) cells.foreach(_.foreach(_.update)) } override def toString() = { cells.map(_.map(_.alive.toString).reduce(_ + "," + _)).reduce(_ + "\n" + _) } } val board = Board(List(List(0,1,1,1,0),List(0,1,0,0,0),List(0,0,1,0,0),List(0,0,0,0,0),List(0,0,0,0,0))) board.life print(board) scalaの機能を余り活用できていない感じ。
582 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 01:14:20.15 ] これで静的型付け言語なんだぜ。 val msg = if (true) "true dayo" else "false dayo"
583 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 01:27:13.41 ] せっかくなのですべてのセルが並行に動くように>581を修正 case class Cell(var alive:Int) extends Actor { var neighborhood = List[Cell]() def act() = { neighborhood.foreach(_ ! alive) var count = 0; var s = 0 loopWhile(count < neighborhood.size) { receive { case i:Int => s += i; count += 1 } } andThen { alive = if(s == 3 || s == 4 && alive == 1) 1 else 0 } } } case class Board(val lattice:List[List[Int]]) { val cells = lattice.map(_.map(x => Cell(x))) val m = lattice.size; val n = lattice(0).size for(i <- 0 until m; j <- 0 until n; k <- -1 to 1; l <- -1 to 1) cells(i)(j).neighborhood ::= cells((i+k+m)%m)((j+l+n)%n) def life() { cells.foreach(_.foreach(_.start)) } override def toString() = cells.map(_.map(_.alive.toString).reduce(_ + "," + _)).reduce(_ + "\n" + _) } val board = Board(List(List(0,1,1,1,0),List(0,1,0,0,0),List(0,0,1,0,0),List(0,0,0,0,0),List(0,0,0,0,0))) board.life print(board) evaluate/updateの分割が不要になったので少し短くなったか
584 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 01:30:58.02 ] これで静的型付け言語なのか。 本当に短いコードは動的型付け言語だけの特権じゃないことを 証明してしまったな。
585 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 02:11:32.74 ] ただ静的型にしては遅いよね。 500x500 500世代で動的な >>579 が 112秒なのに、>>581 は 196秒。
586 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 02:18:22.73 ] >>585 それ事前コンパイルしてないだろ?
587 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 02:35:44.97 ] >>583 これって一回のlifeのコール後、 すべてのセルがアップデートを終えるのをどこで待ち合わせているの?
588 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 06:27:13.54 ] >>582 そんなんで感動できるとか何時の時代の人? OCaml : let msg = if true then "true" else "false" Haskell : let msg = if True then "true" else "false"
589 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 06:30:26.82 ] どうせ、RubyとかLLばっかり使ってる人だろw
590 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 07:52:20.17 ] C++,C#にも導入されたね C++11 : auto msg = true ? "true dayo" : "false dayo"; C#(3.0) : var msg = true ? "true dayo" : "false dayo";
591 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 08:14:29.69 ] 最近どんどん動的型付け言語の メリットがなくなっていくね。
592 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 08:47:25.44 ] >>590 …それでmsgの型を推論しろってか。
593 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 09:24:13.53 ] >>591 この戦いが終わったら全ての武器のメリットがなくなるんだ
594 名前:デフォルトの名無しさん mailto:sage [2012/04/29(日) 09:42:55.39 ] 機械語のメリットがなくなってゆくね、とか言ってる奴の同類だよなぁw