0. 오늘은 무엇을 했는가
오늘도 어제처럼 코드카타와 과제에 시간을 쏟았습니다.
아쉽게도 오늘은 코드 카타를 푸는 데 실패해서, 정답을 보고, 분석해서 다시 풀었습니다.
과제는 Lv. 3까지 완성했습니다.
1. 코드 카타
[ 09:00 ~ 12:00]
오늘의 코드 카타는 멀리 뛰기 였습니다.
효진이는 멀리 뛰기를 연습하고 있습니다. 효진이는 한번에 1칸, 또는 2칸을 뛸 수 있습니다. 칸이 총 4개 있을 때, 효진이는
(1칸, 1칸, 1칸, 1칸)
(1칸, 2칸, 1칸)
(1칸, 1칸, 2칸)
(2칸, 1칸, 1칸)
(2칸, 2칸)
의 5가지 방법으로 맨 끝 칸에 도달할 수 있습니다. 멀리뛰기에 사용될 칸의 수 n이 주어질 때, 효진이가 끝에 도달하는 방법이 몇 가지인지 알아내, 여기에 1234567를 나눈 나머지를 리턴하는 함수, solution을 완성하세요. 예를 들어 4가 입력된다면, 5를 return하면 됩니다.
이 문제를 봤을 때, 2가 n개일 때의 경우의 수를 계산해봤습니다.
예를 들어, 8이라면
8칸 가면 4
2 1개 - 1 6개 - 7 / 1
2 2개 - 1 4개 - 6 x 5 / 2 x 1
2 3개 - 1 2개 - 5 x 4 x 3 / 3 x 2 x 1
2 4개 - 1 0개 - 1개 4 x 3 x 2 x 1 / 4 x 3 x 2 x 1
이렇게 됩니다. 2가 0일 때는 무조건 1가지 경우의 수밖에 없으므로, 이 수를 다 더한 34가 정답입니다.
즉, 전체 합부터 -(2의 개수-1)까지 곱하고 2의 개수!로 나누면 된다고 생각했습니다.
식으로 만들면 2가 나올 수 있는 개수가 x개 일 때,
(1~x) + (n - 2(1~x))들의 곱 / x! 가 됩니다.
이 식을 그대로 대입했고, 테스트에서는 잘 적용이 됐지만, 문제는 제출이었습니다.
6개 정도만 맞고, 나머지 경우가 전부 런타임 에러나 실패가 떴습니다.
식 자체는 맞았지만, 곱할 때 % 1234567을 제대로 못 사용한 점과
곱셈과 나눗셈 둘 다 사용하다보니까 값이 많이 꼬였습니다.
다른 해결 방법을 찾지 못한 저는 포기하고, 정답을 보기로 했습니다.
근데 어디서 익숙한 놈이 나와서...

문제를 푸는 해법은 피보나치 수열이었습니다.
어째서 피보나치 수열이 나오게 됐을까요?
그건 매우 간단했습니다.
저처럼 경우의 수를 생각하지 않고, 1칸과 2칸 가는 걸 수열로 생각하신 분들이 존재했기 때문입니다.
우리가 n칸을 간다고 했을 때 이걸 계산하는 식을 f(n)이라고 해보자고요.
그러면, 1칸 가는 데는 f(1)이 나옵니다. 이 값은 1입니다.
2칸 가는 f(2) = 2입니다.
3칸 가는 f(3)은 1칸을 가고, 2칸을 가면 됩니다. 순서가 적용되기 때문에 그대로 f(1) + f(2)가 되면 됩니다.
즉, f(3) = f(1) + f(2)가 됩니다. 만약 n이 3이었다면? f(n) = f(n-2) + f(n-1)이 됩니다.
피보나치 수열이죠.
사실은 이렇게 안 풀고 그냥 연속돼 있는 3가지 경우의 수의 정답만 봤어도 설마 하고 풀었을 수도 있습니다.
8칸이 34고, 7칸이 21입니다. 만약 제가 6칸도 값을 구하고, 비교해봤다면, 바로 풀었을 수도 있습니다.
근데... 저는 다른 곳에 꽂혀서 그러지는 못했네요.
어제도 그렇고, 오늘도 그렇고, 제가 생각한 푸는 방식은 곱셈을 이용해서 복잡하게 만드는 반면,
다른 분들의 방식은 덧셈이나, 수열을 써서 풀어내는 방식이 많습니다.
이런 점을 고쳐야 할 것 같습니다. 특히, 어떠한 규칙을 풀어내는 게 중요한데, 여기서 다양한 방식을 적용해봐야 할 것 같습니다.
2. 개인 과제
[ 13:00 ~ 18:00 ]
오늘은 개인 과제를 Lv. 3 상속과 컬렉션까지 진행했습니다.
그리고 코드를 깔끔하게 만들기 위해 노력했습니다.
val menuMap: Map<String, List<CorrectMenu>> =
mapOf(
"MainMenu" to mutableListOf(
MainMenu("버거", "맛있는 버거",),
MainMenu("디저트", "감자튀김이랑 치즈스틱",),
MainMenu("음료", "시원한 음료",),
MainMenu("아이스크림", "자연산 우유로 만든 아이스크림",)
),
"Burger" to mutableListOf(
Burger("불고기 버거", 4700, "두툼한 쇠고기패티와 한국적인 맛의 소스가 잘 조화된 롯데리아 대표 버거",),
Burger("모짜렐라 인 더 버거", 7400, "자연산 모짜렐라 치즈와 고소한 베이컨이 만나 풍부한 맛의 버거",),
Burger("오징어 얼라이브 버거", 5500, "오징어가 살아있다! 오징어다리를 그대로 튀겨 낸 토핑과 쫄깃한 오징어패티로 극대화된 맛과 식감의 오징어버거",),
Burger("전주 비빔라이스 버거", 6900, "전주비빔밥을 담은 라이스번과 노른자가 터지는 반숙란,달콤한 고추장 소스가 어우러진 새로운 라이스 버거",),
Burger("새우 버거", 4700, "새우살을 가득넣어 더 맛있어진 오리지널 새우버거",),
),
"Dessert" to mutableListOf(
Dessert("감자 튀김",1800,"바로 튀겨낸 바삭바삭한 후렌치 포테이토",),
Dessert("양념 감자",2300,"시즈닝(어니언, 치즈, 칠리, 실비김치맛) 한가지를 선택해 뿌려먹는 포테이토",),
Dessert("치즈스틱",2400,"통모짜렐라치즈에 튀김옷을 입혀 만든 바삭하고 고소한 롯데리아 대표 디저트 메뉴",),
),
"Drink" to mutableListOf(
Drink("콜라",2000,"톡 쏘는 시원 상쾌한 콜라",),
Drink("사이다",2000,"톡 쏘는 시원 청량한 사이다",),
Drink("아이스 아메리카노",2500,"부드럽고 마일드한 바디감을 느낄 수 있는 롯데리아만의 ICE 아메리카노 (고카페인 함유) ※어린이,임산부,카페인 민감자는 섭취에 주의 바랍니다.",),
Drink("망고젤리쿨러",2900,"달콤한 망고와 상큼한 레몬의 맛의 청량감과 동시에 곤약젤리의 재밌는 식감까지 즐길 수 있는 비탄산 아이스 드링크",),
),
"IceCream" to mutableListOf(
IceCream("소프트콘",900,"부드러운 맛과 시원한 소프트 타입의 아이스콘 제품",),
IceCream("팥빙수",5500,"빙수팥과 후르츠칵테일이 풍성하게 토핑된 전형적인 팥빙수",),
IceCream("토네이도",2800,"부드러운 아이스크림에 맛있는 토핑을 넣어 만든 아이스크림",),
),
)
위처럼 Map으로 기존의 메뉴들을 정리했습니다.
Map으로 한 이유는, 객체에 맞는 값을 찾기 편하게 하기 위해서입니다.
fun main() {
var nowMenu: CorrectMenu = MainMenu()
while (true) {
showMenu(nowMenu)
val selectNum = selectNum(nowMenu)
if(selectNum == -1) break
var selectedMenu: CorrectMenu = nowMenu
if(nowMenu is MainMenu)
selectedMenu = selectMenu(selectNum)
else if(nowMenu is Food) selectedMenu = selectFood(nowMenu, selectNum)
nowMenu = selectedMenu
}
}
그리고 드디어 main의 양을 줄였습니다.
먼저, showMenu는 현재의 메뉴를 담은 변수인 nowMenu의 정보를 보여줍니다.
그리고, selectNum은 숫자를 입력받아서 nowMenu가 어떤 것이냐에 따라 결과를 다르게 합니다.
이건 나중에 다른 쪽으로 옮기는 방안도 생각 중입니다.
다음으로, 선택한 메뉴를 어떻게 처리할 것인지를 selectMenu 와 selectFood로 나눠서 진행합니다.
두 코드가 같이 있으니까 너무 어지러워서 나눴습니다.
selectMenu는 메인 메뉴일 때, 어느 메뉴로 갈지 정하고, selectFood는 음식 고르는 메뉴일 때,
그 음식과 관련된 기능을 합니다. 해당 기능은 아직은 미구현입니다.
마지막으로, 현재 메뉴를 선택된 메뉴로 바꿉니다. selectMenu는 메인 메뉴이므로, 고른 숫자에 따라 메뉴가 바뀝니다.
selectFood는 돌아가기로, 메인 메뉴로 돌아갈 수 있습니다.
그리고 객체 구성은 Menu가 가장 상위의 인터페이스로 존재하고, 이를 받는 CorrectMenu와 WrongMenu가 존재합니다.
WrongMenu는 잘못된 메뉴 선택 시 만들어두긴 했는데, 나중에 삭제할 수도 있을 것 같습니다.
3. 끝
이렇게 해서 오늘 하루도 어느 정도 끝났습니다.
아마도 Lv. 4까지 어느 정도는 끝내놓을 것 같은데, 만약 끝나면 수정해서, 4번에 추가하겠습니다.
끝.