Last active
January 16, 2020 18:45
-
-
Save MasterGroosha/90abdfbd840518240976a3fd9d33185e to your computer and use it in GitHub Desktop.
Что выгоднее: постоянная скидка или накопление и трата баллов?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Во всех тестах считаем скидку и баллы как 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