F # головная боль выделения денег - PullRequest
1 голос
/ 14 ноября 2011

У меня один вопрос:

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 сумма в 10% от 1400 долларов составляет всего 140 долларов, что меньше 250 долларов, но, поскольку у каждой из Сторон А и В есть только по 500 долларов, следовательно, остается еще 400 долларов, так что Сторона С может иметь минимальную сумму 250 долларов. Если у вас есть хорошая идея, пожалуйста, покажите мне свой код. Спасибо, John

Ответы [ 2 ]

2 голосов
/ 14 ноября 2011

Как насчет этого (см. Встроенные комментарии для описания алгоритма):

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|]

(Я не совсем уверен, откуда вы взяли 500 долларов, выделяемых стороне A & B в вашем примере, но я считаю, что алгоритм, который я представил, является разумным подходом к проблеме, насколько я понимаю)

1 голос
/ 15 ноября 2011

Я новичок в 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|]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...