1
0
Fork 0
mirror of https://github.com/Luzifer/aoc2019.git synced 2024-10-18 03:04:19 +00:00
aoc2019/day04.go
Knut Ahlers 588a27e37d
Add solution for Day 4
Signed-off-by: Knut Ahlers <knut@ahlers.me>
2019-12-04 15:13:58 +01:00

123 lines
2.3 KiB
Go

package aoc2019
import (
"io/ioutil"
"strconv"
"strings"
"github.com/pkg/errors"
)
func day4NumberToDigitSlice(n int64) []int {
var out []int
sn := strconv.FormatInt(n, 10)
for _, c := range sn {
d, err := strconv.Atoi(string(c))
if err != nil {
// This should not happen as the input is a guaranteed base-10 number
panic(err)
}
out = append(out, d)
}
return out
}
func day4IsValidPassword(n, min, max int64) bool {
sn := day4NumberToDigitSlice(n)
// It is a six-digit number.
if len(sn) != 6 {
return false
}
// The value is within the range given in your puzzle input.
if n < min || n > max {
return false
}
// Two adjacent digits are the same (like 22 in 122345).
var foundAdjacentMatch bool
for i := 1; i < len(sn); i++ {
if sn[i] == sn[i-1] {
foundAdjacentMatch = true
}
}
if !foundAdjacentMatch {
return false
}
// Going from left to right, the digits never decrease; they only ever increase or stay the same (like 111123 or 135679).
for i := 1; i < len(sn); i++ {
if sn[i] < sn[i-1] {
return false
}
}
return true
}
func day4IsValidPasswordPart2(in, min, max int64) bool {
// Previous rules still apply
if !day4IsValidPassword(in, min, max) {
return false
}
sn := day4NumberToDigitSlice(in)
var (
last = sn[0]
count = 1
)
for i := 1; i < len(sn); i++ {
if sn[i] != last && count == 2 {
return true
}
if sn[i] == last {
count++
continue
}
last = sn[i]
count = 1
}
return count == 2
}
func solveDay4WithFunction(inFile string, vf func(int64, int64, int64) bool) (int, error) {
raw, err := ioutil.ReadFile(inFile)
if err != nil {
return 0, errors.Wrap(err, "Unable to read input file")
}
pts := strings.Split(strings.TrimSpace(string(raw)), "-")
min, err := strconv.ParseInt(pts[0], 10, 64)
if err != nil {
return 0, errors.Wrap(err, "Unable to parse minimum")
}
max, err := strconv.ParseInt(pts[1], 10, 64)
if err != nil {
return 0, errors.Wrap(err, "Unable to parse maximum")
}
var count int
for i := min; i <= max; i++ {
if vf(i, min, max) {
count++
}
}
return count, nil
}
func solveDay4Part1(inFile string) (int, error) {
return solveDay4WithFunction(inFile, day4IsValidPassword)
}
func solveDay4Part2(inFile string) (int, error) {
return solveDay4WithFunction(inFile, day4IsValidPasswordPart2)
}