Skip to content

Commit

Permalink
Day 5: part 1 - refactor and simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
dmytro-spivakov committed Oct 11, 2024
1 parent 7ef0265 commit 736783e
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 80 deletions.
129 changes: 50 additions & 79 deletions day05/day05.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,110 +132,81 @@ func Solution1(filepath string) int {
log.Fatalf("Failed to open the input file %v\n", filepath)
}

processingOrder := []string{
"soil",
"fertilizer",
"water",
"light",
"temperature",
"humidity",
"location",
// read seeds, handle the first two lines as an edge-case outside the main reading loop
var mappedInputs []int
scanner := bufio.NewScanner(file)
scanner.Scan()
seedRegex := regexp.MustCompile(`\d+`)
for _, seed := range seedRegex.FindAllString(scanner.Text(), -1) {
mappedInputs = append(mappedInputs, parseInt(seed))
}

processStepToHeader := map[string]string{
"soil": "seed-to-soil map:",
"fertilizer": "soil-to-fertilizer map:",
"water": "fertilizer-to-water map:",
"light": "water-to-light map:",
"temperature": "light-to-temperature map:",
"humidity": "temperature-to-humidity map:",
"location": "humidity-to-location map:",
scanner.Scan()
if scanner.Err() != nil {
log.Fatalf("Error during input file read: %v\n", scanner.Err().Error())
}
var seeds []int
processStepToRange := make(map[string][]Range)

rangeRegex := regexp.MustCompile(`(\d+)\s+(\d+)\s+(\d+)`)
seedRegex := regexp.MustCompile(`\d+`)
currentContext := ""
scanner := bufio.NewScanner(file)
var currentMappingSection []string
for scanner.Scan() {
currentLine := scanner.Text()

// sections are separated by a blank line
if len(currentLine) == 0 {
currentContext = ""
// sections are ordered -> don't need to care about parsing headers
if strings.Contains(currentLine, "map:") {
continue
}

if strings.Contains(currentLine, "seeds:") {
for _, seed := range seedRegex.FindAllString(currentLine, -1) {
seeds = append(seeds, parseInt(seed))
}
continue
}
if len(currentLine) == 0 {
mappedInputs = applySectionMapping(currentMappingSection, mappedInputs)
currentMappingSection = nil

contextChanged := false
for step, header := range processStepToHeader {
if strings.Contains(currentLine, header) {
currentContext = step
contextChanged = true
break
}
}
if contextChanged {
continue
}

rangeNumbers := rangeRegex.FindStringSubmatch(currentLine)
if rangeNumCount := len(rangeNumbers); rangeNumCount > 0 && rangeNumCount != 4 {
log.Fatalf("Failed to parse range row %v\n", rangeNumbers)
currentMappingSection = append(currentMappingSection, currentLine)
}
// last section edge-case, there's no trailing empty line to trigger mapping
mappedInputs = applySectionMapping(currentMappingSection, mappedInputs)

result := mappedInputs[0]
for _, mappedInput := range mappedInputs {
if mappedInput < result {
result = mappedInput
}
}
return result
}

processStepToRange[currentContext] = append(
processStepToRange[currentContext],
func applySectionMapping(sectionLines []string, inputs []int) (mappedInputs []int) {
rangeRegex := regexp.MustCompile(`(\d+)\s+(\d+)\s+(\d+)`)

var mappingRanges []Range
for _, sectionLine := range sectionLines {
matches := rangeRegex.FindStringSubmatch(sectionLine)

mappingRanges = append(
mappingRanges,
Range{
destStart: parseInt(rangeNumbers[1]),
srcStart: parseInt(rangeNumbers[2]),
length: parseInt(rangeNumbers[3]),
destStart: parseInt(matches[1]),
srcStart: parseInt(matches[2]),
length: parseInt(matches[3]),
},
)
}
if scanner.Err() != nil {
log.Fatalf("Error during input file read: %v\n", scanner.Err().Error())
}

mappingInput := seeds
var outputs []int
for _, step := range processingOrder {
outputs = nil

for _, input := range mappingInput {
found := false
for _, rangeStr := range processStepToRange[step] {
if mappedValue := rangeStr.findDest(input); mappedValue >= 0 {
outputs = append(outputs, mappedValue)
found = true
break
}
}

if !found {
outputs = append(outputs, input)
for _, input := range inputs {
found := false
for _, rangeStr := range mappingRanges {
if mappedInput := rangeStr.findDest(input); mappedInput >= 0 {
mappedInputs = append(mappedInputs, mappedInput)
found = true
break
}
}

mappingInput = make([]int, len(outputs))
copy(mappingInput, outputs)
}

result := outputs[0]
for _, output := range outputs {
if output < result {
result = output
if !found {
mappedInputs = append(mappedInputs, input)
}
}

return result
return mappedInputs
}

func parseInt(numStr string) int {
Expand Down
22 changes: 21 additions & 1 deletion day05/day05_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

func TestSolution1(t *testing.T) {
cases := map[string]int{
"test_input11": 35,
"test_input11": 3,
}

for inputFile, expectedResult := range cases {
Expand All @@ -19,3 +19,23 @@ func TestSolution1(t *testing.T) {
}
}
}

func TestRangeFindDest(t *testing.T) {
rangeStr := Range{srcStart: 10, destStart: 20, length: 10}
cases := map[int]int{
10: 20,
20: 30,
15: 25,
9: -1,
31: -1,
}

for srcStart, expectedDest := range cases {
result := rangeStr.findDest(srcStart)
if result != expectedDest {
t.Fatalf("Range.findDest() = %d, expecting %d\n", result, expectedDest)
} else {
fmt.Printf("Range.findDest() = %d, OK\n", result)
}
}
}
1 change: 1 addition & 0 deletions day05/test_input11
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ temperature-to-humidity map:
humidity-to-location map:
60 56 37
56 93 4
3 35 1

0 comments on commit 736783e

Please sign in to comment.