Вот стандартное решение. Это похоже на ответ Лоуренса Гонсалвеса, но имеет два преимущества перед этим ответом. (1) Это единообразно: каждая комбинация из 4 положительных целых чисел, добавляющая до 40, в равной степени может придумать эту схему, и (2) легко адаптироваться к другим итоговым значениям (7 чисел, добавляя до 100 и т. Д.):
import random
def constrained_sum_sample_pos(n, total):
"""Return a randomly chosen list of n positive integers summing to total.
Each such list is equally likely to occur."""
dividers = sorted(random.sample(xrange(1, total), n - 1))
return [a - b for a, b in zip(dividers + [total], [0] + dividers)]
Выводы выборки:
>>> constrained_sum_sample_pos(4, 40)
[4, 4, 25, 7]
>>> constrained_sum_sample_pos(4, 40)
[9, 6, 5, 20]
>>> constrained_sum_sample_pos(4, 40)
[11, 2, 15, 12]
>>> constrained_sum_sample_pos(4, 40)
[24, 8, 3, 5]
Объяснение: существует взаимно однозначное соответствие между (1) 4-кортежами (a, b, c, d)
положительных целых чисел, для которых a + b + c + d == 40
, и (2) тройки целых чисел (e, f, g)
с 0 < e < f < g < 40
, и это легко произвести последним, используя random.sample
. Соответствие задается параметром (e, f, g) = (a, a + b, a + b + c)
в одном направлении и (a, b, c, d) = (e, f - e, g - f, 40 - g)
в обратном направлении.
Если вы хотите неотрицательные целые числа (то есть, разрешая 0
) вместо положительные, то есть простое преобразование: если (a, b, c, d)
- неотрицательные целые числа, суммирующие к 40
, тогда (a+1, b+1, c+1, d+1)
представляют собой положительные целые числа, суммирующие 44
, и наоборот. Используя эту идею, мы имеем:
def constrained_sum_sample_nonneg(n, total):
"""Return a randomly chosen list of n nonnegative integers summing to total.
Each such list is equally likely to occur."""
return [x - 1 for x in constrained_sum_sample_pos(n, total + n)]
Графическая иллюстрация constrained_sum_sample_pos(4, 10)
, благодаря @FM. (Отредактировано слегка.)
0 1 2 3 4 5 6 7 8 9 10 # The universe.
| | # Place fixed dividers at 0, 10.
| | | | | # Add 4 - 1 randomly chosen dividers in [1, 9]
a b c d # Compute the 4 differences: 2 3 4 1
Работает нормально, но "правильный" подход и там лучше альтернатива?
Я использую Throwable
или Exception
в самом экземпляре AsyncTask
, а затем что-то делаю с ним в onPostExecute ()
, поэтому моя обработка ошибок позволяет отображать диалоговое окно на экране.