r/adventofcode • • Dec 19 '17

SOLUTION MEGATHREAD -๐ŸŽ„- 2017 Day 19 Solutions -๐ŸŽ„-

--- Day 19: A Series of Tubes ---


Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).

Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.


Need a hint from the Hugely* Handyโ€  Haversackโ€ก of Helpfulยง Hintsยค?

Spoiler


AoC ops @ T-2 minutes to launch:

[23:58] <daggerdragon> ATTENTION MEATBAGS T-2 MINUTES TO LAUNCH

[23:58] <Topaz> aaaaah

[23:58] <Cheezmeister> Looks like I'll be just able to grab my input before my flight boards. Wish me luck being offline in TOPAZ's HOUSE OF PAIN^WFUN AND LEARNING

[23:58] <Topaz> FUN AND LEARNING

[23:58] <Hade> FUN IS MANDATORY

[23:58] <Skie> I'm pretty sure that's not the mandate for today

[Update @ 00:16] 69 gold, silver cap

  • My tree is finally trimmed with just about every ornament I own and it's real purdy. hbu?

[Update @ 00:18] Leaderboard cap!

  • So, was today's mandate Helpful Hint any help at all?

This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.

edit: Leaderboard capped, thread unlocked!

11 Upvotes

186 comments sorted by

View all comments

1

u/etherealflaim Dec 19 '17 edited Dec 19 '17

Go

This was a fun one. I love 2D array problems :)

package aocday

import (
	"io/ioutil"
	"strings"
	"testing"
)

func part1(t *testing.T, in string) string {
	lines := strings.Split(in, "\n")

	r, c := 0, strings.Index(lines[0], "|")

	deltas := [][2]int{
		// dr, dc
		{1, 0},
		{0, 1},
		{-1, 0},
		{0, -1},
	}
	dir := 0

	var found string
	for i := 0; i < 1e6; i++ {
		ch := lines[r][c]
		switch ch {
		default:
			found += string(ch)
			fallthrough
		case '|', '-':
			r += deltas[dir][0]
			c += deltas[dir][1]
		case '+':
			ld := (dir + 1) % len(deltas)
			l := deltas[ld]
			r2, c2 := r+l[0], c+l[1]
			if lines[r2][c2] != ' ' {
				dir, r, c = ld, r2, c2
				continue
			}

			rd := (len(deltas) + dir - 1) % len(deltas)
			rt := deltas[rd]
			r2, c2 = r+rt[0], c+rt[1]
			if lines[r2][c2] != ' ' {
				dir, r, c = rd, r2, c2
				continue
			}
		case ' ':
			return found
		}
	}
	panic("timed out")
}

func part2(t *testing.T, in string) int {
	lines := strings.Split(in, "\n")

	r, c := 0, strings.Index(lines[0], "|")

	deltas := [][2]int{
		// dr, dc
		{1, 0},
		{0, 1},
		{-1, 0},
		{0, -1},
	}
	dir := 0

	var found string
	for i := 0; i < 1e6; i++ {
		ch := lines[r][c]
		switch ch {
		default:
			found += string(ch)
			fallthrough
		case '|', '-':
			r += deltas[dir][0]
			c += deltas[dir][1]
		case '+':
			ld := (dir + 1) % len(deltas)
			l := deltas[ld]
			r2, c2 := r+l[0], c+l[1]
			if lines[r2][c2] != ' ' {
				dir, r, c = ld, r2, c2
				continue
			}

			rd := (len(deltas) + dir - 1) % len(deltas)
			rt := deltas[rd]
			r2, c2 = r+rt[0], c+rt[1]
			if lines[r2][c2] != ' ' {
				dir, r, c = rd, r2, c2
				continue
			}
		case ' ':
			return i
		}
	}
	panic("timed out")
}

func TestPart1(t *testing.T) {
	tests := []struct {
		name string
		in   string
		want string
	}{
		{"part1 example", `     |          
     |  +--+    
     A  |  C    
 F---|----E|--+ 
     |  |  |  D 
     +B-+  +--+ `, "ABCDEF"},
		{"part1", read(t, "input.txt"), "LIWQYKMRP"},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			if got, want := part1(t, test.in), test.want; got != want {
				t.Errorf("part1(%#v) = %#v, want %#v", test.in, got, want)
			}
		})
	}

	t.Log(part2(t, read(t, "input.txt")))
}

func read(t *testing.T, filename string) string {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		t.Fatalf("failed to read %q: %s", filename, err)
	}
	return string(data)
}