Skip to content

Instantly share code, notes, and snippets.

@MasterGroosha
Last active January 16, 2020 18:45
Show Gist options
  • Save MasterGroosha/90abdfbd840518240976a3fd9d33185e to your computer and use it in GitHub Desktop.
Save MasterGroosha/90abdfbd840518240976a3fd9d33185e to your computer and use it in GitHub Desktop.
Что выгоднее: постоянная скидка или накопление и трата баллов?
from random import choice, shuffle, seed
from os import urandom
prices = [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000]
def prepare_data_shuffle():
"""
:return: Возвращает исходный массив prices, но перемешанный
"""
p = prices
shuffle(p)
return p
def prepare_data_random(num_of_iterations):
"""
Возвращает массив заданной длины, содержащий элементы из prices, выбранные случайным образом
:param num_of_iterations:
:return:
"""
result = []
for i in range(num_of_iterations):
result.append(choice(prices))
return result
def discount(array, percent=10):
"""
Метод "скидка на товары". Для каждого товара в списке вычисляем размер скидки и оставшуюся стоимость и суммируем итог
:param array: Список покупок (каждый элемент - исходная стоимость товара)
:param percent: Размер скидки (в процентах)
:return: Итоговую потраченную сумму с учётом скидок
"""
percent_float = percent * 0.01 # переводим во float
saved_money = 0
paid_money = 0
for item in array:
saved_money += item * percent_float
paid_money += item * (1 - percent_float)
return paid_money
def points(array, bonus_percentage=10, fair=True):
"""
Метод "начисление и списание баллов". Для каждого товара в списке вычисляем размер скидки на следующую покупку
как процент от исходной стоимости товара. Перед списанием имеющихся баллов начисляем баллы на следующую покупку
:param array: Список покупок (каждый элемент - исходная стоимость товара)
:param bonus_percentage: Размер бонусов с каждой покупки (в процентах)
:param fair: Считать ли бонусы с исходной стоимости покупок или уже после вычета имеющихся баллов
:return:
"""
paid_money = 0
points_quantity = 0
if fair:
# В этом варианте мы берём 10% после вычета имеющихся баллов, как в жизни
for item in array:
paid_current = item - points_quantity
paid_money += paid_current
points_quantity = (paid_current / bonus_percentage)
else:
# В этом варианте мы берём 10% до вычета бонусов, а не после, в реальности ещё хуже :)
for item in array:
paid_money += (item - points_quantity)
points_quantity = (item / bonus_percentage)
return paid_money
def main():
seed(urandom(20)) # Инициализируем рандомизатор
repeats = 100
print("Во всех тестах считаем скидку и баллы как 10% от покупки (после вычета баллов)")
print("=== Проверка на случайной выборке из 2^x элементов ===")
for i in range(1, 17): # от 2^1 по 2^16
total_with_discount = 0
total_with_points = 0
for j in range(repeats):
shopping_list_random = prepare_data_random(2 ** i)
total_with_discount += discount(shopping_list_random)
total_with_points += points(shopping_list_random)
if total_with_discount < total_with_points:
diff = total_with_points/repeats - total_with_discount/repeats
print(f"При {2**i} покупках ({repeats} попыток) вариант со скидками выгоднее в среднем на {diff:.0f} руб.")
else:
diff = total_with_discount/repeats - total_with_points/repeats
print(f"При {2**i} покупках ({repeats} попыток) вариант с баллами выгоднее в среднем на {diff:.0f} руб.")
print("\n=== Проверка на нисходящем массиве 1000 -> 100 с шагом в 100 ===")
shopping_list_down = [i for i in reversed(prices)]
down_with_discount = discount(shopping_list_down)
down_with_points = points(shopping_list_down)
if down_with_discount < down_with_points:
diff = down_with_points - down_with_discount
print(f"При покупках всё более дешёвых товаров вариант со скидками выгоднее на {diff:.0f} руб.")
else:
diff = down_with_discount - down_with_points
print(f"При покупках всё более дешёвых товаров вариант с баллами выгоднее на {diff:.0f} руб.")
print("\n=== Проверка на восходящем массиве 100 -> 1000 с шагом в 100 ===")
up_with_discount = discount(prices)
up_with_points = points(prices)
if up_with_discount < up_with_points:
diff = up_with_points - up_with_discount
print(f"При покупках всё более дешёвых товаров вариант со скидками выгоднее на {diff:.0f} руб.")
else:
diff = up_with_discount - up_with_points
print(f"При покупках всё более дешёвых товаров вариант с баллами выгоднее на {diff:.0f} руб.")
print("\n=== Проверка на перемешанном исходном массиве (100 попыток) ===")
shuffle_with_discount = 0
shuffle_with_points = 0
for i in range(repeats):
shuffle_list = prepare_data_shuffle()
shuffle_with_discount += discount(shuffle_list)
shuffle_with_points += points(shuffle_list)
if shuffle_with_discount < shuffle_with_points:
diff = shuffle_with_points/repeats - shuffle_with_discount/repeats
print(f"При случайном перемешивании списка покупок вариант со скидками выгоднее в среднем на {diff:.0f} руб.")
else:
diff = shuffle_with_discount/repeats - shuffle_with_points/repeats
print(f"При случайном перемешивании списка покупок вариант с баллами выгоднее в среднем на {diff:.0f} руб.")
if __name__ == "__main__":
main()
Во всех тестах считаем скидку и баллы как 10% от покупки (после вычета баллов)
=== Проверка на случайной выборке из 2^x элементов ===
При 2 покупках (100 попыток) вариант со скидками выгоднее в среднем на 49 руб.
При 4 покупках (100 попыток) вариант со скидками выгоднее в среднем на 69 руб.
При 8 покупках (100 попыток) вариант со скидками выгоднее в среднем на 81 руб.
При 16 покупках (100 попыток) вариант со скидками выгоднее в среднем на 124 руб.
При 32 покупках (100 попыток) вариант со скидками выгоднее в среднем на 208 руб.
При 64 покупках (100 попыток) вариант со скидками выгоднее в среднем на 370 руб.
При 128 покупках (100 попыток) вариант со скидками выгоднее в среднем на 680 руб.
При 256 покупках (100 попыток) вариант со скидками выгоднее в среднем на 1326 руб.
При 512 покупках (100 попыток) вариант со скидками выгоднее в среднем на 2606 руб.
При 1024 покупках (100 попыток) вариант со скидками выгоднее в среднем на 5170 руб.
При 2048 покупках (100 попыток) вариант со скидками выгоднее в среднем на 10290 руб.
При 4096 покупках (100 попыток) вариант со скидками выгоднее в среднем на 20526 руб.
При 8192 покупках (100 попыток) вариант со скидками выгоднее в среднем на 40982 руб.
При 16384 покупках (100 попыток) вариант со скидками выгоднее в среднем на 81926 руб.
При 32768 покупках (100 попыток) вариант со скидками выгоднее в среднем на 163944 руб.
При 65536 покупках (100 попыток) вариант со скидками выгоднее в среднем на 327622 руб.
=== Проверка на нисходящем массиве 1000 -> 100 с шагом в 100
При покупках всё более дешёвых товаров вариант со скидками выгоднее на 58 руб.
=== Проверка на восходящем массиве 100 -> 1000 с шагом в 100
При покупках всё более дешёвых товаров вариант со скидками выгоднее на 133 руб.
=== Проверка на перемешанном исходном массиве (100 попыток)
При случайном перемешивании списка покупок вариант со скидкой выгоднее в среднем на 92 руб.
Process finished with exit code 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment