原题地址 https://adventofcode.com/2024/day/19
以下是DeepSeek译文
第 19 天:亚麻布陈列
今天,历史学家们带你去了齿轮岛上的温泉!非常可疑的是,当他们开始仔细搜索广阔的螺旋田野时,绝对没有任何问题发生。
这终于可能是你参观隔壁温泉的机会了吗?只有一种方法能知道。
在与温泉前台的接待人员简短交谈后,你发现自己没有正确种类的钱来支付入场费。然而,在你离开之前,工作人员引起了你的注意。显然,他们听说了你如何在温泉帮忙,并且愿意做个交易:如果你能简单地帮他们整理毛巾,他们就让你免费入场!
这个温泉的每条毛巾都标有一种彩色条纹图案。只有少数几种图案,但对于任何特定图案,工作人员都可以为你提供所需数量的带有该图案的毛巾。每条条纹可以是白色 (w)、蓝色 (u)、黑色 (b)、红色 ® 或绿色 (g)。因此,带有图案 ggr 的毛巾会有一条绿色条纹、一条绿色条纹,然后是一条红色条纹,按此顺序。(你不能通过将毛巾上下翻转来反转图案,因为那会导致温泉标志朝向错误。)
官方温泉品牌专家制作了一个设计列表——每个设计都是一长串条纹颜色——他们希望能够展示这些设计。你可以使用任何你想要的毛巾,但所有毛巾的条纹必须完全符合所需的设计。因此,要展示设计 rgrgr,你可以使用两条 rg 毛巾和一条 r 毛巾,或者一条 rgr 毛巾和一条 gr 毛巾,甚至一条巨大的 rgrgr 毛巾(假设这种毛巾图案确实可用)。
首先,收集所有可用的毛巾图案和所需的设计列表(你的谜题输入)。例如:
r, wr, b, g, bwu, rb, gb, br
brwrr
bggr
gbbr
rrbgbr
ubwu
bwurrg
brgr
bbrgwb
第一行表示可用的毛巾图案;在这个例子中,温泉拥有无限数量的带有一条红色条纹 ® 的毛巾,无限数量的带有一条白色条纹和一条红色条纹 (wr) 的毛巾,等等。
在空行之后,其余各行描述了一个温泉希望展示的设计。在这个例子中,第一个设计 (brwrr) 表示温泉希望展示一条黑色条纹、一条红色条纹、一条白色条纹,然后是两条红色条纹,按此顺序。
并非所有设计都能用可用的毛巾实现。在上面的例子中,设计的可实现与否如下:
brwrr可以用一条br毛巾,然后一条wr毛巾,最后一条r毛巾制成。bggr可以用一条b毛巾,两条g毛巾,然后一条r毛巾制成。gbbr可以用一条gb毛巾和一条br毛巾制成。rrbgbr可以用r,rb,g, 和br制成。ubwu无法实现。bwurrg可以用bwu,r,r, 和g制成。brgr可以用br,g, 和r制成。bbrgwb无法实现。
在这个例子中,八个设计中有 6 个是可以用可用的毛巾图案实现的。
为了尽快进入温泉,请仔细查阅你的毛巾图案和所需设计列表。有多少个设计是可能实现的?
要开始,请获取你的谜题输入。
第二部分
工作人员并不完全喜欢你提出的一些毛巾摆放方案。为了避免无休止的毛巾重新摆放循环,也许你应该直接给他们所有可能的选择。
以下是上述示例中各个设计所有不同的实现方式:
-
brwrr可以通过两种不同的方式实现:b, r, wr, r或br, wr, r。 -
bggr只能通过b, g, g, r这一种方式实现。 -
gbbr可以通过 4 种不同的方式实现:g, b, b, rg, b, brgb, b, rgb, br
-
rrbgbr可以通过 6 种不同的方式实现:r, r, b, g, b, rr, r, b, g, brr, r, b, gb, rr, rb, g, b, rr, rb, g, brr, rb, gb, r
-
bwurrg只能通过bwu, r, r, g这一种方式实现。 -
brgr可以通过两种不同的方式实现:b, r, g, r或br, g, r。 -
ubwu和bbrgwb仍然无法实现。
将此示例中所有毛巾可以排列成所需设计的方式数量相加,得到 16 (2 + 1 + 4 + 6 + 1 + 2)。
只要你有了这个列表,他们就会让你进入温泉。如果将你能实现每个设计的不同方式的数量相加,你会得到什么?
我用SQL做出来了第一部分题目中的例子,但是同样的语句做不出附件全部的解, 因为using key(w)每次会覆盖相同的w,从而把同一个毛巾的不同组合漏掉, 使结果偏小
with recursive co as(
select trim(unnest(string_split(c, ',')))c from (from read_csv('2419-input0.txt', header=0, delim='-')t(c) limit 1)),
w as(select * from read_csv('2419-input0.txt', header=0, delim='-', skip=2) t(w)),
t using key(w)as(select 1 lv , w,w s from w
union
select lv+1,w, substr(s, length(c)+1) from t,co where s like c||'%' and s<>''
and lv<80)
select count(*)from t where s='';
实在想不出来就丢给DeepSeek,
编写python函数,判断字符串a能否由一个字符串集合b中的元素组成,集合中的元素允许重复使用,拼接的字符串必须和要判断的字符串相同。比如集合{bi,l,k,ike}能组成bill,不能组成bike
再编写python函数,输出字符串a能由一个字符串集合b中的元素组成的方法数目,集合中的元素允许重复使用,拼接的字符串必须和要判断的字符串相同。比如集合{r, b, g, rb, gb, br},字符串brgr有2种组成方法: b, r, g, r 或 br, g, r,返回2,不能组成的返回0
他把两部分都轻松做对了
def can_compose_string(a: str, b: set) -> bool:
"""
判断字符串a能否由字符串集合b中的元素组成
Args:
a: 目标字符串
b: 字符串集合
Returns:
bool: 如果能够组成返回True,否则返回False
"""
n = len(a)
# dp[i] 表示a的前i个字符能否被b中的字符串组成
dp = [False] * (n + 1)
dp[0] = True # 空字符串可以被组成
for i in range(1, n + 1):
for j in range(i):
# 如果前j个字符可以被组成,且a[j:i]在集合b中
if dp[j] and a[j:i] in b:
dp[i] = True
break # 找到一个可行的分解即可
return dp[n]
def can_compose_string_memo(a: str, b: set) -> bool:
"""
使用记忆化递归判断字符串a能否由字符串集合b中的元素组成
"""
memo = {}
def dfs(start):
if start == len(a):
return True
if start in memo:
return memo[start]
for end in range(start + 1, len(a) + 1):
substring = a[start:end]
if substring in b and dfs(end):
memo[start] = True
return True
memo[start] = False
return False
return dfs(0)
def find_composition(a: str, b: set):
"""
返回字符串a的分解方式,如果无法分解返回None
"""
n = len(a)
dp = [None] * (n + 1)
dp[0] = [] # 空字符串的分解为空列表
for i in range(1, n + 1):
for j in range(i):
if dp[j] is not None and a[j:i] in b:
dp[i] = dp[j] + [a[j:i]]
break
return dp[n]
import sys
import time
def count_composition_ways_optimized(a: str, b: set) -> int:
"""
优化版本:限制子串最大长度,提高效率
"""
n = len(a)
if n == 0:
return 1
# 计算集合中字符串的最大长度
max_len = max(len(word) for word in b) if b else 0
dp = [0] * (n + 1)
dp[0] = 1
for i in range(1, n + 1):
# 只检查可能的子串长度,避免不必要的检查
for length in range(1, min(i, max_len) + 1):
start = i - length
if a[start:i] in b:
dp[i] += dp[start]
return dp[n]
def main():
if len(sys.argv) != 2:
print("用法: python script.py <文件名>")
return
filename = sys.argv[1]
cnt=0
try:
with open(filename, 'r', encoding='utf-8') as file:
while True:
line = file.readline().strip()
if line == '':
break
print(f"题目: {line}")
t = time.time()
cnt+=count_composition_ways_optimized(line, b)
#if can_compose_string(line, b):
# cnt+=1
# print(f"题目有解: {line}")
#print(f"耗时: {round(time.time()-t, 4)} s")
except FileNotFoundError:
print(f"错误: 文件 '{filename}' 不存在")
except Exception as e:
print(f"错误: {e}")
print(cnt)
#列表b保存从附件输入的子串集合, 以下只列出部分。待求解字符串保存在文件中用命令行输入文件名
b=['grbuu','bbg','rwrwrru','bw','gwburwr','gubgu','wrbug','brrb']
if __name__ == "__main__":
main()
其实第一部分的结果也可以用第二部分的函数顺便得出。

697

被折叠的 条评论
为什么被折叠?



