Рекурсивный вопрос в Python. Никаких условных выражений или циклов

Я пытаюсь понять, как напечатать слово «привет» 121 раз в python. Мне нужно использовать функцию без условных выражений или циклов, без новых строк и без умножения строки на целое число.

Я думаю что-то вроде:

print_hello(): 
   print('hello')
   print_hello()

print_hello()

но я не могу найти способ ограничить рекурсивный вывод без условий. Любая помощь будет принята с благодарностью.

Обновлять Вот все ограничения задачи, возможно, рекурсия - неправильный подход.

  • максимум 20 строк кода
  • нет входных данных для функции.
  • нет импорта или модулей
  • нет если операторы
  • без циклов (для или пока)
  • нет символов новой строки (\n)
  • не могу сделать что-то вроде: print("hello\n"*121)
  • без точек с запятой или кортежей
  • не могу использовать функции exec

не могу сделать что-то вроде: print("hello\n"*121)" Это... неконкретно.

Stef 03.02.2023 13:53

try ... except ... разрешено? Разрешены ли and и or? Используя эти операторы, легко подделать условное выражение в Python.

Stef 03.02.2023 13:55

@Стеф, я не согласен. и там не сказано, что их нельзя использовать...

Mitchell Matheny 03.02.2023 13:55

Если вы не можете использовать '\n', вы можете схитрить и заменить его на ''' в одной строке и ''' в следующей строке.

Stef 03.02.2023 18:54
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
4
234
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

from sys import setrecursionlimit
setrecursionlimit(121)

def phello():
    print('hello', end='')
    phello()
  
try:
    phello()
except:
    print('done')
def print_hello():
    print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello'); print('hello');

Это не рекурсивно?

Maximilian Ballard 03.02.2023 05:28

@MaximilianBallard «но я не могу найти способ ограничить рекурсивный вывод без условных выражений». Насколько я понимаю, это не условие задачи.

sergzach 03.02.2023 05:44

@MaximilianBallard Кстати, это рекурсивно. Но количество вызовов рекурсии равно нулю.

sergzach 13.02.2023 03:41
def print_hello(i):
   print('hello', end = "")
   i -= 1
   a = 42 / i
   try:
       print_hello(i)
   except ZeroDivisionError:
       pass

print_hello(121)

На самом деле 42 может быть чем угодно, просто нужно вызвать ошибку деления на 0

ХОРОШО. Просто еще один ответ, просто для удовольствия.

def print_hello121():
    print(('\n'.join(['hello']*121)))

Здесь - умножаем список, а не строку.

"нет новых строк" так и должно быть "".join(['hello']*121)

gee3107 03.02.2023 05:50

ОП отредактировал вопрос, чтобы запретить использование '\n', хотя с '''<real line break>''' это легко обойти.

Stef 03.02.2023 18:55
def print_single_hello():
    print('hello')

def print_hello121():
    [print_single_hello()] * 121

Это на самом деле не работает правильно, но может быть идеей.

Ничего из этого "*" не разрешено.

gerald 08.02.2023 00:16

Просто использовать списки довольно просто:

def myr(l=[lambda *a: 0] + 120*[lambda a, b: a(b)]):
    print("hello", end = "")
    l.pop()(myr, l)

myr()

Мне нравится, как ваш ответ начинается с «это довольно просто», а затем сразу же прибегает к черной магии.

Stef 03.02.2023 09:31

Это какой-то pythonic анти-шаблон: список значений по умолчанию для функции: docs.quantifiedcode.com/python-anti-patterns/correctness/….

sergzach 13.02.2023 04:37

Идея.

def loop(x):
    try:
        next(x)
        print("hello", end = "")
        loop(x)
    except StopaIteration:
        pass

def hello(n_repeat):
    loop(iter(range(n_repeat)))

...
hello(50)

Используя ленивые операторы and или or, в Python легко подделать условное выражение:

def print_hello(n):
    n > 0 and (print('hello') or print_hello(n - 1))

print_hello(3)
# hello
# hello
# hello

print_hello(121)
# ...

Есть неявные условия (без if).

sergzach 13.02.2023 03:37

Вы можете использовать свойство короткого замыкания and. Ноль — Ложь, все остальные числа — Истина. Если первая часть выражения ложна, вторая часть не оценивается.

def print_hello(n=121):
   print('hello', end=' ')
   n and print_hello(n - 1)

print_hello()

Редактировать: я видел, что вы дисквалифицировали другой ответ, потому что у функции был параметр, поэтому вот версия, в которой вместо этого используется глобальная переменная. Это также исправляет проблему с несовпадением в оригинале.

n = 121

def print_hello():
    global n
    print('hello', end=' ')
    n -= 1
    n and print_hello()

print_hello()

Есть неявные условия (без if).

sergzach 13.02.2023 03:38

@sergzach, если вы проверите часть вопроса «ограничения на вызов», я думаю, вы увидите, что это не нарушает ни одно из них. Утверждение об «условиях» кажется небрежным перефразированием.

Mark Ransom 13.02.2023 04:39

Не очень понятно — любое условие можно легко заменить удалением if, смотрите: gist.github.com/sergzach/f613e0035cfe4c753546b210a4a950d0

sergzach 13.02.2023 06:38
Ответ принят как подходящий

(Примечание: я отредактировал сообщение. См. лучшее решение в конце)

Если мы не попытаемся найти серебряную пулю, используя трюк, который был бы забыт в ограничениях (переменные global для обхода запрета параметров, and/try для обхода запрета if, список умножения для обхода запрета умножения строки, .. .), насколько я понимаю вопрос, речь идет о поиске правильного разделения функций/подфункций на 20 строк кода (без точки с запятой)

Например, если бы нам нужно было напечатать 32 hello, мы могли бы, как привыкли рассуждать гики в степени 2,

def h2():
    print("hello")
    print("hello")
def h4():
    h2()
    h2()
def h8():
    h4()
    h4()
def h16():
    h8()
    h8()
h16()
h16()

Которые 14 строк. Но части def усложняют вещи и усложняют то, что является оптимальным. Например, здесь, поскольку мы не используем h2 нигде, кроме h4, было бы короче напрямую печатать hello 4 раза в h4. Аналогично, для h16

def h4():
    print("hello")
    print("hello")
    print("hello")
    print("hello")
def h16():
    h4()
    h4()
    h4()
    h4()
h16()
h16()

которых всего 12 строк.

Здесь число 121. Это конкретное число. Именно по этой причине я считаю, что это ожидаемое решение: непросто решить, какую промежуточную функцию нам нужно создать.

Это было бы интересной проблемой само по себе: создать код, который оптимизирует количество необходимых строк, используя такого рода инкапсуляцию подфункций.

Но есть одна комбинация, умещающаяся в 20 строк:

def h3():
    print("hello")
    print("hello")
    print("hello")
def h7():
    h3()
    h3()
    print("hello")
def h15():
    h7()
    h7()
    print("hello")
def h60():
    h15()
    h15()
    h15()
    h15()
h60()
h60()
print("hello")

Я знаю, что это гораздо менее умно (и даже «умно»), чем все другие предложенные решения. Но я действительно убежден, что это ожидаемое решение. Это может показаться слишком простым и наивным. Но решить, что h?? написать, не так просто (ну, это не так сложно, если ограничение просто «уместиться в 20 строк». Но мне было бы сложнее, если бы ограничение было «использовать наименьшее число». возможных линий")

Редактировать

Я не мог устоять, поэтому написал код, оптимизирующий это

def size(n, l):
    ml=max(k for k in l if k<=n)
    nm=n//ml
    r=n-nm*ml
    if r==0: 
        return nm
    else:
        return nm+size(r, l)

def sizefn(l):
    return sum(size(k, [x for x in l if x<k])+1 for k in l if k>1)

def totsize(n,l):
    return size(n, l) + sizefn(l)

rec=1000

def compute(l, k):
    global rec
    if k>120: return False
    sfn =sizefn(l) 
    if sfn+2>=rec:
        return False
    f = size(121, l)
    if sfn+f<rec:
        rec=sfn+f
        print(f'{sfn+f} ({sfn}+{f}) :', l)
    compute(l+[k], k+1)
    compute(l, k+1)

Что он делает, так это просто пробует все возможные комбинации промежуточных функций. Итак, то есть теоретически 2¹²⁰ комбинаций (все промежуточные функции h? могут существовать или нет), и посчитать, сколько будет строк кода, и оставить лучшую. За исключением того, что я делаю это с помощью Branch&Bound, что позволяет избежать рассмотрения целых подмножеств множества всех комбинаций.

Результат

121 (0+121) : [1]
64 (3+61) : [1, 2]
47 (6+41) : [1, 2, 3]
40 (9+31) : [1, 2, 3, 4]
37 (12+25) : [1, 2, 3, 4, 5]
36 (15+21) : [1, 2, 3, 4, 5, 6]
35 (31+4) : [1, 2, 3, 4, 5, 6, 7, 8, 9, 13, 39]
34 (28+6) : [1, 2, 3, 4, 5, 6, 7, 8, 9, 23]
33 (28+5) : [1, 2, 3, 4, 5, 6, 7, 8, 10, 30]
32 (28+4) : [1, 2, 3, 4, 5, 6, 7, 8, 13, 39]
31 (25+6) : [1, 2, 3, 4, 5, 6, 7, 8, 23]
30 (25+5) : [1, 2, 3, 4, 5, 6, 7, 10, 30]
29 (25+4) : [1, 2, 3, 4, 5, 6, 7, 13, 39]
28 (22+6) : [1, 2, 3, 4, 5, 6, 8, 24]
27 (22+5) : [1, 2, 3, 4, 5, 6, 10, 30]
26 (20+6) : [1, 2, 3, 4, 5, 6, 23]
25 (19+6) : [1, 2, 3, 4, 5, 8, 24]
24 (19+5) : [1, 2, 3, 4, 5, 10, 30]
23 (17+6) : [1, 2, 3, 4, 6, 24]
22 (16+6) : [1, 2, 3, 4, 8, 24]
21 (16+5) : [1, 2, 3, 5, 10, 30]
20 (14+6) : [1, 2, 3, 6, 24]
19 (13+6) : [1, 2, 4, 8, 24]
18 (12+6) : [1, 2, 6, 24]

И это заканчивается там. Это означает, что нет лучшего решения, чем решение с h2, h6 и h24 (h1 — это просто print(hello))

Всего 18 строк

Который дает

def h2():
    print("hello")
    print("hello")
def h6():
    h2()
    h2()
    h2()
def h24():
    h6()
    h6()
    h6()
    h6()
h24()
h24()
h24()
h24()
h24()
print("hello")

Я убежден, что это то, что они ищут.

Mitchell Matheny 03.02.2023 18:43

@MitchellMatheny Я пошел немного дальше, так как вы приняли ответ (спасибо, кстати). Итак, теперь у меня есть (в том же духе) решение из 18 строк. И код, доказывающий, что 17-строчного решения быть не может (без уловок).

chrslg 03.02.2023 18:46

Вы можете использовать «функции более высокого порядка», такие как map, filter, max, min или sorted, чтобы многократно применять функцию к range.

def print_hello_map(n):
    any(map(lambda _: print('hello'), range(n)))

def print_hello_filter(n):
    next(filter(lambda x: print('hello') or x + 1>= n, range(n)))

def print_hello_max(n):
    max(range(n), key=lambda x: bool(print('hello')))

def print_hello_sorted(n):
    sorted(range(n), key=lambda x: bool(print('hello')))

Если бы вы разрешили импорт из стандартной библиотеки, то было бы много альтернатив map и filter, например, functools.reduce и itertools.repeat, а также все функции из itertools, выполняющие любой цикл.

from functools import reduce
def print_hello_reduce(n):
    reduce(lambda acc,x: print('hello'), range(n+1))

from itertools import repeat
def f(x):
    yield bool(print('hello'))
def print_hello_repeat(n):
    sum(repeat(f, n))

Другие вопросы по теме