package main


type geometry interface {
    area() float64
    perim() float64
}


type rect struct {
    width, height float64
}

func (r rect) perim() float64 {
    return 2*r.width + 2*r.height
}

func (r rect) area() float64 {
    return r.width * r.height
}

func measure(x geometry) float64 {
    return x.perim()
}

func measure2(x geometry, f float64, y geometry) float64 {
    return x.perim() + f + y.perim()
}

func measure3(x geometry, c float64, v... geometry) float64 {
    total := x.perim() + c
    for _, g := range v {
        total += g.perim()
    }
    return total
}

func measure4(x geometry, v... float64) float64 {
    total := x.perim()
    for _, g := range v {
        total += g
    }
    return total
}

/*
type circle struct {
    radius float64
}

func (r rect) area() float64 {
    return r.width * r.height
}
func (r rect) perim() float64 {
    return 2*r.width + 2*r.height
}

func (c circle) area() float64 {
    return c.radius * c.radius
}
func (c circle) perim() float64 {
    return 1 * c.radius
}

func measure(g geometry) {
    assert(g.area() == 1)
}
*/

func aaa() (int, *rect) {
    var r rect
    r2 := &r
    r.height = 2
    assert(2 == r2.height)
    return 1, r2
}


func main() {

    var r rect
    r.height = 8
    assert(8 == r.height)

    var g geometry
    f, g := -6, &r
    assert(f == -6)
    assert(16 == measure(g))

    f, g = aaa()
    assert(f == 1)
    assert(4 == measure(g))

    assert(37 == measure2(r, 5, r))

    assert(16 * 3 + 5 == 53)

    //measure3(r, 2, r, r, r)
    assert(53 == measure3(r, 5, r, r))

    assert(30 == measure4(r, 2, 3,4,5))

    /*
    r := rect{width: 1, height: 1}
    c := circle{radius: 1}

    measure(r)
    measure(c)
    */
}