なあ、再帰関数好きな人いる? パート3 [転載禁止]©2ch.net

1デフォルトの名無しさん
垢版 |
2015/11/28(土) 18:51:38.86ID:Rc2MJzM/
なあ、再帰関数好きな人いる?
2015/11/29(日) 17:09:26.93ID:BHpn4xqB
>>45
再帰じゃあ、10件程度のソートに控えるという事なんだよな。
2015/11/29(日) 17:29:39.96ID:+8PPW4GA
10件程度のソートならソーティングネットワークによるソーティングが一番速いから
十分少ない要素数に対してはそいつを呼び出して終わりだろ。

書いてないだけだろうけど。
49デフォルトの名無しさん
垢版 |
2015/11/29(日) 20:46:37.54ID:ILoya83o
>>9
俺の見解では、ツリートラバースに再帰を必要とするのはデータ構造に問題があると思うんだよな。
イテレータの実装を考えると再帰はちょっと無理があるんじゃないかと思う。
もちろん出来ないわけではないのだが。
ノードが子ノードを保持するような原始的なデータ構造は良くないのではないか。
50デフォルトの名無しさん
垢版 |
2015/11/29(日) 20:56:36.78ID:ILoya83o
代表的なツリーの一つとしてHTMLがある。
HTMLのフラグメントを切り出し、別のノードの子として加えるような操作を考えるとき、
これはやはりループに軍配が上がると思う。
もちろん、ノードに子ノードを保持するような原始的なデータ構造ではかなりメンドクサイ。
というのもHTMLの一部を切り出す時、ノードの種類によって、ノードの分割や併合が起こる。
再帰と原始的なデータ構造では非常にめんどくさい。
私はこの用途のために直列化ツリー構造というデータ構造を考案した。
(おそらくすでに一般的に使われているとは思うのだが。)
2015/11/29(日) 21:13:17.76ID:TqJ6Jff5
ループは再帰の特別なケースに過ぎない
ループの方が無駄がなく見える事もあるだろう
だが結局はその程度の話だ
2015/11/29(日) 21:25:34.60ID:+8PPW4GA
>>49
> イテレータの実装を考えると再帰はちょっと無理があるんじゃないかと思う。
問題はデータ構造の方じゃなくて言語の方だと思う。
というのも、yieldを持つ言語なら再帰を使ったやり方が最も簡潔に書けるから。

-- language:lua
function traverse(node)
 if node then
  traverse(node.left)
  coroutine.yield(node.value)
  traverse(node.right)
 end
end

co = coroutine.create(traverse)
not_end, value = coroutine.resume(co, node)
53デフォルトの名無しさん
垢版 |
2015/11/29(日) 21:52:31.69ID:ILoya83o
>>52
ちょっとそのやり方で、HTMLの一部をコピペするコード書いてみて。
2015/11/29(日) 22:12:36.39ID:+8PPW4GA
>>53
一部ってのはどういう風に探すのん?
特定の属性を持ってるタグを探す感じ?
2015/11/29(日) 22:23:46.56ID:euqwPPlR
どういう風に探すか後から指定できる感じで。
56デフォルトの名無しさん
垢版 |
2015/11/29(日) 23:04:51.51ID:ILoya83o
>>54
HTMLのコピペがいつ起こるかというと、ユーザーがその操作をした時なので、
そういう前提で設計してはどうでしょうか。
57デフォルトの名無しさん
垢版 |
2015/11/29(日) 23:13:29.23ID:ILoya83o
HTMLをユーザーの直観に適合する形で操作するのは意外と難しいですよ。
HTMLフラグメントの移動なんてどうですかね。
面白い題材だと思うのですが。
2015/11/29(日) 23:27:31.14ID:euqwPPlR
直列化ツリー構造kwsk
2015/11/30(月) 00:13:02.74ID:vNB8BIt6
>>53
書いてはみたけどウェブプログラミング初心者でごめんよ
https://ideone.com/KO4rFy
2015/11/30(月) 11:10:04.73ID:lmaKmArc
>>59
2015/11/30(月) 14:51:10.36ID:+Ls/PK0X
>>52>>53を繰り返しで書ける人はいないみたいだね。
2015/11/30(月) 20:27:21.92ID:lmaKmArc
そういやC++のstd::mapのイテレータとかってどうなってんるのん?
2015/11/30(月) 21:11:57.14ID:9VRs5I4S
>>62
ノードオブジェクトに親を指すポインターもあって愚直に辿ってる。
赤黒木使ってるのが殆どだから、
レスしてる奴もコード読めない奴の方が多いんじゃないかw
2015/12/01(火) 00:02:40.17ID:M545w8lo
赤黒木って難しいよね、結構。
2015/12/01(火) 13:24:08.38ID:wfTLHpyu
データを吐き出す方法として前方イテレートしかしないの前提ならB+木がループでトラバース出来る上に高速なんだけど
挿入と削除を頻繁にするなら、そしてデータがキャッシュに乗り切らない程度に沢山あるなら赤黒木が高速になる
全部キャッシュに乗る程度の小さなデータ数ならAVL木が高速で
更に小さいならベクタ上にヒープ木でも作ればって話になる。
どの構造でも再帰で列挙出来るけど、ループでAVL木や赤黒木のデータを列挙するのは骨だな
2015/12/01(火) 15:00:00.16ID:p3g6QuXB
再帰・ループの相互変換が難しいとかさあ
アルゴリズムの根本的なところ理解してないだけ

恥ずかしすぎるこのスレ
2015/12/01(火) 16:04:55.52ID:M545w8lo
f(0,b)=b+1
f(a,0)=f(a-1,1)
f(a,b)=f(a-1,f(a,b-1))
2015/12/01(火) 16:39:12.55ID:wfTLHpyu
>>66
>>67をループに変換するのは難しくないんだね?
ちょっとやってみせてよ。
2015/12/01(火) 17:10:17.46ID:p3g6QuXB
rubyで書いてくれないとちょっと。
2015/12/01(火) 17:22:48.32ID:wfTLHpyu
>>69
rubyで書いたぞ
http://ideone.com/B1bDnp
2015/12/01(火) 17:26:42.78ID:alJpKlDN
再帰・ループの相互変換が難しいとかさあ
アルゴリズムの根本的なところ理解してないだけ

無能の>>68 は、勉強しろ。
2015/12/01(火) 17:26:51.00ID:UT6gApH3
uyって式も読めないのかな
2015/12/01(火) 17:33:25.45ID:wfTLHpyu
>>71
無能でーすチッスチッス
インターン先はGoogle(技術職8週間、コンパイラを改良するお仕事)でしたが何か?
今The Art of Computer Programmingの英語版の2巻読んでるんだけど
次に読むべき本は何?

>>72
数式から雰囲気掴むことも出来ない重度のアスペだから仕方ない。
2015/12/01(火) 17:39:29.54ID:UT6gApH3
>>73
uyの残した名言

何で出来ているか?というのは愚問過ぎる

例えばそれを「uy」としましょう
「uy」から派性したAやBといった概念から「uy」を辿る事は出来る

例えばこの世界にある「オブジェクト指向」という概念や「量子ビット」といった概念から
「uy」を辿る事が可能なので、
それらで世界が出来ているといった勘違いが可能なのです
でもそれは、一体いくつ「uy」から継承がネストしていて、プログラム等でいえばメソッドが追加されてしまった純粋性のない概念なのでしょうか?
それを知っているのは「uy」だけです

この世界にあるすべての概念は「uy」へと通じているので、
料理人は料理を通じて世界を知り、スポーツ選手はスポーツを通じて世界を知ります

誰も「uy」からは逃げられないんだよ
2015/12/01(火) 17:44:25.62ID:wfTLHpyu
>>74
酉とIDくらい見なさいな

# どうでもいいけど最近障害者3級取ったわ
2015/12/01(火) 17:49:32.14ID:wfTLHpyu
あぁ、俺がuyと同一人物だと勘違いされたのではなく、
uyって人がそういう名言を残したって話か
ごめんごめん
2015/12/01(火) 18:38:14.45ID:UT6gApH3
誰も uy なんかに価値を求めてないのにね
2015/12/01(火) 18:56:25.56ID:wfTLHpyu
でかでかと引用した奴が言うと説得力があるね。
2015/12/01(火) 19:16:25.46ID:UT6gApH3
んでuyちゃんのループ問題はまだ解決しないのかしら
2015/12/01(火) 19:43:22.28ID:M545w8lo
まさにuyがアルゴリズムの根本的なところを理解しているかどうか問われているなw
2015/12/01(火) 19:54:09.54ID:UT6gApH3
それな、今までC++スレ読んでてこいつ頭おかしいなとは思ってたけど実力が問われるよな
2015/12/01(火) 19:58:37.14ID:wfTLHpyu
はてさてuyの実力は如何。

# 俺自身の実力はさておき。
2015/12/01(火) 20:19:08.98ID:UT6gApH3
おせぇな uy
2015/12/01(火) 20:49:22.02ID:M545w8lo
uy自力で頑張ってんのか?
なかなか根性あるじゃないか。
俺ならググって解答見てしまうがw
2015/12/02(水) 00:55:46.45ID:SG5bn8pD
再帰で書かれた超有名な関数をループにするだけの簡単なお仕事なのに
何ですぐに出来ないんだろうね?

# 全然簡単じゃないからです
2015/12/02(水) 02:08:55.48ID:sE+ivAhG
末尾再帰に書き換えてから蓄積引数を中に押し込んでループにするんだよ。
やり方を書いたのだからきっとuyにもできるはず!
2015/12/02(水) 06:47:05.05ID:UkYZlpUx
>>85
普通に悩んだけど再帰なら一瞬でとけんのに
ループじゃまず何のデータ構造を使っていいかわからん。
2015/12/02(水) 08:22:03.59ID:73uUfhWJ
スタックだろ。
再帰とループ+スタックは等価。
理屈ではそうだが実際やるのは結構難しいんじゃね。
2015/12/02(水) 08:50:25.92ID:znqtbEKc
>>70
http://ideone.com/KDSDTc

「この程度」が難しいとか言われても
は? としか思えない

再帰というのは単なるスタック付きのループであって
君たちがどこら辺で躓いているのか理解できないんです
やっぱわからない所がわからない状態なんだろうけど、

つうかSTACKUって知っていますか?
2015/12/02(水) 09:14:47.18ID:znqtbEKc
ちなみにここ一週間のuyの生活は、朝起きて、ネトゲして朝寝る です。

ちょうどいま、起きたところではなく24時間起き続けていたので今から寝る前でした

とあるゲームであと100戦程の対戦をこなし、誰よりも速く称号を獲得しようとしてる最中です
2chのム板なんて頻繁に開いてる暇とかないし結構忙しいんですわ
2015/12/02(水) 09:18:01.80ID:UkYZlpUx
>>89
お見事です。申し訳ありませんでした。
2015/12/02(水) 09:19:02.13ID:UkYZlpUx
自分には分からなかったわ

じゃあ質問なんだけど、再帰は全てスタック+ループで書き換えられるの?
2015/12/02(水) 09:34:55.30ID:UkYZlpUx
連投だけど分かったかも、
再帰で帰ってくるべき値をスタックしておくってことでループ+スタック=再帰なのね
2015/12/02(水) 09:39:29.64ID:SG5bn8pD
>>89
問題のすり替えはいけないな。
俺は「難しくないならやってみて?」って言っただけで
そもそも「再帰のほうがループより圧倒的に簡潔に書けるよね?」って文脈だろ。
君が「難しいから出来るもんならやってみろ」って捉えたかどうかなんざ知らんがおつかれさん
うんうん、言いたいことは分かった。
それで、そのコードのどこら辺が綺麗なの?

ちなみに機械的に変換したのがこちら(rubyじゃなくてごめんよ)
https://ideone.com/XsZh4c
fとhは機械的に変換したという意味では等価だし君のコードとほぼ同じ事をしてるのだけど、
h関数をパッと見て>>69式と等しいって言うのは凄く度胸が居るよね?

>>92
そもそも再帰をどうやってソフトウェア実装してるかというとコールスタック+ジャンプ≒スタック+ループな訳で

# ちなみにスタックの正しいスペルはstack。stackuなんて子は知りませんね。
2015/12/02(水) 09:48:27.56ID:SG5bn8pD
s/69/67/
2015/12/02(水) 10:13:14.24ID:amR8vvu9
>>92
数学的に証明されてる。
2015/12/02(水) 10:15:05.34ID:UkYZlpUx
>>96
そうなのか、、、
ならできるようにならなきゃだな
2015/12/02(水) 11:13:43.91ID:sE+ivAhG
>>92
再帰は機械的にCPSに書き換えることで末尾再帰にできて
そうしたらそれをループに書き換えられる
両方証明されてる
2015/12/02(水) 11:28:01.97ID:SG5bn8pD
>>97
アセンブリ言語によくあるcall系命令の挙動を正確に言えるようになれば
どんな再帰もスタックとループで書けるようになるよ
何しろスタックとループで再帰を表現してるのがcall系命令だからね。

それをそのまま書くとこんな具合に超汚くなるけど。
https://ideone.com/0QXd8O
2015/12/02(水) 12:52:27.49ID:UkYZlpUx
ありがとうございます
2015/12/02(水) 18:34:40.93ID:73uUfhWJ
uyなかなかやるな。
ググって解答見た可能性もあるが、ググれるのも実力のうちだからな。
2015/12/02(水) 20:57:19.51ID:V8iEgN6C
>>90
> ちなみにここ一週間のuyの生活は、朝起きて、ネトゲして朝寝る です。
悲観することはない(してないかもしれないがw)
それも一つの生き方だ
人間の人生などそんなものだ
2015/12/02(水) 22:54:08.11ID:73uUfhWJ
https://ideone.com/upRuBk
アッカーマン関数の展開の様子を書いてみた。
メモリリークあるけど気にしない。
もっとスマートにかけそうな気もするが言語が悪いのかな?
2015/12/03(木) 13:20:12.94ID:lU1L6vf0
誰かループ版と再帰版でベンチマークしてみなよ
2015/12/03(木) 13:56:10.07ID:cYXsvyZR
>>103
俺も書いてみたけど
確かにどう書いてももうちょっとスマートに書ける気がする。
https://ideone.com/BFP2wh
2015/12/03(木) 17:06:18.36ID:Sp77D/ez
>>105
メンドクサイやつだなお前w
2015/12/03(木) 17:30:30.61ID:Sp77D/ez
>>104
ack(3,10)を100回計算させたところ

ループ 3.99秒
再帰 4.50秒

だった。微妙にループが速い。
言語はg++ 最適化あり
2015/12/03(木) 17:54:16.46ID:cYXsvyZR
>>106
でも115行目以降は>>103に比べてスマートじゃない?
アッカーマン関数をより素直に表現している(ように見える)というか。

テンプレートその他がひじょーに面倒臭い事になってるのは認めるよww
2015/12/03(木) 18:28:15.45ID:Sp77D/ez
>>108
まあそうかも。
言語によってはめちゃくちゃ簡潔に書けたりするのかな、気になる。
2015/12/03(木) 19:58:47.04ID:cYXsvyZR
>>109
ちなみに扱ってるのがアッカーマン関数だけだということとか考慮しつつ短く書くとこうなる。
https://ideone.com/ILFKf2
2015/12/03(木) 20:19:17.43ID:Sp77D/ez
>>110
だいぶスッキリした。
でも入れ子構造がなくなっちゃってるのはちょっと寂しいかな。
2015/12/03(木) 22:49:14.77ID:Sp77D/ez
https://ideone.com/hlWWly
んんん、haskell 気持ちいい!
2015/12/04(金) 18:59:19.58ID:abMxFNxB
きっしょ
2015/12/04(金) 20:33:45.20ID:tAWNVevx
んぎもちいいいいいいいいいい
2015/12/05(土) 12:06:08.66ID:kPO9yvRD
気持ち悪い生き物だなこいつは
116デフォルトの名無しさん
垢版 |
2015/12/05(土) 12:08:54.94ID:75VGJDuj
再起関数難しくて苦手だわ
117デフォルトの名無しさん
垢版 |
2015/12/05(土) 12:38:44.60ID:vOhmiziG
おいらも苦手だわ
2015/12/05(土) 12:50:09.98ID:fWHJ2v3J
アッカーマンを知ったばかりで嬉しくてしょうがないんだろうな
俺くらいになるとどうでもよくなるけど
2015/12/05(土) 14:22:16.61ID:3X0n/q/1
さぁ次は竹内関数(たらい回し関数)だ!
2015/12/05(土) 14:24:24.30ID:FIUesRuL
>>118
アッカーマン関数が原始帰納関数でない証明を頼む。
定義がシンプルかつ一般帰納関数になるように
アッカーマンさんが構成したらしいが。
2015/12/05(土) 16:27:08.57ID:fWHJ2v3J
その問題が解けて嬉しかったんだろうな
2015/12/05(土) 22:53:23.45ID:Ij5oOkBB
たらいのループ化と展開の様子誰か頼む
2015/12/07(月) 01:05:16.16ID:OW/BWl2V
なんで自分でやらない?

再帰関数が好きなんだろ?
2015/12/07(月) 02:12:06.27ID:IGEuV37f
2015/12/07(月) 19:27:26.73ID:NCOmGjcr
https://ideone.com/63bZSE

たらいの展開の様子

haskell気持ちEー!

ループ化は誰か頼むわ
2015/12/08(火) 10:04:03.24ID:HiEYAt85
きも
2015/12/10(木) 22:01:50.93ID:ZuWvmJPo
たらいのループ化どうやるかわからん。
2015/12/10(木) 23:27:19.50ID:ZuWvmJPo
んーなんかプログラムカウンタに相当するものをスタックに積まなきゃいけない感じ?
2015/12/11(金) 02:06:03.72ID:6gh0GR4/
https://ideone.com/rO18tw
んーできたっぽい?
コンパイラの吐いたアセンブラとか見ながら書いたからチートしてるけど。
2015/12/11(金) 13:42:03.51ID:Z+QL5bbx
再帰厨はcall命令とjmp命令の違いが分かってから布教してほしい
2015/12/11(金) 18:14:40.60ID:H0NYZxX+
>>130
何言ってるんだ。。
ループで書けば早い、自分でスタック作れば、って言ってるループキチガイに、
命令にもこういうのがあるよ、必要だからあるんだよ。
と教えてあげてはどうだ?
2015/12/11(金) 18:27:07.72ID:FXKTAEC3
>命令にもこういうのがあるよ、必要だからあるんだよ。

だからどうしたとしか。
基地外宗教を布教するなら、自分でするんだね。
2015/12/11(金) 19:01:03.96ID:DIOiIqvd
callとjumpの中間の命令もあるよな。
call使わない奴はいないのか?
2015/12/11(金) 19:02:56.29ID:6gh0GR4/
中間の命令ってなんだよ?
2015/12/11(金) 19:40:32.13ID:DIOiIqvd
>>134
MIPSのjalとjrとか。
callとretに相当。
jal相当すらなくてpcのレジスタ保存命令しかないのもあった。
2015/12/13(日) 22:44:03.31ID:1ET048aA
ツリーのイテレータってどう書くの
誰か頼む
137uy ◆Qawu9.2l1E
垢版 |
2015/12/14(月) 05:58:59.61ID:0uboKikK
まずはこの手のアルゴリズム抽象化でC++使うのをやめろ
効率悪すぎ
138uy ◆Qawu9.2l1E
垢版 |
2015/12/14(月) 06:02:04.72ID:WJU5GahL
ツリーのイテレータっつうか
ゲームプログラミング的にいえばツリー構造のタスクシステム
ゲームプログラミングしてれば普通に書いてるような低レベルの話
2015/12/14(月) 11:28:00.80ID:v4oN6dOD
>>136
ツリーのイテレータの書き方は大きく分けて3種類ある。
一つ目はイテレータ自身に「どのノードを辿ってきたか」って情報を覚えさせておいてそれを用いる方法
イテレータの空間効率がO(log n)になる代わりにサクセッサの時間効率が平均でO(1)になる。
二つ目はイテレータ自身にキーを覚えさせておいて、一旦そのキーを手繰ってから次のノードを手繰り直す方法
イテレータの空間効率がO(1)になる代わりにサクセッサの時間効率がO(log n)になる。
三つ目は木構造の各葉っぱに次の葉っぱへのポインタを書いておく方法
イテレータの空間効率がO(1)、サクセッサの時間効率がO(1)になる代わりに葉要素のサイズがO(1)増える。
2015/12/14(月) 11:57:14.44ID:S7hw1GZs
イテレータってそんなにたくさん使うもんじゃないし、一つ目がいいかな、俺的に。
141uy ◆Qawu9.2l1E
垢版 |
2015/12/14(月) 15:02:59.78ID:WIf5dtaV
それ種類じゃなくて、全部組み合わせて実装したほうが汎用的じゃねーの

class A
  attr_accessor :up , :key , :list , :data
end

最低でも1と3のup listは無ければ木構造にならないだろ
君の考えは prev(up) と next(list) になってる
2015/12/14(月) 16:34:38.86ID:S7hw1GZs
全部組み合わせたほうが汎用的?
何を言ってるかよくわからん
143uy ◆Qawu9.2l1E
垢版 |
2015/12/14(月) 21:12:22.29ID:WIf5dtaV
まず、ツリーにしたらそれはイテレータとは呼ばないから
ただのツリーを走査する為の関数に過ぎない

「イテレータ」にしか使用できないツリーじゃなくて
一通りの事に使用できるツリークラス作れば?って話
2015/12/14(月) 21:30:28.83ID:lwFUcSQC
function NodeIterator(node, childNodesName) {
  this._stack = [node];
  this._name = childNodesName;
}
NodeIterator.prototype.hasNext = function() {
  return this._stack.length > 0;
}
NodeIterator.prototype.next = function() {
  var node = this._stack.pop();
  if (node) {
    for (var i = node[this._name].length -1; i > -1; --i) {
      this._stack.push(node[this._name][i]);
    }
  }
  return node;
}

ノードの親や深さも欲しい時は、スタックに積むノードをオブジェクトでラップして親の参照や深さを持たせればいいかも
2015/12/14(月) 22:23:44.30ID:S7hw1GZs
uyのイテレータの定義がさっぱりわからん。
俺はC++STLのイテレータを想像しているんだが。
uyの言ってるイテレータはなんのイテレータなんだ?
2015/12/14(月) 23:47:42.33ID:S7hw1GZs
uyが言ってるのはツリーで実装されたイテレータということかな?
俺が言いたいのはツリーを巡回するイテレータなんだが?
2015/12/15(火) 02:12:24.45ID:1v1TladX
コレクションを操作するのがイタレータ
レスを投稿する

5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況