皆様にだいぶ遅れを取る形となってしまいましたがこちら無事完走しました。
稚拙ではありますが一応正解している(はずの)コードを置いておきます。
ツッコミポイントはありそう。
いつかこれを見直して笑ってやる。
Exercise: Loops and Functions
関数とループを使った簡単な練習として、平方根の計算を実装してみましょう:
数値 x が与えられたときに z² が最も x に近い数値 z を求めたいと思います。
(以下略)
package main
import (
"fmt"
. "math"
)
func Sqrt(x float64) float64 {
z := x / 2.0
for i := 0; i < 10; i++ {
diff := (z*z - x) / (2.0 * z)
z = z - diff
if Abs(diff) < 1e-6 {
break
}
}
return z
}
func main() {
fmt.Println(Sqrt(3))
}
// Output: 1.7320508075688772
Exercise: Slices
Pic 関数を実装してみましょう。
このプログラムを実行すると、生成した画像が下に表示されるはずです。
この関数は、長さ dy のsliceに、各要素が8bitのunsigned int型で長さ dx のsliceを割り当てたものを返すように実装する必要があります。
画像は、整数値をグレースケール(実際はブルースケール)として解釈したものです。
(以下略)
package main
import "golang.org/x/tour/pic"
func Pic(dx, dy int) [][]uint8 {
// 準備
img := make([][]uint8, dy)
for y := range img {
img[y] = make([]uint8, dx)
}
// 関数
for y := 0; y < dy; y++ {
for x := 0; x < dx; x++ {
img[y][x] = uint8(x ^ y - y ^ x)
}
}
return img
}
func main() {
pic.Show(Pic)
}
// Output: 省略
Exercise: Maps
WordCount 関数を実装してみましょう。string s で渡される文章の、各単語の出現回数のmapを返す必要があります。
package main
import (
"golang.org/x/tour/wc"
"strings"
)
func WordCount(s string) map[string]int {
arr := strings.Fields(s)
// Mapの用意
m := make(map[string]int)
// WordCount
for _, w := range arr {
m[w]++
}
return m
}
func main() {
wc.Test(WordCount)
}
// Output: 省略
Exercise: Fibonacci closure
fibonacci (フィボナッチ)関数を実装しましょう。
この関数は、連続するフィボナッチ数(0, 1, 1, 2, 3, 5, ...)を返す関数(クロージャ)を返します。
package main
import "fmt"
// fibonacci = int型を返す関数を返す関数
func fibonacci() func() int {
p := 1
pp := 0
return func() int {
fib := pp + p
pp = p
p = fib
return fib
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Print(f(), ",")
}
}
// Output: 1,2,3,5,8,13,21,34,55,89,
Exercise: Stringers
IPAddr 型を実装してみましょう
IPアドレスをドットで4つに区切った( dotted quad )表現で出力するため、 fmt.Stringer インタフェースを実装してください。
package main
import "fmt"
type IPAddr [4]byte
func (a IPAddr) String() string {
return fmt.Sprintf("%d.%d.%d.%d", a[0], a[1], a[2], a[3])
}
func main() {
hosts := map[string]IPAddr{
"loopback": {127, 0, 0, 1},
"googleDNS": {8, 8, 8, 8},
}
for name, ip := range hosts {
fmt.Printf("%v: %v\n", name, ip)
}
}
// Output:
// loopback: 127.0.0.1
// googleDNS: 8.8.8.8
Exercise: Errors
Sqrt 関数を 以前の演習 からコピーし、 error の値を返すように修正してみてください。
Sqrt は、複素数をサポートしていないので、負の値が与えられたとき、nil以外のエラー値を返す必要があります。
package main
import (
"fmt"
. "math"
)
type ErrNegativeSqrt float64
func (e ErrNegativeSqrt) Error() string {
return fmt.Sprintf("cannot Sqrt negative number: %f", e)
}
func Sqrt(x float64) (float64, error) {
// 負の値が与えられたときnil以外のエラー値を返す
if x < 0.0 {
return 0, ErrNegativeSqrt(x)
}
// 初期値
z := x / 2.0
for i := 0; i < 10; i++ {
diff := (z*z - x) / (2.0 * z)
z = z - diff
if Abs(diff) < 1e-9 {
break
}
}
return z, nil
}
func main() {
fmt.Println(Sqrt(2))
fmt.Println(Sqrt(-2))
}
// Output:
// 1.4142135623730951 <nil>
// 0 cannot Sqrt negative number: -2.000000
Exercise: Readers
ASCII文字 'A' の無限ストリームを出力する Reader 型を実装してください。
package main
import "golang.org/x/tour/reader"
type MyReader struct{}
func (r MyReader) Read(buf []byte) (int, error) {
for i := range buf {
buf[i] = 'A'
}
return len(buf), nil
}
func main() {
reader.Validate(MyReader{})
}
// Output: 略
Exercise: rot13Reader
io.Reader を実装し、 io.Reader でROT13 換字式暗号( substitution cipher )をすべてのアルファベットの文字に適用して読み出すように rot13Reader を実装してみてください。
package main
import (
"io"
"os"
"strings"
)
type rot13Reader struct {
r io.Reader
}
// io.Readerインターフェイスを見てみる
// type Reader interface {
// Read(p []byte) (n int, err error)
// }
// byteの並んだsliceを受け取って、intとerrorを返す
func (r13 *rot13Reader) Read(b []byte) (int, error) {
n, e := r13.r.Read(b)
for i := 0; i < n; i++ {
if b[i] > 'A' && b[i] < 'z' {
if b[i] > 'z'-13 {
b[i] = b[i] - 13
} else {
b[i] = b[i] + 13
}
}
}
return n, e
}
func main() {
b := strings.NewReader("Lbh penpxrq gur pbqr!")
r := rot13Reader{b}
io.Copy(os.Stdout, &r)
}
// Output: You cracked the code!
Exercise: Images
自分の Image 型を定義し、 インタフェースを満たすのに必要なメソッド を実装し、 pic.ShowImage を呼び出してみてください。
Bounds は、 image.Rect(0, 0, w, h) のようにして image.Rectangle を返すようにします。
ColorModel は、 color.RGBAModel を返すようにします。
At は、ひとつの色を返します。 生成する画像の色の値 v を color.RGBA{v, v, 255, 255} を利用して返すようにします。
package main
import (
"golang.org/x/tour/pic"
"image"
"image/color"
)
type Image struct {
w int
h int
}
// 以下のinterfaceを満たす
// type Image interface {
// ColorModel() color.Model
// Bounds() Rectangle
// At(x, y int) color.Color
// }
func (img Image) Bounds() image.Rectangle {
return image.Rect(0, 0, img.w, img.h)
}
func (img Image) ColorModel() color.Model {
return color.RGBAModel
}
func (img Image) At(x, y int) color.Color {
v := uint8((x + y)/2)
return color.RGBA{v, v, 255, 255}
}
func main() {
m := Image{256, 256}
pic.ShowImage(m)
}
// Output: 略
Exercise: Equivalent Binary Trees
長いので略。
https://go-tour-jp.appspot.com/concurrency/7
https://go-tour-jp.appspot.com/concurrency/8
package main
import (
"fmt"
"golang.org/x/tour/tree"
)
// type Tree struct {
// Left *Tree
// Value int
// Right *Tree
// }
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
// 終わったらchannelをcloseさせたいので更に関数に切り出す
walk(t, ch)
close(ch)
}
func walk(t *tree.Tree, ch chan int) {
if t == nil {
return
}
if t.Left != nil {
walk(t.Left, ch)
}
ch <- t.Value
if t.Right != nil {
walk(t.Right, ch)
}
}
//Same determines whether the trees
//t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {
ch1 := make(chan int)
ch2 := make(chan int)
go Walk(t1, ch1)
go Walk(t2, ch2)
for v1 := range ch1 {
v2 := <-ch2
if v1 != v2 {
return false
}
}
return true
}
func main() {
ch := make(chan int)
go Walk(tree.New(1), ch)
for v := range ch {
fmt.Print(v,":")
}
fmt.Println()
fmt.Println(Same(tree.New(1), tree.New(1)))
fmt.Println(Same(tree.New(2), tree.New(3)))
}
// Output:
// 1:2:3:4:5:6:7:8:9:10:
// true
// false
ではまた。
この記事は著者のブログからの転載記事となります。