Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package day5
- import (
- "bufio"
- "fmt"
- "os"
- "strconv"
- "strings"
- )
- const path = "day5/input.txt"
- const testpath = "day5/test.txt"
- type mapping []submapping
- type submapping struct {
- source, size, offset int
- }
- // Range represents a range with a start and length
- type Range struct {
- Start int
- End int
- }
- func Run() {
- // Open the file
- file, err := os.Open(path)
- if err != nil {
- fmt.Println("Error opening file:", err)
- return
- }
- defer file.Close()
- // Create a scanner to read the file
- scanner := bufio.NewScanner(file)
- var seeds []int
- var mappings []mapping
- currentMap := mapping{}
- // Iterate through each line
- for scanner.Scan() {
- line := scanner.Text()
- // Skip empty lines
- if line == "" {
- continue
- }
- if strings.Contains(line, "seeds: ") {
- seedsString := strings.Split(line, "seeds: ")
- seedList := strings.Split(seedsString[1], " ")
- for _, seedItem := range seedList {
- seeds = append(seeds, StringToInt(seedItem))
- }
- continue
- }
- if strings.Contains(line, "-") {
- // Current map was not empty so we have to start over for the new mappings
- if len(currentMap) > 0 {
- mappings = append(mappings, currentMap)
- }
- currentMap = mapping{}
- continue
- }
- values := strings.Split(line, " ")
- currentMap = append(currentMap, submapping{
- source: StringToInt(values[1]),
- size: StringToInt(values[2]),
- offset: StringToInt(values[0]) - StringToInt(values[1]),
- })
- }
- // Add the current map when reaching the end of file
- if len(currentMap) > 0 {
- mappings = append(mappings, currentMap)
- }
- // Check for scanner errors
- if err := scanner.Err(); err != nil {
- fmt.Println("Error reading file:", err)
- }
- lowest := int(^uint(0) >> 1) // Initialize to the maximum positive int value
- for _, seed := range seeds {
- val := seed
- for _, mapping := range mappings {
- for _, submapping := range mapping {
- if val >= submapping.source && val <= submapping.source+submapping.size {
- val += submapping.offset
- break
- }
- }
- }
- lowest = min(val, lowest)
- }
- fmt.Println("Part 1 - Lowest location is", lowest)
- var ranges []Range
- for i := 0; i < len(seeds); i += 2 {
- rangeStart := seeds[i]
- rangeLength := seeds[i+1]
- ranges = append(ranges, Range{Start: rangeStart, End: rangeStart + rangeLength - 1})
- }
- fmt.Println(ranges)
- // Do a reverse lookup, start from location = 0 and find if we have the seed, keep going until the first seed
- var lowestReverse int
- for location := 0; location >= 0; {
- val := location
- for i := len(mappings) - 1; i >= 0; i-- {
- mapping := mappings[i]
- for _, submapping := range mapping {
- if val-submapping.offset >= submapping.source && val-submapping.offset <= submapping.source+submapping.size {
- val -= submapping.offset
- break
- }
- }
- }
- for _, r := range ranges {
- if r.InRange(val) {
- lowestReverse = location
- fmt.Println(location)
- break
- }
- }
- // If val is in one of the ranges break and print val, also assign lowest to current location iteration
- if lowestReverse > 0 {
- break
- }
- location += 1
- }
- fmt.Println("Part 2 - Lowest location of any of the initial seeds is", lowestReverse)
- }
- func StringToInt(s string) int {
- i, err := strconv.Atoi(s)
- if err != nil {
- panic(err.Error())
- }
- return i
- }
- // InRange checks if a number is in the given range
- func (r Range) InRange(num int) bool {
- return num >= r.Start && num <= r.End
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement