[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 2chのread.cgiへ]
Update time : 05/14 13:02 / Filesize : 255 KB / Number-of Response : 780
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

【激突】関数型言語 VS オブジェクト指向言語2



1 名前:営利利用に関するLR審議中@詳細は自治スレへ mailto:sage [2012/04/07(土) 21:26:47.61 ]
一般的には、オブジェクト指向型言語が優勢でが
一部には関数型言語を崇拝している人もいます

どちらが上なのか、この際はっきりさせましょう

前スレ toro.2ch.net/test/read.cgi/tech/1331328955/

449 名前:デフォルトの名無しさん mailto:sage [2012/04/15(日) 21:48:54.81 ]
C#作った奴らはvoidを型と思っていなかった。
だから、C#じゃクロージャ作るのに引数や戻り値にvoidがあると作れないw
やるには予めデリゲートを定義しなきゃならん。
クロージャを使うのを考えさせられる。
ありえん。手軽さが全然ない。

F#はローカル変数(厳密には違うが)を定義するのもクロージャを定義するのも同じ手間しかかからない。
クロージャをバンバン使っていけるのでクロージャの応用もどんどん閃ける。
F#やった方がC#が上手くなるという現実。
C#はやればやるほど馬鹿になる言語。

450 名前:デフォルトの名無しさん mailto:sage [2012/04/15(日) 21:50:04.90 ]
速度やメモリ・言語ごとの風習で最適かどうかは変わるのだろうけれど、
関数型でOOPをするときは、返り値として変更したオブジェクトを返すより、新たなオブジェクトを返したほうが関数型ぽいのかね?

451 名前: ◆QZaw55cn4c mailto:sage [2012/04/15(日) 21:51:05.55 ]
>>447
F#のことも思い出してあげてください

452 名前:デフォルトの名無しさん mailto:sage [2012/04/15(日) 21:59:08.45 ]
関数型言語でWindowsアプリを開発したいっつー需要がどれだけあるかだな

453 名前:デフォルトの名無しさん mailto:sage [2012/04/15(日) 22:00:17.15 ]
>>442
どちらが糞でどちらが最高かなんて、問い詰められても答えなくていいと思うんだが
沈黙が正解って小学生でも知ってる奴は知ってるだろ

454 名前:デフォルトの名無しさん mailto:sage [2012/04/15(日) 22:54:52.02 ]
>>443
>>443
がんばってみたんですが、糸口がみえてきません。もしよろしければアドバイスをいただけないでしょうか。

>new myInteger(3).fizz() が "Fizz" を返せる

@ これは、「メソッド fizz() が副作用として "Fizz" を出力する」ということですか?
この場合、fizz(), buzz(), gizz() を通過してきて 3 でも 5 でも 7 でもわりきれなかった場合に元の数字を出力する、ということが不可能だと思います。
>>303 では妥協して endl() というメソッドを準備してこの処理を行うしかありませんでした。

A それとも「メソッド fizz() の返り値が String("fizz") であるべき」ということですか?
String にメソッド fizz() を追加したいのであれば、 String から新しいクラスmyString を継承して、そこにメソッドを定義するということだろうと思いますが、
(new myString(3).fizz() が myString("Fizz") を返す)
A-1 java.lang.String は final。
A-2 メソッド fizz() が "Fizz" を返してしまうと、もとの String("3") を忘れてしまい、buzz(), gizz() が処理できない。多値を返したいのですが >>304 で精一杯。
>>304 の toString()#Object をオーバーライドする、ってこういうときには普通にすることだと思っていたんですが、何かまずい問題でもあるのでしょうか?

455 名前:デフォルトの名無しさん mailto:sage [2012/04/15(日) 23:40:26.22 ]
トイプログラムしか書かない奴は言語なんて何でもいいだろw

456 名前:デフォルトの名無しさん mailto:sage [2012/04/15(日) 23:47:29.56 ]
>>443
>>303 の方針でがんばってみました。gizz() は最後に置かなければならない、と決めうちすることにしました。
toro.2ch.net/test/read.cgi/tech/1313183984/194

457 名前:デフォルトの名無しさん mailto:sage [2012/04/15(日) 23:49:17.32 ]
苦しいねぇ



458 名前:デフォルトの名無しさん mailto:sage [2012/04/15(日) 23:50:41.61 ]
>>454
> fizz() が "Fizz" を返してしまうと、もとの String("3") を忘れてしまい、buzz(), gizz() が処理できない

その一見回避不可能な問題を解決する方法を考えるのがこのクイズがクイズたるゆえんです。
言語によっては型システムの制約によりどうやっても実現できないこともあります。

459 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 00:02:21.18 ]
>>450
関数型に限らず、GCのあるOOPLだと
属性変更をせずに新規オブジェクトをサクサク作るやり方も結構使うね

460 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 00:45:51.08 ]
>>454
>>341の方法(元の数値をどこかにメモしておいて適宜参照)はJavaでも使えます。

461 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 01:11:55.59 ]
>>458
OOとPFの言語比較としてこのようなクイズを出したのは、
どのような観点からこれら両者のパラダイムの優劣を比較しようとしたのか
聞きたい

462 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 01:13:44.79 ]
もうこのお題はcloseでいいんじゃないの?
このクイズではせっかくの労力を生産的でないことに費やしている

463 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 01:30:58.12 ]
>>462
クイズなんかそんなもんだろ。しょせん暇つぶし。
つーか、こんな程度のクイズ解くのに「労力」なんか大仰なもん必要か?

464 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 01:38:59.77 ]
このクイズのくだらなさはかなり問題。

465 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 01:48:07.75 ]
くやしいのうw

466 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 02:07:04.82 ]
全然くやしくないぜよ。perlでobjectのnew版も多値版もさらりと書いた。
tieとマクロ使ったのも書こうと思ったけれど手間がもったいなくなってやめた。
パラダイム比較としてもうすこし書く値打ちのあるテーマ出せよ、
このクイズじゃ再帰は使いどころないし
javaのnewだめ静的型システムダメ
何を有利に誘導したいんだか
せめて前スレのpermutationレベルのテーマを出題の下限レベルとしてクレヨ

467 名前:466 mailto:sage [2012/04/16(月) 02:18:35.03 ]
大体fizz buzzってのが下らないんだよ
プログラムプロムナード、ナノピコ教室、Cマガ課題、オイラー4、AIアルゴリズム、OR最適化、
パーサ、マッチング、グラフ問題あたりの
小問題で再帰・高階/部分適用、遅延・カーリー化vsOOの比較できる題材が妥当かもな
step数は2chの1レスに収まるくらいの小問題でいいからサ



468 名前:466 mailto:sage [2012/04/16(月) 02:26:58.99 ]
最悪、基本アルゴリズムの再実装でもいいや
たとえばqsortはperlやhaskellでpivotを適当に選択して再帰した短いコードと
pivot選択くどくど頑張ったCやjavaの長いコード比較してファンクショナルの再帰はマンセーみたいな
サイトがあちこちにあるだろ、
あのレベルでも今回のFizzBuzzGizzよりましだろ

469 名前:466 mailto:sage [2012/04/16(月) 02:35:35.13 ]
あと、言い出しっぺの法則はナシだぞw


470 名前:466 mailto:sage [2012/04/16(月) 02:44:04.67 ]
つか、OOとPFの単純比較って何か意味あるのか?
どのみち記述する言語の特徴または弱点、癖の比較レベルの議論に落ちがちな稀ガス
ズット前スレでヨンだが、意味論的にはOOとPFは相容れない物らしい
しかし生々しい実装レベルではいまんとこ清濁併せ呑んで実現するし
まあいいや寝るか。ノシ

471 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 02:46:25.77 ]
多値使うアイデアはイケてたはずなのに、仕上げの文字列との結合やprintとの併用で
ズル呼ばわりされるわ、Rubyの>>377の挙動も再現できなかったしで散々だったしね。

472 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 02:53:06.66 ]
なぜかC++で挑み続ける俺。
これ以上C++では無理かも。0xだと知らんが。

template< int e, unsigned t >
struct fizzbuzz
{
  int in; std::string out;
  fizzbuzz( int i ):in( i ){ init(); }
  template< int e2, unsigned t2 >
  fizzbuzz( const fizzbuzz< e2, t2 > &r )
    :in( r.in ),out( r.out ){ init(); }
  void init(){ if( in%e ) return;
    unsigned tmp=t; out.append( (char*)&tmp, 4 ); }
  operator const char *(){ return out.c_str(); }
  operator int(){ return in; }
};
typedef fizzbuzz< 3, 'zziF' > fizz;
typedef fizzbuzz< 5, 'zzuB' > buzz;
typedef fizzbuzz< 7, 'zziG' > gizz;

int main()
{
  int     i = (gizz)(buzz)(fizz)1;
  std::string t = (gizz)(buzz)(fizz)15;
  std::string u = (gizz)(buzz)(fizz)105;
  std::string v = gizz((buzz(fizz(105)))); //こうも書けるね
  return 0;
}

473 名前:466 mailto:sage [2012/04/16(月) 02:54:29.65 ]
>>471
あれはね最初に書いたnewはだめって言われて仕方なくの面はあるのよ

$scalar = 関数(関数

と明示的にscalarで主値だけを受けとるように明示するのがホントは作法なんだ。

Rubyの>>377に関しては読んでなかったから挙動の再現にそもそも着手してないよ。
rubyは文法がかなりカオスになって来ちゃって残念だね

474 名前:466 mailto:sage [2012/04/16(月) 02:59:22.51 ]
fizzbuzzgizzはいいんだどうでも。
それより前スレのpermutaion perl版はwebなど参照せず一から考えて書いて
オレなりに結構な自信作だったのに
なんの反応もなかったことの方が寂しかったな

475 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 03:19:21.92 ]
何このスレ

476 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 06:20:08.75 ]
ruby無双をしたかった奴が、もっとエレガントな解を他言語で出されて、
涙目でdisるスレです

477 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 06:53:26.91 ]
Rubyと違う解法が出る度に
必死に難癖付けてて笑ったわww



478 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 08:13:17.85 ]
頭が固くて馬鹿だから
数や文字列に状態持たせる以外の方法が
理解できないんだろう

479 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 08:32:48.03 ]
頭が固くて馬鹿だから
数や文字列に状態持たせる方法が
許容できないんだろう

480 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 08:38:53.99 ]
世の中は状態がある世界なのにねw

481 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 08:50:48.96 ]
じゃあFixnumのインスタンスに特異メソッド定義してみろRuby厨

482 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 09:44:46.42 ]
元ネタのCLのEQLスペシャライザならそういうことできたよな。

Haskellとかでコンストラクタ無しで1以外の引数をとるとコンパイル時に
型エラーになる関数って定義できたっけ?

483 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 10:00:08.87 ]
template< int n > void func(){int i="";}
template<> void func<1>(){}
・・・
func<2>();//エラー

484 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 12:34:04.90 ]
> cat FooTH.hs
{-# LANGUAGE TemplateHaskell #-}
module FooTH where
import Language.Haskell.TH
foo 1 = [| 1 |]
foo _ = error ""

> cat Main.hs
{-# LANGUAGE TemplateHaskell #-}
import FooTH
main = print $(foo 1) -- foo 2 に変えるとコンパイルエラー

485 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 12:50:08.98 ]
>>474
あれ覚えてるよ、実は感心してた
ていうか、このスレでPerlの評価が結構変わったよ(もちろん高い方へ)

でも、読み易さ優先で書いてあれとは
Perl使いとは分かり合えないな...と思ったけどw

486 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 20:25:48.62 ]
>>479
許容はしてるだろう
エレガントさから程遠いと言ってるだけで

487 名前:デフォルトの名無しさん mailto:sage [2012/04/16(月) 22:19:41.52 ]
俺の基準における
エレガントってやつかw



488 名前:285 mailto:sage [2012/04/17(火) 00:46:48.85 ]
正直、あの問題は無いと思うよ
問題があれだし書き捨てだからやったが、実際には絶対にやりたくないな

489 名前:デフォルトの名無しさん mailto:sage [2012/04/17(火) 00:47:44.00 ]
>>487
FizzBuzzすら書けない口だけ野郎の基準よりマシだろwww
お前はこのスレでは最底辺のカスなんだから敬語使えw

490 名前:デフォルトの名無しさん mailto:sage [2012/04/17(火) 00:53:04.36 ]
>>481
ぶっちゃけ>>479のバカが理解できたのが
たまたまRubyのコードだっただけでRuby厨ですらねーと思うぜ
むしろバカにクソコード褒められてRuby可哀想ってなもんだ

491 名前:デフォルトの名無しさん mailto:sage [2012/04/17(火) 00:59:54.74 ]
あの問題出したのぶっちゃけPython使いだと思う(陰謀説)

492 名前:466 mailto:sage [2012/04/17(火) 01:35:17.45 ]
>>491
アレは学部・卒研レベルの課題をここに投げたのかなーと
オレは感じた。(真相はシラネ)
もしかしてオレ様はボクちゃんに利用されたのかなとww

493 名前:デフォルトの名無しさん mailto:sage [2012/04/17(火) 10:56:11.26 ]
F#のスレッドローカル(有り体にはグローバル変数)と同様の方法でSqueak Smalltalkの解。
オープンクラスは使わずにブロック(無名関数)で。

| fb fizz buzz gizz |
fb := [:x :cond :str |
   | p n |
   p := Processor activeProcess.
   (x isKindOf: Integer)
      ifTrue: [p instVarNamed: #env put: (n := x). x := '']
      ifFalse: [n := p instVarNamed: #env].
   (cond value: n) ifTrue: [x, str] ifFalse: [x ifEmpty: [n]]].

fizz := [:x | fb value: x value: [:n | n isDivisibleBy: 3] value: 'Fizz' ].
buzz := [:x | fb value: x value: [:n | n isDivisibleBy: 5] value: 'Buzz'].
gizz := [:x | fb value: x value: [:n | n isDivisibleBy: 7] value: 'Gizz'].

self assert: (fizz value: 1) = 1.
self assert: (fizz value: 3) = 'Fizz'.
self assert: (buzz value: (fizz value: 1)) = 1.
self assert: (buzz value: (fizz value: 3)) = 'Fizz'.
self assert: (buzz value: (fizz value: 5)) = 'Buzz'.
self assert: (buzz value: (fizz value: 15)) = 'FizzBuzz'.
self assert: (gizz value: (buzz value: (fizz value: 105))) = 'FizzBuzzGizz'.
self assert: (buzz value: (gizz value: (fizz value: 105))) = 'FizzGizzBuzz'.

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ならセルごとにオブジェクトで、と思ったが、
仕様が全状態の配列から配列への変換なのね。






[ 続きを読む ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<255KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef