Уведомления

Группа в Telegram: @pythonsu

#1 Окт. 11, 2017 16:33:22

SergeyChmutov
Зарегистрирован: 2017-08-04
Сообщения: 50
Репутация: +  0  -
Профиль   Отправить e-mail  

Оптимизация кода

Добрый день!
Обучаюсь на курсах по Питону. Была задана домашка, но по итогам сдачи ее преподаватель не разбирал часть hard. Я ее конечно же решил, по неопытности нагородил немного костылей. И вот хотелось бы услышать мнение опытных питонистов, как оптимизировать их решения?

З.Ы. Файлы используемы во 2 и 3 задаче прикрепил в архиве.

 # -*- coding: utf-8 -*-
import re
# Задание-1:
# Написать программу, выполняющую операции (сложение и вычитание) с простыми дробями.
# Дроби вводятся и выводятся в формате:
# n x/y ,где n - целая часть, x - числитель, у - знаменатель.
# Дроби могут быть отрицательные и не иметь целой части, или иметь только целую часть.
# Примеры:
# Ввод: 5/6 + 4/7 (всё выражение вводится целиком в виде строки)
# Вывод: 1 17/42  (результат обязательно упростить и выделить целую часть)
# Ввод: -2/3 - -2
# Вывод: 1 1/3
def search_nod(a, b):
    '''Нахождение нибольшего общего делителя для чисел а и b'''
    while a != 0 and b != 0:
        if a > b:
            a = a % b
        else:
            b = b % a
    return a + b
def search_nok(a, b):
    '''Нахождение наименьшего общего кратного для чисел а и b'''
    return a * b / search_nod(a, b)
def diff(lst):
    '''Вычисление разности элементов списка'''
    difference = lst[0]
    for x in range(len(lst)):
        if x:
            difference = difference - lst[x]
    return difference
def format_dec(num, NOK):
    '''выделение целой части дроби'''
    if num > NOK:
        cel = num // NOK
        new_num = num % NOK
        result = '{0:.0f} {1:.0f}/{2:.0f}'.format(cel, new_num, NOK)
    else:
        result = '{0:.0f}/{1:.0f}'.format(num, NOK)
    return result
print('-' * 50)
print('Задача 1')
equation = '7/17 - -5'
# получаем все дроби из строки
params = re.findall(r'[-]?[0-9]+/[0-9]+|[-]?[0-9]+', equation)
# получаем список содержащий оператор
funcs = re.split(r'[-]?[0-9]+/[0-9]+|[-]?[0-9]+', equation)
nums = []
noms = []
i = 0
for param in params:
    temp = param.split('/')
    nums.append(int(temp[0]))
    if len(temp) > 1:
        noms.append(int(temp[1]))
    else:
        noms.append(1)
for p in funcs:
    # определяем оператор действия с дробями
    if p:
        func = p.strip()
        break
NOK = search_nok(noms[0], noms[1])
for n in nums:
    # вычисляем новые числители по найденному НОК
    nums[i] = n * NOK / noms[i]
    i += 1
print('Результат вычисления ' + equation + ':')
if func == '+':
    print(format_dec(sum(nums), NOK))
elif func == '-':
    print(format_dec(diff(nums), NOK))
else:
    print('Действие не определено')
 # -*- coding: utf-8 -*-
import re
# Задание-2:
# Дана ведомость расчета заработной платы (файл "data/workers").
# Рассчитайте зарплату всех работников, зная что они получат полный оклад,
# если отработают норму часов. Если же они отработали меньше нормы,
# то их ЗП уменьшается пропорционально, а за заждый час переработки
# они получают удвоенную ЗП, пропорциональную норме.
# Кол-во часов, которые были отработаны, указаны в файле "data/hours_of"
print('-' * 50)
print('Задача 2')
info_person = []
info_hours = []
info =[]
workers = open('data/workers.txt', 'r', encoding='utf-8')
for line in workers:
    info_person.append(re.findall(r'[А-я]+[_]?[А-я]+|[0-9]+', line))
workers.close()
hours = open('data/hours_of.txt', 'r', encoding='utf-8')
for line in hours:
    info_hours.append(re.findall(r'[А-я]+\s?[А-я]+|[0-9]+', line))
hours.close()
cvit = open('data/cvit_of_price.txt', 'w', encoding='utf-8')
cvit.write('Имя Фамилия Заработанная плата\n')
# убираем из матриц строку с названием колонок
info_person = info_person[1:]
info_hours = info_hours[1:]
for i in info_person:
    name_one_table = i[0]
    surname_one_table= i[1]
    for n in info_hours:
        name_two_table = n[0]
        surname_two_table = n[1]
        if name_one_table == name_two_table and \
            surname_one_table == surname_two_table:
            salary = int(i[2])      # оклад
            hours_norm = int(i[4])  # норма отработанных часов
            hours_work = int(n[2])  # отработано часов
            work = hours_work - hours_norm
            # Усли отработано больше нормы, сверурочную почасовую оплату
            # считаем по двойному тарифу.
            # Если отработано меньше нормы, недоработанную почасовую оплату
            # считаем по текущему тарифу
            if work > 0:
                price = salary + \
                        (2 * (salary / hours_norm) * (hours_work - hours_norm))
            else:
                price = salary + \
                        (salary / hours_norm) * (hours_work - hours_norm)
            # записываем в файл квитанции
            person_data = '{0} {1} {2:.2f}\n'.format(name_one_table,
                                                  surname_one_table,
                                                  price)
            cvit.write(person_data)
            print(person_data.strip())
cvit.close()
print('Зарплатная ведомость сформирована в файле - data/cvit_of_price.txt')
 # -*- coding: utf-8 -*-
import re
# Задание-3:
# Дан файл ("data/fruits") со списком фруктов.
# Записать в новые файлы все фрукты, начинающиеся с определенной буквы.
# Т.е. в одном файле будут все фрукты на букву “А”, во втором на “Б” и т.д.
# Файлы назвать соответственно.
# Пример имен файлов: fruits_А, fruits_Б, fruits_В ….
# Важно! Обратите внимание, что нет фруктов, начинающихся с некоторых букв.
# Напишите универсальный код, который будет работать с любым списком фруктов
# и распределять по файлам в зависимости от первых букв, имеющихся в списке фруктов.
# Подсказка:
# Чтобы получить список больших букв русского алфавита:
# print(list(map(chr, range(ord('А'), ord('Я')+1))))
def write_in_file(name, lst):
    '''Выполняет открытие файла с переданным именем, если файла в директори нет
    создает новый файл. После записи в файл элементов списка закрывает файл.'''
    file_name = 'data/fruits_' + name + '.txt'
    file = open(file_name, 'w', encoding='utf-8')
    for n in lst:
        file.write(n)
    file.close()
print('-' * 50)
print('Задача 3')
first_liter = ''
count = 0
temp = []
fruits = open('data/fruits.txt', 'r', encoding='utf-8')
for line in fruits:
    if (line[0] != first_liter) & (count == False):
        first_liter = line[0]
    elif line[0] == first_liter:
        name = line[0]
        temp.append(line)
    else:
        write_in_file(name, temp)
        first_liter = line[0]
        temp = []
        temp.append(line)
        if name != line[0]:
            name = line[0]
    count += 1
write_in_file(name, temp)
print('Формирование файлов по именам фруктво закончено!')

Отредактировано SergeyChmutov (Окт. 11, 2017 16:37:38)

Прикреплённый файлы:
attachment data.rar (2,8 KБ)

Офлайн

#2 Окт. 12, 2017 17:12:01

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2832
Репутация: +  186  -
Профиль   Отправить e-mail  

Оптимизация кода

> Написать программу, выполняющую операции (сложение и вычитание) с простыми дробями.

Ты ООП уже проходил? Если не проходил, то нормально решить не сможешь. В остальном ты всё переусложняеш. Вот например как я решил последнюю задачу.

 from itertools import groupby
 
with open("fruits.txt" ) as fail:
	for bukva, data in groupby(fail.readlines(), key=lambda x: x[0]):
		with open(bukva, "w") as out:
			for x in data:
				out.write(x)



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#3 Окт. 12, 2017 19:31:18

marvellik
Зарегистрирован: 2016-05-15
Сообщения: 639
Репутация: +  73  -
Профиль   Отправить e-mail  

Оптимизация кода

  # -*- coding: utf-8 -*-
''' Задание-3:'''
dikt_fruts = dict()
with open('fruits.txt',encoding='utf-8') as inp_ut:
    for fruits in inp_ut.readlines():
        file_name = 'fruits_{}'.format(fruits[0].upper())
        dikt_fruts[file_name] = dikt_fruts.get(file_name,'')+fruits
    
for i in dikt_fruts:
    name = '{}.txt'.format(i)
    with open(name,'w') as out:
        out.write(dikt_fruts[i])
print('Формирование файлов по именам фруктов закончено!')

  # -*- coding: utf-8 -*-
''' Задание-2:'''
def select(x):
    ''' функция рассчитывает зарплату по часам согласно условию'''
    mani,clock,real_clock = list(map(int,x))
    if clock > real_clock:
        res = mani/clock*real_clock
    else:
        res = mani + (mani/clock * real_clock - clock)*2
    return int(res)
with open('workers.txt',encoding='utf-8') as inp, open('hours_of.txt',encoding='utf-8') as clock:
    ''' получаем 2 списка list_norm- список полных данных,
        list_real-список имя фам. и отработанных ч.'''
    list_norm = inp.read().split('\n')
    list_real = clock.read().split('\n')
    
# ==============================================================
''' часть которая была бы не нужна при одинаковом порядке следования имен в файлах обошлись
бы одним циклом фор и индексами нужных элементов'''
def name_data(x):
    ''' получаем из строки упорядоченные данные имя фамилия и список [ зарпл. нормо_часы]'''
    x = x.split()
    name,mani,clock = ' '.join(x[:2]),x[2],x[4]
    return name,[mani,clock]
full_data = dict()
''' так как порядок следования имя-фам в файлах разный создаем словарь из первого файла 
полных данных с ключами из имен с фамилией и значением-список из зарплаты и нормачасов'''
for x in list_norm[1:]:
    name,data = name_data(x)
    full_data[name] = data
for i in list_real[1:]:
    ''' читаем второй список с именами и отработанными часами, получаем имя фамил. и добавляем в
    словарь по ключу(имя фамил.) в значение-список реально отраб. часы'''
    i = i.split()
    full_data[' '.join(i[:2])].append(i[-1])
#===============================================================
with open('data_cvit_of_price.txt', 'w', encoding='utf-8') as out:
    out.write('Имя Фамилия  Зарплата  Норма_часов  Отработано  К выдаче\n')
    ''' берем человека и его данные обрабатываем и пишем в файл'''
    for name in full_data:
        out.write('{}  {}  {}  {}   {}\n'.format(name,*(full_data[name]),select(full_data[name])))

Отредактировано marvellik (Окт. 12, 2017 23:32:53)

Офлайн

#4 Окт. 13, 2017 10:53:30

SergeyChmutov
Зарегистрирован: 2017-08-04
Сообщения: 50
Репутация: +  0  -
Профиль   Отправить e-mail  

Оптимизация кода

Rodegast
Ты ООП уже проходил?
Нет, дошли только до функций. Я и сам понимаю, что можно все это было проще написать, вот только знаний не хватает. О такой библиотеке, что ты использовал даже не слышал.
Дописал строку, чтобы формировал имя файла по задаче. Крутой способ а главное короткий и понятный. Просто здорово
 from itertools import groupby
with open('data/fruits.txt', encoding='utf-8') as file:
    for liter, data in groupby(file.readlines(), key=lambda x: x[0]):
        new_file = 'data/fruit_{}.txt'.format(liter)
        with open(new_file, 'w') as out:
            for x in data:
                out.write(x)

Отредактировано SergeyChmutov (Окт. 13, 2017 11:06:50)

Офлайн

#5 Окт. 13, 2017 10:54:06

SergeyChmutov
Зарегистрирован: 2017-08-04
Сообщения: 50
Репутация: +  0  -
Профиль   Отправить e-mail  

Оптимизация кода

Спасибо что помогли, буду разбираться дальше и пробовать оптимизировать написанное мной ранее)

Отредактировано SergeyChmutov (Окт. 13, 2017 12:49:26)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version