Solution to submarine navigation

This commit is contained in:
2021-12-02 14:01:30 +00:00
parent d41d58d2cf
commit 95b0635e7a
5 changed files with 1209 additions and 0 deletions

View File

@@ -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

File diff suppressed because it is too large Load Diff

39
two/main.go Normal file
View 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
View 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
View 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()
}
}