commit
b27151efe1
1
Where-is-the-Arrow-Pointing/gnieark/input.txt
Symbolic link
1
Where-is-the-Arrow-Pointing/gnieark/input.txt
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../input.txt
|
104
Where-is-the-Arrow-Pointing/moul/witap.go
Normal file
104
Where-is-the-Arrow-Pointing/moul/witap.go
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
package witap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Resolver struct {
|
||||||
|
Lines []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Position struct{ X, Y int }
|
||||||
|
|
||||||
|
func (p *Position) Up() Position { return Position{X: p.X, Y: p.Y - 1} }
|
||||||
|
func (p *Position) Down() Position { return Position{X: p.X, Y: p.Y + 1} }
|
||||||
|
func (p *Position) Left() Position { return Position{X: p.X - 1, Y: p.Y} }
|
||||||
|
func (p *Position) Right() Position { return Position{X: p.X + 1, Y: p.Y} }
|
||||||
|
|
||||||
|
func NewResolverFromString(theMap string) Resolver {
|
||||||
|
return Resolver{
|
||||||
|
Lines: strings.Split(theMap, "\n"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resolver) GetStartPosition() (Position, error) {
|
||||||
|
for y, line := range r.Lines {
|
||||||
|
if pos := strings.Index(line, "S"); pos != -1 {
|
||||||
|
return Position{pos, y}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Position{-1, -1}, fmt.Errorf("No such starting point")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resolver) Run() (string, error) {
|
||||||
|
startPos, err := r.GetStartPosition()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Step(startPos, Position{-1, -1})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resolver) PrintMap() {
|
||||||
|
fmt.Println(strings.Join(r.Lines, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Position) Continue(lastPos Position) Position {
|
||||||
|
return Position{
|
||||||
|
X: 2*p.X - lastPos.X,
|
||||||
|
Y: 2*p.Y - lastPos.Y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resolver) GetChar(position Position) string {
|
||||||
|
return string(r.Lines[position.Y][position.X])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Position) AllDirections() []Position {
|
||||||
|
return []Position{
|
||||||
|
p.Up(), p.Down(), p.Left(), p.Right(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Resolver) Step(curPos, lastPos Position) (string, error) {
|
||||||
|
if curPos.X < 0 || curPos.Y < 0 || curPos.Y >= len(r.Lines) || curPos.X >= len(r.Lines[curPos.Y]) {
|
||||||
|
return "", fmt.Errorf("Invalid position")
|
||||||
|
}
|
||||||
|
|
||||||
|
letter := r.GetChar(curPos)
|
||||||
|
|
||||||
|
if letter == "S" && lastPos.X != -1 {
|
||||||
|
return "", fmt.Errorf("S must be the first position")
|
||||||
|
} else if letter == "+" && lastPos.X == -1 {
|
||||||
|
return "", fmt.Errorf("Cannot do this symbol after a start")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch letter {
|
||||||
|
case "S", "+":
|
||||||
|
for _, nextPos := range curPos.AllDirections() {
|
||||||
|
if nextPos == lastPos {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
letter, err := r.Step(nextPos, curPos)
|
||||||
|
if err == nil {
|
||||||
|
return letter, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("Nothing to do, cannot continue")
|
||||||
|
case "-", "|":
|
||||||
|
return r.Step(curPos.Continue(lastPos), curPos)
|
||||||
|
case "V":
|
||||||
|
return r.Step(curPos.Down(), curPos)
|
||||||
|
case ">":
|
||||||
|
return r.Step(curPos.Right(), curPos)
|
||||||
|
case "<":
|
||||||
|
return r.Step(curPos.Left(), curPos)
|
||||||
|
case "^":
|
||||||
|
return r.Step(curPos.Up(), curPos)
|
||||||
|
case " ":
|
||||||
|
return "", fmt.Errorf("Invalid path, cannot continue")
|
||||||
|
default:
|
||||||
|
return letter, nil
|
||||||
|
}
|
||||||
|
}
|
63
Where-is-the-Arrow-Pointing/moul/witap_test.go
Normal file
63
Where-is-the-Arrow-Pointing/moul/witap_test.go
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
package witap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
)
|
||||||
|
|
||||||
|
var inputs = []string{
|
||||||
|
`
|
||||||
|
d S------+ b
|
||||||
|
|
|
||||||
|
|
|
||||||
|
c +--->a
|
||||||
|
`, `
|
||||||
|
S-----+---a->c
|
||||||
|
|
|
||||||
|
V
|
||||||
|
b
|
||||||
|
`, `
|
||||||
|
a S s
|
||||||
|
| |
|
||||||
|
V V
|
||||||
|
b c
|
||||||
|
`, `
|
||||||
|
d s<+S+--V
|
||||||
|
||| Q
|
||||||
|
-++
|
||||||
|
`, `
|
||||||
|
d s-+ +-S +--+
|
||||||
|
+-->b | | |
|
||||||
|
| | +--+ |
|
||||||
|
+--+ A<----+
|
||||||
|
`, `
|
||||||
|
S-----+
|
||||||
|
| +-^
|
||||||
|
+---+->B
|
||||||
|
+---^
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
var outputs = []string{
|
||||||
|
"a", "b", "b", "Q", "A", "B",
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleResolver_a() {
|
||||||
|
resolver := NewResolverFromString(inputs[0])
|
||||||
|
fmt.Println(resolver)
|
||||||
|
// fixme: add output
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResolver(t *testing.T) {
|
||||||
|
Convey("Testing resolver", t, func() {
|
||||||
|
for idx, input := range inputs {
|
||||||
|
Convey(fmt.Sprintf("input %d", idx+1), func() {
|
||||||
|
resolver := NewResolverFromString(input[1 : len(input)-1])
|
||||||
|
output, err := resolver.Run()
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(output, ShouldEqual, outputs[idx])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user