AOC第4天 - 营地清理
#编程 #教程 #go #adventofcode

营地清理

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节)。
  • 第二对中的精灵分别分配了两个部分。

一如既往,让我们从将我们的作业列表解析为可以使用

的事物列表

解析

首先,让我们决定要输出的样子。
我们可以创建一个代表每个对任务的结构,但这似乎有点冗余,让我们保持简单并创建类似
[[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
感谢您的阅读!