# [Tutor] Creating lists with 3 (later4) items occuring only once

Martin A. Brown martin at linux-ip.net
Sun Sep 27 21:22:43 CEST 2015

```Hello Marcus,

> I never exspected to get such motivating comments and advice !!!
> Thank you again.

Much appreciated!  Each of us contributes to this mailing list in
some way or another.  And, not a one of us sprang fully-formed from
Zeus's head with our Python expertise.

> 1. I explain my task in plain text:
> Flights (in golfers language) or Triples (in computer language)  composed of
> 3 golfers  (in golfers language)  or 3 letters (in
> computer language)  play once a day for n days.
> Each golfer or letter should only once be combined with another, meaning a
> combination of 2 golfers/letters should never
> be    >1  for n days.

OK, so this certainly appears to be the social golfer problem or
some similar variant.

I had never heard of it before your posting and it is not a problem
space I'm familiar with.  Earlier, people pointed out the similarity
of the Steiner triple system and Kirkman's schoolgirl problem.  I
think this is where you should study now.  I suspect that you would
benefit more from talking to somebody who knows combinatorics and/or
this particular problem.

In particular, I think the closest already-proposed partial solution
to your problem was from Marc Tompkins.  You might have a second
look at that and see what you make of it:

https://mail.python.org/pipermail/tutor/2015-September/106695.html

I also find myself asking the same question Marc asked at the end of
his posting:  How confident are you about the number 301?

> 2. I considered ['a +b', 'a + c', 'b+c'] == ['a','b','c']

This is a combination.  So, for example, for this very small part of

>>> list(itertools.combinations(('a','b','c'), 2))
[('a', 'b'), ('a', 'c'), ('b', 'c')]

Now, you need to figure out how to keep the stuff you want and pitch
the duplicates.

> 3. I'am glad that it can be done with all letters. However, with
> Triples I need a number dividable by 3 so the maximum would be 24
> golfers or letters.
>
> That is why I limited my samples to 9 and 15. 5 and 7 would not
> work since ther are prime numbers.
>
> I hope to get a program allowing to change the varables like
> number of days played(n) and number of golfers/letters, up to a
> max of 24 according to different situations.

Here's how I would accomplish the second part (this is an
implementation suggestion only):

import sys
import string

if __name__ == '__main__':
try:
alphalength = int(sys.argv[1])
except IndexError:
alphalength = 5
alphabet = string.ascii_letters[:alphalength]

result = compute_solution(alphabet)

# -- print result or summary stats on result

You would still have to write the computation to solve your problem
and apply all the constraints you wish to apply.

Now, the part that I have not done anything with is the matter of
days played.

> The posting of your sample with 5 letters below is correct.

I goofed in my generation of the list.  After writing a bit of code
to try it out, I see that the last item in the list below, ('c',
'd', 'e'), should have been discarded because pair ('c', 'd') was

[
('a', 'b', 'c'),   # keep
('a', 'c', 'd'),   # keep
('a', 'd', 'e'),   # keep
('b', 'c', 'd'),   # discard; subsequences ('b', 'c') and ('c', 'd') already seen
]

> That  made me think itertools might not be the right tool.

It can be part of the solution.  See above (and below).  Of course,
it's not the whole solution--that's your challenge, isn't it?

Here are the parts of the problem with which itertools can help you.

#1: It can generate the list of possible triples for you:

itertools.combinations('abcde', 3)

#2: From each triple, it can generate the pairs:

itertools.combinations(('a', 'b', 'c'), 2)

> the subsequences with "already seen's"
> 4 Triples/sequences are left but a variance of the contained letters:
>     'a' occurs 3 times
>     'b' occurs 1 time
>     'c' occurs 3 times
>     'd' occurs 3 times
>     'e' occurs 2 times
> which of course does not fit my task.
>
> However, I noticed  variance gets smaller with bigger samples and might turn
> 0 with 24 letters.

The variance decrease seems nifty.

> But I don't know how to eliminate the "already seen's" by code.

Ah-ha!  Well, see Marc Tompkins' code for an example of tracking
"already seen" pairs.  Here's a generic technique that will work for

# assume a single triple, for example
triple = ('a', 'b', 'c')
gen_pairs = lambda x: itertools.combinations(x, 2)
for pair in gen_pairs(triple):
# after the loop completes, you should have:
# already_seen = {('a', 'b'), ('a', 'c'), ('b', 'c')}

You can then, later, test to see if the pair(s) are in the

> You are absolutely right that one has to write down first exactly his task
> to be accomplished. But my knowledge goes only
> as far as "Python for Infomatics" (by MOOC/Coursera) and "Practical
> Programming" . I know there are a myriad of other
> modules and tools etc. and there I need the help of "Pythonistas".
>
> To where should I proceed now ?

I would suggest the following:

* write down the problem as you understand it
* write code to solve the problem
* find a shortcoming in the code (or your description of the problem)
* try to fix the problem description or the code
- if success, pat yourself on the back and drink a beer (or whatever)
- if failure, send the smallest possible relevant problem description and code
to the Python tutor list and we will try to help

While this has been a bit of a fun problem and learning experience
for me, I am going to stop posting on this thread.  I lack
sufficient experience in combinatorics to guide you in thinking