平均以上のリスト内の要素の数をカウントする関数を記述します (簡単にするために整数除算を使用します)。リスト構造の
を使用するだけです!single traversal
私はすでにこれに対する解決策を持っていますが、それはref変数が閉鎖から変更されたことを含みますfoo'。
が満たされたときに機能的に値を渡す方法に 興味がありますか? []
を使用した私の単純なソリューションref:
let foo ls =
let avg = ref 0
let rec foo' xs sumAcc lenAcc =
match xs with
| x'::xs' ->
let s = foo' xs' (x' + sumAcc) (1 + lenAcc)
if x' < !avg then s else s + 1
| [] ->
avg := (sumAcc / lenAcc) //? how to change THIS to functional code ?
0
foo' ls 0 0
編集(3):
パフォーマンスに興味があった...list [1..11000]
`(my solution with REF) 5501: elapsed <00.0108708>`
`(nlucaroni) 5501: elapsed <00.0041484>`
`(kvb) 5501: elapsed <00.0029200>` <-- continuation is fastest
`(two pass solution) 5501: elapsed <00.0038364>`
1.と3.のソリューションは非末尾再帰であるため、
// simple two-pass solution
let foo2pass (xs : System.Numerics.BigInteger list) =
let len = System.Numerics.BigInteger.Parse(xs.Length.ToString())
let avg = List.sum xs / len
(List.filter (fun x -> x >= avg) xs).Length
2つのパスとkvbのバージョンは、大きなリスト、つまり: で動作しますlist [1I .. 10 000 000I]:
(two-pass solution) 5000001: elapsed <00:00:12.3200438> <-- 12 first time
(two-pass solution) 5000001: elapsed <00:00:06.7956307> <-- 6
(two-pass solution) 5000001: elapsed <00:00:09.1390587> <-- 9? WHY IS THAT
(two-pass solution) 5000001: elapsed <00:00:06.8345791> <-- 6
(two-pass solution) 5000001: elapsed <00:00:09.1071856> <-- 9? WHY IS THAT
各ソリューションで 5 回
(kvb tail-recursive) 5000001I: elapsed <00:00:21.1825866> <-- 21 first time
(kvb tail-recursive) 5000001I: elapsed <00:00:14.8113939> <-- stable
(kvb tail-recursive) 5000001I: elapsed <00:00:14.8335997>
(kvb tail-recursive) 5000001I: elapsed <00:00:14.8418234>
(kvb tail-recursive) 5000001I: elapsed <00:00:14.8331327>
の場合list [1I .. 1 000 000I]、kvbのソリューションの方が高速です
(two-pass solution) 500001I: elapsed <00:00:01.8975782>
(kvb tail-recursive) 500001: elapsed <00:00:00.6004453>