Use newtons method to find square roots
Solution
package main
import (
"fmt"
)
func Sqrt(x float64) float64 {
del := 0.0000001
srt, prevSrt := x, x * 2
for prevSrt - srt > del {
prevSrt = srt
srt = srt - (srt*srt - x)/(2 * srt)
//fmt.Printf("Difference of prev - srt = %v\n", prevSrt-srt)
}
return srt
}
func main() {
fmt.Println(Sqrt(25))
}
Implement Pic. It should return a slice of length dy, each element of which is a slice of dx 8-bit unsigned integers. When you run the program, it will display your picture, interpreting the integers as grayscale (well, bluescale) values.
The choice of image is up to you. Interesting functions include (x+y)/2
, x*y
, and x^y
.
(You need to use a loop to allocate each []uint8
inside the [][]uint8
.)
(Use uint8(intValue) to convert between types.)
Solution
package main
import (
"golang.org/x/tour/pic"
)
func Pic(dx, dy int) [][]uint8 {
b := make([][]uint8, dy)
for i:= range b{
b[i] = make([]uint8, dx)
for j:=range b[i]{
b[i][j] = uint8((i*j)/10)
}
}
return b
}
func main() {
pic.Show(Pic)
}
Implement WordCount. It should return a map of the counts of each “word” in the string s. The wc.Test function runs a test suite against the provided function and prints success or failure.
You might find strings.Fields helpful
Solution
package main
import (
"golang.org/x/tour/wc"
"strings"
)
func WordCount(s string) map[string]int {
var ok bool
count := make(map[string]int)
words := strings.Fields(s)
for _, word:= range words{
_, ok = count[word]
if ok == false {
count[word] = 1
}else {
count[word] += 1
}
}
return count
}
func main() {
wc.Test(WordCount)
}
Let's have some fun with functions.
Implement a fibonacci function that returns a function (a closure) that returns successive fibonacci numbers (0, 1, 1, 2, 3, 5, ...).
Solution
package main
import "fmt"
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
x := 0
y := 1
return func() int{
x, y = y, x+y
return y
}
}
func main() {
f := fibonacci()
fmt.Println("0\n1")
for i := 0; i < 20; i++ {
fmt.Println(f())
}
}
Exercise: Stringers Make the IPAddr type implement fmt.Stringer to print the address as a dotted quad.
For instance, IPAddr{1, 2, 3, 4} should print as "1.2.3.4".
Solution
package main
import "fmt"
type IPAddr [4]byte
func (ip IPAddr) String() string{
return fmt.Sprintf("%v.%v.%v.%v", ip[0], ip[1], ip[2], ip[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)
}
}
Exercise: Errors Copy your Sqrt function from the earlier exercise and modify it to return an error value.
Sqrt should return a non-nil error value when given a negative number, as it doesn't support complex numbers.
Create a new type
type ErrNegativeSqrt float64 and make it an error by giving it a
func (e ErrNegativeSqrt) Error() string method such that ErrNegativeSqrt(-2).Error() returns "cannot Sqrt negative number: -2".
Note: a call to fmt.Sprint(e) inside the Error method will send the program into an infinite loop. You can avoid this by converting e first: fmt.Sprint(float64(e)). Why?
Change your Sqrt function to return an ErrNegativeSqrt value when given a negative number.
Solution
package main
import (
"fmt"
)
type ErrNegativeSqrt float64
func (e ErrNegativeSqrt) Error() string{
q := fmt.Sprint(float64(e))
return fmt.Sprintf("cannot Sqrt negative number: %v",q)
}
func Sqrt(x float64) (float64, error) {
if x < 0 {
return x, ErrNegativeSqrt(x)
} else {
del := 1e-9
srt, prevSrt := x, x * 2
for prevSrt - srt > del {
prevSrt = srt
srt = srt - (srt*srt - x)/(2 * srt)
}
return srt, nil
}
}
func main() {
fmt.Println(Sqrt(2))
fmt.Println(Sqrt(-2))
}
Exercise: Readers Implement a Reader type that emits an infinite stream of the ASCII character 'A'.
Solution
package main
import "golang.org/x/tour/reader"
type MyReader struct{}
func (m MyReader) Read(b []byte) (int, error) {
for i := range b {
b[i] = 'A'
}
return len(b), nil
}
func main() {
reader.Validate(MyReader{})
}
Exercise: rot13Reader A common pattern is an io.Reader that wraps another io.Reader, modifying the stream in some way.
For example, the gzip.NewReader function takes an io.Reader (a stream of compressed data) and returns a *gzip.Reader that also implements io.Reader (a stream of the decompressed data).
Implement a rot13Reader that implements io.Reader and reads from an io.Reader, modifying the stream by applying the rot13 substitution cipher to all alphabetical characters.
The rot13Reader type is provided for you. Make it an io.Reader by implementing its Read method.
package main
import (
"io"
"os"
"strings"
)
type rot13Reader struct {
r io.Reader
}
func (rt rot13Reader) Read(b []byte) (int, error) {
n, err := rt.r.Read(b)
for i:=0; i < n; i++ {
if b[i] >= 60 && b[i] <= 77 || b[i] >= 90 && b[i] <= 105 {
b[i] += 13
} else if b[i] > 77 && b[i] <= 90 || b[i] > 105 && b[i] <= 122 {
b[i] -= 13
}
}
return n, err
}
func main() {
s := strings.NewReader("Lbh penpxrq gur pbqr!")
r := rot13Reader{s}
io.Copy(os.Stdout, &r)
}
Exercise: Equivalent Binary Trees
-
Implement the Walk function.
-
Test the Walk function.
The function tree.New(k) constructs a randomly-structured binary tree holding the values k, 2k, 3k, ..., 10k.
Create a new channel ch and kick off the walker:
go Walk(tree.New(1), ch) Then read and print 10 values from the channel. It should be the numbers 1, 2, 3, ..., 10.
-
Implement the Same function using Walk to determine whether t1 and t2 store the same values.
-
Test the Same function.
Same(tree.New(1), tree.New(1)) should return true, and Same(tree.New(1), tree.New(2)) should return false.
The documentation for Tree can be found here.
Solution:
package main
import (
"golang.org/x/tour/tree"
"fmt"
)
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int){
if t != nil {
Walk(t.Left, ch)
ch <- t.Value
Walk(t.Right, ch)
}
}
// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool{
c1, c2 := make(chan int), make(chan int)
go Walk(t1, c1)
go Walk(t2, c2)
if <-c1 == <-c2 {
return true
}else {
return false
}
}
func main() {
t1 := tree.New(1)
t2 := tree.New(8)
ch := make(chan int)
go Walk(t1, ch)
go Walk(t2, ch)
fmt.Println("the two trees are")
for i:=0; i<20; i++{
fmt.Println(<-ch)
}
fmt.Println("the two trees are same?", Same(t1, t2))
}