Created
December 3, 2022 21:56
-
-
Save Roemerb/14bfd3424b34b1c3936ab8a37ead8c9b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package day3 | |
import ( | |
"bufio" | |
"errors" | |
"fmt" | |
"log" | |
"os" | |
) | |
var RucksackContents [][]byte | |
func Run() { | |
readRucksackContents("./day3/3.txt") | |
fmt.Println("Total dupe score: ", getTotalDupeScore(RucksackContents)) | |
// Part 2 | |
splitScore := 0 | |
split := splitRucksacksInGroups(RucksackContents, 3) | |
for groupNr, group := range split { | |
fmt.Println("Group ", groupNr) | |
fmt.Print("\t") | |
for _, rucksack := range group { | |
fmt.Print(string(rucksack), ", ") | |
} | |
commonItem := findCommonItemInRucksackGroup(group) | |
commonItemScore, _ := getItemPriorityScore(commonItem) | |
splitScore += commonItemScore | |
fmt.Print(" have in common: ", commonItem, " (", string(commonItem), ") score: ", commonItemScore) | |
fmt.Print("\n") | |
} | |
fmt.Println("The total priority score for the split rucksacks is", splitScore) | |
} | |
func ReadInputToFile(path string) *os.File { | |
content, err := os.Open(path) | |
if err != nil { | |
log.Fatal("Cannot read input: ", err) | |
} | |
return content | |
} | |
func readRucksackContents(path string) { | |
content := ReadInputToFile(path) | |
scanner := bufio.NewScanner(content) | |
scanner.Split(bufio.ScanLines) | |
for scanner.Scan() { | |
str := scanner.Text() | |
RucksackContents = append(RucksackContents, []byte(str)) | |
} | |
} | |
func findDuplicatesInRucksack(rucksack []byte) []byte { | |
var halfSize int = (len(rucksack) / 2) | |
firstHalf := rucksack[0:halfSize] | |
secondHalf := rucksack[halfSize:] | |
// Find the unique characters in the first half | |
uniqChars := make(map[byte]bool) | |
for _, char := range firstHalf { | |
// Ignore line-break chars | |
if char == 10 { | |
continue | |
} | |
if !uniqChars[char] { | |
uniqChars[char] = true | |
} | |
} | |
// Find which of the unique chars also exists in the second half | |
dupes := make(map[byte]bool) | |
for _, char := range secondHalf { | |
if uniqChars[char] { | |
if !dupes[char] { | |
dupes[char] = true | |
} | |
} | |
} | |
var dupeChars []byte | |
for char, _ := range dupes { | |
dupeChars = append(dupeChars, char) | |
} | |
return dupeChars | |
} | |
// getItemPriorityScore translates a byte into the appropriate | |
// score for that item. | |
// | |
// a-z have scores 1-26 | |
// A-Z have scores 27-52 | |
// | |
// However, the byte value for these characters is actually the | |
// opposite way around so the scores for uppercase and lowercase | |
// items must be calculated differently. | |
func getItemPriorityScore(item byte) (int, error) { | |
if item >= 97 && item <= 122 { | |
return int(item) % 96, nil | |
} else if item >= 65 && item <= 90 { | |
return (int(item) % 64) + 26, nil | |
} | |
return -1, errors.New("item is invalid") | |
} | |
func getDupeScoreForRucksack(rucksack []byte) int { | |
var score int = 0 | |
dupes := findDuplicatesInRucksack(rucksack) | |
for _, dupe := range dupes { | |
itemScore, err := getItemPriorityScore(dupe) | |
if err != nil { | |
log.Fatal(err) | |
} | |
score += itemScore | |
} | |
return score | |
} | |
func getTotalDupeScore(rucksacks [][]byte) int { | |
var totalScore int = 0 | |
for _, rucksack := range rucksacks { | |
totalScore += getDupeScoreForRucksack(rucksack) | |
} | |
return totalScore | |
} | |
func splitRucksacksInGroups(rucksacks [][]byte, groupSize int) map[int][][]byte { | |
nGroups := len(rucksacks) / groupSize | |
groups := make(map[int][][]byte) | |
for i := 0; i < nGroups; i++ { | |
groups[i] = rucksacks[i*groupSize : i*groupSize+groupSize] | |
} | |
return groups | |
} | |
func findCommonItemInRucksackGroup(rucksackGroup [][]byte) byte { | |
for _, c := range rucksackGroup[0] { | |
if arrContains(rucksackGroup[1], c) && arrContains(rucksackGroup[2], c) { | |
return c | |
} | |
} | |
return 0 | |
} | |
func arrContains(arr []byte, s byte) bool { | |
for _, c := range arr { | |
if c == s { | |
return true | |
} | |
} | |
return false | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment