]> git.friedersdorff.com Git - max/project_euler.go.git/blob - 102_triangle_containment/main.go
Solution for problem 102: Triangle containment
[max/project_euler.go.git] / 102_triangle_containment / main.go
1 package main
2
3 import (
4         "encoding/csv"
5         "errors"
6         "fmt"
7         "git.friedersdorff.com/max/vector.go"
8         "os"
9         "strconv"
10 )
11
12 // sameSide returns true if p1 and p2 are on the same side of the line ab, false
13 // otherwise
14 func sameSide(p1, p2, a, b vector.Vec) bool {
15         cp1 := b.Sub(a).Cross(p1.Sub(a))
16         cp2 := b.Sub(a).Cross(p2.Sub(a))
17
18         return cp1.Dot(cp2) >= 0
19 }
20
21 // inTriangle returns true if point p is in triangle abc, false otherwise
22 func inTriangle(p, a, b, c vector.Vec) bool {
23         return sameSide(p, a, b, c) && sameSide(p, b, a, c) && sameSide(p, c, a, b)
24 }
25
26 func getVec(record []string) ([]vector.Vec, error) {
27         if len(record)%2 != 0 {
28                 return nil, errors.New(
29                         fmt.Sprintf("Length of record is not divisible by 2: %s",
30                                 len(record)))
31         }
32         var vecs []vector.Vec
33
34         floats := make([]float64, len(record))
35         for i, v := range record {
36                 num, err := strconv.ParseFloat(v, 64)
37
38                 if err != nil {
39                         return nil, errors.New(
40                                 fmt.Sprintf("Couldn't parse record to floats: %s",
41                                         record))
42                 }
43
44                 floats[i] = num
45         }
46
47         for i := 0; i < len(floats); i += 2 {
48                 vecs = append(vecs, vector.Vec{floats[i], floats[i+1], 0.0})
49         }
50         return vecs, nil
51
52 }
53
54 func main() {
55         if len(os.Args) != 2 {
56                 fmt.Println("Expect input file as first argument.")
57                 return
58         }
59
60         f, err := os.Open(os.Args[1])
61
62         if err != nil {
63                 fmt.Println(err)
64                 return
65         }
66
67         r := csv.NewReader(f)
68
69         nInTriangle := 0
70         for {
71                 triangle, err := r.Read()
72                 if err != nil {
73                         break
74                 }
75
76                 points, err := getVec(triangle)
77                 if err != nil {
78
79                         break
80                 }
81
82                 if len(points) != 3 {
83                         break
84                 }
85
86                 if inTriangle(vector.Vec{0, 0, 0},
87                         points[0], points[1], points[2]) {
88                         nInTriangle++
89                 }
90         }
91
92         fmt.Println(nInTriangle)
93         return
94 }