Skip to content

Commit

Permalink
Merge pull request #926 from vaskoz/day458
Browse files Browse the repository at this point in the history
Day458
  • Loading branch information
vaskoz committed Feb 23, 2020
2 parents dffcb73 + 0987e99 commit 8a6f80c
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -455,4 +455,5 @@ problems from
* [Day 455](https://github.com/vaskoz/dailycodingproblem-go/issues/919)
* [Day 456](https://github.com/vaskoz/dailycodingproblem-go/issues/921)
* [Day 457](https://github.com/vaskoz/dailycodingproblem-go/issues/923)
* [Day 458](https://github.com/vaskoz/dailycodingproblem-go/issues/925)

114 changes: 114 additions & 0 deletions day458/problem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package day458

import "strings"

// Direction represents the eight cardinal and intercardinal directions.
type Direction string

const (
// N is North
N Direction = "N"
// NE is North-East
NE Direction = "NE"
// E is East
E Direction = "E"
// SE is South-East
SE Direction = "SE"
// S is South
S Direction = "S"
// SW is South-West
SW Direction = "SW"
// W is West
W Direction = "W"
// NW is North-West
NW Direction = "NW"
)

// Position represents a point in Euclidean geometry.
type Position struct {
X, Y int
}

// directions defines the relative coordinates of each Direction.
// nolint
var directions = map[Direction]Position{
N: {0, -1},
NE: {1, -1},
E: {1, 0},
SE: {1, 1},
S: {0, 1},
SW: {-1, 1},
W: {-1, 0},
NW: {-1, -1},
}

// IsValidRules answers if the rules are consistent.
func IsValidRules(rules []string) bool {
positions := make(map[string]Position)

for _, rule := range rules {
parts := strings.Split(rule, " ")
to, dir, from := parts[0], Direction(parts[1]), parts[2]
toPos, toFound := positions[to]
fromPos, fromFound := positions[from]

switch delta := directions[dir]; {
case toFound && fromFound:
if !checkValid(fromPos, toPos, dir) {
return false
}
case toFound && !fromFound:
positions[from] = Position{toPos.X - delta.X, toPos.Y - delta.Y}
case !toFound && fromFound:
positions[to] = Position{fromPos.X + delta.X, fromPos.Y + delta.Y}
default:
positions[from] = Position{0, 0}
positions[to] = directions[dir]
}
}

return true
}

func checkValid(from, to Position, dir Direction) bool {
return isNorth(from, to, dir) ||
isNorthEast(from, to, dir) ||
isEast(from, to, dir) ||
isSouthEast(from, to, dir) ||
isSouth(from, to, dir) ||
isSouthWest(from, to, dir) ||
isWest(from, to, dir) ||
isNorthWest(from, to, dir)
}

func isNorth(from, to Position, dir Direction) bool {
return dir == N && to.Y < from.Y
}

func isNorthEast(from, to Position, dir Direction) bool {
return dir == NE && to.Y < from.Y && to.X > from.X
}

func isEast(from, to Position, dir Direction) bool {
return dir == E && to.X > from.X
}

func isSouthEast(from, to Position, dir Direction) bool {
return dir == SE && to.X > from.X && to.Y > from.Y
}

func isSouth(from, to Position, dir Direction) bool {
return dir == S && to.Y > from.Y
}

func isSouthWest(from, to Position, dir Direction) bool {
return dir == SW && to.X < from.X && to.Y > from.Y
}

func isWest(from, to Position, dir Direction) bool {
return dir == W && to.X < from.X
}

func isNorthWest(from, to Position, dir Direction) bool {
return dir == NW && to.Y < from.Y && to.X < from.X
}
40 changes: 40 additions & 0 deletions day458/problem_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package day458

import "testing"

// nolint
var testcases = []struct {
rules []string
isValid bool
}{
{[]string{"A N B", "B NE C", "C N A"}, false},
{[]string{"A NW B", "A N B"}, true},
{[]string{"A N B", "C N A", "A S C"}, true},
{[]string{"A NW B", "C NE A", "A S C"}, true},
{[]string{"A NW B", "C NE A", "A SE C"}, false},
{[]string{"A NW B", "C NE A", "A SW C"}, true},
{[]string{"A NW B", "C NE A", "A W C"}, true},
{[]string{"A NW B", "C NE A", "A E C"}, false},
{[]string{"A NW B", "C NE A", "B S C"}, true},
{[]string{"A NW B", "C NE A", "C E B"}, false},
{[]string{"A NW B", "C NE A", "B SE A"}, true},
{[]string{"A NW B", "C NE A", "A SE B"}, false},
}

func TestIsValidRules(t *testing.T) {
t.Parallel()

for tcid, tc := range testcases {
if result := IsValidRules(tc.rules); result != tc.isValid {
t.Errorf("TC%d Expected %v got %v", tcid, tc.isValid, result)
}
}
}

func BenchmarkIsValidRules(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tc := range testcases {
IsValidRules(tc.rules)
}
}
}

0 comments on commit 8a6f80c

Please sign in to comment.