Path: csiph.com!usenet.pasdenom.info!news.redatomik.org!newsfeed.xs4all.nl!newsfeed3a.news.xs4all.nl!xs4all!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.015 X-Spam-Evidence: '*H*': 0.97; '*S*': 0.00; '"""': 0.07; 'intermediate': 0.07; 'squares': 0.07; 'function:': 0.09; 'prefix': 0.09; 'subject:number': 0.09; 'def': 0.12; 'parentheses': 0.16; 'set()': 0.16; 'simplest': 0.16; 'sorting': 0.16; 'subject:happy': 0.16; 'true:': 0.16; 'tuple': 0.16; 'wrote:': 0.18; 'variable': 0.18; 'thu,': 0.19; 'written': 0.21; 'memory': 0.22; 'creating': 0.23; 'refers': 0.24; 'compare': 0.26; 'skip:_ 20': 0.27; 'values': 0.27; 'header:In-Reply-To:1': 0.27; 'testing': 0.29; 'am,': 0.29; 'sets': 0.30; 'message- id:@mail.gmail.com': 0.30; 'url:wiki': 0.31; 'really,': 0.31; 'subject:skip:i 10': 0.31; 'url:wikipedia': 0.31; 'probably': 0.32; 'skip:c 30': 0.32; 'implemented': 0.33; 'skip:_ 10': 0.34; 'could': 0.34; 'but': 0.35; 'received:google.com': 0.35; 'there': 0.35; 'false': 0.36; 'url:org': 0.36; 'two': 0.37; 'list': 0.37; 'e.g.': 0.38; 'to:addr:python-list': 0.38; 'list,': 0.38; 'short': 0.38; 'extremely': 0.39; 'structure': 0.39; 'sure': 0.39; 'to:addr:python.org': 0.39; 'enough': 0.39; 'how': 0.40; 'expression': 0.60; 'save': 0.62; '30,': 0.65; 'here': 0.66; 'containing': 0.69; 'union': 0.69; 'as:': 0.81; '2015': 0.84; 'loses': 0.84; 'sets,': 0.84; 'do:': 0.91 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :content-type; bh=Q0/bHPIaYRYXm2grPjAFUT6GQNTR772VSYaC1Cr8e4Q=; b=OhYmUjzMG8mgobr8blLDIthMzSohYS3TpZECVEpj9WaH1r8xMV505oHnTgxIq1jCyF OeOqc8L9mrntqqdqktpjT/KvBjWldn1Plq2QQ2D810emSN5hTspQUCpdKXPS06RSSMsv M7pzxMzBebKu4x/GH3KjAIPrXeFHkWiAFGvjsGkIJrhBJ8v93vm/ou/937gk9VX6e66J pjtrAA1nB4PKkaT3cWn1UTbZO/5bepE/sDZ76wYD9/QqCSLiqZBXgsUPiUETQPO6rhrF R8l3NLhT6UmyYBRhlhZLSekZ8dhK+GBeiU40TuCR38kbJ00cYpT8VbGG+hseW/xRd295 qz2Q== X-Received: by 10.50.30.105 with SMTP id r9mr3110467igh.11.1430415470565; Thu, 30 Apr 2015 10:37:50 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: <87oam5vc8k.fsf@Equus.decebal.nl> References: <87oam5vc8k.fsf@Equus.decebal.nl> From: Ian Kelly Date: Thu, 30 Apr 2015 11:37:10 -0600 Subject: Re: Is my implementation of happy number OK To: Python Content-Type: text/plain; charset=UTF-8 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20+ Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 82 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1430415473 news.xs4all.nl 2876 [2001:888:2000:d::a6]:35818 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:89650 On Thu, Apr 30, 2015 at 9:59 AM, Cecil Westerhof wrote: > I implemented happy_number function: > _happy_set = { '1' } > _unhappy_set = set() > > def happy_number(n): > """ > Check if a number is a happy number > https://en.wikipedia.org/wiki/Happy_number > """ > > def create_current(n): > current_array = sorted([value for value in str(n) if value != '0']) A generator expression in place of the list comprehension would avoid creating an intermediate list, which would save memory on extremely large numbers. Not sure without testing how it would compare on small numbers. For reference, since size here refers to number of digits, 1E8 would be considered tiny. Also for large numbers, there might be a smarter data structure to use than just sorting the digits, which is O(n log n). Simplest would probably just be a 9-element tuple containing the count of each non-zero digit, which would be only O(n) to build. > return (current_array, ''.join(current_array)) You don't seem to be actually using current_array for anything, so why not just return the string? > global _happy_set > global _unhappy_set > > current_run = set() > current_array, \ > current_string = create_current(n) As a stylistic rule, avoid line continuations using \. Prefer using unclosed parentheses for line continuations, e.g. the above could be written as: (current_array, current_string) = create_current(n) But really, the above is short enough it could just be written on a single line. Also, I feel like the prefix "current_" is used so much here that it loses its meaning. All these variable names would be better without it. > if current_string in _happy_set: > return True > if current_string in _unhappy_set: > return False Instead of two sets, consider using a single _happy_dict with values True for happy and False for unhappy. Then the above becomes: if current_string in _happy_dict: return _happy_dict[current_string] > while True: > current_run.add(current_string) > current_array, \ > current_string = create_current(sum([int(value) ** 2 > for value in current_string])) Since there are only 9 values that get squared, you could precompute the squares to avoid squaring them over and over again. > if current_string in current_run | _unhappy_set: In case the sets get large it might be better to avoid creating the union and just do: if current_string in current_run or current_string in _unhappy_set: > _unhappy_set |= current_run > return False > if current_string in _happy_set: > _happy_set |= current_run > return True