2

I am trying to figure out how to print the word "hello" 121 times in python. I need to use a function without conditionals or loops, no new lines, and no multiplying the string by an integer.

I thinking something like:

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

print_hello()

but I can't seem to find a way to limit the recursive output without conditionals. Any help would be greatly appreciated.

Update Here are all of the constraints to the challenge, it's possible recursion isn't the right approach.

  • max 20 lines of code
  • no inputs to a function.
  • no imports or modules
  • no if statements
  • no loops (for or while)
  • no new line characters (\n)
  • can't do something like: print("hello\n"*121)
  • no semi colons or tuples
  • can't use exec functions
4
  • 2
    "can't do something like: print("hello\n"*121)" That's... unspecific. Commented Feb 3, 2023 at 12:53
  • 3
    Is try ... except ... allowed? Are and and or allowed? It's easy to fake a conditional in python using these operators. Commented Feb 3, 2023 at 12:55
  • @Stef I don't disagree. and it doesn't say those can't be used... Commented Feb 3, 2023 at 12:55
  • If you can't use '\n', you can cheat and replace it with ''' on one line and ''' on the next line. Commented Feb 3, 2023 at 17:54

11 Answers 11

4

(Note: I've edited the message. So see better solution at the end)

If we don't try to find a silver bullet, using a trick that would have been forgotten in the restrictions (global variables to bypass parameters interdiction, and/try to bypass if interdiction, multiplying list to bypass multiplication of string interdiction, ...), as I understand the question, it is about finding a correct splitting in functions/subfunctions to have 20 lines of code (no semicolon)

For example, if we had to print 32 hello, we could, as geeks used to reason in power of 2,

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

Which are 14 lines. But the def parts complicates things, and complicates what is optimal. For example, here, since we don't use h2 elsewhere that in h4, it would be shorter to directly print hello 4 times in h4. Likewise, for h16

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

which are only 12 lines.

Now, here, number is 121. That is a specific number. Which is even the reason why I believe that this is the kind of expected solution: it is not easy to decide what intermediate function we need to create.

That would be an interesting problem per se: create a code, that optimize the number of lines needed, using this kind of subfunctions encapsulation.

But one combination that fit in 20 lines is

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")

I know it is way less smart (and, even, "smart ass") than all the other solutions that were proposed. But I am really convinced that this is the kind of expected solution. It may seem too simple and naive. But it is not that an easy problem to decide which h?? to write (well, it is not that hard if the constraint is just "fit in 20 lines". But I would have a harder time if the constraint was "use the smallest number of lines possible")

Edit

I couldn't resist, so I wrote a code that optimize this

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)

What it does is just try all possible combinations of intermediate functions. So, that is, theoretically 2¹²⁰ combinations (all intermediate function h? may exist or not), and count how many line of code that would be, and keep the best. Except that I do it with Branch&Bound, allowing to avoid examination of whole subsets of the set of all combination.

Result is

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]

And it ends there. Meaning that there is no better solution that the one with h2, h6, and h24 (h1 is just print(hello))

For a total of 18 lines

Which gives

def h2():
    print("hello")
    print("hello")
def h6():
    h2()
    h2()
    h2()
def h24():
    h6()
    h6()
    h6()
    h6()
h24()
h24()
h24()
h24()
h24()
print("hello")
Sign up to request clarification or add additional context in comments.

2 Comments

I am convinced that this is what they are looking for as well.
@MitchellMatheny I've gone a bit further since you accepted the answer (thx, btw). So now I have (in the same spirit) a 18 lines solution. And a code to prove that there can't be a 17 lines solution (without tricks).
2

Using lazy operators and or or, it is easy to fake a conditional in python:

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

print_hello(3)
# hello
# hello
# hello

print_hello(121)
# ...

1 Comment

There are implicit conditions (without if).
2

You could use a "higher-order function" such as map, filter, max, min or sorted, to apply a function repeatedly to a 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')))

If you had allowed imports from the standard library, then there would have been many alternatives to map and filter, for instance functools.reduce and itertools.repeat, but also all functions from itertools that perform any kind of looping.

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))

Comments

2

You can use the short circuiting property of and. Zero is False, every other number is True. If the first part of the expression is false the second part isn't evaluated.

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

print_hello()

Edit: I saw that you disqualified another answer because the function had a parameter, so here's a version that uses a global variable instead. It also fixes an off-by-one problem in the original.

n = 121

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

print_hello()

3 Comments

There are implicit conditions (without if).
@sergzach if you check the "constraints to the challenge" part of the question, I think you'll see this doesn't violate any of them. The statement about "conditions" appears to be sloppy paraphrasing.
It's not very clear — you can easily replace any condition removing if, look: gist.github.com/sergzach/f613e0035cfe4c753546b210a4a950d0
2

Just using lists its pretty easy:

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

myr()

2 Comments

I love how your answer begins with "it's pretty easy" and then immediately resorts to black magic.
This is some pythonic anti-pattern: the list a default value for a function: docs.quantifiedcode.com/python-anti-patterns/correctness/….
1
from sys import setrecursionlimit
setrecursionlimit(121)

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

Comments

1
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');

3 Comments

Its not recursive though?
@MaximilianBallard "but I can't seem to find a way to limit the recursive output without conditionals." As I understand that's not a condition for the task.
@MaximilianBallard BTW, it's recursive. But the number of recursion calls is zero.
1
def print_hello(i):
   print('hello', end="")
   i -= 1
   a = 42 / i
   try:
       print_hello(i)
   except ZeroDivisionError:
       pass

print_hello(121)

The 42 could be anything really, just need to trigger the division by 0 error

Comments

1

OK. Just another answer, just for fun.

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

Here - we multiply the list, not the string.

2 Comments

"no new lines" so it should be "".join(['hello']*121)
The OP has edited the question to forbid the use of '\n', although that's easy to sidestep with '''<real line break>'''.
1

The idea.

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)

Comments

0
def print_single_hello():
    print('hello')

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

This does not actually works correctly, but it can be an idea.

1 Comment

None of this ' * ' is allowed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.