19 novembre 2018

/**
Esercizio: calcolatrice RPN (il file deve chiamarsi RPN.go)

https://it.wikipedia.org/wiki/Notazione_polacca_inversa

per vederne una in funzione: http://www.alcula.com/calculators/rpn/

versione semplice:
- 2 accumulatori
- 4 operazioni (+ - * /)
- valori float

versione full: array di accumulatori


Implementazione LOOP:

- legge input utente
 - se numero accumula
 - se operatore collassa

- condizione di uscita (inserimento operatore "q")
- condizioni di errore


A1[]
A2[]

sequenza 3 4 5 6 +

risultato (per iterazioni):

A1[3]
A2[]

A1[4]
A2[3]

A1[5]
A2[4]

A1[6]
A2[5]

A1[11]
A2[]


IMPORTANTE: quando finito (a qualunque livello decidiate di mettervi, se cioè con 2 accum o array) caricate su upload.di.unimi.it che poi facciamo girare i test

*/

package main
import "fmt"
import "strconv"

func main() {
	var input string
	var accumulatore [4]float64

	for {

		fmt.Scanf("%s", &input)
		in, err := strconv.ParseFloat(input, 64)

		switch {

			case err==nil:

				accumulatore=accumula(in, accumulatore)
				fmt.Println(accumulatore)

			case input=="+":

				a := somma(accumulatore)
				accumulatore=collassa(a, accumulatore)
				fmt.Println(accumulatore)

			case input=="-":

				a := sottrai(accumulatore)
				accumulatore=collassa(a, accumulatore)
				fmt.Println(accumulatore)

			case input=="*":

				a := moltiplica(accumulatore)
				accumulatore=collassa(a, accumulatore)
				fmt.Println(accumulatore)

			case input=="/":

				a := dividi(accumulatore)
				accumulatore=collassa(a, accumulatore)
				fmt.Println(accumulatore)

			case input=="q":

				goto end

			default:

				fmt.Println("Errore. Il programma verrà terminato.")
				goto end

		}

	}

	end:
}

/*
func isNumber(s string) bool {

	for _, c := range s {

		if !(c=='0' || c=='1' || c=='2' || c=='3' || c=='4' || c=='5' || c=='6' || c=='7' || c=='8' || c=='9') {
			return false
		}
	}

	return true
}
*/


func accumula(a float64, vet [4]float64) [4]float64 {
	var vet1 [4]float64

	for i:=len(vet)-1; i>0; i-- {

		vet[i]=vet[i-1]

	}

	vet[0]=a

	vet1=vet
	return vet1
}

func collassa(a float64, vet [4]float64) [4]float64 {
	var vet1 [4]float64

	vet[0]=a

	for i:=1; i<len(vet)-1; i++ {

		vet[i]=vet[i+1]

	}

	vet1=vet
	return vet1
}


func somma(vet [4]float64) float64 {
	var r float64

	r=vet[0]+vet[1]

	return r
}


func sottrai(vet [4]float64) float64 {
	var r float64

	r=vet[0]-vet[1]

	return r
}


func moltiplica(vet [4]float64) float64 {
	var r float64

	r=vet[0]*vet[1]

	return r
}

func dividi(vet [4]float64) float64 {
	var r float64

	r=vet[0]/vet[1]

	return r
}
/*
package main

import (
	"fmt"
	"os"
	"strconv"
)

func MoveSlice(x []string, y []string, i int) {
	for j := i + 1; j < len(x); j++ {
		x[j] = y[j]
	}
	for k := i - 3; k >= 0; k-- {
		x[k+2] = y[k]
	}
	x = y
} //funzione per riorganizzare le slice dopo un'operazione

func Rpn(n []string) string {
	var m []string
	m = n        //in modo che m non sia vuota
	var last int //l'ultimo numero nello slice m sarà quello dato come soluzione
	var a, b float64

	for _, runa := range n[len(n)-1] {
		if runa == '.' || runa == '0' || runa == '1' || runa == '2' || runa == '3' || runa == '4' || runa == '5' || runa == '6' || runa == '7' || runa == '8' || runa == '9' {
			fmt.Println("Errore: non puoi avere un numero alla fine dell'espressione")
			os.Exit(0)
		}
	} //debug per numero dopo operatori

	for i := 0; i < len(n); i++ {

		if n[0] == "+" || n[0] == "-" || n[0] == "*" || n[0] == "/" {
			fmt.Println("Errore: non puoi avere un operatore all'inizio")
			os.Exit(0)
		} //debug per operatore all'inizio

		for _, runa := range n[i] { //controlla la validità dell'input runa per runa in ciascuna stringa dello slice contenente l'espressione
			if runa == '.' || runa == '0' || runa == '1' || runa == '2' || runa == '3' || runa == '4' || runa == '5' || runa == '6' || runa == '7' || runa == '8' || runa == '9' || n[i] == "+" || n[i] == "-" || n[i] == "*" || n[i] == "/" {

				if len(n) <= 1 {
					break
				}

				switch n[i] { //operazioni, eseguite convertendo avanti e indietro da string a float
				case "+":
					a, _ = strconv.ParseFloat(n[i-2], 64)
					b, _ = strconv.ParseFloat(n[i-1], 64)
					m[i] = strconv.FormatFloat((a + b), 'f', -1, 64)
					MoveSlice(n, m, i)
					i = 0
				case "-":
					a, _ = strconv.ParseFloat(n[i-2], 64)
					b, _ = strconv.ParseFloat(n[i-1], 64)
					m[i] = strconv.FormatFloat((a - b), 'f', -1, 64)
					MoveSlice(n, m, i)
					i = 0
				case "*":
					a, _ = strconv.ParseFloat(n[i-2], 64)
					b, _ = strconv.ParseFloat(n[i-1], 64)
					m[i] = strconv.FormatFloat((a * b), 'f', -1, 64)
					MoveSlice(n, m, i)
					i = 0
				case "/":
					a, _ = strconv.ParseFloat(n[i-2], 64)
					b, _ = strconv.ParseFloat(n[i-1], 64)
					m[i] = strconv.FormatFloat((a / b), 'f', -1, 64)
					MoveSlice(n, m, i)
					i = 0
				}
				last = i
			} else {
				fmt.Println("Errore: non hai inserito un input valido")
				os.Exit(0)
			} // debug dell'input, gestito insieme al for di riga 40
			if n[last] == "." {
				fmt.Println("Errore")
				os.Exit(0)
			} //debug per non inserire il punto (decimali) dopo gli operatori
		}
	}
	return n[last] //restituisce la soluzione (v. riga 23)
}

func main() {
	var term string
	var operation []string
	fmt.Println("Inserire numeri ed operatori separati da uno spazio. Il programma termina con =.")
	fmt.Scan(&term)
	for term != "=" {
		operation = append(operation, term)
		fmt.Scan(&term)
	}
	fmt.Println(Rpn(operation))
}
*/

/*
package main
import "fmt"
import "strconv"

var input string
var accumulatore [4]float64


func main() {

	for {

		fmt.Scanf("%s", &input)
		in, err := strconv.ParseFloat(input, 64)

		switch {

			case err==nil:

				accumula(in)
				fmt.Println(accumulatore)

			case input=="+":

				somma(accumulatore[0], accumulatore[1])
				fmt.Println(accumulatore)

			case input=="-":

				sottrai(accumulatore[0], accumulatore[1])
				fmt.Println(accumulatore)

			case input=="*":

				moltiplica(accumulatore)
				fmt.Println(accumulatore)

			case input=="/":

				dividi(accumulatore)
				fmt.Println(accumulatore)

			case input=="q":

				goto end

			default:

				fmt.Println("Errore. Il programma verrà terminato.")
				goto end

		}

	}

	end:
}

func accumula(a float64) {

	for i:=len(accumulatore)-1; i>0; i-- {

		accumulatore[i]=accumulatore[i-1]

	}

	accumulatore[0]=a
}

func collassa(a float64) {

	accumulatore[0]=a

	for i:=1; i<len(accumulatore)-1; i++ {

		accumulatore[i]=accumulatore[i+1]

	}
}


func somma(a, b float64) {
	var r float64

	r=a+b

	collassa(r)
}

func sottrai(a, b float64) {
	var r float64

	r=a-b

	collassa(r)
}

func moltiplica(a, b float64) {
	var r float64

	r=a*b

	collassa(r)
}

func dividi(a, b float64) {
	var r float64

	r=a/b

	collassa(r)
}
*/
/*
Creare un programma che gestisca uno stack generico (numero arbitrario di posizioni)

Lo stack è un array di valori (float) che mantiene nella prima posizione il valore più recente.
E' possibile accedere sempre e solo alla prima posizione.
Operazioni disponibili sullo stack:
- push -> aggiunge un valore in testa allo stack
- pop -> rimuove il valore in testa allo stack e lo ritorna
- top (o peek) -> ritorna il valore in testa allo stack senza rimuoverlo
- eventualmente empty -> lo stack è vuoto vero o falso?

ESEMPI:
stack -> [1, 5, 7, 1]
push(13)
stack -> [13, 1, 5, 7, 1]
n = pop()
n -> 13
stack -> [1, 5, 7, 1]
n = top()
n -> 1
stack -> [1, 5, 7, 1]
*/
package main

import (
    "fmt"
    "strings"
)

var stack []float32

func main() {
    push(1)
    push(7)
    push(5)
    push(1)
    fmt.Println("stack ->", str())
    push(13)
    fmt.Println("stack ->", str())
    fmt.Println("n ->", pop())
    fmt.Println("stack ->", str())
    fmt.Println("n ->", top())
    fmt.Println("stack ->", str())
}

func pop() float32 {
    var r float32
    r, stack = stack[0], stack[1:]
    return r
}

func top() float32 {
	return stack[0]
}

func push(value float32) {
	stack = append([]float32{value}, stack...)
}

func empty() bool {
	return len(stack) == 0
}

func str() string {
    return strings.Replace(fmt.Sprintf("%v", stack), " ", ", ", -1)
}
/*
Combinare i due esercizi precedenti per creare una RPN con un numero arbitrario di accumulatori
*/
package main

import (
    "fmt"
    "strings"
    "strconv"
)

var stack []float32

func main() {
    var command string
    for bytesRead, _ := fmt.Scan(&command); bytesRead > 0 && command != "q"; bytesRead, _ = fmt.Scan(&command) {
        parseCommand(command)
    }
}

func parseCommand(command string) {
    if num, err := strconv.ParseFloat(command, 32); err == nil {
        push(float32(num))
    } else {
        parseOperator(command)
    }
    fmt.Println(str())
}

func parseOperator(command string) {
    operand1 := pop()
    operand2 := pop()
    switch command {
    case "+":
        push(operand1 + operand2)
    case "-":
        push(operand1 - operand2)
    case "*":
        push(operand1 * operand2)
    case "/":
        push(operand1 / operand2)
    default:
        //ignore
    }
}

func pop() float32 {
    var r float32
    r, stack = stack[0], stack[1:]
    return r
}

func top() float32 {
    return stack[0]
}

func push(value float32) {
    stack = append([]float32{value}, stack...)
}

func empty() bool {
    return len(stack) == 0
}

func str() string {
    return strings.Replace(fmt.Sprintf("%v", stack), " ", ", ", -1)
}
pub/labprog/20181119.txt · Last modified: 2018/11/21 18:04 by lucafavalli
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0