원래는 스마트컴포저보다 커서가 폴더 구조를 재구성하는 데 성능이 좋다길래, 커서로 폴더구조를 개편해보려 했었다. 그런데, 폴더 하위에 있는 노트를 일부만 읽거나 전혀 읽지 못하는 문제가 있었고 당최 왜 그런지 알 수가 없어서, 내가 또 설정을 이상하게 했다보다하고(자주 있는 일임!) 다른 걸 해 보기로 했다.
한국어 메뉴 스크린샷
커서로 뭘 할 수 있는지조차 아직 파악이 안 된 상태라, 이리저리 찾아보니 상상러님이 말만 했는데 PRD를 짜 줬다는 글이 눈에 띄었다. 나는 전부터 백일몽같은 아이디어를 옵시디언에 적어 놓곤 했는데, 그 중에 생각을 데이터처럼 간주해서 시각화하면 좋겠다는 것이 있었다. 그래서 그 중 일부를 시도해 보기로 했다.
진행 방법
어떤 도구를 사용했고, 어떻게 활용하셨나요?
Tip: 사용한 프롬프트 전문을 꼭 포함하고, 내용을 짧게 소개해 주세요.
Tip: 활용 이미지나 캡처 화면을 꼭 남겨주세요.
Tip: 코드 전문은 코드블록에 감싸서 작성해주세요. ( / 을 눌러 '코드 블록'을 선택)
1차. 커서 - 실패. 이상한 결과 나옴
[프롬프트]
1) 파이썬으로 a* 알고리즘을 시각화하는 것을 구현할 수 있어?
2) 할 일을 계획할 때 a* 알고리즘을 적용하여 시각화하는 MVP를 만들고 싶어. 최종 목적이 '프로그래밍','디자인','PM' 3가지가 있고, 이 각각에 이르는 최적 경로를 찾아가는 것을 a* 알고리즘으로 시각화해 줘. node들은 과목으로 하고 y축은 스킬 수준으로 해 줘
코드를 보여주는 컴퓨터 화면의 스크린샷
산술 위험의 확률을 보여주는 그래프
2차. 클로드 - good! 그런데 나는 파이썬으로 하는 것이 궁금했다.
[프롬프트]
할 일을 계획할 때 a* 알고리즘을 적용하여 시각화하는 MVP를 만들고 싶어. 최종 목적이 '프로그래밍','디자인','PM' 3가지가 있고, 이 각각에 이르는 최적 경로를 찾아가는 것을 a* 알고리즘으로 시각화해 줘. node들은 과목으로 하고 y축은 스킬 수준으로 해 줘
3차. 커서 - 사실은 3차가 아니고 어제 한 것인데, 복원이 안된다 ㅠㅠ 중간에 하도 수정을 많이 했어서, 정확한 프롬프트가 뭔지 모르겠음. 원래 생각한 모양에 가까운 것임
from queue import PriorityQueue
from dataclasses import dataclass
from typing import List, Dict
import math
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
# 폰트 설정 부분 수정
try:
plt.rcParams['font.family'] = 'Malgun Gothic' # 윈도우
except:
try:
plt.rcParams['font.family'] = 'AppleGothic' # macOS
except:
print("사용 가능한 기본 폰트를 사용합니다.")
plt.rcParams['axes.unicode_minus'] = False
@dataclass(order=True)
class Task:
priority: float # f 비용
id: str
name: str
effort: float # 작업에 필요한 노력/시간
skills_gained: Dict[str, float] # 획득할 수 있는 스킬과 수준
prerequisites: List[str] # 선행 작업 ID 목록
class TaskOptimizer:
def __init__(self, final_goal: Dict[str, float]):
self.tasks = {} # id -> Task
self.final_goal = final_goal # 목표로 하는 스킬과 수준
def add_task(self, task: Task):
"""새로운 작업 추가"""
self.tasks[task.id] = task
def calculate_distance_to_goal(self, current_skills: Dict[str, float]) -> float:
"""현재 스킬 상태와 목표 간의 거리 계산"""
distance = 0
for skill, target_level in self.final_goal.items():
current_level = current_skills.get(skill, 0)
distance += math.pow(target_level - current_level, 2)
return math.sqrt(distance)
def merge_skills(self, skills1: Dict[str, float], skills2: Dict[str, float]) -> Dict[str, float]:
"""두 스킬 세트 병합"""
result = skills1.copy()
for skill, level in skills2.items():
result[skill] = max(result.get(skill, 0), level)
return result
def find_optimal_path(self, start_skills: Dict[str, float]) -> List[Task]:
"""A* 알고리즘을 사용하여 최적 작업 경로 찾기"""
initial_state = (self.calculate_distance_to_goal(start_skills), 0, start_skills, [])
frontier = PriorityQueue()
frontier.put(initial_state)
while not frontier.empty():
current = frontier.get()
_, current_cost, current_skills, path = current
# 목표에 충분히 근접했는지 확인
if self.calculate_distance_to_goal(current_skills) < 0.1:
return path
# 가능한 모든 다음 작업 탐색
for task_id, task in self.tasks.items():
# 이미 수행한 작업은 건너뛰기
if task_id in [t.id for t in path]:
continue
# 선행 작업 확인
prereqs_met = all(prereq_id in [t.id for t in path] for prereq_id in task.prerequisites)
if not prereqs_met:
continue
# 새로운 상태 계산
new_skills = self.merge_skills(current_skills, task.skills_gained)
new_cost = current_cost + task.effort
new_path = path + [task] # 여기에 Task 객체가 포함됨
# 휴리스틱: 현재까지의 비용 + 목표까지의 예상 거리
priority = new_cost + self.calculate_distance_to_goal(new_skills)
# 새로운 상태를 frontier에 추가
new_state = (priority, new_cost, new_skills, new_path)
frontier.put(new_state)
return [] # 경로를 찾지 못한 경우, 빈 리스트 반환
def visualize_path(self, optimal_path: List[Task], start_skills: Dict[str, float]):
"""최적 경로와 스킬 발전을 시각화"""
plt.figure(figsize=(12, 6))
# 스킬 발전 과정 시각화
skills = list(self.final_goal.keys())
current_skills = start_skills.copy()
skill_progress = [current_skills.copy()]
# 각 작업 후의 스킬 상태 계산
for task in optimal_path:
current_skills = self.merge_skills(current_skills, task.skills_gained)
skill_progress.append(current_skills.copy())
# 그래프 그리기
x = range(len(skill_progress))
for skill in skills:
y = [progress.get(skill, 0) for progress in skill_progress]
plt.plot(x, y, 'o-', label=skill, linewidth=2, markersize=8)
# 작업 이름 표시
task_names = ['시작'] + [task.name for task in optimal_path]
plt.xticks(range(len(task_names)), task_names, rotation=45, ha='right')
plt.grid(True)
plt.xlabel('작업 진행')
plt.ylabel('스킬 레벨')
plt.title('최적 경로에 따른 스킬 발전 과정')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
# 목표 스킬 레벨 표시
for skill in skills:
plt.axhline(y=self.final_goal[skill],
color='gray',
linestyle='--',
alpha=0.5,
label=f'{skill} 목표')
plt.tight_layout()
plt.show()
def main():
# 최종 목표 정의
final_goal = {
"프로그래밍": 0.8,
"디자인": 0.6,
"PM": 0.7
}
# 옵티마이저 초기화
optimizer = TaskOptimizer(final_goal)
# 샘플 작업들 추가
tasks = [
Task(priority=0, id="A", name="기초 프로그래밍 학습",
effort=2.0,
skills_gained={"프로그래밍": 0.3},
prerequisites=[]),
Task(priority=0, id="B", name="UI 디자인 기초",
effort=1.5,
skills_gained={"디자인": 0.4},
prerequisites=[]),
Task(priority=0, id="C", name="프로젝트 기획 연습",
effort=1.0,
skills_gained={"PM": 0.3},
prerequisites=[]),
Task(priority=0, id="D", name="중급 프로그래밍 프로젝트",
effort=3.0,
skills_gained={"프로그래밍": 0.6, "PM": 0.2},
prerequisites=["A"]),
Task(priority=0, id="E", name="디자인 심화 학습",
effort=2.0,
skills_gained={"디자인": 0.6},
prerequisites=["B"]),
Task(priority=0, id="F", name="종합 프로젝트",
effort=4.0,
skills_gained={"프로그래밍": 0.8, "디자인": 0.3, "PM": 0.7},
prerequisites=["A", "C"])
]
for task in tasks:
optimizer.add_task(task)
# 현재 스킬 상태에서 시작
current_skills = {
"프로그래밍": 0.1,
"디자인": 0.1,
"PM": 0.1
}
# 최적 경로 찾기
optimal_path = optimizer.find_optimal_path(current_skills)
# 결과 출력
print("최적 작업 경로:")
total_effort = 0
for i, task in enumerate(optimal_path, 1):
print(f"{i}. {task.name} (소요 시간: {task.effort})")
total_effort += task.effort
print(f"\n총 소요 시간: {total_effort}")
# 시각화
optimizer.visualize_path(optimal_path, current_skills)
if __name__ == "__main__":
main()
한국의 성장을 보여주는 그래프 한국 한국 한국 한국 한국
결과와 배운 점
배운 점과 나만의 꿀팁을 알려주세요.
실패담도 괜찮아요. 시행착오나 도움이 필요한 부분이 있나요?
앞으로의 계획이 있다면 들려주세요.
배운 점은 예상보다 적은 단서로 복잡해 보이는 것을 잘 구현한다는 점. 그래서 생각의 시각화를 커서의 도움을 받아 계속 시도해 볼 수 있겠다 싶었다.
그런데, 위 사례처럼 수 차례 수정을 반복하면서 결과를 만들 때, 맥락에 영향을 받기 때문에 복원 가능한 프롬프트를 신중히 만들어야겠다는 것을 절감했다. 아! 어젠 분명히 잘 됬었는데...