More Itertools Techniques
We built a dictionary that maps from the truncated RGB color to the closest crayon.
In order to use this mapping, we'll truncate a source color before looking up the
nearest crayon in the mapping. This use of truncation coupled with the precomputed
mapping shows how we might need to combine mapping techniques.
The following are the commands for the image replacement:
clone = img.copy()
for xy, p in pixel_iter(img):
r, g, b = p
repl = color_map[(([(0b11100000&r, 0b11100000&g,
0b11100000&b)]])]
clone.putpixel(xy, repl)
clone.show()
This simply uses a number of PIL features to replace all of the pixels in a picture with
other pixels.
What we've seen is that the naïve use of some functional programming tools can lead
to algorithms that are expressive and succinct, but also inefficient. The essential tools
to compute the complexity of a calculation—sometimes called Big-O analysis—is just
as important for functional programming as it is for imperative programming.
The problem is not that the product() function is inefficient. The problem is that we
can use the product() function in an inefficient algorithm.
Permuting a collection of values
When we permute a collection of values, we'll elaborate all the possible orders for the
items. There are n! ways to permute n items. We can use permutations as a kind of
brute-force solution to a variety of optimization problems.
By visiting http://en.wikipedia.org/wiki/Combinatorial_optimization,
we can see that the exhaustive enumeration of all permutations isn't appropriate
for larger problems. The use of the itertools.permutations() function is a handy
way to explore very small problems.
One popular example of these combinatorial optimization problems is the
assignment problem. We have n agents and n tasks, but the cost of each agent
performing a given task is not equal. Imagine that some agents have trouble with
some details, while other agents excel at these details. If we can properly assign tasks
to agents, we can minimize the costs.