Discussion:
[Tutor] Creating lists with 3 (later4) items occuring only once
marcus lütolf
2015-09-18 15:41:52 UTC
Permalink
dear pythonistas

in the code below
import string, itertools
s = ['ab','ac','bc','ad','ae','de']
count = 0
count = count + 1
stl = list(startlist)
print count, stl
x = stl.count(pair)
print x, pair
the variable stl produces 20 lists. The variable x counts how many times the items of s occur in each of the 20 lists.
How can I concatenate the 20 lists in oder to get one count for each of the items in s , for example 10 for 'ab'?
My further task will be expand s to all 26 letters oft he alphabet (giving 325 items) and the to eliminate all list in which the items in s occur more than once.

Thank you for help, Marcus.



---
Diese E-Mail wurde von Avast Antivirus-Software auf Viren geprüft.
https://www.avast.com/antivirus

_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org
Alan Gauld
2015-09-18 16:57:55 UTC
Permalink
Post by marcus lütolf
s = ['ab','ac','bc','ad','ae','de']
How can I concatenate the 20 lists in oder to get one count for each of the items in s , for example 10 for 'ab'?
counts = {'ab':0,'ac':0,'bc':0,'ad':0,'ae':0,'de':0}
... for pair in combo:
... counts[pair] += 1
...
Post by marcus lütolf
counts
{'ac': 10, 'ab': 10, 'ae': 10, 'ad': 10, 'bc': 10, 'de': 10}

Is that what you want?
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://
marcus lütolf
2015-09-20 15:47:01 UTC
Permalink
Hi Alan G,
thanks for your quick answer.

The copy of my code below, sent on 18/09/15 16:41 is for some reasons incomplete. It should read
Post by marcus lütolf
import string, itertools
s = ['ab','ac','bc','ad','ae','de']
count = 0
count = count + 1
stl = list(startlist)
print count, stl
x = stl.count(pair)
print x, pair
My task is to have lists containing 3 tuples, each tuple ocurring only once. In my code above I started off with 6 tuples ( = s) of which 20
lists (count) are produced containing each of the 6 tuples multiple times.
Therefore, I try to write additional code for eliminating all lists which contain tuples occuring more than once.
If I use all 325 tuples I would first get many thousand lists.
Your code proposal uses dictionaries. If I used dictionaries with all the 325 possible tuples I would have to do a lot of typing and not
getting lists with 3 tuples in it.
So, I am stuck somehow and hope to have made my tasks clear.

Thanks for further help, Marcus.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-----Ursprüngliche Nachricht-----
Von: Tutor [mailto:tutor-bounces+marcus.luetolf=***@python.org] Im Auftrag von Alan Gauld
Gesendet: Freitag, 18. September 2015 18:58
An: ***@python.org
Betreff: Re: [Tutor] Creating lists with 3 (later4) items occuring only once
Post by marcus lütolf
s = ['ab','ac','bc','ad','ae','de'] for startlist in
How can I concatenate the 20 lists in oder to get one count for each of the items in s , for example 10 for 'ab'?
counts = {'ab':0,'ac':0,'bc':0,'ad':0,'ae':0,'de':0}
... for pair in combo:
... counts[pair] += 1
...
Post by marcus lütolf
counts
{'ac': 10, 'ab': 10, 'ae': 10, 'ad': 10, 'bc': 10, 'de': 10}

Is that what you want?

--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


---
Diese E-Mail wurde von Avast Antivirus-Software auf Viren geprüft.
https://www.avast.com/antivirus

_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.o
Martin A. Brown
2015-09-21 18:16:29 UTC
Permalink
Hello again Marcus,
My task is to have lists containing 3 tuples, each tuple ocurring
only once. In my code above I started off with 6 tuples ( = s) of
which 20 lists (count) are produced containing each of the 6
tuples multiple times.
Below, I'm confirming that there are 325 input "tuples". I would,
however, call them pairs (since the term tuple has a different
meaning in Python). If I were to turn one of your pairs 'ab' into a
tuple, I would call it ('a', 'b'). Anyway, here's confirmation on
your numbers (I don't think anybody has been doubting these numbers
Post by marcus lütolf
len([''.join(x) for x in itertools.combinations(string.ascii_lowercase, 2)])
325

Confirming that there are 20 combinations starting from 6 pairs
(N.B. you have 6 pairs in your code, although they are slightly
Post by marcus lütolf
s = [''.join(x) for x in itertools.combinations('abcd',2)]
len(s)
6
Post by marcus lütolf
len(list(itertools.combinations(s, 3)))
20
Your code proposal uses dictionaries. If I used dictionaries with
all the 325 possible tuples I would have to do a lot of typing and
not getting lists with 3 tuples in it.
Alan's code proposal was using dictionaries merely to count and
validate. Essentially, all his code did was prove to you (and us)
that itertools.combinations() was doing what it advertises.
Therefore, I try to write additional code for eliminating all
lists which contain tuples occuring more than once. If I use all
325 tuples I would first get many thousand lists.
So, I am stuck somehow and hope to have made my tasks clear.
The problem remains that none of us understands exactly what you
mean when you say duplicates.

If you use itertools.combinations(), no tuple produced will contain
a pair more than once. So, you clearly have some other duplicate
detection criteria in mind.

In your first postings, you used single letters and built tuple
pairs. Now, you are using concatenated string pairs. This is
syntactic sugar (for most of us). The real issue is that we do not
understand your needs for duplicate detection.

Several people (at least Oscar, Mark, Peter, Alan, Marc and I) have
attempted to infer which duplicates you are trying to remove and
even provide guidance on generic, known solutions to the problem
that you are posing (the Steiner system, for example). Here are
some of the earlier replies:

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

In the following response you sent to the list,

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

you mentioned golfers and the passing of time, but you made no
further explanation of the rules for tossing duplicates.

Could you try again to explain what you mean by duplicate?

It's possible that once you better explain the rules of the system
you are trying to model, somebody can provide further assistance.

[('ab', 'ac', 'ad'),
('ab', 'ac', 'bc'),
('ab', 'ac', 'bd'),
('ab', 'ac', 'cd'),
('ab', 'ad', 'bc'),
('ab', 'ad', 'bd'),
('ab', 'ad', 'cd'),
('ab', 'bc', 'bd'),
('ab', 'bc', 'cd'),
('ab', 'bd', 'cd'),
('ac', 'ad', 'bc'),
('ac', 'ad', 'bd'),
('ac', 'ad', 'cd'),
('ac', 'bc', 'bd'),
('ac', 'bc', 'cd'),
('ac', 'bd', 'cd'),
('ad', 'bc', 'bd'),
('ad', 'bc', 'cd'),
('ad', 'bd', 'cd'),
('bc', 'bd', 'cd')]

I've pasted above a small list of tuples (using your most recent
pair generation). Could you annotate each tuple and explain why it
should be kept or thrown away? That may help me (and any others who
are interested) understand what you are asking.

-Martin
Post by marcus lütolf
s = ['ab','ac','bc','ad','ae','de'] for startlist in
How can I concatenate the 20 lists in oder to get one count for each of the items in s , for example 10 for 'ab'?
counts = {'ab':0,'ac':0,'bc':0,'ad':0,'ae':0,'de':0}
... counts[pair] += 1
...
Post by marcus lütolf
counts
{'ac': 10, 'ab': 10, 'ae': 10, 'ad': 10, 'bc': 10, 'de': 10}
Is that what you want?
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
http://www.flickr.com/photos/alangauldphotos
_______________________________________________
https://mail.python.org/mailman/listinfo/tutor
---
Diese E-Mail wurde von Avast Antivirus-Software auf Viren geprüft.
https://www.avast.com/antivirus
_______________________________________________
https://mail.python.org/mailman/listinfo/tutor
--
Martin A. Brown
http://linux-ip.net/
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/ma
Martin A. Brown
2015-09-22 01:10:04 UTC
Permalink
Marcus,

I have more questions for you, as well as a possible solution
(though it's a bit more verbose than I would have liked to offer).

Question:

Problem A: Are you looking to identify the complete set of
possible options for constructing the triples of pairs?

Problem B: Are you looking only to construct one set that
satisfies the problem? [see my lousy solution]

You may observe that the question I ask is quite similar to the
question asked by Francesco [0].

If you are asking about the complete set of possible options
(Problem A), then I submit to you that you are asking a mathematical
question, not a Python question. If that's the case, perhaps you
should look further into the Steiner system and/or ask again on the
list.

If you are asking about finding an individual solution satisfying
the constraints, I submit to you that either my approach or
Francesco's approach could work for you. If that's the case, then
using random.sample may offer you some help. See my sample,
below--it should work on Python 2.x or Python 3.x.

Comments:

* There are rules in your system about when a player can play
again. The rules were not fully clear to me, so I allowed
players to be selecteda second time, if there were no more
players who had not already been chosen.

* This program produces only one possible scenario for 7
rounds of 3 distinct, simultaneously played 2-player games.
No player can play twice in the same round. (Simple arithmetic
determines the minimum number of players.)

If your question is Problem A, then I wonder if you know anybody who
knows combinatorics? I do not.

-Martin

[0] https://mail.python.org/pipermail/tutor/2015-September/106820.html


#! /usr/bin/python

from __future__ import print_function

import sys
import string
import random
import logging

logging.basicConfig(stream=sys.stderr, level=logging.INFO)
logger = logging.getLogger()


class NotEnoughPlayers(Exception):
pass


def choose_game_participants(players, pcount=2):
'''returns a tuple of players for a single game
'''
if len(players) < pcount:
raise NotEnoughPlayers("not enough players, need %d, have only %d: %r" %
(pcount, len(players), players))
game = tuple(sorted(random.sample(players, pcount)))
return game


def choose_match_games(players, pcount=2, gcount=3):
'''returns a list of games where no player is duplicated
'''
mcount = pcount * gcount
if len(players) < mcount:
raise NotEnoughPlayers("not enough players, need %d, have only %d: %r" %
(mcount, len(players), players))
eligible_players = random.sample(players, mcount)
match = list()
while eligible_players:
m = choose_game_participants(eligible_players, pcount)
for x in m:
eligible_players.remove(x)
match.append(m)
match.sort() # optional
return match


def generate_rounds(players, pcount, gcount, rcount):
games = set()
matches = list()
mcount = pcount * gcount
eligible_players = list(players)
if mcount > len(eligible_players):
raise NotEnoughPlayers("not enough players (%d) to guarantee %d %d-player games per match" %
(len(eligible_players), gcount, pcount))
r = 1
while r <= rcount:
try:
proposed_match = choose_match_games(eligible_players, pcount, gcount)
except NotEnoughPlayers:
logger.info("adding %d additional players in round %d to meet minimum pool requirements",
mcount, r)
how_many = mcount - len(eligible_players)
eligible_players.extend(random.sample(players, how_many))
continue
already_played = games.intersection(set(proposed_match))
if already_played:
logger.info("discarding %d %r because %r have already played",
r, proposed_match, list(already_played))
continue
else:
games.update(proposed_match)
matches.append(proposed_match)
logger.info('Proposed match %r', proposed_match)
for game in proposed_match:
for player in game:
eligible_players.remove(player)
r = r + 1
return matches


def log_match_info(matches, detail=False):
for mnum, match in enumerate(matches, 1):
logger.info("match summary %d: %r", mnum, match)
for gnum, game in enumerate(match, 1):
if not detail:
continue
logger.info("match detail %d, game %d: players %r",
mnum, gnum, game)


def log_match_summary(matches):
log_match_info(matches, detail=False)


def log_match_detail(matches):
log_match_info(matches, detail=True)


if __name__ == '__main__':
players = list(string.ascii_uppercase)
random.shuffle(players)
# players = set('ABCDEFGHIJ')
pcount = 2 # players per game
gcount = 3 # games per match
rcount = 7 # rounds (of matches)
matches = generate_rounds(players, pcount, gcount, rcount)
log_match_detail(matches)

# -- end of file
--
Martin A. Brown
http://linux-ip.net/
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Martin A. Brown
2015-09-26 17:37:53 UTC
Permalink
Good morning(PDT)/evening(CET) Marcus,
again thanks for your endeavour, ist tought me to really think deeply how to
specify my task fort he Python language.
Before I start to work with your "heavy" piece of code for a beginner below
1. my task is to create lists or tupleS (whichever works best) containing 3
letters, later to be assigned names, in unique sequences.
OK. So, your second round of postings was closer to the actual
problem you are trying to solve. And, now, it's clear to me that
you are operating with triples.

You are doing something with pairs, but I don't understand what.
See below.
2. My first approach with pairs like 'a b', 'a c',..... does not work with
itertools.combinations(s, 3): Although, it produces lists/tuples with 3
pairs
there are 4 letters in each list/tuple whereas I need only 3.
Understood.
3. Therfore, I'am working with single letters creating lists/tuples with 3
letters: ('a', 'b', 'c'), ('a','b','d')........
Impossible to handle.
Not impossible, at all. And, in fact, here is a wonderful point.

If you can describe the problem using a small sample and capture all
of the rules of your system (or model), then you can write a program
to solve that problem. Professional programmers often use small
data samples like this to test the validity of their code, before
running the code on a larger input data set.

Also, it sounds like you want to solve problem A, which is to
enumerate (or simply find the size of) the result set in this system
you are constructing.
Using only 15 letters would already create 455 lists/tuples.
The 9 letters produce 84 lists/tuples.
len(list(itertools.combinations(string.ascii_lowercase[:9], 3)))
84
len(list(itertools.combinations(string.ascii_lowercase[:15], 3)))
455
So I am using 9 letters which is practical for one letter or name can be
combined with 2 others 5 times or on 5 days, each letter/name can occur
only once a day.
But if I am isolating lists/tuple with unique sequences by hand
It is precisely here that I (and probably the others on this mailing
list) do not understand what you are trying to accomplish. What are
the rules that you are using for 'isolating lists with unique
sequences'? It sounds like something with subsequences.

I'm going to make a stab at writing down the rules I think you may
be using. I will probably be wrong. Please correct me.

As noted above, I'm going to use a very small sample, using an
"alphabet" of 5 letters. I'm taking a stab at the rules in your
system and writing down. Could you correct and/or explain whether I
have understood what you are doing?

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

Now, some additional, more general, comments....
4. I have come to the conclusion that my task is too mathematical for
itertools.
It's possible that itertools may not have the tools exactly that
you are looking for, but several of us suggested it because there
seems to be some part of your problem that can be satisfied by the
module. Maybe you need some other algorithm or module.

I'll make an analogy. When you are building a house, you use many
different sorts of tools and materials. Though programming involves
no tangible result, there are many tools and techniques you can
apply. Which sort of tool we might recommend depends on what sort
of house you want to build. Do you want to build a house of stone,
brick or wood? With curved railings? Clear or stained glass
windows?

We can help you by suggesting things like Python's itertools or
other modules. We can suggest alternate approaches or algorithms.
We can also help with the technical implementation (i.e. what does
the code look like), but we can only help if the problem is clearly
understood.

Some of us can even help with the mathematical part of the problem
(I, less so than some of the others on this list).

Understanding the problem, though, is the beginning of the process
of writing software.
[taught] me to really think deeply how to specify my task [for
the] Python language.
You will always benefit from thinking deeply about what you hope to
accomplish before starting to code. (I have known quite a few
programmers with decades of experience who will not touch the
computer until they have written a description of the problem on
paper.)

Also: There is no shame in writing code and throwing it away if it
helps you get closer to the solution. It's common (and a good idea)
to throw away code.
I hope I can be successfull with your code below although it will
me take time to comprehend it.
Don't worry unduly about my code. Note that it solves Problem B,
providing one possible example. This appears not to be what you
want. It will not enumerate all possible examples.

Good luck and enjoy the remainder of your weekend, Marcus,

-Martin
-----Ursprüngliche Nachricht-----
Gesendet: Dienstag, 22. September 2015 03:10
Betreff: Re: [Tutor] Creating lists with 3 (later4) items occuring only once
Marcus,
I have more questions for you, as well as a possible solution (though it's a
bit more verbose than I would have liked to offer).
Problem A: Are you looking to identify the complete set of
possible options for constructing the triples of pairs?
Problem B: Are you looking only to construct one set that
satisfies the problem? [see my lousy solution]
You may observe that the question I ask is quite similar to the question
asked by Francesco [0].
If you are asking about the complete set of possible options (Problem A),
then I submit to you that you are asking a mathematical question, not a
Python question. If that's the case, perhaps you should look further into
the Steiner system and/or ask again on the list.
If you are asking about finding an individual solution satisfying the
constraints, I submit to you that either my approach or Francesco's approach
could work for you. If that's the case, then using random.sample may offer
you some help. See my sample, below--it should work on Python 2.x or Python
3.x.
* There are rules in your system about when a player can play
again. The rules were not fully clear to me, so I allowed
players to be selecteda second time, if there were no more
players who had not already been chosen.
* This program produces only one possible scenario for 7
rounds of 3 distinct, simultaneously played 2-player games.
No player can play twice in the same round. (Simple arithmetic
determines the minimum number of players.)
If your question is Problem A, then I wonder if you know anybody who knows
combinatorics? I do not.
-Martin
[0] https://mail.python.org/pipermail/tutor/2015-September/106820.html
#! /usr/bin/python
from __future__ import print_function
import sys
import string
import random
import logging
logging.basicConfig(stream=sys.stderr, level=logging.INFO) logger =
logging.getLogger()
pass
'''returns a tuple of players for a single game
'''
raise NotEnoughPlayers("not enough players, need %d, have only %d: %r" %
(pcount, len(players), players))
game = tuple(sorted(random.sample(players, pcount)))
return game
'''returns a list of games where no player is duplicated
'''
mcount = pcount * gcount
raise NotEnoughPlayers("not enough players, need %d, have only %d: %r" %
(mcount, len(players), players))
eligible_players = random.sample(players, mcount)
match = list()
m = choose_game_participants(eligible_players, pcount)
eligible_players.remove(x)
match.append(m)
match.sort() # optional
return match
games = set()
matches = list()
mcount = pcount * gcount
eligible_players = list(players)
raise NotEnoughPlayers("not enough players (%d) to guarantee %d
%d-player games per match" %
(len(eligible_players), gcount, pcount))
r = 1
proposed_match = choose_match_games(eligible_players, pcount, gcount)
logger.info("adding %d additional players in round %d to meet
minimum pool requirements",
mcount, r)
how_many = mcount - len(eligible_players)
eligible_players.extend(random.sample(players, how_many))
continue
already_played = games.intersection(set(proposed_match))
logger.info("discarding %d %r because %r have already played",
r, proposed_match, list(already_played))
continue
games.update(proposed_match)
matches.append(proposed_match)
logger.info('Proposed match %r', proposed_match)
eligible_players.remove(player)
r = r + 1
return matches
logger.info("match summary %d: %r", mnum, match)
continue
logger.info("match detail %d, game %d: players %r",
mnum, gnum, game)
log_match_info(matches, detail=False)
log_match_info(matches, detail=True)
players = list(string.ascii_uppercase)
random.shuffle(players)
# players = set('ABCDEFGHIJ')
pcount = 2 # players per game
gcount = 3 # games per match
rcount = 7 # rounds (of matches)
matches = generate_rounds(players, pcount, gcount, rcount)
log_match_detail(matches)
# -- end of file
--
Martin A. Brown
http://linux-ip.net/
---
Diese E-Mail wurde von Avast Antivirus-Software auf Viren geprüft.
https://www.avast.com/antivirus
--
Martin A. Brown
http://linux-ip.net/
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
marcus lütolf
2015-09-27 11:39:02 UTC
Permalink
Hello Martin.
I never exspected to get such motivating comments and advice !!! Thank you
again.
Referring to my statments below

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.

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

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. 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.

That is why I limited my samples to 9 and 15. 5 and 7 would not work since
ther are prime numbers.

The posting of your sample with 5 letters below is correct. Having discarded
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. That made me think itertools might
not be the right tool.
However, I noticed variance gets smaller with bigger samples and might turn
0 with 24 letters.
But I don't know how to eliminate the "already seen's" by code.

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 ?

Have a sunny Sunday, Marcus.
----------------------------------------------------------------------------
----------------------------------------------------------------------------
----
-----Ursprüngliche Nachricht-----
Von: Martin A. Brown [mailto:***@linux-ip.net]
Gesendet: Samstag, 26. September 2015 19:38
An: marcus lütolf <***@bluewin.ch>
Cc: ***@python.org
Betreff: Re: AW: [Tutor] Creating lists with 3 (later4) items occuring only
once


Good morning(PDT)/evening(CET) Marcus,
again thanks for your endeavour, ist tought me to really think deeply
how to specify my task fort he Python language.
Before I start to work with your "heavy" piece of code for a beginner
1. my task is to create lists or tupleS (whichever works best)
containing 3 letters, later to be assigned names, in unique sequences.
OK. So, your second round of postings was closer to the actual problem you
are trying to solve. And, now, it's clear to me that you are operating with
triples.

You are doing something with pairs, but I don't understand what.
See below.
2. My first approach with pairs like 'a b', 'a c',..... does not work
with
itertools.combinations(s, 3): Although, it produces lists/tuples with 3
pairs
there are 4 letters in each list/tuple whereas I need only 3.
Understood.
3. Therfore, I'am working with single letters creating lists/tuples with 3
letters: ('a', 'b', 'c'), ('a','b','d')........
Impossible to handle.
Not impossible, at all. And, in fact, here is a wonderful point.

If you can describe the problem using a small sample and capture all of the
rules of your system (or model), then you can write a program to solve that
problem. Professional programmers often use small data samples like this to
test the validity of their code, before running the code on a larger input
data set.

Also, it sounds like you want to solve problem A, which is to enumerate (or
simply find the size of) the result set in this system you are constructing.
Using only 15 letters would already create 455 lists/tuples.
The 9 letters produce 84 lists/tuples.
len(list(itertools.combinations(string.ascii_lowercase[:9], 3)))
84
len(list(itertools.combinations(string.ascii_lowercase[:15], 3)))
455
So I am using 9 letters which is practical for one letter or name can
be combined with 2 others 5 times or on 5 days, each letter/name can
occur only once a day.
But if I am isolating lists/tuple with unique sequences by hand
It is precisely here that I (and probably the others on this mailing
list) do not understand what you are trying to accomplish. What are the
rules that you are using for 'isolating lists with unique sequences'? It
sounds like something with subsequences.

I'm going to make a stab at writing down the rules I think you may be using.
I will probably be wrong. Please correct me.

As noted above, I'm going to use a very small sample, using an "alphabet" of
5 letters. I'm taking a stab at the rules in your system and writing down.
Could you correct and/or explain whether I have understood what you are
doing?

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

Now, some additional, more general, comments....
4. I have come to the conclusion that my task is too mathematical for
itertools.
It's possible that itertools may not have the tools exactly that you are
looking for, but several of us suggested it because there seems to be some
part of your problem that can be satisfied by the module. Maybe you need
some other algorithm or module.

I'll make an analogy. When you are building a house, you use many different
sorts of tools and materials. Though programming involves no tangible
result, there are many tools and techniques you can apply. Which sort of
tool we might recommend depends on what sort of house you want to build. Do
you want to build a house of stone, brick or wood? With curved railings?
Clear or stained glass windows?

We can help you by suggesting things like Python's itertools or other
modules. We can suggest alternate approaches or algorithms.
We can also help with the technical implementation (i.e. what does the code
look like), but we can only help if the problem is clearly understood.

Some of us can even help with the mathematical part of the problem (I, less
so than some of the others on this list).

Understanding the problem, though, is the beginning of the process of
writing software.
[taught] me to really think deeply how to specify my task [for
the] Python language.
You will always benefit from thinking deeply about what you hope to
accomplish before starting to code. (I have known quite a few programmers
with decades of experience who will not touch the computer until they have
written a description of the problem on
paper.)

Also: There is no shame in writing code and throwing it away if it helps
you get closer to the solution. It's common (and a good idea) to throw away
code.
I hope I can be successfull with your code below although it will me
take time to comprehend it.
Don't worry unduly about my code. Note that it solves Problem B, providing
one possible example. This appears not to be what you want. It will not
enumerate all possible examples.

Good luck and enjoy the remainder of your weekend, Marcus,

-Martin
-----Ursprüngliche Nachricht-----
Gesendet: Dienstag, 22. September 2015 03:10
Betreff: Re: [Tutor] Creating lists with 3 (later4) items occuring only once
Marcus,
I have more questions for you, as well as a possible solution (though
it's a bit more verbose than I would have liked to offer).
Problem A: Are you looking to identify the complete set of
possible options for constructing the triples of pairs?
Problem B: Are you looking only to construct one set that
satisfies the problem? [see my lousy solution]
You may observe that the question I ask is quite similar to the
question asked by Francesco [0].
If you are asking about the complete set of possible options (Problem
A), then I submit to you that you are asking a mathematical question,
not a Python question. If that's the case, perhaps you should look
further into the Steiner system and/or ask again on the list.
If you are asking about finding an individual solution satisfying the
constraints, I submit to you that either my approach or Francesco's
approach could work for you. If that's the case, then using
random.sample may offer you some help. See my sample, below--it
should work on Python 2.x or Python 3.x.
* There are rules in your system about when a player can play
again. The rules were not fully clear to me, so I allowed
players to be selecteda second time, if there were no more
players who had not already been chosen.
* This program produces only one possible scenario for 7
rounds of 3 distinct, simultaneously played 2-player games.
No player can play twice in the same round. (Simple arithmetic
determines the minimum number of players.)
If your question is Problem A, then I wonder if you know anybody who
knows combinatorics? I do not.
-Martin
[0]
https://mail.python.org/pipermail/tutor/2015-September/106820.html
#! /usr/bin/python
from __future__ import print_function
import sys
import string
import random
import logging
logging.basicConfig(stream=sys.stderr, level=logging.INFO) logger =
logging.getLogger()
pass
'''returns a tuple of players for a single game
'''
raise NotEnoughPlayers("not enough players, need %d, have only %d: %r" %
(pcount, len(players), players))
game = tuple(sorted(random.sample(players, pcount)))
return game
'''returns a list of games where no player is duplicated
'''
mcount = pcount * gcount
raise NotEnoughPlayers("not enough players, need %d, have only %d: %r" %
(mcount, len(players), players))
eligible_players = random.sample(players, mcount)
match = list()
m = choose_game_participants(eligible_players, pcount)
eligible_players.remove(x)
match.append(m)
match.sort() # optional
return match
games = set()
matches = list()
mcount = pcount * gcount
eligible_players = list(players)
raise NotEnoughPlayers("not enough players (%d) to guarantee
%d %d-player games per match" %
(len(eligible_players), gcount, pcount))
r = 1
proposed_match = choose_match_games(eligible_players,
pcount,
gcount)
logger.info("adding %d additional players in round %d to
meet minimum pool requirements",
mcount, r)
how_many = mcount - len(eligible_players)
eligible_players.extend(random.sample(players, how_many))
continue
already_played = games.intersection(set(proposed_match))
logger.info("discarding %d %r because %r have already played",
r, proposed_match, list(already_played))
continue
games.update(proposed_match)
matches.append(proposed_match)
logger.info('Proposed match %r', proposed_match)
eligible_players.remove(player)
r = r + 1
return matches
logger.info("match summary %d: %r", mnum, match)
continue
logger.info("match detail %d, game %d: players %r",
mnum, gnum, game)
log_match_info(matches, detail=False)
log_match_info(matches, detail=True)
players = list(string.ascii_uppercase)
random.shuffle(players)
# players = set('ABCDEFGHIJ')
pcount = 2 # players per game
gcount = 3 # games per match
rcount = 7 # rounds (of matches)
matches = generate_rounds(players, pcount, gcount, rcount)
log_match_detail(matches)
# -- end of file
--
Martin A. Brown
http://linux-ip.net/
---
Diese E-Mail wurde von Avast Antivirus-Software auf Viren geprüft.
https://www.avast.com/antivirus
--
Martin A. Brown
http://linux-ip.net/


---
Diese E-Mail wurde von Avast Antivirus-Software auf Viren geprüft.
https://www.avast.com/antivirus

_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Martin A. Brown
2015-09-27 19:22:43 UTC
Permalink
Hello Marcus,
Post by marcus lütolf
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.
Post by marcus lütolf
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?
Post by marcus lütolf
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
Post by marcus lütolf
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.
Post by marcus lütolf
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.
Post by marcus lütolf
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
already seen.

[
('a', 'b', 'c'), # keep
('a', 'b', 'd'), # discard; subsequence ('a', 'b') already seen
('a', 'b', 'e'), # discard; subsequence ('a', 'b') already seen
('a', 'c', 'd'), # keep
('a', 'c', 'e'), # discard; subsequence ('a', 'c') already seen
('a', 'd', 'e'), # keep
('b', 'c', 'd'), # discard; subsequences ('b', 'c') and ('c', 'd') already seen
('b', 'c', 'e'), # discard; subsequence ('b', 'c') already seen
('b', 'd', 'e'), # discard; subsequence ('b', 'd') already seen
('c', 'd', 'e') # discard: subsequenc ('c', 'd') already seen
]
Post by marcus lütolf
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)
Post by marcus lütolf
Having discarded
the subsequences with "already seen's"
'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.
Post by marcus lütolf
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
identifying "already seen", but tailored for your problem.

# assume a single triple, for example
triple = ('a', 'b', 'c')
gen_pairs = lambda x: itertools.combinations(x, 2)
already_seen = set()
for pair in gen_pairs(triple):
already_seen.add(pair)
# 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
already_seen set.
Post by marcus lütolf
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
properly (and clearly) about this problem and that is where you are
stuck at the moment. Sorry I can't help you much further.

Good luck, Marcus,

-Martin
--
Martin A. Brown
http://linux-ip.net/
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Oscar Benjamin
2015-09-28 12:36:42 UTC
Permalink
Post by marcus lütolf
Hello Martin.
I never exspected to get such motivating comments and advice !!! Thank you
again.
Referring to my statments below
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.
2. I considered ['a +b', 'a + c', 'b+c'] == ['a','b','c']
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. 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.
That is why I limited my samples to 9 and 15. 5 and 7 would not work since
ther are prime numbers.
Ah okay. This is what I thought your problem was but with an
additional constraint. I will spell out the two constraints formally:

You want a set of triples where each triple consists of three distinct
players and:
1) Each player plays each other player exactly once.
2) It is possible to arrange the triples so that every player plays
once on each day.

Constraint 1 means that you need N=1mod6 or N=3mod6. Constraint 2
means that you need N to be a multiple of three so we cannot have
N=1mod6. This means that we must have N=3mod6 or in other words:

N = 3, 9, 15, 21, 27, ...

If I understand correctly you are only interested to know how to find
a solution to constraints 1) and 2) for these values of N. You do not
care what happens for values of N where a perfect solution is
impossible.
Post by marcus lütolf
The posting of your sample with 5 letters below is correct. Having discarded
the subsequences with "already seen's"
'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. That made me think itertools might
not be the right tool.
However, I noticed variance gets smaller with bigger samples and might turn
0 with 24 letters.
So you want every player to play the same number of times? That's
reasonable. Is it also important that every player plays every other
player exactly once (i.e. constraint 1) )?

Unfortunately you will not be able to meet constraint 1) for N=24
since it is an even number.
Post by marcus lütolf
But I don't know how to eliminate the "already seen's" by code.
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 that you begin working on pen and paper. How can you
construct a solution for N=3, N=9 etc?

An algorithm occurs to me as follows. Consider N=9 so we have golfers ABCDEFGHI.

We know that player A needs to play some games so let's begin there

(A...
...

Player A will at some point need to play both B and C and has not
played them yet so

(ABC)
...

Player A has not played everyone and will need to play players D and E so

(ABC)
(ADE)
...

Continuing we have

(ABC)
(ADE)
(AFG)
(AHI)
...

Now player A has played everyone but player B hasn't so

(ABC)
(ADE)
(AFG)
(AHI)
(B...)
...

Player B has already played both A and C which leaves the
possibilities DEFGHI. At some point player B must play D so let's
assume that's what happens:

(ABC)
(ADE)
(AFG)
(AHI)
(BD...)
...

Who can play with B and D? Well B has played A and C and D has played
A and E. So that leaves FGHI. We now loop through those possibilities
trying each out. This is where the algorithm recurses:

(ABC)
(ADE)
(AFG)
(AHI)
(BDF) - F could be GHI
...

Now B has still not played everyone and at some point B must play G so
let's try that out:

(ABC)
(ADE)
(AFG)
(AHI)
(BDF) - F could be GHI
(BG...)
...

Okay so who can play with B and G. Well B has played ACDF and G has
played AF so we need something that is not ABCDFG which leaves EHI as
possibilities. Let's loop through these trying them out. We'll begin
with E:

(ABC)
(ADE)
(AFG)
(AHI)
(BDF) - F could be GHI
(BGE) - E could be HI
...

Now B still hasn't played everyone and there's only two possibilities
H and I. which gives

(ABC)
(ADE)
(AFG)
(AHI)
(BDF) - F could be GHI
(BGE) - E could be HI
(BHI) <- conflict!!
...

Oh dear H and I have already played each other. Now we need to back
track. Maybe we were wrong to choose E? We'll try H instead:

(ABC)
(ADE)
(AFG)
(AHI)
(BDF) - F could be GHI
(BGH) - H could be I (E was already rejected on backtrack)
...

Now B has one more game to play against E and I:

(ABC)
(ADE)
(AFG)
(AHI)
(BDF) - F could be GHI
(BGH) - H could be I (E was already rejected on backtrack)
(BEI)
...

Okay so now A and B have played everyone. What about C?

And so on...

Follow this through on pen and paper. I don't think it will take too
long. Once you understand the algorithm you can think about how to
tell the computer to do it.

The target is that every player has played every other. You will have
reached this target when the number of triples is N*(N-1)/6. Why is
that? Well how many pairs are there? I can make all pairs by combining
each of N people with each of the N-1 remaining people. However this
double counts each pair since I count AB and BA. So the number of
pairs is N*(N-1)/2. Each pair is contained in exactly one triple and
each triple contains 3 distinct pairs. It follows that the number of
pairs is 3 times the number of triples. So the number of triples is
N*(N-1)/6. If we were working with quadruples instead of triples then
each quadruple contains 6 distinct pairs so the number of quadruples
is N*(N-1)/12.

In general if we work k-tuples then the number of pairs in each
k-tuple is k*(k-1)/2. It follows that the number of k-tuples is
N*(N-1)/(k*(k-1)) so when we have that many we've reached a solution.
Clearly a necessary (but not sufficient) condition for the existence
of a perfect solution is that N*(N-1) is divisible by k*(k-1). We also
know that N-1 needs to be divisible by k-1 since player each player
plays every other player in groups of size k-1. Finally we have that N
itself must be divisible by k so that every golfer can play on every
day. Bringing these together we have that N is divisible by k and N-1
is divisible by k-1.

For triples this gives:

N = 3, 9, 15, 21, 27, 33, ...

which is correct since we already established that N=3mod6.

For quadruples k=4 and we need that N is divisible by 4 and n-1 is
divisible by 3 which gives:

N = 4, 16, 28, 40, 52, ...

In other words N=4mod12.

However is is possible that not all of these admit perfect solutions.

In general you may need to simply try and find a perfect solution
exhaustively but the above two results suggest the general form

N=k mod k*(k-1)

This guarantees that N is divisible by k and N-1 by k-1. Which is
certainly a necessary condition but not necessarily a sufficient one.

--
Oscar
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinf

Loading...