[Tutor] Creating lists with definite (n) items without repetitions

Francesco A. Loffredo fal at libero.it
Mon Sep 21 23:54:25 CEST 2015


On 15/09/2015 23.14, Francesco A. Loffredo wrote:

    On 14/09/2015 13:50, Oscar Benjamin wrote:

        ...   Your algorithm loops through all triples and accepts any
        triple if it doesn't immediately conflict with any of the
        triples already accepted.
        If you were solving a sudoku puzzle then an analogous algorithm
        would
        take each empty square and fill it with any number that doesn't
        contradict any of the currently filled squares. If you try this on a
        real puzzle then you will reach a dead end and you won't fill the
        grid. The problem is that some of the squares you filled in
        could have
        had a number of possible values and you've just chosen them
        arbitrarily (and incorrectly).


        ...
        Also there will be many possible solutions and you only really
        need to
        find one. Up to isomorphism there is 1 solution for N=9 but that
        means
        there will be 9! isomorphic solutions (the number of ways of
        relabelling the numbers 1 through 9). This means that you may
        not have
        to go far in the search before coming across a solution.

        -- 
        Oscar

    Thank you for your explanation, Oscar! I'll study a better algorithm
    and I'll post it here. While I hope Marcus Luetolf ( the OP) will
    find it useful, I will certainly get some learning from this exercise.

Still thinking about it. I have read about Steiner systems and the 
Social Golfer problem, and I'm afraid this will remain an Unsolved 
Problem despite my efforts. Up to now, I thought that backtracking can't 
be a solution, unless I can rethink my algorithm as a tree traversal.
Problem is, when you arrive at the end of the combos list and you 
discover you hit a dead end, how can you choose which triple you should 
change?
One possible solution is a non-deterministic one: instead of reading the 
list in order, I could shuffle it. And if my solution doesn't match the 
formula, I could simply repeat the random reading of the list. As you 
said, <<you may not have to go far in the search before coming across a 
solution>>!

Of course, dear Tutors, if some of you can think a way to educate my 
guessing, you're more than welcome!

Here is my current algorithm:

import pprint, itertools, random, math
poolbase = 
"abcdefghijklmnopqrstuvwxyz!ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789"

def maketriples(tuplelist):
     final = []
     used = set()
     for a, b, c in tuplelist:
         if ( ((a,b) in used) or ((b,c) in used) or ((a,c) in used) or 
((b,a) in used) or ((c,b) in used) or ((c,a) in used) ):
             continue
         else:
             final.append((a, b, c))
             used.add((a,b))
             used.add((a,c))
             used.add((b,c))
             used.add((b,a))
             used.add((c,a))
             used.add((c,b))
     return final

def formula(sequence):
     dim = len(sequence)
     return (dim * (dim - 1) / 6)

for i in range(3, len(poolbase) + 1):
     pool = poolbase[:i]
     print("pool = %s:  -> '%s'" % (i, pool))
     combos = list(itertools.combinations(pool, 3))
     print("combos contains %s triples." % len(combos))

     now_quit = 100 * len(combos)
     matching = False
     tries_count = 0
     theory = formula(pool)
     while not matching:
         triples = maketriples(random.sample(combos, len(combos)))
         tries_count += 1
         matching = (len(triples) == theory)
         if matching:
             print("Found a match after %s tries!" % tries_count)
         else:
             if not (tries_count % (10 ** int(math.log(tries_count, 10)))):
                 print("Tried %s times..." % tries_count)
             if tries_count > now_quit:
                 print("Reached %s tries, now quitting!" % tries_count)
                 break

     print("maketriples(combos) yields %s triples." % len(triples))
     print("formula(pool) gives %s." % theory)
     if matching:
         pprint.pprint(triples)
         input("\n--- Press Enter ---")
     else:
         print("\n\n")
     print("-------------------------------------")

---------------------------
Francesco


More information about the Tutor mailing list