[Tutor] Re: newbie looking for code suggestions

Thorsten Kampe thorsten@thorstenkampe.de
Mon, 23 Sep 2002 13:37:36 +0200


* Danny Yoo
>>> Okay, so mathematically spoken, you want the size of a certain
>>> list where each item is equivalent to the others by it's cross sum
>>> (sorry Magnus). This is the code for the "equivalent lists":
>>> [...]
>>> >>> min_number, max_number, digit_total = 1, 999999, 21
>>> >>> len(quotient_set(range(min_number, max_number+1), cross_sum)[str(digit_total)])
>>> 39962

> Wow, very cool. That quotient_set() function is appearing
> everywhere! *grin* I hadn't thought about applying quotient_set()
> this way to solve the problem.

I didn't someday think to myself: "I'm so bored, let's code something
/really/ weird: why not ... equivalence classes?!" But I was noticing
that a lot of day-to-day problems were - at least partially - solved
by grouping related ("equivalent") elements.

The one thing I do not like about the algorithm is that I had to write
"repr(func(item)" because some func(item) (list or dictionary) might
not be hashable. So other programs that process the quotient set
further have to do "eval(key)"/"eval(repr(func(item)))".

One possible solution is to pass a flag to quotient_set() meaning: "I
guarantee all func(item) are hashable, so omit 'repr(func(item))',
just hash func(item)"


Here are two functions demonstrating the use of quotient_set():
#v+
def set(seq):
    """ make seq a true set by removing duplicates """
    return [item[0] for item in quotient_set(seq, lambda x: x).values()]

def extr(seq, func):
    """ return [(min(func(seq)), min_func_seq), (max(func(seq)), max_func_seq)] """
    equiv_classes = [(eval(key), value) for key, value in quotient_set(seq, func).items()]
    return [(min(equiv_classes)), (max(equiv_classes))]
#v-

The first one is pretty self explanatory and the second is related to
the fact that in math you're often not interested in maximum or
minimum but in "the extrema", for instance:

* here's a bunch of reals, give me those with the smallest fractional
  part:
  extr(list_of_reals, lambda x: math.modf(x)[0])[0][1]

  sorry, I meant the /biggest/:
  extr(list_of_reals, lambda x: math.modf(x)[0])[1][1]

  yes, but I need to know the fractional part, too:
  extr(list_of_reals, lambda x: math.modf(x)[0])[1]

* here's a list of words. I want the longest words, please:
  extr(list_of_words, len)[1][1]

  sorry, I meant: just the size of the longest word(s):
  extr(list_of_words, len)[1][0]

  
Thorsten