2011-11-13 6 views
1

私は一つの質問があります。F#のお金の配分頭痛

let totalAmount = 1400.0M 
let allocations = [| 0.45M; 0.45M; 0.1M |] 
let minAmount = 250.0M 

は、の3つの者に割り当てるために$ 1400があると仮定してみましょうを、割り当てる最小量は$ 250。各当事者は総額の割合が異なります。ここでパーティーA & Bは合計金額の45%を得、パーティCは10%を得るでしょう、割り当てられた金額は最小金額の回数でなければなりません。 私は結果を取得するための関数を書きたい:

let allocated = [| 500.0M; 500.0M; 250.0M |] 

をしかし、私は機能のための良い方法を把握することはできません。問題は次のとおりです:パーティCでは、$ 1400の10%の金額は$ 140未満で、$ 250未満ですが、パーティAとBはそれぞれ$ 500しかないので、まだ$ 400残っています。最低額は250ドルです。 良いアイデアがある場合は、コードを表示してください。 おかげで、この(アルゴリズムの説明については、インラインコメントを参照)について ジョン

+3

だから、 '割り当てられた[n]は'です複数の'' alloc [n] * totalAmount'に可能な限り近い['n]'を割り当てる '' minAmount'?あなたが求めていることを伝えるのは難しいです。 –

答えて

1

私はF#に初心者です。これはF#の問題を解決するための私の最初の試みです。ちょっとそれは

コード作品:

let HandOutMoney (totalAmount:decimal) (allocations:decimal[]) (minAmount:decimal) = 
    let possibleMinimumAllocations (int) = totalAmount/minAmount 
    let allocateMoney = allocations |> Array.map(fun p -> p * totalAmount/minAmount) |> Array.map int |> Array.map(fun x -> if x = 0 then 1 else x) |> Array.map decimal 
    let finalallocateMoney = allocateMoney |> Array.map(fun p -> p * minAmount) 
    finalallocateMoney 

入力値:

let totalAmount = 1400.0M 
let allocations = [| 0.45M; 0.45M; 0.1M |] 
let minAmount = 250.0M 

出力:

HandOutMoney totalAmount allocations minAmount 

val it : decimal [] = [|500.0M; 500.0M; 250.0M|] 
+0

ありがとうございます! コードが正常に機能しています! 私は機能しない方法を見つけましたが、あなたのコードは良く見えます、私はあなたのコードを使用します。 あなたの親切な助けをもう一度ありがとう! John –

+0

うれしい。私は助けることができた。 F#:D – swapneel

2

方法:

let handoutMoney totalAmount allocations minAmount = 
    //the general approach is to start off giving each party the 
    //minAmount, and then from there dividing up the remaining 
    //totalAmount proportionally by allocation for those parties 
    //that have not exceeded their original allocation 

    //with respect to minAmount, map under-allocated as Some, 
    //and over-allocated as None 
    let underAllocated = 
     allocations 
     |> Array.map (fun pct -> 
      if pct * totalAmount > minAmount then Some(pct) else None) 

    //Sum all the under-allocated percentages, we will use this 
    //to recalculate percentages for remaining allocations beyond 
    //the minAmount 
    let remainingAllocationTotal = 
     underAllocated 
     |> Array.sumBy (function | Some(pct) -> pct | None -> 0.0M) 

    //Now using the remainingAllocationTotal we can adjust the 
    //underAllocated allocations so that the remaining amount 
    //after the min amount is subtracted can be proportionally allocated 
    let remainingAllocations = 
     underAllocated 
     |> Array.map (function 
      | Some(pct) -> (pct/remainingAllocationTotal) 
      | None -> 0.0M) 

    //the amount leftover from the totalAmount after the subtracting 
    //the minAmount which was given to each party 
    let remainingAmount = 
     totalAmount - (minAmount * decimal allocations.Length) 

    //tie it all together: add the minAmount to the remainingAllocation 
    //pct times the remainingAmount 
    remainingAllocations 
    |> Array.map (fun pct -> 
     minAmount + (pct * remainingAmount)) 

は、次にあなたの例与えられた私たちは持っていると思います:

> handoutMoney totalAmount allocations minAmount;; 
val it : decimal [] = 
    [|575.00000000000000000000000000M; 575.00000000000000000000000000M; 250.0M|] 

を(私はしませんよ本当にあなたの例では、パーティーA & Bに割り振られた500ドルを思い付いたのは確かですが、私が提示したアルゴリズムは、私が理解しているように問題に合理的にアプローチしていると信じています)

+0

こんにちは、 あなたの説明とコードをありがとうございます。 しかし、私は割り当てられた資金をminAmountの整数倍にする必要があります。パーティA&Bのあなたの機能の結果は$ 575、$ 575/$ 250 = 2.3です。したがって、それは私が欲しいものではない、私はパーティーA&Bが$ 500/$ 250 = 2であり、$ 2が整数であることを望む。 答えを見つけるのは簡単ではないようです。私は最初にそれを理解するために非機能的な方法を使用しようとし、次に機能的な方法を使用しようとします。 –