Solution to submarine navigation
This commit is contained in:
3
main.go
3
main.go
@@ -6,6 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"unsupervised.ca/aoc2021/one"
|
"unsupervised.ca/aoc2021/one"
|
||||||
|
"unsupervised.ca/aoc2021/two"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -25,6 +26,8 @@ func main() {
|
|||||||
switch flagParts[1] {
|
switch flagParts[1] {
|
||||||
case "one":
|
case "one":
|
||||||
day = one.Init("one/input.txt")
|
day = one.Init("one/input.txt")
|
||||||
|
case "two":
|
||||||
|
day = two.Init("two/input.txt")
|
||||||
default:
|
default:
|
||||||
fmt.Printf("%q does not have a solution.\n", flagParts[1])
|
fmt.Printf("%q does not have a solution.\n", flagParts[1])
|
||||||
help()
|
help()
|
||||||
|
1000
two/input.txt
Normal file
1000
two/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
39
two/main.go
Normal file
39
two/main.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package two
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type Two struct {
|
||||||
|
sub sub
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init(filepath string) *Two {
|
||||||
|
two := &Two{
|
||||||
|
sub: sub{},
|
||||||
|
}
|
||||||
|
|
||||||
|
two.sub.load(filepath)
|
||||||
|
|
||||||
|
return two
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Two) Answer() string {
|
||||||
|
d.sub.reset()
|
||||||
|
d.sub.execute()
|
||||||
|
|
||||||
|
return fmt.Sprintf("Horizontal is %d, depth is %d, answer is %d",
|
||||||
|
d.sub.horizontal,
|
||||||
|
d.sub.depth,
|
||||||
|
d.sub.horizontal*d.sub.depth,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Two) FollowUp() string {
|
||||||
|
d.sub.reset()
|
||||||
|
d.sub.executeWithAim()
|
||||||
|
|
||||||
|
return fmt.Sprintf("Horizontal is %d, depth is %d, answer is %d",
|
||||||
|
d.sub.horizontal,
|
||||||
|
d.sub.depth,
|
||||||
|
d.sub.horizontal*d.sub.depth,
|
||||||
|
)
|
||||||
|
}
|
87
two/sub.go
Normal file
87
two/sub.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package two
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type command struct {
|
||||||
|
instruction string
|
||||||
|
value int
|
||||||
|
}
|
||||||
|
|
||||||
|
type sub struct {
|
||||||
|
input []command
|
||||||
|
depth int
|
||||||
|
horizontal int
|
||||||
|
aim int
|
||||||
|
}
|
||||||
|
|
||||||
|
// load Loads the commands from input.txt into the sub
|
||||||
|
func (s *sub) load(filename string) error {
|
||||||
|
s.input = []command{}
|
||||||
|
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
for scanner.Scan() {
|
||||||
|
parts := strings.Split(scanner.Text(), " ")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return fmt.Errorf("Unable to parse input: %s", parts)
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := strconv.Atoi(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.input = append(s.input, command{
|
||||||
|
instruction: parts[0],
|
||||||
|
value: value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sub) reset() {
|
||||||
|
s.horizontal = 0
|
||||||
|
s.depth = 0
|
||||||
|
s.aim = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sub) execute() {
|
||||||
|
for _, command := range s.input {
|
||||||
|
switch command.instruction {
|
||||||
|
case "forward":
|
||||||
|
s.horizontal += command.value
|
||||||
|
case "up":
|
||||||
|
s.depth -= command.value
|
||||||
|
if s.depth < 0 {
|
||||||
|
s.depth = 0
|
||||||
|
}
|
||||||
|
case "down":
|
||||||
|
s.depth += command.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sub) executeWithAim() {
|
||||||
|
for _, command := range s.input {
|
||||||
|
switch command.instruction {
|
||||||
|
case "forward":
|
||||||
|
s.horizontal += command.value
|
||||||
|
s.depth += s.aim * command.value
|
||||||
|
case "up":
|
||||||
|
s.aim -= command.value
|
||||||
|
case "down":
|
||||||
|
s.aim += command.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
80
two/sub_test.go
Normal file
80
two/sub_test.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package two
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testInput = []string{
|
||||||
|
"forward 5",
|
||||||
|
"down 5",
|
||||||
|
"forward 8",
|
||||||
|
"up 3",
|
||||||
|
"down 8",
|
||||||
|
"forward 2",
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_scan(t *testing.T) {
|
||||||
|
s := sub{}
|
||||||
|
if err := s.load("input.txt"); err != nil {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.input) != 1000 {
|
||||||
|
t.Logf("Expected 1000 commands, found %d", len(s.input))
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_execute(t *testing.T) {
|
||||||
|
s := sub{
|
||||||
|
input: []command{},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, raw := range testInput {
|
||||||
|
parts := strings.Split(raw, " ")
|
||||||
|
value, _ := strconv.Atoi(parts[1])
|
||||||
|
s.input = append(s.input, command{
|
||||||
|
instruction: parts[0],
|
||||||
|
value: value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
s.execute()
|
||||||
|
if s.horizontal != 15 {
|
||||||
|
t.Logf("Expected horizontal of 15, found %d", s.horizontal)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.depth != 10 {
|
||||||
|
t.Logf("Expected depth of 10, found %d", s.depth)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_executeWithAim(t *testing.T) {
|
||||||
|
s := sub{
|
||||||
|
input: []command{},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, raw := range testInput {
|
||||||
|
parts := strings.Split(raw, " ")
|
||||||
|
value, _ := strconv.Atoi(parts[1])
|
||||||
|
s.input = append(s.input, command{
|
||||||
|
instruction: parts[0],
|
||||||
|
value: value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
s.executeWithAim()
|
||||||
|
if s.horizontal != 15 {
|
||||||
|
t.Logf("Expected horizontal of 15, found %d", s.horizontal)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.depth != 60 {
|
||||||
|
t.Logf("Expected depth of 60, found %d", s.depth)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user