[Tutor] problem solving with lists: final (amateur) solution
dn
PythonList at DancesWithMice.info
Sat Jun 25 20:34:54 EDT 2022
On 26/06/2022 06.45, marcus.luetolf at bluewin.ch wrote:
> Hello Experts, hello dn,
> it's a while since I - in terms of Mark Lawrence - bothered you with my
> problem.
> Thanks to your comments, especially to dn's structured guidance I've come up
> with the code below, based on repeatability.
> I am shure there is room for improvement concerning pythonish style but for
> the moment the code serves my purposes.
> A commented version can be found on
> https://github.com/luemar/player_startlist.
>
> def startlist(all_players, num_in_flight):
> c_all_players = all_players[:]
> history = {'a':[], 'b':[],'c':[],'d':[],'e':[],'f':[],'g':[],'h':[],\
> 'i':[],'j':[],'k':[],'l':[],'m':[],'n':[],'o':[],'p':[]}
> print('...............day_1................')
> def day_1_flights():
> key_hist = list(history.keys())
> c_key_hist = key_hist[:]
> for dummy_i in c_key_hist:
> print('flights_day_1: ', c_key_hist[:num_in_flight])
> for key in c_key_hist[:num_in_flight]:
> [history[key].append(player)for player in
> c_all_players[0:num_in_flight]]
> del c_key_hist[:num_in_flight]
> del c_all_players[0:num_in_flight]
> day_1_flights()
>
> def day_2_to_5_flights():
> flights = {}
> for i in range(2,6):
> print('...............day_' + str(i)+'................')
> flights['a_flight_day_'+str(i)]= []
> flights['b_flight_day_'+str(i)]= []
> flights['c_flight_day_'+str(i)]= []
> flights['d_flight_day_'+str(i)]= []
> lead = list('abcd')
> flight_list = [flights['a_flight_day_'+str(i)],
> flights['b_flight_day_'+str(i)],\
> flights['c_flight_day_'+str(i)],
> flights['d_flight_day_'+str(i)]]
>
> for j in range(len(flight_list)):
> def flight(cond, day):
> for player in all_players:
> if player not in cond:
> day.extend(player)
> cond.extend(history[player])
> history[lead[j]].extend(player)
> day.extend(lead[j])
> day.sort()
> [history[pl].extend(day) for pl in day[1:]]
> return lead[j]+'_flight_day_'+str(i)+ ': ' +
> str(flight_list[j])
>
> conditions = [history[lead[j]], history[lead[j]] +
> flights['a_flight_day_'+str(i)],\
> history[lead[j]] +
> flights['a_flight_day_'+str(i)] + \
> flights['b_flight_day_'+str(i)], \
> history[lead[j]] +
> flights['a_flight_day_'+str(i)] + \
> flights['b_flight_day_'+str(i)]+
> flights['c_flight_day_'+str(i)]]
> print(flight(list(set(conditions[j])), flight_list[j]))
> day_2_to_5_flights()
> startlist(list('abcdefghijklmnop'), 4)
>
> Many thanks, Marcus.
...
> The word "hardcoded" immediately stopped me in my tracks!
>
> The whole point of using the computer is to find 'repetition' and have the
> machine/software save us from such boredom (or nit-picking detail in which
> we might make an error/become bored).
...
> The other 'side' of both of these code-constructs is the data-construct.
> Code-loops require data-collections! The hard-coded "a" and "day_1" made me
> shudder.
> (not a pretty sight - the code, nor me shuddering!)
...
> Sadly, the 'hard-coded' parts may 'help' sort-out week-one, but (IMHO) have
> made things impossibly-difficult to proceed into week-two (etc).
...
It works. Well done!
What could be better than that?
[Brutal] critique:
- «pythonish» in German becomes «pythonic» in English (but I'm sure we
all understood)
- position the two inner-functions outside and before startlist()
- whereas the «4», ie number of players per flight (num_in_flight), is
defined as a parameter in the call to startlist(), the five «times or
days» is a 'magic constant' (worse, it appears in day_2_to_5_flights()
as part of «range(2,6)» which 'disguises' it due to Python's way of working)
- the comments also include reference to those parameters as if they are
constants (which they are - if you only plan to use the algorithm for
this 16-4-5 configuration of the SGP). Thus, if the function were called
with different parameters, the comments would be not only wrong but have
the potential to mislead the reader
- in the same vein (as the two points above), the all_players (variable)
argument is followed by the generation of history as a list of constants
(«constant» cf «variable»)
- on top of which: day_1_flights() generates key_hist from history even
though it already exists as all_players
- the Python facility for a 'dummy value' (that will never be used, or
perhaps only 'plugged-in' to 'make things happen') is _ (the
under-score/under-line character), ie
for _ in c_key_hist:
- an alternative to using a meaningless 'placeholder' with no
computational-purpose, such as _ or dummy_i, is to choose an identifier
which aids readability, eg
for each_flight in c_key_hist
- well done for noting that a list-comprehension could be used to
generate history/ies. Two thoughts:
1 could the two for-loops be combined into a single nested
list-comprehension?
2 does the reader's mind have to 'change gears' between reading the
outer for-loop as a 'traditional-loop' structure, and then the
inner-loop as a list-comprehension? ie would it be better to use the
same type of code-construct for both?
- both the code- and data-structures of day_1_flights() seem rather
tortured (and tortuous), and some are unused and therefore unnecessary.
Might it be possible to simplify, if the control-code commences with:
for first_player_index in range( 0, len( all_players ), num_in_flight ):
print( first_player_index,
all_players[ first_player_index:
first_player_index+num_in_flight
]
)
NB the print() is to make the methodology 'visible'.
- the docstring for day_1_flights() is only partly-correct. Isn't the
function also creating and building the history set?
- that being the case, should the initial set-definition be moved inside
the function?
- functions should not depend upon global values. How does the history
'pass' from one function to another - which is allied to the question:
how do the functions know about values such as _all_players and
num_in_flight? To make the functions self-contained and «independent»,
these values should be passed-in as parameters/arguments and/or return-ed
- much of the above also applies to day_2_to_5_flights()
- chief concern with day_2_to_5_flights() is: what happens to
d_flight_day_N if there are fewer/more than four players per flight, or
what if there are fewer/more than 5 flights?
- the observation that the same players would always be the 'lead' of a
flight, is solid. Thus, could the lead-list be generated from a
provided-parameter, rather than stated as a constant? Could that
construct (also) have been used in the earlier function?
- we know (by definition) that flight() is an unnecessary set of
conditions to apply during day_1, but could it be used nonetheless? If
so, could day_1_flights() be 'folded into' day_2_to_5_flights() instead
of having separate functions?
(yes, I recall talking about the essential differences in an earlier
post - and perhaps I'm biased because this was how I structured the
draft-solution)
[More than] enough for now?
--
Regards,
=dn
More information about the Tutor
mailing list