F # - Как лучше разделить целое число на (в основном равные) сегменты? - PullRequest
1 голос
/ 13 июля 2020

У меня есть целое число, которое я хотел бы разделить на список целочисленных «ведер» почти одинакового размера. Некоторые примеры:

  • Разделив 10 на 2, я получу список как «[5; 5] »(5 + 5 = 10), или
  • Разделив 20 на 3, я получу список как« [7; 7; 6] »(7 + 7 + 6 = 20), или
  • Разделив 15 на 4, я получу список как« [4; 4; 4; 3] ”(4 + 4 + 4 + 3), и тому подобное.

    Я написал код, который, кажется, работает нормально, но кажется слишком беспорядочным и его трудно осмыслить: не люблю математику в циклах for; так легко сделать ошибку и / или случайно изменить. Но я не уверен не только в математике. * Я не прошу кого-то предоставить лучший фрагмент кода, скорее я прошу указатели на области, на которые мне следует обратить внимание, чтобы самому научиться делать код лучше.

Ответы [ 2 ]

3 голосов
/ 13 июля 2020

Я думаю, что подход, описанный ниже, подойдет. По сути, я создаю список частных, а затем распределяю 1 единицу остатка по списку, пока он не будет полностью использован.

let integerBuckets total divider =
    let rem = total % divider
    let quo = total / divider
    let dividerList = [1..divider]
    [ for _ in dividerList do yield quo ]  //create list of quotients
    |> List.map2 (+) [for i in dividerList do if i <= rem then 1 else 0] //distribuite remainder

EDIT:

Функцию, описанную выше, можно резюмировать как следует:

let integerBuckets2 total divider =
    let rem,quo = total % divider,total / divider
    [ for i in [1..divider] do yield if i <= rem then quo + 1 else quo ]
0 голосов
/ 13 июля 2020

Я предлагаю вам использовать более ориентированный на данные подход к проблеме разделения заданий для обработки. Если вы храните элементы для обработки в массиве, вы можете управлять ими с помощью функций массива. Вот несколько возможных способов сделать это:

let chunkByChunkCount array chunkCount =
    let chunkSize = 
        (float (Array.length array) / float chunkCount)
        |> ceil
        |> int
    array |> Array.chunkBySize chunkSize

chunkByChunkCount [| 1 .. 15 |] 4
// [|[|1; 2; 3; 4|]; [|5; 6; 7; 8|]; [|9; 10; 11; 12|]; [|13; 14; 15|]|]



let dealIntoChunks array chunkCount =
    array
    |> Array.indexed
    |> Array.groupBy (fun (i, _) -> i % chunkCount)
    |> Array.map snd
    |> Array.map (Array.map snd)

dealIntoChunks [| 1 .. 15 |] 4
// [|[|1; 5; 9; 13|]; [|2; 6; 10; 14|]; [|3; 7; 11; 15|]; [|4; 8; 12|]|]
...