From alan.gauld at yahoo.co.uk Tue Mar 1 05:47:05 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 1 Mar 2022 10:47:05 +0000 Subject: [Tutor] Tkinter canvas on frame In-Reply-To: <2a8de7b4-a1c7-c740-e38f-b3093e872299@gmail.com> References: <6b3c4594-14a3-5363-5fa3-6e990bf213f7@gmail.com> <6e521b71-3d97-7029-d165-e4504b143edf@gmail.com> <9e3b626d-2b4d-94dd-5046-01d87a15a81e@gmail.com> <2a8de7b4-a1c7-c740-e38f-b3093e872299@gmail.com> Message-ID: On 28/02/2022 23:52, Phil wrote: > I understand that the pack manager should be left to automatically > adjust the size of the window.? However, in the case of a drawn line or > a shape that extends off the edge of the canvas, isn't it still > necessary to specifically set the window geometry or is it simply left > to the user to enlarge the window? So what if the user draws it even bigger? What happens in other graphics programs you've used? Usually you have the option to zoom in/out without changing the size of the window. But when zoomed in part of the image will be off-screen. But scaling the content of a canvas could be tricky. I don't know if the widget offers any assistance there? -- 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 From wlfraed at ix.netcom.com Tue Mar 1 11:54:00 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Tue, 01 Mar 2022 11:54:00 -0500 Subject: [Tutor] Tkinter canvas on frame References: <6b3c4594-14a3-5363-5fa3-6e990bf213f7@gmail.com> <6e521b71-3d97-7029-d165-e4504b143edf@gmail.com> <9e3b626d-2b4d-94dd-5046-01d87a15a81e@gmail.com> <2a8de7b4-a1c7-c740-e38f-b3093e872299@gmail.com> Message-ID: On Tue, 1 Mar 2022 10:47:05 +0000, Alan Gauld via Tutor declaimed the following: >On 28/02/2022 23:52, Phil wrote: > >> I understand that the pack manager should be left to automatically >> adjust the size of the window.? However, in the case of a drawn line or >> a shape that extends off the edge of the canvas, isn't it still >> necessary to specifically set the window geometry or is it simply left >> to the user to enlarge the window? > >So what if the user draws it even bigger? What happens in other graphics >programs you've used? Usually you have the option to zoom in/out without >changing the size of the window. But when zoomed in part of the image >will be off-screen. > >But scaling the content of a canvas could be tricky. I don't know >if the widget offers any assistance there? Haven't looked at Tkinter, but as I recall, most of these windowing packages issue a "redraw" event if a general drawing widget is resized (or even just covered/uncovered), requiring the application to redo any calculations needed for scaling. Note that this most applies to "paint" or "line draw" type windows -- regular widgets being just rectangular shapes with/without text, and easy to rescale or just position. "paint" and "line draw" type windows tend to be sequences of actions, and the windowing system doesn't save the sequence used to produce the display. It becomes part of the application "redraw" handler to regenerate the display data -- and determine if the viewport has expanded but not the scale (ie: the world coordinates now span 0..2 when they used to be 0..1) or if the scale has changed but the real world coordinates are the same (world is still 0..1, but there may be twice as many pixels spanning that range). The last time I did anything with graphical data was in the days of DECWindows, UIL (to define the DECWindows interface) and used a particular DECWindows widget as a canvas for GKS (Graphical Kernel System). GKS supported Display-Lists and scaling from "world" to "display". Resizing the application window required replaying the display list using new scaling factors. Considering the full system required running something like five separate executables to one "display" window (legacy system was a RAMTEK 9300 Graphics Engine -- which operated as an I/O device shared by each executable; the update required writing a "display app" to which those executables would send commands), and some of those executables (separate executable to, say, draw the axes labels, another to render the "temperature scale" bar, a third to render a world map, and a fourth to read a massive data file of "temperature points" and send them to the display) might take half an hour or more to process input for display -- well, having to rerun all those executables every time the "display" was resized (or worse, had another window dragged across it -- no equivalent to the Amiga Smart Refresh window (where the OS would maintain an off-screen bitmap from which to refill exposed areas) was a non-starter. I've not seen any mention of modern window packages (Tk, wX, Qt...) incorporating the equivalent of a display list, and some may not even handle world<>viewport<>display coordinate translation. Apologies for the history harangue... -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From phillor9 at gmail.com Tue Mar 1 17:51:49 2022 From: phillor9 at gmail.com (Phil) Date: Wed, 2 Mar 2022 09:51:49 +1100 Subject: [Tutor] Tkinter canvas on frame In-Reply-To: References: <6b3c4594-14a3-5363-5fa3-6e990bf213f7@gmail.com> <6e521b71-3d97-7029-d165-e4504b143edf@gmail.com> <9e3b626d-2b4d-94dd-5046-01d87a15a81e@gmail.com> <2a8de7b4-a1c7-c740-e38f-b3093e872299@gmail.com> Message-ID: <7b723d8a-0d40-f89e-09d4-01fb6dc1a0cb@gmail.com> On 1/3/22 21:47, Alan Gauld via Tutor wrote: > So what if the user draws it even bigger? What happens in other graphics > programs you've used? Usually you have the option to zoom in/out without > changing the size of the window. But when zoomed in part of the image > will be off-screen. > > But scaling the content of a canvas could be tricky. I don't know > if the widget offers any assistance there? Thank you Alan and Dennis, I woke up during the early hours of this morning and realised that I would need a zoom function and felt a bit silly for posting such a silly question. I thought about this for awhile but couldn't think of an easy way to achieve this. As Dennis mentioned a redraw event is common, otherwise an uncovered window wouldn't be redrawn. I'll give this some more thought. -- Regards, Phil From colinbdaly at gmail.com Wed Mar 2 00:15:26 2022 From: colinbdaly at gmail.com (Colin Daly) Date: Tue, 1 Mar 2022 21:15:26 -0800 Subject: [Tutor] Help with Package Importing Message-ID: Hello, I have a question about how to properly import packages. I had created a basic nested program in order to clearly show my error, but it doesn't look like I can upload files for sharing. Please excuse me as this is my first time posting here. I have the following folder and file structure: /MainDirectory MainFile.py | -- / Sub 1 | -- | -- SubProgram1_1.py | -- | -- SubProgram1.py | -- / Sub 2 | -- | -- ReadFile.py I'm working out of MainDirectory. In MainFile.py I have: MainFile.py ******************************************************** import Sub1.SubProgram1_1 as s1_1 def DoSomething(): z = s1_1.SubFunc1_2() print(z) DoSomething() ******************************************************** And inside ./Sub1/SubProgram1_1 I have SubProgram1_1.py ******************************************************** import Sub1.SubProgram1 as s1 def SubFunc1_2(): xx = s1.SubFunc1() yy = xx + 22 return yy def main(): n = SubFunc1_2() print(f"you are in subprogram1_1. value from SubFunc1_2 is {n}") if __name__ == "__main__": main() ******************************************************** MainFile.py runs fine like this, but SubProgram1_1.py does not run like this. I need to change import Sub1.SubProgram1 as s1 to import SubProgram1 as s1 How should I have things such that I can run MainFile.py and SubProgram1_1.py without messing with the import statements. Best I can tell is to add the following to SubProgram1_1.py: import os, sys sys.path.insert(0, os.path.join(os.path.split(__file__)[0], "..")) but that seems not very clean. Why should SubProgram1_1 need to import Sub1.SubProgram1_1 when it's in the same folder? Thank you! From mats at wichmann.us Wed Mar 2 09:06:02 2022 From: mats at wichmann.us (Mats Wichmann) Date: Wed, 2 Mar 2022 07:06:02 -0700 Subject: [Tutor] Help with Package Importing In-Reply-To: References: Message-ID: <4c72e737-bb5b-ba64-904b-56b09f3c8327@wichmann.us> I sent this but seem to have not sent it to the list, doing so now for completeness: > How should I have things such that I can run MainFile.py and > SubProgram1_1.py without messing with the import statements. Best I can > tell is to add the following to SubProgram1_1.py: > > import os, sys > sys.path.insert(0, os.path.join(os.path.split(__file__)[0], "..")) You don't want to do that. > but that seems not very clean. Why should SubProgram1_1 need to import > Sub1.SubProgram1_1 when it's in the same folder? Because it's not in the same file, Python sees it as a separate module (the directory makes it a package, but it's still has multiple modules). Try it this way, which may be more readable to you: from . import SubProgram1 as s1 BTW, Importing as a different name will probably lead to confusion at some point. I know there are a few places where it's done a lot (import numpy as np) but using the name of the module makes it easier to keep track of what you're doing - and for other readers to be able to find the context more quickly. That's just a suggestion, it's not any kind of rule - if you weren't allowed to "import as" the facility wouldn't exist! From __peter__ at web.de Wed Mar 2 12:36:33 2022 From: __peter__ at web.de (Peter Otten) Date: Wed, 2 Mar 2022 18:36:33 +0100 Subject: [Tutor] Help with Package Importing In-Reply-To: References: Message-ID: <74598d5f-377f-85ab-000c-261a644acf34@web.de> On 02/03/2022 06:15, Colin Daly wrote: > Hello, > > I have a question about how to properly import packages. I had created a > basic nested program in order to clearly show my error, but it doesn't look > like I can upload files for sharing. Please excuse me as this is my first > time posting here. > > I have the following folder and file structure: > > /MainDirectory > MainFile.py > | -- / Sub 1 > | -- | -- SubProgram1_1.py > | -- | -- SubProgram1.py > | -- / Sub 2 > | -- | -- ReadFile.py > > I'm working out of MainDirectory. In MainFile.py I have: > > MainFile.py > ******************************************************** > import Sub1.SubProgram1_1 as s1_1 > > def DoSomething(): > z = s1_1.SubFunc1_2() > print(z) > > DoSomething() > > ******************************************************** > > And inside ./Sub1/SubProgram1_1 I have > > SubProgram1_1.py > ******************************************************** > import Sub1.SubProgram1 as s1 > > def SubFunc1_2(): > > xx = s1.SubFunc1() > yy = xx + 22 > return yy > > def main(): > n = SubFunc1_2() > > print(f"you are in subprogram1_1. value from SubFunc1_2 is {n}") > > if __name__ == "__main__": > main() > > ******************************************************** > > MainFile.py runs fine like this, but SubProgram1_1.py does not run like > this. When MainDirectory is your current working directory you should be able to run the script inside the package with with the -m option: $ python -m sub1.subprogram1_1 I need to change > import Sub1.SubProgram1 as s1 > to > import SubProgram1 as s1 > > How should I have things such that I can run MainFile.py and > SubProgram1_1.py without messing with the import statements. Best I can > tell is to add the following to SubProgram1_1.py: > > import os, sys > sys.path.insert(0, os.path.join(os.path.split(__file__)[0], "..")) > > but that seems not very clean. Don't do that. The search path for modules should be part of the environment rather than the program. Why should SubProgram1_1 need to import > Sub1.SubProgram1_1 when it's in the same folder? In Python 2 you could write import module and depending on context it could mean import module or from package import module This caused enough problems to convince Python's developers to change it https://www.python.org/dev/peps/pep-0328/ PS: It is generally a good idea to follow the style guide for Python https://www.python.org/dev/peps/pep-0008/#package-and-module-names which suggests lowercase for module names. From __peter__ at web.de Wed Mar 2 12:36:33 2022 From: __peter__ at web.de (Peter Otten) Date: Wed, 2 Mar 2022 18:36:33 +0100 Subject: [Tutor] Help with Package Importing In-Reply-To: References: Message-ID: <74598d5f-377f-85ab-000c-261a644acf34@web.de> On 02/03/2022 06:15, Colin Daly wrote: > Hello, > > I have a question about how to properly import packages. I had created a > basic nested program in order to clearly show my error, but it doesn't look > like I can upload files for sharing. Please excuse me as this is my first > time posting here. > > I have the following folder and file structure: > > /MainDirectory > MainFile.py > | -- / Sub 1 > | -- | -- SubProgram1_1.py > | -- | -- SubProgram1.py > | -- / Sub 2 > | -- | -- ReadFile.py > > I'm working out of MainDirectory. In MainFile.py I have: > > MainFile.py > ******************************************************** > import Sub1.SubProgram1_1 as s1_1 > > def DoSomething(): > z = s1_1.SubFunc1_2() > print(z) > > DoSomething() > > ******************************************************** > > And inside ./Sub1/SubProgram1_1 I have > > SubProgram1_1.py > ******************************************************** > import Sub1.SubProgram1 as s1 > > def SubFunc1_2(): > > xx = s1.SubFunc1() > yy = xx + 22 > return yy > > def main(): > n = SubFunc1_2() > > print(f"you are in subprogram1_1. value from SubFunc1_2 is {n}") > > if __name__ == "__main__": > main() > > ******************************************************** > > MainFile.py runs fine like this, but SubProgram1_1.py does not run like > this. When MainDirectory is your current working directory you should be able to run the script inside the package with with the -m option: $ python -m sub1.subprogram1_1 I need to change > import Sub1.SubProgram1 as s1 > to > import SubProgram1 as s1 > > How should I have things such that I can run MainFile.py and > SubProgram1_1.py without messing with the import statements. Best I can > tell is to add the following to SubProgram1_1.py: > > import os, sys > sys.path.insert(0, os.path.join(os.path.split(__file__)[0], "..")) > > but that seems not very clean. Don't do that. The search path for modules should be part of the environment rather than the program. Why should SubProgram1_1 need to import > Sub1.SubProgram1_1 when it's in the same folder? In Python 2 you could write import module and depending on context it could mean import module or from package import module This caused enough problems to convince Python's developers to change it https://www.python.org/dev/peps/pep-0328/ PS: It is generally a good idea to follow the style guide for Python https://www.python.org/dev/peps/pep-0008/#package-and-module-names which suggests lowercase for module names. From colinbdaly at gmail.com Fri Mar 4 18:47:10 2022 From: colinbdaly at gmail.com (Colin Daly) Date: Fri, 4 Mar 2022 15:47:10 -0800 Subject: [Tutor] Help with Package Importing In-Reply-To: References: Message-ID: Thank you for the reply, Mats. Your suggestion yielded the following error: from . import SubProgram1 as s1 ImportError: attempted relative import with no known parent package On Wed, Mar 2, 2022 at 6:00 AM Mats Wichmann wrote: > On 3/1/22 22:15, Colin Daly wrote: > > Hello, > > > > I have a question about how to properly import packages. I had created a > > basic nested program in order to clearly show my error, but it doesn't > look > > like I can upload files for sharing. Please excuse me as this is my first > > time posting here. > > > > I have the following folder and file structure: > > > > /MainDirectory > > MainFile.py > > | -- / Sub 1 > > | -- | -- SubProgram1_1.py > > | -- | -- SubProgram1.py > > | -- / Sub 2 > > | -- | -- ReadFile.py > > > > I'm working out of MainDirectory. In MainFile.py I have: > > > > MainFile.py > > ******************************************************** > > import Sub1.SubProgram1_1 as s1_1 > > > > def DoSomething(): > > z = s1_1.SubFunc1_2() > > print(z) > > > > DoSomething() > > > > ******************************************************** > > > > And inside ./Sub1/SubProgram1_1 I have > > > > SubProgram1_1.py > > ******************************************************** > > import Sub1.SubProgram1 as s1 > > > > def SubFunc1_2(): > > > > xx = s1.SubFunc1() > > yy = xx + 22 > > return yy > > > > def main(): > > n = SubFunc1_2() > > > > print(f"you are in subprogram1_1. value from SubFunc1_2 is {n}") > > > > if __name__ == "__main__": > > main() > > > > ******************************************************** > > > > MainFile.py runs fine like this, but SubProgram1_1.py does not run like > > this. I need to change > > import Sub1.SubProgram1 as s1 > > to > > import SubProgram1 as s1 > > > > How should I have things such that I can run MainFile.py and > > SubProgram1_1.py without messing with the import statements. Best I can > > tell is to add the following to SubProgram1_1.py: > > > > import os, sys > > sys.path.insert(0, os.path.join(os.path.split(__file__)[0], "..")) > > > > but that seems not very clean. Why should SubProgram1_1 need to import > > Sub1.SubProgram1_1 when it's in the same folder? > > Because it's not in the same file, Python sees it as a separate module > (the directory makes it a package, but it's still has multiple modules). > Try it this way, which may be more readable to you: > > from . import SubProgram1 as s1 > > > BTW, Importing as a different name will probably lead to confusion at > some point. I know there are a few places where it's done a lot (import > numpy as np) but using the name of the module makes it easier to keep > track of what you're doing - and for other readers to be able to find > the context more quickly. That's just a suggestion, it's not any kind > of rule - if you weren't allowed to "import as" the facility wouldn't > exist! > > From marcus.luetolf at bluewin.ch Sun Mar 6 02:15:31 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Sun, 6 Mar 2022 08:15:31 +0100 Subject: [Tutor] problem solving with lists Message-ID: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> Hello Experts, I'am still biting my teeth out trying to put in to code the following pseudocode: 1.Set up a list of 16 letters and assign it to a variable : all_letters = list(abcdefghijklmnop) 2.Find an code to insert all 16 letters in 5 Lists in 4 sublists of 4 letters in each list: list1 = [['a', 'b', 'c', 'd'], ['e', 'f', 'g', 'k'].....['m', 'n', 'o', 'p']] list2= [['a', 'e', 'f','g'] ...............,['d', 'i', 'l',' p']] . . list5 =[[...],....................,[.........]] with constraint that a pair of letters, p.e. ['a', 'b', ..] can occur only once in all 20 sublists or if list1 contains sublist ['a', 'b',..], such a sublist cannot appear in list2 through list5. To write this code, as a first step I made a list (comb_list) containing all possible sublists and reducing their number to 80 by sorting them : ['a', 'b'..] equals ['b', 'a', ..] : with to code snippet below. >comb_list = [] >for dummy_i in range(4): >copy_all_letters = all_letters[:] >lst = (16*16)*copy_all_letters >f1 = [] >f2 = [] >f3 = [] >f4 = [] > f1.append(lst[0+n]) >f1.append(lst[2+n]) >f1.append(lst[4+n]) >f1.append(lst[6+n]) > f1.sort() >comb_list.append(f1) >f2.append(lst[8+n]) >f2.append(lst[10+n]) >f2.append(lst[12+n]) >f2.append(lst[14+n]) >f2.sort() >comb_list.append(f2) > f3.append(lst[1+n]) >f3.append(lst[3+n]) >f3.append(lst[5+n]) >f3.append(lst[7+n]) >f3.sort() >comb_list.append(f3) > f4.append(lst[9+n]) >f4.append(lst[11+n]) > f4.append(lst[13+n]) > f4.append(lst[15+n]) >f4.sort() > comb_list.append(f4) > print(f1, f2, f4, f4) > print(comb_list) > n += 3 The next step should be to extract out of the 80 sublists in comb_list 20 sublists fullfilling the above mentioned constraint. a) I don't know how to do that, b) I am not shure wether this is a way do it, nor c) if my problem can by solved by python at all. Marcus. From alan.gauld at yahoo.co.uk Sun Mar 6 04:04:27 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sun, 6 Mar 2022 09:04:27 +0000 Subject: [Tutor] problem solving with lists In-Reply-To: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> Message-ID: On 06/03/2022 07:15, marcus.luetolf at bluewin.ch wrote: > Hello Experts, > > I'am still biting my teeth out trying to put in to code the following > pseudocode: > ... c) if my problem can by solved by python at all. It is important to remember that programming languages do not solve problems. They merely provide tools to generalize and automate the solution once YOU have found it. But it's up to you to formulate a solution. And at this point it seems to be the required algorithm that is eluding you rather than the python constructs needed to implement that. Can you reduce the size of the problem and solve it on paper? That may give a clue to how you should solve it for bigger cases. What if you reduce the problem to, say, 9 letters and sublists of only 3? Does that help? Even if it only clarifies the definition of the output. -- 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 From wlfraed at ix.netcom.com Sun Mar 6 13:05:26 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sun, 06 Mar 2022 13:05:26 -0500 Subject: [Tutor] problem solving with lists References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> Message-ID: <38q92hli62o5rr01oi46d9quoo8i4v8fdf@4ax.com> On Sun, 6 Mar 2022 08:15:31 +0100, declaimed the following: > >1.Set up a list of 16 letters and assign it to a variable : all_letters = >list(abcdefghijklmnop) > FYI (presuming you left out quote markers in the string) this isn't really needed. You can directly index a string, rather than making it a list of 1-character strings. >>> sixteen = "abcdefghijklmnop" >>> lsixteen = list(sixteen) >>> sixteen, lsixteen ('abcdefghijklmnop', ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p']) >>> sixteen[3], lsixteen[3] ('d', 'd') Note how both return the same item. >>> >2.Find an code to insert all 16 letters in 5 Lists in 4 sublists of 4 >letters in each list: > > list1 = [['a', 'b', 'c', 'd'], ['e', 'f', 'g', 'k'].....['m', 'n', 'o', >'p']] > > list2= [['a', 'e', 'f','g'] ...............,['d', 'i', 'l',' p']] > > . > > . > > list5 =[[...],....................,[.........]] > > with constraint that a pair of letters, p.e. ['a', 'b', ..] can occur >only once in all 20 sublists > > or if list1 contains sublist ['a', 'b',..], such a sublist cannot appear >in list2 through list5. > > > >To write this code, > >as a first step I made a list (comb_list) containing all possible sublists >and reducing their number to 80 Overkill and wasteful of memory -- note that your #2 above reads "insert", not "reduce". The algorithm shouldn't, in my mind, even generate an invalid set. Nested loops with differing increments (skips) may suffice. Consider the first set of four substrings: abcd efgh ijkl mnop Now, how to avoid any matching pairs? Well, you could take the "a", and one character from the other three substrings aeim afjn agko ahlp But you can't do that with "b" -- as beim has "eim" in common. Instead of matching through "ijkl" you could wrap it -- "jkli". (hint, use a modulo operator and just increment the position) bej. bfk. bgl. ghi. Now you need to handle "mnop" to fill the "."; perhaps the same wrap? "nopm". bejn -- NO, conflicts with afjn. So... an algorithm that needs to determine how much of a circular wrap each four-character substring needs after the first simple splitting, based upon which starting character is in play. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From subodh.khandelwal at gmail.com Sun Mar 6 18:10:18 2022 From: subodh.khandelwal at gmail.com (subodh.khandelwal at gmail.com) Date: Sun, 6 Mar 2022 15:10:18 -0800 Subject: [Tutor] To show the result on a map Message-ID: <2d6f01d831af$58e99310$0abcb930$@gmail.com> Hello, I am very new to Python with basic understanding to programming. Currently I am doing a project on a dataset of crimes in Seattle which has the following columns: ID | Offense_Grp | Offense_code | Block_Add | Precint | Report_Number | Longitude | Latitude | Offense | Area_Name | Offense_start_date_time . I have written a code which gives the top 10 most unsafe areas and 10 most safe areas in Seattle based on the number of crimes there. I would like to plot these on the map of Seattle. The code I have written in Jupyter notebook is: import pandas as pd from shapely.geometry import point import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt import geopandas as gpd from geopandas import GeoDataFrame import geopy from geopy.geocoders import Nominatim import folium from geopy.extra.rate_limiter import RateLimiter from folium import plugins from folium.plugins import MarkerCluster import seaborn as sns df = pd.read_csv('C:/file path.csv') df.head() # to count the number of offenses df.offense.value_counts().iloc[:100] # to list the top 10 crimes in Seattle max_crimes = df.offense.value_counts().nlargest(10) max_crimes # to show the top 10 crimes in a bar chart df.offense.value_counts().iloc[:10].sort_values().plot(kind= 'barh') # to show the top 10 unsafe areas in seattle with the most number of crimes in a pie chart df.Area_Name.value_counts().iloc[:10].sort_values().plot(kind= 'pie') # to list the most 10 unsafe areas in Seattle most_unsafe = df.Area_Name.value_counts().nlargest(10) most_unsafe # to list the most 10 safe areas in Seattle most_safe = df.Area_Name.value_counts().nsmallest(10) most_safe I would like to show the most_unsafe and most_safe areas in the map of Seattle. Can someone please help me with the code for this? In case you need any more information, please let me know. Thanks for your time. From phillor9 at gmail.com Sun Mar 6 19:33:59 2022 From: phillor9 at gmail.com (Phil) Date: Mon, 7 Mar 2022 11:33:59 +1100 Subject: [Tutor] Class access rules Message-ID: I've imported the following class into several wxpython projects and now into a tkinter project and now I'm wondering if I should modify the class by adding setter and getter methods instead of directly accessing the instance attributes. I know that Python will warn me that I shouldn't access these attributes if I prefix them with an underscore. My question is does it really matter or is simply just a method to warn programmers who work in a group to not access those attributes? class Led: ??? def __init__(self, pos, state=False, size=10): ??????? self.pos = pos # position is a tuple (x, y) ??????? self.state = state # True is on, False is off ??????? self.size = size ??????? self.onColour = 'red' ??????? self.offColour = 'black' ??? def toggle(self): ??????? self.state = not self.state I'm thinking of adding a blink method (I'm not sure what use it would be). My initial thoughts seem to show that the method would be specific to tkinter rather than generic. I don't have a method to draw the LED either and instead use either GUI to draw a circle based on the position, state, size and colour of the LED class attributes. I'm thinking that I should do the same with the blink method or should I have specific methods (draw circle and blink) for wxpython and tkinter? I don't think so, but I'm not sure. -- Regards, Phil From mats at wichmann.us Sun Mar 6 19:42:53 2022 From: mats at wichmann.us (Mats Wichmann) Date: Sun, 6 Mar 2022 17:42:53 -0700 Subject: [Tutor] Class access rules In-Reply-To: References: Message-ID: <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us> On 3/6/22 17:33, Phil wrote: > I've imported the following class into several wxpython projects and now > into a tkinter project and now I'm wondering if I should modify the > class by adding setter and getter methods instead of directly accessing > the instance attributes. Why? It's not Java, so it's fine to leave them as attribute access. If you later find you need to add some extra stuff, you can create a getter and/or setter that retains the same apparent attribute access method. If you have a real reason why they need to be getters/setters, then of course go ahead. From phillor9 at gmail.com Sun Mar 6 19:59:32 2022 From: phillor9 at gmail.com (Phil) Date: Mon, 7 Mar 2022 11:59:32 +1100 Subject: [Tutor] Class access rules In-Reply-To: <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us> References: <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us> Message-ID: <9fd4f0f4-c952-7574-107f-e1e0d9c218dd@gmail.com> On 7/3/22 11:42, Mats Wichmann wrote: > > Why? Just for the sake of correctness, that's all. -- Regards, Phil From wlfraed at ix.netcom.com Sun Mar 6 20:48:45 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sun, 06 Mar 2022 20:48:45 -0500 Subject: [Tutor] To show the result on a map References: <2d6f01d831af$58e99310$0abcb930$@gmail.com> Message-ID: <65ma2hl06pt74cllac1nj6joihrpbgflpq@4ax.com> On Sun, 6 Mar 2022 15:10:18 -0800, declaimed the following: >I would like to show the most_unsafe and most_safe areas in the map of >Seattle. Can someone please help me with the code for this? In case you need >any more information, please let me know. > You'll need to define where the map itself is coming from, how coordinates equate to map points, etc. The solution will vary significantly from using, say, Google Maps (sign up for access to the API) https://medium.com/future-vision/google-maps-in-python-part-2-393f96196eaf ... to ArcGIS which has its own API for Python. Are you simply wanting to identify /points/, or draw /regions/ -- I don't think Google Maps does regions, only points. The Plotly package can apparently draw maps -- but you need to subscribe to some map provider for the actual maps it works with; otherwise it may just do polygonal data from coordinates. Are you scanning USGS topographic maps into image files -- then you need image manipulation and some way of encoding lat/long into pixels. https://towardsdatascience.com/creating-beautiful-maps-with-python-6e1aae54c55c https://towardsdatascience.com/making-artistic-maps-with-python-9d37f5ea8af0 This obtains the map vector data from a provider, then generates/saves image files to use PhotoShop/GIMP for adding overlays -- you might be able to do that part using the Python Imaging Library (but again, knowing how to map coordinates into the image is going to be a factor). https://www.earthdatascience.org/courses/scientists-guide-to-plotting-data-in-python/plot-spatial-data/customize-raster-plots/interactive-maps/ -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From cs at cskk.id.au Sun Mar 6 20:31:54 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Mon, 7 Mar 2022 12:31:54 +1100 Subject: [Tutor] Class access rules In-Reply-To: References: Message-ID: On 07Mar2022 11:33, Phil wrote: >I've imported the following class into several wxpython projects and >now into a tkinter project and now I'm wondering if I should modify >the class by adding setter and getter methods instead of directly >accessing the instance attributes. I know that Python will warn me >that I shouldn't access these attributes if I prefix them with an >underscore. My question is does it really matter or is simply just a >method to warn programmers who work in a group to not access those >attributes? Warnings about access to ._foo attributes are just a reminder. The language itself doesn't care. They're just a cue that the implementor of the class considers these attributes irrelevant to the _features_ provided by the class, and importantly: subject to change without warning. So: if these attributes are basic features of the class (and ideally independent of each other, so that setting them directly should not lead to internal-to-the-class nonsense) and won't be going away just access them directly. We don't do much setter/getter methods in Python. We do something make properties, which present as attributes to the outside and are implemented as getter methods with optional setter methods. Example: @property def post_pos(self): ''' The location "beyond" the rectangle implied by pos+size. ''' return (self.pos[0] + self.size, self.pos[1] + self.size) This makes an attribute whose value is _computed_ from self.pos and self.size. In this case there's no need for a setter method because you could try to set this to nonsense (eg different x/y "sizes", not expressible with your class' internal state). Cheers, Cameron Simpson From cs at cskk.id.au Sun Mar 6 22:00:36 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Mon, 7 Mar 2022 14:00:36 +1100 Subject: [Tutor] To show the result on a map In-Reply-To: <65ma2hl06pt74cllac1nj6joihrpbgflpq@4ax.com> References: <65ma2hl06pt74cllac1nj6joihrpbgflpq@4ax.com> Message-ID: On 06Mar2022 20:48, Dennis Lee Bieber wrote: > Are you simply wanting to identify /points/, or draw /regions/ -- I >don't think Google Maps does regions, only points. If they still support KML you can draw regions. And GroundOverlays too (paste an image over an area). Cheers, Cameron Simpson From phillor9 at gmail.com Sun Mar 6 22:54:58 2022 From: phillor9 at gmail.com (Phil) Date: Mon, 7 Mar 2022 14:54:58 +1100 Subject: [Tutor] Class access rules In-Reply-To: References: Message-ID: <23c41ff3-7bac-4708-7ec2-efc9317f9277@gmail.com> On 7/3/22 12:31, Cameron Simpson wrote: > We don't do much setter/getter methods in Python. We do something make > properties, which present as attributes to the outside and are > implemented as getter methods with optional setter methods. Example: > > @property > def post_pos(self): > ''' The location "beyond" the rectangle implied by pos+size. > ''' > return (self.pos[0] + self.size, self.pos[1] + self.size) Thanks Cameron, I read a brief explanation about the use the @property decorator but couldn't see where I could use it. I'll continue with my current line of class usage. -- Regards, Phil From cs at cskk.id.au Sun Mar 6 23:08:32 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Mon, 7 Mar 2022 15:08:32 +1100 Subject: [Tutor] Class access rules In-Reply-To: <23c41ff3-7bac-4708-7ec2-efc9317f9277@gmail.com> References: <23c41ff3-7bac-4708-7ec2-efc9317f9277@gmail.com> Message-ID: On 07Mar2022 14:54, Phil wrote: >On 7/3/22 12:31, Cameron Simpson wrote: >>We don't do much setter/getter methods in Python. We do something make >>properties, which present as attributes to the outside and are >>implemented as getter methods with optional setter methods. Example: >> >> @property >> def post_pos(self): >> ''' The location "beyond" the rectangle implied by pos+size. >> ''' >> return (self.pos[0] + self.size, self.pos[1] + self.size) > >Thanks Cameron, I read a brief explanation about the use the @property >decorator but couldn't see where I could use it. I'll continue with my >current line of class usage. Thank's fine. Plenty of people don't use them much. I use them for things which are (a) secondary things the user will frequently want but which are derived from some more basic thing and (b) cheap, almost always O(1) time to compute (because they look like attributes and people expect attribute access to be essentially free). An example from my POP3 mail fetcher: @property def netrc_entry(self): ''' The default `NetrcEntry` for this `ConnectionSpec`. ''' machine = f'{self.user}@{self.host}:{self.port}' return NetrcEntry.get(machine) @property def password(self): ''' The password for this connection, obtained from the `.netrc` file via the key *user*`@`*host*`:`*port*. ''' entry = self.netrc_entry return entry.password The enclosing class represents a POP3 class whose credentials are kept in a netrc file. So I pretend there's direct access to the netrc entry, and direct access to the password. The former does a look up and the latter grabs the entry from the looked up netrc entry. From outside I start the POP3 stuff like this: self.client_begin() self.client_auth(self.conn_spec.user, self.conn_spec.password) because the calling code just wants to send a username and password without caring where they come from. Cheers, Cameron Simpson From marcus.luetolf at bluewin.ch Mon Mar 7 02:44:54 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Mon, 7 Mar 2022 08:44:54 +0100 Subject: [Tutor] problem solving with lists In-Reply-To: References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> Message-ID: <000401d831f7$3f9c7150$bed553f0$@bluewin.ch> Hello Experts, I might be misunderstood: I am absolutely aware of what computers can do and what computing or more specifically "computationalt hinking" or the difference between an algorithm and a computer code means, having attende edx courses authored by Eric Grimsson and John Guttag from MIT. I should have written ... c) if my problem can by solved with python or any other programming language at all. It's the process of finding an algorithm to solve my task I am stuck with and that's why I addressed tutor with my problem for a hint how to hink about it. I think there is a level of mathematics involved for which I have not enough background if any. I'am very gratefull for your advice to reduce the task to 9 items/letters in sublists of 3 (soem sort of recursion ?) but it doesn't get me any further. Marcus. -----Urspr?ngliche Nachricht----- Von: Tutor Im Auftrag von Alan Gauld via Tutor Gesendet: Sonntag, 6. M?rz 2022 10:04 An: tutor at python.org Betreff: Re: [Tutor] problem solving with lists On 06/03/2022 07:15, marcus.luetolf at bluewin.ch wrote: > Hello Experts, > > I'am still biting my teeth out trying to put in to code the following > pseudocode: > ... c) if my problem can by solved by python at all. It is important to remember that programming languages do not solve problems. They merely provide tools to generalize and automate the solution once YOU have found it. But it's up to you to formulate a solution. And at this point it seems to be the required algorithm that is eluding you rather than the python constructs needed to implement that. Can you reduce the size of the problem and solve it on paper? That may give a clue to how you should solve it for bigger cases. What if you reduce the problem to, say, 9 letters and sublists of only 3? Does that help? Even if it only clarifies the definition of the output. -- 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 at python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor From phillor9 at gmail.com Mon Mar 7 04:54:58 2022 From: phillor9 at gmail.com (Phil) Date: Mon, 7 Mar 2022 20:54:58 +1100 Subject: [Tutor] Class access rules In-Reply-To: References: <23c41ff3-7bac-4708-7ec2-efc9317f9277@gmail.com> Message-ID: On 7/3/22 15:08, Cameron Simpson wrote: > Thank's fine. Plenty of people don't use them much. Thank you again Cameron. I don't think I need a @property decorator in my current project but I've saved your example code for future reference. What I decided to was to create a custom canvas widget class with a draw method and amazingly it worked so I'll continue to expand it with additional methods. -- Regards, Phil From alan.gauld at yahoo.co.uk Mon Mar 7 06:24:20 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 7 Mar 2022 11:24:20 +0000 Subject: [Tutor] problem solving with lists In-Reply-To: <000401d831f7$3f9c7150$bed553f0$@bluewin.ch> References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch> Message-ID: On 07/03/2022 07:44, marcus.luetolf at bluewin.ch wrote: > I should have written ... c) if my problem can by solved with python or any > other programming language at all. Python, or any other "Turing complete" programming language can represent any algorithm you come up with. So the answer is yes, once you have the algorithm. > It's the process of finding an algorithm to solve my task I am stuck with And that is often the hardest bit. > I'am very gratefull for your advice to reduce the task to 9 items/letters in > sublists of 3 (soem sort of recursion ?) > but it doesn't get me any further. Can you solve it by hand? - ie. using a pencil and paper. If not then you don't really understand your problem yet. So you need to write down all the different conditions that must be met, including all the exceptional cases that might arise. Once you understand what needs to be done you should be able to work out how to do it using pencil and paper. That will give you an algorithm. It may not be the most efficient, and it will likely not be generalized to "N sublists from M" elements yet. But it is a start. But unless you understand the solution at that level you are unlikely to be able to write a program to solve it. (Unless it's a swell known algorithm and you can find a library. But it looks as if your requirements are slightly different from the more common cases) We can certainly help you formulate the required algorithm, and possibly some shortcuts. But you need to give us a complete and precise description of the problem. -- 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 From alan.gauld at yahoo.co.uk Mon Mar 7 06:30:01 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 7 Mar 2022 11:30:01 +0000 Subject: [Tutor] Class access rules In-Reply-To: <9fd4f0f4-c952-7574-107f-e1e0d9c218dd@gmail.com> References: <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us> <9fd4f0f4-c952-7574-107f-e1e0d9c218dd@gmail.com> Message-ID: On 07/03/2022 00:59, Phil wrote: > > On 7/3/22 11:42, Mats Wichmann wrote: >> >> Why? > > Just for the sake of correctness, that's all. > There is nothing correct about getters and setters, in fact there's a strong argument for saying they are a fundamental error on OOP. They were introduced in Java as part of the Javabeans definition so that IDEs and GUI builders could use them to create working GUIs on the fly. In good OOP design you should ideally not need to access the internal attributes of a class at all. The methods should do all the work and the attributes are only there internally to support those methods. In practice of course objects often represent data stores and the attributes are of interest. But the goal should be to minimize that and not to expose them. -- 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 From alan.gauld at yahoo.co.uk Mon Mar 7 06:42:04 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 7 Mar 2022 11:42:04 +0000 Subject: [Tutor] Class access rules In-Reply-To: References: Message-ID: On 07/03/2022 00:33, Phil wrote: > class Led: > ??? def __init__(self, pos, state=False, size=10): > > ??? def toggle(self): > ??????? self.state = not self.state > > I'm thinking of adding a blink method (I'm not sure what use it would > be). Don't add methods you don't need (search YAGNI). One of the insanely great things about OOP is that it allows you to easily extend classes to add methods if you need them later: class BlinkingLed(Led): def blink(self, rate=1): # ideally put this loop in a thread if not rate: #stop any existing blinks while rate: self.toggle() sleep(rate) > have specific methods (draw circle and blink) for wxpython and tkinter? The professional answer to this is that you should create the Led as a data object (a "Model") that does the logic of switching state/blinking or whatever and have a separate "View" object that does the drawing on the GUI. Then you can have Tkinter and wxPython view objects and the same generic model object. You need to connect the model and view obviously but that can be as simple as passing the model to the view when you create it. This is a large part of the famous Model View Controller architecture used in most modern GUIs and web frameworks. The amateur approach is just do it for the GUI you are actually using and worry about multi-platform as and when you need it! -- 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 From wlfraed at ix.netcom.com Mon Mar 7 11:23:26 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 07 Mar 2022 11:23:26 -0500 Subject: [Tutor] Class access rules References: <23c41ff3-7bac-4708-7ec2-efc9317f9277@gmail.com> Message-ID: On Mon, 7 Mar 2022 14:54:58 +1100, Phil declaimed the following: > >Thanks Cameron, I read a brief explanation about the use the @property >decorator but couldn't see where I could use it. I'll continue with my >current line of class usage. To give you one viewpoint. I've so seldom used properties that I haven't learned the decorator view... My last use was via the property() function! (which puts everything on one spot, vs having to know that @property only defines a getter, and one has to then use decorators with the name of the getter to create setter/deleter) https://docs.python.org/3/library/functions.html#property My favorite example is for, say, a Point() class which supports coordinates in both Cartesian (x,y) and Polar (rho, theta). The class would only really store one format, say x, y. Accessing rho, theta would then be done via properties to (for read) compute the rho/theta from x/y, and (on write) computing x/y from provided rho/theta (since only one is set at a time, this does get a bit complex -- changing rho requires the setter to first compute existing rho/theta from x/y, then change the rho value, and finally recompute x/y from the new rho and calculated theta. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Mon Mar 7 11:46:42 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 07 Mar 2022 11:46:42 -0500 Subject: [Tutor] problem solving with lists References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <38q92hli62o5rr01oi46d9quoo8i4v8fdf@4ax.com> Message-ID: On Sun, 06 Mar 2022 13:05:26 -0500, Dennis Lee Bieber declaimed the following: > Nested loops with differing increments (skips) may suffice. > > Consider the first set of four substrings: >abcd efgh ijkl mnop > > Now, how to avoid any matching pairs? Well, you could take the "a", and >one character from the other three substrings >aeim afjn agko ahlp > > But you can't do that with "b" -- as beim has "eim" in common. Instead >of matching through "ijkl" you could wrap it -- "jkli". (hint, use a >modulo operator and just increment the position) >bej. bfk. bgl. ghi. > > Now you need to handle "mnop" to fill the "."; perhaps the same wrap? >"nopm". >bejn -- NO, conflicts with afjn. > > So... an algorithm that needs to determine how much of a circular wrap >each four-character substring needs after the first simple splitting, based >upon which starting character is in play. I'll confess I spent too many hours yesterday trying to code a formula that would produce viable cycles with no result. The best I managed was to get three "rows" clear. Granted, just to wake up old skills, I was using REXX for this and its 1-based indexing of strings kept complicating matters. So... If full use of the Python standard library is a viable option... Generate quad-letters (string of four letters, from the string of 16) using itertools combinations. For each fetched quad-letter, perform a set intersection operation against the elements of an "accepted" list. If the fetched quad-letter passes, add it to the accepted list. Stop when appropriate, format for output. I had a bit more detail before, but removed it as the above should be sufficient to trigger reading in the library reference and start an algorithm development. If full use of the Python library is NOT PERMITTED... If not, you'll need to specify what is permitted beyond lists, strings, and slices of either -- and create your own functions for comparison, generation of quad-letters (strings for length 4) from sixteen-letters (a single string of a..p). DON'T think in terms of lists of four letters; pretty much anything you'd do with that list can be done with a string. This route may involve manually writing a combinations procedure -- should be a generator function as you don't want to create all 1820 combinations and /then/ examine them; or coming up with some equation using row/col/char positions to index into the 16-letter string. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Mon Mar 7 13:28:49 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 07 Mar 2022 13:28:49 -0500 Subject: [Tutor] problem solving with lists References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <38q92hli62o5rr01oi46d9quoo8i4v8fdf@4ax.com> Message-ID: On Mon, 07 Mar 2022 11:46:42 -0500, Dennis Lee Bieber declaimed the following: > So... If full use of the Python standard library is a viable option... > > Generate quad-letters (string of four letters, from the string of 16) >using itertools combinations. For each fetched quad-letter, perform a set >intersection operation against the elements of an "accepted" list. If the >fetched quad-letter passes, add it to the accepted list. Stop when >appropriate, format for output. > AND.... Using set intersection appears to fail (runs out of candidates). [['abcd', 'aefg', 'ahij', 'aklm'], ['anop', 'behk', 'bfil', 'bgjm'], ['ceim', 'cfhn', 'cgko', 'cjlp'], ['dejn', 'dfkp', 'dghl'], []] My combinations/set intersection ran out at only 15 quads. Perhaps your description of the acceptance criteria is ambiguous. Original> with constraint that a pair of letters, p.e. ['a', 'b', ..] can occur Original> only once in all 20 sublists Set intersection means that, say "afmp" is in the accepted list, then "fgim" would be rejected as "f" and "m" are common to both quad-letter strings. Is the requirement that ADJACENT PAIRS (in sorted order) result in rejection -- so both "afmp" and "fgim" are accepted, but "fmop" would be rejected as "afmp" and "fmop" have "fm" as adjacent pairs? Or is it even more constrained -- and the adjacent pairs must be at the same offset in the strings? Changing my filter logic to use adjacent pairs, but anywhere in the quad, results in [['abcd', 'acef', 'adeg', 'aehi'], ['afgh', 'agij', 'ahjk', 'aikl'], ['ajlm', 'akmn', 'alno', 'amop'], ['bdfh', 'beil', 'bfim', 'bgjm'], ['bhkn', 'binp', 'cfjn', 'cgko']] FYI: Running without a limit of 20 accepted resulted in a total of only 23 quads passing. [['abcd', 'acef', 'adeg', 'aehi'], ['afgh', 'agij', 'ahjk', 'aikl'], ['ajlm', 'akmn', 'alno', 'amop'], ['bdfh', 'beil', 'bfim', 'bgjm'], ['bhkn', 'binp', 'cfjn', 'cgko'], ['chlo', 'dglp', 'dhmp']] If I assume the pairs must be in the same offset position, I get 35 quads [['abcd', 'acde', 'adef', 'aefg'], ['afgh', 'aghi', 'ahij', 'aijk'], ['ajkl', 'aklm', 'almn', 'amno'], ['anop', 'bceg', 'bdfh', 'begi'], ['bfhj', 'bgik', 'bhjl', 'bikm'], ['bjln', 'bkmo', 'blnp', 'cdgj'], ['cehk', 'cfil', 'cgjm', 'chkn'], ['cilo', 'cjmp', 'deim', 'dfjn'], ['dgko', 'dhlp', 'efkp']] NOTE: All solutions are using itertools.combinations and itertools.filterfalse, but differ on the filter predicate function. {Now, do I want to attempt to code a string combinations generator/iterator in REXX -- I'll need to study if it supports "static" data (previous value retained between invocations) in procedures. Otherwise there may be some ugly global data exposed; filterfalse generator/iterator isn't really required as the filter predicate can be manually called} -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From ludo.a.joris at telenet.be Mon Mar 7 08:02:19 2022 From: ludo.a.joris at telenet.be (Ludo Joris) Date: Mon, 7 Mar 2022 14:02:19 +0100 (CET) Subject: [Tutor] Printing byte arrays Message-ID: <942343061.132289131.1646658139428.JavaMail.zimbra@telenet.be> Hello, Fedora 35, Python 3.10.2 List of strings with 8 ones or zeros. Convert to list of integers, all integers fit in range(256). Convert list to bytes object (not bytearray). Where do those spaces come from when printing this bytes object? >>> a = ['00000000', '11100000', '11100000', '00000000', '11100000', '11100000', '00100000', '11000000', '11100000', '10100000', '10100000', '10100000', '00000000', '00100000', '00100000', '11100000', '11100000', '00100000', '00100000', '00100000', '00100000', '11100000', '11100000', '00100000', '00100000', '11000000', '11100000', '00100000', '11100000', '11000000', '00000000', '00000000', '00000000', '00000000', '00000000', '00000000', '00000000', '10000000', '11100000', '11000000', '11100000', '10000000', '00000000', '11000000', '11100000', '00100000', '11100000', '11000000', '00000000', '00100000', '11100000', '11100000', '00100000', '00000000', '00000000', '00100000', '00100000', '11100000', '11100000', '00100000', '00100000', '11000000', '11100000', '00100000'] >>> b = [int(e,2) for e in a] >>> b [0, 224, 224, 0, 224, 224, 32, 192, 224, 160, 160, 160, 0, 32, 32, 224, 224, 32, 32, 32, 32, 224, 224, 32, 32, 192, 224, 32, 224, 192, 0, 0, 0, 0, 0, 0, 0, 128, 224, 192, 224, 128, 0, 192, 224, 32, 224, 192, 0, 32, 224, 224, 32, 0, 0, 32, 32, 224, 224, 32, 32, 192, 224, 32] >>> c = bytes([int(e,2) for e in a]) >>> c b'\x00\xe0\xe0\x00\xe0\xe0 \xc0\xe0\xa0\xa0\xa0\x00 \xe0\xe0 \xe0\xe0 \xc0\xe0 \xe0\xc0\x00\x00\x00\x00\x00\x00\x00\x80\xe0\xc0\xe0\x80\x00\xc0\xe0 \xe0\xc0\x00 \xe0\xe0 \x00\x00 \xe0\xe0 \xc0\xe0 ' >>> >>> len(a) 64 >>> len(b) 64 >>> len(c) 64 >>> Thanks From alan.gauld at yahoo.co.uk Mon Mar 7 14:46:50 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 7 Mar 2022 19:46:50 +0000 Subject: [Tutor] Printing byte arrays In-Reply-To: <942343061.132289131.1646658139428.JavaMail.zimbra@telenet.be> References: <942343061.132289131.1646658139428.JavaMail.zimbra@telenet.be> Message-ID: On 07/03/2022 13:02, Ludo Joris wrote: >>>> b = [int(e,2) for e in a] >>>> b > [0, 224, 224, 0, 224, 224, 32,... >>>> c = bytes([int(e,2) for e in a]) >>>> c > b'\x00\xe0\xe0\x00\xe0\xe0 \xc0... In UTF8/ASCII decimal 32 is the space character. I'm surprised you aren't getting other random characters and numbers too. You just got 'lucky' in that the only printable values were spaces. -- 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 From wlfraed at ix.netcom.com Mon Mar 7 17:02:29 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 07 Mar 2022 17:02:29 -0500 Subject: [Tutor] Printing byte arrays References: <942343061.132289131.1646658139428.JavaMail.zimbra@telenet.be> Message-ID: On Mon, 7 Mar 2022 14:02:19 +0100 (CET), Ludo Joris declaimed the following: >>>> c >b'\x00\xe0\xe0\x00\xe0\xe0 \xc0\xe0\xa0\xa0\xa0\x00 \xe0\xe0 \xe0\xe0 \xc0\xe0 \xe0\xc0\x00\x00\x00\x00\x00\x00\x00\x80\xe0\xc0\xe0\x80\x00\xc0\xe0 \xe0\xc0\x00 \xe0\xe0 \x00\x00 \xe0\xe0 \xc0\xe0 ' This isn't really "print"ing c as a string, but is producing a representation (repr(c)) which is a form that could be used as a literal in a subsequent assignment. One aspect is that NON-PRINTABLE bytes/characters are shown as hex-escape sequences: \xXX (X is in 0..9a..f). Any bytes mapping to a printable character will be output as that character. Compare: >>> b [0, 224, 224, 0, 224, 224, 32, 192, 224, 160, 160, 160, 0, 32, 32, 224, 224, 32, 32, 32, 32, 224, 224, 32, 32, 192, 224, 32, 224, 192, 0, 0, 0, 0, 0, 0, 0, 128, 224, 192, 224, 128, 0, 192, 224, 32, 224, 192, 0, 32, 224, 224, 32, 0, 0, 32, 32, 224, 224, 32, 32, 192, 224, 32] >>> c = bytes(b) >>> c b'\x00\xe0\xe0\x00\xe0\xe0 \xc0\xe0\xa0\xa0\xa0\x00 \xe0\xe0 \xe0\xe0 \xc0\xe0 \xe0\xc0\x00\x00\x00\x00\x00\x00\x00\x80\xe0\xc0\xe0\x80\x00\xc0\xe0 \xe0\xc0\x00 \xe0\xe0 \x00\x00 \xe0\xe0 \xc0\xe0 ' >>> print(c) b'\x00\xe0\xe0\x00\xe0\xe0 \xc0\xe0\xa0\xa0\xa0\x00 \xe0\xe0 \xe0\xe0 \xc0\xe0 \xe0\xc0\x00\x00\x00\x00\x00\x00\x00\x80\xe0\xc0\xe0\x80\x00\xc0\xe0 \xe0\xc0\x00 \xe0\xe0 \x00\x00 \xe0\xe0 \xc0\xe0 ' >>> print(" ".join(["%2.2X" % bt for bt in c])) 00 E0 E0 00 E0 E0 20 C0 E0 A0 A0 A0 00 20 20 E0 E0 20 20 20 20 E0 E0 20 20 C0 E0 20 E0 C0 00 00 00 00 00 00 00 80 E0 C0 E0 80 00 C0 E0 20 E0 C0 00 20 E0 E0 20 00 00 20 20 E0 E0 20 20 C0 E0 20 >>> in which I explicitly convert each byte into two hex digits (eschewing the \x escape notation) Hex 20 => decimal 32 => ASCII space character >>> byte = bytes(range(256)) >>> byte b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' >>> " ".join(["%2.2X" % bt for bt in byte]) '00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF' >>> >>> print(" ".join(["%2.2X" % bt for bt in byte])) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF >>> -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From phillor9 at gmail.com Mon Mar 7 18:17:23 2022 From: phillor9 at gmail.com (Phil) Date: Tue, 8 Mar 2022 10:17:23 +1100 Subject: [Tutor] Class access rules In-Reply-To: References: <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us> <9fd4f0f4-c952-7574-107f-e1e0d9c218dd@gmail.com> Message-ID: On 7/3/22 22:30, Alan Gauld via Tutor wrote: > In good OOP design you should ideally not need to > access the internal attributes of a class at all. The > methods should do all the work and the attributes are only > there internally to support those methods. In practice > of course objects often represent data stores and the > attributes are of interest. But the goal should be > to minimize that and not to expose them. I suppose I really should have said good practice rather that correctness. My LED class uses a boolean state attribute, if the state is True then the LED is filled with the on_colour. I had in mind creating on and off methods that set the state rather then directly setting the state attribute. From what I understand setting the state attribute directly is good practice. -- Regards, Phil From phillor9 at gmail.com Mon Mar 7 18:42:54 2022 From: phillor9 at gmail.com (Phil) Date: Tue, 8 Mar 2022 10:42:54 +1100 Subject: [Tutor] Class access rules In-Reply-To: References: <23c41ff3-7bac-4708-7ec2-efc9317f9277@gmail.com> Message-ID: <922bae9c-f19b-60fd-105c-859c6b12246f@gmail.com> On 8/3/22 03:23, Dennis Lee Bieber wrote: > To give you one viewpoint. I've so seldom used properties that I > haven't learned the decorator view I think I'll research the property decorator if I ever have a need o use it. -- Regards, Phil From alan.gauld at yahoo.co.uk Mon Mar 7 18:55:52 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 7 Mar 2022 23:55:52 +0000 Subject: [Tutor] Class access rules In-Reply-To: References: <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us> <9fd4f0f4-c952-7574-107f-e1e0d9c218dd@gmail.com> Message-ID: On 07/03/2022 23:17, Phil wrote: >> methods should do all the work and the attributes are only >> there internally to support those methods. > My LED class uses a boolean state attribute, if the state is True then > the LED is filled with the on_colour. I had in mind creating on and off > methods that set the state rather then directly setting the state > attribute. From what I understand setting the state attribute directly > is good practice. Actually I'd advocate having on/off (and maybe toggle) methods. Those are the things you actually do with a LED. How you implement those methods may or may not involve internal state. But I have never in practice asked a LED for its state (unless you count looking at it to see if it is lit I suppose, but that should then become an isLit() predicate) Focusing on the internal state attribute leads to a data centric view of the object rather than its operational interface. But notice how a single state attribute now results in 4 operations. You could just provide two: getState/setState, but then you move the understanding of how the LED operates to the user of the LED rather than it being intrinsic to the LED itself. Remember the OOP axim, "objects do it to themselves"(*) (*) Coad & Nicola in their book "Object Oriented Programming" circa 1993. -- 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 From phillor9 at gmail.com Mon Mar 7 18:58:33 2022 From: phillor9 at gmail.com (Phil) Date: Tue, 8 Mar 2022 10:58:33 +1100 Subject: [Tutor] Tkinter threads Message-ID: Alan mentioned the use of threads when replying to the Class access rules thread. # ideally put this loop in a thread From what I understand, and I haven't researched this topic deeply, tkinter is not multithreaded. How might I put a loop into it's own thread? I have a project (Conway's game of life) where either the GUI or the calculation code needs to be in independent threads. The GUI is very sluggish to unresponsive while cell generations are being calculated. This is a wxpython project, perhaps tkinter handles threads in a way that's more understandable to the amateur programmer. -- Regards, Phil From mats at wichmann.us Mon Mar 7 19:23:54 2022 From: mats at wichmann.us (Mats Wichmann) Date: Mon, 7 Mar 2022 17:23:54 -0700 Subject: [Tutor] Tkinter threads In-Reply-To: References: Message-ID: <83e0e7c9-75ee-b6c9-204e-2ba1833dcf5e@wichmann.us> On 3/7/22 16:58, Phil wrote: > Alan mentioned the use of threads when replying to the Class access > rules thread. > > ?# ideally put this loop in a thread > > From what I understand, and I haven't researched this topic deeply, > tkinter is not multithreaded. How might I put a loop into it's own thread? > > I have a project (Conway's game of life) where either the GUI or the > calculation code needs to be in independent threads. The GUI is very > sluggish to unresponsive while cell generations are being calculated. > This is a wxpython project, perhaps tkinter handles threads in a way > that's more understandable to the amateur programmer. > Just as a general comment: not likely. Threading in Python has to live with the famous GIL - which is, basically, that whenever you're executing Python code that will be modifying object state, the global interpreter lock is used to keep other Python threads from messing with things. You say the GUI is unresponsive while calculation is in progress - but does this actually matter? If you don't know the next generation to display, then there's nothing new to display, so you might as well wait a bit, right? Conway in Python is a pretty well studied topic, just FWIW (as In, people use it as an interview question. [[Deep Sigh]])... but usually people leave the display part of it, because getting the computation right, and efficient, is usually what's considered the interesting problem. From wlfraed at ix.netcom.com Mon Mar 7 19:30:17 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 07 Mar 2022 19:30:17 -0500 Subject: [Tutor] Tkinter threads References: Message-ID: On Tue, 8 Mar 2022 10:58:33 +1100, Phil declaimed the following: >Alan mentioned the use of threads when replying to the Class access rules thread. > > # ideally put this loop in a thread > > From what I understand, and I haven't researched this topic deeply, tkinter is not multithreaded. How might I put a loop into it's own thread? > >I have a project (Conway's game of life) where either the GUI or the calculation code needs to be in independent threads. The GUI is very sluggish to unresponsive while cell generations are being calculated. This is a wxpython project, perhaps tkinter handles threads in a way that's more understandable to the amateur programmer. Not really. Pretty much all of the GUI frameworks operate where there is an "app" object and, after doing all configuration of the GUI, does something like "app.mainloop" or "app.run". The mainloop essentially consists of catching user interface events and invoking callback methods to handle them. If any callbacks take a long time to process, then the GUI "stutters" (sluggish) until the long running callback returns to the mainloop. One CAN start threads to do long running computations, but those threads must not manipulate the GUI itself. If the GUI needs to know when such a thread has completed, the thread has to send a signal to the event processing mainloop, which will trigger a signal specific callback that can then update the GUI display state. The /other/ side is an "idle" handler, which gets called whenever the GUI has no other events to process. Idle handlers can not be long running tasks -- but if a long running task can be "paused" with saved state it can do something like if last_step = 0: do some stuff elif last_step = 1: do another bit of task elif last_step = 2: etc. .... last_step = (last_step + 1) % number_of_steps return last_step and any data that has to keep state between each invocation may need to be global, or provided in some structure. So, making this a method in a class would encapsulate the state. class idle_process: def __init__(self): set up initial state def idle_worker(self): if self.last_step: .... and then, after instantiating it, provide instance.idle_worker to the framework idle task system. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From phillor9 at gmail.com Mon Mar 7 19:33:54 2022 From: phillor9 at gmail.com (Phil) Date: Tue, 8 Mar 2022 11:33:54 +1100 Subject: [Tutor] Class access rules In-Reply-To: References: Message-ID: On 7/3/22 22:42, Alan Gauld via Tutor wrote: > > Don't add methods you don't need (search YAGNI). One of the insanely > great things about OOP is that it allows you to easily extend classes > to add methods if you need them later: The thing is, what do I need? Very few of my projects are truly useful. > class BlinkingLed(Led): > def blink(self, rate=1): > # ideally put this loop in a thread > if not rate: #stop any existing blinks > while rate: > self.toggle() > sleep(rate) This is pretty close to what I have done except my blink is a method. A blinking subclass might be better. > The professional answer to this is that you should create the > Led as a data object (a "Model") that does the logic of switching > state/blinking or whatever and have a separate "View" object > that does the drawing on the GUI. I looked up the model/view object programming idea the last time this came up and I didn't understand how to handle the position of the LED so I included it's position in the class constructor. That way either wxpython or tkinter knew where to place the LED and use it's own draw method. This is unlikely to be considered good practice. > The amateur approach is just do it for the GUI you are > actually using and worry about multi-platform as and > when you need it! It feels like cheating, but that's what I've done this time. -- Regards, Phil From phillor9 at gmail.com Mon Mar 7 20:08:06 2022 From: phillor9 at gmail.com (Phil) Date: Tue, 8 Mar 2022 12:08:06 +1100 Subject: [Tutor] Class access rules In-Reply-To: References: <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us> <9fd4f0f4-c952-7574-107f-e1e0d9c218dd@gmail.com> Message-ID: On 8/3/22 10:55, Alan Gauld via Tutor wrote: > > Actually I'd advocate having on/off (and maybe toggle) methods. That's how this thread started, I was wondering if I should have methods to set the LED's state rather than setting the state attribute directly. This is how I use the state attribute in my toggle method: ??? def toggle(self): ??????? self.state = not self.state I also use the LED's state to determine the LED draw fill colour. > Those are the things you actually do with a LED. > How you implement those methods may or may not involve > internal state. But I have never in practice asked a LED > for its state (unless you count looking at it to see if > it is lit I suppose, but that should then become an isLit() > predicate) Perhaps I should change the name state to is_on? It would still be a boolean flag. > Focusing on the internal state attribute leads to a data > centric view of the object rather than its operational interface. > > But notice how a single state attribute now results in 4 operations. > > You could just provide two: getState/setState, That's what I was originally asking, no doubt clumsily, "Should I modify the class by adding setter and getter methods instead of directly accessing the instance attributes?" > but then you move > the understanding of how the LED operates to the user of the LED > rather than it being intrinsic to the LED itself. Remember > the OOP axim, "objects do it to themselves"(*) > > (*) Coad & Nicola in their book "Object Oriented Programming" Thank you Alan for your time, you've given more to think about. I'm already thinking about the need for the following methods: on, off, toggle, set_size, set on_colour and set_off colour. I cannot, at the moment, see a need for any getter methods. Currently all of this, except for toggle, are achieved through direct access to the attributes. On and off methods would negate the need for a set state (or is_on) method or to set the state attribute directly, because the on, off and toggle methods would set or reset this flag. The class constructor's current default arguments are, state=False, size=10, on_colour='red', off_colour='black'. Back to the drawing board. -- Regards, Phil From alan.gauld at yahoo.co.uk Mon Mar 7 20:34:23 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 8 Mar 2022 01:34:23 +0000 Subject: [Tutor] Class access rules In-Reply-To: References: <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us> <9fd4f0f4-c952-7574-107f-e1e0d9c218dd@gmail.com> Message-ID: On 08/03/2022 01:08, Phil wrote: >> Actually I'd advocate having on/off (and maybe toggle) methods. > > That's how this thread started, I was wondering if I should have methods > to set the LED's state rather than setting the state attribute directly. but there is a world of difference between having methods to set the "state" on/off and having metjods to turn the LED on/off. The code may look the same but to the user the latter is much more intuitive myLed = Led() myLed.setState(True) myLed = Led() myLed.on() The second is much more easy to understand and gives no clue to what the internal data structures look like. > This is how I use the state attribute in my toggle method: > > ??? def toggle(self): > ??????? self.state = not self.state Which s fine. The user doesn't need to know how you do it. > I also use the LED's state to determine the LED draw fill colour. Yes, and that would be true whether you controlled the visuals in a View or directly in the Model. > Perhaps I should change the name state to is_on? It would still be a > boolean flag. That would remove the need for the predicate method but you should still have on/off operations(ie methods). Think how clumsy this looks: myLed = Led() myLed.is_on = True compared to myLed.on() The direct command is how you use a LED. You throw a switch and it turns on, you don;t worry about its internal state. > That's what I was originally asking, no doubt clumsily, "Should I modify > the class by adding setter and getter methods instead of directly > accessing the instance attributes?" seytter/getters impy modifying an intenal attribute. on/off/toggle are operations on a real LED. The internal code is identical to set/get methods but the difference in name makes a huge difference to how your users (which might just be you!) perceive the use of the LED object. > on, off, toggle, set_size, set on_colour and set_off colour. I cannot, > at the moment, see a need for any getter methods. Currently all of this, > except for toggle, are achieved through direct access to the attributes. They shouldn't be. They should be actual methods even if those methods do just change the internal state attribute. The need for an is_on() method (or renamed state attribute) would be especially useful if you separate the model and view. The view needs to query whether the LED is on to know what colour to display. (Even if the colours are supplied by the LED too!) > On and off methods would negate the need for a set state (or is_on) > method or to set the state attribute directly, because the on, off and > toggle methods would set or reset this flag. Correct. That's what I mean about the internal state only being there to support the exposed operations. > The class constructor's current default arguments are, state=False, > size=10, on_colour='red', off_colour='black'. If you replace state with is_on I think tat looks reasonable. Then create a LedView class that takes things like position, size, shape, model as init arguments. Every time the LedView draws itself it will look up the current LED status via the is_on attribute and use the on/off color attributes to draw the Led. but the control of its position and size within the GUI are entirely the View's own responsibility, the Led doesn't need to know anything about that. -- 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 From alan.gauld at yahoo.co.uk Mon Mar 7 20:48:30 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 8 Mar 2022 01:48:30 +0000 Subject: [Tutor] Tkinter threads In-Reply-To: References: Message-ID: On 07/03/2022 23:58, Phil wrote: > Alan mentioned the use of threads when replying to the Class access rules thread. > > # ideally put this loop in a thread > > From what I understand, and I haven't researched this topic deeply, > tkinter is not multithreaded. How might I put a loop into it's own thread? By not putting it in the Tkinter part of your code. If you also adopt the Model/View paradigm then the threading is in the non Tkinter Model part of your code. It periodically updates the state of the Led. Meanwhile the Tkinter code is running in its own thread(usually the main one!) and when needed it reads the current state of the Led (see the other discussion about the View object) and displays it, quite oblivious to the existence of any threads. > I have a project (Conway's game of life) where either the GUI or > the calculation code needs to be in independent threads. The GUI > is very sluggish to unresponsive while cell generations are being > calculated. You could use the same approach but Python threading has a gotcha which is that it doesn't really hep if the thread does not block for any I/O or memory/file access. So you might need concurrency instead. However, for a game of life program this shouldn't really be a problem unless your cell colony is gigantic! And usually there is very little interaction by users, the colony, once started, just runs to completion. But in most games of life I've written it's more likely that I'd be putting in sleep() statements to create a pause between displays rather than needing to wait for the calculations. Are you sure you are calculating efficiently? > This is a wxpython project, perhaps tkinter handles threads Very few GUIs "handle threads" because they usually run in the top level thread and any threads are started by the model objects. But threading is always a risky approach and only advised when absolutely necessary. (Like your toggle loop which would, without threading, lock up the program indefinitely! There are other approaches you can use but threading is probably the simplest in this simple case) -- 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 From alan.gauld at yahoo.co.uk Mon Mar 7 20:56:56 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 8 Mar 2022 01:56:56 +0000 Subject: [Tutor] Class access rules In-Reply-To: References: Message-ID: On 08/03/2022 00:33, Phil wrote: > > On 7/3/22 22:42, Alan Gauld via Tutor wrote: >> class BlinkingLed(Led): >> def blink(self, rate=1): >> # ideally put this loop in a thread >> if not rate: #stop any existing blinks >> while rate: >> self.toggle() >> sleep(rate) > > This is pretty close to what I have done except my blink is a method. Note that blink() is a method here too, just restrictred to the subclass. myLed = BlinkingLed() myLed.on() # can still use normal Led methods myLed.off() myLed.blink() # but can also blink. > I looked up the model/view object programming idea the last time this > came up and I didn't understand how to handle the position of the LED Position is part of its visual representation so goes in the view. But MVC is hard to get used to, and more difficult because there are very many variations that all tackle the same basic structure but use slightly different approaches. Ultimately they all aspire to: Model - controls the data and logical operation of the object View - controls everything about how the object appears Controller - Handles the interaction of the object and the user. It determines whether a user action requires a model or view method (or both) >> The amateur approach is just do it for the GUI you are >> actually using and worry about multi-platform as and >> when you need it! > > It feels like cheating, but that's what I've done this time. It's not cheating but it tends not to be very scaleable or portable so leads to ore work on a long running project. But most amateur projects are not that long lived or required to be that portable or scaleable. -- 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 From __peter__ at web.de Tue Mar 8 03:36:15 2022 From: __peter__ at web.de (Peter Otten) Date: Tue, 8 Mar 2022 09:36:15 +0100 Subject: [Tutor] Tkinter threads In-Reply-To: References: Message-ID: <2dbb4e82-8c14-7b7a-a018-d271e27563ff@web.de> On 08/03/2022 00:58, Phil wrote: > Alan mentioned the use of threads when replying to the Class access > rules thread. > > ?# ideally put this loop in a thread > > From what I understand, and I haven't researched this topic deeply, > tkinter is not multithreaded. How might I put a loop into it's own thread? > > I have a project (Conway's game of life) where either the GUI or the > calculation code needs to be in independent threads. The GUI is very > sluggish to unresponsive while cell generations are being calculated. > This is a wxpython project, perhaps tkinter handles threads in a way > that's more understandable to the amateur programmer. > If you have a loop like while some_condition: do_stuff() sleep(delay_in_seconds) you don't have to put it into a separate thread. Replace sleep() with Tk.after() instead: class App(tk.Tk): def repeat_stuff(self): do_stuff() if not some_condition: self.after(delay_in_milliseconds, self.repeat_stuff) root = App() root.repeat_stuff() root.mainloop() This is under the assumption that do_stuff() doesn't take long enough to produce an annoying lag in the GUI. On the rare occasions where I've used tkinter with threads I've followed a recipe by the late Fredrik Lundh: https://web.archive.org/web/20170505053848/http://effbot.org/zone/tkinter-threads.htm The threads write to a queue.Queue() that is polled by the main (tkinter) thread. These days there's also asyncio. I've yet to wrap my head around that, though, so no sample code here :( From wlfraed at ix.netcom.com Tue Mar 8 10:17:25 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Tue, 08 Mar 2022 10:17:25 -0500 Subject: [Tutor] problem solving with lists References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <38q92hli62o5rr01oi46d9quoo8i4v8fdf@4ax.com> Message-ID: o/~ Talking to myself in public... o/~ On Mon, 07 Mar 2022 13:28:49 -0500, Dennis Lee Bieber declaimed the following: >NOTE: All solutions are using itertools.combinations and >itertools.filterfalse, but differ on the filter predicate function. > If the OP is still "listening"... Generating all (1820) combinations first, and then trying to exclude those sharing adjacent letter pairs by testing the first against the rest of the list is a complete failure -- accepting only the last generated quad-letter (since, if you've eliminated all prior quads for sharing letter pairs, the only remaining quad is now unique sharing with nothing). In contrast, the step-wise generate/filter-against-accepted-only process, begins with one accepted quad (the first, since there is nothing else against which to filter it out). One could still generate all 1820 combinations, but the filter logic still has to be: reject a quad if it shares any letter pairs with previously accepted quads (NOT with the rest of the 1820 combinations). If running from the top-down (generation order), the result would be the same as the step-wise method that generates new quads on demand, and only has to maintain the shorter "accepted" list of quads. Of course, one could process the full list in reverse (accepting the last quad automatically, the checking the next prior quad against it, etc.). This WILL result in a different set of quads being accepted. Might as well just run the step-wise process over a "reversed" generator (which will likely generate all 1820 in order to reverse the list, but that is behind the scenes). Generator order: quadFilter = filterfalse(theFilter, quads) >>> 23 [['abcd', 'acef', 'adeg', 'aehi'], ['afgh', 'agij', 'ahjk', 'aikl'], ['ajlm', 'akmn', 'alno', 'amop'], ['bdfh', 'beil', 'bfim', 'bgjm'], ['bhkn', 'binp', 'cfjn', 'cgko'], ['chlo', 'dglp', 'dhmp']] Reversed order: quadFilter = filterfalse(theFilter, reversed(list(quads))) >>> 20 [['mnop', 'klnp', 'jlmp', 'jkmo'], ['hilp', 'gikp', 'ghlo', 'fijp'], ['fhko', 'fgkn', 'ehjo', 'egjn'], ['efjm', 'deip', 'cdio', 'bdhp'], ['bcin', 'adgp', 'acho', 'abim']] Interesting -- reversed produced exactly 20 accepted quads, whereas forward found 23... I wonder if the instructor may have coded something in that nature -- by whatever means -- and based the assignment on this (hmmm, pondering a recursive scheme to create the 1820 quads, and then unwinding the stack would mean starting with "mnop" as the first quad to be filtered/accepted... Though a recursion depth of 1820 sounds obscene to me) >{Now, do I want to attempt to code a string combinations generator/iterator >in REXX -- I'll need to study if it supports "static" data (previous value >retained between invocations) in procedures. Otherwise there may be some >ugly global data exposed; filterfalse generator/iterator isn't really >required as the filter predicate can be manually called} Not that anyone cares -- using the Python documentation for itertools.combinations I did manage to code something in REXX similar to the generator (convoluted as no "yield" equivalent, nor StopIteration; and only one "generator" could be in use at a time due to how state was carried between calls... I'm not going to study an Object REXX text to see if I can create a class for the generator!). It produces the same 23 quads as "forward" processing Python does, so at least the combination generator works for that case. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From mayoadams at gmail.com Tue Mar 8 12:38:11 2022 From: mayoadams at gmail.com (Mayo Adams) Date: Tue, 8 Mar 2022 12:38:11 -0500 Subject: [Tutor] problem solving with lists In-Reply-To: References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <38q92hli62o5rr01oi46d9quoo8i4v8fdf@4ax.com> Message-ID: > > with constraint that a pair of letters, p.e. ['a', 'b', ..] can occur > only once in all 20 sublists > Was the assignment for adjacent letters? Surely it was, if " or in the next part means "namely": or if list1 contains sublist ['a', 'b',..], such a sublist cannot appear > in list2 through list5. On Tue, Mar 8, 2022 at 10:17 AM Dennis Lee Bieber wrote: > > o/~ Talking to myself in public... o/~ > > On Mon, 07 Mar 2022 13:28:49 -0500, Dennis Lee Bieber > declaimed the following: > > >NOTE: All solutions are using itertools.combinations and > >itertools.filterfalse, but differ on the filter predicate function. > > > > If the OP is still "listening"... > > Generating all (1820) combinations first, and then trying to > exclude > those sharing adjacent letter pairs by testing the first against the rest > of the list is a complete failure -- accepting only the last generated > quad-letter (since, if you've eliminated all prior quads for sharing letter > pairs, the only remaining quad is now unique sharing with nothing). > > In contrast, the step-wise generate/filter-against-accepted-only > process, begins with one accepted quad (the first, since there is nothing > else against which to filter it out). > > One could still generate all 1820 combinations, but the filter > logic > still has to be: reject a quad if it shares any letter pairs with > previously accepted quads (NOT with the rest of the 1820 combinations). If > running from the top-down (generation order), the result would be the same > as the step-wise method that generates new quads on demand, and only has to > maintain the shorter "accepted" list of quads. > > Of course, one could process the full list in reverse (accepting > the > last quad automatically, the checking the next prior quad against it, > etc.). This WILL result in a different set of quads being accepted. Might > as well just run the step-wise process over a "reversed" generator (which > will likely generate all 1820 in order to reverse the list, but that is > behind the scenes). > > Generator order: > quadFilter = filterfalse(theFilter, quads) > > >>> 23 > [['abcd', 'acef', 'adeg', 'aehi'], > ['afgh', 'agij', 'ahjk', 'aikl'], > ['ajlm', 'akmn', 'alno', 'amop'], > ['bdfh', 'beil', 'bfim', 'bgjm'], > ['bhkn', 'binp', 'cfjn', 'cgko'], > ['chlo', 'dglp', 'dhmp']] > > Reversed order: > quadFilter = filterfalse(theFilter, reversed(list(quads))) > > >>> 20 > [['mnop', 'klnp', 'jlmp', 'jkmo'], > ['hilp', 'gikp', 'ghlo', 'fijp'], > ['fhko', 'fgkn', 'ehjo', 'egjn'], > ['efjm', 'deip', 'cdio', 'bdhp'], > ['bcin', 'adgp', 'acho', 'abim']] > > Interesting -- reversed produced exactly 20 accepted quads, whereas > forward found 23... I wonder if the instructor may have coded something in > that nature -- by whatever means -- and based the assignment on this (hmmm, > pondering a recursive scheme to create the 1820 quads, and then unwinding > the stack would mean starting with "mnop" as the first quad to be > filtered/accepted... Though a recursion depth of 1820 sounds obscene to me) > > > > >{Now, do I want to attempt to code a string combinations > generator/iterator > >in REXX -- I'll need to study if it supports "static" data (previous value > >retained between invocations) in procedures. Otherwise there may be some > >ugly global data exposed; filterfalse generator/iterator isn't really > >required as the filter predicate can be manually called} > > Not that anyone cares -- using the Python documentation for > itertools.combinations I did manage to code something in REXX similar to > the generator (convoluted as no "yield" equivalent, nor StopIteration; and > only one "generator" could be in use at a time due to how state was carried > between calls... I'm not going to study an Object REXX text to see if I can > create a class for the generator!). > > It produces the same 23 quads as "forward" processing Python does, > so > at least the combination generator works for that case. > > > -- > Wulfraed Dennis Lee Bieber AF6VN > wlfraed at ix.netcom.com > http://wlfraed.microdiversity.freeddns.org/ > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- Mayo Adams 287 Erwin Rd. Chapel Hill, NC 27514 (919)-780-3917 mayoadams at gmail.com From phillor9 at gmail.com Tue Mar 8 18:17:26 2022 From: phillor9 at gmail.com (Phil) Date: Wed, 9 Mar 2022 10:17:26 +1100 Subject: [Tutor] Tkinter threads In-Reply-To: <2dbb4e82-8c14-7b7a-a018-d271e27563ff@web.de> References: <2dbb4e82-8c14-7b7a-a018-d271e27563ff@web.de> Message-ID: <4a4f81d5-cb83-8cba-a6e3-2dd3440fe261@gmail.com> On 8/3/22 19:36, Peter Otten wrote: > If you have a loop like > > while some_condition: > ??? do_stuff() > ??? sleep(delay_in_seconds) > > you don't have to put it into a separate thread. > Replace sleep() with Tk.after() instead: Thank you Peter, My game of life project is written for wxpython rather than tkinter. I use wxpython's time event to do the cell generation calculations which is intense enough to cause my old laptop to run hot fairly quickly and the GUI to become sluggish. I use the GUI to select different seed patterns and adjust the speed of cell generation while it's running. I've used threads in C++ and so I thought that would be the answer under tkinter but... It's not something that occupies much of my time, I was just wondering. -- Regards, Phil From wlfraed at ix.netcom.com Tue Mar 8 18:59:12 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Tue, 08 Mar 2022 18:59:12 -0500 Subject: [Tutor] Tkinter threads References: <2dbb4e82-8c14-7b7a-a018-d271e27563ff@web.de> <4a4f81d5-cb83-8cba-a6e3-2dd3440fe261@gmail.com> Message-ID: On Wed, 9 Mar 2022 10:17:26 +1100, Phil declaimed the following: > >My game of life project is written for wxpython rather than tkinter. I >use wxpython's time event to do the cell generation calculations which >is intense enough to cause my old laptop to run hot fairly quickly and >the GUI to become sluggish. I use the GUI to select different seed >patterns and adjust the speed of cell generation while it's running. > The compute thread likely would call wxPython's .callAfter() [which queues an event for the main app to process -- probably a function to update the grid] when it has computed a complete state update (and should probably then wait on a Queue or other synchronization method, which the main app would signal when it had consumed [displayed] the current state data, before starting to compute the next grid pattern). -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From phillor9 at gmail.com Tue Mar 8 19:52:08 2022 From: phillor9 at gmail.com (Phil) Date: Wed, 9 Mar 2022 11:52:08 +1100 Subject: [Tutor] Tkinter threads In-Reply-To: References: <2dbb4e82-8c14-7b7a-a018-d271e27563ff@web.de> <4a4f81d5-cb83-8cba-a6e3-2dd3440fe261@gmail.com> Message-ID: <7a06235e-732b-a81a-c27d-d4b767033673@gmail.com> On 9/3/22 10:59, Dennis Lee Bieber wrote: > > The compute thread likely would call wxPython's .callAfter() [which > queues an event for the main app to process -- probably a function to > update the grid] when it has computed a complete state update (and should > probably then wait on a Queue or other synchronization method, which the > main app would signal when it had consumed [displayed] the current state > data, before starting to compute the next grid pattern). That sounds logical Dennis, perhaps I'll look into it after I get my current project out of the way. -- Regards, Phil From marcus.luetolf at bluewin.ch Wed Mar 9 14:39:56 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Wed, 9 Mar 2022 20:39:56 +0100 Subject: [Tutor] problem solving with lists In-Reply-To: References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch> Message-ID: <000801d833ed$78111200$68333600$@bluewin.ch> Hello Experts, many thanks for your offer. My problem to solve: for a sublist of length 3 and a list of 9 letters (all_letters = list('abcdefghi')) create 4 lists ( = (len(all_letters)- 1)/2), each containing 3 sublists (9/3) for a total of 12 sublists. Append all 9 letters to each list, 3 letters to each sublist 4 times. Apply a constraint that in all 12 sublists a pairing of 2 letters can occur only once. P.e. if the first sublist of the first list = ['a', 'b', 'c'] the combination of 'a','b' or 'a', 'c', or 'b','c' cannot occur in a sublist in the subsequent lists any more. A solution exists only for a specific lenght of sublists and number of letters: (number of letters -1)%(length of sublist -1) == 0 In the first part of my algorithm I created sublists of all possible letter combInations: >all_letters = list('abcdefghi') >l1 = [] >l2 = [] >l3 = [] >l4 = [] >chars = [] >for index, letter in enumerate(all_letters): > copy_all_letters = all_letters[:] > del(copy_all_letters[index]) > lst = copy_all_letters > l1.append(lst[0]) > l1.append(lst[1]) > l1.append(letter) > l1.sort() > chars.append(l1) > l2.append(lst[2]) > l2.append(lst[3]) > l2.append(letter) > l2.sort() > chars.append(l2) > l3.append(lst[4]) > l3.append(lst[5]) > l3.append(letter) > l3.sort() > chars.append(l3) > l4.append(lst[6]) > l4.append(lst[7]) > l4.append(letter) > l4.sort() > chars.append(l4) > l1 = [] > l2 = [] > l3 = [] > l4 = [] >print(chars, len(chars)) >all_chars = [] >for i in chars: > if i not in all_chars: > all_chars.append(i) >print('all_chars: ', all_chars, len(all_chars)) In a second step I should create sub_sub_lists containing all possble pairs of letters (['a', 'b'], ['a', 'c'] ..... ['i', 'h'] , a total of len(all_letters) -1 * len(all_letters) = 72 and eliminating sub_sub_lists with equal pairs when 'a', 'b' = 'b', 'a'. In a third step append to a final list only sublists not already containing one ot the sub_sub_lists It is this third step I am unable to code efficiently, avoiding to hardcode it. In a last step the code (if it works properly including border cases) should be changed in a function for use with a length of sublists of 4 and number of letters of 16 or other combinations if a solution is possible. Finally the letters will be sustituted by words. I hope I made myself clear, Marcus. -----Urspr?ngliche Nachricht----- Von: Tutor Im Auftrag von Alan Gauld via Tutor Gesendet: Montag, 7. M?rz 2022 12:24 An: tutor at python.org Betreff: Re: [Tutor] problem solving with lists On 07/03/2022 07:44, marcus.luetolf at bluewin.ch wrote: > I should have written ... c) if my problem can by solved with python > or any other programming language at all. Python, or any other "Turing complete" programming language can represent any algorithm you come up with. So the answer is yes, once you have the algorithm. > It's the process of finding an algorithm to solve my task I am stuck > with And that is often the hardest bit. > I'am very gratefull for your advice to reduce the task to 9 > items/letters in sublists of 3 (soem sort of recursion ?) but it > doesn't get me any further. Can you solve it by hand? - ie. using a pencil and paper. If not then you don't really understand your problem yet. So you need to write down all the different conditions that must be met, including all the exceptional cases that might arise. Once you understand what needs to be done you should be able to work out how to do it using pencil and paper. That will give you an algorithm. It may not be the most efficient, and it will likely not be generalized to "N sublists from M" elements yet. But it is a start. But unless you understand the solution at that level you are unlikely to be able to write a program to solve it. (Unless it's a swell known algorithm and you can find a library. But it looks as if your requirements are slightly different from the more common cases) We can certainly help you formulate the required algorithm, and possibly some shortcuts. But you need to give us a complete and precise description of the problem. -- 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 at python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor From alan.gauld at yahoo.co.uk Wed Mar 9 16:19:04 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 9 Mar 2022 21:19:04 +0000 Subject: [Tutor] problem solving with lists In-Reply-To: <000801d833ed$78111200$68333600$@bluewin.ch> References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch> <000801d833ed$78111200$68333600$@bluewin.ch> Message-ID: On 09/03/2022 19:39, marcus.luetolf at bluewin.ch wrote: > for a sublist of length 3 and a list of 9 letters (all_letters = > list('abcdefghi')) > create 4 lists ( = (len(all_letters)- 1)/2), each containing 3 sublists > (9/3) for a total of 12 sublists. > In the first part of my algorithm I created sublists of all possible letter > combInations: > >> all_letters = list('abcdefghi') all_letter = 'abcdefghi' # no need to create a list >> chars = [] >> for index, letter in enumerate(all_letters): >> l1 = [] # initialize once at top of loop >> l2 = [] >> l3 = [] >> l4 = [] >> copy_all_letters = all_letters[:] >> del(copy_all_letters[index]) >> lst = copy_all_letters You could just have done: lst = all_letters[:] del(lst[index]) >> l1.append(lst[0]) >> l1.append(lst[1]) >> l1.append(letter) >> l1.sort() >> chars.append(l1) chars = [[a,b,c]] >> l2.append(lst[2]) >> l2.append(lst[3]) >> l2.append(letter) >> l2.sort() >> chars.append(l2) chars = [[a,b,c],[a,d,e]] >> l3.append(lst[4]) >> l3.append(lst[5]) >> l3.append(letter) >> l3.sort() >> chars.append(l3) chars = [[a,b,c],[a,d,e],[a,f,g]] >> l4.append(lst[6]) >> l4.append(lst[7]) >> l4.append(letter) >> l4.sort() >> chars.append(l4) chars = [[a,b,c],[a,d,e],[a,f,g],[a,h,i]] After the first iteration. Is that correct? Is it what you want it to contain? After the first 4 iterations: chars = [ [a,b,c],[a,d,e],[a,f,g],[a,h,i], [a,b,c],[b,d,e],[b,f,g],[b,h,i], [a,b,c],[c,d,e],[c,f,g],[c,h,i], [a,b,d],[c,d,e],[d,f,g],[d,h,i] ] You already have 12 sublists but you still have another 5 loop iterations to go, so you will wind up with 9 groups of 4 sublists, 36 in total. I don't think that's what you wanted? >> print(chars, len(chars)) This should have highlighted the issue, if indeed it is an issue. >> all_chars = [] >> for i in chars: so i represents a sublist above. sub_list might have been clearer... >> if i not in all_chars: >> all_chars.append(i) So that removed duplicates? Maybe create a set of sublists instead? >> print('all_chars: ', all_chars, len(all_chars)) > > In a second step I should create sub_sub_lists containing> all possble pairs They aren't really sub_sub_lists though. They are completely separate lists of pairs. > of letters (['a', 'b'], ['a', 'c'] ..... ['i', 'h'] , > a total of len(all_letters) -1 * len(all_letters) = 72 and eliminating > sub_sub_lists with equal pairs when 'a', 'b' = 'b', 'a'. One of the itertools modules methods should be able to do this for you. So let's assume: pairs = itertools.some_magic_here(all_chars...) > In a third step append to a final list only sublists not already containing > one of the sub_sub_lists Let's reword that to sublists of chars containing sublists of pairs. > > It is this third step I am unable to code efficiently, avoiding to hardcode > it. Efficiently is always a dangerous word. What constitutes efficient? How do you measure it? How do you know whether an algorithm is "efficient" or not? Start with the simple approach(pseudo code - you may want some helper functions for the tests): result = [] used_pairs = [] for sub_list in chars: for pair in pairs: if pair in sub_list and pair not in used_pairs: result.append(sub_list) used_pairs.append(pair) break # next sublist??? may need more here??? I think, I'm not 100% confident I understood that step. That's why it helps to see the pencil & paper outcome. ie. what does correct look like? Can you post your manual solution for each of the three steps? Even 9 letters might be two much, try reducing it to 6 letters if that's the case. > In a last step the code (if it works properly including border cases) should > be changed in a function for use with a > length of sublists of 4 and number of letters of 16 or other combinations if > a solution is possible. Seems to me each step could (should?) be a function... > Finally the letters will be sustituted by words. I have no clue what that means! Which words? Where do they come from? Is it a master dictionary perhaps with letters corresponding to words? -- 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 From wlfraed at ix.netcom.com Wed Mar 9 19:42:09 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Wed, 09 Mar 2022 19:42:09 -0500 Subject: [Tutor] problem solving with lists References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch> <000801d833ed$78111200$68333600$@bluewin.ch> Message-ID: On Wed, 9 Mar 2022 20:39:56 +0100, declaimed the following: >Hello Experts, >many thanks for your offer. My problem to solve: > >for a sublist of length 3 and a list of 9 letters (all_letters = >list('abcdefghi')) >create 4 lists ( = (len(all_letters)- 1)/2), each containing 3 sublists >(9/3) for a total of 12 sublists. "create 4 lists" is noise... Just create the one list of 12 triplets -- you can THEN split that into your 4x3 layout. That presumes there ARE 12 passing triplets. > >Append all 9 letters to each list, 3 letters to each sublist 4 times. > >Apply a constraint that in all 12 sublists a pairing of 2 letters can occur >only once. >P.e. if the first sublist of the first list = ['a', 'b', 'c'] the >combination of 'a','b' or 'a', 'c', or 'b','c' >cannot occur in a sublist in the subsequent lists any more. > So far, the above description is essentially the same as the original post in this thread, except replacing 4-character with 3 and 16-character with 9 -- except you've now described a constraint that /any/ pair of letters can not appear a second time, not just adjacent pairs. That means working with sets and set intersection is viable to filter rejects. >A solution exists only for a specific lenght of sublists and number of >letters: >(number of letters -1)%(length of sublist -1) == 0 > >In the first part of my algorithm I created sublists of all possible letter >combInations: > >>all_letters = list('abcdefghi') Just leave this as all string... You can index a string just like a list. > >>l1 = [] >>l2 = [] >>l3 = [] >>l4 = [] > >>chars = [] >>for index, letter in enumerate(all_letters): >> copy_all_letters = all_letters[:] >> del(copy_all_letters[index]) >> lst = copy_all_letters Why copy "all_letters" only to then remove one based upon index... And then you attach second name to that copy. >>> all_letters = "abcdefghi" >>> ltr = "a" >>> copy_less = "".join(all_letters.split(ltr)) >>> copy_less 'bcdefghi' >> l1.append(lst[0]) >> l1.append(lst[1]) >> l1.append(letter) >> l1.sort() Again, this brute-force approach is not scalable -- all four combinations for a given "ltr" can be done >>> triples = [] >>> for x in range(0, len(copy_less), 2): ... triples.append("".join(sorted([ltr, copy_less[x], copy_less[x+1]]))) ... >>> triples ['abc', 'ade', 'afg', 'ahi'] >>> And just if you don't believe the .split(ltr) works... >>> ltr = "c" >>> copy_less = "".join(all_letters.split(ltr)) >>> copy_less 'abdefghi' >>> triples = [] >>> for x in range(0, len(copy_less), 2): ... triples.append("".join(sorted([ltr, copy_less[x], copy_less[x+1]]))) ... >>> triples ['abc', 'cde', 'cfg', 'chi'] >>> I don't recommend that approach, BTW -- just showing it in-line with your brute-force scheme. >>all_chars = [] >>for i in chars: >> if i not in all_chars: >> all_chars.append(i) >>print('all_chars: ', all_chars, len(all_chars)) > >In a second step I should create sub_sub_lists containing all possble pairs >of letters (['a', 'b'], ['a', 'c'] ..... ['i', 'h'] , >a total of len(all_letters) -1 * len(all_letters) = 72 and eliminating >sub_sub_lists with equal pairs when 'a', 'b' = 'b', 'a'. > And here is the main problem with your attempt -- in my view. If you create ALL possible triples first, and THEN try to eliminate those that share 2 characters, you will eliminate everything! since in any collection of all possible triples, all pairs will occur multiple times. Here are all 84 possible triples, generated in TWO lines of code! >>> import itertools >>> triples = ["".join(combo) for combo in itertools.combinations("abcdefghi", 3)] >>> triples ['abc', 'abd', 'abe', 'abf', 'abg', 'abh', 'abi', 'acd', 'ace', 'acf', 'acg', 'ach', 'aci', 'ade', 'adf', 'adg', 'adh', 'adi', 'aef', 'aeg', 'aeh', 'aei', 'afg', 'afh', 'afi', 'agh', 'agi', 'ahi', 'bcd', 'bce', 'bcf', 'bcg', 'bch', 'bci', 'bde', 'bdf', 'bdg', 'bdh', 'bdi', 'bef', 'beg', 'beh', 'bei', 'bfg', 'bfh', 'bfi', 'bgh', 'bgi', 'bhi', 'cde', 'cdf', 'cdg', 'cdh', 'cdi', 'cef', 'ceg', 'ceh', 'cei', 'cfg', 'cfh', 'cfi', 'cgh', 'cgi', 'chi', 'def', 'deg', 'deh', 'dei', 'dfg', 'dfh', 'dfi', 'dgh', 'dgi', 'dhi', 'efg', 'efh', 'efi', 'egh', 'egi', 'ehi', 'fgh', 'fgi', 'fhi', 'ghi'] >>> You need to generate one triple first, and just accept that this triple will be unique (there are no others to compare against). Then generate a second triple and test it against the first triple -- if it shares two letters, then you reject the second triple and generate another. Repeat until you have a triple that passes the criteria. You then continue generating triples and testing against the accepted ones... Consider this, which is your testing against everything logic... And is based upon the idea that the letter pairs do not have to adjacent. >>> for trip1 in triples: ... ctriples = triples[:] ... ctriples.remove(trip1) ... for trip2 in ctriples: ... if len(set(trip1) & set(trip2)) >= 2: ... print("%s REJECTED shares with %s" % (trip1, trip2)) ... break ... else: ... print("%s ACCEPTED not shared" % trip1) ... abc REJECTED shares with abd abd REJECTED shares with abc abe REJECTED shares with abc abf REJECTED shares with abc abg REJECTED shares with abc abh REJECTED shares with abc abi REJECTED shares with abc acd REJECTED shares with abc ace REJECTED shares with abc acf REJECTED shares with abc acg REJECTED shares with abc ach REJECTED shares with abc aci REJECTED shares with abc ade REJECTED shares with abd adf REJECTED shares with abd adg REJECTED shares with abd adh REJECTED shares with abd adi REJECTED shares with abd aef REJECTED shares with abe aeg REJECTED shares with abe aeh REJECTED shares with abe aei REJECTED shares with abe afg REJECTED shares with abf afh REJECTED shares with abf afi REJECTED shares with abf agh REJECTED shares with abg agi REJECTED shares with abg ahi REJECTED shares with abh bcd REJECTED shares with abc bce REJECTED shares with abc bcf REJECTED shares with abc bcg REJECTED shares with abc bch REJECTED shares with abc bci REJECTED shares with abc bde REJECTED shares with abd bdf REJECTED shares with abd bdg REJECTED shares with abd bdh REJECTED shares with abd bdi REJECTED shares with abd bef REJECTED shares with abe beg REJECTED shares with abe beh REJECTED shares with abe bei REJECTED shares with abe bfg REJECTED shares with abf bfh REJECTED shares with abf bfi REJECTED shares with abf bgh REJECTED shares with abg bgi REJECTED shares with abg bhi REJECTED shares with abh cde REJECTED shares with acd cdf REJECTED shares with acd cdg REJECTED shares with acd cdh REJECTED shares with acd cdi REJECTED shares with acd cef REJECTED shares with ace ceg REJECTED shares with ace ceh REJECTED shares with ace cei REJECTED shares with ace cfg REJECTED shares with acf cfh REJECTED shares with acf cfi REJECTED shares with acf cgh REJECTED shares with acg cgi REJECTED shares with acg chi REJECTED shares with ach def REJECTED shares with ade deg REJECTED shares with ade deh REJECTED shares with ade dei REJECTED shares with ade dfg REJECTED shares with adf dfh REJECTED shares with adf dfi REJECTED shares with adf dgh REJECTED shares with adg dgi REJECTED shares with adg dhi REJECTED shares with adh efg REJECTED shares with aef efh REJECTED shares with aef efi REJECTED shares with aef egh REJECTED shares with aeg egi REJECTED shares with aeg ehi REJECTED shares with aeh fgh REJECTED shares with afg fgi REJECTED shares with afg fhi REJECTED shares with afh ghi REJECTED shares with agh >>> >In a third step append to a final list only sublists not already containing >one ot the sub_sub_lists > This is, as I describe above, not a third step because the "final list" is what you have to compare against, NOT the complete set of combinations. (that [above] is NOT optimized -- it would be simpler to have created the initial "triples" as set() objects, and only convert to strings for final output). >It is this third step I am unable to code efficiently, avoiding to hardcode >it. > You've already hard-coded too much... >>> accepted = [] >>> for trip1 in triples: abc ACCEPTED not shared with [] abd REJECTED shares with abc abe REJECTED shares with abc abf REJECTED shares with abc abg REJECTED shares with abc abh REJECTED shares with abc abi REJECTED shares with abc acd REJECTED shares with abc ace REJECTED shares with abc acf REJECTED shares with abc acg REJECTED shares with abc ach REJECTED shares with abc aci REJECTED shares with abc ade ACCEPTED not shared with ['abc'] adf REJECTED shares with ade adg REJECTED shares with ade adh REJECTED shares with ade adi REJECTED shares with ade aef REJECTED shares with ade aeg REJECTED shares with ade aeh REJECTED shares with ade aei REJECTED shares with ade afg ACCEPTED not shared with ['abc', 'ade'] afh REJECTED shares with afg afi REJECTED shares with afg agh REJECTED shares with afg agi REJECTED shares with afg ahi ACCEPTED not shared with ['abc', 'ade', 'afg'] bcd REJECTED shares with abc bce REJECTED shares with abc bcf REJECTED shares with abc bcg REJECTED shares with abc bch REJECTED shares with abc bci REJECTED shares with abc bde REJECTED shares with ade bdf ACCEPTED not shared with ['abc', 'ade', 'afg', 'ahi'] bdg REJECTED shares with bdf bdh REJECTED shares with bdf bdi REJECTED shares with bdf bef REJECTED shares with bdf beg ACCEPTED not shared with ['abc', 'ade', 'afg', 'ahi', 'bdf'] beh REJECTED shares with beg bei REJECTED shares with beg bfg REJECTED shares with afg bfh REJECTED shares with bdf bfi REJECTED shares with bdf bgh REJECTED shares with beg bgi REJECTED shares with beg bhi REJECTED shares with ahi cde REJECTED shares with ade cdf REJECTED shares with bdf cdg ACCEPTED not shared with ['abc', 'ade', 'afg', 'ahi', 'bdf', 'beg'] cdh REJECTED shares with cdg cdi REJECTED shares with cdg cef ACCEPTED not shared with ['abc', 'ade', 'afg', 'ahi', 'bdf', 'beg', 'cdg'] ceg REJECTED shares with beg ceh REJECTED shares with cef cei REJECTED shares with cef cfg REJECTED shares with afg cfh REJECTED shares with cef cfi REJECTED shares with cef cgh REJECTED shares with cdg cgi REJECTED shares with cdg chi REJECTED shares with ahi def REJECTED shares with ade deg REJECTED shares with ade deh REJECTED shares with ade dei REJECTED shares with ade dfg REJECTED shares with afg dfh REJECTED shares with bdf dfi REJECTED shares with bdf dgh REJECTED shares with cdg dgi REJECTED shares with cdg dhi REJECTED shares with ahi efg REJECTED shares with afg efh REJECTED shares with cef efi REJECTED shares with cef egh REJECTED shares with beg egi REJECTED shares with beg ehi REJECTED shares with ahi fgh REJECTED shares with afg fgi REJECTED shares with afg fhi REJECTED shares with ahi ghi REJECTED shares with ahi >>> >>> accepted ['abc', 'ade', 'afg', 'ahi', 'bdf', 'beg', 'cdg', 'cef'] >>> NOTE that only 8 triples passed... NOT 12 Changing the code to reject only if the letter pairs are adjacent produces abc ACCEPTED not shared with [] abd REJECTED shares with abc abe REJECTED shares with abc abf REJECTED shares with abc abg REJECTED shares with abc abh REJECTED shares with abc abi REJECTED shares with abc acd ACCEPTED not shared with ['abc'] ace REJECTED shares with acd acf REJECTED shares with acd acg REJECTED shares with acd ach REJECTED shares with acd aci REJECTED shares with acd ade ACCEPTED not shared with ['abc', 'acd'] adf REJECTED shares with ade adg REJECTED shares with ade adh REJECTED shares with ade adi REJECTED shares with ade aef ACCEPTED not shared with ['abc', 'acd', 'ade'] aeg REJECTED shares with aef aeh REJECTED shares with aef aei REJECTED shares with aef afg ACCEPTED not shared with ['abc', 'acd', 'ade', 'aef'] afh REJECTED shares with afg afi REJECTED shares with afg agh ACCEPTED not shared with ['abc', 'acd', 'ade', 'aef', 'afg'] agi REJECTED shares with agh ahi ACCEPTED not shared with ['abc', 'acd', 'ade', 'aef', 'afg', 'agh'] bcd REJECTED shares with abc bce REJECTED shares with abc bcf REJECTED shares with abc bcg REJECTED shares with abc bch REJECTED shares with abc bci REJECTED shares with abc bde REJECTED shares with ade bdf ACCEPTED not shared with ['abc', 'acd', 'ade', 'aef', 'afg', 'agh', 'ahi'] bdg REJECTED shares with bdf bdh REJECTED shares with bdf bdi REJECTED shares with bdf bef REJECTED shares with aef beg ACCEPTED not shared with ['abc', 'acd', 'ade', 'aef', 'afg', 'agh', 'ahi', 'bdf'] beh REJECTED shares with beg bei REJECTED shares with beg bfg REJECTED shares with afg bfh ACCEPTED not shared with ['abc', 'acd', 'ade', 'aef', 'afg', 'agh', 'ahi', 'bdf', 'beg'] bfi REJECTED shares with bfh bgh REJECTED shares with agh bgi ACCEPTED not shared with ['abc', 'acd', 'ade', 'aef', 'afg', 'agh', 'ahi', 'bdf', 'beg', 'bfh'] bhi REJECTED shares with ahi cde REJECTED shares with acd cdf REJECTED shares with acd cdg REJECTED shares with acd cdh REJECTED shares with acd cdi REJECTED shares with acd cef REJECTED shares with aef ceg REJECTED shares with beg ceh ACCEPTED not shared with ['abc', 'acd', 'ade', 'aef', 'afg', 'agh', 'ahi', 'bdf', 'beg', 'bfh', 'bgi'] cei REJECTED shares with ceh cfg REJECTED shares with afg cfh REJECTED shares with bfh cfi ACCEPTED not shared with ['abc', 'acd', 'ade', 'aef', 'afg', 'agh', 'ahi', 'bdf', 'beg', 'bfh', 'bgi', 'ceh'] cgh REJECTED shares with agh cgi REJECTED shares with bgi chi REJECTED shares with ahi def REJECTED shares with ade deg REJECTED shares with ade deh REJECTED shares with ade dei REJECTED shares with ade dfg REJECTED shares with afg dfh REJECTED shares with bdf dfi REJECTED shares with bdf dgh REJECTED shares with agh dgi REJECTED shares with bgi dhi REJECTED shares with ahi efg REJECTED shares with aef efh REJECTED shares with aef efi REJECTED shares with aef egh REJECTED shares with agh egi REJECTED shares with beg ehi REJECTED shares with ahi fgh REJECTED shares with afg fgi REJECTED shares with afg fhi REJECTED shares with ahi ghi REJECTED shares with agh >>> >>> len(accepted) 13 >>> accepted ['abc', 'acd', 'ade', 'aef', 'afg', 'agh', 'ahi', 'bdf', 'beg', 'bfh', 'bgi', 'ceh', 'cfi'] >>> Note that this passes 13 triplets, one more than the 12 you imply. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Wed Mar 9 19:52:59 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Wed, 09 Mar 2022 19:52:59 -0500 Subject: [Tutor] problem solving with lists References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch> <000801d833ed$78111200$68333600$@bluewin.ch> Message-ID: On Wed, 09 Mar 2022 19:42:09 -0500, Dennis Lee Bieber declaimed the following: > Note that this passes 13 triplets, one more than the 12 you imply. Just a follow-up note: Which triplets pass is all dependent upon which triplet you use to initialize the accepted list. If you were to initialize with "abd", the "abc" would be rejected. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From manpritsinghece at gmail.com Thu Mar 10 12:14:34 2022 From: manpritsinghece at gmail.com (Manprit Singh) Date: Thu, 10 Mar 2022 22:44:34 +0530 Subject: [Tutor] Function that returns True if a list contains odd number else return False Message-ID: Dear Sir, This may be an inappropriate question, just thinking about it and writing, so I was to make a function that can accept a list as an argument and returns True if the list contains an odd number else the function should return False . Above problem can be solved in two way : Inside a user defined function just returning 1) any(1 for ele in seq if ele%2) 2) any(ele%2 for ele in seq) where seq is the formal parameter of the function. Which one is more appropriate ? Regards Manprit Singh From alan.gauld at yahoo.co.uk Thu Mar 10 12:40:54 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 10 Mar 2022 17:40:54 +0000 Subject: [Tutor] Function that returns True if a list contains odd number else return False In-Reply-To: References: Message-ID: On 10/03/2022 17:14, Manprit Singh wrote: > Above problem can be solved in two way : > > Inside a user defined function just returning > 1) any(1 for ele in seq if ele%2) > > 2) any(ele%2 for ele in seq) Intuitively, number 2 should be slightly faster since it doesn't have an extra test/assignment but in practice you can only tell by measuring them. Either of them would be acceptable but personally I'd favour the second since it expresses the intent more directly. -- 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 From iamsatyabrata428 at gmail.com Thu Mar 10 14:31:27 2022 From: iamsatyabrata428 at gmail.com (SATYABRATA DATTA) Date: Fri, 11 Mar 2022 01:01:27 +0530 Subject: [Tutor] HOW TO DOWNGRADE NUMPY Message-ID: I am facing this issue *AttributeError: 'float' object has no attribute 'log'* y = np.sum(n*m2*m2* (np.log(np.abs(m2/self.renormScaleSq) + 1e-100) *TypeError: loop of ufunc does not support argument 0 of type float which has no callable log method* How to downgrade numpy, since all mentioned ways of doing it on stack exchange are not working. Tese errors are not there in previous versions of numpy(like on 1.15.4) From PythonList at DancesWithMice.info Fri Mar 11 05:39:25 2022 From: PythonList at DancesWithMice.info (dn) Date: Fri, 11 Mar 2022 23:39:25 +1300 Subject: [Tutor] Invitation to join AuckPUG's virtual meeting on Testing Message-ID: "The Alex to Zac of Testing" 0530~0730 UTC (1830~2030 NZDT), Wed 16Mar2022 Alex Znamensky (AuckPUG member) will introduce testing as a practice (what your training course didn't tell you about the real-world!). Zac Hatfield-Dodds will aim at more advanced users, talking about Property-Based testing and the Hypothesis library (https://hypothesis.readthedocs.io/en/latest/). Originally based at the Australian National University, he has recently moved and will come to us from San Francisco. We use a BigBlueButton-instance for web-conferencing. A recent web-browser and head-set should enable you to join us. No downloads/plug-ins etc. Further details including access instructions: https://www.meetup.com/NZPUG-Auckland/ or email me (off-list)... -- Regards, =dn From amer.saeed at tu.edu.iq Sat Mar 12 18:47:06 2022 From: amer.saeed at tu.edu.iq (Amer Saeed) Date: Sun, 13 Mar 2022 02:47:06 +0300 Subject: [Tutor] I need help Message-ID: I need help about how to represent these equations in python Task which is index start with 1 to m Tasks ti=[t1, t2, t3, t4,?,tm] Each t1 is assigned to either Iot device, sy,z, when y=o, z=n Fog cloud or s0,n then sy,z, when y=1, z=1,..f Cloud or s0,n then s1,z then sy,z, when y=2, z=1,?c Xn,i= 0 when it is first case above Xn,i=1 when it is second case above Xn,i=2 when it is third case above Xn,i= 0 depicts that the ith task is assigned to the nth IoT device (s^0,n) for local execution, and Xn,i =1 and xn;i = 2 denote that the ith task is assigned to one of fog servers and cloud servers, respectively, for the remote execution. Moreover, the f and c show the number of available From manpritsinghece at gmail.com Sun Mar 13 07:14:53 2022 From: manpritsinghece at gmail.com (Manprit Singh) Date: Sun, 13 Mar 2022 16:44:53 +0530 Subject: [Tutor] Example of good use of enumerate() Message-ID: Dear Sir, Consider an example of printing all elements of a principal diagonal of a rectangular matrix. lx = [[2, 5, 9, 0], [3, 8, 1, 5], [4, 8, 1, 2], [6, 1, 2, 4], [3, 1, 6, 7]] for i, nlist in enumerate(lx): for j, num in enumerate(nlist): if i==j: print(num) The above use of enumerate() works well. Another solution is also given below: for i in range(len(lx)): for j in range(len(lx[0])): if i == j: print(lx[i][j]) also works, but lots of indexing and other operations don't look good and effective to me . Is there any other better solution other than the first one using enumerate() ? Is this a valid and preferred use case of using enumerate() function ? Regards Manprit Singh From manpritsinghece at gmail.com Sun Mar 13 07:25:19 2022 From: manpritsinghece at gmail.com (Manprit Singh) Date: Sun, 13 Mar 2022 16:55:19 +0530 Subject: [Tutor] Example of good use of enumerate() In-Reply-To: References: Message-ID: Dear Sir, One can solve it like this also: lx = [[2, 5, 9, 0], [3, 8, 1, 5], [4, 8, 1, 2], [6, 1, 2, 4], [3, 1, 6, 7]] mlen = min(len(lx), len(lx[0])) for i in range(mlen): print(lx[i][i]) What do you suggest ? On Sun, Mar 13, 2022 at 4:44 PM Manprit Singh wrote: > Dear Sir, > > Consider an example of printing all elements of a principal diagonal of a > rectangular matrix. > lx = [[2, 5, 9, 0], > [3, 8, 1, 5], > [4, 8, 1, 2], > [6, 1, 2, 4], > [3, 1, 6, 7]] > > for i, nlist in enumerate(lx): > for j, num in enumerate(nlist): > if i==j: > print(num) > > The above use of enumerate() works well. Another solution is also given > below: > for i in range(len(lx)): > for j in range(len(lx[0])): > if i == j: > print(lx[i][j]) > also works, but lots of indexing and other operations don't look good and > effective to me . > > Is there any other better solution other than the first one using > enumerate() ? > Is this a valid and preferred use case of using enumerate() function ? > > Regards > Manprit Singh > > > From alan.gauld at yahoo.co.uk Sun Mar 13 08:14:27 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sun, 13 Mar 2022 12:14:27 +0000 Subject: [Tutor] Example of good use of enumerate() In-Reply-To: References: Message-ID: On 13/03/2022 11:25, Manprit Singh wrote: > Dear Sir, > > One can solve it like this also: > > lx = [[2, 5, 9, 0], > [3, 8, 1, 5], > [4, 8, 1, 2], > [6, 1, 2, 4], > [3, 1, 6, 7]] > > mlen = min(len(lx), len(lx[0])) > for i in range(mlen): > print(lx[i][i]) > > What do you suggest ? > Personally, I prefer this version because I think it more clearly expresses the intent. It is also much more efficient since it doesn't access every member of the matrix. And the enumerate version comes second but has the efficiency issue. The indexing version is just horrible and also potentially error prone. > On Sun, Mar 13, 2022 at 4:44 PM Manprit Singh > wrote: > >> Dear Sir, >> >> Consider an example of printing all elements of a principal diagonal of a >> rectangular matrix. >> lx = [[2, 5, 9, 0], >> [3, 8, 1, 5], >> [4, 8, 1, 2], >> [6, 1, 2, 4], >> [3, 1, 6, 7]] >> >> for i, nlist in enumerate(lx): >> for j, num in enumerate(nlist): >> if i==j: >> print(num) >> >> The above use of enumerate() works well. Another solution is also given >> below: >> for i in range(len(lx)): >> for j in range(len(lx[0])): >> if i == j: >> print(lx[i][j]) >> also works, but lots of indexing and other operations don't look good and >> effective to me . >> >> Is there any other better solution other than the first one using >> enumerate() ? >> Is this a valid and preferred use case of using enumerate() function ? >> >> Regards >> Manprit Singh >> >> >> > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- 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 From alan.gauld at yahoo.co.uk Sun Mar 13 08:19:28 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sun, 13 Mar 2022 12:19:28 +0000 Subject: [Tutor] I need help In-Reply-To: References: Message-ID: On 12/03/2022 23:47, Amer Saeed wrote: > I need help about how to represent these equations in python > > Task which is index start with 1 to m > > > Tasks ti=[t1, t2, t3, t4,?,tm] > > Each t1 is assigned to either I assume you mean ti and not t1? > > Iot device, sy,z, when y=o, z=n > > Fog cloud or s0,n then sy,z, when > y=1, z=1,..f > > Cloud or s0,n then s1,z > then sy,z, when y=2, z=1,?c But I don't understand what you mean by that. Can you provide more context? What problem domain are you dealing with? What do these mysterious variables(sy,z,n etc) represent? Where do they come from? > Xn,i= 0 when it is first case above > Xn,i=1 when it is second case above > Xn,i=2 when it is third case above > Xn,i= 0 depicts that the ith task is assigned to the nth IoT device (s^0,n) > for local execution, > > and Xn,i =1 and xn;i = 2 denote that the ith task is assigned to one of > fog servers and cloud servers, respectively, for the remote execution. > > Moreover, the f and c show the number of available number of available what? You need to give us a lot more information about the context and ideally a simple example - say with m = 4? -- 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 From __peter__ at web.de Sun Mar 13 10:47:36 2022 From: __peter__ at web.de (Peter Otten) Date: Sun, 13 Mar 2022 15:47:36 +0100 Subject: [Tutor] Example of good use of enumerate() In-Reply-To: References: Message-ID: <216e2124-dc6d-002a-0191-9ef9306a0350@web.de> On 13/03/2022 12:25, Manprit Singh wrote: > > On Sun, Mar 13, 2022 at 4:44 PM Manprit Singh > wrote: > >> Dear Sir, >> >> Consider an example of printing all elements of a principal diagonal of a >> rectangular matrix. >> lx = [[2, 5, 9, 0], >> [3, 8, 1, 5], >> [4, 8, 1, 2], >> [6, 1, 2, 4], >> [3, 1, 6, 7]] >> >> for i, nlist in enumerate(lx): >> for j, num in enumerate(nlist): >> if i==j: >> print(num) I don't like that because you are discarding almost every matrix value here. > One can solve it like this also: > mlen = min(len(lx), len(lx[0])) > for i in range(mlen): > print(lx[i][i]) I think the solution above is the best approach. > What do you suggest ? You can avoid both range() and len() with >>> def diag(m): try: for i, row in enumerate(m): yield row[i] except IndexError: pass >>> list(diag(["ab", "cd"])) ['a', 'd'] >>> list(diag(["abc", "def"])) ['a', 'e'] >>> list(diag(["ab", "cd", "ef"])) ['a', 'd'] though I'm not sure I'm seriously suggesting this ;) From PythonList at DancesWithMice.info Sun Mar 13 16:49:50 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 14 Mar 2022 09:49:50 +1300 Subject: [Tutor] Example of good use of enumerate() In-Reply-To: References: Message-ID: <21aded2e-ffdb-8097-c48c-1df6a9e3e325@DancesWithMice.info> On 14/03/2022 01.14, Alan Gauld via Tutor wrote: > On 13/03/2022 11:25, Manprit Singh wrote: >> Dear Sir, >> >> One can solve it like this also: >> >> lx = [[2, 5, 9, 0], >> [3, 8, 1, 5], >> [4, 8, 1, 2], >> [6, 1, 2, 4], >> [3, 1, 6, 7]] >> >> mlen = min(len(lx), len(lx[0])) >> for i in range(mlen): >> print(lx[i][i]) >> >> What do you suggest ? >> > Personally, I prefer this version because I think it > more clearly expresses the intent. > It is also much more efficient since it doesn't > access every member of the matrix. > > And the enumerate version comes second but has the efficiency issue. > > The indexing version is just horrible and also potentially error prone. Agree with the above. However, native Python is probably *not* the tool-for-the-job! Python's for-each loops have to be augmented by enumerate(), to revert to working like for-index loops. (a backward step IMHO) The reason Python/we don't use the latter in the first place is illustrated in @Alan's last comment/warning! You could 'improve' basic-Python by taking to the PSL. For instance: import itertools as it list( it.chain.from_iterable( lx ) )[ 0::min( len( lx ), len( lx[ 0 ] ) )+1 ] -> [2, 8, 1, 4] or even, keeping it all in itertools: list( it.islice( it.chain.from_iterable( lx ), 0, 999, min( len( lx ), len( lx[ 0 ] ) ) + 1 ) ) NB the "999" is a ghastly 'magic number'. OK, it could be replaced by the order of the matrix, but... Wouldn't these tasks be better performed by employing a numeric or matrix-processing library, ie something that has been specifically designed for the job? -- Regards, =dn From manpritsinghece at gmail.com Mon Mar 14 12:08:20 2022 From: manpritsinghece at gmail.com (Manprit Singh) Date: Mon, 14 Mar 2022 21:38:20 +0530 Subject: [Tutor] finding sum of digits in a string Message-ID: Dear Sir, Take an example of finding the sum of digits in a string : st = "ab23YH6UJ7ik83LO" To find the sum of digits in the string st, i can do it in below given manners : 1) sum(int(ele) for ele in st if ele in "123456789") 2) sum(int(ele) for ele in st if ele.isdigit()) Although the 2nd one is more compact, using isdigit() method , what bothers me is - isdigit() method. It should be used to check a substring, not a single character. Here I have to check all characters of the string one by one, why not use in operator as done in the 1st way. Any guidelines regarding this ? Regards Manprit Singh From cs at cskk.id.au Mon Mar 14 18:53:58 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Tue, 15 Mar 2022 09:53:58 +1100 Subject: [Tutor] finding sum of digits in a string In-Reply-To: References: Message-ID: On 14Mar2022 21:38, Manprit Singh wrote: >Take an example of finding the sum of digits in a string : > >st = "ab23YH6UJ7ik83LO" > >To find the sum of digits in the string st, i can do it in below given >manners : > >1) sum(int(ele) for ele in st if ele in "123456789") > >2) sum(int(ele) for ele in st if ele.isdigit()) > >Although the 2nd one is more compact, using isdigit() method , what bothers >me >is - isdigit() method. It should be used to check a substring, not a single >character. Here I have to check all characters of the string one by one, >why not use in operator as done in the 1st way. Any guidelines regarding >this ? Well, one could argue that each character _is_ a substring. What's the "should" mean here? Python does not have an individual character type, so substrings are what you get. I prefer the second version as it clearly expresses the purpose of the test. The first version relies on the literal string-of-digits being correct, and a simple typo can lead to incorrect code. And, in fact, your own code there _is_ incorrect, technically, though I suppose that adding "0" has no effect, so missing it out in the string still produces a correct result. If I saw the first code I might _either_: - miss the omission of "0" and read it as "all digits" i.e. misunderstand the code - or notice the missing "0" and spend time figuring out why you're using some special subset of the digits and if that is important, either directly here or elsewhere in the codebase Either of those outcomes is unfortunate. As usual, my advice is broadly: write the most readable code. The second clearly says "isdigit", which seems more readable to me. Cheers, Cameron Simpson From alan.gauld at yahoo.co.uk Mon Mar 14 20:41:11 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 15 Mar 2022 00:41:11 +0000 Subject: [Tutor] finding sum of digits in a string In-Reply-To: References: Message-ID: On 14/03/2022 16:08, Manprit Singh wrote: > Dear Sir, > > Take an example of finding the sum of digits in a string : > > st = "ab23YH6UJ7ik83LO" > > To find the sum of digits in the string st, i can do it in below given > manners : > > 1) sum(int(ele) for ele in st if ele in "123456789") > > 2) sum(int(ele) for ele in st if ele.isdigit()) > > Although the 2nd one is more compact, using isdigit() method , what bothers > me is - isdigit() method. It should be used to check a substring, not a single > character. A single character is a substring. And there is no dedicated method for checking single characters as a special case. > why not use in operator as done in the 1st way. Because it iterates over the list of numbers meaning, on average 5 tests for each character. Now isdigit() might do that too but I hope not! You might improve things by using a set instead of a string - the set inclusion operator should theoretically be faster than an 'in' search. But as always with performance test to see... But the most important reason, as always, is readability. isdigit() clearly expresses what you want to do. (Although you may want to consider whether you really want isdecimal() or isnumeric() instead. I suspect isdecimal() suits you best here.) -- 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 From wlfraed at ix.netcom.com Mon Mar 14 21:13:59 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 14 Mar 2022 21:13:59 -0400 Subject: [Tutor] finding sum of digits in a string References: Message-ID: On Tue, 15 Mar 2022 09:53:58 +1100, Cameron Simpson declaimed the following: >> >>1) sum(int(ele) for ele in st if ele in "123456789") >> >And, in fact, your own code there _is_ incorrect, technically, though I >suppose that adding "0" has no effect, so missing it out in the string >still produces a correct result. > I'd missed that on my first glance at the code (and I should note that I've sort of started ignoring the OP -- 99% of their posts come down to some trivial example that is highly unlikely to be seen in any actual program, and the "question" is one of aesthetics/style, which is highly subjective to the experience of the reader). However, based upon https://docs.python.org/3/library/string.html, the first version could be replaced with import string sum(int(ele) for ele in st if ele in string.digits) >>> import string >>> string.digits '0123456789' That avoids the "missing" digit ambiguity/error, along with the overhead of call ele.isdigit() for each character in the input (after all, .isdigit() probably does a loop over each character in "ele" and does the same "in string.digits" test internally) -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From cs at cskk.id.au Mon Mar 14 21:49:44 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Tue, 15 Mar 2022 12:49:44 +1100 Subject: [Tutor] finding sum of digits in a string In-Reply-To: References: Message-ID: On 15Mar2022 00:41, Alan Gauld wrote: >> why not use in operator as done in the 1st way. > >Because it iterates over the list of numbers meaning, on >average 5 tests for each character. Now isdigit() might >do that too but I hope not! It might consult a mapping. But the set of digits is very small - there's a domain where searching a short list/sequence is faster than a more "efficient" but more elaborate structure. Though I was surprised by the recent discussion about frozensets and how the CPython compiler converts: if x in (1,2,3): into a precompiled frozenset lookup, which is still apparently more efficient that searching a tuple. >You might improve things by using a set instead of a >string - the set inclusion operator should theoretically >be faster than an 'in' search. But as always with performance >test to see... Aye. For small things it can be surprising. But also, for small things the difference is often less important. >But the most important reason, as always, is readability. >isdigit() clearly expresses what you want to do. (Although >you may want to consider whether you really want isdecimal() >or isnumeric() instead. I suspect isdecimal() suits you >best here.) isdecimal() and isnumeric() recognise the various Unicode base 10 numerals and the Unicode numeric symbols (or which there are very many) respectively. By contrast, int() is far more narrow minded and isdigit() is probably the most correct thing to use. Cheers, Cameron Simpson From PythonList at DancesWithMice.info Mon Mar 14 22:28:13 2022 From: PythonList at DancesWithMice.info (dn) Date: Tue, 15 Mar 2022 15:28:13 +1300 Subject: [Tutor] finding sum of digits in a string In-Reply-To: References: Message-ID: <2ff5651e-85b0-dc8f-224e-8bee30a3aba1@DancesWithMice.info> On 15/03/2022 14.13, Dennis Lee Bieber wrote: > On Tue, 15 Mar 2022 09:53:58 +1100, Cameron Simpson > declaimed the following: > > >>> >>> 1) sum(int(ele) for ele in st if ele in "123456789") >>> > >> And, in fact, your own code there _is_ incorrect, technically, though I >> suppose that adding "0" has no effect, so missing it out in the string >> still produces a correct result. >> > I'd missed that on my first glance at the code (and I should note that > I've sort of started ignoring the OP -- 99% of their posts come down to > some trivial example that is highly unlikely to be seen in any actual > program, and the "question" is one of aesthetics/style, which is highly > subjective to the experience of the reader). Worse for his (declining) good-will: not responding when asked questions or invited to give (at least some) feedback. These questions remind me of the worst of educators asking 'tricky' questions, or potential-employers and 'clever' pre-tests - most of which seem designed to as an ego-trip (I'm better than you because THE answer is...). They reflect abilities to write 'one-liners' and similar, but don't answer the question: can I give this person a spec and expect him/her to return with a completed program? Although, might this characterisation reflect the education system used in the OP's country/institution/employer? I'm 'here', to take a break from struggling to find a realistic example to use in a tutorial. As @Dennis says, it needs to be "trivial"; but loses relevance and becomes somewhat distractive if "[not] actual". The 'real life' component adds relevance and therefore motivates learning! At the very minimum I'll need a 'story' with which to introduce the 'problem', but "Take an example of..." wouldn't meet the standard. We don't have time to have individual examples/tests for each little fact, eg prove you can use isdigit(). We need to include several 'new' constructs and/or concepts in each challenge! An essential difficulty with each of these discussions, is that we are considering the 'how' of coding, and only thereafter worrying about which option is more/most readable. The real concentration should be on the 'what' of the problem are we trying to solve. The 'readability' of the solution comes after how we document the spec and consequent sub-problems, have decided upon the approach/tactics we'll take to solve that individual problem, and only then, how we'll implement a 'readable' (and meaningful) solution (in code) to accomplish it all. Can we consider 'readability' at the code-level? Of course! Does 'readability' and thus 'understanding' of the code start at an higher level? Whither "context"? Alternate solution: The spec biases one's thinking by its use of the words: "the ... digits". Instead of that fixation, could we consider something like using translate() to replace any undesired characters with NULSTRING or zero, and then adding the digits/all that remains? -- Regards, =dn From wlfraed at ix.netcom.com Tue Mar 15 10:05:56 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Tue, 15 Mar 2022 10:05:56 -0400 Subject: [Tutor] finding sum of digits in a string References: <2ff5651e-85b0-dc8f-224e-8bee30a3aba1@DancesWithMice.info> Message-ID: On Tue, 15 Mar 2022 15:28:13 +1300, dn declaimed the following: >Alternate solution: >The spec biases one's thinking by its use of the words: "the ... >digits". Instead of that fixation, could we consider something like >using translate() to replace any undesired characters with NULSTRING or >zero, and then adding the digits/all that remains? Which leads me to the nightmare I envisioned overnight. Taking common phone number formats and stripping down to just digits... While also translating those fancy "word-based" phone numbers. Hadn't realized translate() allows one to "remove" (your NULSTRING) case... But that is in the documentation... I'd expected to convert things to spaces, split on space, then join on "" >>> phone_numbers = [ "+1 (616) 987-5555", ... "1 (800) CALL-SAM", #Sam Bernstein law offices ... "TW7-5555" ] #old 60s "TWin oaks" exchange ... >>> trans_table = "".maketrans("abcdefghijklmnopqrstuvwxyz", ... "22233344455566677778889999", ... "+()- ") >>> for pn in phone_numbers: ... print("Pure phone #: %s" % pn.lower().translate(trans_table)) ... Pure phone #: 16169875555 Pure phone #: 18002255726 Pure phone #: 8975555 >>> -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Tue Mar 15 10:16:53 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Tue, 15 Mar 2022 10:16:53 -0400 Subject: [Tutor] finding sum of digits in a string References: Message-ID: <9h713hhaub194o55le9rqlk5rmt46phcl1@4ax.com> On Tue, 15 Mar 2022 00:41:11 +0000, Alan Gauld via Tutor declaimed the following: >Because it iterates over the list of numbers meaning, on >average 5 tests for each character. Now isdigit() might >do that too but I hope not! > Naive implementations (done at the level of Python rather than C)(using the OPs "ele" term) all([(ch in string.digits) for ch in ele]) all([("0" <= ch <= "9") for ch in ele]) I'd hope C is using something like a while loop to break out on the first False compare rather than scanning all characters in ele. Okay for .isdigits(), but the various upper/lower/alpha/printable etc may be better implemented with a table look-up (ignoring unicode matters), maybe with a bit-map indicating each category the character fills. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From PythonList at DancesWithMice.info Tue Mar 15 15:56:33 2022 From: PythonList at DancesWithMice.info (dn) Date: Wed, 16 Mar 2022 08:56:33 +1300 Subject: [Tutor] finding sum of digits in a string In-Reply-To: References: <2ff5651e-85b0-dc8f-224e-8bee30a3aba1@DancesWithMice.info> Message-ID: <88962278-ce45-4f05-90fa-5da70689ee76@DancesWithMice.info> On 16/03/2022 03.05, Dennis Lee Bieber wrote: > On Tue, 15 Mar 2022 15:28:13 +1300, dn > declaimed the following: > >> Alternate solution: >> The spec biases one's thinking by its use of the words: "the ... >> digits". Instead of that fixation, could we consider something like >> using translate() to replace any undesired characters with NULSTRING or >> zero, and then adding the digits/all that remains? > > Which leads me to the nightmare I envisioned overnight. Taking common > phone number formats and stripping down to just digits... While also > translating those fancy "word-based" phone numbers. > > Hadn't realized translate() allows one to "remove" (your NULSTRING) > case... But that is in the documentation... I'd expected to convert things > to spaces, split on space, then join on "" > > >>>> phone_numbers = [ "+1 (616) 987-5555", > ... "1 (800) CALL-SAM", #Sam Bernstein law offices > ... "TW7-5555" ] #old 60s "TWin oaks" exchange Only too pleased to be able to return the inspirations you have provided over the years! This is a great example - for us older folk, eg a vocational context. Young-people question the use of land-lines, have no knowledge of rotary-dial phones, and certainly post-date the old system of alpha exchange-codes. There is?was a very interesting annual 'list' constructed by an academic in the US (that I can't lay my hands on, at this moment), which highlights the differences in what 'we' know, and the 'world-view' of the uni-freshman, eg whether they've ever known a time before cell-phones, microwave ovens, etc. It's a very useful reminder that we (presenters) need to adjust our view of 'culture' and 'what is real'. Thus "relevance"! I've been playing with a 'story' based on a friend with a Japanese heritage, attempting to help his parents find a new place. He found somewhere. His sister even 'approved'. However, when he finally took his parents to view, with a sense of "Ta Da!", before they even stepped out of the car, he was presented with flat refusal. It turns-out that more traditional/superstitious folk avoid the number "4" (also in Chinese culture), which happened to be the number prominently displayed on the mail-box. Their old (but not as old as me) Mother, saw the portents! Accordingly, a similar translation/editing/renumbering challenge: some Japanese buildings proceed from level 3 to level 5, and from level 39 directly to 50. Complicated by source data arriving from various sources, eg realtors, spreadsheets, web-scraping, etc, and thus some being strings and some integers. It's a work-in-progress... The learning-objective is "using the debugger". So, will have syntax errors in the data, in the code, a calculation error, mistaken choice of identifier being used, data not being input (probably returned) to/from a function (which gives us the StepNext and StepInto variation), and anything else I can think-of/throw-into the 'kitchen sink'... Thanks! -- Regards, =dn From perseus1702 at gmail.com Wed Mar 16 20:00:32 2022 From: perseus1702 at gmail.com (Devanshu Nalavade) Date: Thu, 17 Mar 2022 05:30:32 +0530 Subject: [Tutor] Anonymous function Message-ID: Respected Tutor, I have written a code that finds the sum of numbers passed as arguments in a user-defined function. This function has an anonymous function that takes the same arguments and does the summation. However for some reason the code is not giving me the desired output, there are no syntax errors so I'm not understanding what I'm doing wrong. Your help is much appreciated, the program I wrote is as follows: >>>def sum(arg1,arg2,arg3=10): ... m = lambda arg1,arg2,arg3:arg1+arg2+arg3 >>>print(sum(5,6)) The output comes out as 'None' Thanks and Regards, Devanshu Nalavade From alan.gauld at yahoo.co.uk Wed Mar 16 20:57:53 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 17 Mar 2022 00:57:53 +0000 Subject: [Tutor] Anonymous function In-Reply-To: References: Message-ID: On 17/03/2022 00:00, Devanshu Nalavade wrote: > a user-defined function. This function has an anonymous function that takes > the same arguments and does the summation. However for some reason the code > is not giving me the desired output, there are no syntax errors so I'm not > understanding what I'm doing wrong. There are so many issues here it is hard to know where to start, so my apologies if I over simplify things. Caveat: My code below is untested so may not be 100% correct... >>>> def sum(arg1,arg2,arg3=10): > ... m = lambda arg1,arg2,arg3:arg1+arg2+arg3 That creates a function object(aka a lambda) and assigns it the name m It is identical to: def sum(arg1,arg2,arg3=10): def m(arg1,arg2,arg3): return arg1+arg2+arg3 But sum() does nothing except define the function - which is then just thrown away when sum() finishes. And because sum has no return value Python returns None - the default for functions. But of course calling the function sum means you have hidden the built-in function sum(), which does a similar thing but for an unlimited number of args and without the default value of 10 for arg3. Hiding the built in functions is not usually a good idea. Perhaps calling it sum3() or some-such would be better. Also you use the names arg1,arg2,arg3 as the definition of the parameters to lambda. But that creates 3 new names inside the function, it does not pass the parameters of sum() into the lambda as I suspect you think it does! It potentially then becomes very confusing so I suggest using different names in the lambda, say a1,a2,a3? >>>> print(sum(5,6)) > > The output comes out as 'None' Yes because your function does not return anything, not even the lambda. To get this to work you'd need to modify it like so: def sum3(arg1,arg2,arg3=10): m = lambda a1,a2,a3:a1+a2+a3 return m(arg1,arg2,arg3) print( sum3(5,6) ) # prints 21 That now defines the lambda and then calls it. but since the lambda is not stored anywhere you might as well just execute the code directly: def sum3(arg1,arg2,arg3=10): return arg1+arg2+arg3 Or even def sum3(arg1,arg32,arg3=10): return sum(arg1,arg2,arg3) Normally we use lambdas when we want the return value to be a function that the caller will use later. Or where we want a function passed in and the caller provides a lambda. We don't usually use them to define a function that we immediately call then throw away. For example here is a function that returns a function that sums but with a user defined default value: def sum3N(N): return lambda a1,a2,a3=N: sum(a1,a2,a3) sum10 = sum3N(10) sum10(4,5) # returns 4+5+10 = 19 sum666 = sum3N(666) sum666(10,20) # returns 696 sum666(1,2,3) # returns 6 HTH -- 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 From marcus.luetolf at bluewin.ch Thu Mar 17 10:36:57 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Thu, 17 Mar 2022 15:36:57 +0100 Subject: [Tutor] problem solving with lists In-Reply-To: References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch> Message-ID: <001301d83a0c$746c1ad0$5d445070$@bluewin.ch> Hello Experts again, I was a couple days away from my computer and had ample time to rethink my problem computationally, since my previous approach below is bound to a dead end: As a remark in between: ? all_letters = 'abcdefghi' instead of all_letters = list('abcdefghi') threw an error. ? The problem with 6 instead of 9 letters cannot be solved for mathematical reasons (below). Problem description: Distribute letters (or items) of a list of n letter (or items) to sublists containig r letters (or items) in a manner that pairs of letters, p.e. 'a', 'b' or 'd', 'f' can occur only once. As a border or constraint r can only be 3 or 4 and a solution requires (n - 1) % ( r - 1) == 0. Algorithm for n = 9, r = 3: 1. Step: Create sublists of all possible combinations of letters [['a','a','a'], ['a', 'a', 'b'].......['i', 'i', 'i']], a total of 9^3 = 729 sublists. 2. Step: Remove all sublists containing the same letter more than once. 3. Step: Sort all remaining sublists. 4. Step: Remove all duplicates. These four steps can accomplished by itertools funcion combinations: >from itertools import combinations >iterable = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] >r = 3 >all_tuples = list(combinations(iterable, 3)) >all_sub_lists = [] >for i in all_tuples: >all_sub_lists.append(list(i)) >print(all_sub_lists, len(all_sub_lists)) yielding 84 sublists. Using not paper and pencil but Excel I got the same number. 5. and most crucial step: Remove all sublists containing duplicates of pairs of letters: P.e. if pairs of sublist[0]and sublist[1], or sublist[0] and sublist[2] or sublist[1] and sublist[2] were already seen, remove that sublist. There should result 12 sublists. It's that last step I struggle with and which would allow to apply the algorithm for n = 16 and r = 4, my final problem or further. I possibly could do it by hand but not for n = 16, r = 4 (1820 sublists !) Appreciate any help, Marcus. -----Urspr?ngliche Nachricht----- Von: Tutor Im Auftrag von Alan Gauld via Tutor Gesendet: Montag, 7. M?rz 2022 12:24 An: tutor at python.org Betreff: Re: [Tutor] problem solving with lists On 07/03/2022 07:44, marcus.luetolf at bluewin.ch wrote: > I should have written ... c) if my problem can by solved with python > or any other programming language at all. Python, or any other "Turing complete" programming language can represent any algorithm you come up with. So the answer is yes, once you have the algorithm. > It's the process of finding an algorithm to solve my task I am stuck > with And that is often the hardest bit. > I'am very gratefull for your advice to reduce the task to 9 > items/letters in sublists of 3 (soem sort of recursion ?) but it > doesn't get me any further. Can you solve it by hand? - ie. using a pencil and paper. If not then you don't really understand your problem yet. So you need to write down all the different conditions that must be met, including all the exceptional cases that might arise. Once you understand what needs to be done you should be able to work out how to do it using pencil and paper. That will give you an algorithm. It may not be the most efficient, and it will likely not be generalized to "N sublists from M" elements yet. But it is a start. But unless you understand the solution at that level you are unlikely to be able to write a program to solve it. (Unless it's a swell known algorithm and you can find a library. But it looks as if your requirements are slightly different from the more common cases) We can certainly help you formulate the required algorithm, and possibly some shortcuts. But you need to give us a complete and precise description of the problem. -- 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 at python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor From wlfraed at ix.netcom.com Thu Mar 17 12:38:04 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Thu, 17 Mar 2022 12:38:04 -0400 Subject: [Tutor] problem solving with lists References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch> <001301d83a0c$746c1ad0$5d445070$@bluewin.ch> Message-ID: On Thu, 17 Mar 2022 15:36:57 +0100, declaimed the following: My comments are directly in order of your presented text, so may be superseded by later text from you... > >As a remark in between: >? all_letters = 'abcdefghi' instead of all_letters = list('abcdefghi') threw >an error. What error? Don't paraphrase -- cut&paste the exact traceback along with the relevant code. >? The problem with 6 instead of 9 letters cannot be solved for mathematical >reasons (below). > What is the source for these "mathematical reasons"... That is, some text (wikipedia, other source) besides your less than clear description. >Problem description: >Distribute letters (or items) of a list of n letter (or items) to sublists >containig r letters (or items) >in a manner that pairs of letters, p.e. 'a', 'b' or 'd', 'f' can occur only >once. This is still an unclear statement. Provide actual examples showing sets of letters which violate the constraint, and those that do not. ABC ABD <- AB are adjacent and in the same column ACD <- AC appears in ABC, is this in violation BCE <- BC is adjacent, but in different column >As a border or constraint r can only be 3 or 4 and a solution requires (n - >1) % ( r - 1) == 0. > And this is the constraint that most intrigues me? Where does it come from, what really is its purpose? After all -- you've opened the question with predefined values of n and r, so this constraint has no effect. It is only of meaning if one is starting from scratch and needs to find values for n and r in the first place. However, n=16, r=4 gives 15 % 3, so passes. >Algorithm for n = 9, r = 3: >1. Step: Create sublists of all possible combinations of letters >[['a','a','a'], ['a', 'a', 'b'].......['i', 'i', 'i']], a total of 9^3 = 729 >sublists. Terminology! "combinations" has a specific mathematical meaning. As does "permutations". And variant "combinations with replacement" (after selecting an element from the source pool, you put it back in so it can be selected again). Permutations don't require ordered selection ("ABC" and "ACB" are different). Combinations are ordered ("ABC" and "ACB" -> "ABC" are the same value). You only get duplicate letters if 1) the source pool of letters has duplicates or 2) you are using "combinations with replacement" 9^3 implies "combinations with replacement"... BUT if... >2. Step: Remove all sublists containing the same letter more than once. ... you are then going to remove any element with duplicate letters WHY DID YOU GENERATE IT! >>> math.perm(9, 3) 504 >>> math.comb(9, 3) 84 >>> There are 504 permutations (no duplicate letters, but the letter order differs) and only 84 combinations (order is "sorted"). That's a lot of elements you are throwing away after generation -- going from 729 -> 84! >3. Step: Sort all remaining sublists. A good combinatorial generator creates sorted items. >4. Step: Remove all duplicates. > >These four steps can accomplished by itertools funcion combinations: Okay -- now we get down to updated logic... > >>from itertools import combinations > >>iterable = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] You are still focused on using LISTS rather than STRINGS. A string IS an iterable. >>> import itertools >>> pool = "abcdefghi" >>> list(itertools.combinations(pool, 3)) Granted... .combinations() has the bad habit (in my mind) of returning the combinations as tuples rather than rebuilding strings when the pool was a string. [('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'b', 'e'), ('a', 'b', 'f'), ('a', 'b', 'g'), ('a', 'b', 'h'), ('a', 'b', 'i'), ('a', 'c', 'd'), ('a', 'c', 'e'), ('a', 'c', 'f'), ('a', 'c', 'g'), ('a', 'c', 'h'), ('a', 'c', 'i'), ('a', 'd', 'e'), ('a', 'd', 'f'), ('a', 'd', 'g'), ('a', 'd', 'h'), ('a', 'd', 'i'), ('a', 'e', 'f'), ('a', 'e', 'g'), ('a', 'e', 'h'), ('a', 'e', 'i'), ('a', 'f', 'g'), ('a', 'f', 'h'), ('a', 'f', 'i'), ('a', 'g', 'h'), ('a', 'g', 'i'), ('a', 'h', 'i'), ('b', 'c', 'd'), ('b', 'c', 'e'), ('b', 'c', 'f'), ('b', 'c', 'g'), ('b', 'c', 'h'), ('b', 'c', 'i'), ('b', 'd', 'e'), ('b', 'd', 'f'), ('b', 'd', 'g'), ('b', 'd', 'h'), ('b', 'd', 'i'), ('b', 'e', 'f'), ('b', 'e', 'g'), ('b', 'e', 'h'), ('b', 'e', 'i'), ('b', 'f', 'g'), ('b', 'f', 'h'), ('b', 'f', 'i'), ('b', 'g', 'h'), ('b', 'g', 'i'), ('b', 'h', 'i'), ('c', 'd', 'e'), ('c', 'd', 'f'), ('c', 'd', 'g'), ('c', 'd', 'h'), ('c', 'd', 'i'), ('c', 'e', 'f'), ('c', 'e', 'g'), ('c', 'e', 'h'), ('c', 'e', 'i'), ('c', 'f', 'g'), ('c', 'f', 'h'), ('c', 'f', 'i'), ('c', 'g', 'h'), ('c', 'g', 'i'), ('c', 'h', 'i'), ('d', 'e', 'f'), ('d', 'e', 'g'), ('d', 'e', 'h'), ('d', 'e', 'i'), ('d', 'f', 'g'), ('d', 'f', 'h'), ('d', 'f', 'i'), ('d', 'g', 'h'), ('d', 'g', 'i'), ('d', 'h', 'i'), ('e', 'f', 'g'), ('e', 'f', 'h'), ('e', 'f', 'i'), ('e', 'g', 'h'), ('e', 'g', 'i'), ('e', 'h', 'i'), ('f', 'g', 'h'), ('f', 'g', 'i'), ('f', 'h', 'i'), ('g', 'h', 'i')] >>> Doesn't this look a lot easier to read? >>> ["".join(tpl) for tpl in itertools.combinations(pool, 3)] ['abc', 'abd', 'abe', 'abf', 'abg', 'abh', 'abi', 'acd', 'ace', 'acf', 'acg', 'ach', 'aci', 'ade', 'adf', 'adg', 'adh', 'adi', 'aef', 'aeg', 'aeh', 'aei', 'afg', 'afh', 'afi', 'agh', 'agi', 'ahi', 'bcd', 'bce', 'bcf', 'bcg', 'bch', 'bci', 'bde', 'bdf', 'bdg', 'bdh', 'bdi', 'bef', 'beg', 'beh', 'bei', 'bfg', 'bfh', 'bfi', 'bgh', 'bgi', 'bhi', 'cde', 'cdf', 'cdg', 'cdh', 'cdi', 'cef', 'ceg', 'ceh', 'cei', 'cfg', 'cfh', 'cfi', 'cgh', 'cgi', 'chi', 'def', 'deg', 'deh', 'dei', 'dfg', 'dfh', 'dfi', 'dgh', 'dgi', 'dhi', 'efg', 'efh', 'efi', 'egh', 'egi', 'ehi', 'fgh', 'fgi', 'fhi', 'ghi'] >>> >>r = 3 >>all_tuples = list(combinations(iterable, 3)) > >>all_sub_lists = [] >>for i in all_tuples: > >all_sub_lists.append(list(i)) > What purpose? All you are doing is converting each tuple element into a list element. Lots of noise signifying nothing -- you can index a tuple just as easily as a list or string... Look above to the one-liner that produced strings -- no intermediate list of tuples needed, the generator returns one tuple at a time, which is converted to a string element, then repeats until the generator is out of values. >>> ("a", "b", "c")[1] 'b' >>> ["a", "b", "c"][1] 'b' >>> "abc"[1] 'b' >>> >>print(all_sub_lists, len(all_sub_lists)) > >5. and most crucial step: Remove all sublists containing duplicates of pairs >of letters: >P.e. if pairs of sublist[0]and sublist[1], or sublist[0] and sublist[2] or >sublist[1] and sublist[2] were And here is one source of confusion to the reader... Your use of "lists", "sublists", et al makes it very difficult to follow just what you mean here. SHOW us the actual "sublist" in question. My initial interpretation is that "sublist[0]" is "ABC", sublist[1] is "ABD" and sublist[2] is "ABE". If you mean the /letters/ in the tuples (again, string, list, tuple are all indexable, so avoiding nested lists of lists would help). Taking the second interpretation, where you are accessing the LETTERS in an element, then I have to interpret it to mean that "matching pairs" DO NOT have to be ADJACENT; that is, ACD conflicts with ABC. If so, the easiest way to test is to create a SET from each element, perform set INTERSECTION, and reject an element if the intersection has 2 or more members (ie; letters in common). All my working code has been written on the assumption that letter pairs must be adjacent (especially the ooREXX implementation, done as an exercise). >already seen, remove that sublist. There should result 12 sublists. > Where did this "12" come from? Note that, for 9/3 and using ADJACENT letters, I do get 12 passing elements. **** THIS IS ERRONEOUS, first element was hard-coded to 4 letters! C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 9 3 Accepted items: 12 abcd ace ade aef afg agh ahi bdf beg bfh bgi cfi C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX> 16/4 produces 23 passing elements C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 16 4 Accepted items: 23 abcd acef adeg aehi afgh agij ahjk aikl ajlm akmn alno amop bdfh beil bfim bgjm bhkn binp cfjn cgko chlo dglp dhmp C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX> If I revert to a version that uses set intersection, 9/3 only produces 8 passing elements, and 16/4 produces 15 passing elements. >It's that last step I struggle with and which would allow to apply the >algorithm for n = 16 and r = 4, For ADJACENT pairs, it works a lot easier with STRINGS. You only need to loop over the "new" element taking substrings of 2 characters, and testing if that substring is IN any of the previously accepted elements (especially since substrings just require [strt:end] indexing in Python) I'm not going to present working Python -- so the working ooREXX filter procedure will be shown . Hints: accepted. is a "stem" variable, the stuff following the . serves as an index or key (it can be anything). There is no way to get a length from a stem variable, so I store the number of items as accepted.0 (REXX tends to index from 1..., not 0... as Python). substr(item, j, 2) is equivalent to item[j:j+2], pos() returns where the match is (0 meaning no matches), Python "in" just says "it is there/it is not there" filter: procedure use arg item, accepted. rc = 1 /* assume item will be accepted */ /* for each accepted item */ do i = 1 to accepted.0 aitem = accepted.i do j = 1 to length(item) - 1 pair = substr(item, j, 2) if pos(pair, aitem) > 0 then do /* reject this item, and leave do i loop! */ rc = 0 leave i end end j end i return rc >my final problem or further. I possibly could do it by hand but not for n = >16, r = 4 (1820 sublists !) And as you can see by my earlier ooREXX output, the algorithm is not specific to n/r. C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 26 5 Accepted items: 36 abcd acefg adegh aehij afhjk agikl ahkmn ailmo ajlno aknpq alopr ampst anqrs aoqsu aptuv aqtvw artwx asvxy auwyz bdfim beinr bfjmq bgjns bhlpu bioru bjosw bkotx blqux bmrvy cfkpv cgkqv chmsx cipwz cjpxz dglrw dhnty C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX> Hmmm, I do seem to have a minor bug... the first entry should have been abcde C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 26 5 Accepted items: 37 abcde acefg adfhi aeghj afijk agikl ahkmn ailmo ajlno aknpq alopr ampst anqrs aoqsu aptuv aqtvw artwx asvxy auwyz bdgjm behlp bfjnr bgkor bhmqu bimru bjosw bkpux blqvy bmsxz cfkqw cglrv chnsy cintx cjpvz ckrwz dhoty diouy C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX> That's better... Had a 4 hard-coded rather than using sublen. Which also invalidated the 9/3 case above. Corrected 9/3 is C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 9 3 Accepted items: 13 abc acd ade aef afg agh ahi bdf beg bfh bgi ceh cfi C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX> WHERE 13 ELEMENTS PASS, NOT YOUR DECREED 12! -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Thu Mar 17 13:57:42 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Thu, 17 Mar 2022 13:57:42 -0400 Subject: [Tutor] problem solving with lists References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch> <001301d83a0c$746c1ad0$5d445070$@bluewin.ch> Message-ID: On Thu, 17 Mar 2022 12:38:04 -0400, Dennis Lee Bieber declaimed the following: Just additional musing... >On Thu, 17 Mar 2022 15:36:57 +0100, declaimed >the following: > >>? The problem with 6 instead of 9 letters cannot be solved for mathematical >>reasons (below). >> > > What is the source for these "mathematical reasons"... That is, some >text (wikipedia, other source) besides your less than clear description. > After all, there ARE solutions for any scheme where rletters.rex 6 2 Accepted items: 15 ab ac ad ae af bc bd be bf cd ce cf de df ef C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 6 3 Accepted items: 5 abc acd ade aef bdf C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 6 4 Accepted items: 2 abcd acef C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 6 5 Accepted items: 1 abcde C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX> C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 5 2 Accepted items: 10 ab ac ad ae bc bd be cd ce de C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 5 3 Accepted items: 3 abc acd ade C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 5 4 Accepted items: 1 abcd C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX> C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 5 5 Accepted items: 1 abcde C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 6 6 Accepted items: 1 abcdef C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 9 9 Accepted items: 1 abcdefghi C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX> C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 2 1 Accepted items: 2 a b C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX> >>> for n in range(1, 9+1): ... for r in range(2, n+1): ... print("%s %s: %s" % (n, r, ((n-1) % (r-1)) == 0)) ... 2 2: True 3 2: True 3 3: True 4 2: True 4 3: False 4 4: True 5 2: True 5 3: True 5 4: False 5 5: True 6 2: True 6 3: False 6 4: False 6 5: False 6 6: True 7 2: True 7 3: True 7 4: True 7 5: False 7 6: False 7 7: True 8 2: True 8 3: False 8 4: False 8 5: False 8 6: False 8 7: False 8 8: True 9 2: True 9 3: True 9 4: False 9 5: True 9 6: False 9 7: False 9 8: False 9 9: True >>> C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 9 6 Accepted items: 2 abcdef aceghi C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.rex 9 5 Accepted items: 3 abcde acefg adfhi C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX> 9/5 passes the modulo constraint, 9/6 does not -- but what does that constraint provide to the problem solution as both 9/5 and 9/6 generate passing elements. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From perseus1702 at gmail.com Thu Mar 17 12:21:43 2022 From: perseus1702 at gmail.com (Devanshu Nalavade) Date: Thu, 17 Mar 2022 21:51:43 +0530 Subject: [Tutor] Anonymous function Message-ID: Respected Tutor, I am very thankful that you took the time to clear my doubts and explain this concept to me in a manner I can understand. -- Thanks and Regards, Devanshu Nalavade From marcus.luetolf at bluewin.ch Fri Mar 18 09:07:00 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Fri, 18 Mar 2022 14:07:00 +0100 Subject: [Tutor] problem solving with lists In-Reply-To: References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch> Message-ID: <000f01d83ac9$0e1cde00$2a569a00$@bluewin.ch> Hello Experts, I found a partial solution to the 5. Step below as an example code with a limited number of sub- or nested lists using a while loop. A for loop did not work: >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] >n = len(lst) >p = 0 >new_lst = [] >while n > 0: > pair1 = lst[p][0:2] > pair2 = list(lst[p][0]+ lst[p][2]) > pair3 = lst[p][1:] > print('pair1:', pair1, 'pair2: ', pair2, 'pair3: ', pair3) > if pair1 or pair2 or pair3 not in new_lst: > new_lst.append(lst[p]) > print(new_lst) > p += 1 > n -= 1 However, instead of getting new_lst containing only lst[0] and lst[1], sub_lst appends all 4 sub- or nested lists. ['a', 'b', 'g'] and ['b', 'c', 'h'] should not be in new_lst since 'a', 'b' and 'b', 'c' are already in the first 2 sublists. Whre is my mistake ?? ............................................................................ ............................................................................ ............... Hello Experts again, I was a couple days away from my computer and had ample time to rethink my problem computationally, since my previous approach below is bound to a dead end: As a remark in between: ? all_letters = 'abcdefghi' instead of all_letters = list('abcdefghi') threw an error. ? The problem with 6 instead of 9 letters cannot be solved for mathematical reasons (below). Problem description: Distribute letters (or items) of a list of n letter (or items) to sublists containig r letters (or items) in a manner that pairs of letters, p.e. 'a', 'b' or 'd', 'f' can occur only once. As a border or constraint r can only be 3 or 4 and a solution requires (n - 1) % ( r - 1) == 0. Algorithm for n = 9, r = 3: 1. Step: Create sublists of all possible combinations of letters [['a','a','a'], ['a', 'a', 'b'].......['i', 'i', 'i']], a total of 9^3 = 729 sublists. 2. Step: Remove all sublists containing the same letter more than once. 3. Step: Sort all remaining sublists. 4. Step: Remove all duplicates. These four steps can accomplished by itertools funcion combinations: >from itertools import combinations >iterable = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] >r = 3 >all_tuples = list(combinations(iterable, 3)) >all_sub_lists = [] >for i in all_tuples: >all_sub_lists.append(list(i)) >print(all_sub_lists, len(all_sub_lists)) yielding 84 sublists. Using not paper and pencil but Excel I got the same number. 5. and most crucial step: Remove all sublists containing duplicates of pairs of letters: P.e. if pairs of sublist[0]and sublist[1], or sublist[0] and sublist[2] or sublist[1] and sublist[2] were already seen, remove that sublist. There should result 12 sublists. It's that last step I struggle with and which would allow to apply the algorithm for n = 16 and r = 4, my final problem or further. I possibly could do it by hand but not for n = 16, r = 4 (1820 sublists !) Appreciate any help, Marcus. -----Urspr?ngliche Nachricht----- Von: Tutor Im Auftrag von Alan Gauld via Tutor Gesendet: Montag, 7. M?rz 2022 12:24 An: tutor at python.org Betreff: Re: [Tutor] problem solving with lists On 07/03/2022 07:44, marcus.luetolf at bluewin.ch wrote: > I should have written ... c) if my problem can by solved with python > or any other programming language at all. Python, or any other "Turing complete" programming language can represent any algorithm you come up with. So the answer is yes, once you have the algorithm. > It's the process of finding an algorithm to solve my task I am stuck > with And that is often the hardest bit. > I'am very gratefull for your advice to reduce the task to 9 > items/letters in sublists of 3 (soem sort of recursion ?) but it > doesn't get me any further. Can you solve it by hand? - ie. using a pencil and paper. If not then you don't really understand your problem yet. So you need to write down all the different conditions that must be met, including all the exceptional cases that might arise. Once you understand what needs to be done you should be able to work out how to do it using pencil and paper. That will give you an algorithm. It may not be the most efficient, and it will likely not be generalized to "N sublists from M" elements yet. But it is a start. But unless you understand the solution at that level you are unlikely to be able to write a program to solve it. (Unless it's a swell known algorithm and you can find a library. But it looks as if your requirements are slightly different from the more common cases) We can certainly help you formulate the required algorithm, and possibly some shortcuts. But you need to give us a complete and precise description of the problem. -- 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 at python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor From alan.gauld at yahoo.co.uk Fri Mar 18 09:59:58 2022 From: alan.gauld at yahoo.co.uk (alan.gauld at yahoo.co.uk) Date: Fri, 18 Mar 2022 13:59:58 +0000 Subject: [Tutor] problem solving with lists In-Reply-To: <000f01d83ac9$0e1cde00$2a569a00$@bluewin.ch> References: <70f917e6-3573-4042-a62e-a7f770cfa665.ref@email.android.com> Message-ID: <70f917e6-3573-4042-a62e-a7f770cfa665@email.android.com> On 18 Mar 2022 13:07, marcus.luetolf at bluewin.ch wrote: >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] >n = len(lst) >p = 0 >new_lst = [] >while n > 0: >??? pair1 = lst[p][0:2] >??? pair2 = list(lst[p][0]+ lst[p][2]) >??? pair3 = lst[p][1:] >??? print('pair1:', pair1, 'pair2: ', pair2, 'pair3: ', pair3) >??? if pair1 or pair2 or pair3 not in new_lst I suspect that's not doing what you think. Python sees it as If pair 1 not empty Or pair2 not empty Or pair3 not in newlist I don't think that's what you want.? BTW why does? For p in lst not work?? It seems to be what you are effectively doing...? Alan G? From my phone, apologies for any typing errors...? From marcus.luetolf at bluewin.ch Fri Mar 18 11:12:19 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Fri, 18 Mar 2022 16:12:19 +0100 Subject: [Tutor] problem solving with lists In-Reply-To: <70f917e6-3573-4042-a62e-a7f770cfa665@email.android.com> References: <70f917e6-3573-4042-a62e-a7f770cfa665.ref@email.android.com> <70f917e6-3573-4042-a62e-a7f770cfa665@email.android.com> Message-ID: <000f01d83ada$8fd4a930$af7dfb90$@bluewin.ch> ?many thanks for your quick replay. When I used a for loop : >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] >sub_lst = [] >for p in lst: > pair1 = lst[p][0:2] > pair2 = list(lst[p][0]+ lst[p][2]) > pair3 = lst[p][1:] > print('pair1:', pair1, 'pair2: ', pair2, 'pair3: ', pair3) > if pair1 or pair2 or pair3 not in sub_lst: > sub_lst.append(lst[p]) > print(sub_lst) I got a traceback: ??.. line 5, in pair1 = lst[p][0:2] TypeError: list indices must be integers or slices, not list And yes, the code above did not do what I exspected. But I don?t understand what you mean with If pair 1 not empty Or pair2 not empty Or pair3 not in newlist What is the difference between pair not beeing empty or not beeing in new_list ? How should I define the if condition properly ? Marcus. Von: alan.gauld at yahoo.co.uk Gesendet: Freitag, 18. M?rz 2022 15:00 An: marcus.luetolf at bluewin.ch Cc: tutor at python.org Betreff: Re: AW: [Tutor] problem solving with lists On 18 Mar 2022 13:07, marcus.luetolf at bluewin.ch wrote: >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] >n = len(lst) >p = 0 >new_lst = [] >while n > 0: > pair1 = lst[p][0:2] > pair2 = list(lst[p][0]+ lst[p][2]) > pair3 = lst[p][1:] > print('pair1:', pair1, 'pair2: ', pair2, 'pair3: ', pair3) > if pair1 or pair2 or pair3 not in new_lst I suspect that's not doing what you think. Python sees it as If pair 1 not empty Or pair2 not empty Or pair3 not in newlist I don't think that's what you want. BTW why does For p in lst not work? It seems to be what you are effectively doing... Alan G >From my phone, apologies for any typing errors... From wlfraed at ix.netcom.com Fri Mar 18 11:34:27 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Fri, 18 Mar 2022 11:34:27 -0400 Subject: [Tutor] problem solving with lists References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch> <000f01d83ac9$0e1cde00$2a569a00$@bluewin.ch> Message-ID: <7p893h9rvomtk1pk8gjsris9elmmkg17ip@4ax.com> On Fri, 18 Mar 2022 14:07:00 +0100, declaimed the following: > >>lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] > >>n = len(lst) >>p = 0 >>new_lst = [] >>while n > 0: >> pair1 = lst[p][0:2] >> pair2 = list(lst[p][0]+ lst[p][2]) >> pair3 = lst[p][1:] ONE: this is not scaleable... You are hard-coded to working with elements of exactly length three... TWO: your definition of pair2 seems to imply that pairs are NOT adjacent... Your examples over the course of this thread have never provided an answer to that question -- even after having been asked multiple times. If pairs are not required to be adjacent letters, then testing with "in" will not suffice. Set intersection is the best solution for disjoint pairs. >> print('pair1:', pair1, 'pair2: ', pair2, 'pair3: ', pair3) >> if pair1 or pair2 or pair3 not in new_lst: This does not do anything like you think it does. It is parsed as if (pair1) OR (pair2) OR (pair3 not in new_lst) and since a non-empty list is "true", "pair1" by itself determines the condition and pair2/pair3 aren't even looked at... https://docs.python.org/3/reference/expressions.html#membership-test-operations https://docs.python.org/3/reference/expressions.html#boolean-operations -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Fri Mar 18 11:36:39 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Fri, 18 Mar 2022 11:36:39 -0400 Subject: [Tutor] problem solving with lists References: <70f917e6-3573-4042-a62e-a7f770cfa665.ref@email.android.com> <70f917e6-3573-4042-a62e-a7f770cfa665@email.android.com> <000f01d83ada$8fd4a930$af7dfb90$@bluewin.ch> Message-ID: <6m993htlbo7e1tuitb9p8a5futu6fk2qk4@4ax.com> On Fri, 18 Mar 2022 16:12:19 +0100, declaimed the following: >?many thanks for your quick replay. > >When I used a for loop : > > > >>lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] > >>sub_lst = [] > >>for p in lst: > >> pair1 = lst[p][0:2] "p" IS the "sublist", not an index. pair1 = p[0:2] -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From marcus.luetolf at bluewin.ch Fri Mar 18 13:21:19 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Fri, 18 Mar 2022 18:21:19 +0100 Subject: [Tutor] problem solving with lists In-Reply-To: <70f917e6-3573-4042-a62e-a7f770cfa665@email.android.com> References: <70f917e6-3573-4042-a62e-a7f770cfa665.ref@email.android.com> <70f917e6-3573-4042-a62e-a7f770cfa665@email.android.com> Message-ID: <000001d83aec$94f64510$bee2cf30$@bluewin.ch> ..I simplified the code below with a for loop : >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] >sub_lst = [] >p = 0 >pair1 = lst[p][0:2] >pair2 = list(lst[p][0]+ lst[p][2]) >pair3 = lst[p][1:] >for i in lst: > print(i) > if pair1 or pair2 or pair3 not in i: > sub_lst.append(i) > p += 1 >print(sub_lst) Bur main problem stays the same, getting all 4 instead of only 3 sublists. Marcus ?many thanks for your quick replay. When I used a for loop : >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] >sub_lst = [] >for p in lst: > pair1 = lst[p][0:2] > pair2 = list(lst[p][0]+ lst[p][2]) > pair3 = lst[p][1:] > print('pair1:', pair1, 'pair2: ', pair2, 'pair3: ', pair3) > if pair1 or pair2 or pair3 not in sub_lst: > sub_lst.append(lst[p]) > print(sub_lst) I got a traceback: ??.. line 5, in pair1 = lst[p][0:2] TypeError: list indices must be integers or slices, not list And yes, the code above did not do what I exspected. But I don?t understand what you mean with If pair 1 not empty Or pair2 not empty Or pair3 not in newlist What is the difference between pair not beeing empty or not beeing in new_list ? How should I define the if condition properly ? Marcus. Von: alan.gauld at yahoo.co.uk Gesendet: Freitag, 18. M?rz 2022 15:00 An: marcus.luetolf at bluewin.ch Cc: tutor at python.org Betreff: Re: AW: [Tutor] problem solving with lists On 18 Mar 2022 13:07, marcus.luetolf at bluewin.ch wrote: >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] >n = len(lst) >p = 0 >new_lst = [] >while n > 0: > pair1 = lst[p][0:2] > pair2 = list(lst[p][0]+ lst[p][2]) > pair3 = lst[p][1:] > print('pair1:', pair1, 'pair2: ', pair2, 'pair3: ', pair3) > if pair1 or pair2 or pair3 not in new_lst I suspect that's not doing what you think. Python sees it as If pair 1 not empty Or pair2 not empty Or pair3 not in newlist I don't think that's what you want. BTW why does For p in lst not work? It seems to be what you are effectively doing... Alan G >From my phone, apologies for any typing errors... From wlfraed at ix.netcom.com Fri Mar 18 13:56:00 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Fri, 18 Mar 2022 13:56:00 -0400 Subject: [Tutor] problem solving with lists References: <70f917e6-3573-4042-a62e-a7f770cfa665.ref@email.android.com> <70f917e6-3573-4042-a62e-a7f770cfa665@email.android.com> <000001d83aec$94f64510$bee2cf30$@bluewin.ch> Message-ID: <9bh93hdursa6lrth23vns910kq9fsip0cr@4ax.com> On Fri, 18 Mar 2022 18:21:19 +0100, declaimed the following: Since the OP appears to be conducting a private email conversation with Mr. Gauld -- having never even acknowledged any other posts provided by others -- I'm going to do something I normally wouldn't on the basis that the OP probably won't notice this post either Provide my working code! Both versions... (though I see my comments are a bit out of date -- current code is parameterized rather than hard-coded to particular lengths) ***** Assumption: common pairs are ADJACENT letters """ letters.py based upon a homework question on tutor list dennis l bieber march 18 2022 a blend of the original sixteen_letters.py and ooREXX letters.rex This version interprets "common pairs" to mean "adjacent" letters """ import sys import string from itertools import combinations, filterfalse import pprint LETTERS = string.ascii_lowercase accepted = [] #accumlate good item strings here def theFilter(item): """ Returns False (accepted) if no adjacent letter pair in item is IN any previously accepted item """ rc = False #assume item will be accepted item = "".join(sorted(item)) for aitem in accepted: for pairx in range(len(item) - 1): if item[pairx:pairx+2] in aitem: #reject this item, don't test other items rc = True break if rc: break return rc def main(pool_len, item_len): #generator of four-letter substrings, then generator of filtered items = combinations(LETTERS[:pool_len], item_len) itemFilter = filterfalse(theFilter, items) #generator unfortunately returns tuples, not strings #also, accepted is "global", theFilter reads it for item in itemFilter: accepted.append("".join(sorted(item))) return accepted #even though a global item if __name__ == "__main__": if len(sys.argv) < 3: print("\n***\tUsage: letters.py pool_length item_length\n") else: accepted = main(int(sys.argv[1]), int(sys.argv[2])) print("\nAccepted Items: %s" % len(accepted)) answer = [accepted[i*4:i*4+4] for i in range(round(len(accepted) / 5 + 0.5) + 1)] pprint.pp(answer) -=-=- ***** Assumption: common pairs are set intersection """ letters_set.py based upon a homework question on tutor list dennis l bieber march 18 2022 a blend of the original sixteen_letters.py and ooREXX letters.rex This version interprets "common pairs" to mean "set intersection" """ import sys import string from itertools import combinations, filterfalse import pprint LETTERS = string.ascii_lowercase accepted = [] #accumlate good item strings here def theFilter(item): """ Returns False (accepted) if no adjacent letter pair in item is IN any previously accepted item """ rc = False #assume item will be accepted #not optimized -- should save set() in accepted #rather than continually converting item = set(item) for aitem in accepted: if len(item & set(aitem)) >= 2: #reject this item, don't test other items rc = True break return rc def main(pool_len, item_len): #generator of four-letter substrings, then generator of filtered items = combinations(LETTERS[:pool_len], item_len) itemFilter = filterfalse(theFilter, items) #generator unfortunately returns tuples, not strings #also, accepted is "global", theFilter reads it for item in itemFilter: accepted.append("".join(sorted(item))) return accepted #even though a global item if __name__ == "__main__": if len(sys.argv) < 3: print("\n***\tUsage: letters_set.py pool_length item_length\n") else: accepted = main(int(sys.argv[1]), int(sys.argv[2])) print("\nAccepted Items: %s" % len(accepted)) answer = [accepted[i*4:i*4+4] for i in range(round(len(accepted) / 5 + 0.5))] pprint.pp(answer) -=-=- -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From alan.gauld at yahoo.co.uk Fri Mar 18 14:16:04 2022 From: alan.gauld at yahoo.co.uk (alan.gauld at yahoo.co.uk) Date: Fri, 18 Mar 2022 18:16:04 +0000 Subject: [Tutor] problem solving with lists In-Reply-To: <000f01d83ada$8fd4a930$af7dfb90$@bluewin.ch> References: <5e6e77f9-4bf9-42a6-a8a4-1312e8f9a251.ref@email.android.com> Message-ID: <5e6e77f9-4bf9-42a6-a8a4-1312e8f9a251@email.android.com> On 18 Mar 2022 15:12, marcus.luetolf at bluewin.ch wrote: ?many thanks for your quick replay. When I used a for loop?: ? >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] >sub_lst = [] >for p in lst: >??? pair1 = lst[p][0:2] P is not an index its the actual sublist. So you just need Pair1 = p[0:2] > > ected. But I don?t understand what you mean with If pair 1 not empty Or pair2 not empty Or pair3 not in newlist ? What is the difference between pair not beeing empty or not beeing in new_list ? Pair not empty means pair contains anything other than the empty list. Pair not in newlist means pair is not empty and it's contents are not I. Newlist. Very different!? How should I define the if condition properly?? You need, I assume,? If Pair1 not in newlist? Or pair2 not in newlist Or pair3 not in newlist Alan g.? From wlfraed at ix.netcom.com Fri Mar 18 19:17:37 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Fri, 18 Mar 2022 19:17:37 -0400 Subject: [Tutor] problem solving with lists References: <5e6e77f9-4bf9-42a6-a8a4-1312e8f9a251.ref@email.android.com> <000f01d83ada$8fd4a930$af7dfb90$@bluewin.ch> <5e6e77f9-4bf9-42a6-a8a4-1312e8f9a251@email.android.com> Message-ID: On Fri, 18 Mar 2022 18:16:04 +0000, Alan G via Tutor declaimed the following: Interesting... Out of curiosity (mainly to confirm my posts have been getting to the list from gmane) I started perusing archives... The current thread bears a strange resemblance to a thread from 6.5 years ago... https://www.mail-archive.com/tutor at python.org/msg72192.html Apparently from the same author -- or there are a number of people using the same email (and having vastly different skill levels with Python: the 6 year old code actually looks clean, but what little has been shown recently has regressed to a first year student level). -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From PythonList at DancesWithMice.info Fri Mar 18 23:02:47 2022 From: PythonList at DancesWithMice.info (dn) Date: Sat, 19 Mar 2022 16:02:47 +1300 Subject: [Tutor] problem solving with lists In-Reply-To: <9bh93hdursa6lrth23vns910kq9fsip0cr@4ax.com> References: <70f917e6-3573-4042-a62e-a7f770cfa665.ref@email.android.com> <70f917e6-3573-4042-a62e-a7f770cfa665@email.android.com> <000001d83aec$94f64510$bee2cf30$@bluewin.ch> <9bh93hdursa6lrth23vns910kq9fsip0cr@4ax.com> Message-ID: <86fe30c9-cbe1-a93c-6f43-da4456aec2a2@DancesWithMice.info> > a) I don't know how to do that, b) I am not shure wether this is a way do > it, nor c) if my problem can by solved by python at all. a) as below - but this is an question of algorithm, NOT Python b) as below c) disingenuous question - if it can't be, then why were you assigned such a problem by your tutor/teacher? That said, I dislike assignments which so-obviously require attention to "indexing" (of strings or lists). They allude that someone has taken a BASIC, C, Java, etc, assignment, and re-used it in Python! See also (frequent and official) notices about our not being a homework/assignment mill/factory! Has the OP's rather arcane approach 'blinkered' our responses? Why build a number of 'combinations' and then attempt to prove/select the ones that fit the criteria (or do not)? Wouldn't it be better to build the sub-lists correctly and avoid any post-processing? Results obtained: /usr/bin/python3 /home/dn/Projects/experiments/marcus.py 0 [['a', 'b', 'c', 'd'], ['b', 'c', 'd', 'e'], ['c', 'd', 'e', 'f'], ['d', 'e', 'f', 'g']] 1 [['a', 'c', 'e', 'g'], ['c', 'e', 'g', 'i'], ['e', 'g', 'i', 'k'], ['g', 'i', 'k', 'm']] 2 [['a', 'd', 'g', 'j'], ['d', 'g', 'j', 'm'], ['g', 'j', 'm', 'p'], ['j', 'm', 'p', 'c']] 3 [['a', 'e', 'i', 'm'], ['e', 'i', 'm', 'a'], ['i', 'm', 'a', 'e'], ['m', 'a', 'e', 'i']] 4 [['a', 'f', 'k', 'p'], ['f', 'k', 'p', 'e'], ['k', 'p', 'e', 'j'], ['p', 'e', 'j', 'o']] Are these correct? If not, please advise which part is incorrect? If incomplete, are the following definitions correct, or in need of augmentation/clarification? all_letters = "abcdefghijklmnop" number_of_lists = 5 number_of_sub_lists = 4 number_per_sub_list = 4 Solution in 32 nicely-formatted LoC, including both printing and assembling the results into a single result-list, docstring, comment, defining of 'magic constants' and helpers, PEP-8 spacings, and full for-loops (cf comprehension one-liners). itertools has been imported, but the solution could work just as well without. -- Regards, =dn From alan.gauld at yahoo.co.uk Sat Mar 19 08:24:31 2022 From: alan.gauld at yahoo.co.uk (alan.gauld at yahoo.co.uk) Date: Sat, 19 Mar 2022 12:24:31 +0000 Subject: [Tutor] problem solving with lists In-Reply-To: <007d01d83b80$1dc78fa0$5956aee0$@bluewin.ch> References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> Message-ID: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> On 19 Mar 2022 10:57, marcus.luetolf at bluewin.ch wrote: Many thanks again. Using your first advice my code got even clearer?: ? >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] >sub_lst = [] ? >for p in lst: >??? pair1 = p[0:2] >??? pair2 = list(p[0]+ p[2]) >??? pair3 = p[1:] >??? if pair1 not in sub_lst or pair2 not in sub_lst or pair3 not in sub_lst: >??????? sub_lst.append(p) >print(sub_lst) ? But your second advice?: >if pair1 not in sub_lst or pair2 not in sub_lst or pair3 not in sub_lst: ? Still yields all four sublists instead of eliminating the last 2 sublists , ['a', 'b', 'g'], ['b', 'c', 'h'], since ?a?, ?b? and ?b?, ?c? were already in the first 2 sublists. I think python does not allow to check if an item is in a list with only slices of the item to be checked ?? Python does what you ask. If you get the wrong answer then you are asking the wrong question.? But I still don't really understand what you are trying to do. Have you looked at Dennis replies, his approach is more likely to get you what you want....? Alan g Von: alan.gauld at yahoo.co.uk Gesendet: Freitag, 18. M?rz 2022 19:16 An: marcus.luetolf at bluewin.ch Cc: tutor at python.org Betreff: Re: AW: AW: [Tutor] problem solving with lists ? ? ? On 18 Mar 2022 15:12, [1]marcus.luetolf at bluewin.ch wrote: ?many thanks for your quick replay. When I used a for loop?: ? >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] >sub_lst = [] >for p in lst: >??? pair1 = lst[p][0:2] ? ? P is not an index its the actual sublist. So you just need ? Pair1 = p[0:2] ? ? >? > ected. But I don?t understand what you mean with If pair 1 not empty Or pair2 not empty Or pair3 not in newlist ? What is the difference between pair not beeing empty or not beeing in new_list ? ? Pair not empty means pair contains anything other than the empty list. Pair not in newlist means pair is not empty and it's contents are not I. Newlist. Very different!? How should I define the if condition properly?? ? ? You need, I assume,? ? If Pair1 not in newlist? Or pair2 not in newlist Or pair3 not in newlist ? Alan g.? ? References Visible links 1. mailto:marcus.luetolf at bluewin.ch From marcus.luetolf at bluewin.ch Sat Mar 19 09:55:31 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Sat, 19 Mar 2022 14:55:31 +0100 Subject: [Tutor] problem solving with lists In-Reply-To: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> Message-ID: <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> First to dn?s answer: I am not an professional programmer. Programming with pyhon is a hobby in the sense of life long learning. And other than a course in C I have no knowledge of other programming languages. I am just trying to solve my problem with what little I know about python. That?s why I turned to tutor for help. I have found an algorithm and all required code steps but the very last one, admittedly helped by most wellcome comments from tutor. dn?s ? definitions ? are correct but I reduced the problem solving to >all_letters = ?abcdefghi? >number_of_lists = 4 >number_of_sublists per list = 3 >number_per_sublist = 3 But dn?s ?results obtained? is not what I need, I replaced them by itertools function combinations. dn?s last section I don?t understand. Second to Alan G.?s replay : My problem ist to create a set of unique sublists of 3 items/letters out of a list of 9 items/letters, later to be extended to sublists of 4 items/letters out of a list of 16 items/letters. I am using letters as items for the sake of readability. Once the code works letters will be substituted by names of people for the final goal is to set up ?unique? teams. ?Unique? means that other than single items/letters, pairs of items/letters (pair1, pair2, pair3) can appear only once in all sublists. A sublist could be understood as a combination of pair1+pair2+pair3. At the end there should be only 12 sublists in 4 lists left. Sorry for the length of this replay, Marcus. Von: alan.gauld at yahoo.co.uk Gesendet: Samstag, 19. M?rz 2022 13:25 An: marcus.luetolf at bluewin.ch Cc: tutor at python.org Betreff: Re: AW: AW: AW: [Tutor] problem solving with lists On 19 Mar 2022 10:57, marcus.luetolf at bluewin.ch wrote: Many thanks again. Using your first advice my code got even clearer : >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] >sub_lst = [] >for p in lst: > pair1 = p[0:2] > pair2 = list(p[0]+ p[2]) > pair3 = p[1:] > if pair1 not in sub_lst or pair2 not in sub_lst or pair3 not in sub_lst: > sub_lst.append(p) >print(sub_lst) But your second advice : >if pair1 not in sub_lst or pair2 not in sub_lst or pair3 not in sub_lst: Still yields all four sublists instead of eliminating the last 2 sublists , ['a', 'b', 'g'], ['b', 'c', 'h'], since ?a?, ?b? and ?b?, ?c? were already in the first 2 sublists. I think python does not allow to check if an item is in a list with only slices of the item to be checked ?? Python does what you ask. If you get the wrong answer then you are asking the wrong question. But I still don't really understand what you are trying to do. Have you looked at Dennis replies, his approach is more likely to get you what you want.... Alan g Von: alan.gauld at yahoo.co.uk > Gesendet: Freitag, 18. M?rz 2022 19:16 An: marcus.luetolf at bluewin.ch Cc: tutor at python.org Betreff: Re: AW: AW: [Tutor] problem solving with lists On 18 Mar 2022 15:12, marcus.luetolf at bluewin.ch wrote: ?many thanks for your quick replay. When I used a for loop : >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] >sub_lst = [] >for p in lst: > pair1 = lst[p][0:2] P is not an index its the actual sublist. So you just need Pair1 = p[0:2] > > ected. But I don?t understand what you mean with If pair 1 not empty Or pair2 not empty Or pair3 not in newlist What is the difference between pair not beeing empty or not beeing in new_list ? Pair not empty means pair contains anything other than the empty list. Pair not in newlist means pair is not empty and it's contents are not I. Newlist. Very different! How should I define the if condition properly ? You need, I assume, If Pair1 not in newlist Or pair2 not in newlist Or pair3 not in newlist Alan g. From wlfraed at ix.netcom.com Sat Mar 19 13:04:26 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sat, 19 Mar 2022 13:04:26 -0400 Subject: [Tutor] problem solving with lists References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> Message-ID: <83ub3htt035srbueav1vj8rtagdhaq754m@4ax.com> On Sat, 19 Mar 2022 14:55:31 +0100, declaimed the following: >First to dn?s answer: > >I am not an professional programmer. Programming with pyhon is a hobby in the sense of life long learning. > >And other than a course in C I have no knowledge of other programming languages. I am just trying to solve > >my problem with what little I know about python. That?s why I turned to tutor for help. I have found an > >algorithm and all required code steps but the very last one, admittedly helped by most wellcome > >comments from tutor. > Based upon the list archives, you've been trying to solve this problem for over six years. https://www.mail-archive.com/tutor at python.org/msg72192.html Over a period of 10 days, /that/ thread evolved into an explanation that you were attempting to produce a solution to the "Social Golfer Problem". In contrast, this thread has been running for 13 days, and there have only been a few hints as to what the real problem to be solved is... And it ISN'T eliminating any sets that have two or more elements in common. The Social Golfer Problem rarely has a perfect solution -- normally the best one can achieve is to minimize the repeated pairings. >?Unique? means that other than single items/letters, pairs of items/letters (pair1, pair2, pair3) can appear only once in > >all sublists. A sublist could be understood as a combination of pair1+pair2+pair3. At the end there should be only 12 sublists > >in 4 lists left. In most cases, there may be NO solution meeting that criteria. https://www.localsolver.com/docs/last/exampletour/socialgolfer.html claims that 32 players, in (8) foursomes, and playing for 10 days/weeks does have a known solution with no repeated pairs. """ More generally the problem is to schedule m groups of n golfers over p weeks, with maximum socialisation. The complexity of the problem is unknown. """ Unfortunately, that web site, like many other hits on "social golfer problem", wants to sell you their proprietary solution library. https://en.wikipedia.org/wiki/Social_golfer_problem https://en.wikipedia.org/wiki/Steiner_system """ The corresponding question for finding thirteen different disjoint S(2,3,15) systems was asked by James Sylvester in 1860 as an extension of the Kirkman's schoolgirl problem, namely whether Kirkman's schoolgirls could march for an entire term of 13 weeks with no triplet of girls being repeated over the whole term. The question was solved by RHF Denniston in 1974,[11] who constructed Week 1 as follows: Denniston reported in his paper that the search he employed took 7 hours on an Elliott 4130 computer at the University of Leicester, and he immediately ended the search on finding the solution above, not looking to establish uniqueness. """ Javascript "near" solver at https://github.com/islemaster/good-enough-golfers (and running page https://goodenoughgolfers.com/ ) A text description of the real-world problem, and not this confusing emphasis on list of sublists of sublists (...) would have short-cut a lot of this thread. -=-=-=- Given a POOL of 16 golfers/players, who play a MATCH once a week (day), in four FOURSOMES (16/4 => 4), over the course of a TOURNAMENT lasting five weeks (days), devise a schedule assigning players to foursomes such that the number of repeated pairings between foursomes is minimized. Constraint: Each of the 16 players is assigned to a foursome each week (day); conversely no player may appear in multiple foursomes within a single week (day). -=-=-=- Tournament <= top-level list, having five weekly (daily) Matches <= sublists each having four groups of Foursomes <= sublists/tuples/strings of length four Those terms would make following the discussion much cleaner, and avoids getting bogged down in thoughts of "indexing" etc. While it may be possible to make a generalized program (allowing for parameters for pool size, group size (threesome, foursome, quintets...) and number of weeks (days) in the tournament... Everything I've read implies that there is no simple numerical solution. Solutions appear to rely upon brute-force searching, applying some sort of scoring to each repeated pairing (is it better to have one pair repeat four times, or two pairs that each repeat twice?). After all, an easy start for 16/4/5 case is simply abcd efgh ijkl mnop aeim bfjn cgko dhlp wherein the second week take the first player of each foursome from the previous week to make the first foursome of the new week, second players for second foursome, etc. But you can't do that for the third week -- the transform just reverses.. This will likely be my last post within this thread. Attempting to solve problems when much of the actual problem domain is being withheld from the assistant is an exercise in futility... -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From PythonList at DancesWithMice.info Sat Mar 19 16:35:53 2022 From: PythonList at DancesWithMice.info (dn) Date: Sun, 20 Mar 2022 09:35:53 +1300 Subject: [Tutor] problem solving with lists In-Reply-To: <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> Message-ID: Marcus, On 20/03/2022 02.55, marcus.luetolf at bluewin.ch wrote: > First to dn?s answer: > > I am not an professional programmer. Programming with pyhon is a hobby > in the sense of life long learning. > > And other than a course in C I have no knowledge of other programming > languages. I am just trying to solve > > my problem with what little I know about python. That?s why I turned to > tutor for help. I have found an > > algorithm and all required code steps but the very last one, ?admittedly > helped by most wellcome This explains a lot - and is partly why you are experiencing so much difficulty! I'm expecting that you are multi-lingual in spoken languages. You would not learn a new language, let's say Swahili, by taking every word in your native-tongue and translating it, by itself. Dictionaries are useful, but sentences are not mere words strung together. For example, the order of words in an English sentence, and those same words translated one-at-a-time into German, will probably not produce a grammatically-correct sentence. Then there are those ghastly English words which have multiple meanings - depending upon the context of their use. Even more complicated are idioms and sayings. The New Zealand "yeah, nah" (literally "yes, no", but meaning: I'll pretend to agree, but I don't) or the American "yeah right" (the exact opposite of what the words 'say', ie this is NOT correct - I don't really believe you), will definitely not convey correct meaning if the translation is merely word-for-word! May I recommend that you put aside your C-knowledge (don't throw it away), and benefit from the guidance in a 'How to learn Python' book or an online course (many are free)*. One of these will introduce you to the syntax of Python AND the semantics, idioms, etc, in a structured manner. Thus, you won't be left trying to make your own way, without knowing a good path to follow! * @Alan's messages used to finish with a link to his course. If you ask, perhaps he'll explain why his latest did not... When you do, you will quickly skim through things like assignment statements, because they will be very familiar to you. However, you will quickly start to notice important differences, eg for-loops are not the same, no matter their appearance. Accordingly, the manner in which one employs a for-loop changes, and with it the idiom - the way one processes items in lists and characters within strings! > dn?s ??definitions?? are correct but I reduced the problem solving to > >>all_letters = ?abcdefghi? >>number_of_lists = 4 >>number_of_sublists per list = 3 >>number_per_sublist = 3 The first step to finding a solution is to understand the problem. It is sad that you have resisted requests to show the 'real world' problem, and thus have reduced the matter to an academic exercise - which is why it seems to be 'homework'! However, understanding the parameters is a start. > But dn?s ?results obtained? ?is not what I need, I replaced them by > itertools function combinations. Sometimes it is a good idea to step-back from the problem. Some suggestions the psychologists and neuroscientists offer are: to take a shower, or a walk, watch TV, read a book - anything to get the problem out of the 'front' of your head. Of course it won't be completely 'gone'. The sub-conscious will still be 'turning it over in your mind'. This process of looking at things in a different way can yield alternate approaches! Thus, people often saying something like: "the answer 'came to me' while I was in the shower"! You asked for help - and that is what at least three of us have been rendering. Yet, here you have said "is not what I need". What does that mean? What is in your head, that is not in mine? How do you move/copy this knowledge of what you need, from your head to mine? Have you done so? The distinct request was: "Are these correct? If not, please advise which part is incorrect?" The first part was answered. What of the second? In what way were the answers incorrect? In what way was the specification/problem-statement not fulfilled? Have you invested time and effort to help the person who has given up free-time to help you? (see also @Dennis' comments, despite the hours he must have given already) Perhaps that idea of 'taking a break' is needed, so that you can be as helpful as they, to the people who are being helpful to you? > dn?s last section I don?t understand. Again, what you say is understandable, but *why*? If you indicate the part that you don't understand, then we can help your "life long learning"... Has this abrupt dismissal, or rejection, helped you? Helped me? > My problem ist to create a set of unique sublists of 3 items/letters out > of a list of 9 items/letters, later to be extended to > sublists of 4 items/letters out of a list of 16 items/letters. This statement: "3 items/letters out of a list of 9 items/letters" does *not* appear in the original post. Why? Why not? Can we solve one problem at a time, and then move-on to the next? You say "later", which may be the case inside your own head. However, in our context, the original post has us thinking of 'the solution' as four sub-lists of four items - and that problem is not yet solved. An English idiom for causing such confusion is that you are "moving the goal-posts". Generally regarded as either cheating, or at least causing confusion. Do you mean to do this to us? Yes, "three" or "four", I (think I) can see that they are similar problems - strangely enough, this is why I wrote the "definitions" at the beginning of the code, rather than 'burying' the fours and the five as "magic numbers" within the algorithm! Such is a good programming practice, because it enables the very flexibility of sizes and selections, your second problem (may) requires. > I am using letters as items for the sake of readability. Once the code > works letters will be substituted by names of people > for the final goal is to set up ??unique? teams. > > ?Unique? means that other than single items/letters, ?pairs of > items/letters (pair1, pair2, pair3) can appear only once in > all sublists. A sublist could be understood as a combination of > pair1+pair2+pair3. At the end there should be only 12 sublists > in 4 lists left. Which leaves me baffled. The solution provided-earlier appears to do exactly that. There is no repetition of letter-combinations/team-members' names. (or perhaps I can't see that there are*, and need to be shown...) * am in-recovery from a recent eye operation So, exactly why did you reject it? (and I'm repeating an earlier question) Similarly, and further to my earlier comment about "real world", @Dennis' explanation of 'golfers and schoolgirls' suddenly brought the problem into focus - I remembered staff at our school (many, many, years ago) trying to do exactly this sort of thing - otherwise the strong players would always want to play together, and the unskilled players would end-up (always) on the losing team. Learning to deal with this (what seemed like a frustrating imposition, at the time) taught me that each person can do certain things (and not others), and thus the concept of "the right man for the job" (today: updated to an "equal-opportunities" attitude) Thanks @Dennis! A key to "learning" (which includes learning about/understanding the problem to be solved) is to start from something we know, and then step (one small pace) into the unknown. Thus, we learn something 'new' *and* absorbing it, we also align that knowledge in our minds. For example, to know when we can use it/employ such a solution! Now that I understand that the letters represent names of people, my confidence has grown... Speaking of "solutions". There is often more than one way to solve a problem. Twee example: 1 + 2 == 2 + 1. The idea of 'stepping back' (as above) often enables one to realise that 'there's another way'. As mentioned previously, we could either generate every "combination" and then trim those with unacceptable repetitions, or we could generate unique combinations in the first place. (and maybe there are other approaches) Persisting with a solution (that isn't working) without stopping to consider such, reminds me of another idiom: "flogging a dead horse" - and we wouldn't want to be unkind to animals, would we? So, please take a breath and relax. Then instead of rushing to code/to reply to email, consider what you have been offered, answer questions (first for yourself, and only later for us), and look at the problem and the solution(s) - from all angles... > Sorry for the length of this replay, Marcus. ... Nobody here is 'against' you. Please avoid letting your frustrations communicate the negativity towards your helpers (which has been happening)! Please ask yourself: if someone has taken a chunk of time to consider the problem and (attempt to) offer help, should I give a similar amount of time, care, and respect; in response? -- Regards, =dn From alan.gauld at yahoo.co.uk Sat Mar 19 19:17:53 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sat, 19 Mar 2022 23:17:53 +0000 Subject: [Tutor] problem solving with lists In-Reply-To: References: Message-ID: > * @Alan's messages used to finish with a link to his course. If you ask, > perhaps he'll explain why his latest did not... This is simple. I?m currently on vacation and responding from my tablet and phone. Neither of which have my usual .signature set up. Normal service (and sig) will be resumed next week? Alan G. Tutorial: http://www.alan-g.me.uk/l2p2 From wlfraed at ix.netcom.com Sat Mar 19 22:07:19 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sat, 19 Mar 2022 22:07:19 -0400 Subject: [Tutor] problem solving with lists References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> Message-ID: On Sun, 20 Mar 2022 09:35:53 +1300, dn declaimed the following: >(see also @Dennis' comments, despite the hours he must have given already) > I have the advantage (?) of being retired and just living with a slew of medical problems (chemo/immuno-therapy for high-stage cancer; a neck brace since my Jeep rolled over last November [and neck surgery planned for first week of April]).. The only thing keeping me from being a couch-potato is that the couch is in the living room, covered by a slew of small boxes, with a TV that does not have an antenna/cable/satellite feed (the working TV is in a spare room with a recliner, but "recliner rock" doesn't give the same sense ). But enough about me -- and no doubt a number of idioms that may perplex others. >Similarly, and further to my earlier comment about "real world", >@Dennis' explanation of 'golfers and schoolgirls' suddenly brought the >problem into focus - I remembered staff at our school (many, many, years Identifying "shared pairs" is trivial, compared to the search algorithm needed for solving the "Social Golfers Problem" (SGP). All one needs is Set Intersection operations and a test for >= 2 intersecting elements. And the SGP is why I'm phasing out of this thread. After getting past the half-dozen companies selling specialized solver libraries, the next half-dozen entries are university research papers -- and even a Master's Thesis! One paper is titled "CSP2SAT4J: A Simple CSP to SAT translator"... I'm guessing the "4J" is "for Java", but I'm 99 44/100% * certain that CSP is NOT "Communicating Sequential Processes" (https://www.amazon.com/Communicating-sequential-processes-Prentice-Hall-International/dp/0131532715) and SAT is NOT "Scholastic Aptitude Test". {Wikipedia suggests these are https://en.wikipedia.org/wiki/Constraint_satisfaction_problem and https://en.wikipedia.org/wiki/Boolean_satisfiability_problem. That is way much more theory than I'm willing to approach on a "tutor" role. Add in that, in the late 70s, CompSci at my college WAS a Math major (not physics) -- reducing the number of advanced math coursed to be taken. Graph theory was the most complex, along with Statistics 1 (Stat-2 was a requirement of the Business Computing specialty -- using SPSS; I was in System Software specialty which meant assorted OS and language design courses). >Thanks @Dennis! For waking nightmares? * obscure reference https://lyricsjonk.com/ronnie-milsap-pure-love.html AND the old Ivory soap advertisements -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From nathan-tech at hotmail.com Sat Mar 19 22:13:52 2022 From: nathan-tech at hotmail.com (Nathan Smith) Date: Sun, 20 Mar 2022 02:13:52 +0000 Subject: [Tutor] identifying if a path is heading into a zip file - windows Message-ID: Take a path, for instance: path="c:\my folder" ?os.path.isdir(path) = True Take a second path: path= 'c:\my folder\a file.zip\a folder in the zip' Is there a way for python to know, without me physically breaking it down, that that path is in a zip file? For instance, a way for it to know it's dealing with a zip archive file, and not just a folder with .zip in the name? thanks -- Best Wishes, Nathan Smith, BSC My Website: https://nathantech.net From PythonList at DancesWithMice.info Sat Mar 19 23:35:44 2022 From: PythonList at DancesWithMice.info (dn) Date: Sun, 20 Mar 2022 16:35:44 +1300 Subject: [Tutor] problem solving with lists In-Reply-To: References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> Message-ID: <5fcd5318-c555-9df7-e9b9-00c0b8efef22@DancesWithMice.info> On 20/03/2022 15.07, Dennis Lee Bieber wrote: ... >> Similarly, and further to my earlier comment about "real world", >> @Dennis' explanation of 'golfers and schoolgirls' suddenly brought the >> problem into focus - I remembered staff at our school (many, many, years > > Identifying "shared pairs" is trivial, compared to the search algorithm > needed for solving the "Social Golfers Problem" (SGP). All one needs is Set > Intersection operations and a test for >= 2 intersecting elements. So, first criticism is that line 1: 0 [['a', 'b', 'c', 'd'], ['b', 'c', 'd', 'e'], ['c', 'd', 'e', 'f'], ['d', 'e', 'f', 'g']]the should be more like: 0 [['a', 'b', 'c', 'd'], ['e', 'f', 'g', 'h'], ['i', 'j', 'k', 'l'], ['m', 'n', 'o', 'p']] but when it comes to the next list, would ['a', 'c', 'd', 'e'] be unacceptable because although the 'b' has been dropped, the first three all served-together previously. Thus, should the remaining lists commence: ['a', 'e', 'i', 'm']... ['a', 'f', 'j', 'n']... ['a', 'g', 'k', 'o']... ['a', 'h', 'l', 'p']... (at which no more are possible within the limit of 16 names) - or have I still 'missed' whatever the OP's objective might be? (because this still seems like a relatively-trivial selection exercise) > That is way much more theory than I'm willing to approach on a "tutor" Which is why the OP would be best served by actually giving us the result-expected, and thus something against which to measure our advice, and success or otherwise in finding a solution... > role. Add in that, in the late 70s, CompSci at my college WAS a Math major > (not physics) -- reducing the number of advanced math coursed to be taken. > Graph theory was the most complex, along with Statistics 1 (Stat-2 was a > requirement of the Business Computing specialty -- using SPSS; I was in > System Software specialty which meant assorted OS and language design > courses). Yes, I too was manufactured in the fifties (most parts still original!), but our uni enabled the business route ("Data Processing" in the terms of the day). Yes to the stats courses. However, this skewed into econometrics and modelling. No to graph theory as a formal course, but obviously I picked-up it and trees along the way, and to help cope with knot theory. (not much to do with ropes!) We didn't cover compilers, other than maybe a single lecture. My intro to systems programming came when I had a team of mainframe sys-progs to supervise - and regularly remind that they didn't actually own the machine, it was (also) there for workloads to be run... Referring to "waking nightmares", all I need say is "JCL"! >> Thanks @Dennis! > > For waking nightmares? The business of programming is a constant reminder of human frailty - the interpreter/compiler is always merciless in pointing-out our faults! > * obscure reference https://lyricsjonk.com/ronnie-milsap-pure-love.html AND > the old Ivory soap advertisements I'm glad you pointed it out. I knew I'd heard it (somewhere) before, but... Thereafter disappeared into memories of Cap'n Krunch, "Seadog", and the (what were they?) the milkies/soakies/sloppies. I've got to get a life - everyone else is alive! -- Regards, =dn From alan.gauld at yahoo.co.uk Sun Mar 20 05:02:19 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sun, 20 Mar 2022 09:02:19 +0000 Subject: [Tutor] identifying if a path is heading into a zip file - windows In-Reply-To: References: Message-ID: <9ED85EBF-024C-46CC-B46A-1D8433647A4F@yahoo.co.uk> > Take a second path: > > path= 'c:\my folder\a file.zip\a folder in the zip' > > Is there a way for python to know, without me physically breaking it down, that that path is in a zip file? > I don?t think so, the standard library tools simply analyse the text. You would need to write a function that traversed the path checking for isfile() Alan G. From mayoadams at gmail.com Sat Mar 19 10:34:00 2022 From: mayoadams at gmail.com (Mayo Adams) Date: Sat, 19 Mar 2022 10:34:00 -0400 Subject: [Tutor] problem solving with lists In-Reply-To: <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> Message-ID: So what's wrong with Dennis Bieber's answer? On Sat, Mar 19, 2022 at 9:58 AM wrote: > First to dn?s answer: > > I am not an professional programmer. Programming with pyhon is a hobby in > the sense of life long learning. > > And other than a course in C I have no knowledge of other programming > languages. I am just trying to solve > > my problem with what little I know about python. That?s why I turned to > tutor for help. I have found an > > algorithm and all required code steps but the very last one, admittedly > helped by most wellcome > > comments from tutor. > > > > dn?s ? definitions ? are correct but I reduced the problem solving to > > >all_letters = ?abcdefghi? > > >number_of_lists = 4 > > >number_of_sublists per list = 3 > > >number_per_sublist = 3 > > > > But dn?s ?results obtained? is not what I need, I replaced them by > itertools function combinations. > > > > dn?s last section I don?t understand. > > Second to Alan G.?s replay : > > My problem ist to create a set of unique sublists of 3 items/letters out > of a list of 9 items/letters, later to be extended to > > sublists of 4 items/letters out of a list of 16 items/letters. > > I am using letters as items for the sake of readability. Once the code > works letters will be substituted by names of people > > for the final goal is to set up ?unique? teams. > > > > ?Unique? means that other than single items/letters, pairs of > items/letters (pair1, pair2, pair3) can appear only once in > > all sublists. A sublist could be understood as a combination of > pair1+pair2+pair3. At the end there should be only 12 sublists > > in 4 lists left. > > > > Sorry for the length of this replay, Marcus. > > > > > > Von: alan.gauld at yahoo.co.uk > Gesendet: Samstag, 19. M?rz 2022 13:25 > An: marcus.luetolf at bluewin.ch > Cc: tutor at python.org > Betreff: Re: AW: AW: AW: [Tutor] problem solving with lists > > > > > > > > On 19 Mar 2022 10:57, marcus.luetolf at bluewin.ch marcus.luetolf at bluewin.ch> wrote: > > Many thanks again. > > Using your first advice my code got even clearer : > > > > >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] > > >sub_lst = [] > > > > >for p in lst: > > > pair1 = p[0:2] > > > pair2 = list(p[0]+ p[2]) > > > pair3 = p[1:] > > > if pair1 not in sub_lst or pair2 not in sub_lst or pair3 not in > sub_lst: > > > sub_lst.append(p) > > >print(sub_lst) > > > > But your second advice : > > >if pair1 not in sub_lst or pair2 not in sub_lst or pair3 not in sub_lst: > > > > Still yields all four sublists instead of eliminating the last 2 sublists > , ['a', 'b', 'g'], ['b', 'c', 'h'], > > since ?a?, ?b? and ?b?, ?c? were already in the first 2 sublists. > > I think python does not allow to check if an item is in a list with only > slices of the item to be checked ?? > > Python does what you ask. If you get the wrong answer then you are asking > the wrong question. > > > > But I still don't really understand what you are trying to do. Have you > looked at Dennis replies, his approach is more likely to get you what you > want.... > > > > Alan g > > Von: alan.gauld at yahoo.co.uk < > alan.gauld at yahoo.co.uk > > Gesendet: Freitag, 18. M?rz 2022 19:16 > An: marcus.luetolf at bluewin.ch > Cc: tutor at python.org > Betreff: Re: AW: AW: [Tutor] problem solving with lists > > > > > > > > On 18 Mar 2022 15:12, marcus.luetolf at bluewin.ch marcus.luetolf at bluewin.ch> wrote: > > ?many thanks for your quick replay. > > When I used a for loop : > > > > >lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['a', 'b', 'g'], ['b', 'c', 'h']] > > >sub_lst = [] > > >for p in lst: > > > pair1 = lst[p][0:2] > > > > > > P is not an index its the actual sublist. So you just need > > > > Pair1 = p[0:2] > > > > > > > > > > ected. But I don?t understand > > what you mean with > > > If pair 1 not empty > > Or pair2 not empty > > Or pair3 not in newlist > > > > What is the difference between pair not beeing empty or not beeing in > new_list ? > > > > Pair not empty means pair contains anything other than the empty list. > > Pair not in newlist means pair is not empty and it's contents are not I. > Newlist. Very different! > > How should I define the if condition properly ? > > > > > > You need, I assume, > > > > If Pair1 not in newlist > > Or pair2 not in newlist > > Or pair3 not in newlist > > > > Alan g. > > > > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- Mayo Adams From marcus.luetolf at bluewin.ch Sun Mar 20 10:55:27 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Sun, 20 Mar 2022 15:55:27 +0100 Subject: [Tutor] problem solving with lists In-Reply-To: References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> Message-ID: <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> Hello Experts and Helpers, a lot to answer: yes, I am multi-langual. I should have said "And other ...............knowledge of other programming languages but python. I have worked several online courses in python (coursera, edx etc.) over the past years, including most of Alan Gould's online tutorial. Therfore, a am still a beginner in python but not a learning beginner. I am using most oft he recomandations below, stepping back for a break, duck (my wife) method, reducing problem's (mental recursion), even dreaming. P.e. I've reduced my problem from >all_letters = ?abcdefghijklmnop? >number_of_lists = 5 >number_of_sublists per list = 4 >number_per_sublist = 4 to >all_letters = ?abcdefghi? >number_of_lists = 4 >number_of_sublists per list = 3 >number_per_sublist = 3 to >all_letters = 'abcdef'. My "real world problem" to build teams of unique composition ist exactly the same as to build unique sublists with letters. The latter beeing much easier do handle (typing(errors), readabilty etc.) to me. My goal was to explain my problem, algorithm, solution steps as precise as possible to avoid confusion. I might have not succeeded. dn's 'Results obtained:' (mail 20/03/2022 15.07) were altered in his mail of 19.03.2022 04:03 resulting in the exclusion of shared pairs, what was required. But there was no code offered. What means "OP", "32 nicely formated LoC", "PEP-8 spacings" ??? Concerning my definition of "Unique" > ?Unique? means that other than single items/letters, pairs of > items/letters (pair1, pair2, pair3) can appear only once in all > sublists. A sublist could be understood as a combination of > pair1+pair2+pair3. At the end there should be only 12 sublists > in 4 lists left. Which "solution provided-earlier" are you referring to ? I am very gratful for the hint to use the intersections method to identify "shared pairs" instead of laboring with indices, seems rather straightforward. But for now I cannot see yet how to use it to remove all non-uniques sublists/teams. SPG exactly describes my goal. Also for finding a solution without postprocessing but with finding unique sublists/teams from the beginning I have no idea at the moment. But I am very greatfull for this and possibly future exchanges on tutor with you as as Experts and Helpers. I have learned a very lot. I hope I belong not to the people who can't do certain things. Thank you all for your time. Marcus. -----Urspr?ngliche Nachricht----- Von: Tutor Im Auftrag von dn Gesendet: Samstag, 19. M?rz 2022 21:36 An: tutor at python.org Betreff: Re: [Tutor] problem solving with lists Marcus, On 20/03/2022 02.55, marcus.luetolf at bluewin.ch wrote: > First to dn?s answer: > > I am not an professional programmer. Programming with pyhon is a hobby > in the sense of life long learning. > > And other than a course in C I have no knowledge of other programming > languages. I am just trying to solve > > my problem with what little I know about python. That?s why I turned > to tutor for help. I have found an > > algorithm and all required code steps but the very last one, > admittedly helped by most wellcome This explains a lot - and is partly why you are experiencing so much difficulty! I'm expecting that you are multi-lingual in spoken languages. You would not learn a new language, let's say Swahili, by taking every word in your native-tongue and translating it, by itself. Dictionaries are useful, but sentences are not mere words strung together. For example, the order of words in an English sentence, and those same words translated one-at-a-time into German, will probably not produce a grammatically-correct sentence. Then there are those ghastly English words which have multiple meanings - depending upon the context of their use. Even more complicated are idioms and sayings. The New Zealand "yeah, nah" (literally "yes, no", but meaning: I'll pretend to agree, but I don't) or the American "yeah right" (the exact opposite of what the words 'say', ie this is NOT correct - I don't really believe you), will definitely not convey correct meaning if the translation is merely word-for-word! May I recommend that you put aside your C-knowledge (don't throw it away), and benefit from the guidance in a 'How to learn Python' book or an online course (many are free)*. One of these will introduce you to the syntax of Python AND the semantics, idioms, etc, in a structured manner. Thus, you won't be left trying to make your own way, without knowing a good path to follow! * @Alan's messages used to finish with a link to his course. If you ask, perhaps he'll explain why his latest did not... When you do, you will quickly skim through things like assignment statements, because they will be very familiar to you. However, you will quickly start to notice important differences, eg for-loops are not the same, no matter their appearance. Accordingly, the manner in which one employs a for-loop changes, and with it the idiom - the way one processes items in lists and characters within strings! > dn?s ? definitions ? are correct but I reduced the problem solving to > >>all_letters = ?abcdefghi? >>number_of_lists = 4 >>number_of_sublists per list = 3 >>number_per_sublist = 3 The first step to finding a solution is to understand the problem. It is sad that you have resisted requests to show the 'real world' problem, and thus have reduced the matter to an academic exercise - which is why it seems to be 'homework'! However, understanding the parameters is a start. > But dn?s ?results obtained? is not what I need, I replaced them by > itertools function combinations. Sometimes it is a good idea to step-back from the problem. Some suggestions the psychologists and neuroscientists offer are: to take a shower, or a walk, watch TV, read a book - anything to get the problem out of the 'front' of your head. Of course it won't be completely 'gone'. The sub-conscious will still be 'turning it over in your mind'. This process of looking at things in a different way can yield alternate approaches! Thus, people often saying something like: "the answer 'came to me' while I was in the shower"! You asked for help - and that is what at least three of us have been rendering. Yet, here you have said "is not what I need". What does that mean? What is in your head, that is not in mine? How do you move/copy this knowledge of what you need, from your head to mine? Have you done so? The distinct request was: "Are these correct? If not, please advise which part is incorrect?" The first part was answered. What of the second? In what way were the answers incorrect? In what way was the specification/problem-statement not fulfilled? Have you invested time and effort to help the person who has given up free-time to help you? (see also @Dennis' comments, despite the hours he must have given already) Perhaps that idea of 'taking a break' is needed, so that you can be as helpful as they, to the people who are being helpful to you? > dn?s last section I don?t understand. Again, what you say is understandable, but *why*? If you indicate the part that you don't understand, then we can help your "life long learning"... Has this abrupt dismissal, or rejection, helped you? Helped me? > My problem ist to create a set of unique sublists of 3 items/letters > out of a list of 9 items/letters, later to be extended to sublists of > 4 items/letters out of a list of 16 items/letters. This statement: "3 items/letters out of a list of 9 items/letters" does *not* appear in the original post. Why? Why not? Can we solve one problem at a time, and then move-on to the next? You say "later", which may be the case inside your own head. However, in our context, the original post has us thinking of 'the solution' as four sub-lists of four items - and that problem is not yet solved. An English idiom for causing such confusion is that you are "moving the goal-posts". Generally regarded as either cheating, or at least causing confusion. Do you mean to do this to us? Yes, "three" or "four", I (think I) can see that they are similar problems - strangely enough, this is why I wrote the "definitions" at the beginning of the code, rather than 'burying' the fours and the five as "magic numbers" within the algorithm! Such is a good programming practice, because it enables the very flexibility of sizes and selections, your second problem (may) requires. > I am using letters as items for the sake of readability. Once the code > works letters will be substituted by names of people for the final > goal is to set up ?unique? teams. > > ?Unique? means that other than single items/letters, pairs of > items/letters (pair1, pair2, pair3) can appear only once in all > sublists. A sublist could be understood as a combination of > pair1+pair2+pair3. At the end there should be only 12 sublists > in 4 lists left. Which leaves me baffled. The solution provided-earlier appears to do exactly that. There is no repetition of letter-combinations/team-members' names. (or perhaps I can't see that there are*, and need to be shown...) * am in-recovery from a recent eye operation So, exactly why did you reject it? (and I'm repeating an earlier question) Similarly, and further to my earlier comment about "real world", @Dennis' explanation of 'golfers and schoolgirls' suddenly brought the problem into focus - I remembered staff at our school (many, many, years ago) trying to do exactly this sort of thing - otherwise the strong players would always want to play together, and the unskilled players would end-up (always) on the losing team. Learning to deal with this (what seemed like a frustrating imposition, at the time) taught me that each person can do certain things (and not others), and thus the concept of "the right man for the job" (today: updated to an "equal-opportunities" attitude) Thanks @Dennis! A key to "learning" (which includes learning about/understanding the problem to be solved) is to start from something we know, and then step (one small pace) into the unknown. Thus, we learn something 'new' *and* absorbing it, we also align that knowledge in our minds. For example, to know when we can use it/employ such a solution! Now that I understand that the letters represent names of people, my confidence has grown... Speaking of "solutions". There is often more than one way to solve a problem. Twee example: 1 + 2 == 2 + 1. The idea of 'stepping back' (as above) often enables one to realise that 'there's another way'. As mentioned previously, we could either generate every "combination" and then trim those with unacceptable repetitions, or we could generate unique combinations in the first place. (and maybe there are other approaches) Persisting with a solution (that isn't working) without stopping to consider such, reminds me of another idiom: "flogging a dead horse" - and we wouldn't want to be unkind to animals, would we? So, please take a breath and relax. Then instead of rushing to code/to reply to email, consider what you have been offered, answer questions (first for yourself, and only later for us), and look at the problem and the solution(s) - from all angles... > Sorry for the length of this replay, Marcus. ... Nobody here is 'against' you. Please avoid letting your frustrations communicate the negativity towards your helpers (which has been happening)! Please ask yourself: if someone has taken a chunk of time to consider the problem and (attempt to) offer help, should I give a similar amount of time, care, and respect; in response? -- Regards, =dn _______________________________________________ Tutor maillist - Tutor at python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor From wlfraed at ix.netcom.com Sun Mar 20 10:58:35 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sun, 20 Mar 2022 10:58:35 -0400 Subject: [Tutor] problem solving with lists References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> Message-ID: On Sat, 19 Mar 2022 10:34:00 -0400, Mayo Adams declaimed the following: >So what's wrong with Dennis Bieber's answer? > Probably the same unspoken requirement: it isn't a solution to the SGP (defined by pool size [# of players], group size [which I understand has to divide evenly into the pool -- there are no "bye" weeks], and number of weeks; though the referenced master's thesis uses the notation (# groups, group size, weeks), which makes my (32, 4, 10) => (8, 4, 10); I will be using my notation throughout). That is: 1) for each week in the tournament, each player is assigned to just one group 2) over the course of the tournament, there are no repeated pairs of players By the definition of the strict SGP, this does mean that some player pairs may never appear (each pairing appears 0..1 times in the tournament) A solution to 16/4/1 would be: "abcd" "efgh" "ijkl" "mnop". That meets both #1 and #2. Granted, it also means, for example, that there are 12 pairings with each player that never occur. The goal being to maximize the number of unique pairings. I have seen one paper that proposes a relaxed variant of the SGP. It changes the 0..1 pairing requirement to 1..+; every pairing must occur at least once, but some pairings may occur more than once. The goal here, then, being to minimize the number of repeat pairings. I glanced at some of the master's thesis. Their initial solver library (in SWI-Prolog, running on a MacBook with 2.16GHz Core 2 Duo and 1GB -- depending upon software, a Raspberry-Pi 4B 4GB could probably compete these days ) could solve SGP(32, 4, 7) in 20 minutes, it failed to find a solution for SGP(32, 4, 8) after a week of running. While SGP(32, 4, 10) has been proven to have a solution, the author's improved/modified software [they borrowed an allocator from another system] was incapable of running that case -- managing a solution for SGP(32, 4, 9) [nine weeks, but not ten weeks]. The timings reported in that paper don't include an SGP(16, 4, 5) case: SGP(15, 3, 5) and SGP(24, 4, 5) are shown, taking upwards of 30 seconds when using their initial (unoptimized) solver. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Sun Mar 20 11:25:34 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sun, 20 Mar 2022 11:25:34 -0400 Subject: [Tutor] problem solving with lists References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <5fcd5318-c555-9df7-e9b9-00c0b8efef22@DancesWithMice.info> Message-ID: <6jge3hl6kcnjf6en6f7ga4k560qca95p54@4ax.com> On Sun, 20 Mar 2022 16:35:44 +1300, dn declaimed the following: >So, first criticism is that line 1: > >0 [['a', 'b', 'c', 'd'], ['b', 'c', 'd', 'e'], ['c', 'd', 'e', 'f'], >['d', 'e', 'f', 'g']]the > >should be more like: > >0 [['a', 'b', 'c', 'd'], ['e', 'f', 'g', 'h'], ['i', 'j', 'k', 'l'], >['m', 'n', 'o', 'p']] > >but when it comes to the next list, would > >['a', 'c', 'd', 'e'] > >be unacceptable because although the 'b' has been dropped, the first >three all served-together previously. > As I understand it, that is dead three times over: AC, AD, and CD ... presuming the intent is the strict Social Golfer's Problem (no pairing occurs more than once, but some pairings may never appear). The relaxed SGP (all pairings occur at least once, some pairings may repeat) might accept it -- though some sort of scoring mechanism would be needed (is one repeat each of AC, AD, and CD better or worse than three repeats of just AC?) to rank multiple solutions. I could see a time-consuming inefficient procedure that recurses for each week, and each layer has its own combinations() iterator. For each layer (week) loop obtaining a grouping; verify that the grouping shares no players with other groupings in that same week AND that is does not share any pairs with previously accepted groupings (if it does, reject and draw another grouping; if one runs out of groupings, back up and reject previous layer). Properly done, this also needs to be able to backtrack within each week -- and that may require having an iterator for each position in the solution (and iterators that get reset when that position is rejected and one has to move the previous position). -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Sun Mar 20 12:05:16 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sun, 20 Mar 2022 12:05:16 -0400 Subject: [Tutor] problem solving with lists References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> Message-ID: <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> On Sun, 20 Mar 2022 15:55:27 +0100, declaimed the following: >>all_letters = ?abcdefghijklmnop? >>number_of_lists = 5 >>number_of_sublists per list = 4 >>number_per_sublist = 4 >to >>all_letters = ?abcdefghi? >>number_of_lists = 4 >>number_of_sublists per list = 3 >>number_per_sublist = 3 >to >>all_letters = 'abcdef'. > The discussion would be much easier if you gave real names to all those... (since you later confirm this is the SGP) number of weeks number of groupings players per grouping This avoids all confusion over lists, sublists, etc... "week 1", "group 3", "player 2". >What means "OP", "32 nicely formated LoC", "PEP-8 spacings" ??? > "Original Poster" -- you, the person who started this thread "Lines of Code". Mine isn't as compact, taking 54 lines including blank and comment-only lines "Python Enhancement Proposal" (as I recall). PEP-8 being concerned with how Python code should be formatted -- primarily for inclusion in the Python library, though others have standardized on its recommendations. >seems rather straightforward. But for now I cannot see yet how to use it to remove all non-uniques sublists/teams. You don't "remove" them! "Remove" implies you already placed a grouping into the solution and now are checking for if they meet the constraints. Instead you check the constraints for a candidate grouping BEFORE ADDING it to the solution. >SPG exactly describes my goal. The SGP is not a week-end programming exercise. It is the subject of multiple university research papers in developing/optimizing constraint-based solver algorithms. A one-time pass over the output of .combinations() will not be sufficient (especially as the criteria per week that no player appears more than once means going from "abcd" [the first foursome .combinations() spits out] has to skip all other groups that begin with "a", "b", "c" or "d" -- and you can't get them back later. At a minimum you need to restart the .combinations() on each week. You'll really need to implement some way of backtracking ("we ran out of groupings without being able to place one in 'this' position, back up and change the previously placed grouping and start over on this position") -- it is possible you might have to back all the way up to the first grouping and try a different value for it. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From PythonList at DancesWithMice.info Sun Mar 20 13:47:32 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 21 Mar 2022 06:47:32 +1300 Subject: [Tutor] identifying if a path is heading into a zip file - windows In-Reply-To: <9ED85EBF-024C-46CC-B46A-1D8433647A4F@yahoo.co.uk> References: <9ED85EBF-024C-46CC-B46A-1D8433647A4F@yahoo.co.uk> Message-ID: <24afeb3d-4061-358f-11cb-614e3d03b98b@DancesWithMice.info> On 20/03/2022 22.02, Alan Gauld via Tutor wrote: >> Take a second path: >> >> path= 'c:\my folder\a file.zip\a folder in the zip' >> >> Is there a way for python to know, without me physically breaking it down, that that path is in a zip file? >> > I don?t think so, the standard library tools simply analyse the text. > You would need to write a function that traversed the path checking for isfile() Can't say I've ever tried this. (nor do I use MS-Windows) You rightly suggest that file.zip\archive_folder might involve a zipped-archive, but that zipped.tie\single_use would (possibly?probably) not. There may be a reliance on 'good practice'. IIRC, just because a file has the 'extension' ".zip" is an indication of its purpose; but not a definition or restriction. Thus "long.zip" may not be an archive, but "monday.backup" is. YMMV! Referring to the second-half of the question: (and it may vary according to OpSys in-use!) can we assume that the back-slash (\) is a character that may *not* be used within a file-name? - is only used within paths to separate folder- and file-names? Putting it all together, find()-ing the following sub-strings in "path": - "zip" would not be adequate, eg "zipped" - ".zip" similarly, eg "tie.zip.button" - might ".zip\" do the trick? -- Regards, =dn From wlfraed at ix.netcom.com Sun Mar 20 15:21:41 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sun, 20 Mar 2022 15:21:41 -0400 Subject: [Tutor] identifying if a path is heading into a zip file - windows References: Message-ID: On Sun, 20 Mar 2022 02:13:52 +0000, Nathan Smith declaimed the following: >path= 'c:\my folder\a file.zip\a folder in the zip' > Just a comment... "\a" is a control character . For literals, easier to use / rather than \ -- Windows accepts either. If you really need it, run os.path.normpath() on it. > >Is there a way for python to know, without me physically breaking it >down, that that path is in a zip file? > Other than traversing the path components -- no. Especially if some path components might be symbolic links and/or mount points Something like (untested -- may need work to handle the end-of-path case): import os.path def embedded_file(aPath): ef = False while True: aPath = os.path.dirname(aPath) if aPath: if os.path.isfile(aPath): ef = True break else: break return ef -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From cs at cskk.id.au Sun Mar 20 17:54:16 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Mon, 21 Mar 2022 08:54:16 +1100 Subject: [Tutor] identifying if a path is heading into a zip file - windows In-Reply-To: References: Message-ID: On 20Mar2022 02:13, nathan tech wrote: >Take a path, for instance: > >path="c:\my folder" > >?os.path.isdir(path) = True > >Take a second path: > >path= 'c:\my folder\a file.zip\a folder in the zip' > >Is there a way for python to know, without me physically breaking it >down, that that path is in a zip file? > >For instance, a way for it to know it's dealing with a zip archive >file, and not just a folder with .zip in the name? Well, I would start by just `os.stat(path)`. Since a path entering a zip file is meaningless, because to the OS it the zip is just a file, and therefore has no children) the stat should fail. So if the stat succeeds, you know the "a file.zip" is in fact a folder. If the stat fails, _then_ you need to exampine the path components individually with os.path.isfile. And once you hi a file-ending-in-.zip, maybe further examine it with the `zip` module to see if it really is a zip file. And if it contains "a folder in the zip". Cheers, Cameron Simpson From PythonList at DancesWithMice.info Mon Mar 21 01:25:27 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 21 Mar 2022 18:25:27 +1300 Subject: [Tutor] problem solving with lists In-Reply-To: <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> Message-ID: On 21/03/2022 03.55, marcus.luetolf at bluewin.ch wrote: > Hello Experts and Helpers, > a lot to answer: > > yes, I am multi-langual. I should have said "And other ...............knowledge of other programming languages but python. > I have worked several online courses in python (coursera, edx etc.) over the past years, including most of Alan Gould's > online tutorial. Therfore, a am still a beginner in python but not a learning beginner. and a good idea is never to say 'this is just the same as in C' (or whichever language), but to think: 'this is how we do it in Python'! For example, Tok Pisin, a trading-language in Papua New Guinea (and other places) 'borrows' many words from English and German. Thus "brata", "bruder", and "brother". In this case, I'm unlikely to think that the English word will do; but if I memorise it according to some sort of logic like "it's close to the German 'original'" I will fail (even if such pronunciation is likely to be understood). NB computers are neither as friendly nor as forgiving as Papua New Guineans! > My "real world problem" to build teams of unique composition ist exactly the same as to build unique > sublists with letters. The latter beeing much easier do handle (typing(errors), readabilty etc.) to me. > My goal was to explain my problem, algorithm, solution steps as precise as possible to avoid confusion. > I might have not succeeded. See @Dennis' comment on choosing meaningful names/identifiers. I'm happy with the letters A through P in place of peoples' names - keeps things short, until we're ready to 'go live' and work with 'real data'! > dn's 'Results obtained:' (mail 20/03/2022 15.07) were altered in his mail of 19.03.2022 04:03 resulting in > the exclusion of shared pairs, what was required. But there was no code offered. The reason at the time was the suspicion that it is a homework assignment. You tell me this is not. However, the same learning/teacher aspects may still apply. If someone gives you the code/answer, then have you learned to solve the problem? This is why at Tutor we try to lead you to the answer. In this case, I'm not convinced that I (be relied upon to) lead you anywhere! The first step to writing any program[me] is to understand the problem. I suspect we are both 'stuck' at this point - but better to speak only for myself. (see current (?improved) attempt in separate message) -- Regards, =dn From PythonList at DancesWithMice.info Mon Mar 21 01:34:40 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 21 Mar 2022 18:34:40 +1300 Subject: [Tutor] problem solving with lists In-Reply-To: <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> Message-ID: Have I managed to understand the problem, this time? On 21/03/2022 05.05, Dennis Lee Bieber wrote: > On Sun, 20 Mar 2022 15:55:27 +0100, declaimed > the following: > >>> all_letters = ?abcdefghijklmnop? >>> number_of_lists = 5 >>> number_of_sublists per list = 4 >>> number_per_sublist = 4 >> to >>> all_letters = ?abcdefghi? >>> number_of_lists = 4 >>> number_of_sublists per list = 3 >>> number_per_sublist = 3 >> to >>> all_letters = 'abcdef'. > The discussion would be much easier if you gave real names to all > those... (since you later confirm this is the SGP) > > number of weeks > number of groupings > players per grouping > > This avoids all confusion over lists, sublists, etc... "week 1", "group 3", > "player 2". How about these as 'meaningful names': players = "abcdefghijklmnop" number_of_weeks = 5 number_of_groupings = 4 players_per_grouping = 4 >> seems rather straightforward. But for now I cannot see yet how to use it to remove all non-uniques sublists/teams. > You don't "remove" them! "Remove" implies you already placed a grouping > into the solution and now are checking for if they meet the constraints. > Instead you check the constraints for a candidate grouping BEFORE ADDING it > to the solution. Yes, the more 'constructivist' approach is probably easier - it is easier to 'see' as things are added to the solution, than it is to keep track of what was there 'before' when subtracting/pruning. YMMV! This solution keeps track of each player's history, ie if player-a is grouped with players 'b', 'c', and 'd' in the first game, then: player_history['a'] == {'b','c','d'} and in the second game (s)he is grouped with players 'e', 'i', 'm'; then it becomes: player_history['a'] == {'b','c','d', 'e', 'i', 'm'} and so-on (see output-report, below) The player's history is used whenever (s)he is 'selected' to ensure that there is no repetition of anyone who has participated in that player's previous groupings. >> SPG exactly describes my goal. > > The SGP is not a week-end programming exercise. It is the subject of > multiple university research papers in developing/optimizing > constraint-based solver algorithms. > > A one-time pass over the output of .combinations() will not be > sufficient (especially as the criteria per week that no player appears more > than once means going from "abcd" [the first foursome .combinations() spits > out] has to skip all other groups that begin with "a", "b", "c" or "d" -- > and you can't get them back later. At a minimum you need to restart the > .combinations() on each week. You'll really need to implement some way of > backtracking ("we ran out of groupings without being able to place one ink > 'this' position, back up and change the previously placed grouping and > start over on this position") -- it is possible you might have to back all > the way up to the first grouping and try a different value for it. Which all serves to make me think that I have yet to grasp the full-measure of the problem! Herewith the output-report. The "draw" for each week (who is playing whom during that week) appears as four Python-lists under the week's sub-title. (the 'real' output) Inspecting the "draw", one can visually-check that each player only plays against everyone else, once - and only once - and exactly once (per @Dennis' comment about byes - no, none of them necessary with this combination of definitions)! The 16-player listing (debug-print) underneath each week's draw, shows how the program[me] keeps a record of which players each player has played to-date - thus after each week's game it extends by another three players' names/letters. Finally, by the end of the league/tournament (whatever you want to call the five-weeks of play, per definitions), every player is shown to have played against every other player:- /usr/bin/python3 /home/dn/Projects/Experiments/marcus.py Draw for 5 week league Draw for week 1 ['a', 'b', 'c', 'd'] ['e', 'f', 'g', 'h'] ['i', 'j', 'k', 'l'] ['m', 'n', 'o', 'p'] a ['a', 'b', 'c', 'd'] b ['a', 'b', 'c', 'd'] c ['a', 'b', 'c', 'd'] d ['a', 'b', 'c', 'd'] e ['e', 'f', 'g', 'h'] f ['e', 'f', 'g', 'h'] g ['e', 'f', 'g', 'h'] h ['e', 'f', 'g', 'h'] i ['i', 'j', 'k', 'l'] j ['i', 'j', 'k', 'l'] k ['i', 'j', 'k', 'l'] l ['i', 'j', 'k', 'l'] m ['m', 'n', 'o', 'p'] n ['m', 'n', 'o', 'p'] o ['m', 'n', 'o', 'p'] p ['m', 'n', 'o', 'p'] Draw for week 2 ['a', 'e', 'i', 'm'] ['b', 'f', 'j', 'n'] ['c', 'g', 'k', 'o'] ['d', 'h', 'l', 'p'] a ['a', 'b', 'c', 'd', 'e', 'i', 'm'] b ['a', 'b', 'c', 'd', 'f', 'j', 'n'] c ['a', 'b', 'c', 'd', 'g', 'k', 'o'] d ['a', 'b', 'c', 'd', 'h', 'l', 'p'] e ['a', 'e', 'f', 'g', 'h', 'i', 'm'] f ['b', 'e', 'f', 'g', 'h', 'j', 'n'] g ['c', 'e', 'f', 'g', 'h', 'k', 'o'] h ['d', 'e', 'f', 'g', 'h', 'l', 'p'] i ['a', 'e', 'i', 'j', 'k', 'l', 'm'] j ['b', 'f', 'i', 'j', 'k', 'l', 'n'] k ['c', 'g', 'i', 'j', 'k', 'l', 'o'] l ['d', 'h', 'i', 'j', 'k', 'l', 'p'] m ['a', 'e', 'i', 'm', 'n', 'o', 'p'] n ['b', 'f', 'j', 'm', 'n', 'o', 'p'] o ['c', 'g', 'k', 'm', 'n', 'o', 'p'] p ['d', 'h', 'l', 'm', 'n', 'o', 'p'] Draw for week 3 ['a', 'f', 'k', 'p'] ['b', 'e', 'l', 'o'] ['c', 'h', 'i', 'n'] ['d', 'g', 'j', 'm'] a ['a', 'b', 'c', 'd', 'e', 'f', 'i', 'k', 'm', 'p'] b ['a', 'b', 'c', 'd', 'e', 'f', 'j', 'l', 'n', 'o'] c ['a', 'b', 'c', 'd', 'g', 'h', 'i', 'k', 'n', 'o'] d ['a', 'b', 'c', 'd', 'g', 'h', 'j', 'l', 'm', 'p'] e ['a', 'b', 'e', 'f', 'g', 'h', 'i', 'l', 'm', 'o'] f ['a', 'b', 'e', 'f', 'g', 'h', 'j', 'k', 'n', 'p'] g ['c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'o'] h ['c', 'd', 'e', 'f', 'g', 'h', 'i', 'l', 'n', 'p'] i ['a', 'c', 'e', 'h', 'i', 'j', 'k', 'l', 'm', 'n'] j ['b', 'd', 'f', 'g', 'i', 'j', 'k', 'l', 'm', 'n'] k ['a', 'c', 'f', 'g', 'i', 'j', 'k', 'l', 'o', 'p'] l ['b', 'd', 'e', 'h', 'i', 'j', 'k', 'l', 'o', 'p'] m ['a', 'd', 'e', 'g', 'i', 'j', 'm', 'n', 'o', 'p'] n ['b', 'c', 'f', 'h', 'i', 'j', 'm', 'n', 'o', 'p'] o ['b', 'c', 'e', 'g', 'k', 'l', 'm', 'n', 'o', 'p'] p ['a', 'd', 'f', 'h', 'k', 'l', 'm', 'n', 'o', 'p'] Draw for week 4 ['a', 'g', 'l', 'n'] ['b', 'h', 'k', 'm'] ['c', 'e', 'j', 'p'] ['d', 'f', 'i', 'o'] a ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'i', 'k', 'l', 'm', 'n', 'p'] b ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'j', 'k', 'l', 'm', 'n', 'o'] c ['a', 'b', 'c', 'd', 'e', 'g', 'h', 'i', 'j', 'k', 'n', 'o', 'p'] d ['a', 'b', 'c', 'd', 'f', 'g', 'h', 'i', 'j', 'l', 'm', 'o', 'p'] e ['a', 'b', 'c', 'e', 'f', 'g', 'h', 'i', 'j', 'l', 'm', 'o', 'p'] f ['a', 'b', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'n', 'o', 'p'] g ['a', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'o'] h ['b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k', 'l', 'm', 'n', 'p'] i ['a', 'c', 'd', 'e', 'f', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'] j ['b', 'c', 'd', 'e', 'f', 'g', 'i', 'j', 'k', 'l', 'm', 'n', 'p'] k ['a', 'b', 'c', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'o', 'p'] l ['a', 'b', 'd', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'p'] m ['a', 'b', 'd', 'e', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'o', 'p'] n ['a', 'b', 'c', 'f', 'g', 'h', 'i', 'j', 'l', 'm', 'n', 'o', 'p'] o ['b', 'c', 'd', 'e', 'f', 'g', 'i', 'k', 'l', 'm', 'n', 'o', 'p'] p ['a', 'c', 'd', 'e', 'f', 'h', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] Draw for week 5 ['a', 'h', 'j', 'o'] ['b', 'g', 'i', 'p'] ['c', 'f', 'l', 'm'] ['d', 'e', 'k', 'n'] a ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] b ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] c ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] d ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] e ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] f ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] g ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] h ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] i ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] j ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] k ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] l ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] m ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] n ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] o ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] p ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] Process finished with exit code 0 Is this what we're trying to achieve? -- Regards, =dn From PythonList at DancesWithMice.info Mon Mar 21 06:13:41 2022 From: PythonList at DancesWithMice.info (dn) Date: Mon, 21 Mar 2022 23:13:41 +1300 Subject: [Tutor] problem solving with lists In-Reply-To: <007a01d83d00$ce757c50$6b6074f0$@bluewin.ch> References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> <007a01d83d00$ce757c50$6b6074f0$@bluewin.ch> Message-ID: On 21/03/2022 21.51, marcus.luetolf at bluewin.ch wrote: > ...yes, the weekly Draws below are exactly what I have in mind !!! > And I realised earlier that "I asked the wrong questions". But with your > Cooments about the solution I think I can find a solution myself. > It was never my intention to let tutor do my "homework", I had learned nothing. > Thanks, Marcus. Excellent news! Keep going! (here) Follow earlier suggestions of defining meaningful terminology by first writing (specifying) the problem, as completely as you can. All those detailed clauses, as we say in English: "the if-s, the but-s, and the maybe-s" are the details which cause trips and stumbles. A lot of programmers rush to start coding. The above is well-worth spending the time - and if the spec[ification] has come from someone else (as it would in a commercial environment), this is where we find, as early as possible, that the client hasn't given us the full-story! As you say, the key to it all is to ask the 'right' questions and document the requirements and 'rules'. Once the problem is clearly understood, we can start looking for solutions. Often there is more than one, and certainly more than one way to approach building a solution. These are the major steps of "program[me] design". Again, it is worth checking and re-checking, because errors caught early in the development process are cheaper (time and/or $) to fix, than those not realised until later. Thus, the completed work described earlier was a second, and longer, version of the first - so a complete re-write became necessary because I did not understand what was needed! Now you understand why there was evidence of frustration in the way people were replying to you! Next try to break-up the chosen solution into stages or phases. In this case, I think of a League (or competition) which will take (number_of_weeks) five weeks before all 'unique' combinations of players can be played. Each week requires its own "draw", which will consist of (number_of_groupings) four groups of players. Each group of players will consist of (players_per_grouping) four players - who have never played with each-other before (in this league/competition). You can see that the overall solution consists of sub-solutions to sub-problems. It's a bit like those inter-locking Russian dolls, or (?Swiss) chocolates with a center and multiple layers/flavors inside a hard chocolate coating. We also refer to it as like an onion. This approach to problem-solving is called "stepwise decomposition" (or "- refinement). It is the process of dividing a large problem into smaller problems, and those into smaller... until the small problem is one that is easy to solve. The beauty of this is that if you have a correct and sensible design (easily said, not so easily done!), it should be possible to write and test (or 'prove') each 'unit' or sub-solution of the code, by itself - which is a good deal easier than trying to test the whole 'onion' and not being sure where some failure or error is caused within the mass of code! What happens when you have to cut-up a (real) onion? I tend to code each 'layer' as a function. Indeed after choosing the name of the function (and writing the def ... line), I'll add a docstring which is basically that section of the 'design' (from earlier). I'll repeat this until the whole problem has been covered. Only then, do I sit down to start writing code for the smallest of the sub-solutions (or, the inner-most layer of the onion/chocolate). Now, to help you on your way, here are a few other data-structures which I used: weekly_draws = list() - to hold the [five] weeks' draws - perhaps only necessary if you're going to do something with this data (I was only printing it out) player_history = { player:{ player } for player in players } - to hold the set of players who this player has previously played - rather than complicating loop-controls (or maybe adding lots of one-time if-conditions) within the code, it seemed easier to initialise each player's set with him-/her-self - after all, under the 'rules' you cannot play someone you've already played, nor can you play yourself. (two 'rules' for the price of one!) - this 'one-liner' code-construction is called a "set-comprehension" and I very rarely see/use one - whereas their close-relatives, "list-comprehensions", are very common. If you'd like to post your sub-solutions (text-design, plus Python-code), we'll be happy to help you along... -- Regards, =dn From marcus.luetolf at bluewin.ch Mon Mar 21 12:37:20 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Mon, 21 Mar 2022 17:37:20 +0100 Subject: [Tutor] problem solving with lists In-Reply-To: References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> <007a01d83d00$ce757c50$6b6074f0$@bluewin.ch> Message-ID: <000101d83d41$efb14390$cf13cab0$@bluewin.ch> I will do. Extremly valuable and motivating comments !!! I am surprised why I am getting so much support from you, Experts. But I need a break. Many thanks again, til later, Marcus. -----Urspr?ngliche Nachricht----- Von: Tutor Im Auftrag von dn Gesendet: Montag, 21. M?rz 2022 11:14 An: tutor at python.orgfrom you, Experts. Betreff: Re: [Tutor] problem solving with lists On 21/03/2022 21.51, marcus.luetolf at bluewin.ch wrote: > ...yes, the weekly Draws below are exactly what I have in mind !!! > And I realised earlier that "I asked ink I can find a solution myself. > It was never my intention to let tutor do my "homework", I had learned nothing. > Thanks, Marcus. Excellent news! Keep going! (here) Follow earlier suggestions of defining meaningful terminology by first writing (specifying) the problem, as completely as you can. All those detailed clauses, as we say in English: "the if-s, the but-s, and the maybe-s" are the details which cause trips and stumbles. A lot of programmers rush to start coding. The above is well-worth spending the time - and if the spec[ification] has come from someone else (as it would in a commercial environment), this is where we find, as early as possible, that the client hasn't given us the full-story! As you say, the key to it all is to ask the 'right' questions and document the requirements and 'rules'. Once the problem is clearly understood, we can start looking for solutions. Often there is more than one, and certainly more than one way to approach building a solution. These are the major steps of "program[me] design". Again, it is worth checking and re-checking, because errors caught early in the development process are cheaper (time and/or $) to fix, than those not realised until later. Thus, the completed work described earlier was a second, and longer, version of the first - so a complete re-write became necessary because I did not understand what was needed! Now you understand why there was evidence of frustration in the way people were replying to you! Next try to break-up the chosen solution into stages or phases. In this case, I think of a League (or competition) which will take (number_of_weeks) five weeks before all 'unique' combinations of players can be played. Each week requires its own "draw", which will consist of (number_of_groupings) four groups of players. Each group of players will consist of (players_per_grouping) four players - who have never played with each-other before (in this league/competition). You can see that the overall solution consists of sub-solutions to sub-problems. It's a bit like those inter-locking Russian dolls, or (?Swiss) chocolates with a center and multiple layers/flavors inside a hard chocolate coating. We also refer to it as like an onion. This approach to problem-solving is called "stepwise decomposition" (or "- refinement). It is the process of dividing a large problem into smaller problems, and those into smaller... until the small problem is one that is easy to solve. The beauty of this is that if you have a correct and sensible design (easily said, not so easily done!), it should be possible to write and test (or 'prove') each 'unit' or sub-solution of the code, by itself - which is a good deal easier than trying to test the whole 'onion' and not being sure where some failure or error is caused within the mass of code! What happens when you have to cut-up a (real) onion? I tend to code each 'layer' as a function. Indeed after choosing the name of the function (and writing the def ... line), I'll add a docstring which is basically that section of the 'design' (from earlier). I'll repeat this until the whole problem has been covered. Only then, do I sit down to start writing code for the smallest of the sub-solutions (or, the inner-most layer of the onion/chocolate). Now, to help you on your way, here are a few other data-structures which I used: weekly_draws = list() - to hold the [five] weeks' draws - perhaps only necessary if you're going to do something with this data (I was only printing it out) player_history = { player:{ player } for player in players } - to hold the set of players who this player has previously played - rather than complicating loop-controls (or maybe adding lots of one-time if-conditions) within the code, it seemed easier to initialise each player's set with him-/her-self - after all, under the 'rules' you cannot play someone you've already played, nor can you play yourself. (two 'rules' for the price of one!) - this 'one-liner' code-construction is called a "set-comprehension" and I very rarely see/use one - whereas their close-relatives, "list-comprehensions", are very common. If you'd like to post your sub-solutions (text-design, plus Python-code), we'll be happy to help you along... -- Regards, =dn _______________________________________________ Tutor maillist - Tutor at python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor From wlfraed at ix.netcom.com Mon Mar 21 12:38:06 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 21 Mar 2022 12:38:06 -0400 Subject: [Tutor] problem solving with lists References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> Message-ID: On Mon, 21 Mar 2022 18:34:40 +1300, dn declaimed the following: >Have I managed to understand the problem, this time? > Asking me? Everything I understand about it is based upon things like Wikipedia and research papers... >How about these as 'meaningful names': > >players = "abcdefghijklmnop" >number_of_weeks = 5 >number_of_groupings = 4 >players_per_grouping = 4 > I stopped short of going the full OO approach: class Schedule: class Week: class Group: maybe (if one doesn't mind the tedium of initializing the alpha placeholder with actual player names) class Player: aschedule = Schedule(group_size, number_groups, number_weeks) leading to things like aschedule.week[1].group[3].player[2] Keeping each group as Set of player probably makes the constraint checking easier. Technically, the groups in each week are also Set ({"abcd", "efgh", "ijkl", "mnop"} and {"ijkl", "pnom", "ehfg", "abcd"} are the same groups). And the weeks in the schedule are properly Set, as rearranging them doesn't change the solution (the same players are paired against each other at some point). >Which all serves to make me think that I have yet to grasp the >full-measure of the problem! For all I know, the OP has cherry-picked cases with exactly one complete solution. The generalized problem may not have a solution (at the extreme, if one specifies too many weeks, one has duplicate pairings; too few weeks, and one will have failed to maximize "socialization" by missing groupings). -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Mon Mar 21 15:14:53 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Mon, 21 Mar 2022 15:14:53 -0400 Subject: [Tutor] problem solving with lists References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> Message-ID: On Mon, 21 Mar 2022 18:34:40 +1300, dn declaimed the following: >Which all serves to make me think that I have yet to grasp the >full-measure of the problem! > Is your solution generalized enough to handle the classic SGP test? 8 groups of 4 players over 10 weeks According to the research, there IS a solution to this. I've spent the afternoon hacking my previous code to work in loops of weeks groups in week using set intersection as the filter (within week, intersection between groups must return empty sets -- no duplicate players) and then against prior weeks (intersection must not be greater than 1; 2+ indicates a repeated pair of players). The 4 4 6 case is an expected result. C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py *** Usage: SGP.py number_of_groups group_size number_of_weeks C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 4 4 1 Week # 0: abcd efgh ijkl mnop C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 4 4 2 Week # 0: abcd efgh ijkl mnop Week # 1: aeim bfjn cgko dhlp C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 4 4 3 Week # 0: abcd efgh ijkl mnop Week # 1: aeim bfjn cgko dhlp Week # 2: afkp belo chin dgjm C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 4 4 4 Week # 0: abcd efgh ijkl mnop Week # 1: aeim bfjn cgko dhlp Week # 2: afkp belo chin dgjm Week # 3: agln bhkm cejp dfio C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 4 4 5 Week # 0: abcd efgh ijkl mnop Week # 1: aeim bfjn cgko dhlp Week # 2: afkp belo chin dgjm Week # 3: agln bhkm cejp dfio Week # 4: ahjo bgip cflm dekn C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 4 4 6 ***** NO SOLUTION FOUND ***** However, for the classic problem (remember, a solution IS known for 8 4 10), I get... C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 8 4 1 Week # 0: abcd efgh ijkl mnop qrst uvwx AByz CDEF C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 8 4 2 Week # 0: abcd efgh ijkl mnop qrst uvwx AByz CDEF Week # 1: aeim bfjn cgko dhlp Cquy Drvz AEsw BFtx C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 8 4 3 Week # 0: abcd efgh ijkl mnop qrst uvwx AByz CDEF Week # 1: aeim bfjn cgko dhlp Cquy Drvz AEsw BFtx Week # 2: afkp belo chin dgjm AFqv BEru Dsxy Ctwz C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 8 4 4 Week # 0: abcd efgh ijkl mnop qrst uvwx AByz CDEF Week # 1: aeim bfjn cgko dhlp Cquy Drvz AEsw BFtx Week # 2: afkp belo chin dgjm AFqv BEru Dsxy Ctwz Week # 3: agln bhkm cejp dfio BDqw ACrx Fsuz Etvy C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 8 4 5 Week # 0: abcd efgh ijkl mnop qrst uvwx AByz CDEF Week # 1: aeim bfjn cgko dhlp Cquy Drvz AEsw BFtx Week # 2: afkp belo chin dgjm AFqv BEru Dsxy Ctwz Week # 3: agln bhkm cejp dfio BDqw ACrx Fsuz Etvy Week # 4: ahjo bgip cflm dekn Eqxz Frwy BCsv ADtu C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 8 4 6 ***** NO SOLUTION FOUND ***** C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 8 4 7 ***** NO SOLUTION FOUND ***** C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 8 4 8 ***** NO SOLUTION FOUND ***** C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 8 4 9 ***** NO SOLUTION FOUND ***** C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py 8 4 10 ***** NO SOLUTION FOUND ***** C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP> ... so it is apparent that my current version is missing some aspect. I'm not thinking of adding telemetry/debug to find out where the higher cases are triggering rejects. "No solution found" is what I dump when itertools.combinations() runs out of values (StopIteration exception). I restart .combination() for each week in order to reclaim combinations that were skipped in the previous week. While "1 week" is no problem (I can run 15 groups of 4 for 1 week) my program fails to even get a second week of 5 groups of 4 I have no back-tracking in place, beyond the restart of the generator on each week. I suspect the next attempt -- should I get ambitious -- is to put a generator on each group in each week (and save them as some structure), to allow for back-tracking. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From PythonList at DancesWithMice.info Mon Mar 21 16:47:16 2022 From: PythonList at DancesWithMice.info (dn) Date: Tue, 22 Mar 2022 09:47:16 +1300 Subject: [Tutor] problem solving with lists In-Reply-To: References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> Message-ID: On 22/03/2022 05.38, Dennis Lee Bieber wrote: > On Mon, 21 Mar 2022 18:34:40 +1300, dn > declaimed the following: > >> Have I managed to understand the problem, this time? >> > Asking me? No, but... > I stopped short of going the full OO approach: > > class Schedule: > > class Week: > > class Group: > > maybe (if one doesn't mind the tedium of initializing the alpha placeholder > with actual player names) > class Player: > > aschedule = Schedule(group_size, number_groups, number_weeks) > > leading to things like > > aschedule.week[1].group[3].player[2] > > Keeping each group as Set of player probably makes the constraint > checking easier. Technically, the groups in each week are also Set > ({"abcd", "efgh", "ijkl", "mnop"} and {"ijkl", "pnom", "ehfg", "abcd"} are > the same groups). And the weeks in the schedule are properly Set, as > rearranging them doesn't change the solution (the same players are paired > against each other at some point). Each constraint/controlling-factor only has one~three 'attributes', so I happily used built-in data-constructs. More "modular" or "structured" than OO... >> Which all serves to make me think that I have yet to grasp the >> full-measure of the problem! > > For all I know, the OP has cherry-picked cases with exactly one > complete solution. The generalized problem may not have a solution (at the > extreme, if one specifies too many weeks, one has duplicate pairings; too > few weeks, and one will have failed to maximize "socialization" by missing > groupings). More on this in another msg, but yes the 16-5-4-4 is a mathematically-elegant combination - as said earlier: no need for 'byes' which would have added complication! Someone went to a lot of trouble to tailor a 'toy example' that would 'come out' easily. Salute! -- Regards, =dn From PythonList at DancesWithMice.info Mon Mar 21 17:54:28 2022 From: PythonList at DancesWithMice.info (dn) Date: Tue, 22 Mar 2022 10:54:28 +1300 Subject: [Tutor] problem solving with lists In-Reply-To: References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> Message-ID: <58b3690c-4173-8ffa-5d57-6490dea20309@DancesWithMice.info> On 22/03/2022 08.14, Dennis Lee Bieber wrote: > On Mon, 21 Mar 2022 18:34:40 +1300, dn > declaimed the following: > >> Which all serves to make me think that I have yet to grasp the >> full-measure of the problem! >> > > Is your solution generalized enough to handle the classic SGP test? > > 8 groups of 4 players over 10 weeks Sadly, no! NB the number of players in the tournament/available to draw, is an important component! My 'solution' is relatively brute-force, in that it lacks any tactical-component to the selection process - in fact it is close to alphabetical if it can be described as having any intent. Thus the above configuration fails after week 5/the fifth iteration. By this stage, player-a has played everyone from 'b' to 'p'. Thus, the next logical 'pairing' would be to group 'a' with 'q'. However, in the mean-time 'q' has played everyone from 'r' to 'F'. So, 'stalemate'! > According to the research, there IS a solution to this. > > I've spent the afternoon hacking my previous code to work in loops of > weeks > groups in week > using set intersection as the filter (within week, intersection between > groups must return empty sets -- no duplicate players) and then against > prior weeks (intersection must not be greater than 1; 2+ indicates a > repeated pair of players). The 4 4 6 case is an expected result. Generalising the problem, takes it way-beyond the level of an intermediate~advanced (Python) programming course (IMHO). It requires some higher-order math, rather than 'just Python'! If you told me this was a post-grad level assignment in a math stream, I'd believe you! Certainly it's beyond (my impression of) the OP's level (and interest). As mentioned, my 'solution' (to @marcus) was simplistic and basic. It doesn't even consider back-tracking and is limited to one 'strategy' (ie selection based upon not much more than blind-luck). Beyond the four definitions: globals(): player_history is a dict (key is player-name) of sets (previous team-mates?opponents) * yes, I know about the perils of globals! Referring to discussion of OO, perhaps making the league/tournament an object which contains all the specifications would have the advantage of avoiding globals... arrange_draws_for_league() could assemble a list of weekly draws/groups, but as the spec seemed to only require a print-out, I refactored it 'out'. arrange_this_weeks_groups() has two constructs: - this_weeks_draw which a list to be filled with the groups of (4) players (itself a list, returned from the inner function...) - players_already_drawn is the set of players already placed in this_weeks_draw Hence the (inner) function find_undrawn_player() which serially-searches the list of players (string of letters) to find a player with which to 'seed' the next player-group. [here is where the simplicity of rote (as a tactic) reduces generalisation!] I guess these two constructs might be combined, but I wasn't sure if the order of players in the draw might have some significance; whereas processing is faster and (the thinking) easier using sets (where 'order' has no meaning). NB both start the 'week' empty, which is why player-a will always be the first player, in the first group, every week - again a gross simplification and referring to previous criticism, may not be 'fair' if the order of the players within a group (or of the groups within a draw) has particular significance! arrange_group_to_play() is the 'inner loop'/inner layer of the 'onion' - grouping is the set of players who will play together 'this time' and seeded by the player selected above - players_played starts life as a copy* of the seed-player's player_history, and is extended by the history of each player as (s)he is added to the group. Thus, it informs the mechanism ensuring that no player repeats a meeting with any other player in the competition. * Yes, whilst grouping is a set, to ease the load on my eyes, I always sort before printing. What a cheat! So, whilst the solution keeps 'player history', it makes no record of attempts to solve, and thus there's no opportunity to back-track. Perhaps instead of the first combination being 'a' and 'b' (simplistic approach), if 'a' and 'p' (say) were tried first, might that lead to an actual solution that was not otherwise possible? At which point I say: "stop the world - I want to get off"! If you'd like a copy of this code-solution* (off-list), then will be happy to send - but I think you're an order of magnitude beyond my achievement to-date (and my interest for the future)! * 69 LoC, nicely commented, written for 'intermediate level' coders, blah-blah, puff-puff, including debug-prints for the player histories. > C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py > > *** Usage: SGP.py number_of_groups group_size number_of_weeks Another point-of-difference is that I perhaps (mis-)understood that the specs included a requirement that every player play every other player, at some stage during the league/tournament. In reality the number_of_weeks specification is the code's control. Many of these (snipped) combinations of league-definitions you've attempted don't meet that spec - hence I've not tried. Apologies... (see comment elsewhere about the elegance and careful selection of definitions in the 'assignment') > I have no back-tracking in place, beyond the restart of the generator > on each week. I suspect the next attempt -- should I get ambitious -- is to > put a generator on each group in each week (and save them as some > structure), to allow for back-tracking. "You're a braver man than I [am], Gunga Din"! -- Regards, =dn From marcus.luetolf at bluewin.ch Tue Mar 22 07:04:11 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Tue, 22 Mar 2022 12:04:11 +0100 Subject: [Tutor] problem solving with lists In-Reply-To: <58b3690c-4173-8ffa-5d57-6490dea20309@DancesWithMice.info> References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> <58b3690c-4173-8ffa-5d57-6490dea20309@DancesWithMice.info> Message-ID: <008001d83ddc$8fcdac70$af690550$@bluewin.ch> If I may make a comment: Starting off with the real task to provide a startlist for next week: 16 players, teams of 4 players, 5 days to play, 4 teams a day , each player playes once with each other, I reckoned I could find a solution with these particular "parameters" using python instead of trial and error on an Excel sheet (and never accomplish the task). I then found that I could define other particular parameters: n = number of players r = numbert of players in a team if (n-1)%(r-1) == 0 then (n-1)/(r-1) = p = numbers of days played. A couple of years ago I tried to find a generalized solution for variable parameters and posted my attempts on tutor. At that time I was refered to a mathematics forum for it was felt to be a mathematical problem of very high order. Regards, Marcus. -----Urspr?ngliche Nachricht----- Von: Tutor Im Auftrag von dn Gesendet: Montag, 21. M?rz 2022 22:54 An: tutor at python.org Betreff: Re: [Tutor] problem solving with lists On 22/03/2022 08.14, Dennis Lee Bieber wrote: > On Mon, 21 Mar 2022 18:34:40 +1300, dn > declaimed the following: > >> Which all serves to make me think that I have yet to grasp the >> full-measure of the problem! >> > > Is your solution generalized enough to handle the classic SGP test? > > 8 groups of 4 players over 10 weeks Sadly, no! NB the number of players in the tournament/available to draw, is an important component! My 'solution' is relatively brute-force, in that it lacks any tactical-component to the selection process - in fact it is close to alphabetical if it can be described as having any intent. Thus the above configuration fails after week 5/the fifth iteration. By this stage, player-a has played everyone from 'b' to 'p'. Thus, the next logical 'pairing' would be to group 'a' with 'q'. However, in the mean-time 'q' has played everyone from 'r' to 'F'. So, 'stalemate'! > According to the research, there IS a solution to this. > > I've spent the afternoon hacking my previous code to work in loops of > weeks > groups in week > using set intersection as the filter (within week, intersection > between groups must return empty sets -- no duplicate players) and > then against prior weeks (intersection must not be greater than 1; 2+ > indicates a repeated pair of players). The 4 4 6 case is an expected result. Generalising the problem, takes it way-beyond the level of an intermediate~advanced (Python) programming course (IMHO). It requires some higher-order math, rather than 'just Python'! If you told me this was a post-grad level assignment in a math stream, I'd believe you! Certainly it's beyond (my impression of) the OP's level (and interest). As mentioned, my 'solution' (to @marcus) was simplistic and basic. It doesn't even consider back-tracking and is limited to one 'strategy' (ie selection based upon not much more than blind-luck). Beyond the four definitions: globals(): player_history is a dict (key is player-name) of sets (previous team-mates?opponents) * yes, I know about the perils of globals! Referring to discussion of OO, perhaps making the league/tournament an object which contains all the specifications would have the advantage of avoiding globals... arrange_draws_for_league() could assemble a list of weekly draws/groups, but as the spec seemed to only require a print-out, I refactored it 'out'. arrange_this_weeks_groups() has two constructs: - this_weeks_draw which a list to be filled with the groups of (4) players (itself a list, returned from the inner function...) - players_already_drawn is the set of players already placed in this_weeks_draw Hence the (inner) function find_undrawn_player() which serially-searches the list of players (string of letters) to find a player with which to 'seed' the next player-group. [here is where the simplicity of rote (as a tactic) reduces generalisation!] I guess these two constructs might be combined, but I wasn't sure if the order of players in the draw might have some significance; whereas processing is faster and (the thinking) easier using sets (where 'order' has no meaning). NB both start the 'week' empty, which is why player-a will always be the first player, in the first group, every week - again a gross simplification and referring to previous criticism, may not be 'fair' if the order of the players within a group (or of the groups within a draw) has particular significance! arrange_group_to_play() is the 'inner loop'/inner layer of the 'onion' - grouping is the set of players who will play together 'this time' and seeded by the player selected above - players_played starts life as a copy* of the seed-player's player_history, and is extended by the history of each player as (s)he is added to the group. Thus, it informs the mechanism ensuring that no player repeats a meeting with any other player in the competition. * Yes, whilst grouping is a set, to ease the load on my eyes, I always sort before printing. What a cheat! So, whilst the solution keeps 'player history', it makes no record of attempts to solve, and thus there's no opportunity to back-track. Perhaps instead of the first combination being 'a' and 'b' (simplistic approach), if 'a' and 'p' (say) were tried first, might that lead to an actual solution that was not otherwise possible? At which point I say: "stop the world - I want to get off"! If you'd like a copy of this code-solution* (off-list), then will be happy to send - but I think you're an order of magnitude beyond my achievement to-date (and my interest for the future)! * 69 LoC, nicely commented, written for 'intermediate level' coders, blah-blah, puff-puff, including debug-prints for the player histories. > C:\Users\Wulfraed\Documents\_Hg-Repositories\Python Progs\SGP>main.py > > *** Usage: SGP.py number_of_groups group_size number_of_weeks Another point-of-difference is that I perhaps (mis-)understood that the specs included a requirement that every player play every other player, at some stage during the league/tournament. In reality the number_of_weeks specification is the code's control. Many of these (snipped) combinations of league-definitions you've attempted don't meet that spec - hence I've not tried. Apologies... (see comment elsewhere about the elegance and careful selection of definitions in the 'assignment') > I have no back-tracking in place, beyond the restart of the generator > on each week. I suspect the next attempt -- should I get ambitious -- > is to put a generator on each group in each week (and save them as > some structure), to allow for back-tracking. "You're a braver man than I [am], Gunga Din"! -- Regards, =dn _______________________________________________ Tutor maillist - Tutor at python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor From wlfraed at ix.netcom.com Tue Mar 22 12:20:00 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Tue, 22 Mar 2022 12:20:00 -0400 Subject: [Tutor] problem solving with lists References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> <58b3690c-4173-8ffa-5d57-6490dea20309@DancesWithMice.info> Message-ID: <1fsj3h97u4a110u8396mmc63b66r7v8i5i@4ax.com> On Tue, 22 Mar 2022 10:54:28 +1300, dn declaimed the following: >Another point-of-difference is that I perhaps (mis-)understood that the >specs included a requirement that every player play every other player, >at some stage during the league/tournament. > That IS the desired result, but the based upon the research papers and Wikipedia, the real SGP merely determines IF a schedule exists that meets All players play each week (no player plays twice in the week) Every possible pairing of players occurs zero or one time over the specified number of weeks. (No pairing occurs two or more times) Obviously, for short (less than maximal) weeks, there will be a lot of "zero" pairings. Including an 18-line "docstring", and the output formatting logic, mine run 84 LoC. WHOOPS... Correction (just realized I have a leftover unused function from previous code): Now down to 68 LoC. The core computation takes just 18 LoC. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From marcus.luetolf at bluewin.ch Wed Mar 23 15:54:01 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Wed, 23 Mar 2022 20:54:01 +0100 Subject: [Tutor] problem solving with lists In-Reply-To: References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> Message-ID: <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch> Hello Experts, I tried to follow your advises logically think over my task and set up an algorithm as sort of pseudocode below. Before doing coding I'd like to present it for critisism: >players_list = list('abcdefghijklmnop') >for day_1 : >? create 4 lists named team_lists, containing 4 subsequent letters/players > by iterating over every 4th letter/player > identifying its indices in players_list (0, 4, 8, 12) > list/print team_lists of 4 subsequent Letters/elements each starting > at every 4th letter/player in players_list >? assign all 4 letter/player of the first team lists as lead_player (?a?, ?b?, ?c?, ?d?) >? create a player_history as list (set ?) for all letter/player in all_players containing > all of the letter/players of the team_list they were in, total of 16. >for each day_2 through day_5 : >? create 4 lists named team_lists, containing 4 letter/player, > inserting as first letter/player the lead_player ('a', 'b', 'c', 'd'). > appending letter/player 2 - 4 from players_list if they were > not in player_history of lead_player, and not in player_history of > subsequent letter/player. Appreciate critic, thanks, Marcus. ------------------------------------------------------------------------------------------------------------------------------ -----Urspr?ngliche Nachricht----- Von: Tutor Im Auftrag von dn Gesendet: Montag, 21. M?rz 2022 06:35 An: tutor at python.org Betreff: Re: [Tutor] problem solving with lists Have I managed to understand the problem, this time? On 21/03/2022 05.05, Dennis Lee Bieber wrote: > On Sun, 20 Mar 2022 15:55:27 +0100, > declaimed the following: > >>> all_letters = ?abcdefghijklmnop? >>> number_of_lists = 5 >>> number_of_sublists per list = 4 >>> number_per_sublist = 4 >> to >>> all_letters = ?abcdefghi? >>> number_of_lists = 4 >>> number_of_sublists per list = 3 >>> number_per_sublist = 3 >> to >>> all_letters = 'abcdef'. > The discussion would be much easier if you gave real names to all > those... (since you later confirm this is the SGP) > > number of weeks > number of groupings > players per grouping > > This avoids all confusion over lists, sublists, etc... "week 1", > "group 3", "player 2". How about these as 'meaningful names': players = "abcdefghijklmnop" number_of_weeks = 5 number_of_groupings = 4 players_per_grouping = 4 >> seems rather straightforward. But for now I cannot see yet how to use it to remove all non-uniques sublists/teams. > You don't "remove" them! "Remove" implies you already placed a > grouping into the solution and now are checking for if they meet the constraints. > Instead you check the constraints for a candidate grouping BEFORE ADDING it > to the solution. Yes, the more 'constructivist' approach is probably easier - it is easier to 'see' as things are added to the solution, than it is to keep track of what was there 'before' when subtracting/pruning. YMMV! This solution keeps track of each player's history, ie if player-a is grouped with players 'b', 'c', and 'd' in the first game, then: player_history['a'] == {'b','c','d'} and in the second game (s)he is grouped with players 'e', 'i', 'm'; then it becomes: player_history['a'] == {'b','c','d', 'e', 'i', 'm'} and so-on (see output-report, below) The player's history is used whenever (s)he is 'selected' to ensure that there is no repetition of anyone who has participated in that player's previous groupings. >> SPG exactly describes my goal. > > The SGP is not a week-end programming exercise. It is the subject of > multiple university research papers in developing/optimizing > constraint-based solver algorithms. > > A one-time pass over the output of .combinations() will not be > sufficient (especially as the criteria per week that no player appears > more than once means going from "abcd" [the first foursome > .combinations() spits out] has to skip all other groups that begin > with "a", "b", "c" or "d" -- and you can't get them back later. At a > minimum you need to restart the > .combinations() on each week. You'll really need to implement some way > of backtracking ("we ran out of groupings without being able to place > one ink 'this' position, back up and change the previously placed > grouping and start over on this position") -- it is possible you might > have to back all the way up to the first grouping and try a different value for it. Which all serves to make me think that I have yet to grasp the full-measure of the problem! Herewith the output-report. The "draw" for each week (who is playing whom during that week) appears as four Python-lists under the week's sub-title. (the 'real' output) Inspecting the "draw", one can visually-check that each player only plays against everyone else, once - and only once - and exactly once (per @Dennis' comment about byes - no, none of them necessary with this combination of definitions)! The 16-player listing (debug-print) underneath each week's draw, shows how the program[me] keeps a record of which players each player has played to-date - thus after each week's game it extends by another three players' names/letters. Finally, by the end of the league/tournament (whatever you want to call the five-weeks of play, per definitions), every player is shown to have played against every other player:- /usr/bin/python3 /home/dn/Projects/Experiments/marcus.py Draw for 5 week league Draw for week 1 ['a', 'b', 'c', 'd'] ['e', 'f', 'g', 'h'] ['i', 'j', 'k', 'l'] ['m', 'n', 'o', 'p'] a ['a', 'b', 'c', 'd'] b ['a', 'b', 'c', 'd'] c ['a', 'b', 'c', 'd'] d ['a', 'b', 'c', 'd'] e ['e', 'f', 'g', 'h'] f ['e', 'f', 'g', 'h'] g ['e', 'f', 'g', 'h'] h ['e', 'f', 'g', 'h'] i ['i', 'j', 'k', 'l'] j ['i', 'j', 'k', 'l'] k ['i', 'j', 'k', 'l'] l ['i', 'j', 'k', 'l'] m ['m', 'n', 'o', 'p'] n ['m', 'n', 'o', 'p'] o ['m', 'n', 'o', 'p'] p ['m', 'n', 'o', 'p'] Draw for week 2 ['a', 'e', 'i', 'm'] ['b', 'f', 'j', 'n'] ['c', 'g', 'k', 'o'] ['d', 'h', 'l', 'p'] a ['a', 'b', 'c', 'd', 'e', 'i', 'm'] b ['a', 'b', 'c', 'd', 'f', 'j', 'n'] c ['a', 'b', 'c', 'd', 'g', 'k', 'o'] d ['a', 'b', 'c', 'd', 'h', 'l', 'p'] e ['a', 'e', 'f', 'g', 'h', 'i', 'm'] f ['b', 'e', 'f', 'g', 'h', 'j', 'n'] g ['c', 'e', 'f', 'g', 'h', 'k', 'o'] h ['d', 'e', 'f', 'g', 'h', 'l', 'p'] i ['a', 'e', 'i', 'j', 'k', 'l', 'm'] j ['b', 'f', 'i', 'j', 'k', 'l', 'n'] k ['c', 'g', 'i', 'j', 'k', 'l', 'o'] l ['d', 'h', 'i', 'j', 'k', 'l', 'p'] m ['a', 'e', 'i', 'm', 'n', 'o', 'p'] n ['b', 'f', 'j', 'm', 'n', 'o', 'p'] o ['c', 'g', 'k', 'm', 'n', 'o', 'p'] p ['d', 'h', 'l', 'm', 'n', 'o', 'p'] Draw for week 3 ['a', 'f', 'k', 'p'] ['b', 'e', 'l', 'o'] ['c', 'h', 'i', 'n'] ['d', 'g', 'j', 'm'] a ['a', 'b', 'c', 'd', 'e', 'f', 'i', 'k', 'm', 'p'] b ['a', 'b', 'c', 'd', 'e', 'f', 'j', 'l', 'n', 'o'] c ['a', 'b', 'c', 'd', 'g', 'h', 'i', 'k', 'n', 'o'] d ['a', 'b', 'c', 'd', 'g', 'h', 'j', 'l', 'm', 'p'] e ['a', 'b', 'e', 'f', 'g', 'h', 'i', 'l', 'm', 'o'] f ['a', 'b', 'e', 'f', 'g', 'h', 'j', 'k', 'n', 'p'] g ['c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'o'] h ['c', 'd', 'e', 'f', 'g', 'h', 'i', 'l', 'n', 'p'] i ['a', 'c', 'e', 'h', 'i', 'j', 'k', 'l', 'm', 'n'] j ['b', 'd', 'f', 'g', 'i', 'j', 'k', 'l', 'm', 'n'] k ['a', 'c', 'f', 'g', 'i', 'j', 'k', 'l', 'o', 'p'] l ['b', 'd', 'e', 'h', 'i', 'j', 'k', 'l', 'o', 'p'] m ['a', 'd', 'e', 'g', 'i', 'j', 'm', 'n', 'o', 'p'] n ['b', 'c', 'f', 'h', 'i', 'j', 'm', 'n', 'o', 'p'] o ['b', 'c', 'e', 'g', 'k', 'l', 'm', 'n', 'o', 'p'] p ['a', 'd', 'f', 'h', 'k', 'l', 'm', 'n', 'o', 'p'] Draw for week 4 ['a', 'g', 'l', 'n'] ['b', 'h', 'k', 'm'] ['c', 'e', 'j', 'p'] ['d', 'f', 'i', 'o'] a ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'i', 'k', 'l', 'm', 'n', 'p'] b ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'j', 'k', 'l', 'm', 'n', 'o'] c ['a', 'b', 'c', 'd', 'e', 'g', 'h', 'i', 'j', 'k', 'n', 'o', 'p'] d ['a', 'b', 'c', 'd', 'f', 'g', 'h', 'i', 'j', 'l', 'm', 'o', 'p'] e ['a', 'b', 'c', 'e', 'f', 'g', 'h', 'i', 'j', 'l', 'm', 'o', 'p'] f ['a', 'b', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'n', 'o', 'p'] g ['a', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'o'] h ['b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k', 'l', 'm', 'n', 'p'] i ['a', 'c', 'd', 'e', 'f', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'] j ['b', 'c', 'd', 'e', 'f', 'g', 'i', 'j', 'k', 'l', 'm', 'n', 'p'] k ['a', 'b', 'c', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'o', 'p'] l ['a', 'b', 'd', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'p'] m ['a', 'b', 'd', 'e', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'o', 'p'] n ['a', 'b', 'c', 'f', 'g', 'h', 'i', 'j', 'l', 'm', 'n', 'o', 'p'] o ['b', 'c', 'd', 'e', 'f', 'g', 'i', 'k', 'l', 'm', 'n', 'o', 'p'] p ['a', 'c', 'd', 'e', 'f', 'h', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] Draw for week 5 ['a', 'h', 'j', 'o'] ['b', 'g', 'i', 'p'] ['c', 'f', 'l', 'm'] ['d', 'e', 'k', 'n'] a ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] b ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] c ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] d ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] e ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] f ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] g ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] h ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] i ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] j ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] k ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] l ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] m ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] n ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] o ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] p ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] Process finished with exit code 0 Is this what we're trying to achieve? -- Regards, =dn _______________________________________________ Tutor maillist - Tutor at python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor From wlfraed at ix.netcom.com Thu Mar 24 11:41:45 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Thu, 24 Mar 2022 11:41:45 -0400 Subject: [Tutor] problem solving with lists References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch> Message-ID: <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com> On Wed, 23 Mar 2022 20:54:01 +0100, declaimed the following: >Hello Experts, >I tried to follow your advises logically think over my task and set up an algorithm as sort of pseudocode below. >Before doing coding I'd like to present it for critisism: > >>players_list = list('abcdefghijklmnop') > And again you are back to where the only data structure to be used for everything is a LIST. Keep your players as a string. Think of your "team" as a unit, made out of a string. Strings are indexable -- the syntax looks just like what you'd use with a list of 1-char strings). >>> import sys >>> import string >>> pch = string.ascii_lowercase[:16] >>> plst = list(pch) >>> pch 'abcdefghijklmnop' >>> plst ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] >>> sys.getsizeof(pch) 65 >>> sys.getsizeof(plst) 184 >>> (as strings, the storage is also a third of the list) >>for day_1 : >>? create 4 lists named team_lists, containing 4 subsequent letters/players >> by iterating over every 4th letter/player >> identifying its indices in players_list (0, 4, 8, 12) >> list/print team_lists of 4 subsequent Letters/elements each starting >> at every 4th letter/player in players_list >>? assign all 4 letter/player of the first team lists as lead_player (?a?, ?b?, ?c?, ?d?) Since you are defining a on-off process, and not something programmatic (that is -- there is nothing in the above that can be CHANGED from run to run), you might as well hard-code this step. >>> day1 = [ pch[0:4], pch[4:8], pch[8:12], pch[12:16] ] >>> day1 ['abcd', 'efgh', 'ijkl', 'mnop'] >>> -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Thu Mar 24 13:26:58 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Thu, 24 Mar 2022 13:26:58 -0400 Subject: [Tutor] problem solving with lists References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch> <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com> Message-ID: On Thu, 24 Mar 2022 11:41:45 -0400, Dennis Lee Bieber declaimed the following: > > Keep your players as a string. Think of your "team" as a unit, made out >of a string. > > Strings are indexable -- the syntax looks just like what you'd use with >a list of 1-char strings). > Alternatively -- don't use LIST or STRING... Since for purposes of the problem itself, there is no difference between "abcd" and "dbac" (and similarly, there is no difference between "abcd", "efgh", "ijkl", "mnop" and "ijkl", "abcd", "mnop", "efgh") you should be thinking of using SET as a data structure. You state you are trying to come up with an algorithm, but your description is always at the level of implementation at the low-level of the language itself -- and you have already defined a one-use implementation. An algorithm would be something like: { /w/ <= a week /nw/ <= number of weeks /g/ <= a group /ng/ <= number of groups /pg/ <= player in group /sg/ <= size of group /p/ <= a player } for each /w/ in /nw/ weeks for each /g/ in /ng/ groups for each /pg/ in /sg/ players-in-group select /p/ from (pg * g) players such that /p/ is only selected once in the current week AND any pair of /p/ in /pg/ does not appear in any prior week's groups At an implementation level -- .combinations() does most of the for each /pg/ ... select /p/ ... in that it will return /sg/ size groups of /p/, and within the group, there are no duplicates. You are still responsible for testing that they are unique across the groups in each week (that means rejecting many of the groups that .combinations() will provide). If you use set logic, you don't even have to index the members within each group. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From PythonList at DancesWithMice.info Thu Mar 24 23:56:06 2022 From: PythonList at DancesWithMice.info (dn) Date: Fri, 25 Mar 2022 16:56:06 +1300 Subject: [Tutor] problem solving with lists In-Reply-To: <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com> References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch> <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com> Message-ID: <683dcf73-ab97-48b8-f3d5-b20121b008d1@DancesWithMice.info> On 25/03/2022 04.41, Dennis Lee Bieber wrote: > On Wed, 23 Mar 2022 20:54:01 +0100, declaimed > the following: ... > And again you are back to where the only data structure to be used for > everything is a LIST. > > Keep your players as a string. Think of your "team" as a unit, made out > of a string. > > Strings are indexable -- the syntax looks just like what you'd use with > a list of 1-char strings). +1 Whereas I disagree with people using single-letter identifiers (for example), sample-data has very little meaning and little impact on the overall result. Another angle to the point is that it is a lot easier to scan a line of letters, or in groups of four, both for omissions and for duplications, than it is to scan a list of letters (because of all those apostrophes/single-quotation marks)! Certainly to these old eyes... In this case, once the code is tested and working, it is an easy change to 'upgrade' from single-letter strings, to proper names of people. >>> for day_1 : >>> ? create 4 lists named team_lists, containing 4 subsequent letters/players >>> by iterating over every 4th letter/player >>> identifying its indices in players_list (0, 4, 8, 12) >>> list/print team_lists of 4 subsequent Letters/elements each starting >>> at every 4th letter/player in players_list >>> ? assign all 4 letter/player of the first team lists as lead_player (?a?, ?b?, ?c?, ?d?) > > Since you are defining a on-off process, and not something programmatic > (that is -- there is nothing in the above that can be CHANGED from run to > run), you might as well hard-code this step. > >>>> day1 = [ pch[0:4], pch[4:8], pch[8:12], pch[12:16] ] >>>> day1 > ['abcd', 'efgh', 'ijkl', 'mnop'] Am not sure about this - as a tactic - can't/won't argue with the logic! The solution is going to require a series of nested iterations (outlined earlier). These will produce the 'alphabetic' first week's groups as a matter of course. Thus, stating the first week's 'solution' as a constant/taken as read/a natural part of the process is reasonable, but the code for every week thereafter then has to include logic (or 'magic constants') which enables the first week to be 'different', ie an exception to the norm. The same result will be printed, either way! NB I recall that my code includes a 'special' function to select the first player in each new group (as distinct from the second, third, ... number of players in each group) - so sit back and count my two faces! Further, if we consider that arranging players into a logical order, before selection, is also a likely and 'natural' approach; this would seem to imply that every time they enter a tournament, 'a' and 'b' will play each other in the first game. That may not be a good thing! (may not even be seen as "fair" - by those who don't think in statistics) Accordingly, I'm wondering how 'expensive' it would be to 'throw' all the player's names into a 'pool' and make repeated random drawings to form the groupings? Each such selection, will either be 'accepted' if the player may be added to the group currently being constructed, or 'rejecting' if the player is not suitable/permitted to be added (and returning to the 'pool'). Yes, each 'rejection' would be a cost with no benefit, and the ratio of rejections to acceptances will grow ~exponentially week-by-week... This is the way kids typically separate themselves into teams for a 'pick up' game (of whatever sport), there's no concept of taking 'from left to right' - except for the (proposed) randomisation of selection, rather than kids using previous-knowledge or assessing 'looks like might be a good player'. Yes, I so like the 'story' - but...it would be so much easier/cheaper to take the original-string/list of names, as produced by the tournament organisers, and at the beginning of the program[me] rearrange it into a random sequence! -- Regards, =dn From PythonList at DancesWithMice.info Fri Mar 25 00:26:35 2022 From: PythonList at DancesWithMice.info (dn) Date: Fri, 25 Mar 2022 17:26:35 +1300 Subject: [Tutor] problem solving with lists In-Reply-To: References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch> <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com> Message-ID: On 25/03/2022 06.26, Dennis Lee Bieber wrote: > On Thu, 24 Mar 2022 11:41:45 -0400, Dennis Lee Bieber > declaimed the following: ... > you should be thinking of using SET as a data structure. +1 > You state you are trying to come up with an algorithm, but your > description is always at the level of implementation at the low-level of > the language itself -- and you have already defined a one-use > implementation. > > An algorithm would be something like: > > { > /w/ <= a week > /nw/ <= number of weeks > /g/ <= a group > /ng/ <= number of groups > /pg/ <= player in group > /sg/ <= size of group > /p/ <= a player > } > for each /w/ in /nw/ weeks > for each /g/ in /ng/ groups > for each /pg/ in /sg/ players-in-group > select /p/ from (pg * g) players > such that /p/ is only selected once in the current week > AND > any pair of /p/ in /pg/ does not appear in any prior > week's groups Except use descriptive names inside the algorithm/code rather than abbreviations! > At an implementation level -- .combinations() does most of the > for each /pg/ ... > select /p/ ... > in that it will return /sg/ size groups of /p/, and within the group, there > are no duplicates. You are still responsible for testing that they are > unique across the groups in each week (that means rejecting many of the > groups that .combinations() will provide). If you use set logic, you don't > even have to index the members within each group. Maybe it comes down to @Dennis' brain working differently/better than my own, or even a matter of taste, but... The outer-loop (weeks) is constructed gradually. The next loop (groups) is constructed gradually. The next loop (players into a group) is constructed gradually. The inner-loop (player) is constructed gradually. Whereas substituting the two inner-most loops for: itertools.combinations(players, nr_of_players_in_a_group) and then having to reject some combinations because they fail either/both of the selection rules, is subtractive (cf constructive). The combinations-implementation makes sense to people with statistics knowledge/skills. For example, we recognise the difference between a "combination" and a "permutation" - even though that significance is not readily-apparent in every-day English-language usage. Should we expect/demand that of 'the average programmer'? In a statistics-oriented team, "yes". In a business team? Probably not! Speaking personally, I'd be happy to see the solution and read the code expressed, either way. However, if 'readability' becomes a deciding-factor, the 'consistency' of the first implementation of the algorithm, is likely to be preferred. (Hey, maybe I'm becoming a hobgoblin!) -- -- Regards, =dn From wlfraed at ix.netcom.com Fri Mar 25 09:27:12 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Fri, 25 Mar 2022 09:27:12 -0400 Subject: [Tutor] problem solving with lists References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch> <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com> <683dcf73-ab97-48b8-f3d5-b20121b008d1@DancesWithMice.info> Message-ID: On Fri, 25 Mar 2022 16:56:06 +1300, dn declaimed the following: >Further, if we consider that arranging players into a logical order, >before selection, is also a likely and 'natural' approach; this would >seem to imply that every time they enter a tournament, 'a' and 'b' will >play each other in the first game. That may not be a good thing! (may >not even be seen as "fair" - by those who don't think in statistics) > >Accordingly, I'm wondering how 'expensive' it would be to 'throw' all >the player's names into a 'pool' and make repeated random drawings to >form the groupings? Each such selection, will either be 'accepted' if >the player may be added to the group currently being constructed, or >'rejecting' if the player is not suitable/permitted to be added (and >returning to the 'pool'). > Since "a", "b", etc. are just placeholders, and -- if all tournaments are based upon the same criteria (4 groups of 4 players for 5 weeks) such that the "table of placeholders" doesn't change (it becomes a constant in the code that translates from placeholder to player name) -- all that is required is to randomize the list of 16 players before mapping them to the placeholder letters. """ random.shuffle(x[, random]) Shuffle the sequence x in place. To shuffle an immutable sequence and return a new shuffled list, use sample(x, k=len(x)) instead. """ """ random.sample(population, k) Return a k length list of unique elements chosen from the population sequence or set. Used for random sampling without replacement. Returns a new list containing elements from the population while leaving the original population unchanged. The resulting list is in selection order so that all sub-slices will also be valid random samples. This allows raffle winners (the sample) to be partitioned into grand prize and second place winners (the subslices). """ players = [ "Lady Gaga", "Arnold Palmer", ..., "George Bush" ] random.shuffle(players) lookup = {} for i, placeholder in enumerate("abcdefghijklmnop"): lookup[placeholder] = players[i] Alternatively, untested: players = [ "Lady Gaga", "Arnold Palmer", ..., "George Bush" ] random.shuffle(players) lookup = {} for placeholder, player in zip("abcdefghijklmnop", players): lookup[placeholder] = player Final output would look something like (pseudo-code) for w, week in enumerate(weeks):: print("Week %s" % w+1) for t, team in enumerate(week): print("\tTeam %s" % t+1) for player in team: print("\t\t%s" % players[player]) -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From marcus.luetolf at bluewin.ch Sat Mar 26 05:25:54 2022 From: marcus.luetolf at bluewin.ch (marcus.luetolf at bluewin.ch) Date: Sat, 26 Mar 2022 10:25:54 +0100 Subject: [Tutor] problem solving with lists In-Reply-To: References: <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a.ref@email.android.com> <3a7bfe8b-6cef-4b0e-a9d8-30c6c8150a0a@email.android.com> <00d501d83b98$ffce5650$ff6b02f0$@bluewin.ch> <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch> <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com> Message-ID: <005901d840f3$7e838a10$7b8a9e30$@bluewin.ch> Thanks, very helpfull. Two points I don't understand: 1. in your 4th and inner loop " select /p/ from (pg * g) players" what does (pg * g) mean ? the value for pg is 4 but g should initially be an empty list or set ??? If I use combinations() I get 1820 lists or sets out of 16 players and sg = 4. 2. in sets there is no order. If I use sets instead of lists how could I find/reject sets with equal pairings of elements ? Regards, Marcus. -----Urspr?ngliche Nachricht----- Von: Tutor Im Auftrag von dn Gesendet: Freitag, 25. M?rz 2022 05:27 An: tutor at python.org Betreff: Re: [Tutor] problem solving with lists On 25/03/2022 06.26, Dennis Lee Bieber wrote: > On Thu, 24 Mar 2022 11:41:45 -0400, Dennis Lee Bieber > declaimed the following: ... > you should be thinking of using SET as a data structure. +1 > You state you are trying to come up with an algorithm, but your > description is always at the level of implementation at the low-level > of the language itself -- and you have already defined a one-use > implementation. > > An algorithm would be something like: > > { > /w/ <= a week > /nw/ <= number of weeks > /g/ <= a group > /ng/ <= number of groups > /pg/ <= player in group > /sg/ <= size of group > /p/ <= a player > } > for each /w/ in /nw/ weeks > for each /g/ in /ng/ groups > for each /pg/ in /sg/ players-in-group > select /p/ from (pg * g) players > such that /p/ is only selected once in the current week > AND > any pair of /p/ in /pg/ does not appear in any prior week's > groups Except use descriptive names inside the algorithm/code rather than abbreviations! > At an implementation level -- .combinations() does most of the > for each /pg/ ... > select /p/ ... > in that it will return /sg/ size groups of /p/, and within the group, > there are no duplicates. You are still responsible for testing that > they are unique across the groups in each week (that means rejecting > many of the groups that .combinations() will provide). If you use set > logic, you don't even have to index the members within each group. Maybe it comes down to @Dennis' brain working differently/better than my own, or even a matter of taste, but... The outer-loop (weeks) is constructed gradually. The next loop (groups) is constructed gradually. The next loop (players into a group) is constructed gradually. The inner-loop (player) is constructed gradually. Whereas substituting the two inner-most loops for: itertools.combinations(players, nr_of_players_in_a_group) and then having to reject some combinations because they fail either/both of the selection rules, is subtractive (cf constructive). The combinations-implementation makes sense to people with statistics knowledge/skills. For example, we recognise the difference between a "combination" and a "permutation" - even though that significance is not readily-apparent in every-day English-language usage. Should we expect/demand that of 'the average programmer'? In a statistics-oriented team, "yes". In a business team? Probably not! Speaking personally, I'd be happy to see the solution and read the code expressed, either way. However, if 'readability' becomes a deciding-factor, the 'consistency' of the first implementation of the algorithm, is likely to be preferred. (Hey, maybe I'm becoming a hobgoblin!) -- -- Regards, =dn _______________________________________________ Tutor maillist - Tutor at python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor From wlfraed at ix.netcom.com Sat Mar 26 12:52:31 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Sat, 26 Mar 2022 12:52:31 -0400 Subject: [Tutor] problem solving with lists References: <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch> <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com> <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch> <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com> <005901d840f3$7e838a10$7b8a9e30$@bluewin.ch> Message-ID: <64gu3hpmbi8ji4sudga32m8happuv0jg8p@4ax.com> On Sat, 26 Mar 2022 10:25:54 +0100, declaimed the following: >1. in your 4th and inner loop " select /p/ from (pg * g) players" what does >(pg * g) mean ? the value for pg is 4 but g should initially be an empty >list or set ??? My apologies... both of those should be changed... (sg * ng) That is: the size of each group times the number of groups determines how many players are to be available for selection. > If I use combinations() I get 1820 lists or sets out of 16 players and >sg = 4. >2. in sets there is no order. If I use sets instead of lists how could I >find/reject sets with equal pairings of elements ? It is EASIER using sets. set1 INTERSECT set2 => a set of only common elements If the result is empty, there are no common elements (useful for filtering the groups in each week, as no player is to appear more than once) If the result has 2 or more elements, there are one or more common pairs (useful for filtering current group against previous weeks) https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset Alternative notations: set1.intersection(set2) set1 & set2 Hmmm, I'd missed the .isdisjoint() method -- that replaces (consolidates) testing if an intersection is empty; though may not save much in code... if not set1.isdisjoint(set2): vs if set1 & set2: -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From phillor9 at gmail.com Wed Mar 30 02:35:00 2022 From: phillor9 at gmail.com (Phil) Date: Wed, 30 Mar 2022 17:35:00 +1100 Subject: [Tutor] Tkinter draw line segments Message-ID: The segment table contains the start and end points of lines to be drawn on the canvas. ??????? seg = {0: (20, 20, 40, 20), ?????????????? 1: (44, 24, 44, 44), ?????????????? 2: (44, 48, 44, 68), ?????????????? 3: (20, 72, 40, 72), ?????????????? 4: (16, 48, 16, 68), ?????????????? 5: (16, 24, 16, 44), ?????????????? 6: (20, 46, 40, 46), ????????????? } Say I want to draw segments 1 and 2. ??????? num = {1: (seg[1], seg[2])} The following will draw all of the segments correctly. ??????? for i in range(7): ??????????? self.canvas.create_line(seg[i], width=4, fill="green") What I haven't sorted out is how to draw segments 1 and 2 without having two draw statements. The following does draw the two segments but without the break between them. ??????? self.canvas.create_line(num[1], width=4, fill="green") What I'm trying to come up with is a table entry that tells the draw routine how many draw statements there are, one for each segment. No doubt I'm making this more complicated than it needs to be. One way around this is to draw all of the segments in two colours. In the above case I would draw segments 1 and 2 green and the remainder black. That way I'd only need one draw statement in a for loop with a variable fill colour. This would work perfectly on a black background but it seems like an amateurish solution. -- Regards, Phil From __peter__ at web.de Wed Mar 30 11:27:51 2022 From: __peter__ at web.de (Peter Otten) Date: Wed, 30 Mar 2022 17:27:51 +0200 Subject: [Tutor] Tkinter draw line segments In-Reply-To: References: Message-ID: On 30/03/2022 08:35, Phil wrote: > The segment table contains the start and end points of lines to be drawn > on the canvas. > > ??????? seg = {0: (20, 20, 40, 20), > ?????????????? 1: (44, 24, 44, 44), > ?????????????? 2: (44, 48, 44, 68), > ?????????????? 3: (20, 72, 40, 72), > ?????????????? 4: (16, 48, 16, 68), > ?????????????? 5: (16, 24, 16, 44), > ?????????????? 6: (20, 46, 40, 46), > ????????????? } > > Say I want to draw segments 1 and 2. > > ??????? num = {1: (seg[1], seg[2])} > > The following will draw all of the segments correctly. > > ??????? for i in range(7): > ??????????? self.canvas.create_line(seg[i], width=4, fill="green") > > What I haven't sorted out is how to draw segments 1 and 2 without having > two draw statements. The following does draw the two segments but > without the break between them. > > ??????? self.canvas.create_line(num[1], width=4, fill="green") > > What I'm trying to come up with is a table entry that tells the draw > routine how many draw statements there are, one for each segment. No > doubt I'm making this more complicated than it needs to be. > > One way around this is to draw all of the segments in two colours. In > the above case I would draw segments 1 and 2 green and the remainder > black. That way I'd only need one draw statement in a for loop with a > variable fill colour. This would work perfectly on a black background > but it seems like an amateurish solution. > I'd go about it a bit differently. When you draw all segments separately you can remember them by their ids. To display the desired digits you can hide/display segments as needed. A complete example: import tkinter as tk segments = [ (20, 20, 40, 20), (44, 24, 44, 44), (44, 48, 44, 68), (20, 72, 40, 72), (16, 48, 16, 68), (16, 24, 16, 44), (20, 46, 40, 46), ] segment_states = [ (1, 1, 1, 1, 1, 1, 0), # 0 (0, 1, 1, 0, 0, 0, 0), # 1 (1, 1, 0, 1, 1, 0, 1), # 2 (1, 1, 1, 1, 0, 0, 1), # 3 (0, 1, 1, 0, 0, 1, 1), # 4 (1, 0, 1, 1, 0, 1, 1), # 5 (0, 0, 1, 1, 1, 1, 1), # 6 (1, 1, 1, 0, 0, 0, 0), # 7 (1, 1, 1, 1, 1, 1, 1), # 8 (1, 1, 1, 0, 0, 1, 1), # 9 ] class Demo: def __init__(self): self.root = tk.Tk() self.label = tk.Label( self.root, text="Hit digit key to display corresponding number" ) self.label.pack() self.canvas = tk.Canvas(self.root, width=100, height=100) self.canvas.pack() self.segment_ids = [] self.draw_segments() for c in "0123456789": self.root.bind( c, lambda event, n=int(c): self.set_segments( segment_states[n] ) ) def draw_segments(self): for segment in segments: self.segment_ids.append( self.canvas.create_line(segment, width=4, fill="green") ) def set_segments(self, states): for seg_id, on in zip(self.segment_ids, states): self.canvas.itemconfigure( seg_id, state=tk.NORMAL if on else tk.HIDDEN ) def mainloop(self): self.root.mainloop() if __name__ == "__main__": demo = Demo() demo.mainloop() From wlfraed at ix.netcom.com Wed Mar 30 11:45:17 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Wed, 30 Mar 2022 11:45:17 -0400 Subject: [Tutor] Tkinter draw line segments References: Message-ID: On Wed, 30 Mar 2022 17:35:00 +1100, Phil declaimed the following: >The segment table contains the start and end points of lines to be drawn >on the canvas. > > ??????? seg = {0: (20, 20, 40, 20), > ?????????????? 1: (44, 24, 44, 44), > ?????????????? 2: (44, 48, 44, 68), > ?????????????? 3: (20, 72, 40, 72), > ?????????????? 4: (16, 48, 16, 68), > ?????????????? 5: (16, 24, 16, 44), > ?????????????? 6: (20, 46, 40, 46), > ????????????? } > >Say I want to draw segments 1 and 2. > > ??????? num = {1: (seg[1], seg[2])} > >The following will draw all of the segments correctly. > > ??????? for i in range(7): > ??????????? self.canvas.create_line(seg[i], width=4, fill="green") for s in seg: self.canvas.create_line(s, ...) No magic numbers (7), no need to create an index (though you've made it a dictionary where the KEY is nothing more than what would be a list index if you drop the x: notation and change { } to [ ]. > >What I haven't sorted out is how to draw segments 1 and 2 without having >two draw statements. The following does draw the two segments but >without the break between them. > > ??????? self.canvas.create_line(num[1], width=4, fill="green") Based upon Tkinter terminology, you are drawing TWO DISCONNECTED LINES -- not "segments" (segments are the result of adjacent pairs of coordinates provided in a single call). {Apparently Tkinter will unpack a tuple if provided -- the documentation just uses a sequence of coordinate pairs, as all options are keyword type} A line with two segments would look like ...create_line(20, 20, 40, 20, 44, 24, ...) This will draw a segment from (20, 20) to (40, 20) and then continue on to draw to (44, 24). > >What I'm trying to come up with is a table entry that tells the draw >routine how many draw statements there are, one for each segment. No >doubt I'm making this more complicated than it needs to be. > >One way around this is to draw all of the segments in two colours. In >the above case I would draw segments 1 and 2 green and the remainder >black. That way I'd only need one draw statement in a for loop with a >variable fill colour. This would work perfectly on a black background >but it seems like an amateurish solution. No dictionary to be seen lines = [ (20, 20, 40, 20), (44, 24, 44, 44, 68, 72), #toss in a 2-segment line (44, 48, 44, 68), (20, 72, 40, 72), (16, 48, 16, 68), (16, 24, 16, 44), (20, 46, 40, 46) ] >Say I want to draw segments 1 and 2. > desired_lines = (1, 2) for ln in desired_lines: self.canvas.create_line(lines[ln], width=4, fill="green") The lines don't have to be consecutive in "lines" (and "desired_lines can be tuple, list, or other iterator object) desired_lines = [1, 3, 4, 6] for ln in desired_lines: self.canvas.create_line(lines[ln], width=4, fill="green") Or even in list order desired_lines = (4, 0, 2, 6) for ln in desired_lines: self.canvas.create_line(lines[ln], width=4, fill="green") -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From __peter__ at web.de Wed Mar 30 12:21:31 2022 From: __peter__ at web.de (Peter Otten) Date: Wed, 30 Mar 2022 18:21:31 +0200 Subject: [Tutor] Tkinter draw line segments In-Reply-To: References: Message-ID: <9fc62dce-ad39-e8e1-bfca-a2a803b1353b@web.de> On 30/03/2022 17:27, Peter Otten wrote: > I'd go about it a bit differently. When you draw all segments separately > you can remember them by their ids. To display the desired digits you > can hide/display segments as needed. A complete example: Shortly after hitting send I had a Eureka moment: use tags! So here's the altered script: import tkinter as tk segments = [ (20, 20, 40, 20), (44, 24, 44, 44), (44, 48, 44, 68), (20, 72, 40, 72), (16, 48, 16, 68), (16, 24, 16, 44), (20, 46, 40, 46), ] tags_list = [ '0235789', '01234789', '013456789', '023568', '0268', '045689', '2345689' ] tags_list = [tuple(f"digit{d}" for d in s) for s in tags_list] class Demo: def __init__(self): self.root = tk.Tk() self.label = tk.Label( self.root, text="Hit digit key to display corresponding number" ) self.label.pack() self.canvas = tk.Canvas(self.root, width=100, height=100) self.canvas.pack() self.segment_ids = [] self.draw_segments() for c in "0123456789": self.root.bind( c, lambda event, tag=c: self.set_segments(tag) ) def draw_segments(self): for segment, tags in zip(segments, tags_list): self.canvas.create_line( segment, width=4, fill="green", tags=tags + ("all",) ) def set_segments(self, tag): self.canvas.itemconfigure("all", state=tk.HIDDEN) self.canvas.itemconfigure(f"digit{tag}", state=tk.NORMAL) def mainloop(self): self.root.mainloop() if __name__ == "__main__": demo = Demo() demo.mainloop() From phillor9 at gmail.com Wed Mar 30 19:17:21 2022 From: phillor9 at gmail.com (Phil) Date: Thu, 31 Mar 2022 10:17:21 +1100 Subject: [Tutor] Tkinter draw line segments In-Reply-To: <9fc62dce-ad39-e8e1-bfca-a2a803b1353b@web.de> References: <9fc62dce-ad39-e8e1-bfca-a2a803b1353b@web.de> Message-ID: <4311943e-8a03-dc94-d452-bfae61ed96b7@gmail.com> On 31/3/22 03:21, Peter Otten wrote: > On 30/03/2022 17:27, Peter Otten wrote: > >> I'd go about it a bit differently. When you draw all segments separately >> you can remember them by their ids. To display the desired digits you >> can hide/display segments as needed. A complete example: Thank you Peter and Dennis, once again you've given me something to think about. I abandoned my initial design and this is how I managed to solve the problem: seg = {0: (20, 20, 40, 20), ?????? 1: (44, 24, 44, 44), ?????? 2: (44, 48, 44, 68), ?????? 3: (20, 72, 40, 72), ?????? 4: (16, 48, 16, 68), ?????? 5: (16, 24, 16, 44), ?????? 6: (20, 46, 40, 46) ?????? } digits = {0: ('lime', 'lime', 'lime', 'lime', 'lime', 'lime', 'black'), ?????? 1: ('black', 'lime', 'lime', 'black', 'black', 'black', 'black'), ?????? 2: ('lime', 'lime', 'black', 'lime', 'lime', 'black', 'lime'), ?????? 3: ('lime', 'lime', 'lime', 'lime', 'black', 'black', 'lime'), ???? ?? etc Inside an after loop I have: ??????? for i in range(7): # yes I know I should use for s in seq. It's a hard-to-break habit ??????????? self.canvas.create_line(seg[i], width=4, fill=digits[number][i]) number is incremented every second. The digits are displayed on a black rectangle and, even if I say so myself, the result is quite realistic. > > Shortly after hitting send I had a Eureka moment: use tags! I've not come across tags until now so that'll probably keep me busy for the rest of the day. -- Regards, Phil