背包重组
Question
我们要进入丛林!我们让Legolas负责打包我们的旅程,但他的包装能力似乎不像他的弓箭技巧,他有点痛苦地包装...
但是,我们确实有每个背包中项目的清单,列表看起来如下
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
每行代表一个背包,该行的每一半代表背包中的一个隔间。
物品可以通过其字符来识别,是的,“ a”和“ a”不是相同的项目。
例如
第一个背包包含vJrwpWtwJgWrhcsFMMfFFhFp
的项目,这意味着其第一个隔间包含vJrwpWtwJgWr
的项目,而第二个隔间包含hcsFMMfFFhFp
的项目。两个隔间中出现的唯一项目类型是小写p。
为了帮助优先考虑项目重排,每个项目类型都可以转换为优先级:
小写的项目A类型A到Z具有优先级1至26。
大写项目A类型A至Z具有优先级27至52。
在上面的示例中,每个背包的两个隔室中出现的项目类型的优先级为16(p),38(l),42(p),22(v),20(t)和19(s);这些的总和是157。
第1部分
在第一部分中,我们的任务是总结两个隔间中出现的项目的优先级
让我们从分析我们的输入
开始解析
理想情况下,我们想拥有一个包含元组的阵列,每个套件都有一个半
例如vJrwpWtwJgWrhcsFMMfFFhFp -> [ [set(vJrwpWtwJgWr), set(hcsFMMfFFhFp)]... ]
我们在这里选择一个ds,以便能够轻松回答“集合y中的字母x?”后来
// go doesn't have a built in Set DS so we need to roll our own here
func makeSet(chars string) map[rune]bool {
set := map[rune]bool{}
for _, c := range chars {
set[c] = true
}
return set
}
func parse() [][]map[rune]bool {
data, _ := os.ReadFile("./input.txt")
lines := strings.Split(string(data), "\n")
rucksacks := [][]map[rune]bool{}
for _, line := range lines {
c1 := makeSet(line[:len(line)/2])
c2 := makeSet(line[len(line)/2:])
w := []map[rune]bool{c1, c2}
rucksacks = append(rucksacks, w)
}
return rucksacks
}
有趣的是,我们将每个字符作为rune,这是所述char的ASCII值
我们使用
:
将线切成两个部分,line[x:]
表示从x
切成薄片直至结束,而lines[:x]
表示从数组的开头开始直到x
解决方案
现在我们已经完成了数据,我们可以编写以下代码来计算每个char的优先级
func calcPriority(c rune) int {
if c >= 'a' && c <= 'z' {
return int(c) - 'a' + 1
} else {
return int(c) - 'A' + 27
}
}
基本上,我们正在乘符文,扣除基本值,例如'a'或'a',并添加了从1到26的问题,含义从1到26,大写从27到52
如果我在比较中使用双引号,则此代码将无法使用
好吧,我们都准备好现在,让我们解决第1部分
我们将在所有背包上进行迭代,并且每个人都会找到第一个隔间和第二个隔间中的字母。
当我们找到一个时,我们将其传递给我们的钙化函数并积累其值
func pt1() int {
groups := parse()
sum := 0
for _, group := range groups {
s1 := group[0] // first compartment
s2 := group[1] // second compartment
for k, _ := range s1 {
if s2[k] {
sum += calcPriority(k)
}
}
}
return sum
}
酷酷酷,我们都完成了第1部分的完成,让我们看看第2部分为我们提供了什么
第2部分
我们不是要找到组徽章的优先级的任务,而是将徽章定义为连续3个Rucksacks中包含的item
从上面的示例输入中,我们可以绘制以下示例
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
,第二组的背包是接下来的三行:
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
在第一组中,所有三个背包中出现的唯一项目类型是小写kude11;这一定是他们的徽章。在第二组中,他们的徽章项目类型必须为Z
。
仍然必须找到这些项目的优先级来组织贴纸的依恋工作:在这里,第一组为18(r),第二组为52(z)。这些总和是70。
我们需要对我们的解析代码进行一些调整以一次创建3行的集合,这看起来像
func chunkInto(s []string, size int) [][]string {
results := [][]string{}
for i := 0; i < len(s); i += size {
results = append(results, s[i:i+size])
}
return results
}
func parse2() [][]map[rune]bool {
data, _ := os.ReadFile("./input.txt")
rows := strings.Split(string(data), "\n")
groups := chunkInto(rows, 3)
rucksacks := [][]map[rune]bool{}
for _, chunk := range groups {
w := []map[rune]bool{}
for _, c := range chunk {
w = append(w, makeSet(c))
}
rucksacks = append(rucksacks, w)
}
return rucksacks
}
我们现在可以与第1部分相似地解决第2部分
func pt2() int {
groups := parse2()
sum := 0
for _, group := range groups {
s1 := group[0]
s2 := group[1]
s3 := group[2]
for k, _ := range s1 {
if s2[k] && s3[k] {
sum += calcPriority(k)
}
}
}
return sum
}
就是这样,今天男孩和女孩,我希望您能像我到目前为止一样享受AOC
您可以找到完整的代码here
感谢您的阅读!