Re: [Tutor] Creating lists with 3 (later4) items occuring only once
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:mar...@linux-ip.net] Gesendet: Samstag, 26. September 2015 19:38 An: marcus lütolf <marcus.luet...@bluewin.ch> Cc: tutor@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 > below I like to make the following statements: > > 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') > Using all 26 letters of the alphabet would correspond to Problem A: > 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. Confirmed: >>> 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
Re: [Tutor] Creating lists with 3 (later4) items occuring only once
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 your problem: >>> 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 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 ] 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) 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. 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 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)
Re: [Tutor] Creating lists with 3 (later4) items occuring only once
Hello Martin, 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 I like to make the following statements: 1. my task is to create lists or tupleS (whichever works best) containing 3 letters, later to be assigned names, in unique sequences. 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. 3. Therfore, I'am working with single letters creating lists/tuples with 3 letters: ('a', 'b', 'c'), ('a','b','d') Using all 26 letters of the alphabet would correspond to Problem A: Impossible to handle. Using only 15 letters would already create 455 lists/tuples. 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. The 9 letters produce 84 lists/tuples. But if I am isolating lists/tuple with unique sequences by hand I am left with 15 lists/tuples but with a uneven distrubution of the 9 letters: a 8 b 5 c 6 d 5 e 6 f 6 g 4 h 4 i 4 This variance gets the smaller the more letters are used. 4. I have come to the conclusion that my task is too mathematical for itertools. I hope I can be successfull with your code below although it will me take time to comprehend it. Sorry for this long text, regards, Marcus. -Ursprüngliche Nachricht- Von: Martin A. Brown [mailto:mar...@linux-ip.net] Gesendet: Dienstag, 22. September 2015 03:10 An: marcus lütolf <marcus.luet...@bluewin.ch> Cc: tutor@python.org 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). 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 eligi
Re: [Tutor] Creating lists with 3 (later4) items occuring only once
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- Von: Martin A. Brown [mailto:mar...@linux-ip.net] Gesendet: Dienstag, 22. September 2015 03:10 An: marcus lütolf <marcus.luet...@bluewin.ch> Cc: tutor@python.org 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). 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))
Re: [Tutor] Creating lists with definite (n) items without repetitions
On 21 September 2015 at 22:54, Francesco A. Loffredowrote: >> > 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? I would remove the last one added and then loop over all triples starting from the one after that. I have written a simple implementation below. The problem is that it's really slow for anything more than N=9. There are many ways it can be improved though if you want it to scale to higher levels: #!/usr/bin/env python from itertools import permutations, combinations import pprint, itertools def get_triples(labels): Nlabels = len(labels) if Nlabels % 6 not in (1, 3): raise ValueError("No exact solution") target = (Nlabels * (Nlabels - 1)) // 6 all_triples = list(combinations(labels, 3)) Ntriples = len(all_triples) triples = [] pairs = set() start_index = 0 while True: for index in range(start_index, Ntriples): triple = all_triples[index] # If the triple fits try it out and see what happens... if not any(p in pairs for p in combinations(triple, 2)): triples.append((triple, index)) pairs.update(permutations(triple, 2)) # Success! if len(triples) == target: return [triple for triple, _ in triples] else: # We tried every combination of the current triples # and all subsequently available triples. Time to # pop off the triple at the top and look for another # one to replace it. triple, start_index = triples.pop() pairs.difference_update(permutations(triple, 2)) # Start from the triple after the popped one. start_index += 1 if __name__ == "__main__": import sys Nlabels = int(sys.argv[1]) labels = range(1, Nlabels + 1) triples = get_triples(labels) pprint.pprint(triples) To improve on this I would probably work on it as a constraint propagation problem rather than looping over all the combinations. The problem with backtracking on the full set of combinations is that it grows combinatorially which means it gets complicated very quickly as N increases. For N=9 this ran in 50ms. At the time of writing I'm still waiting for it to finish N=13 under pypy (it's only been a couple of minutes). I don't know if I expect it to finish in a few seconds or take longer than the age of the universe. -- Oscar ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
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). 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 =
Re: [Tutor] Creating lists with definite (n) items without repetitions
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,>! 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 ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with 3 (later4) items occuring only once
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 >>> import string, itertools >>> s = ['ab','ac','bc','ad','ae','de'] >>> count = 0 >>> for startlist in itertools.combinations(s, 3): >>> count = count + 1 >>> stl = list(startlist) >>> print count, stl >>> for pair in s: >>> 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=bluewin...@python.org] Im Auftrag von Alan Gauld Gesendet: Freitag, 18. September 2015 18:58 An: tutor@python.org Betreff: Re: [Tutor] Creating lists with 3 (later4) items occuring only once On 18/09/15 16:41, marcus lütolf wrote: >>>> s = ['ab','ac','bc','ad','ae','de'] for startlist in >>>> itertools.combinations(s, 3): > 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'? If I understand you correctly, something like this: >>> counts = {'ab':0,'ac':0,'bc':0,'ad':0,'ae':0,'de':0} >>> for combo in it.combinations(counts.keys(),3): ... for pair in combo: ...counts[pair] += 1 ... >>> 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 - Tutor@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 - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with 3 (later4) items occuring only once
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 that you keep repeating; I'm just confirming them): >>> 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 different than my 6 pairs): >>> s = [''.join(x) for x in itertools.combinations('abcd',2)] >>> len(s) 6 >>> 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 s = ['ab','ac','bc','ad','ae','de'] for startlist in itertools.combinations(s, 3): 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'? If I understand you correctly, something like this: >>> counts = {'ab':0,'ac':0,'bc':0,'ad':0,'ae':0,'de':0} >>> for combo in it.combinations(counts.keys(),3): ... for pair in combo: ...counts[pair] += 1 ... >>> 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 - Tutor@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 - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor -- Martin A. Brown http://linux-ip.net/
Re: [Tutor] Creating lists with 3 (later4) items occuring only once
On 18/09/15 16:41, marcus lütolf wrote: s = ['ab','ac','bc','ad','ae','de'] for startlist in itertools.combinations(s, 3): 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'? If I understand you correctly, something like this: >>> counts = {'ab':0,'ac':0,'bc':0,'ad':0,'ae':0,'de':0} >>> for combo in it.combinations(counts.keys(),3): ... for pair in combo: ...counts[pair] += 1 ... >>> 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 - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
On 18/09/15 16:17, marcus lütolf wrote: dear pythonistas, in the code below: how can I solve my task wit n items ? Thank you for help, Marcus. I see no code... -- 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 - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Creating lists with definite (n) items without repetitions
dear pythonistas, in the code below: how can I solve my task wit n items ? Thank you for help, Marcus. --- Diese E-Mail wurde von Avast Antivirus-Software auf Viren geprüft. https://www.avast.com/antivirus ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Creating lists with 3 (later4) items occuring only once
dear pythonistas in the code below >>> import string, itertools >>> s = ['ab','ac','bc','ad','ae','de'] >>> count = 0 >>> for startlist in itertools.combinations(s, 3): >>> count = count + 1 >>> stl = list(startlist) >>> print count, stl >>> for pair in s: >>> 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 - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
On 14/09/2015 13:50, Oscar Benjamin wrote: On 10 September 2015 at 08:45, Francesco Loffredo via Tutorwrote: I wrote a small routine (below) to check when and if my code and the formula do match. It easily shows that they only match for len(pool) == (2 ** N) - 1, with N greater or equal to 2. That's interesting. I'm not sure exactly why that would happen. My problem remains: WHY don't they match for every length? Your algorithm is not generally guaranteed to find a full solution. How did you build your 12-triples set? I took it from this diagram: https://upload.wikimedia.org/wikipedia/commons/e/eb/Hesse_configuration.svg What's wrong with my algorithm? And, most of all (and on topic, too): how can you build a Python program that builds your triples list? Perhaps if we compare this problem to a different problem then we can see how your algorithm may not be optimal. Imagine solving a sudoku puzzle. 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. Francesco ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
On 10 September 2015 at 08:45, Francesco Loffredo via Tutorwrote: > > I wrote a small routine (below) to check when and if my code and the formula > do match. It easily shows that > they only match for len(pool) == (2 ** N) - 1, with N greater or equal to 2. That's interesting. I'm not sure exactly why that would happen. > My problem remains: WHY don't they match for every length? Your algorithm is not generally guaranteed to find a full solution. > How did you build your 12-triples set? I took it from this diagram: https://upload.wikimedia.org/wikipedia/commons/e/eb/Hesse_configuration.svg > What's wrong with my algorithm? And, most of all (and on topic, too): how can > you build a Python program that builds your triples list? Perhaps if we compare this problem to a different problem then we can see how your algorithm may not be optimal. Imagine solving a sudoku puzzle. 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). The solution for a sudoku solving algorithm would be to back-track. One of the previously filled squares was filled incorrectly so go back and change what you had before. As a recursive algorithm you would take an unfilled square, loop over the possible values that it can take and for each of those values attempt to fill the remainder of the sudoko grid. The analogous backtracking algorithm for this problem would mean deciding first to include a particular triple if it is compatible with the already accepted triples and then continuing with the remaining triples to see if it leads to a full set (you know how big a full set should be). If it does not lead to a full set then you were wrong to include one of your current triples so now decide not to include it and again loop through the remaining triples looking for a full set. I imagine that the complexity of this algorithm will grow rapidly as N increases. For N=9 you have thousands of triples, so the powerset of this has 2**N members meaning that this binary backtracking algorithm has a very large space to explore. The space is heavily pruned by the pairing constraint though so it may not work out as badly as I expect. 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 ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
On 09/09/2015 19:45, Francesco Loffredo via Tutor wrote: On 09/09/2015 18:59, Oscar Benjamin wrote: I don't think the code above works. For n=27 it should count 117 (according to the formula I showed) but instead it comes up with 101. I tried it with a smaller n by setting pool to range(1, 9+1) meaning that n=9. The output is: combos contains 84 triples. maketriples(combos) contains 8 triples. [(1, 2, 3), (1, 4, 5), (1, 6, 7), (1, 8, 9), (2, 4, 6), (2, 5, 7), (3, 4, 7), (3, 5, 6)] However I can construct a set of 12 triples containing each number exactly 4 times which is the exact Steiner triple system: 1 6 8 1 2 3 1 5 9 1 4 7 2 6 7 2 4 9 2 5 8 3 5 7 3 6 9 3 8 4 4 5 6 7 8 9 This is the number of triples predicted by the formula: 9*(9-1)/6 = 12 -- Oscar That's very interesting! This takes me to my question to Tutors: what's wrong with the above code? I wrote a small routine (below) to check when and if my code and the formula do match. It easily shows that they only match for len(pool) == (2 ** N) - 1, with N greater or equal to 2. My problem remains: WHY don't they match for every length? How did you build your 12-triples set? What's wrong with my algorithm? And, most of all (and on topic, too): how can you build a Python program that builds your triples list? Francesco -- import pprint, itertools 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) matching = {} 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)) triples = maketriples(combos) theory = formula(pool) print("maketriples(combos) yields %s triples." % len(triples)) print("formula(pool) gives %s." % theory) if len(triples) == theory: pprint.pprint(triples) matching[len(pool)] = len(triples) input("\n--- Press Enter ---") print("-") print("Dict of matching solutions and number of obtained triples:") pprint.pprint(matching) ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
Oscar Benjamin wrote: The problem is that there are 26 people and they are divided into groups of 3 each day. We would like to know if it is possible to arrange it so that each player plays each other player exactly once over some period of days. It is not exactly possible to do this with 26 people in groups of 3. Think about it from the perspective of 1 person. They must play against all 25 other people in pairs with neither of the other people repeated: the set of pairs they play against must partition the set of other players. Clearly it can only work if the number of other players is even. I'm not sure but I think that maybe for an exact solution you need to have n=1(mod6) or n=3(mod6) which gives: n = 1, 3, 7, 9, 13, 15, 19, 21, 25, 27, ... The formula for the number of triples if the exact solution exists is n*(n-1)/6 which comes out as 26*25/6 = 108.3 (the formula doesn't give an integer because the exact solution doesn't exist). A quick solution is to add one "dummy" letter to the pool of the OP's golfers. I used "!" as the dummy one. This way, you end up with 101 triples, 11 of which contain the dummy player. But this is better than the 25-item pool, that resulted in an incomplete set of triples (for example, A would never play with Z) So, in your real-world problem, you will have 11 groups of 2 people instead of 3. Is this a problem? import pprint, itertools pool = "abcdefghijklmnopqrstuvwxyz!" 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 combos = list(itertools.combinations(pool, 3)) print("combos contains %s triples." % len(combos)) triples = maketriples(combos) print("maketriples(combos) contains %s triples." % len(triples)) pprint.pprint(triples) ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
On 09/09/2015 18:59, Oscar Benjamin wrote: On 9 September 2015 at 12:05, Francesco Loffredo via Tutorwrote: A quick solution is to add one "dummy" letter to the pool of the OP's golfers. I used "!" as the dummy one. This way, you end up with 101 triples, 11 of which contain the dummy player. But this is better than the 25-item pool, that resulted in an incomplete set of triples (for example, A would never play with Z) So, in your real-world problem, you will have 11 groups of 2 people instead of 3. Is this a problem? import pprint, itertools pool = "abcdefghijklmnopqrstuvwxyz!" 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 combos = list(itertools.combinations(pool, 3)) print("combos contains %s triples." % len(combos)) triples = maketriples(combos) print("maketriples(combos) contains %s triples." % len(triples)) pprint.pprint(triples) I don't think the code above works. For n=27 it should count 117 (according to the formula I showed) but instead it comes up with 101. I tried it with a smaller n by setting pool to range(1, 9+1) meaning that n=9. The output is: combos contains 84 triples. maketriples(combos) contains 8 triples. [(1, 2, 3), (1, 4, 5), (1, 6, 7), (1, 8, 9), (2, 4, 6), (2, 5, 7), (3, 4, 7), (3, 5, 6)] However I can construct a set of 12 triples containing each number exactly 4 times which is the exact Steiner triple system: 1 6 8 1 2 3 1 5 9 1 4 7 2 6 7 2 4 9 2 5 8 3 5 7 3 6 9 3 8 4 4 5 6 7 8 9 This is the number of triples predicted by the formula: 9*(9-1)/6 = 12 -- Oscar That's very interesting! This takes me to my question to Tutors: what's wrong with the above code? Francesco ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
On 9 September 2015 at 12:05, Francesco Loffredo via Tutorwrote: > Oscar Benjamin wrote: > > The problem is that there are 26 people and they are divided into > groups of 3 each day. We would like to know if it is possible to > arrange it so that each player plays each other player exactly once > over some period of days. > > It is not exactly possible to do this with 26 people in groups of 3. > Think about it from the perspective of 1 person. They must play > against all 25 other people in pairs with neither of the other people > repeated: the set of pairs they play against must partition the set of > other players. Clearly it can only work if the number of other players > is even. > > I'm not sure but I think that maybe for an exact solution you need to > have n=1(mod6) or n=3(mod6) which gives: > n = 1, 3, 7, 9, 13, 15, 19, 21, 25, 27, ... > > The formula for the number of triples if the exact solution exists is > n*(n-1)/6 which comes out as 26*25/6 = 108.3 (the formula doesn't > give an integer because the exact solution doesn't exist). > > > A quick solution is to add one "dummy" letter to the pool of the OP's > golfers. > I used "!" as the dummy one. This way, you end up with 101 triples, 11 of > which contain the dummy player. > But this is better than the 25-item pool, that resulted in an incomplete set > of triples (for example, A would never play with Z) > So, in your real-world problem, you will have 11 groups of 2 people instead > of 3. Is this a problem? > > > import pprint, itertools > pool = "abcdefghijklmnopqrstuvwxyz!" > > 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 > > combos = list(itertools.combinations(pool, 3)) > print("combos contains %s triples." % len(combos)) > > triples = maketriples(combos) > > print("maketriples(combos) contains %s triples." % len(triples)) > pprint.pprint(triples) I don't think the code above works. For n=27 it should count 117 (according to the formula I showed) but instead it comes up with 101. I tried it with a smaller n by setting pool to range(1, 9+1) meaning that n=9. The output is: combos contains 84 triples. maketriples(combos) contains 8 triples. [(1, 2, 3), (1, 4, 5), (1, 6, 7), (1, 8, 9), (2, 4, 6), (2, 5, 7), (3, 4, 7), (3, 5, 6)] However I can construct a set of 12 triples containing each number exactly 4 times which is the exact Steiner triple system: 1 6 8 1 2 3 1 5 9 1 4 7 2 6 7 2 4 9 2 5 8 3 5 7 3 6 9 3 8 4 4 5 6 7 8 9 This is the number of triples predicted by the formula: 9*(9-1)/6 = 12 -- Oscar ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
On Fri, Sep 4, 2015 at 7:28 AM, marcus lütolfwrote: > I should probably tell you the real task are a series (maximum ~ 301) > lists in which real names of people are assigned to the items/letters for > 2 people(golfers) can be in the same list(flight) only once for an > extended period of time. > The next step would be to assign compatible and noncompatible attributes > to the items/letters which will reduce the maximum of possible > lists(flights) > > I came up with this (obviously it could be made shorter, but I thought it would be clearer this way): import string, itertools def main(): validCombos = [] usedPairs = [] allCombos = itertools.combinations(string.ascii_lowercase, 3) for combo in allCombos: pair1 = (combo[0],combo[1]) pair2 = (combo[0],combo[2]) pair3 = (combo[1],combo[2]) if pair1 in usedPairs or pair2 in usedPairs or pair3 in usedPairs: next else: usedPairs.append(pair1) usedPairs.append(pair2) usedPairs.append(pair3) validCombos.append(combo) print(validCombos) print(len(validCombos)) if __name__ == '__main__': main() The resulting triplets seem to meet your criteria - but there are only 90 of them. How confident are you about the number 301? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
On 5 September 2015 at 23:28, Mark Lawrencewrote: > On 05/09/2015 10:09, Peter Otten wrote: >> >>> the 5 lists above do not match my task insofar as every of the 5 lists >>> contains 'a' and 'b' which should occur only once, hence my count of a >>> maximum of 301 lists, which might nor be correct 100%. My be one could >>> put >>> it in Python as follows: ('a', 'b', 'c') = True ('a', 'b', 'd')= False ('a', 'b', 'e')= False ('a', 'b', 'f')= False ('a', 'b', 'g')= False > > So for completeness it follows that:- > > ('a', 'c', 'd') == False > ('b', 'c', 'd') == False > > yes? I think so. >>> I should probably tell you the real task are a series (maximum ~ 301) >>> lists in which real names of people are assigned to the items/letters >>> for >>> 2 people(golfers) can be in the same list(flight) only once for an >>> extended period of time. >> > >> It's probably a good idea to ask your question in a mathematics forum -- >> this problem looks common enough to have a name and some brain power spent >> on it. >> > > To me this is clearly an example of a Steiner Triple system > associated with Balanced Incomplete Block Design. Which means I found this > http://mathforum.org/library/drmath/view/52263.html which got me to > https://en.wikipedia.org/wiki/Steiner_system and also > http://oeis.org/A137348/a137348.txt. Just one minor little question, am I > actually correct? It sounds like the social golfer problem (or Kirkman's schoolgirl problem, both of which Steiner systems): http://mathworld.wolfram.com/SocialGolferProblem.html The problem is that there are 26 people and they are divided into groups of 3 each day. We would like to know if it is possible to arrange it so that each player plays each other player exactly once over some period of days. It is not exactly possible to do this with 26 people in groups of 3. Think about it from the perspective of 1 person. They must play against all 25 other people in pairs with neither of the other people repeated: the set of pairs they play against must partition the set of other players. Clearly it can only work if the number of other players is even. I'm not sure but I think that maybe for an exact solution you need to have n=1(mod6) or n=3(mod6) which gives: n = 1, 3, 7, 9, 13, 15, 19, 21, 25, 27, ... The formula for the number of triples if the exact solution exists is n*(n-1)/6 which comes out as 26*25/6 = 108.3 (the formula doesn't give an integer because the exact solution doesn't exist). The question is what do you want to do with the leftovers if it's not possible for every player to play exactly once? Also what do you want with these triples? Are you just trying to count them? Are you interested to know which triples come out? It's not unique and the number of possible sets of triples is massive. -- Oscar ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
Hello Marcus, On Fri, Sep 04, 2015 at 04:28:10PM +0200, marcus lütolf wrote: [...] > I should probably tell you the real task are a series (maximum ~ 301) > lists in which real names of people are assigned to the items/letters > for 2 people(golfers) can be in the same list(flight) only once for an > extended period of time. The next step would be to assign compatible > and noncompatible attributes to the items/letters which will reduce > the maximum of possible lists(flights) Sorry, that description doesn't help me understand your problem. Perhaps you could show how to generate the pairs you want given (say) a small list of names. Let us call them A, B, C, D and E (five people), taken three at a time? (1) Can you write out all the possible lists for n=3 (the maximum)? Assuming order does not matter, I get ten lists: A B C A B D A B E A C D A C E A D E B C D B C E B D E C D E (2) Can you show what you mean by "compatible and noncompatible attributes", and use them to "reduce the maximum of possible lists"? How do you decide which of the ten above are allowed and which are not? -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
marcus lütolf wrote: > Hello Peter, hello Martin, > many thanks for your very quick response !!! > > As for Peter's advice: > >> At first I thought you might want itertools.combinations() >> > import string, itertools > for t in itertools.combinations(string.ascii_lowercase, 3): >> ... print t # list(t) if you actually need a list >> ... >> ('a', 'b', 'c') >> ('a', 'b', 'd') >> ('a', 'b', 'e') >> ('a', 'b', 'f') >> ('a', 'b', 'g') >> [snip] >> >> but that gives >> > sum(1 for t in itertools.combinations(string.ascii_lowercase, 3)) >> 2600 > > the 5 lists above do not match my task insofar as every of the 5 lists > contains 'a' and 'b' which should occur only once, hence my count of a > maximum of 301 lists, which might nor be correct 100%. My be one could put > it in Python as follows: >> ('a', 'b', 'c') = True >> ('a', 'b', 'd')= False >> ('a', 'b', 'e')= False >> ('a', 'b', 'f')= False >> ('a', 'b', 'g')= False > I should probably tell you the real task are a series (maximum ~ 301) > lists in which real names of people are assigned to the items/letters for > 2 people(golfers) can be in the same list(flight) only once for an > extended period of time. OK, you want all triples where no pair inside a triple is repeated. There are 325 pairs, and one triple uses up three pairs. That puts an upper limit of 325/3 = 108 on the number of triples. You then have to find all sets of pairs where the union contains My attempts to solve this analytically have failed so far, therefore I wrote a script that checks random triples for the above condition: $ cat all_teams_101.py import random import sys import textwrap from itertools import combinations, count from string import ascii_lowercase if len(sys.argv) > 1: random.seed(int(sys.argv[1])) def shuffled(items): items = list(items) random.shuffle(items) return items triples = list(combinations(ascii_lowercase, 3)) best_teams = [] best_shuffled = None try: for i in count(): seen_pairs = set() teams = [] shuffled_teams = shuffled(triples) for team in shuffled_teams: team_pairs = [ frozenset(t) for t in [team[:2], team[1:], team[::2]] ] if all((pair not in seen_pairs) for pair in team_pairs): seen_pairs.update(team_pairs) teams.append(team) if len(teams) > len(best_teams): print(i, len(teams)) best_teams = teams best_shuffled = shuffled_teams except KeyboardInterrupt: print() print(textwrap.fill(" ".join(map("".join, best_teams $ python3 all_teams_101.py 42 0 97 55 98 220 100 561 101 ^C bcq aoy nrz bhs gpx cjt cmu cnw fnq tvx cix afx bpv dhm hno dpy hil cfy jlv cdg mnt bln htw aiu fhp jsw qru gkq egl gtu lqx ars kwz emr inp jky kmp uwy gow hjx aep aqt kns bft biw ops efs ghr mov fgi lms dnu bjm lyz cek fkv gmy dev qsy dlt dqw huz bdr nxy eiy dsz mxz flr acz klu adk csv ehq bez eju foz avw iko jpq ewx gjz bkx prw abg qvz krt fmw dfj jor irv ptz ajn dox sux imq clo eot ist bou gnv hvy $ It's probably a good idea to ask your question in a mathematics forum -- this problem looks common enough to have a name and some brain power spent on it. (Google found https://en.wikipedia.org/wiki/Kirkman's_schoolgirl_problem which looks similar; maybe someone here can make sense of it) > The next step would be to assign compatible and noncompatible attributes > to the items/letters which will reduce the maximum of possible > lists(flights) ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
Peter Otten wrote: [proofreading goof] > OK, you want all triples where no pair inside a triple is repeated. > There are 325 pairs, and one triple uses up three pairs. > That puts an upper limit of 325/3 = 108 on the number of triples. > You then have to find all sets of three > pairs where the union contains ... three letters. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
On 05/09/2015 10:09, Peter Otten wrote: marcus lütolf wrote: Hello Peter, hello Martin, many thanks for your very quick response !!! As for Peter's advice: the 5 lists above do not match my task insofar as every of the 5 lists contains 'a' and 'b' which should occur only once, hence my count of a maximum of 301 lists, which might nor be correct 100%. My be one could put it in Python as follows: ('a', 'b', 'c') = True ('a', 'b', 'd')= False ('a', 'b', 'e')= False ('a', 'b', 'f')= False ('a', 'b', 'g')= False So for completeness it follows that:- ('a', 'c', 'd') == False ('b', 'c', 'd') == False yes? I should probably tell you the real task are a series (maximum ~ 301) lists in which real names of people are assigned to the items/letters for 2 people(golfers) can be in the same list(flight) only once for an extended period of time. It's probably a good idea to ask your question in a mathematics forum -- this problem looks common enough to have a name and some brain power spent on it. To me this is clearly an example of a Steiner Triple system associated with Balanced Incomplete Block Design. Which means I found this http://mathforum.org/library/drmath/view/52263.html which got me to https://en.wikipedia.org/wiki/Steiner_system and also http://oeis.org/A137348/a137348.txt. Just one minor little question, am I actually correct? -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
Hello Peter, hello Martin, many thanks for your very quick response !!! As for Peter's advice: > At first I thought you might want itertools.combinations() > import string, itertools for t in itertools.combinations(string.ascii_lowercase, 3): > ... print t # list(t) if you actually need a list > ... > ('a', 'b', 'c') > ('a', 'b', 'd') > ('a', 'b', 'e') > ('a', 'b', 'f') > ('a', 'b', 'g') > [snip] > > but that gives > sum(1 for t in itertools.combinations(string.ascii_lowercase, 3)) > 2600 the 5 lists above do not match my task insofar as every of the 5 lists contains 'a' and 'b' which should occur only once, hence my count of a maximum of 301 lists, which might nor be correct 100%. My be one could put it in Python as follows: > ('a', 'b', 'c') = True > ('a', 'b', 'd')= False > ('a', 'b', 'e')= False > ('a', 'b', 'f')= False > ('a', 'b', 'g')= False I should probably tell you the real task are a series (maximum ~ 301) lists in which real names of people are assigned to the items/letters for 2 people(golfers) can be in the same list(flight) only once for an extended period of time. The next step would be to assign compatible and noncompatible attributes to the items/letters which will reduce the maximum of possible lists(flights) As for Martin's advice: You are using random. Do you want n randomly selected items from the input list? The random module provides random.sample() to select n items from a sequence. If so, try this out at the intercative prompt. Perhaps this is what you are looking for? >>> import random >>> import string >>> l = list(string.lowercase) >>> random.sample(l, 7) ['z', 'h', 'e', 'n', 'c', 'f', 'r'] The two modules random and string should provide 7 ore more sets of 3 items not just one (letter ['z',..'r']) like ['z', 'a', 'b'], ['h','a','c'], ['e','a','d'], ['n','a','f'],.['r','a','g']. I hope I could make myself clear(er) and used the appropriate format to communicate. Thanks again for your help, Marcus ... -Ursprüngliche Nachricht- Von: marcus.luet...@bluewin.ch [mailto:marcus.luet...@bluewin.ch] Gesendet: Freitag, 4. September 2015 15:27 An: marcus.luet...@bluewin.ch Betreff: Fwd: Creating lists with definite (n) items without repetitions Ursprüngliche Nachricht Von : marcus.luet...@bluewin.ch Datum : 03/09/2015 - 15:32 (UTC) An : tutor@python.org Betreff : Creating lists with definite (n) items without repetitions dear pythonistas as a newcomber I want to create a set of lists containing n items, for example n = 3: (['a','b','c'], ['a','d','e']...). The sequence of items in each list should be different. If the letters 'a''z' are used and n = 3 there is a maximum of 301 lists. The following code works only for lists containing 1 item: import random list = ['a', 'b', 'c', 'd',... 'z'] random.shuffle(list) for x in list: print x how can I solve my task wit n items ? Thank you for help, Marcus. --- Diese E-Mail wurde von Avast Antivirus-Software auf Viren geprüft. https://www.avast.com/antivirus ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
Marcus Lütolf wrote: > as a newcomber I want to create a set of lists containing n items, for > example n = 3: (['a','b','c'], ['a','d','e']...). > The sequence of items in each list should be different. If the letters > 'a''z' are used and n = 3 there is a maximum of 301 lists. > The following code works only for lists containing 1 item: > > import random > list = ['a', 'b', 'c', 'd',... 'z'] > random.shuffle(list) > for x in list: > print x > > how can I solve my task wit n items ? At first I thought you might want itertools.combinations() >>> import string, itertools >>> for t in itertools.combinations(string.ascii_lowercase, 3): ... print t # list(t) if you actually need a list ... ('a', 'b', 'c') ('a', 'b', 'd') ('a', 'b', 'e') ('a', 'b', 'f') ('a', 'b', 'g') [snip] but that gives >>> sum(1 for t in itertools.combinations(string.ascii_lowercase, 3)) 2600 2600 different tuples Can you give more details on how to pick the lists? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Creating lists with definite (n) items without repetitions
dear pythonistats as a newcomber I want to create a set of lists containing n items, for example n = 3: (['a','b','c'], ['a','d','e']...). The sequence of items in each list should be different. If the letters 'a''z' are used and n = 3 there is a maximum of 301 lists. The following code works only for lists containing 1 item: import random list = ['a', 'b', 'c', 'd',... 'z'] random.shuffle(list) for x in list: print x how can I solve my task wit n items ? Thank you for help, Marcus. --- Diese E-Mail wurde von Avast Antivirus-Software auf Viren geprüft. https://www.avast.com/antivirus ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
Greetings Marcus, Peter Otten has also responded, recommending itertools. I think both he and I are not sure how you wish to generate your result list (or lists). But, I have a comment or two. dear pythonistats as a newcomber I want to create a set of lists containing n items, for example n = 3: (['a','b','c'], ['a','d','e']...). The sequence of items in each list should be different. If the letters 'a''z' are used and n = 3 there is a maximum of 301 lists. The following code works only for lists containing 1 item: import random list = ['a', 'b', 'c', 'd',... 'z'] I would recommend against using the name "list". The name list is a Python builtin which creates a list(). Try it at the interactive prompt: >>> list() [] So, I'd recommend changing that name to "l" or "result" or something like that. random.shuffle(list) for x in list: print x how can I solve my task wit n items ? Thank you for help, Marcus. You are using random. Do you want n randomly selected items from the input list? The random module provides random.sample() to select n items from a sequence. If so, try this out at the intercative prompt. Perhaps this is what you are looking for? >>> import random >>> import string >>> l = list(string.lowercase) >>> random.sample(l, 7) ['z', 'h', 'e', 'n', 'c', 'f', 'r'] Best of luck, -Martin -- Martin A. Brown http://linux-ip.net/ ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
On 03/09/2015 14:32, Marcus Lütolf wrote: dear pythonistats as a newcomber I want to create a set of lists containing n items, for example n = 3: (['a','b','c'], ['a','d','e']...). The sequence of items in each list should be different. If the letters 'a''z' are used and n = 3 there is a maximum of 301 lists. The formula for combinations is n! / (r! * (n - r)!) = 26! / (3! * 23!) = 26 * 25 * 24 / (3 * 2 * 1) = 2600, the number given by Peter Otten in his earlier answer using itertools.combinations. The number for permutations is n! / (n - k)! = 26! / 23! = 26 * 25 * 24 = 15,600. So what criteria are you using to give 301? -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating lists with definite (n) items without repetitions
> At first I thought you might want itertools.combinations() > import string, itertools for t in itertools.combinations(string.ascii_lowercase, 3): > ... print t # list(t) if you actually need a list > ... > ('a', 'b', 'c') > ('a', 'b', 'd') > ('a', 'b', 'e') > ('a', 'b', 'f') > ('a', 'b', 'g') > [snip] > > but that gives > sum(1 for t in itertools.combinations(string.ascii_lowercase, 3)) > 2600 At the very least, that matches the expected result mathematically, since the number of combinations of 3 elements out of 26 possibilities is "26 choose 3". http://mathworld.wolfram.com/Combination.html and "26 choose 3" computes to 2600. ### >>> 26 * 25 * 24 / (3 * 2 * 1) 2600 ### ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Creating Lists
Create a list of 20 unique (no number appears twice) random integers with values between 1 and 45. Print the list of random numbers with the header “Random list of 20 numbers”. Find the largest number in the list. Remove the largest number from the list. Find the smallest number in the list. Remove the smallest number from the list. Print the length of the list with the header “The length of the list is: ” Print the list with the header “The list with the largest and smallest number removed: ” Sent from Windows Mail___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating Lists
On 12/11/14 04:27, niyanax...@gmail.com wrote: Create a list of 20 unique (no number appears twice) random integers with values between 1 and 45. Print the list of random numbers with the header “Random list of 20 numbers”. Find the largest number in the list. Remove the largest number from the list. Find the smallest number in the list. Remove the smallest number from the list. Print the length of the list with the header “The length of the list is: ” Print the list with the header “The list with the largest and smallest number removed: ” OK, You've shown us your homework, it all looks very reasonable. Now tell us what you have tried. How did it work? Are there any bits you are stuck with? Maybe we can help. But we won't just do your homework for you. Tell us which version of Python you are using too, since that will make a difference. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating Lists
niyanax...@gmail.com writes: Create a list of 20 unique (no number appears twice) random integers […] Print the list with the header “The list with the largest and smallest number removed: ” That all sounds like a good assignment. Feel free to show us your complete program and we can offer advice. This is a forum for *tutoring*, which means you still have to do the work. -- \ “We must find our way to a time when faith, without evidence, | `\disgraces anyone who would claim it.” —Sam Harris, _The End of | _o__) Faith_, 2004 | Ben Finney ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Creating Lists
On Wed, Nov 12, 2014 at 04:27:33AM +, niyanax...@gmail.com wrote: Create a list of 20 unique (no number appears twice) random integers with values between 1 and 45. Here is how I would produce a list of 7 unique random integers with values between 123 and 175. Lines starting with py are code which I have typed in the Python interactive interpreter. I don't type the py part, Python automatically shows that. The output then follows: py import random py random.sample(range(123, 176), 7) [129, 151, 147, 137, 130, 153, 152] Can you adjust that to do what you want? Print the list of random numbers with the header “Random list of 20 numbers”. This is how I would print a list of numbers with a header, separating each number with a bunch of dots: py numbers = [2, 4, 8, 16] py print(This is a header) This is a header py print(*numbers, sep=..) 2..4..8..16 Note the asterisk * in front of numbers. What happens if you leave the asterisk out? What happens if you leave the asterisk in, but remove the sep= part? Find the largest number in the list. Remove the largest number from the list. Find the smallest number in the list. Remove the smallest number from the list. Here is how I would find the largest and smallest numbers from a list: py numbers = [17, 11, 3, 99, 100, 41] py min(numbers) 3 py max(numbers) 100 And here is how I would remove a number from a list: py print(numbers) # Before [17, 11, 3, 99, 100, 41] py numbers.remove(99) py print(numbers) # And after. [17, 11, 3, 100, 41] Print the length of the list with the header “The length of the list is: ” Print the list with the header “The list with the largest and smallest number removed: ” Here is how I would find out the length of the list: py len(numbers) 5 Does this help you solve the problem? -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor