From a947c89ecf5c3650faf150d662860bd0b0c820d3 Mon Sep 17 00:00:00 2001 From: Mark Pilgrim Date: Wed, 15 Apr 2009 22:59:05 -0400 Subject: [PATCH] added intro to advanced-iterators chapter --- advanced-iterators.html | 44 ++++++++++++++++++++++++++++++++--------- examples/alphametics.py | 2 -- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/advanced-iterators.html b/advanced-iterators.html index 3651184..34bf23d 100644 --- a/advanced-iterators.html +++ b/advanced-iterators.html @@ -16,7 +16,29 @@ body{counter-reset:h1 6}

 

Diving In

-

FIXME +

GOYA + INGRES + RENOIR + SARGENT = ARTISTS. Or, to put it another way, 8643 + 598712 + 719657 + 2378190 = 3705202. + +

It might make more sense if I line it up for you. + +

GOYA + INGRES + RENOIR + SARGENT = ARTISTS
+8643 + 598712 + 719657 + 2378190 = 3705202
+
+G = 8
+O = 6
+Y = 4
+A = 3
+I = 5
+N = 9
+R = 7
+E = 1
+S = 2
+T = 0
+ +

This kind of puzzle is called cryptarithm or alphametics. The letters spell out actual words, but if you replace each letter with a digit from 0–9, it also “spells” an arithmetic equation. The trick is to figure out which letter maps to each digit. All the occurrences of each letter must map to the same digit, no digit can be repeated, and no “word” can start with the digit 0. + +

The most well-known alphametic puzzle is SEND + MORE = MONEY. + +

In this chapter, we'll dive into an incredible Python program originally written by Raymond Hettinger. This program solves alphametic puzzles in just 14 lines of code.

[download alphametics.py]

import re
@@ -48,12 +70,15 @@ if __name__ == '__main__':
             print(solution)
-you@localhost:~$ python3 alphametics.py "SEND + MORE == MONEY"
-SEND + MORE == MONEY
-9567 + 1085 == 10652
+you@localhost:~$ python3 alphametics.py "GOYA + INGRES + RENOIR + SARGENT = ARTISTS"
+GOYA + INGRES + RENOIR + SARGENT = ARTISTS
+8643 + 598712 + 719657 + 2378190 = 3705202
 you@localhost:~$ python3 alphametics.py "I + LOVE + YOU == DORA"
 I + LOVE + YOU == DORA
-1 + 2784 + 975 == 3760
+1 + 2784 + 975 == 3760 +you@localhost:~$ python3 alphametics.py "SEND + MORE == MONEY" +SEND + MORE == MONEY +9567 + 1085 == 10652

Finding all occurrences of a pattern

@@ -68,7 +93,7 @@ if __name__ == '__main__':

Finding the unique items in a sequence

-

This section has nothing to do with iterators, but it's put to good use in the alphametics solver. Set comprehensions make it trivial to find the unique items in a sequence. [FIXME-not sure if I'm going to cover set comprehensions in an earlier chapter; if not, this is certainly an abrupt and inadequate introduction to the topic.] +

Set comprehensions make it trivial to find the unique items in a sequence. [FIXME-not sure if I'm going to cover set comprehensions in an earlier chapter; if not, this is certainly an abrupt and inadequate introduction to the topic.]

 >>> a_list = ['a', 'c', 'b', 'a', 'd', 'b']
@@ -97,7 +122,7 @@ if __name__ == '__main__':
 
 

Making assertions

-

Another quick note about a useful debugging tool that's not specific to iterators or generators. Like many programming languages, Python has an assert statement. Here's how it works. +

Like many programming languages, Python has an assert statement. Here's how it works.

 >>> assert 1 + 1 == 2  
@@ -330,6 +355,7 @@ for guess in itertools.permutations(digits, len(characters)):
 
 

A New Kind Of String Manipulation

+

Strings have a powerful

 >>> characters = tuple(ord(c) for c in 'SMEDONRY')
 >>> characters
@@ -361,7 +387,7 @@ for guess in itertools.permutations(digits, len(characters)):
 
 

Putting It All Together

-

To recap: the solver solves alphametic puzzles by brute force, i.e. through an exhaustive search of all possible solutions. To do this, it… +

To recap: this program solves alphametic puzzles by brute force, i.e. through an exhaustive search of all possible solutions. To do this, it…

  1. Finds all the letters in the puzzle with the re.findall() function @@ -375,7 +401,7 @@ for guess in itertools.permutations(digits, len(characters)):
  2. Returns the first solution that evaluates to True
-

…in 14 lines of code. +

…in just 14 lines of code.

Further Reading

diff --git a/examples/alphametics.py b/examples/alphametics.py index 2476eaa..2c9c515 100644 --- a/examples/alphametics.py +++ b/examples/alphametics.py @@ -20,8 +20,6 @@ def solve(puzzle): zero = digits[0] for guess in itertools.permutations(digits, len(characters)): if zero not in guess[:n]: - print(guess) - return equation = puzzle.translate(dict(zip(characters, guess))) if eval(equation): return equation