营地清理
Question
似乎这次我们的任务是优化精灵的清洁任务!这些精灵可以改善他们的清单...
清洁任务分配给每对精灵,例如:
2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8
对于前几对,此列表意味着:
- 在第一对精灵中,第一个小精灵被分配了第2-4节(第2、3和4节),而第二精灵则分配了第6-8节(第6、7、8节)。 li>
- 第二对中的精灵分别分配了两个部分。
一如既往,让我们从将我们的作业列表解析为可以使用
的事物列表解析
首先,让我们决定要输出的样子。
我们可以创建一个代表每个对任务的结构,但这似乎有点冗余,让我们保持简单并创建类似
[[st1, et1, st2, et2] , ... ]
其中st1和et1是第一个小精灵范围,而st2和et2是第二精灵范围。
从现在开始,我们将一系列部分称为“任务”。
要知道我们可以在各种定界符上分手,但是今天我终于有一个借口在GO中使用Regex。
我们将创建一个正则义务,为每个t
包含capture groups并使用
FindStringSubmatch迭代由此产生的比赛。
func parse(raw string) [][]int {
lines := strings.Split(string(raw), "\n")
pairs := [][]int{}
r := regexp.MustCompile(`(\d+)-(\d+),(\d+)-(\d+)`)
for _, l := range lines {
match := r.FindStringSubmatch(l)
pair := []int{}
for _, m := range match[1:] {
num, _ := strconv.Atoi(m)
pair = append(pair, int(num))
}
pairs = append(pairs, pair)
}
return pairs
}
值得注意的是,第一匹匹配是我们正在传递的整个字符串,这就是为什么我们在循环循环的
上跳过它的原因range match[1:]
第1部分
精灵真的很聪明,注意到某些任务完全与他们的伴侣任务重叠。
我们的任务是查找和计算这些重叠。
让我们绘制出来,以便更清楚
.234..... 2-4 // no overlapping
.....678. 6-8
.23...... 2-3 // no overlapping
...45.... 4-5
....567.. 5-7 // just a partial overlapping NOT GOOD ENOUGH
......789 7-9
.2345678. 2-8
..34567.. 3-7 // contained in 2-8
.....6... 6-6 // contained in 4-6
...456... 4-6
.23456... 2-6 // again, partial overlapping
...45678. 4-8
从上面的角度来看,如果精灵的起始任务之一更大或等于另一个小精灵的启动任务,并且最终任务较小或相等,则包含分配。
我们现在为第1部分编写解决方案
func part1(raw []byte) int {
var assignments = parse(string(raw))
count := 0
for _, pairAssignmentRange := range assignments {
st1 := pairAssignmentRange[0]
et1 := pairAssignmentRange[1]
st2 := pairAssignmentRange[2]
et2 := pairAssignmentRange[3]
if (st1 >= st2 && et1 <= et2) || (st2 >= st1 && et2 <= et1) {
count++
}
}
return count
}
如果您知道一种更好的方法来从
pairAssignmentRange
中获取这些价值3,请在评论部分中告知我第2部分
我们被要求计算任何类型的重叠任务,这意味着我们将在我们的范围内拥有一个重叠的“部分”,以便将其算作重叠
这在代码中是什么意思?这意味着我们正在寻找在另一个任务范围内结束的任务。
例如
....567.. 5-7
......789 7-9
这些任务与“第7节”重叠。
现在,我们可以按以下方式编写第2部分解决方案
func part2(raw []byte) int {
var assignments = parse(string(raw))
count := 0
for _, pairAssignmentRange := range assignments {
st1 := pairAssignmentRange[0]
et1 := pairAssignmentRange[1]
st2 := pairAssignmentRange[2]
et2 := pairAssignmentRange[3]
if (et1 >= st2 && et1 <= et2) || (et2 >= st1 && et2 <= et1) {
count++
}
}
return count
}
我们唯一更改的是if
语句,以查看结尾任务“部分”
总结一下事情,每天我对GO感到越来越自信,任务的代码开始流动。
我认为Go的一个优势之一是,该语言相当小,没有任何精美的概念,因此学习曲线并不长或难。
您可以找到完整的代码here
感谢您的阅读!