トピック:雑談.fs
コメント

- 2:いげ太
- 2008/06/09 14:33
forum
すべての文字を各一回使ってできる文字列のパターン
http://code.nanigac.com/forum/view/275
let
let
>
-
val
=

- 3:T_GYOUTEN
- 2008/06/12 21:08
はじめまして、いげ太さんのブログ読ませてもらってます。
let
でいかがでしょう。

- 4:いげ太
- 2008/06/12 23:16
うお~すげぇ!さくっとワンラインで、効率的かつわかりやすい!!
そうか。ネストさせればよかったんですね。レスありがとうございます!
ちなみに、内包表記を展開してみるとこうですね。
let popped lst = List.map (fun i -> (i, List.filter ((<>) i) lst)) lst;;

- 5:いげ太
- 2008/06/13 11:32
T_GYOUTEN
let all_comb lst =
let rec all_comb' lst =
match snd << List.hd <| lst with
[] -> List.map (List.rev << fst) lst
| _ -> [ for l1, l2 in lst ->>
[ for x in l2 -> (x::l1, [ for y in l2 when x <> y -> y ]) ]]
|> all_comb'
in
all_comb' [([], lst)];;
効率を考えるなら 
- 6:T_GYOUTEN
- 2008/06/15 09:28
私もforum
let

- 7:いげ太
- 2008/06/22 21:44
>6
といっても、おおまかな流れしかわかってませんが(汗汗
let all_comb lst =
let rec sub_all_c lh lt ltremain res =
printfn "%A - %A" res lh; // -> 再帰の流れを観察する
if lt = [] then res @ [lh]
else
match ltremain with
| [] -> res
| h :: t ->let t_l = [for j in lt when j <> h -> j] in
let t_r =sub_all_c (lh@[h]) t_l t_l res in
sub_all_c lh lt t t_r
in
sub_all_c [] lst lst [];;
let _ = all_comb [0..2];;
print >5

- 8:いげ太
- 2008/06/22 22:34
あっ。わかりにくいところがあったかもしれないので補足させてください。
いきなり深さ優先探索とか幅優先探索とか言い出しましたが、これは、forum
ちなみに、all_comb
[] -+- [0] -+- [0; 1] -+- [0; 1; 2] - [0; 1; 2; 3]
| | +- [0; 1; 3] - [0; 1; 3; 2]
| |
| +- [0; 2] -+- [0; 2; 1] - [0; 2; 1; 3]
| | +- [0; 2; 3] - [0; 2; 3; 1]
| |
| +- [0; 3] -+- [0; 3; 1] - [0; 3; 1; 2]
| +- [0; 3; 2] - [0; 3; 2; 1]
|
+- [1] -+- [1; 0] -+- [1; 0; 2] - [1; 0; 2; 3]
| | +- [1; 0; 3] - [1; 0; 3; 2]
| |
| +- [1; 2] -+- [1; 2; 0] - [1; 2; 0; 3]
| | +- [1; 2; 3] - [1; 2; 3; 0]
| |
| +- [1; 3] -+- [1; 3; 0] - [1; 3; 0; 2]
| +- [1; 3; 2] - [1; 3; 2; 0]
|
+- [2] -+- [2; 0] -+- [2; 0; 1] - [2; 0; 1; 3]
| | +- [2; 0; 3] - [2; 0; 3; 1]
| |
| +- [2; 1] -+- [2; 1; 0] - [2; 1; 0; 3]
| | +- [2; 1; 3] - [2; 1; 3; 0]
| |
| +- [2; 3] -+- [2; 3; 0] - [2; 3; 0; 1]
| +- [2; 3; 1] - [2; 3; 1; 0]
|
+- [3] -+- [3; 0] -+- [3; 0; 1] - [3; 0; 1; 2]
| +- [3; 0; 2] - [3; 0; 2; 1]
|
+- [3; 1] -+- [3; 1; 0] - [3; 1; 0; 2]
| +- [3; 1; 2] - [3; 1; 2; 0]
|
+- [3; 2] -+- [3; 2; 0] - [3; 2; 0; 1]
+- [3; 2; 1] - [3; 2; 1; 0]

- 9:T_GYOUTEN
- 2008/06/23 17:00
6についてですが、分かりにくいコードで申し訳ないです。
書いた本人でも時々わからなくなります。もっとすっきり書けないものかと思ってます。
補足説明させていただきます。
リストが与えられた時、最初にlhにどれを選ぶかを設定します。選ばれていないのがltに入ります。lhとltが深さを表します。(ふたつ合わすと全体と一致します。)
よってsub_all_c
それぞれの深さのindex代わりを務めるのが、ltremainで、同じ深さで、横方向(?)の移動に使います。sub_all_c
最後の引数は結果を付け加えていくための、結果保存用の変数です。
深さ方向で選ぶものがなくなった時に res
ちなみに、深さ方向で選ぶものがなくなった時に結果に加える代わりに、深さ方向で、えらぶものが特定の個数になったら、結果に加えて、深さ方向へ進むのをやめると、特定の個数を選んだ順列を取り出す関数に変身します。
例えば次のようになります。
let
これでall_conb2
int
と表示されます。
再帰は奥が深いなーと思っているこの頃です。

- 10:T_GYOUTEN
- 2008/06/23 20:02
蛇足ながら、思いついたことがあったので、付け加えさせてもらいます。
上の9のコードで、[for
[for
組み合わせをリストにくるんで返す関数になります。
let
とすると、
all_comb3
val
=
が返ります。

- 11:T_GYOUTEN
- 2008/06/23 20:20
蛇足の蛇足でもう一つ付け加えさせてください。
リスト6の
match
の部分を
match
と置き換えると、何個かを選んで並べた順列すべてを得る関数となります。
例えば
let
において
all_comb4
val
=
が返ります。
さらに先ほどと同様にh<>jの部分をh<jに置き換えると
0個以上の組み合わせをすべて返す関数ができます。
let
でall_comb5
val
=
となります。

- 12:いげ太
- 2008/06/24 13:00
ご説明どうもです!しかし悲しいかな、全然頭がついていかない…(^^;;
T_GYOUTEN
/// n 個から n 個選んだ順列
let perm_get_n lst =
let rec f (h,t) brd res =
match t, brd with
[], _ -> res @ [h]
| _, [] -> res
| _, x::xs -> let ys = [ for y in t when y <> x -> y ] in
f (h,t) xs (f (h@[x],ys) ys res)
in
f ([],lst) lst [];;
/// n 個から m 個選んだ順列
let perm_get_m lst len =
let rec f (h,t) brd res =
match brd with
_ when List.length h = len -> res @ [h]
| [] -> res
| x::xs -> let ys = [ for y in t when y <> x -> y ] in
f (h,t) xs (f (h@[x],ys) ys res)
in
f ([],lst) lst [];;
/// n 個から m 個選んだ組合せ
let comb_get_m lst len =
let rec f (h,t) brd res =
match brd with
_ when List.length h = len -> res @ [h]
| [] -> res
| x::xs -> let ys = [ for y in t when y > x -> y ] in
f (h,t) xs (f (h@[x],ys) ys res)
in
f ([],lst) lst [];;
/// n 個から m 個選ぶ順列において、可能なすべての順列を得る
let perm_every lst =
let rec f (h,t) brd res =
match t, brd with
[], _ | _, [] -> res @ [h]
| _, x::xs -> let ys = [ for y in t when y <> x -> y ] in
f (h,t) xs (f (h@[x],ys) ys res)
in
f ([],lst) lst [];;
/// n 個から m 個選ぶ組合せにおいて、可能なすべての組合せを得る
let comb_every lst =
let rec f (h,t) brd res =
match t, brd with
[], _ | _, [] -> res @ [h]
| _, x::xs -> let ys = [ for y in t when y > x -> y ] in
f (h,t) xs (f (h@[x],ys) ys res)
in
f ([],lst) lst [];;
> perm_get_n [1..3];;
val it : int list list
= [[1; 2; 3]; [1; 3; 2]; [2; 1; 3]; [2; 3; 1]; [3; 1; 2]; [3; 2; 1]]
> perm_get_m [1..4] 2;;
val it : int list list
= [[1; 2]; [1; 3]; [1; 4]; [2; 1]; [2; 3]; [2; 4]; [3; 1]; [3; 2]; [3; 4];
[4; 1]; [4; 2]; [4; 3]]
> comb_get_m [1..4] 2;;
val it : int list list = [[1; 2]; [1; 3]; [1; 4]; [2; 3]; [2; 4]; [3; 4]]
> perm_every [1..3];;
val it : int list list
= [[1; 2; 3]; [1; 2]; [1; 3; 2]; [1; 3]; [1]; [2; 1; 3]; [2; 1]; [2; 3; 1];
[2; 3]; [2]; [3; 1; 2]; [3; 1]; [3; 2; 1]; [3; 2]; [3]; []]
> comb_every [1..3];;
val it : int list list
= [[1; 2; 3]; [1; 2]; [1; 3]; [1]; [2; 3]; [2]; [3]; []]
もうちょっとにらめっこしてみようかと思います。
- 13:いげ太
- 2008/06/25 23:08
>6
ところで、append
let perm_get_n lst =
let rec f xs ys crr res =
match xs, ys with
_, [] -> crr::res
| [], _ -> res
| x::xs, _ -> let zs = List.filter ((<>) x) ys in
f xs ys crr <| f zs zs (x::crr) res
in
f lst lst [] [] |> List.map List.rev |> List.rev;;
以下のようなコードでベンチマークを取ってみるとわかりよいかと。let benchmark f =
let sw = new System.Diagnostics.Stopwatch() in
sw.Start(); f () |> ignore; sw.Stop();
sw.Elapsed;;
// ex:
// (benchmark (fun () -> perm_get_n [0..7])).ToString();;

- 14:T_GYOUTEN
- 2008/06/26 05:53
ベンチマークとってみました、appendを使う方では 約57.5秒、13では0.16秒
実に360倍ほど違いがありました。へたな場所でappendを使うと、寿命がつきてしまいますね。
私はC#をずっと使ってきて、現在F#を勉強中なのですが、こいつはおもしろいですね。

- 15:いげ太
- 2008/07/06 15:20
クイックソートを書いてみた。Haskell
let rec qsort = function [] -> []
| h::t -> qsort [for x in t when x < h -> x]
@ [h]
@ qsort [for x in t when h <= x -> x];;
あまり速そうに見えない。いや、実際計測したわけじゃないですが、なんとなく。見た目的に。F# もうちょっと実装を工夫したほうがいいのかな?

- 16:いげ太
- 2008/07/17 11:31
マージソートも書いてみた。こんな感じかな。
let msort lst =
let rec marge f = function x::y::ys -> f (x, y) :: marge f ys
| xs -> xs
in
let rec sort = function xs, [] | [], xs -> xs
| x::xs, y::ys when x <= y -> x :: sort (xs, y::ys)
| x::xs, y::ys -> y :: sort (x::xs, ys)
in
let rec msort' = function _::_::_ as xs -> msort' << marge sort <| xs
| xs -> xs
in
match msort' [for x in lst -> [x]] with [] -> [] | x::_ -> x;;

- 17:yuji1982
- 2008/08/09 22:31
何か変なエラー??っぽいのがあるのですが、既知のバグ(?)なのでしょうか?
hubFSとかは、追えてません><
まだ、最新では試せてなく、バージョンは1.9.4.17です。
let
internal
となるのです。
これは……内部エラー(?)だからMSにレポートしろよー、って、ことですよね??
ちなみに
let
だと平気なんですが。

- 18:いげ太
- 2008/08/10 06:07
ほとんど憶測で書きますが。。
(調査に関しては最新の
たとえば、F#
let add (x:T) (y:T) = x + y;;
と書いた場合、let add (x:T) (y:T) = T.op_Addition(x, y);;
と変換されます。しかしながら、int32
let inline (+) (x: ^a) (y: ^b) : ^c =
((^a or ^b): (static member (+) : ^a * ^b -> ^c) (x,y))
when ^a : int32 and ^b : int32 = (# "add" x y : int32 #)
when ^a : float and ^b : float = (# "add" x y : float #)
...
ざっと説明すると、これは引数の型による条件分岐です。つまり、引数の型が (+)
問題は
ここで、対応する演算子である
以上から、僕はこの挙動がバグかもしれないと疑います。
ただ、気になるのはエラー
[参考]
http://research.microsoft.com/fsharp/manual/spec2.aspx#_T...

- 19:いげ太
- 2008/08/30 18:13
>>17
>
CTP
>
バグで正解だったみたいですね(^^

- 20:いげ太
- 2008/09/25 13:36
比較くらいなら慣れの問題で。それぞれ逆向きの演算子があるから困ることもない。
> ((<) 10) 1;;
val it : bool = false
> ((>) 10) 1;;
val it : bool = true
しかし、たとえば割り算ではどうか。> ((/) 10.0) 5.0;;
val it : float = 2.0
(/) > (fun x -> x / 10.0) 5.0;;
val it : float = 0.5
いちいち無名関数を作るのはめんどい。ということで、こんなん用意してみる。> let __ f x y = f y x;;
val __ : ('a -> 'b -> 'c) -> 'b -> 'a -> 'c
するとこう書ける。> (__ (<) 10) 1;;
val it : bool = true
> (__ (/) 10.0) 5.0;;
val it : float = 0.5
placeholder 
- 21:いげ太
- 2008/09/26 13:54
tupled
> let f = FuncConvert.FuncFromTupled (DateTime.ParseExact : _ * _ * _ -> _);;
let f = FuncConvert.FuncFromTupled (DateTime.ParseExact : _ * _ * _ -> _);;
--------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdin(3,9): error FS0041: The method 'FuncFromTupled' is overloaded. Possible ma
tches are shown below (or in the Error List window).
Possible overload: 'static member FuncConvert.FuncFromTupled : ('a * 'b * 'c ->
'd) -> ('a -> 'b -> 'c -> 'd)'.
Possible overload: 'static member FuncConvert.FuncFromTupled : ('a -> 'b) -> ('a
-> 'b)'.
もうちょっと型推論くんにがんばってほしかったりするのですが、こうするしかないのかな。> let f : string -> string -> IFormatProvider -> DateTime =
- FuncConvert.FuncFromTupled (DateTime.ParseExact : _ * _ * _ -> _);;
val f : (string -> string -> IFormatProvider -> DateTime)
というか、('a
前へ 1 次へ![]()
コメントする
[block]から[/block]までの範囲はブロック表示されます。
部分的に目立たせたい時や、引用などにお使いください。
[code]から[/code]までの範囲は等幅表示されます。
ソースコードや設定ファイルの記述などにお使いください。
コメントする権限がありません









たとえば、
popped [0; 1; 2; 3]
[(0, [1; 2; 3]); (1, [0; 2; 3]); (2, [0; 1; 3]); (3, [0; 1; 2])] を作りたい。
list 再帰版 popped lst =
let rec popped' ret fr bk =
match bk with
[] -> ret
| x::xs -> popped' ((x, List.append (List.rev fr) xs)::ret)
(x::fr) xs
in
popped' [] [] lst |> List.rev;;
Seq.unfold 版 popped lst =
Seq.unfold
(fun (fr, bk) -> match bk with
[] -> None
| x::xs -> Some ((x, List.append (List.rev fr) xs),
(x::fr, xs)))
([], lst);;
インデントがズレる...
としたときに、
を得る関数、popped
//
let
//
let
うーん。他にいい方法はないものか。
#