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>
 <svfd4j$p16$1@ciao.gmane.io> <svgapd$tbb$1@ciao.gmane.io>
 <6e521b71-3d97-7029-d165-e4504b143edf@gmail.com> <svh4jv$a3f$1@ciao.gmane.io>
 <9e3b626d-2b4d-94dd-5046-01d87a15a81e@gmail.com>
 <svi6kq$16n0$1@ciao.gmane.io>
 <2a8de7b4-a1c7-c740-e38f-b3093e872299@gmail.com>
Message-ID: <svktj9$v72$1@ciao.gmane.io>

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>
 <svfd4j$p16$1@ciao.gmane.io> <svgapd$tbb$1@ciao.gmane.io>
 <6e521b71-3d97-7029-d165-e4504b143edf@gmail.com> <svh4jv$a3f$1@ciao.gmane.io>
 <9e3b626d-2b4d-94dd-5046-01d87a15a81e@gmail.com>
 <svi6kq$16n0$1@ciao.gmane.io>
 <2a8de7b4-a1c7-c740-e38f-b3093e872299@gmail.com> <svktj9$v72$1@ciao.gmane.io>
Message-ID: <tfis1hp2glil77s11023rp6juvtn0s1ld2@4ax.com>

On Tue, 1 Mar 2022 10:47:05 +0000, Alan Gauld via Tutor <tutor at python.org>
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: <svktj9$v72$1@ciao.gmane.io>
References: <6b3c4594-14a3-5363-5fa3-6e990bf213f7@gmail.com>
 <svfd4j$p16$1@ciao.gmane.io> <svgapd$tbb$1@ciao.gmane.io>
 <6e521b71-3d97-7029-d165-e4504b143edf@gmail.com> <svh4jv$a3f$1@ciao.gmane.io>
 <9e3b626d-2b4d-94dd-5046-01d87a15a81e@gmail.com>
 <svi6kq$16n0$1@ciao.gmane.io>
 <2a8de7b4-a1c7-c740-e38f-b3093e872299@gmail.com> <svktj9$v72$1@ciao.gmane.io>
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: <CAO+T6MH1vikkA6t=FWEOqNhrBg8YY=ZfsjGZPUFyEerMcVGG3Q@mail.gmail.com>

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: <CAO+T6MH1vikkA6t=FWEOqNhrBg8YY=ZfsjGZPUFyEerMcVGG3Q@mail.gmail.com>
References: <CAO+T6MH1vikkA6t=FWEOqNhrBg8YY=ZfsjGZPUFyEerMcVGG3Q@mail.gmail.com>
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: <CAO+T6MH1vikkA6t=FWEOqNhrBg8YY=ZfsjGZPUFyEerMcVGG3Q@mail.gmail.com>
References: <CAO+T6MH1vikkA6t=FWEOqNhrBg8YY=ZfsjGZPUFyEerMcVGG3Q@mail.gmail.com>
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: <CAO+T6MH1vikkA6t=FWEOqNhrBg8YY=ZfsjGZPUFyEerMcVGG3Q@mail.gmail.com>
References: <CAO+T6MH1vikkA6t=FWEOqNhrBg8YY=ZfsjGZPUFyEerMcVGG3Q@mail.gmail.com>
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: <bc36c0a9-d9bd-0e0c-677b-f7a84249e648@wichmann.us>
References: <CAO+T6MH1vikkA6t=FWEOqNhrBg8YY=ZfsjGZPUFyEerMcVGG3Q@mail.gmail.com>
 <bc36c0a9-d9bd-0e0c-677b-f7a84249e648@wichmann.us>
Message-ID: <CAO+T6MErFcEs5gcMPQ-3E=2hKwpexsk5tzYE9qmGWckPTZq5Zw@mail.gmail.com>

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 <mats at wichmann.us> 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: <t01ter$3um$1@ciao.gmane.io>

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, <marcus.luetolf at bluewin.ch> 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: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>

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: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
References: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
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: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
 <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, <subodh.khandelwal at gmail.com> 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: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
References: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
Message-ID: <YiVgiq0mQsR5i+PD@cskk.homeip.net>

On 07Mar2022 11:33, Phil <phillor9 at gmail.com> 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 <cs at cskk.id.au>

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: <YiV1VPT17h/4i19b@cskk.homeip.net>

On 06Mar2022 20:48, Dennis Lee Bieber <wlfraed at ix.netcom.com> 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 <cs at cskk.id.au>

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: <YiVgiq0mQsR5i+PD@cskk.homeip.net>
References: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
 <YiVgiq0mQsR5i+PD@cskk.homeip.net>
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: <YiWFQN1gSmOYfXg9@cskk.homeip.net>

On 07Mar2022 14:54, Phil <phillor9 at gmail.com> 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 <cs at cskk.id.au>

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: <t01ter$3um$1@ciao.gmane.io>
References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch>
 <t01ter$3um$1@ciao.gmane.io>
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 <tutor-bounces+marcus.luetolf=bluewin.ch at python.org> 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: <YiWFQN1gSmOYfXg9@cskk.homeip.net>
References: <23c41ff3-7bac-4708-7ec2-efc9317f9277@gmail.com>
 <YiWFQN1gSmOYfXg9@cskk.homeip.net>
Message-ID: <d91183c9-43ab-5fcd-4f7c-df53f5263ece@gmail.com>


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>
 <t01ter$3um$1@ciao.gmane.io> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch>
Message-ID: <t04q15$mgi$1@ciao.gmane.io>

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: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
 <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us>
 <9fd4f0f4-c952-7574-107f-e1e0d9c218dd@gmail.com>
Message-ID: <t04qbp$b8v$1@ciao.gmane.io>

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: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
References: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
Message-ID: <t04r2d$upa$1@ciao.gmane.io>

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: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
 <YiVgiq0mQsR5i+PD@cskk.homeip.net>
 <23c41ff3-7bac-4708-7ec2-efc9317f9277@gmail.com>
Message-ID: <ulbc2hl8ukt4sf1nagulplmp7kn8asqusn@4ax.com>

On Mon, 7 Mar 2022 14:54:58 +1100, Phil <phillor9 at gmail.com> 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: <lccc2h95t8uhu6id2q2flcapcv14ik424a@4ax.com>

On Sun, 06 Mar 2022 13:05:26 -0500, Dennis Lee Bieber
<wlfraed at ix.netcom.com> 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>
 <lccc2h95t8uhu6id2q2flcapcv14ik424a@4ax.com>
Message-ID: <vsfc2h1c10bq2tvekl188oopv99q2vcblm@4ax.com>

On Mon, 07 Mar 2022 11:46:42 -0500, Dennis Lee Bieber
<wlfraed at ix.netcom.com> 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: <t05nfa$63n$1@ciao.gmane.io>

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: <nkvc2hlrcc7a2s528n28unoocjknvdupge@4ax.com>

On Mon, 7 Mar 2022 14:02:19 +0100 (CET), Ludo Joris
<ludo.a.joris at telenet.be> 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: <t04qbp$b8v$1@ciao.gmane.io>
References: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
 <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us>
 <9fd4f0f4-c952-7574-107f-e1e0d9c218dd@gmail.com> <t04qbp$b8v$1@ciao.gmane.io>
Message-ID: <ce938970-c81b-67f0-a43e-be9fb59deb62@gmail.com>


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: <ulbc2hl8ukt4sf1nagulplmp7kn8asqusn@4ax.com>
References: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
 <YiVgiq0mQsR5i+PD@cskk.homeip.net>
 <23c41ff3-7bac-4708-7ec2-efc9317f9277@gmail.com>
 <ulbc2hl8ukt4sf1nagulplmp7kn8asqusn@4ax.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: <ce938970-c81b-67f0-a43e-be9fb59deb62@gmail.com>
References: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
 <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us>
 <9fd4f0f4-c952-7574-107f-e1e0d9c218dd@gmail.com> <t04qbp$b8v$1@ciao.gmane.io>
 <ce938970-c81b-67f0-a43e-be9fb59deb62@gmail.com>
Message-ID: <t06628$vng$1@ciao.gmane.io>

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: <caf29f4f-cf1f-c8dd-438c-f48e00c017cf@gmail.com>

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: <caf29f4f-cf1f-c8dd-438c-f48e00c017cf@gmail.com>
References: <caf29f4f-cf1f-c8dd-438c-f48e00c017cf@gmail.com>
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: <caf29f4f-cf1f-c8dd-438c-f48e00c017cf@gmail.com>
Message-ID: <mv7d2h9r6h5ihvnlj25eh8vd9unda638mv@4ax.com>

On Tue, 8 Mar 2022 10:58:33 +1100, Phil <phillor9 at gmail.com> 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: <t04r2d$upa$1@ciao.gmane.io>
References: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
 <t04r2d$upa$1@ciao.gmane.io>
Message-ID: <dd99dd61-ea92-7e4c-450c-b31848e94514@gmail.com>


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: <t06628$vng$1@ciao.gmane.io>
References: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
 <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us>
 <9fd4f0f4-c952-7574-107f-e1e0d9c218dd@gmail.com> <t04qbp$b8v$1@ciao.gmane.io>
 <ce938970-c81b-67f0-a43e-be9fb59deb62@gmail.com> <t06628$vng$1@ciao.gmane.io>
Message-ID: <e8a06bf2-7c1b-3741-8647-2cec9565fcca@gmail.com>


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: <e8a06bf2-7c1b-3741-8647-2cec9565fcca@gmail.com>
References: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
 <7d620a47-92ab-0a70-87e1-d8e50a7e214a@wichmann.us>
 <9fd4f0f4-c952-7574-107f-e1e0d9c218dd@gmail.com> <t04qbp$b8v$1@ciao.gmane.io>
 <ce938970-c81b-67f0-a43e-be9fb59deb62@gmail.com> <t06628$vng$1@ciao.gmane.io>
 <e8a06bf2-7c1b-3741-8647-2cec9565fcca@gmail.com>
Message-ID: <t06bqv$aqe$1@ciao.gmane.io>

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: <caf29f4f-cf1f-c8dd-438c-f48e00c017cf@gmail.com>
References: <caf29f4f-cf1f-c8dd-438c-f48e00c017cf@gmail.com>
Message-ID: <t06clf$150b$1@ciao.gmane.io>

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: <dd99dd61-ea92-7e4c-450c-b31848e94514@gmail.com>
References: <fba919b5-c358-7744-5707-bc2de0e3f2b4@gmail.com>
 <t04r2d$upa$1@ciao.gmane.io> <dd99dd61-ea92-7e4c-450c-b31848e94514@gmail.com>
Message-ID: <t06d58$14qe$1@ciao.gmane.io>

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: <caf29f4f-cf1f-c8dd-438c-f48e00c017cf@gmail.com>
References: <caf29f4f-cf1f-c8dd-438c-f48e00c017cf@gmail.com>
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>
 <lccc2h95t8uhu6id2q2flcapcv14ik424a@4ax.com>
 <vsfc2h1c10bq2tvekl188oopv99q2vcblm@4ax.com>
Message-ID: <m4re2h5vgltst1lmt9c5loglqs1nhi7gkv@4ax.com>


		o/~		Talking to myself in public...	o/~

On Mon, 07 Mar 2022 13:28:49 -0500, Dennis Lee Bieber
<wlfraed at ix.netcom.com> 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: <m4re2h5vgltst1lmt9c5loglqs1nhi7gkv@4ax.com>
References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch>
 <38q92hli62o5rr01oi46d9quoo8i4v8fdf@4ax.com>
 <lccc2h95t8uhu6id2q2flcapcv14ik424a@4ax.com>
 <vsfc2h1c10bq2tvekl188oopv99q2vcblm@4ax.com>
 <m4re2h5vgltst1lmt9c5loglqs1nhi7gkv@4ax.com>
Message-ID: <CALaREKY7jj_wiiyOhoPkiPHSSQZbR2XvnpVyaJbUPp0KTRN-zw@mail.gmail.com>

>
>  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 <wlfraed at ix.netcom.com>
wrote:

>
>                 o/~             Talking to myself in public...  o/~
>
> On Mon, 07 Mar 2022 13:28:49 -0500, Dennis Lee Bieber
> <wlfraed at ix.netcom.com> 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: <caf29f4f-cf1f-c8dd-438c-f48e00c017cf@gmail.com>
 <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: <caf29f4f-cf1f-c8dd-438c-f48e00c017cf@gmail.com>
 <2dbb4e82-8c14-7b7a-a018-d271e27563ff@web.de>
 <4a4f81d5-cb83-8cba-a6e3-2dd3440fe261@gmail.com>
Message-ID: <u6rf2hdf27l9p15qrkqofu4g7k8qe5ab50@4ax.com>

On Wed, 9 Mar 2022 10:17:26 +1100, Phil <phillor9 at gmail.com> 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: <u6rf2hdf27l9p15qrkqofu4g7k8qe5ab50@4ax.com>
References: <caf29f4f-cf1f-c8dd-438c-f48e00c017cf@gmail.com>
 <2dbb4e82-8c14-7b7a-a018-d271e27563ff@web.de>
 <4a4f81d5-cb83-8cba-a6e3-2dd3440fe261@gmail.com>
 <u6rf2hdf27l9p15qrkqofu4g7k8qe5ab50@4ax.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: <t04q15$mgi$1@ciao.gmane.io>
References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch>
 <t01ter$3um$1@ciao.gmane.io> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch>
 <t04q15$mgi$1@ciao.gmane.io>
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 <tutor-bounces+marcus.luetolf=bluewin.ch at python.org> 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>
 <t01ter$3um$1@ciao.gmane.io> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch>
 <t04q15$mgi$1@ciao.gmane.io> <000801d833ed$78111200$68333600$@bluewin.ch>
Message-ID: <t0b5k8$tab$1@ciao.gmane.io>

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>
 <t01ter$3um$1@ciao.gmane.io> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch>
 <t04q15$mgi$1@ciao.gmane.io> <000801d833ed$78111200$68333600$@bluewin.ch>
Message-ID: <rsbi2hp6fp0oe8dv62qq7pg4t8h1kd8p1d@4ax.com>

On Wed, 9 Mar 2022 20:39:56 +0100, <marcus.luetolf at bluewin.ch> 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:
		<NOT SHOWN AS IT GIVES AWAY TOO MUCH>
		<still assumes letter pairs do not have to be adjacent>
 		
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>
 <t01ter$3um$1@ciao.gmane.io> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch>
 <t04q15$mgi$1@ciao.gmane.io> <000801d833ed$78111200$68333600$@bluewin.ch>
 <rsbi2hp6fp0oe8dv62qq7pg4t8h1kd8p1d@4ax.com>
Message-ID: <upii2h9e79e00ajt4sjrvlgrf5gvf96grl@4ax.com>

On Wed, 09 Mar 2022 19:42:09 -0500, Dennis Lee Bieber
<wlfraed at ix.netcom.com> 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: <CAO1OCwYYP0EBOM6oVzcZTaOUrdav+hVVjbkuoVGZkCtJMT-snw@mail.gmail.com>

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: <CAO1OCwYYP0EBOM6oVzcZTaOUrdav+hVVjbkuoVGZkCtJMT-snw@mail.gmail.com>
References: <CAO1OCwYYP0EBOM6oVzcZTaOUrdav+hVVjbkuoVGZkCtJMT-snw@mail.gmail.com>
Message-ID: <t0dd76$772$1@ciao.gmane.io>

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: <CACNWyvciUvKHR=mEO_u_hGjF8OHzVtHRckHPs_q9Wwn211By-A@mail.gmail.com>

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: <cbb73658-ae9f-3946-0313-524bdb381042@DancesWithMice.info>

"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: <CAL=yKz+cAF-ZtCB+pW+NG3Fa=u_EvagUWKB5a3qbroNy=ueaKw@mail.gmail.com>

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: <CAO1OCwbfqb6c-ShxcEfXVopSjjEZw0hiNY7fj+xGD1iq5sUT4A@mail.gmail.com>

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: <CAO1OCwbfqb6c-ShxcEfXVopSjjEZw0hiNY7fj+xGD1iq5sUT4A@mail.gmail.com>
References: <CAO1OCwbfqb6c-ShxcEfXVopSjjEZw0hiNY7fj+xGD1iq5sUT4A@mail.gmail.com>
Message-ID: <CAO1OCwY=BEO6yB918visuMkT6tJ3XmR=7b8ndqLc9S4G2DzKCA@mail.gmail.com>

  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 <manpritsinghece at gmail.com>
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: <CAO1OCwY=BEO6yB918visuMkT6tJ3XmR=7b8ndqLc9S4G2DzKCA@mail.gmail.com>
References: <CAO1OCwbfqb6c-ShxcEfXVopSjjEZw0hiNY7fj+xGD1iq5sUT4A@mail.gmail.com>
 <CAO1OCwY=BEO6yB918visuMkT6tJ3XmR=7b8ndqLc9S4G2DzKCA@mail.gmail.com>
Message-ID: <t0kn74$kdm$1@ciao.gmane.io>

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 <manpritsinghece at gmail.com>
> 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: <CAL=yKz+cAF-ZtCB+pW+NG3Fa=u_EvagUWKB5a3qbroNy=ueaKw@mail.gmail.com>
References: <CAL=yKz+cAF-ZtCB+pW+NG3Fa=u_EvagUWKB5a3qbroNy=ueaKw@mail.gmail.com>
Message-ID: <t0kngg$4ni$1@ciao.gmane.io>

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: <CAO1OCwY=BEO6yB918visuMkT6tJ3XmR=7b8ndqLc9S4G2DzKCA@mail.gmail.com>
References: <CAO1OCwbfqb6c-ShxcEfXVopSjjEZw0hiNY7fj+xGD1iq5sUT4A@mail.gmail.com>
 <CAO1OCwY=BEO6yB918visuMkT6tJ3XmR=7b8ndqLc9S4G2DzKCA@mail.gmail.com>
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 <manpritsinghece at gmail.com>
 > 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: <t0kn74$kdm$1@ciao.gmane.io>
References: <CAO1OCwbfqb6c-ShxcEfXVopSjjEZw0hiNY7fj+xGD1iq5sUT4A@mail.gmail.com>
 <CAO1OCwY=BEO6yB918visuMkT6tJ3XmR=7b8ndqLc9S4G2DzKCA@mail.gmail.com>
 <t0kn74$kdm$1@ciao.gmane.io>
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: <CAO1OCwYZpYTy9ZMheXNjpd03JGeASLqZ6=Zz=8jNGgC-NXP-LQ@mail.gmail.com>

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: <CAO1OCwYZpYTy9ZMheXNjpd03JGeASLqZ6=Zz=8jNGgC-NXP-LQ@mail.gmail.com>
References: <CAO1OCwYZpYTy9ZMheXNjpd03JGeASLqZ6=Zz=8jNGgC-NXP-LQ@mail.gmail.com>
Message-ID: <Yi/HhreeCcWExE5s@cskk.homeip.net>

On 14Mar2022 21:38, Manprit Singh <manpritsinghece at gmail.com> 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 <cs at cskk.id.au>

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: <CAO1OCwYZpYTy9ZMheXNjpd03JGeASLqZ6=Zz=8jNGgC-NXP-LQ@mail.gmail.com>
References: <CAO1OCwYZpYTy9ZMheXNjpd03JGeASLqZ6=Zz=8jNGgC-NXP-LQ@mail.gmail.com>
Message-ID: <t0onb7$13j9$1@ciao.gmane.io>

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: <CAO1OCwYZpYTy9ZMheXNjpd03JGeASLqZ6=Zz=8jNGgC-NXP-LQ@mail.gmail.com>
 <Yi/HhreeCcWExE5s@cskk.homeip.net>
Message-ID: <cepv2hd8fp9umml912u2qgimlk7i7pquqb@4ax.com>

On Tue, 15 Mar 2022 09:53:58 +1100, Cameron Simpson <cs at cskk.id.au>
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: <t0onb7$13j9$1@ciao.gmane.io>
References: <t0onb7$13j9$1@ciao.gmane.io>
Message-ID: <Yi/wuErDHGqgZr+A@cskk.homeip.net>

On 15Mar2022 00:41, Alan Gauld <alan.gauld at yahoo.co.uk> 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 <cs at cskk.id.au>

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: <cepv2hd8fp9umml912u2qgimlk7i7pquqb@4ax.com>
References: <CAO1OCwYZpYTy9ZMheXNjpd03JGeASLqZ6=Zz=8jNGgC-NXP-LQ@mail.gmail.com>
 <Yi/HhreeCcWExE5s@cskk.homeip.net>
 <cepv2hd8fp9umml912u2qgimlk7i7pquqb@4ax.com>
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 <cs at cskk.id.au>
> 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: <CAO1OCwYZpYTy9ZMheXNjpd03JGeASLqZ6=Zz=8jNGgC-NXP-LQ@mail.gmail.com>
 <Yi/HhreeCcWExE5s@cskk.homeip.net>
 <cepv2hd8fp9umml912u2qgimlk7i7pquqb@4ax.com>
 <2ff5651e-85b0-dc8f-224e-8bee30a3aba1@DancesWithMice.info>
Message-ID: <i2613h1028iai0qq3f30g2tnhgsfo880t3@4ax.com>

On Tue, 15 Mar 2022 15:28:13 +1300, dn <PythonList at DancesWithMice.info>
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: <CAO1OCwYZpYTy9ZMheXNjpd03JGeASLqZ6=Zz=8jNGgC-NXP-LQ@mail.gmail.com>
 <t0onb7$13j9$1@ciao.gmane.io>
Message-ID: <9h713hhaub194o55le9rqlk5rmt46phcl1@4ax.com>

On Tue, 15 Mar 2022 00:41:11 +0000, Alan Gauld via Tutor <tutor at python.org>
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: <i2613h1028iai0qq3f30g2tnhgsfo880t3@4ax.com>
References: <CAO1OCwYZpYTy9ZMheXNjpd03JGeASLqZ6=Zz=8jNGgC-NXP-LQ@mail.gmail.com>
 <Yi/HhreeCcWExE5s@cskk.homeip.net>
 <cepv2hd8fp9umml912u2qgimlk7i7pquqb@4ax.com>
 <2ff5651e-85b0-dc8f-224e-8bee30a3aba1@DancesWithMice.info>
 <i2613h1028iai0qq3f30g2tnhgsfo880t3@4ax.com>
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 <PythonList at DancesWithMice.info>
> 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: <CAP=pCP=wEXCuS_0hUuMCbu5t=CbT-GSfoM9AP_MOZGEOJGWRyA@mail.gmail.com>

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: <CAP=pCP=wEXCuS_0hUuMCbu5t=CbT-GSfoM9AP_MOZGEOJGWRyA@mail.gmail.com>
References: <CAP=pCP=wEXCuS_0hUuMCbu5t=CbT-GSfoM9AP_MOZGEOJGWRyA@mail.gmail.com>
Message-ID: <t0u12h$16a$1@ciao.gmane.io>

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: <t04q15$mgi$1@ciao.gmane.io>
References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch>
 <t01ter$3um$1@ciao.gmane.io> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch>
 <t04q15$mgi$1@ciao.gmane.io>
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 <tutor-bounces+marcus.luetolf=bluewin.ch at python.org> 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>
 <t01ter$3um$1@ciao.gmane.io> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch>
 <t04q15$mgi$1@ciao.gmane.io> <001301d83a0c$746c1ad0$5d445070$@bluewin.ch>
Message-ID: <u0k63hp8grgc17s6onf6pv8rmpfq20ad13@4ax.com>

On Thu, 17 Mar 2022 15:36:57 +0100, <marcus.luetolf at bluewin.ch> 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... <G>
>
>>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 <G>. 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>
 <t01ter$3um$1@ciao.gmane.io> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch>
 <t04q15$mgi$1@ciao.gmane.io> <001301d83a0c$746c1ad0$5d445070$@bluewin.ch>
 <u0k63hp8grgc17s6onf6pv8rmpfq20ad13@4ax.com>
Message-ID: <tor63htckvap88seodltoobrop3p3hja5d@4ax.com>

On Thu, 17 Mar 2022 12:38:04 -0400, Dennis Lee Bieber
<wlfraed at ix.netcom.com> declaimed the following:

	Just additional musing...

>On Thu, 17 Mar 2022 15:36:57 +0100, <marcus.luetolf at bluewin.ch> 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 r<n (technically,
r=n has ONE solution -- the entire source pool as the only element)

C:\Users\Wulfraed\Documents\_Hg-Repositories\REXX>letters.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: <CAP=pCP=ywO=5Ay9AzfPDWr4sTetsipOvGnXRc_2F8EzFEXA6SA@mail.gmail.com>

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: <t04q15$mgi$1@ciao.gmane.io>
References: <000001d83129$f99e9750$ecdbc5f0$@bluewin.ch>
 <t01ter$3um$1@ciao.gmane.io> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch>
 <t04q15$mgi$1@ciao.gmane.io>
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 <tutor-bounces+marcus.luetolf=bluewin.ch at python.org> 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 <module>    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 <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 <mailto: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>
 <t01ter$3um$1@ciao.gmane.io> <000401d831f7$3f9c7150$bed553f0$@bluewin.ch>
 <t04q15$mgi$1@ciao.gmane.io> <000f01d83ac9$0e1cde00$2a569a00$@bluewin.ch>
Message-ID: <7p893h9rvomtk1pk8gjsris9elmmkg17ip@4ax.com>

On Fri, 18 Mar 2022 14:07:00 +0100, <marcus.luetolf at bluewin.ch> 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, <marcus.luetolf at bluewin.ch> 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 <module>    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 <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,  <mailto:marcus.luetolf at bluewin.ch> 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, <marcus.luetolf at bluewin.ch> 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: <l54a3h905f1gfb40e11lj69grj2sgcj9ru@4ax.com>

On Fri, 18 Mar 2022 18:16:04 +0000, Alan G via Tutor <tutor at python.org>
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 <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 <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 <mailto: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 <mailto:alan.gauld at yahoo.co.uk>  <alan.gauld at yahoo.co.uk <mailto:alan.gauld at yahoo.co.uk> > 
Gesendet: Freitag, 18. M?rz 2022 19:16
An: marcus.luetolf at bluewin.ch <mailto:marcus.luetolf at bluewin.ch> 
Cc: tutor at python.org <mailto:tutor at python.org> 
Betreff: Re: AW: AW: [Tutor] problem solving with lists

 

 

 

On 18 Mar 2022 15:12, marcus.luetolf at bluewin.ch <mailto: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, <marcus.luetolf at bluewin.ch> 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:

	<SNIP>

 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: <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>

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: <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
References: <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
Message-ID: <D4CAB064-9F71-4144-B3E8-A1000BF77429@yahoo.co.uk>

> * @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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
Message-ID: <bq0d3hlmbcbtos6er1is48mtv21i797ou2@4ax.com>

On Sun, 20 Mar 2022 09:35:53 +1300, dn <PythonList at DancesWithMice.info>
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 <G>).

	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? <G>


* 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: <DB7PR07MB5093DE538FA8257B19A33986E4159@DB7PR07MB5093.eurprd07.prod.outlook.com>

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: <bq0d3hlmbcbtos6er1is48mtv21i797ou2@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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <bq0d3hlmbcbtos6er1is48mtv21i797ou2@4ax.com>
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? <G>

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: <DB7PR07MB5093DE538FA8257B19A33986E4159@DB7PR07MB5093.eurprd07.prod.outlook.com>
References: <DB7PR07MB5093DE538FA8257B19A33986E4159@DB7PR07MB5093.eurprd07.prod.outlook.com>
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: <CALaREKb_yPnECLOoVh+ffx6foGDpHRD6NN5mOWyRaRpxR3fsRA@mail.gmail.com>

So what's wrong  with Dennis Bieber's answer?

On Sat, Mar 19, 2022 at 9:58 AM <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
>
> 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 <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 <mailto:
> 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 <mailto:alan.gauld at yahoo.co.uk>  <
> alan.gauld at yahoo.co.uk <mailto:alan.gauld at yahoo.co.uk> >
> Gesendet: Freitag, 18. M?rz 2022 19:16
> An: marcus.luetolf at bluewin.ch <mailto:marcus.luetolf at bluewin.ch>
> Cc: tutor at python.org <mailto:tutor at python.org>
> Betreff: Re: AW: AW: [Tutor] problem solving with lists
>
>
>
>
>
>
>
> On 18 Mar 2022 15:12, marcus.luetolf at bluewin.ch <mailto:
> 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: <cba479e9-56a6-ca50-d031-346a35ce0168@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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
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 <tutor-bounces+marcus.luetolf=bluewin.ch at python.org> 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>
 <CALaREKb_yPnECLOoVh+ffx6foGDpHRD6NN5mOWyRaRpxR3fsRA@mail.gmail.com>
Message-ID: <mtde3hp5fk3nq0i64q2boti62ptjr7bccc@4ax.com>

On Sat, 19 Mar 2022 10:34:00 -0400, Mayo Adams <mayoadams at gmail.com>
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 <G>) 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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <bq0d3hlmbcbtos6er1is48mtv21i797ou2@4ax.com>
 <5fcd5318-c555-9df7-e9b9-00c0b8efef22@DancesWithMice.info>
Message-ID: <6jge3hl6kcnjf6en6f7ga4k560qca95p54@4ax.com>

On Sun, 20 Mar 2022 16:35:44 +1300, dn <PythonList at DancesWithMice.info>
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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
Message-ID: <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>

On Sun, 20 Mar 2022 15:55:27 +0100, <marcus.luetolf at bluewin.ch> 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: <DB7PR07MB5093DE538FA8257B19A33986E4159@DB7PR07MB5093.eurprd07.prod.outlook.com>
 <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!

<end of pouring cold water on your ideas>

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: <DB7PR07MB5093DE538FA8257B19A33986E4159@DB7PR07MB5093.eurprd07.prod.outlook.com>
Message-ID: <m3ve3htvcpshlv6oleojj975sdtkebope0@4ax.com>

On Sun, 20 Mar 2022 02:13:52 +0000, Nathan Smith <nathan-tech at hotmail.com>
declaimed the following:

>path= 'c:\my folder\a file.zip\a folder in the zip'
>
	Just a comment... "\a" is a control character <BEL>. 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: <DB7PR07MB5093DE538FA8257B19A33986E4159@DB7PR07MB5093.eurprd07.prod.outlook.com>
References: <DB7PR07MB5093DE538FA8257B19A33986E4159@DB7PR07MB5093.eurprd07.prod.outlook.com>
Message-ID: <YjeiiM1uG3DJmx+f@cskk.homeip.net>

On 20Mar2022 02:13, nathan tech <nathan-tech at hotmail.com> 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 <cs at cskk.id.au>

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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
Message-ID: <ead4b518-4a7c-86df-2194-a4eeab9890ff@DancesWithMice.info>

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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
Message-ID: <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>

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, <marcus.luetolf at bluewin.ch> 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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <007a01d83d00$ce757c50$6b6074f0$@bluewin.ch>
Message-ID: <e5e0fddd-eabb-2204-3d1f-318171b979ec@DancesWithMice.info>

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: <e5e0fddd-eabb-2204-3d1f-318171b979ec@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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <007a01d83d00$ce757c50$6b6074f0$@bluewin.ch>
 <e5e0fddd-eabb-2204-3d1f-318171b979ec@DancesWithMice.info>
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 <tutor-bounces+marcus.luetolf=bluewin.ch at python.org> 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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
Message-ID: <pt8h3h5e4s4ievj6529j5ptfgu0cj47ejc@4ax.com>

On Mon, 21 Mar 2022 18:34:40 +1300, dn <PythonList at DancesWithMice.info>
declaimed the following:

>Have I managed to understand the problem, this time?
>
	Asking me? <G>

	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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
Message-ID: <f9gh3hdf67hj3d8pv1qkb4vld56ip39oho@4ax.com>

On Mon, 21 Mar 2022 18:34:40 +1300, dn <PythonList at DancesWithMice.info>
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: <pt8h3h5e4s4ievj6529j5ptfgu0cj47ejc@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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <pt8h3h5e4s4ievj6529j5ptfgu0cj47ejc@4ax.com>
Message-ID: <c4cc835b-755a-2a07-92c3-23381f76b740@DancesWithMice.info>

On 22/03/2022 05.38, Dennis Lee Bieber wrote:
> On Mon, 21 Mar 2022 18:34:40 +1300, dn <PythonList at DancesWithMice.info>
> declaimed the following:
> 
>> Have I managed to understand the problem, this time?
>>
> 	Asking me? <G>

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: <f9gh3hdf67hj3d8pv1qkb4vld56ip39oho@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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <f9gh3hdf67hj3d8pv1qkb4vld56ip39oho@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 <PythonList at DancesWithMice.info>
> 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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <f9gh3hdf67hj3d8pv1qkb4vld56ip39oho@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 <tutor-bounces+marcus.luetolf=bluewin.ch at python.org> 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 
> <PythonList at DancesWithMice.info> 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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <f9gh3hdf67hj3d8pv1qkb4vld56ip39oho@4ax.com>
 <58b3690c-4173-8ffa-5d57-6490dea20309@DancesWithMice.info>
Message-ID: <1fsj3h97u4a110u8396mmc63b66r7v8i5i@4ax.com>

On Tue, 22 Mar 2022 10:54:28 +1300, dn <PythonList at DancesWithMice.info>
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: <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
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 <tutor-bounces+marcus.luetolf=bluewin.ch at python.org> 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, <marcus.luetolf at bluewin.ch> 
> 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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch>
Message-ID: <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com>

On Wed, 23 Mar 2022 20:54:01 +0100, <marcus.luetolf at bluewin.ch> 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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch>
 <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com>
Message-ID: <q69p3h57jd6af5r21e5bn0kbfkbatcag6n@4ax.com>

On Thu, 24 Mar 2022 11:41:45 -0400, Dennis Lee Bieber
<wlfraed at ix.netcom.com> 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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <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, <marcus.luetolf at bluewin.ch> 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: <q69p3h57jd6af5r21e5bn0kbfkbatcag6n@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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch>
 <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com>
 <q69p3h57jd6af5r21e5bn0kbfkbatcag6n@4ax.com>
Message-ID: <db8076b0-a2df-4438-b091-9b06bd017c73@DancesWithMice.info>

On 25/03/2022 06.26, Dennis Lee Bieber wrote:
> On Thu, 24 Mar 2022 11:41:45 -0400, Dennis Lee Bieber
> <wlfraed at ix.netcom.com> 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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch>
 <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com>
 <683dcf73-ab97-48b8-f3d5-b20121b008d1@DancesWithMice.info>
Message-ID: <hgfr3hduj4t74gchps4b1ntrsfekhq3hbm@4ax.com>

On Fri, 25 Mar 2022 16:56:06 +1300, dn <PythonList at DancesWithMice.info>
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.

<SNIP>

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: <db8076b0-a2df-4438-b091-9b06bd017c73@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>
 <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch>
 <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com>
 <q69p3h57jd6af5r21e5bn0kbfkbatcag6n@4ax.com>
 <db8076b0-a2df-4438-b091-9b06bd017c73@DancesWithMice.info>
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 <tutor-bounces+marcus.luetolf=bluewin.ch at python.org> 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 
> <wlfraed at ix.netcom.com> 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: <cba479e9-56a6-ca50-d031-346a35ce0168@DancesWithMice.info>
 <003501d83c6a$89345da0$9b9d18e0$@bluewin.ch>
 <8jie3h9ndkudm85bbks4jhd3r572uhhi5k@4ax.com>
 <a9c3fe47-174d-bb1b-adad-3a790ad4cf2c@DancesWithMice.info>
 <000301d83eef$be69cbe0$3b3d63a0$@bluewin.ch>
 <9d3p3hht2vst1dni9iuokbd9qpunfa3j5c@4ax.com>
 <q69p3h57jd6af5r21e5bn0kbfkbatcag6n@4ax.com>
 <db8076b0-a2df-4438-b091-9b06bd017c73@DancesWithMice.info>
 <005901d840f3$7e838a10$7b8a9e30$@bluewin.ch>
Message-ID: <64gu3hpmbi8ji4sudga32m8happuv0jg8p@4ax.com>

On Sat, 26 Mar 2022 10:25:54 +0100, <marcus.luetolf at bluewin.ch> 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: <f5e36cc2-30e6-4677-7ef1-f7e9301c3a47@gmail.com>

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: <f5e36cc2-30e6-4677-7ef1-f7e9301c3a47@gmail.com>
References: <f5e36cc2-30e6-4677-7ef1-f7e9301c3a47@gmail.com>
Message-ID: <d7548e5b-0fcb-4b07-c2e1-61fa68ec1831@web.de>

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: <f5e36cc2-30e6-4677-7ef1-f7e9301c3a47@gmail.com>
Message-ID: <qbt84htrso3unk0td9gob4h00f9tp4hd85@4ax.com>

On Wed, 30 Mar 2022 17:35:00 +1100, Phil <phillor9 at gmail.com> 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 <G>

	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: <d7548e5b-0fcb-4b07-c2e1-61fa68ec1831@web.de>
References: <f5e36cc2-30e6-4677-7ef1-f7e9301c3a47@gmail.com>
 <d7548e5b-0fcb-4b07-c2e1-61fa68ec1831@web.de>
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: <f5e36cc2-30e6-4677-7ef1-f7e9301c3a47@gmail.com>
 <d7548e5b-0fcb-4b07-c2e1-61fa68ec1831@web.de>
 <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