Go程序设计语言练习题-第4章(4.1-4.9)

4.1

package main

import (
    "crypto/sha256"
    "fmt"
)

func popCount(b [32]byte) (res int) {
    for _, v := range b {
        n := int(v)
        for n > 0 {
            n = n & (n - 1)
            res++
        }
    }
    return
}

func main() {
    b := sha256.Sum256([]byte("x"))
    fmt.Println(popCount(b))
}
View Code

4.2

package main

import (
    "crypto/sha256"
    "crypto/sha512"
    "flag"
    "fmt"
    "os"
)

var t = flag.Int("t", 2, "-t 2|3|5")

func main() {
    flag.Parse()
    c := make([]byte, 1024)
    n, err := os.Stdin.Read(c)
    if err != nil {
        fmt.Println(err)
        return
    }
    switch *t {
    case 3:
        fmt.Printf("%x
", sha512.Sum384(c[0:n]))
    case 5:
        fmt.Printf("%x
", sha512.Sum512(c[0:n]))
    default:
        fmt.Printf("%x
", sha256.Sum256(c[0:n]))
    }
}
View Code

4.3~4.7

package main

import (
    "fmt"
    "unicode"
    "unicode/utf8"
    "unsafe"
)

// 4.3 重写reverse函数,使用数组指针作为参数而不是slice
// ?数组长度是类型的一部分
func reverse(arr *[5]int) {
    length := len(*arr)
    for i, j := 0, length-1; i < j; i, j = i+1, j-1 {
        (*arr)[i], (*arr)[j] = (*arr)[j], (*arr)[i]
    }
}

// 4.4 编写函数rotate,实现一次遍历就可以完成元素旋转
func rotate(s []int, n int) (t []int) {
    if n <= 0 || n >= len(s) {
        return s
    }
    t = make([]int, len(s))
    for i, v := range s {
        t[(i+n)%len(s)] = v
    }
    return
}

// rotate另一种思路:原地旋转,遍历两次
func reverseSlice(s []int) {
    for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
        s[i], s[j] = s[j], s[i]
    }
}
func rotate2(s []int, n int) {
    if n > len(s) {
        fmt.Errorf("parameter n:%d is out of range(%d)", n, len(s))
        return
    }
    reverseSlice(s[0 : len(s)-n])
    reverseSlice(s[len(s)-n:])
    reverseSlice(s)
}

// 4.5 编写一个就地处理函数,用于去除[]string slice中相邻重复字符串元素
func distinct(s []string) []string {
    dist := s[0:1]
    for i := 1; i < len(s); i++ {
        for s[i] != dist[len(dist)-1] {
            dist = append(dist, s[i])
        }
    }
    return dist
}

// 4.6 编写一个就地处理函数,用于将一个UTF-8编码的字节slice中所有相邻的Unicode空白字符(查看unicode.IsSpace)缩减为一个ASCII空白字符。
func ex4_6(b []byte) []byte {
    var i int
    for i, l := 0, 0; l < len(b); {
        r, size := utf8.DecodeRune(b[i:])
        l += size
        if unicode.IsSpace(r) {
            if i > 0 && b[i-1] == byte(32) {
                copy(b[i:], b[i+size:])
            } else {
                b[i] = byte(32)
                copy(b[i+1:], b[i+size:])
                i++
            }
        } else {
            i += size
        }
    }
    return b[0:i]
}

// 4.7 修改函数reverse,来反转一个UTF-8编码字符串中的字符元素,传入参数是该字符串对应的字节slice类型([]byte)。是否可以做到不重新分配内存就实现该功能。
func mbreverse(b []byte) []byte {
    var res []byte
    for i := len(b); i > 0; {
        r, size := utf8.DecodeLastRune(b[:i])
        res = append(res, []byte(string(r))...)
        i -= size
    }
    return res
}

func main() {
    // 4.3
    arr := [...]int{1, 2, 3, 4, 5}
    reverse(&arr)
    fmt.Println(arr)

    // 4.4
    r := []int{1, 2, 3, 4, 5}
    fmt.Println(rotate(r, 0))
    fmt.Println(rotate(r, 1))
    fmt.Println(rotate(r, 2))
    fmt.Println(rotate(r, 5))
    fmt.Println(rotate(r, 6))

    // 4.5
    s := []string{" ", " ", "aaa", " ", "bbb", "bbb", "c", "d", "d"}
    dist := distinct(s)
    fmt.Printf("原slice的底层数组地址:%p
", unsafe.Pointer(uintptr(unsafe.Pointer(&s))))
    fmt.Printf("原slice的len:%d
", *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + unsafe.Sizeof(&s))))
    fmt.Printf("原slice的cap:%d
", *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + 2*unsafe.Sizeof(&s))))

    fmt.Printf("去重后底层数组地址:%p
", unsafe.Pointer(uintptr(unsafe.Pointer(&dist))))
    fmt.Printf("len:%d
", *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&dist)) + unsafe.Sizeof(&dist))))
    fmt.Printf("cap:%d
", *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&dist)) + 2*unsafe.Sizeof(&dist))))

    // 4.6
    b := []byte("北京	欢迎
您")
    fmt.Printf("%s
%v
", b, b)
    ex4_6(b)
    fmt.Printf("%s
%v
", b, b)

    // 4.7
    b = []byte("北京欢迎您welcome")
    fmt.Printf("%s
", b)
    fmt.Printf("%s
", mbreverse(b))

}
View Code

 4.8~4.9

package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
    "unicode"
)

func charcount() {
    seen := make(map[rune]bool)
    var letterCount, numberCount, otherCount, invalid int
    in := bufio.NewReader(os.Stdin)
    for {
        r, n, err := in.ReadRune()
        if err == io.EOF {
            break
        }
        if err != nil {
            fmt.Fprintln(os.Stderr, "charcount:%v
", err)
            os.Exit(1)
        }
        if r == unicode.ReplacementChar && n == 1 {
            invalid++
            continue
        }
        if unicode.IsLetter(r) && !seen[r] {
            letterCount++
            seen[r] = true
            continue
        }
        if unicode.IsNumber(r) && !seen[r] {
            numberCount++
            seen[r] = true
            continue
        }
        if !seen[r] {
            otherCount++
            seen[r] = true
        }
    }

    fmt.Fprintf(os.Stdout, "letterCount:%d	numberCount:%d	otherCount:%d	invalidCount:%d
", letterCount, numberCount, otherCount, invalid)
}

// 4.9
func wordfreq() map[string]int {
    scanner := bufio.NewScanner(os.Stdin)
    scanner.Split(bufio.ScanWords)
    words := make(map[string]int)
    for scanner.Scan() {
        words[scanner.Text()]++
    }
    if err := scanner.Err(); err != nil {
        fmt.Fprintln(os.Stderr, err)
    }
    return words
}

func main() {
    fmt.Println("ex4.8
")
    charcount()

    fmt.Println("ex4.9 Word Frequency:")
    words := wordfreq()
    for w, n := range words {
        fmt.Printf("%s	%d
", w, n)
    }
}
View Code
原文地址:https://www.cnblogs.com/ling-diary/p/10408376.html