1 package main
2
3 import (
4 "bufio"
5 "fmt"
6 "math"
7 "os"
8 "runtime"
9 )
10
11 const result = "Polar radius=%.02f θ=%.02f° → Cartesian x=%.02f y=%.02f\n"
12
13 var prompt = "Enter a radius and an angle (in degrees), e.g., 12.5 90, " +
14 "or %s to quit."
15
16 type polar struct {
17 radius float64
18 θ float64
19 }
20
21 type cartesian struct {
22 x float64
23 y float64
24 }
25
26 func init() {
27 if runtime.GOOS == "windows" {
28 prompt = fmt.Sprintf(prompt, "Ctrl+Z, Enter")
29 } else { // Unix-like
30 prompt = fmt.Sprintf(prompt, "Ctrl+D")
31 }
32 }
33
34 func main() {
35 questions := make(chan polar)
36 defer close(questions)
37 answers := createSolver(questions)
38 defer close(answers)
39 interact(questions, answers)
40 }
41
42 func createSolver(questions chan polar) chan cartesian {
43 answers := make(chan cartesian)
44 go func() {
45 for {
46 polarCoord := <-questions
47 θ := polarCoord.θ * math.Pi / 180.0 // degrees to radians
48 x := polarCoord.radius * math.Cos(θ)
49 y := polarCoord.radius * math.Sin(θ)
50 answers <- cartesian{x, y}
51 }
52 }()
53 return answers
54 }
55
56 func interact(questions chan polar, answers chan cartesian) {
57 reader := bufio.NewReader(os.Stdin)
58 fmt.Println(prompt)
59 for {
60 fmt.Printf("Radius and angle: ")
61 line, err := reader.ReadString('\n')
62 if err != nil {
63 break
64 }
65 var radius, θ float64
66 if _, err := fmt.Sscanf(line, "%f %f", &radius, &θ); err != nil {
67 fmt.Fprintln(os.Stderr, "invalid input")
68 continue
69 }
70 questions <- polar{radius, θ}
71 coord := <-answers
72 fmt.Printf(result, radius, θ, coord.x, coord.y)
73 }
74 fmt.Println()
75 }