mirror of
				https://github.com/onyx-and-iris/aoc2023.git
				synced 2025-11-03 22:31:46 +00:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "3d42da78628105c6da6f3a37142fae5388fadfb8" and "0f254a243eff75ae44d8631153d63e3548e3893f" have entirely different histories.
		
	
	
		
			3d42da7862
			...
			0f254a243e
		
	
		
@ -1,10 +0,0 @@
 | 
				
			|||||||
module github.com/onyx-and-iris/aoc2023/day-12
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
go 1.21.5
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
require github.com/sirupsen/logrus v1.9.3
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
require (
 | 
					 | 
				
			||||||
	github.com/stretchr/testify v1.8.4 // indirect
 | 
					 | 
				
			||||||
	golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
@ -1,17 +0,0 @@
 | 
				
			|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
					 | 
				
			||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 | 
					 | 
				
			||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
					 | 
				
			||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 | 
					 | 
				
			||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
					 | 
				
			||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
 | 
					 | 
				
			||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 | 
					 | 
				
			||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
					 | 
				
			||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
					 | 
				
			||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
 | 
					 | 
				
			||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 | 
					 | 
				
			||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
 | 
					 | 
				
			||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					 | 
				
			||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					 | 
				
			||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
					 | 
				
			||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
					 | 
				
			||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
					 | 
				
			||||||
@ -1,10 +0,0 @@
 | 
				
			|||||||
TEST="test.txt"
 | 
					 | 
				
			||||||
INPUT="input.txt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
test:
 | 
					 | 
				
			||||||
	cat $(TEST) | go run .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
run:
 | 
					 | 
				
			||||||
	cat $(INPUT) | go run .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
all: test
 | 
					 | 
				
			||||||
							
								
								
									
										113
									
								
								day-12/one.go
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								day-12/one.go
									
									
									
									
									
								
							@ -1,113 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	log "github.com/sirupsen/logrus"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	OPERATIONAL = iota
 | 
					 | 
				
			||||||
	DAMAGED
 | 
					 | 
				
			||||||
	UNKNOWN
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var records []record
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type record struct {
 | 
					 | 
				
			||||||
	format  []int
 | 
					 | 
				
			||||||
	springs []spring
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func newRecord() record {
 | 
					 | 
				
			||||||
	return record{}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// raw returns the state of all springs for this record as int array
 | 
					 | 
				
			||||||
func (r record) raw() []int {
 | 
					 | 
				
			||||||
	vals := make([]int, len(r.springs))
 | 
					 | 
				
			||||||
	for j, spring := range r.springs {
 | 
					 | 
				
			||||||
		vals[j] = spring.state
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return vals
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type spring struct {
 | 
					 | 
				
			||||||
	state int
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func newSpring(state int) spring {
 | 
					 | 
				
			||||||
	return spring{state: state}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// tracker keeps track of results for function calls
 | 
					 | 
				
			||||||
type tracker struct {
 | 
					 | 
				
			||||||
	checked map[string]int
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func newTracker() tracker {
 | 
					 | 
				
			||||||
	return tracker{checked: make(map[string]int)}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (t tracker) add(key string, res int) {
 | 
					 | 
				
			||||||
	t.checked[key] = res
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func validate(springs, format []int) bool {
 | 
					 | 
				
			||||||
	return !contains(springs[:format[0]], OPERATIONAL) && (format[0] == len(springs) || springs[format[0]] != DAMAGED)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// count returns the number of arrangements possible for a set of springs
 | 
					 | 
				
			||||||
func count(springs, format []int) int {
 | 
					 | 
				
			||||||
	if len(springs) == 0 {
 | 
					 | 
				
			||||||
		if len(format) == 0 {
 | 
					 | 
				
			||||||
			return 1
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(format) == 0 {
 | 
					 | 
				
			||||||
		if contains(springs, DAMAGED) {
 | 
					 | 
				
			||||||
			return 0
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return 1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	identifier := fmt.Sprintf("%v%v", format, springs)
 | 
					 | 
				
			||||||
	if res, ok := fnTracker.checked[fmt.Sprintf("%v%v", format, springs)]; ok {
 | 
					 | 
				
			||||||
		log.Debug("returning cached value for ", identifier)
 | 
					 | 
				
			||||||
		return res
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	result := 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if springs[0] == OPERATIONAL || springs[0] == UNKNOWN {
 | 
					 | 
				
			||||||
		result += count(springs[1:], format)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if springs[0] == DAMAGED || springs[0] == UNKNOWN {
 | 
					 | 
				
			||||||
		if format[0] < len(springs) && validate(springs, format) {
 | 
					 | 
				
			||||||
			result += count(springs[format[0]+1:], format[1:])
 | 
					 | 
				
			||||||
		} else if format[0] == len(springs) && validate(springs, format) {
 | 
					 | 
				
			||||||
			result += count(springs[format[0]:], format[1:])
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fnTracker.add(identifier, result)
 | 
					 | 
				
			||||||
	return result
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var fnTracker tracker
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// one returns the sum of all arrangement counts
 | 
					 | 
				
			||||||
func one(lines []string) int {
 | 
					 | 
				
			||||||
	parselines(lines)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fnTracker = newTracker()
 | 
					 | 
				
			||||||
	sum := 0
 | 
					 | 
				
			||||||
	for _, record := range records {
 | 
					 | 
				
			||||||
		raw := record.raw()
 | 
					 | 
				
			||||||
		sum += count(raw, record.format)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sum
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,5 +0,0 @@
 | 
				
			|||||||
#!/usr/bin/env bash
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
INPUT="input.txt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cat $INPUT | go run .
 | 
					 | 
				
			||||||
@ -1,22 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	log "github.com/sirupsen/logrus"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func init() {
 | 
					 | 
				
			||||||
	log.SetLevel(log.InfoLevel)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	lines := readlines()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ans := one(lines)
 | 
					 | 
				
			||||||
	fmt.Printf("solution one: %d\n", ans)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ans = two(lines)
 | 
					 | 
				
			||||||
	fmt.Printf("solution two: %d\n", ans)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,36 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// multiplyBy unfolds all records by a given factor
 | 
					 | 
				
			||||||
func multiplyRawBy(factor int, original []int) []int {
 | 
					 | 
				
			||||||
	multiplied := []int{}
 | 
					 | 
				
			||||||
	for i := 0; i < factor; i++ {
 | 
					 | 
				
			||||||
		multiplied = append(multiplied, original...)
 | 
					 | 
				
			||||||
		if i < factor-1 {
 | 
					 | 
				
			||||||
			multiplied = append(multiplied, UNKNOWN)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return multiplied
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// multiplyBy unfolds all records by a given factor
 | 
					 | 
				
			||||||
func multiplyFormatBy(factor int, original []int) []int {
 | 
					 | 
				
			||||||
	multiplied := []int{}
 | 
					 | 
				
			||||||
	for i := 0; i < factor; i++ {
 | 
					 | 
				
			||||||
		multiplied = append(multiplied, original...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return multiplied
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// two returns the sum of all unfolded arrangement counts
 | 
					 | 
				
			||||||
func two(lines []string) int {
 | 
					 | 
				
			||||||
	fnTracker = newTracker()
 | 
					 | 
				
			||||||
	sum := 0
 | 
					 | 
				
			||||||
	for _, record := range records {
 | 
					 | 
				
			||||||
		raw := record.raw()
 | 
					 | 
				
			||||||
		sum += count(multiplyRawBy(5, raw), multiplyFormatBy(5, record.format))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sum
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,71 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bufio"
 | 
					 | 
				
			||||||
	"log"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"unicode"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readlines reads lines from stdin.
 | 
					 | 
				
			||||||
// returns input as an array of strings
 | 
					 | 
				
			||||||
func readlines() []string {
 | 
					 | 
				
			||||||
	lines := []string{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	scanner := bufio.NewScanner(os.Stdin)
 | 
					 | 
				
			||||||
	for scanner.Scan() {
 | 
					 | 
				
			||||||
		lines = append(lines, scanner.Text())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := scanner.Err(); err != nil {
 | 
					 | 
				
			||||||
		log.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return lines
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func parselines(lines []string) {
 | 
					 | 
				
			||||||
	f := func(c rune) bool {
 | 
					 | 
				
			||||||
		return !unicode.IsDigit(c)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	records = make([]record, len(lines))
 | 
					 | 
				
			||||||
	for i, line := range lines {
 | 
					 | 
				
			||||||
		record := newRecord()
 | 
					 | 
				
			||||||
		for _, r := range line {
 | 
					 | 
				
			||||||
			switch r {
 | 
					 | 
				
			||||||
			case '.':
 | 
					 | 
				
			||||||
				record.springs = append(record.springs, newSpring(OPERATIONAL))
 | 
					 | 
				
			||||||
			case '#':
 | 
					 | 
				
			||||||
				record.springs = append(record.springs, newSpring(DAMAGED))
 | 
					 | 
				
			||||||
			case '?':
 | 
					 | 
				
			||||||
				record.springs = append(record.springs, newSpring(UNKNOWN))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		record.format = convertToInts(strings.FieldsFunc(line, f))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		records[i] = record
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// convertToInts converts a string representing ints to an array of ints
 | 
					 | 
				
			||||||
func convertToInts(data []string) []int {
 | 
					 | 
				
			||||||
	nums := []int{}
 | 
					 | 
				
			||||||
	for _, elem := range data {
 | 
					 | 
				
			||||||
		n, _ := strconv.Atoi(elem)
 | 
					 | 
				
			||||||
		nums = append(nums, n)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nums
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// contains returns true if a slice of elements contains a given element
 | 
					 | 
				
			||||||
func contains[T comparable](elems []T, v T) bool {
 | 
					 | 
				
			||||||
	for _, s := range elems {
 | 
					 | 
				
			||||||
		if v == s {
 | 
					 | 
				
			||||||
			return true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,3 +0,0 @@
 | 
				
			|||||||
module github.com/onyx-and-iris/aoc2023/day-13
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
go 1.21.5
 | 
					 | 
				
			||||||
@ -1,33 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type imgs struct {
 | 
					 | 
				
			||||||
	img []img
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func newImages() imgs {
 | 
					 | 
				
			||||||
	return imgs{img: make([]img, 0)}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type img struct {
 | 
					 | 
				
			||||||
	raw []string
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func newImg() img {
 | 
					 | 
				
			||||||
	return img{raw: make([]string, 0)}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (i img) transposed() []string {
 | 
					 | 
				
			||||||
	transposed := []string{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for x := 0; x < len(i.raw[0]); x++ {
 | 
					 | 
				
			||||||
		buf := ""
 | 
					 | 
				
			||||||
		for j := len(i.raw) - 1; j >= 0; j-- {
 | 
					 | 
				
			||||||
			buf += string(i.raw[j][x])
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		transposed = append(transposed, buf)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return transposed
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var images imgs
 | 
					 | 
				
			||||||
@ -1,10 +0,0 @@
 | 
				
			|||||||
TEST="test.txt"
 | 
					 | 
				
			||||||
INPUT="input.txt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
test:
 | 
					 | 
				
			||||||
	cat $(TEST) | go run .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
run:
 | 
					 | 
				
			||||||
	cat $(INPUT) | go run .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
all: test
 | 
					 | 
				
			||||||
@ -1,62 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	log "github.com/sirupsen/logrus"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// findReflection returns the reflection point for an image
 | 
					 | 
				
			||||||
func findReflection(image []string) (int, bool) {
 | 
					 | 
				
			||||||
	walkToEdge := func(lower, upper int) bool {
 | 
					 | 
				
			||||||
		for lower >= 0 && upper < len(image) && strings.Compare(image[lower], image[upper]) == 0 {
 | 
					 | 
				
			||||||
			lower--
 | 
					 | 
				
			||||||
			upper++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lower++
 | 
					 | 
				
			||||||
		return (lower == 0 || upper == len(image))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i := 0; i < len(image)-1; i++ {
 | 
					 | 
				
			||||||
		if strings.Compare(image[i], image[i+1]) == 0 {
 | 
					 | 
				
			||||||
			log.Debug("start point: ", image[i], " vs ", image[i+1])
 | 
					 | 
				
			||||||
			if walkToEdge(i, i+1) {
 | 
					 | 
				
			||||||
				return i, true
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0, false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// horizontalReflection returns the reflection point of a horizontal mirror
 | 
					 | 
				
			||||||
func horizontalReflection(image img, fn func(image []string) (int, bool)) (int, bool) {
 | 
					 | 
				
			||||||
	n, ok := fn(image.raw)
 | 
					 | 
				
			||||||
	return n, ok
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// verticalReflection returns the reflection point of a vertical mirror
 | 
					 | 
				
			||||||
func verticalReflection(image img, fn func(image []string) (int, bool)) (int, bool) {
 | 
					 | 
				
			||||||
	n, ok := fn(image.transposed())
 | 
					 | 
				
			||||||
	return n, ok
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// one returns a calculation based on reflection points for all images.
 | 
					 | 
				
			||||||
func one(lines []string) int {
 | 
					 | 
				
			||||||
	parselines(lines)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sum := 0
 | 
					 | 
				
			||||||
	for _, image := range images.img {
 | 
					 | 
				
			||||||
		log.Debug("checking for horizontal reflection")
 | 
					 | 
				
			||||||
		n, ok := horizontalReflection(image, findReflection)
 | 
					 | 
				
			||||||
		if ok {
 | 
					 | 
				
			||||||
			sum += 100 * (n + 1)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		log.Debug("checking for vertical reflection")
 | 
					 | 
				
			||||||
		n, ok = verticalReflection(image, findReflection)
 | 
					 | 
				
			||||||
		if ok {
 | 
					 | 
				
			||||||
			sum += (n + 1)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sum
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,19 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/go-playground/assert"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestTranspose(t *testing.T) {
 | 
					 | 
				
			||||||
	//t.Skip("skipping test")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	img := newImg()
 | 
					 | 
				
			||||||
	img.raw = []string{"#.##", "..#.", "##.."}
 | 
					 | 
				
			||||||
	expected := []string{"#.#", "#..", ".##", "..#"}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	t.Run("Should flip the image ninety degrees rightwards", func(t *testing.T) {
 | 
					 | 
				
			||||||
		assert.Equal(t, expected, img.transposed())
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,21 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	log "github.com/sirupsen/logrus"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func init() {
 | 
					 | 
				
			||||||
	log.SetLevel(log.InfoLevel)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func main() {
 | 
					 | 
				
			||||||
	lines := readlines()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ans := one(lines)
 | 
					 | 
				
			||||||
	fmt.Printf("solution one: %d\n", ans)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ans = two(lines)
 | 
					 | 
				
			||||||
	fmt.Printf("solution two: %d\n", ans)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,48 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	log "github.com/sirupsen/logrus"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// findReflectionWithDifference returns the reflection point for an image with one smudge
 | 
					 | 
				
			||||||
func findReflectionWithDifference(image []string) (int, bool) {
 | 
					 | 
				
			||||||
	walkToEdge := func(lower, upper int) bool {
 | 
					 | 
				
			||||||
		diffs := 0
 | 
					 | 
				
			||||||
		for lower >= 0 && upper < len(image) {
 | 
					 | 
				
			||||||
			n := numDiffs(image[lower], image[upper])
 | 
					 | 
				
			||||||
			log.Debug(n, " difference(s) found at line ", lower)
 | 
					 | 
				
			||||||
			diffs += n
 | 
					 | 
				
			||||||
			lower--
 | 
					 | 
				
			||||||
			upper++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		lower++
 | 
					 | 
				
			||||||
		return diffs == 1
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i := 0; i < len(image)-1; i++ {
 | 
					 | 
				
			||||||
		log.Debug("start point: ", image[i], " vs ", image[i+1])
 | 
					 | 
				
			||||||
		if walkToEdge(i, i+1) {
 | 
					 | 
				
			||||||
			return i, true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0, false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// two returns a calculation based on reflection points for all images with one smudge
 | 
					 | 
				
			||||||
func two(lines []string) int {
 | 
					 | 
				
			||||||
	sum := 0
 | 
					 | 
				
			||||||
	for _, image := range images.img {
 | 
					 | 
				
			||||||
		log.Debug("checking for horizontal reflection")
 | 
					 | 
				
			||||||
		n, ok := horizontalReflection(image, findReflectionWithDifference)
 | 
					 | 
				
			||||||
		if ok {
 | 
					 | 
				
			||||||
			sum += 100 * (n + 1)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		log.Debug("checking for vertical reflection")
 | 
					 | 
				
			||||||
		n, ok = verticalReflection(image, findReflectionWithDifference)
 | 
					 | 
				
			||||||
		if ok {
 | 
					 | 
				
			||||||
			sum += (n + 1)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sum
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,57 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bufio"
 | 
					 | 
				
			||||||
	"log"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// readlines reads lines from stdin.
 | 
					 | 
				
			||||||
// it returns them as an array of strings
 | 
					 | 
				
			||||||
func readlines() []string {
 | 
					 | 
				
			||||||
	lines := []string{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	scanner := bufio.NewScanner(os.Stdin)
 | 
					 | 
				
			||||||
	for scanner.Scan() {
 | 
					 | 
				
			||||||
		lines = append(lines, scanner.Text())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := scanner.Err(); err != nil {
 | 
					 | 
				
			||||||
		log.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return lines
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// parselines stores each image into an images struct
 | 
					 | 
				
			||||||
func parselines(lines []string) {
 | 
					 | 
				
			||||||
	addImage := func(i int) int {
 | 
					 | 
				
			||||||
		image := newImg()
 | 
					 | 
				
			||||||
		for ; i < len(lines); i++ {
 | 
					 | 
				
			||||||
			if len(lines[i]) == 0 {
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			image.raw = append(image.raw, lines[i])
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		images.img = append(images.img, image)
 | 
					 | 
				
			||||||
		return i
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	images = newImages()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i := 0; i < len(lines); i++ {
 | 
					 | 
				
			||||||
		next := addImage(i)
 | 
					 | 
				
			||||||
		i = next
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// numDiffs returns the number of difference between two strings
 | 
					 | 
				
			||||||
func numDiffs(a, b string) int {
 | 
					 | 
				
			||||||
	diff := 0
 | 
					 | 
				
			||||||
	for i := range a {
 | 
					 | 
				
			||||||
		if a[i] != b[i] {
 | 
					 | 
				
			||||||
			diff++
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return diff
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user