Мне кажется, что есть элегантное решение Python для этой проблемы, которое я пытался решить с помощью VBA.Может кто-нибудь помочь, пожалуйста?
Как мне составить список чисел, отвечающих следующим критериям:
- Все ли целые числа
- Итог сначала делится на типы.
- Числа далее разбиваются на подтипы и оптимизируются для соответствия требуемым процентам.
- Общая сумма не превышает указанную сумму.
Пример этогозадача:
- Вы планируете построить максимум 102 жилых дома.
- Тип строительства: 40% из них - студии, а 60% - строительство таунхаусов.(Может иметь больше или меньше типов)
- Существует два Приоритета списков для будущих жителей квартир: Сопровождаемые и без посторонней помощи
- Единицапроценты распределения в списке Assisted (A) должны быть полностью выполнены, а список Unassisted (U) является гибким.Мы бы хотели, чтобы список «Без посторонней помощи» (U) составлял до 20% от общего количества юнитов, если это возможно, но нам определенно нужно минимум 80% от общего количества юнитов, которым будут помогать (A).
- Вспомогательные (A) единицы составляют всего 102x80% = 81,6 единиц (уже не целое число)
- Минимум 10% от Assisted (A)Единицы списка должны быть для лиц пожилого возраста.
- Минимум 40% единиц списка Assisted (A) должны быть для семей.
- Остальные 50% единиц списка Assisted (A)для начинающих ученых данных.
Оставшиеся 20% от общего количества единиц - это свободные места (U).
Итак:
- Всего: 102 единицы.
Construction_type_categories=[.4, .6]
(102 единицы разделены на студии и таунхаусы: 40% и 60%) Assisted=[.1,.4,.5]
(80% + от общего числа единиц Помощи, далее классифицируются как пожилые, семьи, другие занятия в соответствии с процентами в списке) - Части без посторонней помощи являются оставшимися единицами, которые не были частью80% + списка Assisted.(до 20% от общего количества единиц)
Результат:
[4,16,12,8,7,25,19,11]
Разбивка:
- 4 студийных блока Помощь для пожилых людей
- 16 студийных единиц Помощь для семей
- 12 студийных единиц для других типов вспомогательных занятий
- 8 студийных единиц (без посторонней помощи)
- 7 таунхаусов для пожилых людей
- 25 единиц таунхаусов для семей
- 19 единиц таунхаусов для других типов вспомогательных помещений
- 11 единиц таунхаусов (без посторонней помощи).
Сначала я подумал о созданииПредварительный массив округленных чисел, а затем цикл и внесение корректировок.Это выглядело так утомительно, что я начал задумываться о создании большой матрицы чисел с использованием numpy и фильтрации по указанным критериям.
Создание и оптимизация чисел вручную занимало много времени, поэтому я признателен за любую помощь в поиске лучшего решения.
import math
def is_even(x):
if x % 2 == 0:
return True
else:
return False
total=102
unassisted=.2
unassisted_unit_count= math.floor(total*unassisted)
assisted_unit_count=total- unassisted_unit_count
construction_type_categories=[.4, .6] #Must be even.
assisted_subcategories=[.1,.4,.5] #Last element here will be of least priority.
def Unit_Number_Getter(L):
if L[1]=='total_constr_type_amounts':
giventotal= total
if L[1]=='assisted_constr_type_amounts':
giventotal= assisted_unit_count
#Spliting by construction type (preliminary).
constr_type_amounts=[]
for ct in construction_type_categories:
constr_type_amounts.append(round(giventotal * ct))
#Making the unit counts even for the total construction type amounts (need to).
for p in constr_type_amounts:
if not is_even(p):
add_here=constr_type_amounts.index(p)
for f in constr_type_amounts:
if not is_even(f):
from_here= constr_type_amounts.index(f)
constr_type_amounts[add_here] +=1
constr_type_amounts[from_here] -=1
assert sum(constr_type_amounts)==giventotal
print L[1]
print(constr_type_amounts)
L[0]=constr_type_amounts
total_constr_type_amounts=0
assisted_constr_type_amounts=0
List_of_lists=[[total_constr_type_amounts,"total_constr_type_amounts"],[assisted_constr_type_amounts,"assisted_constr_type_amounts"]]
#Established the unit counts for each construction type (for Assisted and total units)
for L in List_of_lists:
Unit_Number_Getter(L)
#Getting a list of the unit counts for each assisted subcategory in each constr type.
testlist=[]
for c in List_of_lists[1][0]:
already_added=0
for a in assisted_subcategories[:-1]:
adding_now= math.ceil(c * a)
testlist.append(adding_now)
already_added+=adding_now
#^Added the priority assisted units (all but the last element).
#Now will add the last of the assisted units.
testlist.append(c-already_added)
#Now will add he least prioritized unassisted units up to the max.
Max_unassisted_units= List_of_lists[0][0][List_of_lists[1][0].index(c)]-c
testlist.append(Max_unassisted_units)
assert ((c+Max_unassisted_units)== List_of_lists[0][0][List_of_lists[1][0].index(c)])#all units present
print("Result: "+ "\n" + str(testlist))