Task: Proof




Go: package main

import "fmt"


type Number struct {
    pred *Number
}


type EvenNumber struct {
    half *Number
}


type OddNumber struct {
    half *Number
}


func zero() *Number { return nil }


func isZero(x *Number) bool { return x == nil }


func add1(x *Number) *Number {
    y := new(Number)
    y.pred = x
    return y
}


func sub1(x *Number) *Number { return x.pred }


func add(x, y *Number) *Number {
    if isZero(y) {
        return x
    }
    return add(add1(x), sub1(y))
}


func addEven(x, y *EvenNumber) *EvenNumber {
    if isZero(y.half) {
        return x
    }
    return genEven(add(x.half, y.half))
}


func addOdd(x, y *OddNumber) *EvenNumber {
    z := add(x.half, y.half)
    return genEven(add1(z))
}


func gen(n uint) *Number {
    if n > 0 {
        return add1(gen(n - 1))
    }
    return zero()
}


func genEven(half *Number) *EvenNumber {
    return &EvenNumber{half}
}


func genOdd(half *Number) *OddNumber {
    return &OddNumber{half}
}


func count(x *Number) uint {
    if isZero(x) {
        return 0
    }
    return count(sub1(x)) + 1
}


func countEven(x *EvenNumber) uint {
    return count(x.half) * 2
}


func countOdd(x *OddNumber) uint {
    return count(x.half)*2 + 1
}


func testCommutative(e1, e2 *EvenNumber) {
    c1, c2 := countEven(e1), countEven(e2)
    passed := countEven(addEven(e1, e2)) == countEven(addEven(e2, e1))
    symbol := "=="
    if !passed {
        symbol = "!="
    }
    fmt.Printf("\n%d + %d %s %d + %d\n", c1, c2, symbol, c2, c1)
}


func testAssociative(e1, e2, e3 *EvenNumber) {
    c1, c2, c3 := countEven(e1), countEven(e2), countEven(e3)
    passed := countEven(addEven(addEven(e1, e2), e3)) == countEven(addEven(e1, addEven(e2, e3)))
    symbol := "=="
    if !passed {
        symbol = "!="
    }
    fmt.Printf("\n(%d + %d) + %d %s %d + (%d + %d)\n", c1, c2, c3, symbol, c1, c2, c3)
}

func main() {
    numbers := [10]*Number{}
    fmt.Println("The first 10 natural numbers are:")
    for i := uint(0); i < 10; i++ {
        numbers[i] = gen(i)
        fmt.Printf("%d ", count(numbers[i]))
    }
    fmt.Println("\n")

    fmt.Println("The first 10 even natural numbers are:")
    for i := uint(0); i < 10; i++ {
        e := genEven(numbers[i])
        fmt.Printf("%d ", countEven(e))
    }
    fmt.Println("\n")

    fmt.Println("The first 10 odd natural numbers are:")
    for i := uint(0); i < 10; i++ {
        o := genOdd(numbers[i])
        fmt.Printf("%d ", countOdd(o))
    }
    fmt.Println("\n")

    fmt.Print("The sum of the first 10 natural numbers is: ")
    sum := numbers[0]
    for i := 1; i < 10; i++ {
        sum = add(sum, numbers[i])
    }
    fmt.Println(count(sum))

    fmt.Print("\nThe sum of the first 10 even natural numbers (increasing order) is: ")
    sumEven := genEven(numbers[0])
    for i := 1; i < 10; i++ {
        sumEven = addEven(sumEven, genEven(numbers[i]))
    }
    fmt.Println(countEven(sumEven))

    fmt.Print("\nThe sum of the first 10 even natural numbers (decreasing order) is: ")
    sumEven = genEven(numbers[9])
    for i := 8; i >= 0; i-- {
        sumEven = addEven(sumEven, genEven(numbers[i]))
    }
    fmt.Println(countEven(sumEven))

    testCommutative(genEven(numbers[8]), genEven(numbers[9]))

    testAssociative(genEven(numbers[7]), genEven(numbers[8]), genEven(numbers[9]))
}