'우리는 예지력을 갖고 미래를 알아맞힐 수는 없지만, 우리가 원하는 미래를 만들기 위해 노력하고 대응할 수 있습니다.'
사람들은 예상하지 않은 미래가 오면 두려워한다. 그렇기 때문에 다가오는 미래에 대비하기 위해 각종 예방책과 대응수단을 마련한다. 카이스트 미래전략 2024는 미래에 효과적으로 대비하기 위해 과거와 현재, 미래를 한 권에 담아 독자에게 최대한 주관적인 요소를 배제하고 객관적으로 정보를 전달하고자 한다.
첫 번째 목차인 포스트 AI시대 휴머니즘의 미래는 도구가 어떻게 진화를 해왔는지 살펴보고 현 시점에 기술이 얼마만큼 발전했는지 설명한다. 가장 인상깊었던 목차는 초지능 사회를 열어줄 21세기 새로운 도구인데 여러 도구를 소개했지만 그 중 펌웨어의 도전 부분은 많이 충격적이었다. 이전에 필자는 사이버펑크라는 애니메이션을 본 적이 있는데 이 애니메이션은 2070년의 인간의 미래모습을 그린 작품으로 신체에 기계장치가 이식된 채로 살아가는 삶은 어떨지 보여준다. 이 작품을 보면서도 충격이었지만 실제로 비슷하게 그러한 시도를 현재 2023-2024년에 시행되고 있었다는 점이 충격이었다.
한 가지 예를 소개하자면 최근 바이오닉스 분야에서 가장 뜨거운 이슈는 바로 인공 청각과 인공 시각이다. 인공 청각은 손상된 와우에 전극을 삽입해 전기신호로 변환된 소리를 청신경에 전달하는 장치인데 이미 1970년대에 사용화가 되어 선천적으로 청력을 잃은 많은 청각장애인에게 세상의 소리를 들려주고 있다고 한다. 또 일론머스크의 뇌공학 스타트업인 뉴럴링크는 뇌에 실 형태의 미세전극을 매우 높은 밀도로 정교하게 삽입하고 신경세포를 선택적으로 자극하거나 측정된 신경신호를 무선으로 전송하는 기술을 개발하고 있다. 이 기술이 상용화된다면 뇌를 직접 자극해 사물을 보게하고 소리를 듣게 하고 마비된 사지를 로봇의 힘을 빌려 움직일 수 있게 할 수 있다고 하는데 시간이 많이 걸리기는 하겠지만 실현된다면 이것 자체로 바이오 산업에서 챗GPT 만큼의 파장을 일으킬 수 있을거라고 생각한다. 하지만 이렇게 장애를 가진 사람들의 한계를 극복할 수 있는 장점이 될 수도 있지만 앞서말한 애니메이션 사이버펑크처럼 장애가 없는데도 신체의 기능을 높이기 위한 인간 증강의 기술로 활용될 수도 있다는 불안감도 준다. 이로 인해 인위적으로 개인의 능력을 증강한 사람이 그렇지 않은 사람보다 더 상위 계급이 되어 새로운 양극화를 만들어낼 수 있다. 따라서 우리가 원하는, 즉 인류의 행복을 위해서는 바이오닉스 기술의 감시와 통제는 필수적으로 이행되어야 할 것이다.
두 번째 목차인 변화에 대처하는 STEPPER 전략에서는 기업이나 국가, 개인, 가정이 다가오는 미래에 어떻게 대처해서 급변하는 사회에 대비할 수 있는지 담았다. 여기서 우리나라가 인구가 꾸준하게 감소하고 있는데 이에 대한 대비로 이민자를 수용해야한다는 얘기가 나온다. 이와 같은 유사 사례로 독일이 이민자 정책에 성공했다는 걸 알고 있었던 필자는 이 책에서 어떤 해결책을 제시할지 궁금했다. 여기서는 이민자 정책의 장단점을 따지기에 앞서 왜 인구감소가 문제인지 이민자 정책을 시행한 뒤의 우리나라가 어떤 사회로 뒤바뀔지를 설명했다. 일단 인구가 줄어든다는 것은 인재가 줄어든다는 것으로 이는 국가경쟁력의 약화로 이어진다. 그렇기에 해외 이민자들을 받아들여 우수인재 유치에 힘써야한다는 것이 주된 내용이었다. 그러나 해외 이민자들을 받아들였을 때의 우리 사회 구성원들이 제대로 수용할 수 있을지는 의문이다. 아직까지 외국인에 대한 편견이나 선입견이 존재하기에 이에 대한 교육이 필요하고 이민자들이 우리나라에 왔을 때 잘 자리잡을 수 있도록 해주는 것이 중요하다. 이 책에서는 인구감소의 문제에 대해 국가가 더욱 적극적으로 힘써줘야한다고 주장하고 있는 듯하다. 필자 또한 개개인의 노력만으로는 이 문제를 해결할 수 없다고 생각하기에 국가가 전면적으로 나서야한다고 생각한다. 이처럼 두 번째 목차에서는 STEPPER가 되기위해 우리는 무엇을 신경써줘야하는지 방향을 알려준다.
'선비정신', 우리 선조들이 정파나 개인의 이해관계를 떠나서 오로지 대의와 국가, 백성을 위해 시시비비를 가리고자 하는 한국 고유의 정신. 요즘 우리나라에서는 이런 모습이 거의 보이지 않는 것 같다. 모두가 선비정신을 갖고 대의와 국가를 위해 자신이 맡은 위치에서 힘쓴다면 지금 현재 우리나라의 위기는 충분히 극복할 수 있을 것이라고 생각한다.
2024년 세계의 정세와 우리나라의 상황, 그리고 산업의 동향을 한 권의 책을 통해 대략적으로 파악하고 자신만의 새로운 인사이트를 얻고 싶은 분들에게 이 책을 추천한다.
seed 값에 의해 동일한 코드를 사용해도 결과가 다를 수 있기에, 동일한 결과를 위해 seed값을 고정시킵니다.
import numpy as np
import random
import os
def seed_everything(seed):
random.seed(seed)
os.environ['PYTHONHASHSEED'] = str(seed)
np.random.seed(seed)
seed_everything(42) # Seed 고정
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)
데이터 전처리 2: 범주형 변수 수치화
LabelEncoder를 통해 범주형 변수 수치화를 진행합니다.
from sklearn.preprocessing import LabelEncoder
categorical_features = ['대출기간', '주택소유상태', '대출목적']
for i in categorical_features:
le = LabelEncoder()
le=le.fit(train_x[i])
le=le.fit(X[i])
train_x[i]=le.transform(train_x[i])
X[i]=le.transform(X[i])
for case in np.unique(test_x[i]):
if case not in le.classes_:
le.classes_ = np.append(le.classes_, case)
test_x[i]=le.transform(test_x[i])
display(train_x.head(3))
display(test_x.head(3))
모델 선정 및 학습
RandomForestClassifier
from sklearn.ensemble import RandomForestClassifier
RFC = RandomForestClassifier()
RFC.fit(X_train, y_train)
max_depth_list = range(20,25)
accuracy = []
for m in max_depth_list:
RFC = RandomForestClassifier(random_state = 42, max_depth = m)
RFC.fit(X_train, y_train)
pred = RFC.predict(X_test)
score = accuracy_score(pred, y_test)
accuracy.append(score)
plt.plot(max_depth_list, accuracy)
plt.xlabel('max_depth')
plt.ylabel('accuracy')
plt.show()
최적의 깊이를 찾기위한 코드
from sklearn.metrics import accuracy_score
pred = RFC.predict(X_test)
score = accuracy_score(pred, y_test)
print(f"정확도: {score}")
가장 잘 나온 max_depth의 값을 선택하여 예측한 결과 정확도는 0.8231이 나왔습니다.
nl = []
ll = []
while True:
n = int(input())
if n == -1:
break
l = []
for i in range(1,n+1):
if n % i == 0:
l.append(i)
l.remove(l[-1])
ll.append(l)
nl.append(n)
for j in range(len(ll)):
if nl[j] == sum(ll[j]):
print(f"{nl[j]} = ", end = "")
for k in ll[j]:
if k == 1:
print(f"{k}", end = "")
else:
print(f" + {k}", end = "")
else:
print()
print(f"{nl[j]} is NOT perfect.")
이 코드는 정답이랑 똑같은 형식으로 출력되기는 하는데
출력되는 형식이 이렇게 되면 안되기 떄문에 틀린 문제이다.
한 줄에 하나씩 출력되도록 해야하는데 그렇게 하지 않았기에 틀린문제
그럼 어떻게 해야하나?
옛날에 썼던 적이 있는 것 같은데 요즘 안써서 까먹은 join을 써야한다.
join을 통해 반복문 사이에 있는 인자들을 +로 연결해준다는 생각을 해주면 이렇게 길게 코드를 쓰지 않아도 된다.
정답 코드
nl = []
ll = []
while True:
n = int(input())
if n == -1:
break
l = []
for i in range(1,n+1):
if n % i == 0:
l.append(i)
l.remove(l[-1])
ll.append(l)
nl.append(n)
for j in range(len(ll)):
if nl[j] == sum(ll[j]):
temp = ' + '.join(str(i) for i in ll[j])
print(f"{nl[j]} = {temp}")
else:
print(f"{nl[j]} is NOT perfect.")
위의 그림과 같이 육각형으로 이루어진 벌집이 있다. 그림에서 보는 바와 같이 중앙의 방 1부터 시작해서 이웃하는 방에 돌아가면서 1씩 증가하는 번호를 주소로 매길 수 있다. 숫자 N이 주어졌을 때, 벌집의 중앙 1에서 N번 방까지 최소 개수의 방을 지나서 갈 때 몇 개의 방을 지나가는지(시작과 끝을 포함하여)를 계산하는 프로그램을 작성하시오. 예를 들면, 13까지는 3개, 58까지는 5개를 지난다.
입력
첫째 줄에 N(1 ≤ N ≤ 1,000,000,000)이 주어진다.
출력
입력으로 주어진 방까지 최소 개수의 방을 지나서 갈 때 몇 개의 방을 지나는지 출력한다.
예제 입력 1복사
13
예제 출력 1복사
3
정답코드
N = int(input())
first_interval = 1
answer = 1
while True:
if N == 1:
print(answer)
break
else:
last_interval = first_interval + 6 * answer
if N in range(first_interval, last_interval + 1):
answer += 1
print(answer)
break
else:
answer += 1
first_interval = last_interval
최소 개수의 방을 지나야한다.
그래서 나는 벌집 모양의 수들이 어떤 관계를 이루고 있는지 확인하였다.
확인한 결과 1 밑에 2번 그리고 시계 방향으로 수가 증가한다.
7에서 8로 넘어갈 때 회전하는 층이 바뀐다. 그림으로 설명하면 이렇다.
1 - 7 - 19 - 37 - ... 이런 식으로 간격이 6 X 1, 6 X 2, 6 X 3 ... 이렇게 증가하는 걸 확인할 수 있다.
그래서 구간을 1 ~ 7, 7 ~ 19, 19 ~ 37... 이런 식으로 잡을 수 있도록 변수를 설정해주었다.
코드 설명
1.
N = int(input())
first_interval = 1
answer = 1
N에는 구하려는 숫자를 입력한다.
그리고 처음에 있는 숫자방인 1을 first_interval로 잡아준다.
숫자방 1에 있을 때도 방을 거친 것이 되기 때문에 초기값을 answer = 1로 잡아준다.
2.
while True:
if N == 1:
print(answer)
break
else:
last_interval = first_interval + 6 * answer
if N in range(first_interval, last_interval + 1):
answer += 1
print(answer)
break
else:
answer += 1
first_interval = last_interval
N이 만약에 1이라면 그냥 출력할 수 있도록 한다.
그게 아니면 last_interval을 설정하여 거치는 방의 횟수를 구할 수 있도록 한다.
예를 들면 1 ~ 7의 범위 안에 숫자가 있는지 확인하고 있다면 방을 한번 더 거친 것이기 때문에
answer에 1을 더할 수 있도록 한다.
그러고 난 다음에 print(answer)을 한다.
1 ~ 7의 범위 안에 없다면 다음 범위로 넘어가야 하기 때문에 else 을 통해 다음 범위로 넘어갈 수 있도록 한다.
미국으로 유학간 동혁이는 세탁소를 운영하고 있다. 동혁이는 최근에 아르바이트로 고등학생 리암을 채용했다.
동혁이는 리암에게 실망했다.
리암은 거스름돈을 주는 것을 자꾸 실수한다.
심지어$0.5달러를 줘야하는 경우에 거스름돈으로$5달러를 주는것이다!
어쩔수 없이 뛰어난 코딩 실력을 발휘해 리암을 도와주는 프로그램을 작성하려고 하지만, 디아블로를 하느라 코딩할 시간이 없어서 이 문제를 읽고 있는 여러분이 대신 해주어야 한다.
거스름돈의 액수가 주어지면 리암이 줘야할 쿼터(Quarter,$0.25)의 개수, 다임(Dime,$0.10)의 개수, 니켈(Nickel,$0.05)의 개수, 페니(Penny,$0.01)의 개수를 구하는 프로그램을 작성하시오. 거스름돈은 항상$5.00 이하이고, 손님이 받는 동전의 개수를 최소로 하려고 한다. 예를 들어,$1.24를 거슬러 주어야 한다면, 손님은 4쿼터, 2다임, 0니켈, 4페니를 받게 된다.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 거스름돈 C를 나타내는 정수 하나로 이루어져 있다. C의 단위는 센트이다. (1달러 = 100센트) (1<=C<=500)
출력
각 테스트케이스에 대해 필요한 쿼터의 개수, 다임의 개수, 니켈의 개수, 페니의 개수를 공백으로 구분하여 출력한다.
예제 입력 1복사
3
124
25
194
예제 출력 1복사
4 2 0 4
1 0 0 0
7 1 1 4
내가 만든 정답 코드
T = int(input())
Q = 25
D = 10
N = 5
P = 1
Q_list = []
D_list = []
N_list = []
P_list = []
for i in range(T):
C = int(input())
Quarter = C // Q
Dime = (C - Quarter * Q) // D
Nickel = (C - Quarter * Q - Dime * D) // N
Penny = (C - Quarter * Q - Dime * D - Nickel * N) // P
Q_list.append(Quarter)
D_list.append(Dime)
N_list.append(Nickel)
P_list.append(Penny)
for i in range(T):
print(f"{Q_list[i]} {D_list[i]} {N_list[i]} {P_list[i]}")
다른 사람들의 코드
n = int(input())
for _ in range(n):
money = int(input())
for i in [25, 10, 5, 1]:
print(money//i, end=' ')
money = money%i
다른 사람들이 쓴 코드는 내가 일일이 복잡하게 모든 걸 쓴 코드에 비해 훨씬 간결하다.
여기서 보면 나는 25,10,5,1을 처음에 변수를 통해 설정해준 반면에 여기서는 리스트를 통해 반복문을 돌게 하여 나누도록 하였다. 내가 124에서 100을 빼고 20을 빼고 하는 식으로 코드를 짰는데 굳이 이렇게 안하고 124를 25로 나누고 10으로 나누고 각각 한 몫을 구해서 출력하도록 했으면 더 좋았을 것 같다.
사람들 말로는 이 문제가 전형적인 그리드 문제라고 한다.
그리드가 뭔지 몰라서 나는 찾아봤다.
그리디 알고리즘(욕심쟁이 알고리즘, Greedy Algorithm)이란 "매 선택에서지금 이 순간 당장 최적인 답을 선택하여 적합한 결과를 도출하자"라는 모토를 가지는알고리즘설계 기법이다.[1]