# Books Algorithm Dealing with Square Digit Sums

A little context:

• Book has 411 Pages

• Read a random number of pages on the first day which is unknown

• Number of pages to read next day is the square of the sum of the digits of the page currently on

I.e. on Page 36: read 81 pages next day

• On day 6 The square answer directly adds to current page number to make 411

• Finish Book

How many pages did she read on the first day and how many pages did she read on the 6 days?

This is what I have so far:

from itertools import accumulate, count

for i in range( 6 ): yield start; start += sum( int( digit ) for digit in str( start ) ) ** 2

def find_start( pages ):
for start in count( 1 ):
if read == pages: return start

previous_answer, start = 0, find_start( 411 )


Output:

Pages read on day 1 was 61 (Now on page 61)

Pages read on day 2 was 49 (Now on page 110)

Pages read on day 3 was 4 (Now on page 114)

Pages read on day 4 was 36 (Now on page 150)

Pages read on day 5 was 36 (Now on page 186)

Pages read on day 6 was 225 (Now on page 411)

Is there a more efficient way of writing this using fewer lines of code?

• Welcome to CR.SE! Unless you are looking for a review of your code, this is not the correct place for such a question. Perhaps consider posting to code golf or similar. – psaxton Jan 10 '15 at 20:23
• Okay... Well is this an efficient way of doing the task: if so how would you change it. I have submitted a post in Code-Golf for least no. character answer. But I would like people to answer on here to see if what I have made is good also... If anyone can review my code (not that of others) and suggest corrections/improvements please feel free to share! thanks – user62630 Jan 10 '15 at 20:47

Can someone see if there is a more efficient way of writing this using fewer lines of code?

I suppose your focus is not literally on the part about "fewer lines of code". You could use more semicolons to squeeze more lines onto a single line, but that would violate PEP 20, the Zen of Python, even more than it already does.

Your current solution is essentially a brute force algorithm, counting up from the beginning until you find a suitable start page from which the last page will be reached on Day 6. The algorithm is well implemented, and I don't know a better way. I can suggest some other improvements though.

### Coding style

You should follow PEP8, the Python coding style guide. In particular:

• Do break lines in loops
• Avoid using semicolon to separate multiple statements
• Don't put spaces around method parameters, for example write read_book(start) instead of read_book( start )

### Generalize

It would be nice to make the implementation more general.

For example, the target pages 411 and the required number of days would be nice to put in constants, to make them easier to play with and less magic.

Also, instead of executing code in the global namespace, the best practice is wrap your main code in a main() method, and call that from within if __name__ == '__main__':, like this:

def main():
# main implementation

if __name__ == '__main__':
main()


### Robustness

The find_start method counts up from 1 until the target page is reached, or else...forever. It would better to set an upper limit, like this:

def find_start(pages):
for start in range(1, pages):
pass
return start
raise ValueError("Impossible to reach page {} exactly".format(pages))


### Suggested implementation

Putting the above suggestions together:

PAGES = 411

yield start
start += sum(int(digit) for digit in str(start)) ** 2

def find_start(pages):
for start in range(1, pages):
pass
return start
raise ValueError("Impossible to reach page {} exactly".format(pages))

def main():