# 1. Подсчитать, сколько было выделено памяти под переменные в ранее разработанных программах в рамках первых трех уроков.
# Проанализировать результат и определить программы с наиболее эффективным использованием памяти.
# Примечание: По аналогии с эмпирической оценкой алгоритмов идеальным решением будет:
# a. выбрать хорошую задачу, которую имеет смысл оценивать по памяти;
# b. написать 3 варианта кода (один у вас уже есть), проанализировать 3 варианта и выбрать оптимальный;
# c. результаты анализа (количество занятой памяти в вашей среде разработки) вставить в виде комментариев в файл с кодом.
#    Не забудьте указать версию и разрядность вашей ОС и интерпретатора Python;
# d. написать общий вывод: какой из трёх вариантов лучше и почему.

# Тесты выполнены на 64-разрядной Win 8.1
# Python 3.8.0 [MSC v.1916 32 bit (Intel)] win32

import sys

def memory_count(lst):
    memory = 0
    for var in lst:
        print('***********')
        print(f'Переменная: {var}')
        print('Весит: ', sys.getsizeof(var))
        spam = sys.getsizeof(var)

        if hasattr(var, '__iter__') and not isinstance(var, str):
            if hasattr(var, 'keys'):
                for key, value in var.items():
                    print(f'\nКлюч: \'{key}\' значение {value}')
                    spam += memory_count([key]) + memory_count([value])
            else:
                spam += memory_count(var)
        memory += spam

    return memory

# ***************************************************************************************************
# Найти сумму и произведение цифр трехзначного числа,
# которое вводит пользователь.

# a = 123# int(input('Введите целое трехзначное число:'))
#
# hundred = a // 100
# dozen = (a // 10) % 10
# unit = a % 10
#
# summa = hundred + dozen + unit
# mult = hundred * dozen * unit
#
# print(f'Сумма цифр в числе: {summa}')
# print(f'Произведение цифр в числе: {mult}')

# Затраты памяти программы:  84
# Переменные:  [123, 2, 1, 6, 6, 3]

# ***************************************************************************************************
# a = 123 #int(input('Введите целое трехзначное число:'))
#
# summa = (a // 100) + ((a // 10) % 10) + (a % 10)
# mult = (a // 100) * ((a // 10) % 10) * (a % 10)
#
# print(f'Сумма цифр в числе: {summa}')
# print(f'Произведение цифр в числе: {mult}')

# Затраты памяти программы:  42
# Переменные:  [123, 6, 6]

# ***************************************************************************************************
a = 123# int(input('Введите целое трехзначное число:'))

print(f'Сумма цифр в числе: {(a // 100) + ((a // 10) % 10) + (a % 10)}')
print(f'Произведение цифр в числе: {(a // 100) * ((a // 10) % 10) * (a % 10)}')

# Затраты памяти программы:  14
# Переменные:  [123]

# ВЫВОД: Использование дополнительных переменных занимает в памяти больше места, но их наличие порой облегчает
# читабельность кода.

# ***************************************************************************************************
# собираем переменные для подсчета затрачиваемой памяти
_variable = []
for i in dir():
    if i[0] != '_' and not hasattr(locals()[i], '__name__'):
        _variable.append(locals()[i])

print(f'Переменные: {_variable}')
print(f'Затраты памяти программы: {memory_count(_variable)}')