mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-05-18 19:13:27 +02:00
2016-day21: gross scrambling and then checking permutations
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/alexchao26/advent-of-code-go/algos"
|
||||
"github.com/alexchao26/advent-of-code-go/cast"
|
||||
"github.com/alexchao26/advent-of-code-go/util"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var part int
|
||||
flag.IntVar(&part, "part", 1, "part 1 or 2")
|
||||
flag.Parse()
|
||||
fmt.Println("Running part", part)
|
||||
|
||||
var ans string
|
||||
if part == 1 {
|
||||
ans = part1(util.ReadFile("./input.txt"), "abcdefgh", "")
|
||||
} else {
|
||||
ans = part1(util.ReadFile("./input.txt"), "abcdefgh", "fbgdceah")
|
||||
}
|
||||
fmt.Println("Output:", ans)
|
||||
}
|
||||
|
||||
func part1(input string, starting string, target string) string {
|
||||
runSteps := func(starting string) string {
|
||||
registers := strings.Split(starting, "")
|
||||
for _, inst := range strings.Split(input, "\n") {
|
||||
registers = modifySlice(inst, registers)
|
||||
}
|
||||
return strings.Join(registers, "")
|
||||
}
|
||||
|
||||
// part 1
|
||||
if target == "" {
|
||||
return runSteps(starting)
|
||||
}
|
||||
|
||||
for _, p := range algos.MakeStringPermutations(starting) {
|
||||
if runSteps(p) == target {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
panic("no perms matched")
|
||||
}
|
||||
|
||||
func modifySlice(line string, sli []string) []string {
|
||||
switch {
|
||||
case strings.HasPrefix(line, "swap"):
|
||||
var i1, i2 int
|
||||
if strings.Contains(line, "position") {
|
||||
fmt.Sscanf(line, "swap position %d with position %d", &i1, &i2)
|
||||
} else {
|
||||
var c1, c2 string
|
||||
fmt.Sscanf(line, "swap letter %1s with letter %1s", &c1, &c2)
|
||||
i1, i2 = getIndex(sli, c1), getIndex(sli, c2)
|
||||
}
|
||||
sli[i1], sli[i2] = sli[i2], sli[i1]
|
||||
case strings.HasPrefix(line, "rotate"):
|
||||
var rightShift int
|
||||
parts := strings.Split(line, " ")
|
||||
if strings.Contains(line, "letter") {
|
||||
index := getIndex(sli, parts[6])
|
||||
if index >= 4 {
|
||||
index++
|
||||
}
|
||||
index++
|
||||
rightShift = index % len(sli)
|
||||
} else {
|
||||
// left or right
|
||||
rightShift = cast.ToInt(parts[2])
|
||||
if parts[1] == "left" {
|
||||
rightShift = len(sli) - rightShift
|
||||
}
|
||||
}
|
||||
// perform shift
|
||||
sli = append(sli[len(sli)-rightShift:], sli[:len(sli)-rightShift]...)
|
||||
case strings.HasPrefix(line, "reverse"):
|
||||
var i1, i2 int
|
||||
fmt.Sscanf(line, "reverse positions %d through %d", &i1, &i2)
|
||||
for i1 < i2 {
|
||||
sli[i1], sli[i2] = sli[i2], sli[i1]
|
||||
i1++
|
||||
i2--
|
||||
}
|
||||
case strings.HasPrefix(line, "move"):
|
||||
var i1, i2 int
|
||||
fmt.Sscanf(line, "move position %d to position %d", &i1, &i2)
|
||||
store := sli[i1]
|
||||
|
||||
// remove char at i1
|
||||
copy(sli[i1:], sli[i1+1:])
|
||||
|
||||
for i := len(sli) - 1; i >= i2+1; i-- {
|
||||
sli[i] = sli[i-1]
|
||||
}
|
||||
sli[i2] = store
|
||||
default:
|
||||
panic("unhandled instruction type: " + line)
|
||||
}
|
||||
|
||||
// return modified slice
|
||||
return sli
|
||||
}
|
||||
|
||||
func getIndex(letters []string, toFind string) int {
|
||||
for i, v := range letters {
|
||||
if v == toFind {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alexchao26/advent-of-code-go/util"
|
||||
)
|
||||
|
||||
var example = `swap position 4 with position 0
|
||||
swap letter d with letter b
|
||||
reverse positions 0 through 4
|
||||
rotate left 1 step
|
||||
move position 1 to position 4
|
||||
move position 3 to position 0
|
||||
rotate based on position of letter b
|
||||
rotate based on position of letter d`
|
||||
|
||||
func Test_part1(t *testing.T) {
|
||||
type args struct {
|
||||
input, starting, target string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{"part1 example", args{example, "abcde", ""}, "decab"},
|
||||
{"part1 actual", args{util.ReadFile("input.txt"), "abcdefgh", ""}, "bfheacgd"},
|
||||
{"part2 actual", args{util.ReadFile("input.txt"), "abcdefgh", "fbgdceah"}, "gcehdbfa"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := part1(tt.args.input, tt.args.starting, tt.args.target); got != tt.want {
|
||||
t.Errorf("part1() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user