]> git.friedersdorff.com Git - max/project_euler.go.git/commitdiff
Solution for problem 102: Triangle containment master
authorMaximilian Friedersdorff <max@friedersdorff.com>
Mon, 11 Mar 2019 19:17:04 +0000 (19:17 +0000)
committerMaximilian Friedersdorff <max@friedersdorff.com>
Mon, 11 Mar 2019 19:17:04 +0000 (19:17 +0000)
102_triangle_containment/main.go [new file with mode: 0644]

diff --git a/102_triangle_containment/main.go b/102_triangle_containment/main.go
new file mode 100644 (file)
index 0000000..7a2d4b6
--- /dev/null
@@ -0,0 +1,94 @@
+package main
+
+import (
+       "encoding/csv"
+       "errors"
+       "fmt"
+       "git.friedersdorff.com/max/vector.go"
+       "os"
+       "strconv"
+)
+
+// sameSide returns true if p1 and p2 are on the same side of the line ab, false
+// otherwise
+func sameSide(p1, p2, a, b vector.Vec) bool {
+       cp1 := b.Sub(a).Cross(p1.Sub(a))
+       cp2 := b.Sub(a).Cross(p2.Sub(a))
+
+       return cp1.Dot(cp2) >= 0
+}
+
+// inTriangle returns true if point p is in triangle abc, false otherwise
+func inTriangle(p, a, b, c vector.Vec) bool {
+       return sameSide(p, a, b, c) && sameSide(p, b, a, c) && sameSide(p, c, a, b)
+}
+
+func getVec(record []string) ([]vector.Vec, error) {
+       if len(record)%2 != 0 {
+               return nil, errors.New(
+                       fmt.Sprintf("Length of record is not divisible by 2: %s",
+                               len(record)))
+       }
+       var vecs []vector.Vec
+
+       floats := make([]float64, len(record))
+       for i, v := range record {
+               num, err := strconv.ParseFloat(v, 64)
+
+               if err != nil {
+                       return nil, errors.New(
+                               fmt.Sprintf("Couldn't parse record to floats: %s",
+                                       record))
+               }
+
+               floats[i] = num
+       }
+
+       for i := 0; i < len(floats); i += 2 {
+               vecs = append(vecs, vector.Vec{floats[i], floats[i+1], 0.0})
+       }
+       return vecs, nil
+
+}
+
+func main() {
+       if len(os.Args) != 2 {
+               fmt.Println("Expect input file as first argument.")
+               return
+       }
+
+       f, err := os.Open(os.Args[1])
+
+       if err != nil {
+               fmt.Println(err)
+               return
+       }
+
+       r := csv.NewReader(f)
+
+       nInTriangle := 0
+       for {
+               triangle, err := r.Read()
+               if err != nil {
+                       break
+               }
+
+               points, err := getVec(triangle)
+               if err != nil {
+
+                       break
+               }
+
+               if len(points) != 3 {
+                       break
+               }
+
+               if inTriangle(vector.Vec{0, 0, 0},
+                       points[0], points[1], points[2]) {
+                       nInTriangle++
+               }
+       }
+
+       fmt.Println(nInTriangle)
+       return
+}