Selaa lähdekoodia

Borrowed some code

Piotr Czajkowski 1 viikko sitten
vanhempi
commit
6681232766
2 muutettua tiedostoa jossa 126 lisäystä ja 8 poistoa
  1. 91 8
      09/code.go
  2. 35 0
      09/stack.go

+ 91 - 8
09/code.go

@@ -5,12 +5,103 @@ import (
 	"fmt"
 	"log"
 	"os"
+	"sort"
 )
 
 type Point struct {
 	X, Y int
 }
 
+type PointList []Point
+
+func (p PointList) Len() int {
+	return len(p)
+}
+
+func (p PointList) Swap(i, j int) {
+	p[i], p[j] = p[j], p[i]
+}
+
+func Area2(a, b, c Point) int {
+	return (b.X-a.X)*(c.Y-a.Y) - (c.X-a.X)*(b.Y-a.Y)
+}
+
+func abs(a int) int {
+	if a < 0 {
+		return -a
+	}
+
+	return a
+}
+
+func (p PointList) Less(i, j int) bool {
+	area := Area2(p[0], p[i], p[j])
+	if area == 0 {
+		x := abs(p[i].X-p[0].X) - abs(p[j].X-p[0].X)
+		y := abs(p[i].Y-p[0].Y) - abs(p[j].Y-p[0].Y)
+		if x < 0 || y < 0 {
+			return true
+		} else if x > 0 || y > 0 {
+			return false
+		} else {
+			return false
+		}
+	}
+	return area > 0
+}
+
+func (p PointList) FindLowestPoint() {
+	m := 0
+	for i := 1; i < len(p); i++ {
+		//If lowest points are on the same line, take the rightmost point
+		if (p[i].Y < p[m].Y) || ((p[i].Y == p[m].Y) && p[i].X > p[m].X) {
+			m = i
+		}
+	}
+	p[0], p[m] = p[m], p[0]
+}
+
+func isLeft(p0, p1, p2 Point) bool {
+	return Area2(p0, p1, p2) > 0
+}
+
+func (points PointList) Compute() (PointList, bool) {
+	if len(points) < 3 {
+		return nil, false
+	}
+
+	stack := new(Stack)
+	points.FindLowestPoint()
+	sort.Sort(&points)
+
+	stack.Push(points[0])
+	stack.Push(points[1])
+
+	i := 2
+	for i < len(points) {
+		pi := points[i]
+		p1 := stack.top.next.value.(Point)
+		p2 := stack.top.value.(Point)
+		if isLeft(p1, p2, pi) {
+			stack.Push(pi)
+			i++
+		} else {
+			stack.Pop()
+		}
+	}
+
+	//Copy the hull
+	ret := make(PointList, stack.Len())
+	top := stack.top
+	count := 0
+	for top != nil {
+		ret[count] = top.value.(Point)
+		top = top.next
+		count++
+	}
+	return ret, true
+}
+
 func readInput(file *os.File) []Point {
 	scanner := bufio.NewScanner(file)
 	var tiles []Point
@@ -33,14 +124,6 @@ func readInput(file *os.File) []Point {
 	return tiles
 }
 
-func abs(a int) int {
-	if a < 0 {
-		return -a
-	}
-
-	return a
-}
-
 func part1(tiles []Point) int {
 	end := len(tiles)
 	var maxArea int

+ 35 - 0
09/stack.go

@@ -0,0 +1,35 @@
+// Stack implementation from
+// https://gist.github.com/bemasher/1777766
+package main
+
+type Stack struct {
+	top  *Element
+	size int
+}
+
+type Element struct {
+	value interface{} // All types satisfy the empty interface, so we can store anything here.
+	next  *Element
+}
+
+// Return the stack's length
+func (s *Stack) Len() int {
+	return s.size
+}
+
+// Push a new element onto the stack
+func (s *Stack) Push(value interface{}) {
+	s.top = &Element{value, s.top}
+	s.size++
+}
+
+// Remove the top element from the stack and return it's value
+// If the stack is empty, return nil
+func (s *Stack) Pop() (value interface{}) {
+	if s.size > 0 {
+		value, s.top = s.top.value, s.top.next
+		s.size--
+		return
+	}
+	return nil
+}