news 2026/6/10 22:47:56

我正在用 Python 编写 2024 年的 Advent of Code – 第四天

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
我正在用 Python 编写 2024 年的 Advent of Code – 第四天

原文:towardsdatascience.com/im-doing-the-advent-of-code-2024-in-python-day-4-f0dacf4529a6

欢迎来到第四天!

  • 第一天介绍,如何获取你自己的谜题输入,以及第一天的谜题解决方案。

  • 第二天, 第三天

我们将在第四天的谜题中学习以下主题:

  • Python 中的列表推导

  • 如何处理一维和二维 NumPy 数组

  • 如何转置和翻转 NumPy 数组

到我写这篇文章的时候,已经发布了 22 个谜题,每个谜题有两个部分。每个部分都算作一个开始,以下是我的当前进度:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/8750a11b9f7abe7d44ab75c5e6fe0f95.png

![作者图片]


第四天 – 第一部分

第四天的谜题输入是一个包含字母 X、M、A 和 S 的长字符串。我的谜题输入的前 10 行看起来像这样:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/907c9c23a9a047a85f5156692b4449a2.png

![作者图片]

第四部分谜题的第一部分是要找到文本中“XMAS”的出现次数。难点在于所有水平、垂直和对角线上的出现都计算在内(包括正向和反向)。

这里有一个示例图,展示了在谜题输入中要寻找的内容:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/033846363e8b70307e84768025c22d19.png

![作者图片]

因此,我们需要在水平、垂直和对角线上计数“XMAS”和“SAMX”。

让我们从获取谜题输入开始。

importrequests session_cookie="your session cookie"# or session_cookie = os.getenv(SESSION_COOKIE)defget_puzzle_input(day,session_cookie,year=2024):url=f"https://adventofcode.com/{year}/day/{day}/input"cookies={"session":session_cookie}response=requests.get(url,cookies=cookies)ifresponse.status_code==200:returnresponse.textelse:returnNonepuzzle_input=get_puzzle_input(4,session_cookie)

为了进行水平计数,我将谜题输入分割成一行行的列表,并在列表推导中使用count方法。

# split at new line to convert the puzzle input into a list of lineslines=puzzle_input.split("n")[:-1]# count the occurrences of XMAS and SAMX for each linehorizontal_counts=[line.count("XMAS")+line.count("SAMX")forlineinlines]

horizontal_counts列表包含每行中 XMAS 和 SAMX 出现的次数。sum(horizontal_counts)给出了总的水平计数。

有不同的方法来找到垂直计数。我想使用 NumPy 数组。第一步是将lines列表转换成二维数组。

importnumpyasnp arr=np.array([list(line)forlineinlines])print(arr.shape)# output(140,140)print(arr)# outputarray([['M','S','M',...,'M','X','S'],['S','A','A',...,'S','A','A'],['X','M','X',...,'M','X','S'],...,['M','A','S',...,'S','S','S'],['S','A','M',...,'A','A','M'],['M','M','S',...,'M','M','M']],dtype='<U1')

谜题输入中有 140 行,每行有 140 个字符。

要计算“XMAS”和“SAMX”的垂直出现次数,我将这个数组转置,这样就将垂直变成了水平。

arr_transpose=arr.transpose()arr_transpose# outputarray([['M','S','X',...,'M','S','M'],['S','A','M',...,'A','A','M'],['M','A','X',...,'S','M','S'],...,['M','S','M',...,'S','A','M'],['X','A','X',...,'S','A','M'],['S','A','S',...,'S','M','M']],dtype='<U1')

然后,我为每一行创建一个字符串,通过连接字母可以使用与水平计数相同的方法。

vertical_lines=["".join(line)forlineinarr_transpose]vertical_lines[0]# output'MSXSSSMSMMMXMXMXSSXMASAMMMMSMXMMSMSXMASMMXMASMMMMMSSSXMASAMXMMXSAMMMXAXSMMMMSXMAMMSAMSAMSASMMMASMSSMMSAMASXMXXXSSMMSAMXXSXSXSMSAMXXXMASASMSM'

然后,我可以使用与水平计数相同的方法。

vertical_counts=sum([line.count("XMAS")+line.count("SAMX")forlineinvertical_lines])

现在我们有了水平和垂直计数。最后一个是对角线上的出现次数。我们可以使用 NumPy 数组的diagonal方法创建对角线列表。np.diagonal(arr, 0)给出了主对角线。通过将 0 替换为正整数和负整数,我们可以获得所有对角线。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/dcfe48bd0a66ae6b9c96d2caf029ed2d.png

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4f558e22349a1fb7bfaf8d85a98ed0ac.png

让我们写一个 for 循环来创建所有对角线的列表。

diagonals=[]foriinrange(-len(arr)+1,len(arr)-1):line="".join(np.diagonal(arr,i))diagonals.append(line)# check the first 10 diagonalsdiagonals[:10]# output['M','SM','MAS','SAMA','AXSMM','SXMASX','AMMASAS','MXMASXMM','XSAMMASAM','XMXMMAXSAM']

我们处理了从左上角到右下角的对角线,但我们还需要检查从右上角到左下角的对角线。

我们可以使用相同的循环来完成,但我们只需要翻转二维数组,这可以通过fliplr方法完成。

diagonals_flipped=[]foriinrange(-len(arr)+1,len(arr)-1):line="".join(np.diagonal(np.fliplr(arr),i))diagonals_flipped.append(line)

我们现在可以计算两个对角线和翻转对角线上的“XMAS”和“SAMX”出现的次数。

diagonal_counts=sum([line.count("XMAS")+line.count("SAMX")forlineindiagonals])diagonal_counts_flipped=sum([line.count("XMAS")+line.count("SAMX")forlineindiagonals_flipped])# final answerhorizontal_counts+vertical_counts+diagonal_counts+diagonal_counts_flipped

当我们将我们计算的所有计数相加时,我们得到第一部分的最终答案。


第四天 – 第二部分

在这个谜题的第二部分,我们要找到“X-MAS”的出现次数,这意味着有两个 MAS 值以 X 的形状出现。

下面是我们将在谜题输入中寻找的内容("."代表任何字符)。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4f558e22349a1fb7bfaf8d85a98ed0ac.png

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4f558e22349a1fb7bfaf8d85a98ed0ac.png

我解决这个谜题的方法是创建一个从左上角开始的 3×3 窗口,并向下移动一个位置。在每次移动中,我都会检查 3×3 窗口是否等于我们想要的任何 X-MAS 形状。

一旦我到达底部,我就回到顶部并向右移动一个步骤。我重复同样的过程,直到我到达右下角。

我试图在下面的图中展示这个过程:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/d3c5ef3a7254833a8f8b243c7f7cfa88.png

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4f558e22349a1fb7bfaf8d85a98ed0ac.png

要在代码中执行此操作,我使用了两个 for 循环。让我们首先定义我们将要寻找的 X-MAS 形状。

xmas1=[['M','.','M'],['.','A','.'],['S','.','S']]xmas2=[['S','.','S'],['.','A','.'],['M','.','M']]xmas3=[['M','.','S'],['.','A','.'],['M','.','S']]xmas4=[['S','.','M'],['.','A','.'],['S','.','M']]

我们现在可以创建嵌套的 for 循环来遍历第一部分创建的二维数组。

xmas_cnt=0foriinrange(len(arr)-2):forjinrange(len(arr)-2):res=arr[j:j+3,i:i+3].copy()# very important to use copy hereres[0][1]="."res[1][0]="."res[1][2]="."res[2][1]="."if(res==xmas1).sum()==9:xmas_cnt+=1if(res==xmas2).sum()==9:xmas_cnt+=1if(res==xmas3).sum()==9:xmas_cnt+=1if(res==xmas4).sum()==9:xmas_cnt+=1

我们创建了一个变量(xmas_cnt)来跟踪我们检测到的 X-MAS 形状。如果 3×3 数组等于我们想要的 X-MAS 形状之一,我们就将这个变量的值增加一。xmas_cnt的最终值就是第二部分的答案。

我们将无关位置上的字母替换为"."。否则,我们需要将 3×3 数组与更多的组合进行比较。

非常重要的是要注意,在每一步中,我们需要创建 3×3 数组的副本。否则,当我们用"."替换字母时,我们会修改原始数组,最终会错过一些匹配项。


第四天的谜题是关于列表推导和 NumPy 数组操作的良好实践。我们还学习了嵌套循环结构,如何转置和翻转二维数组。

如果你计划在数据科学生态系统中找工作,所有这些都是在你需要时相当常用的基本操作。

感谢您的阅读。请期待第五天。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 20:33:13

我正在用 Python 做 2024 年的编程挑战赛——第 1 天

原文&#xff1a;towardsdatascience.com/im-doing-the-advent-of-code-2024-in-python-day-1-8a9ea6ca6d3f 编程挑战赛是一套每年 12 月 1 日至 25 日发布的 25 个编程谜题。埃里克瓦斯特尔&#xff08;Eric Wastl&#xff09;受到圣诞日历的启发&#xff0c;自 2015 年以来一…

作者头像 李华
网站建设 2026/6/9 23:47:28

使用jacoco的API方式解析覆盖率和生成覆盖率报告

JaCoCo 离线解析.exec文件&#xff1a;生成与获取详细覆盖率数据全指南 一、概述 在JaCoCo覆盖率统计场景中&#xff0c;jacoco支持cli通过命令行的方式生成覆盖率报告&#xff0c;但是这样无法很好和其他系统集成&#xff0c;本文演示通过jacoco提供的API的方式生成覆盖率报…

作者头像 李华
网站建设 2026/6/10 10:35:46

Logging 已死?从“调试日记”到“结构化事件”的范式转移

大家好&#xff0c;我是Tony Bai。“传统的日志记录&#xff08;Logging&#xff09;已经死了。不是说我们不再需要记录信息&#xff0c;而是那种‘写日记’式的记录方式&#xff0c;在微服务和高并发时代&#xff0c;已经彻底破产。”曾几何时&#xff0c;我们写日志就像写日记…

作者头像 李华
网站建设 2026/6/10 2:37:48

Miniconda-Python3.10结合Prometheus监控GPU使用率

Miniconda-Python3.10结合Prometheus监控GPU使用率 在深度学习项目日益复杂的今天&#xff0c;一个常见的场景是&#xff1a;训练脚本跑起来了&#xff0c;日志也输出了&#xff0c;但你根本不知道这块GPU到底有没有被“榨干”。有时候模型看似在运行&#xff0c;实则GPU利用率…

作者头像 李华
网站建设 2026/6/10 15:07:51

从Anaconda迁移到Miniconda-Python3.10:节省70%磁盘空间的方法

从 Anaconda 迁移到 Miniconda-Python3.10&#xff1a;如何节省 70% 磁盘空间 在 GPU 云服务器上启动一个数据科学环境时&#xff0c;你是否曾因等待 Anaconda 加载而浪费了整整十分钟&#xff1f;或者在 CI/CD 流水线中&#xff0c;构建镜像的时间一半都花在了解压和安装冗余包…

作者头像 李华
网站建设 2026/6/10 17:16:15

Zynq AXI数据总线通道的valid和ready信号

VALID&#xff1a;由数据发送方驱动&#xff0c;高电平表示「我这边的数据 / 地址已经准备好&#xff0c;可以发送了&#xff1b;READY&#xff1a;由数据接收方驱动&#xff0c;高电平表示「我这边已经准备好&#xff0c;可以接收数据 / 地址了。针对写地址&#xff08;AW&…

作者头像 李华