들어가며
이 글의 모든 코드는 Python으로 작성해요.
Exercism은 #48in24 챌린지에서 커뮤니티가 다양한 코딩 챌린지에 어떻게 접근하는지 살펴보고 있어요. "Hello, World!"는 Exercism에서 가장 기본적인 연습 문제인데, 너무 단순하다고 여겨져서 공식 영상으로 만들지 않았어요. 그런데 저는 생각이 좀 달라요. 이 단순한 연습 문제를 조금 더 흥미로운 방식으로 풀어보면 재미있지 않을까 싶었어요!
"Hello, World!" 만나보기
"Hello, World!"는 아마 세계에서 가장 유명한 프로그램일 거예요. 코딩을 배운 사람이라면 거의 누구나 한 번쯤은 작성해 봤을 거예요. 단순함과 다정한 메시지는 프로그래밍이라는 멋진 세계로 들어가는 첫걸음을 상징하곤 해요.
Exercism에서는 "Goodbye, Mars!"를 반환하는 hello라는 함수를 제공해요.
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
끝
제 머릿속을 한 바퀴 요란하게 돌아본 여행이었어요. 도움이 됐는지는 모르겠지만, 재미있었던 건 확실해요.
읽어주셔서 고마워요, 즐거운 코딩 되세요!