引言
本文中的所有代码都用 Python 编写。
在 #48in24 挑战中,Exercism 正在探索社区如何应对各种编程挑战。 “Hello, World!” 是 Exercism 上最基础的练习,因为太简单,被认为不值得制作一期官方视频。 但我并不这么认为,我觉得看看这个简单练习的一些更有趣的解法应该会很有意思!
认识 “Hello, World!”
“Hello, World!” 大概是世界上最著名的程序。 几乎所有学过编程的人都至少写过它一次。 它的简洁和那句友好的问候,往往象征着迈入奇妙编程世界的第一步。
在 Exercism 上,你会得到一个名为hello的函数,它返回“Goodbye, Mars!”。
def hello():
return 'Goodbye, Mars!'
你的任务是修改它,让它改为返回“Hello, World!”。
传统解法
首先是最简单的解法,也是 Exercism 希望你采用的写法。 只要把字符串从“Goodbye, Mars!”简单地改成“Hello, World!”,我们就能放心地把它返回了!
def hello() -> str:
return 'Hello, World'
其他解法
我打算用我能想到的各种方法来解决这个练习。
为了叙述方便,我把这个简单的函数称为“机器”,这台机器唯一的工作就是返回一句“Hello, World!”问候。
看看会走到哪一步吧……!
拼接
机器已经认识其中一些词,但似乎没办法,呃,把它们串成一个字符串。
def hello() -> str:
words = ["Hello", " world!"]
return ",".join(words)
首字母大写
今天机器的电池有点低,所有词都缺乏能量,没能正确地变成首字母大写。
def hello() -> str:
words = "hello, world!"
return words.title()
反转
机器不知怎的知道这句问候,但看起来有点……反过来了。
def hello() -> str:
sdrow = "!dlroW ,olleH"
return sdrow[::-1]
注意:Reverse String 是 #48in24 挑战的特色练习。记得去看看用不同语言解决它的各种方法!
切片拼合
也许机器该换油了,因为正常的问候信息好像有点乱。
def hello() -> str:
w = "Holld, Werlo!"
return f"{w[0]}{w[8]}{w[2:4]}{w[1]}{w[5:8]}{w[-2]}{w[-4:-2]}{w[4]}{w[-1]}"
柯里化
哎呀,机器的某些部分进入了维护模式。 它忘记了问候语,现在只能一点一点地接收消息。
def hello(greet: str):
def world(location: str) -> str:
return f"{greet}, {location}!"
return world
hello = hello("Hello")
hello("World")
ASCII
你不小心把柠檬水泼到了机器上,现在它只给你显示这些奇怪的数字,而不是消息里常见的字符。
def hello() -> str:
ascii = [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33]
return ''.join(chr(value) for value in ascii)
字典
你看新闻时看到一个片段,讲一个男人用 S.O.S 信号获救。 “也许机器也该能处理摩尔斯电码!”你心里想着,但不确定为什么。 它唯一的工作就是返回那句问候……
def hello(morse) -> str:
morse_code = {
"...." : "H",
"." : "e",
".-.." : "l",
"---" : "o",
"--..--": ",",
"/" : " ",
".--" : "W",
".-." : "r",
"-.." : "d",
"-.-.--": "!"
}
return "".join(morse_code[value] for value in morse.split())
print(hello(".... . .-.. .-.. --- --..-- / .-- --- .-. .-.. -.. -.-.--"))
函数式
眼看现在的机器容易变动和损坏,你决定造一台更小、但不可变且坚不可摧的机器,来做完全一样的事。 每当常规机器不工作或出毛病时,它就改为启用那台小机器。 等等,为什么我们不干脆从现在起就用那台小的……
def hi() -> str:
return "Hello, World!"
def hello() -> str:
return hi()
排列
一场强烈的雷暴经过,你可怜的倒霉机器被闪电击中了。 它还能开机,但现在行为很怪异。 组装那句问候所需的所有字符都还在,但顺序全乱了,而且逻辑板受损意味着机器再也无法把消息的顺序弄对。 偏偏你运气这么差,你早先造的那台极其可靠、坚不可摧的小机器其实是可以被偷走的(没错,它不见了!)。 于是,你决定就让你的老朋友把所有这些字母用各种可能的方式重新排成正确的消息。 毕竟只有 13 个字符,而机器内存很大。应该很快……
from itertools import permutations
def hello() -> str:
chars = ['H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!']
all_permutations = permutations(chars)
for perm in all_permutations:
if ("".join(perm) == "Hello, World!"):
return ''.join(perm)
查找
你决定给机器升级,让它能用不同语言打招呼。 但它唯一的工作就是用英语说出“Hello, World!”,于是它一犯迷糊,就决定下载无数种说“Hello, World!”的方式,每种的大小写和位置都略有不同。 这让你很困惑,不知道该选哪一个,但至少它们都按照某种顺序排列着。 你得告诉机器正确的说法,这样它才能找到那句话,重新恢复正常(也许吧)。
def hello(my_fav_phrase) -> str:
combinations = [
"HELLO, WORLD!",
# many many many items later,
"hello, world!"
]
lower = 0
upper = len(combinations)
while lower <= upper:
mid = (lower + upper) // 2
mid_val = combinations[mid]
if mid_val == my_fav_phrase:
return combinations[mid]
elif mid_val < my_fav_phrase:
lower = mid + 1
else:
high = mid - 1
return "Error: Can't find {my_fav_phrase}"
hello("Hello, World!")
你的弟弟一直在旁边看着这一切,他问你为什么不干脆把这堆乱七八糟的东西删掉,然后直接把正确的句子告诉机器让它记住。 你没回答,只是瞪了他一眼。
有格调的类
你决定做点实验,调整机器,让它根据按下的是哪个按钮而表现不同。
你考虑过让它随意一点,开口说“Hi”,但你是个有格调的人,于是决定永远只用hello方法,把另一个用胶带封起来。
你意识到自己在这类事情上还真有不少空闲时间……
class Greeting:
location = "World"
def __init__(self) -> None:
pass
def hello(self):
return f"Hello, {self.location}!"
def hi(self):
return f"Hi, {self.location}!"
salutation = Greeting()
salutation.hello()
递归
不知为什么,你觉得如果机器有点卡顿、总是晚 10 秒才回应会很好玩。 你弟弟又一次质疑这个功能背后的逻辑,因为据他说,用这台机器的只有你一个人。
import time
def hello(n=10):
if n == 0:
return "Hello, World!"
else:
time.sleep(1)
return hello(n-1)
随机
突然有一天,你厌倦了一遍又一遍一成不变的问候,于是决定让它最后向你问候一次,然后彻底把这台机器退休,再也不碰它。 这台机器陪你同甘共苦了很久,你决定让这场“朋友”之间的最后相会交给命运来决定。 你最后一次给它通电,就让它转吧……
import random
def hello():
chars = list("Helo,Wrld!")
greeting = ""
while (greeting != "Hello, World!"):
greeting = "".join(random.choices(chars, k=13))
return greeting
结语
这就是在我脑海里的一场狂野之旅。 我不确定它有没有用,但肯定很有意思。
感谢阅读,编程愉快!