Invalid function return
Question:
This is my code, why when i print(is_happy(13)) i got True, but in the result of happy_numbers i don’t get 13 and many correct numbers?
def is_happy(n, result = []):
next_number = sum(map(lambda x: int(x) ** 2, str(n)))
if next_number == 1:
return True
elif next_number in result:
return False
else:
result.append(next_number)
return is_happy(next_number)
def happy_numbers(n):
result = []
for i in range(1, n + 1):
if is_happy(i):
result.append(i)
return result
Answers:
The issue is that you are using a mutable default argument in is_happy(n, result=[])
. This means that the result
won’t start as an empty list every time it’s run but rather will keep its old results.
To counter this, I’d remove the default argument and explicitly pass the array:
def is_happy(n, result):
# all the stuff you already had
return is_happy(next_number, result)
and in the other function
if is_happy(i, []):
Generators make your programs easier to write –
def is_happy(n, seen = set()):
if n == 1:
return True
elif n in seen:
return False
else:
return is_happy(sum(x ** 2 for x in digits(n)), seen | {n})
def digits(n):
if n < 10:
yield n
else:
yield from digits(n // 10)
yield n % 10
def happy_numbers(n):
for x in range(n):
if is_happy(x):
yield x
print(list(happy_numbers(100)))
is_happy
can be optimized with lru_cache –
from functools import lru_cache
seen = set()
@lru_cache
def is_happy(n):
if n == 1:
return True
elif n in seen:
return False
else:
seen.add(n)
answer = is_happy(sum(x ** 2 for x in digits(n)))
seen.remove(n)
return answer
print(list(happy_numbers(10000)))
before optimization
with LRU cache
real
1,303 ms
284 ms
user
470 ms
118 ms
sys
19 ms
13 ms
This is my code, why when i print(is_happy(13)) i got True, but in the result of happy_numbers i don’t get 13 and many correct numbers?
def is_happy(n, result = []):
next_number = sum(map(lambda x: int(x) ** 2, str(n)))
if next_number == 1:
return True
elif next_number in result:
return False
else:
result.append(next_number)
return is_happy(next_number)
def happy_numbers(n):
result = []
for i in range(1, n + 1):
if is_happy(i):
result.append(i)
return result
The issue is that you are using a mutable default argument in is_happy(n, result=[])
. This means that the result
won’t start as an empty list every time it’s run but rather will keep its old results.
To counter this, I’d remove the default argument and explicitly pass the array:
def is_happy(n, result):
# all the stuff you already had
return is_happy(next_number, result)
and in the other function
if is_happy(i, []):
Generators make your programs easier to write –
def is_happy(n, seen = set()):
if n == 1:
return True
elif n in seen:
return False
else:
return is_happy(sum(x ** 2 for x in digits(n)), seen | {n})
def digits(n):
if n < 10:
yield n
else:
yield from digits(n // 10)
yield n % 10
def happy_numbers(n):
for x in range(n):
if is_happy(x):
yield x
print(list(happy_numbers(100)))
is_happy
can be optimized with lru_cache –
from functools import lru_cache
seen = set()
@lru_cache
def is_happy(n):
if n == 1:
return True
elif n in seen:
return False
else:
seen.add(n)
answer = is_happy(sum(x ** 2 for x in digits(n)))
seen.remove(n)
return answer
print(list(happy_numbers(10000)))
before optimization | with LRU cache | |
---|---|---|
real | 1,303 ms | 284 ms |
user | 470 ms | 118 ms |
sys | 19 ms | 13 ms |