Мне неловко, что я потратил так много времени на это, казалось бы, простое, но непростое упражнение по кодированию.
Задача такая: вводить различные строки — цифры, символы, неанглийские символы, например, некоторые могут быть кириллическими. Входные данные должны быть разбиты на слова, а затем каждое слово должно быть интерпретировано численно, если это возможно. Он должен обрабатывать фактические цифры от 1 до 6 как действительные числа. Все остальные должны быть напечатаны как есть.
Допустимые входные данные включают положительные числа, числа типа int или float от 1 до 6, например следующие:
- 1,2,3,4,5,6
- +1, +2, …, +6
- 1.0, 2.0, … 6.0
- любые научные обозначения, представляющие числа от 1 до 6.
если число 1 — выведите «правило1», 2- «правило2» и т. д.
Особый случай — если входной номер можно интерпретировать как 0 или любой другой вариант 0: 0,0, 0,0000 или 0.e00. Он выводит все 6 — «правило1, правило2, …. правило6».
Некорректный ввод включает отрицательные числа, они должны быть напечатаны как есть: -1 печатает «-1», -2 печатает -2.
- любые цифры в научных обозначениях, не входящие в [1 .. 6] следует печатать как есть.
- любой отдельный символ или строка, английский и неанглийский (например, точка), печатается как есть; «девять» напечатано «девять», а «ывъхзъх» напечатано «ывъхзъх».
Пример ввода:
1.0 03
+5
2.0e0
+.4e1
6.E+00
20e-1 2e1 2ва . 1e-307
ожидаемый результат:
rule1
rule3
rule5
rule2
rule4
rule6
rule2
2e1
2ва
.
1e-307
Вот мой код. Я хочу сделать его более элегантным.
from math import modf
import fileinput
rule1 = 'rule1'
rule2 = 'rule2'
rule3 = 'rule3'
rule4 = 'rule4'
rule5 = 'rule5'
rule6 = 'rule6'
def print_rule(n):
if n == 1:
print(rule1)
elif n == 2:
print(rule2)
elif n == 3:
print(rule3)
elif n == 4:
print(rule4)
elif n == 5:
print(rule5)
elif n == 6:
print(rule6)
def print_all():
print(rule1)
print(rule2)
print(rule3)
print(rule4)
print(rule5)
print(rule6)
def get_num(s):
try:
s = int(s)
if s == 0:
print_all()
elif s in [1, 2, 3, 4, 5, 6]:
print_rule(s)
elif s < 1 or s > 6:
print(s)
except ValueError:
try:
saved = s
s = float(s)
if s == 0:
print_all()
elif s < 1 or s > 6:
print(saved)
else:
s = float(s)
s = check_float(s)
if s == 0:
print_all()
elif s in [1, 2, 3, 4, 5, 6]:
print_rule(s)
else:
print(s)
except ValueError:
print(s)
def check_float(n):
frac, _ = modf(n)
if frac != 0:
return n
else:
return n
def test2():
for line in fileinput.input():
line = line.strip().split()
for item in line:
get_num(item)
if __name__ == "__main__":
test2()
1 ответ
Ваш код для печати всего и правила печати излишне многословен. Вы можете преобразовать число с плавающей запятой в целую и дробную части, как вы это делали в check_float
но никогда не использовал. А затем просто проверьте, находится ли целое число в границах и нет ли дробной части.
def print_rule(number):
integer, fraction = divmod(number, 0)
if 1 <= integer <= 6 and not fraction:
print(f"rule{int(number)}")
Печатать все также можно просто циклом for.
def print_all():
for number in range(1, 7):
print(f"rule{number}")
Задача программирования плохая. Задача просто сложная, и обработка 0 иначе, чем 1-6, просто уловка. Я бы посоветовал использовать другой сайт, потому что задача состоит в том, чтобы понять, что проблема просто плохо сформулирована.
Когда вы сталкиваетесь с проблемой программирования, в которой говорится: «Это нормально, это нормально, это нормально», и то, что нормально, постоянно расширяется, тогда рекомендуется использовать регулярное выражение. Однако мы можем думать об этом в более общем смысле; разделите код на три части:
Извлечение сырых данных.
Вы начинаете с создания средства для извлечения того, что вам нужно, из входных данных. Если в вызове говорится не разрешать что-либо, это проблема на потом. Обычно это делается с помощью регулярного выражения, но иногда использование простого Python может быть полезным.Оцените необработанные данные.
Здесь мы конвертируем необработанные данные во что-то, что мы можем использовать. Вот это просто использованиеfloat
, но иногда это может потребовать больше усилий.Подтвердите данные.
Здесь вы кодируете «если число == 0 …». Поскольку мы проанализировали данные, код много проще.
Ваш код связывает все это вместе.
Задачу программирования можно переформулировать, сделав ее намного проще.
Разделите ввод пробелом на сегменты.
for segment in TEXT.split():
Оцените число из научного обозначения; если это невозможно, выведите сегмент.
try: number = float(segment) except ValueError: print(segment) else: # ...
Если оцениваемое число — 1, 2, 3, 4, 5 или 6, то выведите «rule {number}».
Если оцененное число равно 0, выведите «rule1», «rule2», … «rule6».if number in range(0, 7): numbers = range(1, 7) if number == 0 else [int(number)] for number in numbers: print(f"rule{number}")
В противном случае выведите сегмент.
print(segment)
Тогда задача становится такой же простой, как цикл for с ужасными условиями. Если значение равно this, значение равно this и значение this … И в конечном итоге заставляет вас использовать анти-шаблон стрелки для получения чистого кода. Не фанат.
TEXT = """
1.0 03
+5
2.0e0
+.4e1
6.E+00
20e-1 2e1 2ва . 1e-307
"""
def main():
for segment in TEXT.split():
try:
number = float(segment)
except ValueError:
pass
else:
if number in range(0, 7):
numbers = range(1, 7) if number == 0 else [int(number)]
for number in numbers:
print(f"rule{number}")
continue
print(segment)
if __name__ == "__main__":
main()
Если вы думаете, что просто звоните float
обман, то вы можете вручную извлечь и оценить число.
Чтобы извлечь, нам нужно обратиться к регулярному выражению. Мы можем строить из предметов в описании задачи.
1,2,3, 4,5,6
[0-6]
+1, +2, … +6
+?[0-6]
1.0, 2.0, … 6.0
+?[0-6](?:.0)?
Отрицательные числа следует просто печатать как есть: -1 печатает ‘-1’
[-+]?[0-6](?:.0)?
любые научные обозначения, представляющие числа от 1 до 6.
Во-первых, теперь нам нужно принимать любую цифру, а не только 0 и 0-6, потому что
+.4e1
знак равно4
. И цифры могут быть любой длины,.04e2
знак равно4
.[-+]?(?:d*.d*|d+)
Затем нам нужно получить научную нотацию, которая представляет собой просто букву e между двумя числами.
{number}(?:[eE]{number})?
[-+]?(?:d*.d*|d+)(?:[eE][-+]?(?:d*.d*|d+))?
Поскольку мы хотим проверить, является ли сегмент полностью числом, мы можем проверить, что совпадение начинается в начале и заканчивается в конце. Или используйте
re.fullmatch
^[-+]?(?:d*.d*|d+)(?:[eE][-+]?(?:d*.d*|d+))?$
Вычислить число в научном представлении просто, поскольку мы разделим основание и показатель степени. Затем мы конвертируем оба значения в числа с плавающей запятой, а затем помещаем их в уравнение $ b10 ^ e $, где b — основание, а e — показатель степени. По умолчанию показатель степени равен 0, если он не существует.
def scientific_float(number):
base, _, exponent = number.partition("e")
return float(base) * 10**float(exponent or "0")
Это автоматически обрабатывает +d
, -d
, .d
и d.
если вы думаете, что это обман, вы можете сделать свой собственный float
функция.
Во всем этом показаны три этапа
import re
# Extract
NUMBER = "[-+]?(?:d*.d*|d+)"
SCIENTIFIC_NUMBER = f"{NUMBER}(?:[eE]{NUMBER})?"
NUMBER_MATCHER = re.compile(SCIENTIFIC_NUMBER)
def scientific_float(number): # Evaluate
base, _, exponent = number.partition("e")
return float(base) * 10**float(exponent or "0")
def main():
for segment in TEXT.split(): # Extract
if None is not (match := NUMBER_MATCHER.fullmatch(segment)): # Extract + Validate
try:
number = scientific_float(match.group(0)) # Evaluate
except ValueError:
pass
else:
if number in range(0, 7):
numbers = range(1, 7) if number == 0 else [int(number)]
for number in numbers:
print(f"rule{number}")
continue
print(segment)
if __name__ == "__main__":
main()
ха-ха, этот print_all тупой да
— ЭРДЖАН