搜索
首页后端开发GolangCode n Golang 的出现:做或不做正则表达式

受到 Shradha Agarwal 在 Byte Size Go 上的帖子的启发:这里:我决定写下我的方法,它是不同的,并且想分享它。那篇文章写得很好,解决方案紧凑而简单,我建议也先阅读该文章。

这是一个 blogvent 系列,我也很想参加 blogvent,但不确定我是否会完成这个。

介绍

嗯,现在是 Code 2024 出现的第三天,我一直在直播。我落后了两天,但正在一一解决。到目前为止,我已经在 Go 中学到了很多东西。让我们开始第三天的生活吧。

第 1 部分

任何 AOC 问题的第一部分似乎都很简单,但是一旦第二部分被揭示,真正的实现就开始令人费解(如果你不乐观或不深思熟虑的话)

今天的第 1 部分是解析一个包含 mul(X,Y) 表达式的字符串,其中 X 可以是任何 3 位数字。因此,字符串中可能有多个这样的表达式,目的是将单个表达式中的 X 和 Y 相乘并将它们相加。

Advent of Code n Golang: Do or Don

xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))

在上面的例子中,有 4 个这样的表达式,如果我们将它们相乘,我们得到的答案是 161。

方法

它看起来像正则表达式模式,在字符串中查找类似表达式的模式。因此,方法是使用正则表达式模式找到此类表达式,并将数字解析为整数,然后将它们相乘,简单地。

您可以继续编写解析器来迭代字符串中的每个字符并解析标记,然后评估表达式。这是一种有效的方法,但我选择这样做是因为我不知道如何诚实地编写解析器,我也想在最后尝试该解决方案。

但对于第一部分,快速正则表达式似乎是个好主意。

构建正则表达式

第一件事是编写 mul(X,Y) 部分的正则表达式,这是第一部分中唯一具有挑战性的部分。剩下的只是简单的数学。

所以,我们需要找到 mul,然后找到 a(然后找到任意 1 到 3 位数字长的数字,然后再找到 1 到 3 位数字长的数字,最后以 a 结尾)

翻译为:

mul\((\d{1,3}),(\d{1,3})\) 

让我们细分一下:

  • mul 用于捕获字面词 mul

  • (这是表达式 mul() 中的第一个括号,如果我们想匹配它,我们需要在正则表达式中转义括号,所以我们在它之前使用。

  • 然后我们有一个匹配组 (d{1,3}) ,这将是 mul(X,Y) 中的 X:

    • 匹配组就像正则表达式中的一组匹配,基本上,如果你想捕获整个匹配中的特定部分,那么我们使用 () 将它们单独分组,这不是必需的,但有助于获得正确的事情,没有开销
    • 在本例中,我们使用匹配组来捕获 1 到 3 位数字的数字。
    • 另一种写法是 ([0-9]{1,3}) ,它也会做同样的事情,(注意: [0-9] 和 d 有一些区别,但那就是非常微妙,不会影响这个谜题,如果你仍然好奇,我更喜欢阅读这个 StackOverflow 问题)
  • 然后我们使用 , 作为 mul(X,Y) 表达式中 X 和 Y 操作数的分隔符

  • 然后我们以类似的方式将 mul(X,Y) 中的 Y 与 (d{1,3}) 匹配组进行匹配

  • 最后我们用 ) 来结束正则表达式

编码它

这非常简单,我们将行作为字符串获取,并使用 regexp.MustCompile 函数,它为我们提供了一个 Regexp 对象,该对象又具有一些与之关联的方法来查找、匹配、替换和其他可以执行的操作使用字符串上的正则表达式来完成。

一旦我们有了 mulRegex ,我们就可以使用与 regexp 包中的 Regexp 结构关联的 FindAllStringSubmatch 方法。该函数接受一个字符串来执行正则表达式,以及要返回的最大匹配数。我们想要所有结果,因此我们将它们传入 -1 以获得所有匹配项。

现在,此方法返回字符串切片的切片,每个切片都是一个匹配项,每个切片内都有一个字符串切片,其中包含匹配的字符串以及字符串中的后续匹配组(如果有)。

xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))

所以,上面的函数将返回类似这样的内容

mul\((\d{1,3}),(\d{1,3})\) 

这是一个字符串列表,这些看起来像数字,但它们是 Golang 中的字符串类型。

现在我们有了这个,我们可以创建获取结果的实际逻辑部分,即解析这些表达式,将 X 和 Y 相乘并将每个表达式的结果相加。

func FindMulExpression(line string) [][]string {
  mulRegex := regexp.MustCompile(`mul\((\d{1,3}),(\d{1,3})\)`)
  return mulRegex.FindAllStringSubmatch(line, len(line))
}

这非常简单,我们迭代每个匹配项,即一个 mul(X,Y) 表达式,并将 X 和 Y 分别解析为整数并相乘,然后将获得的结果添加到分数中。我们对字符串(行)中找到的每个 mul(X,Y) 表达式执行此操作并返回最终分数。

输入

现在,示例给了我们一个字符串,但我意识到输入中有六行(单独输入),因此我们需要解析每一行并将分数相加。

请记住这一点,因为它在第 2 部分中至关重要,我花了一些时间并质疑我的存在,才意识到我们需要组合所有行才能获得结果(在第 1 部分中不是必需的,但在第 2 部分中肯定是这样)。

第2部分

这通常是出问题的地方。至少对我来说是这样。

我从一个非常幼稚的方法开始,使用永远循环并找到“做”或“不做”的索引并剥离这些部分,然后循环直到我们没有剩下“做”和“不做”。这对测试用例有效,但在实际输入上失败了。

我最终想出的方法,并通过稍微调整相同的方法来发挥作用。

方法

我想到的是在整个字符串中找到 don’() 和 do() 字符串的第一个匹配位置,我们将其删除并删除 don’t() 之后或 do() 之前的部分。这样我们就可以将字符串修剪为仅有效/启用的 mul() 表达式。

Advent of Code n Golang: Do or Don

因此,更明确定义的方法将是:

  • 查找 dont() 和 do() 表达式的位置(索引)

  • 我们需要跟踪前一个字符串是启用还是禁用,因此将保留一个标志以将启用的表达式(字符串的一部分)附加到最终结果

  • 如果没有找到,则按原样返回字符串(行)

  • 如果我们找到其中任何一个:

    • 如果我们首先发现don't(dont()出现在do()之前)

      • 如果启用标志为 true → 将字符串附加到 dont() 表达式之前
      • 然后将启用切换为 false 并修剪掉 don't() 部分 (这样我们就完成了 don't 表达式之前的所有检查,因此我们从行字符串中删除该部分)
    • 如果我们发现do先出现(do()出现在dont()之前)

      • 如果启用标志为 true → 将字符串附加到 do() 表达式之前
      • 然后将启用切换为true并修剪掉do()部分 (这样我们就完成了 do 表达式之前的所有检查,因此我们从行字符串中删除了这部分)
  • 我们这样做,直到没有剩余的线串需要检查

代码

我使用简单的 Strings.Index 来获取子字符串的第一个匹配索引,在本例中,我想要 dont() 和 do() 的第一个匹配索引。一旦我们有了两个匹配项的索引,我们就可以迭代,直到字符串中不再有任何该做或不该做的事情。

如果我们有 do 或 don ,我们会在字符串中附加 do not 之前的部分(如果启用)或在 do 之前的部分(如果启用),并相应地打开和关闭启用标志。在循环结束时,结果字符串将仅包含行/字符串的启用部分。

xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))

我将这个函数传递给乘法函数,在其中我获取 mul 表达式的匹配模式并进行数学计算。

strings.Index 方法接受一个字符串和一个要在该字符串中查找的子字符串,并返回该子字符串第一个出现的实例的索引。这样我们就可以识别行字符串是否包含 do() 或 dont() 表达式,如果不包含,我们只需返回该行,如果存在它们的实例,我们循环并修剪该行之前和之后的字符串。表达式取决于该标志是启用还是禁用。

让我们举个例子并演练一下逻辑:

xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))

在将结果传递给 FindMulExpression 函数后,我们使用与第一部分中使用的相同的 Multiply 函数来处理结果,该函数将返回结果行字符串中的所有 mul 表达式。

注意输入

拼图的实际输入我认为是多行,所以我们需要在所有剩余的行中保留该行的状态。或者,我们可以更聪明,创建一个大字符串并处理它。两者都是有效的并且会给出相同的结果。我只是不想增加跟踪所有状态和行的开销,所以我只是连接所有行并处理该单个字符串。

结论

本质上这是一个简单的问题,但如果您不了解正则表达式,您可能会陷入编写自己的解析器或有线字符串操作的兔子洞(就像我一样)。

这就是第三天,我将在周末甚至下周进行更多的直播解决问题。在 GitHub 上查找我的 AoC 解决方案的代码。

到那时,

快乐编码:)

以上是Code n Golang 的出现:做或不做正则表达式的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
您如何使用PPROF工具分析GO性能?您如何使用PPROF工具分析GO性能?Mar 21, 2025 pm 06:37 PM

本文解释了如何使用PPROF工具来分析GO性能,包括启用分析,收集数据并识别CPU和内存问题等常见的瓶颈。

您如何在GO中编写单元测试?您如何在GO中编写单元测试?Mar 21, 2025 pm 06:34 PM

本文讨论了GO中的编写单元测试,涵盖了最佳实践,模拟技术和有效测试管理的工具。

如何编写模拟对象和存根以进行测试?如何编写模拟对象和存根以进行测试?Mar 10, 2025 pm 05:38 PM

本文演示了创建模拟和存根进行单元测试。 它强调使用接口,提供模拟实现的示例,并讨论最佳实践,例如保持模拟集中并使用断言库。 文章

如何定义GO中仿制药的自定义类型约束?如何定义GO中仿制药的自定义类型约束?Mar 10, 2025 pm 03:20 PM

本文探讨了GO的仿制药自定义类型约束。 它详细介绍了界面如何定义通用功能的最低类型要求,从而改善了类型的安全性和代码可重复使用性。 本文还讨论了局限性和最佳实践

Debian OpenSSL有哪些漏洞Debian OpenSSL有哪些漏洞Apr 02, 2025 am 07:30 AM

OpenSSL,作为广泛应用于安全通信的开源库,提供了加密算法、密钥和证书管理等功能。然而,其历史版本中存在一些已知安全漏洞,其中一些危害极大。本文将重点介绍Debian系统中OpenSSL的常见漏洞及应对措施。DebianOpenSSL已知漏洞:OpenSSL曾出现过多个严重漏洞,例如:心脏出血漏洞(CVE-2014-0160):该漏洞影响OpenSSL1.0.1至1.0.1f以及1.0.2至1.0.2beta版本。攻击者可利用此漏洞未经授权读取服务器上的敏感信息,包括加密密钥等。

解释GO反射软件包的目的。您什么时候使用反射?绩效有什么影响?解释GO反射软件包的目的。您什么时候使用反射?绩效有什么影响?Mar 25, 2025 am 11:17 AM

本文讨论了GO的反思软件包,用于运行时操作代码,对序列化,通用编程等有益。它警告性能成本,例如较慢的执行和更高的内存使用,建议明智的使用和最佳

您如何在GO中使用表驱动测试?您如何在GO中使用表驱动测试?Mar 21, 2025 pm 06:35 PM

本文讨论了GO中使用表驱动的测试,该方法使用测试用例表来测试具有多个输入和结果的功能。它突出了诸如提高的可读性,降低重复,可伸缩性,一致性和A

如何使用跟踪工具了解GO应用程序的执行流?如何使用跟踪工具了解GO应用程序的执行流?Mar 10, 2025 pm 05:36 PM

本文使用跟踪工具探讨了GO应用程序执行流。 它讨论了手册和自动仪器技术,比较诸如Jaeger,Zipkin和Opentelemetry之类的工具,并突出显示有效的数据可视化

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
2 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)