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

Asked By: Ashtart

||

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, []):
Answered By: Hamatti

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
Answered By: Mulan
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.