diff options
Diffstat (limited to 'day7/main.go')
-rw-r--r-- | day7/main.go | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/day7/main.go b/day7/main.go new file mode 100644 index 0000000..fd20d4f --- /dev/null +++ b/day7/main.go @@ -0,0 +1,111 @@ +package main + +import ( + "bufio" + "fmt" + "math" + "os" + "strconv" + "strings" +) + +func main() { + fmt.Println(part1(readData("example.txt"))) + fmt.Println(part1(readData("data.txt"))) + fmt.Println(part2(readData("example.txt"))) + fmt.Println(part2(readData("data.txt"))) +} + +type Case struct { + target int64 + operands []int64 +} + +func part1(cases []Case) (sumOk int64) { + for _, c := range cases { + if canReach(c.target, 0, c.operands) { + sumOk += c.target + } + } + return +} + +func part2(cases []Case) (sumOk int64) { + for _, c := range cases { + if canReach2(c.target, 0, c.operands) { + sumOk += c.target + } + } + return +} + +func concatenate(a int64, b int64) int64 { + bDecimalLength := len(strconv.FormatInt(b, 10)) + return a*int64(math.Pow(10, float64(bDecimalLength))) + b +} + +func canReach(target int64, currentTotal int64, operands []int64) bool { + if len(operands) == 0 { + return target == currentTotal + } + + if currentTotal > target { + return false + } + + return canReach(target, currentTotal+operands[0], operands[1:]) || + canReach(target, currentTotal*operands[0], operands[1:]) +} + +func canReach2(target int64, currentTotal int64, operands []int64) bool { + if len(operands) == 0 { + return target == currentTotal + } + + if currentTotal > target { + return false + } + + return canReach2(target, currentTotal+operands[0], operands[1:]) || + canReach2(target, currentTotal*operands[0], operands[1:]) || + canReach2(target, concatenate(currentTotal, operands[0]), operands[1:]) +} + +func readData(fileName string) (cases []Case) { + fp, err := os.Open(fileName) + if err != nil { + panic(err) + } + + scanner := bufio.NewScanner(fp) + + for scanner.Scan() { + line := scanner.Text() + splitColon := strings.Split(line, ":") + + if len(splitColon) != 2 { + panic("Not enough data") + } + + target, err := strconv.ParseInt(splitColon[0], 10, 64) + if err != nil { + panic(err) + } + + operandsStr := strings.Split(strings.TrimSpace(splitColon[1]), " ") + operands := make([]int64, len(operandsStr)) + + for i, s := range operandsStr { + n, err := strconv.ParseInt(s, 10, 64) + if err != nil { + panic(err) + } + + operands[i] = n + } + + cases = append(cases, Case{target, operands}) + } + + return +} |