Lab07 - PROGETTI SU SLICE ========================= Lessico ------- Scrivere un programma lessico.go che - stampa il seguente menu di opzioni + (Legge una riga e memorizza le parole) ? (Legge una parola e indica le righe che la contengono) p (Stampa le parole) - legge stringhe da standard input - il programma termina quando riceve un "end of file" (cioè EOF, pressione di 'CTRL-d') Se la stringa inizia con: - "+" (alimenta dizionario): il programma usa il rimanente della riga e memorizza in un "dizionario" le parole che la costituiscono; - "?" (consulta dizionario): il programma usa il rimanente della riga e stampa i numeri di riga del dizionario in cui è comparsa la stringa; - "p" (print): il programma stampa le parole presenti nel "dizionario", con l’elenco dei numeri di riga in cui compaiono; Esempio ------- + (Legge una riga e memorizza le parole) ? (Legge una parola e indica le riga che la contengono) p (Stampa le parole) + la befana ha il fazzoletto e la gonna rattoppata p map[rattoppata:[1] la:[1 1] befana:[1] ha:[1] il:[1] fazzoletto:[1] e:[1] gonna:[1]] + ma quest'anno poverina la befana è raffreddata ? la parola: la righe [1 1 2] ? befana parola: befana righe [1 2] ? il parola: il righe [1] p map[raffreddata:[2] la:[1 1 2] il:[1] fazzoletto:[1] ma:[2] quest'anno:[2] poverina:[2] è:[2] befana:[1 2] ha:[1] e:[1] gonna:[1] rattoppata:[1]] ____________________________________________________ Stack ----- Creare un programma stack.go che gestisca uno stack (pila) generico (numero arbitrario di posizioni) di valori float Lo stack e` una struttura dati con le seguenti caratteristiche: - mantiene nella prima posizione (detta testa) il valore piu' recente - e` possibile accedere sempre e solo alla sua testa Le operazioni disponibili sullo stack sono: - push: aggiunge un valore in testa allo stack - pop: rimuove il valore in testa allo stack e lo restituisce - top (o peek): restituisce il valore in testa allo stack senza rimuoverlo - empty: restituisce vero se lo stack e` vuoto, falso altrimenti Per ciascuna operazione creare una funzione, usando nomi maiuscoli (Push, Pop, ...). Implementare poi una funzione main() che chieda ripetutamente all'utente quale operazione vuole richiedere (push/pop/top/empty/quit), nel caso di push chieda anche il valore da aggiungere, stampi ogni volta il risultato e lo stack, e termini con quit. Esempio ------- Operazione (push/pop/top/empty/quit)? push valore? 4 [4] Operazione (push/pop/top/empty/quit)? push valore? 5 [5 4] Operazione (push/pop/top/empty/quit)? pop testa 5 [4] Operazione (push/pop/top/empty/quit)? top testa 4 [4] Operazione (push/pop/top/empty/quit)? quit Nota: per interrompere un for da uno switch annidato, occorre etichettare il for e aggiungere l'etichetta al break: myloop: for ....{ .... break myloop } Versione 1: Usare per lo stack una variabile globale e per semplicita` implementare lo stack con una slice in cui la testa dello stack e` l'ultimo elemento (quello in posizione len(stack)-1). Versione 2: implementare lo stack con una slice in cui la testa dello stack e` il primo elemento (quello in posizione 0) Suggerimento: e` possibile appendere a una slice s1 un'altra slice s2 usando ... per espandere s2 a una lista di argomenti: append(s1, s2...) e creando una slice che contenga la nuova testa: []float64{val} Versione 3: Usare per lo stack una variabile locale del main e quindi passarlo come parametro alle funzioni (usare puntatori). Per accedere a un elemento di una slice di cui si ha il puntatore la sintassi e`: (*stack)[i] ____________________________________________________ Calcolatrice RPN ---------------- Creare una sottodir stack in cui spostare la versione 3 del programma stack.go. Modificare il nome del pacchetto in "stack" invece che main e commentare la funzione main(). Creare un programma RPN.go che importa "./stack". Il programma deve realizzare una calcolatrice in notazione polacca inversa (RPN), o notazione postfissa (https://it.wikipedia.org/wiki/Notazione_polacca_inversa), notazione in cui prima si inseriscono gli operandi e poi gli operatori: ad esempio 3 4 + 5 * invece che (3 + 4) * 5, e 3 4 5 * + invece di 3 + 4 * 5. La calcolatrice deve disporre delle quattro operazioni aritmetiche (+ - * /) e operare su valori float64. Il funzionamento e` il seguente: ripetere: - leggere un input dall'utente - se e` un numero, lo mette in testa allo stack (una push) - se e` un operatore, - preleva gli operandi dallo stack (due pop) - esegue l'operazione corrispondente all'operatore (+ - * /) - salva il risultato nello stack (push) - condizione di uscita: inserimento di "q" (quit) - condizioni di errore: mancanza di operandi Nel caso l'input non sia ne' un numero ne' un operatore ne' "q", il programma lo ignora (non occorre che segnali errore). Per verificare se l'input e` un numero, utilizzare la funzione val, err := strconv.ParseFloat(input, 64) Nel caso err sia nil, l'input e` un numero che verra` salvato in val. Esempio ------- $ go run RPN.go Next? (+, -, *, /, q o un numero) 3 [3] Next? (+, -, *, /, q o un numero) 5 [3 5] Next? (+, -, *, /, q o un numero) 7 [3 5 7] Next? (+, -, *, /, q o un numero) * [3 35] Next? (+, -, *, /, q o un numero) + [38] Next? (+, -, *, /, q o un numero) - not enough data [38] Next? (+, -, *, /, q o un numero) q Creare una seconda versione RPN2.go in cui l'espressione da valutare sia fornita da linea di comando (os.Args) invece che da standard input (cioe` tastiera). In questo caso se l'espressione contiene moltiplicazioni, l'asterisco va messo tra apici ('*') o tra virgolette ("*"). ____________________________________________________ Black Jack ---------- Riprendere il progetto delle carte da gioco, dove una carta era una struct con i campi seme (string) e valore (string). Definire una funzione main() per testare man mano le funzioni che seguono. Modificare la funzione mazzoPoker che crea e restituisce un mazzo di 52 carte da poker (usare le slice). Modificare la funzione mischia che, dato un mazzo di carte (di dimensione arbitraria), lo rimescola in modo random (usare le slice). Utilizzare lo scambio diretto: slice[i], slice[r] = slice[r], slice[i] // dove r e` un numero estratto a caso tra i e la dimensione del mazzo. Definire una funzione preleva che, dato un mazzo di carte, restituisce la carta che si trova in cima e la toglie dal mazzo. Implementare un simulatore di BJ (https://it.wikipedia.org/wiki/Blackjack), che consenta ad un giocatore singolo di giocare contro il PC (che rappresenta il mazziere). Utilizzare come mazzo due mazzi da poker. ____________________________________________________