news 2026/8/28 2:11:09

我正在用 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/8/21 19:46:32

使用Miniconda为PyTorch项目配置静态代码检查

使用Miniconda为PyTorch项目配置静态代码检查 在深度学习项目的开发过程中&#xff0c;我们常常会遇到这样的场景&#xff1a;模型训练脚本在一个团队成员的机器上运行正常&#xff0c;但换到另一个人的环境中却频繁报错——“torch not found”、“CUDA version mismatch”&a…

作者头像 李华
网站建设 2026/8/25 13:05:19

Miniconda-Python3.10镜像如何提升AI产品市场竞争力

Miniconda-Python3.10镜像如何提升AI产品市场竞争力 在人工智能技术飞速演进的今天&#xff0c;一个AI产品的成败早已不再仅仅取决于算法精度或模型结构。真正拉开差距的&#xff0c;往往是那些“看不见”的工程能力——比如开发环境能不能一键复现&#xff1f;新成员加入项目三…

作者头像 李华
网站建设 2026/8/23 8:33:16

Miniconda-Python3.10镜像如何支撑高并发Token计费接口

Miniconda-Python3.10 镜像如何支撑高并发 Token 计费接口 在大模型服务&#xff08;LLM as a Service&#xff09;快速普及的今天&#xff0c;API 调用按 Token 计费已成为主流商业模式。然而&#xff0c;一个看似简单的“统计文本 token 数量”操作&#xff0c;在生产环境中却…

作者头像 李华
网站建设 2026/8/26 23:15:25

入门必看:AUTOSAR架构图各层功能通俗解读

从零开始搞懂AUTOSAR&#xff1a;一文看透汽车电子软件的“操作系统”你有没有想过&#xff0c;为什么现代汽车能同时处理几十个复杂功能——比如自适应巡航、自动泊车、语音交互&#xff0c;还能保证彼此不打架&#xff1f;这背后靠的不是某个天才程序员写的“万能代码”&…

作者头像 李华
网站建设 2026/8/25 14:56:56

Miniconda-Python3.10环境下使用conda create新建虚拟环境

Miniconda-Python3.10环境下使用conda create新建虚拟环境 在AI项目开发中&#xff0c;你是否曾遇到这样的场景&#xff1a;刚跑通一个基于PyTorch 1.12的模型训练脚本&#xff0c;却因为另一个项目需要升级到PyTorch 2.0而导致原有代码报错&#xff1f;或者团队协作时&#xf…

作者头像 李华
网站建设 2026/8/26 23:49:07

Miniconda-Python3.10结合FastAPI构建高性能Token API

Miniconda-Python3.10 结合 FastAPI 构建高性能 Token API 在 AI 模型服务化浪潮中&#xff0c;一个常见但棘手的问题是&#xff1a;如何让训练好的模型稳定、安全、高效地对外提供接口&#xff1f;尤其当多个团队协作、环境频繁切换时&#xff0c;“在我机器上能跑”的尴尬局…

作者头像 李华