Track
/
Python
Python
/
Esercizi
/
Giochi di carte
Giochi di carte

Giochi di carte

Esercizio di apprendimento

Introduzione

Un list è una collezione mutabile di elementi in sequenza. Come la maggior parte delle collezioni (vedi i tipi incorporati tuple, dict e set), gli array possono contenere riferimenti a qualsiasi tipo (o più tipi) di dato, compresi altri array. Come qualsiasi sequenza, si può accedere agli elementi tramite un numero 0-based index da sinistra e -1-based index da destra. Gli array si possono copiare del tutto o in parte tramite la notazione slice o <list>.copy().

Gli array supportano sia le operazioni comuni sia le operazioni mutabili delle sequenze, come min()/max(), <list>.index(), <list>.append() e <list>.reverse(). Si può iterare sugli elementi di un array usando il costrutto for item in <list>. for index, item in enumerate(<list>) si può usare quando servono sia l'indice sia il valore dell'elemento.

Sotto il cofano, lists sono implementati come array dinamici, simili al tipo ArrayList di Java, e vengono usati per lo più per memorizzare gruppi di dati simili (stringhe, numeri, set ecc.) di lunghezza sconosciuta. Gli array sono una struttura dati estremamente flessibile e utile, e molti metodi e operazioni incorporati in Python producono array come risultato.

Costruzione

Un list si può dichiarare come letterale con parentesi quadre [] e virgole tra gli elementi:

>>> no_elements = []

>>> no_elements
[]

>>> one_element = ["Guava"]

>>> one_element
['Guava']

>>> elements_separated_with_commas = ["Parrot", "Bird", 334782]

>>> elements_separated_with_commas
['Parrot', 'Bird', 334782]

Per una maggiore leggibilità, si possono usare gli a capo quando ci sono molti elementi o strutture dati annidate dentro un list:

>>> lots_of_entries = [
      "Rose",
      "Sunflower",
      "Poppy",
      "Pansy",
      "Tulip",
      "Fuchsia",
      "Cyclamen",
      "Lavender"
   ]
   
>>> lots_of_entries
['Rose', 'Sunflower', 'Poppy', 'Pansy', 'Tulip', 'Fuchsia', 'Cyclamen', 'Lavender']

# Each data structure is on its own line to help clarify what they are.
>>> nested_data_structures = [
      {"fish": "gold", "monkey": "brown", "parrot": "grey"},
      ("fish", "mammal", "bird"),
      ['water', 'jungle', 'sky']
   ]
   
>>> nested_data_structures
[{'fish': 'gold', 'monkey': 'brown', 'parrot': 'grey'}, ('fish', 'mammal', 'bird'), ['water', 'jungle', 'sky']]

Il costruttore list() si può usare vuoto oppure con un iterabile come argomento. Il costruttore percorre ciclicamente gli elementi dell'iterabile e li aggiunge al list in ordine:

>>> no_elements = list()

>>> no_elements
[]

# The tuple is unpacked and each element is added.
>>> multiple_elements_from_tuple = list(("Parrot", "Bird", 334782))

>>> multiple_elements_from_tuple
['Parrot', 'Bird', 334782]

# The set is unpacked and each element is added.
>>> multiple_elements_from_set = list({2, 3, 5, 7, 11})

>>> multiple_elements_from_set
[2, 3, 5, 7, 11]

I risultati dell'uso del costruttore list con una string o un dict possono sorprendere:

# String elements (Unicode code points) are iterated through and added *individually*.
>>> multiple_elements_string = list("Timbuktu")

>>> multiple_elements_string
['T', 'i', 'm', 'b', 'u', 'k', 't', 'u']

# Unicode separators and positioning code points are also added *individually*.
>>> multiple_code_points_string = list('अभ्यास')

>>> multiple_code_points_string
['अ', 'भ', '्', 'य', 'ा', 'स']

# The iteration default for dictionaries is over the keys, so only key data is inserted into the list.
>>> source_data = {"fish": "gold", "monkey": "brown"}

>>> multiple_elements_dict_1 = list(source_data)
['fish', 'monkey']

Dato che il costruttore list accetta solo iterabili (o nulla) come argomenti, gli oggetti che non sono iterabili generano un errore di tipo. Di conseguenza, è molto più facile creare un list con un solo elemento usando il metodo letterale.

# Numbers are not iterable, and so attempting to create a list with a number passed to the constructor fails.
>>> one_element = list(16)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable

# Tuples *are* iterable, so passing a one-element tuple to the constructor does work, but it's awkward
>>> one_element_from_iterable = list((16,))

>>> one_element_from_iterable
[16]

Accesso agli elementi

Agli elementi dentro gli array (così come a quelli in altri tipi sequenza come str e tuple) si può accedere tramite un numero 0-based index e la notazione con parentesi. Gli indici possono andare da left --> right (partendo da zero) oppure da right --> left (partendo da -1).

indice da sinistra ⟹






0
👇🏾
1
👇🏾
2
👇🏾
3
👇🏾
4
👇🏾
5
👇🏾
P y t h o n
👆🏾
-6
👆🏾
-5
👆🏾
-4
👆🏾
-3
👆🏾
-2
👆🏾
-1





⟸ indice da destra
>>> breakfast_foods = ["Oatmeal", "Fruit Salad", "Eggs", "Toast"]

# Oatmeal is at index 0 or index -4.
>>> breakfast_foods[0]
'Oatmeal'

>>> breakfast_foods[-4]
'Oatmeal'

# Eggs are at index -2 or 2
>>> breakfast_foods[-2]
'Eggs'

>>> breakfast_foods[2]
'Eggs'

# Toast is at -1
>>> breakfast_foods[-1]
'Toast'

Si può accedere a una parte degli elementi dentro un list tramite la notazione slice (<list>[start:stop]). Una slice è definita come una sequenza di elementi in posizione index, tale che start <= index < stop. Lo slicing restituisce una copia degli elementi «sliced» e non modifica il list originale.

Si può anche usare un parametro step [start:stop:step] per «saltare» o filtrare gli elementi del list (per esempio, uno step di 2 seleziona un elemento sì e uno no nell'intervallo):

>>> colors = ["Red", "Purple", "Green", "Yellow", "Orange", "Pink", "Blue", "Grey"]

# If there is no step parameter, the step is assumed to be 1.
>>> middle_colors = colors[2:6]

>>> middle_colors
['Green', 'Yellow', 'Orange', 'Pink']

# If the start or stop parameters are omitted, the slice will
# start at index zero, and will stop at the end of the list.
>>> primary_colors = colors[::3]

>>> primary_colors
['Red', 'Yellow', 'Blue']

Lavorare con gli array

Usare la funzione incorporata sum() su un array restituisce la somma di tutti i numeri dell'array:

>>> number_list = [1, 2, 3, 4]
>>> sum(number_list)
10

Puoi anche ottenere la lunghezza di un array usando la funzione len():

>>> long_list = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
>>> len(long_list)
10

Gli array si possono anche combinare in vari modi:

# Using the plus + operator unpacks each list and creates a new list, but it is not efficient.
>>> new_via_concatenate = ["George", 5] + ["cat", "Tabby"]

>>> new_via_concatenate
['George', 5, 'cat', 'Tabby']

# Likewise, using the multiplication operator * is the equivalent of using + n times.
>>> first_group = ["cat", "dog", "elephant"]
>>> multiplied_group = first_group * 3

>>> multiplied_group
['cat', 'dog', 'elephant', 'cat', 'dog', 'elephant', 'cat', 'dog', 'elephant']

Gli array forniscono un iteratore e si possono percorrere in ciclo allo stesso modo degli altri tipi sequenza.

#  Looping through the list and printing out each element.
>>> colors = ["Orange", "Green", "Grey", "Blue"]

>>> for item in colors:
...     print(item)
...
Orange
Green
Grey
Blue

Per una spiegazione più approfondita di loops e iterators, completa il concetto loops.

Istruzioni

Elyse non vede l'ora di giocare un po' di poker (e ad altri giochi di carte) durante il suo prossimo viaggio a Las Vegas. Essendo una grande appassionata di «self-tracking», vuole creare alcune piccole funzioni che la aiuteranno a tenere traccia delle sue attività e ti ha chiesto di aiutarla a ragionarci su.

1. Tenere traccia dei round di poker

Elyse è particolarmente appassionata di poker e vuole tenere traccia di quanti round gioca, e di quali sono. Ogni round ha il suo numero e ogni tavolo mostra il numero del round in corso. Elyse sceglie un tavolo e si siede per giocare il suo primo round. Ha intenzione di giocare tre round.

Implementa una funzione get_rounds(<round_number>) che prende il numero del round attuale e restituisce una singola list con quel round e i due successivi in arrivo:

>>> get_rounds(27)
[27, 28, 29]

2. Tenere tutti i round nello stesso posto

Elyse ha giocato qualche round al primo tavolo, poi ha fatto una pausa e ha giocato altri round a un secondo tavolo... ma è finita con un array diverso per ogni tavolo! Vuole unire i due array, così può tenere traccia di tutti i round di poker nello stesso posto.

Implementa una funzione concatenate_rounds(<rounds_1>, <rounds_2>) che prende due array e restituisce un unico list formato da tutti i round del primo array, seguiti da tutti i round del secondo array:

>>> concatenate_rounds([27, 28, 29], [35, 36])
[27, 28, 29, 35, 36]

3. Trovare i round precedenti

Parlando di alcuni dei round di poker precedenti, un altro giocatore fa notare quanto due di essi si siano svolti in modo simile. Elyse non è sicura di aver giocato quei round o no.

Implementa una funzione list_contains_round(<rounds>, <round_number>) che prende due argomenti, un array di round giocati e un numero di round. La funzione restituirà True se il round è nell'array dei round giocati, False in caso contrario:

>>> list_contains_round([27, 28, 29, 35, 36], 29)
True

>>> list_contains_round([27, 28, 29, 35, 36], 30)
False

4. Calcolare la media dei valori delle carte

Elyse vuole provare un nuovo gioco chiamato Black Joe. È simile al Black Jack, dove l'obiettivo è che le carte in mano sommino a un valore target, ma in Black Joe l'obiettivo è che la media dei valori delle carte sia 7. La media si trova sommando tutti i valori delle carte e poi dividendo quella somma per il numero di carte in mano.

Implementa una funzione card_average(<hand>) che restituirà il valore medio di una mano di Black Joe.

>>> card_average([5, 6, 7])
6.0

5. Medie alternative

In Black Joe la velocità è importante. Elyse proverà a trovare un modo più veloce per calcolare la media.

Ha pensato a due modi per ottenere un numero simile a una media:

  • Fare la media del primo e dell'ultimo numero in mano.
  • Usare la mediana (la carta centrale) della mano.

Implementa la funzione approx_average_is_average(<hand>), dato hand, un array contenente i valori delle carte in mano.

Restituisci True se una or entrambe le strategie sopra citate danno come risultato un numero uguale alla media reale.

Nota: la lunghezza di tutte le mani è dispari, per rendere più facile trovare la mediana.

>>> approx_average_is_average([1, 2, 3])
True

>>> approx_average_is_average([2, 3, 4, 8, 8])
True

>>> approx_average_is_average([1, 2, 3, 5, 9])
False

6. Altre tecniche di media

Incuriosita dai risultati del suo esperimento sulle medie, Elyse si chiede se fare la media delle carte nelle posizioni pari rispetto alla media delle carte nelle posizioni dispari darebbe gli stessi risultati. È il momento di un'altra funzione di test!

Implementa una funzione average_even_is_average_odd(<hand>) che restituisce un valore booleano che indica se la media delle carte agli indici pari è uguale alla media delle carte agli indici dispari.

>>> average_even_is_average_odd([1, 2, 3])
True

>>> average_even_is_average_odd([1, 2, 3, 4])
False

7. Regole del round bonus

Ogni 11ª mano in Black Joe è una mano bonus con una regola bonus: se l'ultima carta che peschi è un fante, raddoppi il suo valore.

Implementa una funzione maybe_double_last(<hand>) che prende una mano e verifica se l'ultima carta è un fante (11). Se l'ultima carta è un fante (11), raddoppia il suo valore prima di restituire la mano.

>>> hand = [5, 9, 11]
>>> maybe_double_last(hand)
[5, 9, 22]

>>> hand = [5, 9, 10]
>>> maybe_double_last(hand)
[5, 9, 10]
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Python Exercism

Vuoi iniziare Giochi di carte?

Iscriviti a Exercism per imparare e padroneggiare Python con 17 concetti146 esercizi e il mentoring di persone reali, tutto gratis.