knapsacka 문제와 LCS 문제.
팀원분이 내가 설명했던 부분의 로직이
구현했더니 생각대로 되지 않아
다시 확인하고, 솔루션 보고, 이해하느라 시간이 걸리셨다며
이렇게 되면 코어타임을 미리 했던 게 의미가 없지 않겠느냐고
얘기해주셨다...
내가 권유했던 코어타임이고,
내가 맡은 설명 부분이라
스스로가 잘 했던 일인지 반문하게 되어 괴로웠는데,
비록 여태까지 내가 생각했던
키워드 코어타임은
개념을 다 같이 모르는 사이니 대강 이해하고
틀린 게 있으면 그 때 고쳐주자... 정도의
구현까지를 생각하지 못한 코어타임이었는데
생각해보니 사실 그 정도는
검색하고 블로그를 쭉 보면
대강 이해할 수 있는 사실인 것도 맞고
오히려 블로그를 보았을 떄
로직이 더 논리정연하게 설명된 것도 사실이다...
그러고보니 저번주에도
내가 맡은 부분을 설명했을 때
자료의 구체적인 예시값이 없었기에
추상적으로 진행했던 점이 없잖아 있었다.
코어 타임을 시켜서 한 건 아니냐는 의문에
조금 놀랐는데(열심히 했으니까)
시켜서 한 거야 뭐...
맞긴 맞으니까....
물론 적극적으로... 필요성을 느껴서 하긴 했지만...
반추해보면 그냥 서로가 했던 내용 재확인에
불과한 건 아니었는가... 고민하게 되었는데
사람마다 진도가 달랐기에
어떤 분은 서로가 했던 내용의 재확인이 필요했고,
그걸 또 자기 말로 설명하는 과정이 필요했지만,
사실....??
설명하는 쪽은 정말로(그러니까 충분히 알고 있다고 생각하는 사람은)
다른 사람이 모두 이해가 가도록 로직을 설명하는 것 역시
맡은 바인 것 같고,
팀원분이 그 로직을 바로 그때그떄 자리에서 확인해주고
그거 들은 대로 구현을 해보실 수 있는 분이라 생긴 경우인 것 같은데?
확실히 실제로는 개념을 이해했는지 되묻는 과정보다는
내가 진행하고 싶은 바, 우리가 진행할 바를
논리정연하게 설명하는 게 정말 필요한 역량이 아닌가,
또 회의를 단순히 할 게 아니라
실효성 있는 회의를 추구하는 것 또한 필요한 일이라는 생각이 들었다.
그래서 정말..꽤...놀랐고...충격도 받았지만
다음에는 팀원들과 무작정 코어타임 하자! 라고 하고
이런 식으로 진행하자, 만 얘기할 게 아니라
코어타임에서 각자 무엇을 추구하는지,(목적 확인)
어디까지 할 수 있는지,(자신의 역량 소개)
어디까지 하고 싶은지,(의욕 정도)
를 얘기를 나누는 과정이 사전에 필요하겠다 싶었다.
맞아...
대개 애로사항을 들었을 때는
'사전에 공지된 것과 다르다' 였으니까
이것도 넓게 보면 그런게 아닐까 싶다.
그리고 나도 로직적으로 명료하게
설명을 가다듬고 예시와 단계적으로 설명하는 법을 익혀야겠다!
CSAPP 3.7 코어. 이후 그리디 알고리즘 난이도 하 문제 얘기.
이전 코어타임 생각한 바 얘기.
G님은 3.4까지 읽으셨고, J님은 3.7을 읽으심.
나는 3.7을 정리하던 중.
J님이 설명해주심.
프로시저는
예를 들어 파이썬에서,
def (함수명) ...
...(실행 코드)
return
이 전체적인 구성을 프로시저라고 칭하는 것 같다.
그래서 이러한
함수의 호출 순서를
시스템 스택에서 관리한다.
특히 여기서 살펴보는 것은
프로시저 P가 프로시저 Q를 호출하는 과정인데
프로시저 P를 진행하다가,
프로시저 P가 프로시저 Q를 호출하면,
그때 프로시저 Q를 호출한 시점을,
스택에 return address를 푸시하고,
그 아래에 Q를 푸시해서 순차적으로 진행하여
어차피 Q가 다 없어졌으므로
마지막으로 리턴 주소 자리에 돌아가기때문에,
실행 시점으로 돌아간다.
스택에서의 포인터가 주목할만한 점인 것 같다...
그 외에는,
이 스택이 특이한 점이,
P가 Q에게 값을 넘길때나,
써야하는 값이 있을 때,
프로시저 Q는 쓸수있는, 이미 할당받은 저장소의 크기가 정해져있기 때문에,
만약에 더 필요하면,
프로시저 P가 그때마다 새로 저장소를 할당해주는데,
그걸 어떤 크기를 준다기보다는,
레지스터의 주소를 스택에 저장해서 쓰는 방식으로 한 게 인상깊었다.
여기서 잠시
기존 스택 포인터가 있고,
ret이라는 포인터가 리턴 시 있는 것 같은데
확실하진 않고 자신의 생각이라고 하셔서,
내가 ret은...
call에 대치되는 명령어가 아닌가? 라고 했더니
call만 되고 ret이 오지 않는 경우가 있다고 하셨다.
이 과정에서 포인터 재설정을
설명하는데에 잠시 꼬였었다가
아무튼 둘다 같이 이해하고 있다는 것을 확인하고
내가 ret은 아마 return address 를 처리하는
명령어의 일종인 것 같다, 라고 의문을 제기하자
J님이 return address를
호출하지만 생성하지 않는 경우를 문제에서 말했던 것 같다고 해주셨다.
그 외에는
스택 프레임에서
파라미터들이 저장된 모습을 봤는데,
J님이 무엇을 말하는지 의문을 가지시자,
내가 아마 데이터의 크기에 따라 배치한게 아닐까
를 얘기하자
진우님이 아 그래서 포인터는 따로 저장했나보다
라고 이해해주셨다...
그렇게 한 차례 지나가고
J님이 뭔가 더 하고 싶거나? 확인하고 싶은게 있는지 여쭤보셨고,
내가 마지막으로 한번더
주요하게 볼만한건 말씀하신대로
프로시저가 서로 호출하는 모양,
대표적으로 나오는 명령어 call, ret의
인스트럭션이 어떻게 되어있는지,
데이터 이동 시 레지스터는 어떻게 할당되고 저장되는지,
뭐 그런걸 보면 좋을 거같다, 라고 하시고
G님이 프로시저가 뭔지 잘 모르겠다고 하시자
J님이 그냥 파이썬의 그 일련의 코드와 같은 거다, 추상화다, 라고 하셔서
내가 나눠진 연산을 하나의 연산처럼 이해하기 좋게 정렬한 추상화가 말씀하신대로 맞다...
라고 했다..
.....
그리고 마무리에
혹 G님이 읽지 않고 합류하셨어서
얼마나 이해하셨는지 물어보자
알것같지만 설명할 정도는 아닌거같다 라고 해주셔서
큰 틀도 괜찮다고 했지만 자신이 없어하셔서
월요일 오전에 할 책 코어타임에
G님이 3.7을 한번 더 설명해주시기로 하셨다.
그리고
문제..
J님과 G님은 이미 보셨는지(아마 보기로 합의했던거같다,
나는 시점을 잘 모르겠어서 아직 안 봤었고
이전 코어타임을 정리하는데 시간이 좀 걸렸다.)
문제를 설명해주시고
문제 풀이 알고리즘을
가볍게 얘기했다.
동전0.
동전 가짓수를 줄테니
동전을 적절히 사용해서, 가치 합을 k로 만드는데,
이때 필요한 동전 개수의 최솟값을 구하는 것인데,
단순히 그리디로 하면
순서대로 가장 큰 값만 집을 경우,
그보다 작은 값으로 했을 때
쓰는 동전의 가짓수가 적은 경우가 존재할 수 있기때문에,
동전을 고르는 방법을,
(현재 값 - 고른 동전값) 으로 뺀 값을
가진 동전의 종류로 전부 몫과 나머지를 구한다.
그래서 그 몫과 나머지의 합이
가장 작은 것을 고르는 방식으로 하는 것이다!
(잘 나누어떨어질 경우,
경우의 수를 적게 쓴다는 것이므로.)
그러다 G님이 문제를 좀 보고싶다고 하셔서
봤는데, 조건으로
주어지는 동전이 앞의 동전의 배수라는 조건을 찾아내셔서,
그래서 아마 J님이 걱정하신 상황은 일어나지 않을 거같다...
라고 해주셔서 그리디로 그대로 해도 된다는 사실을 알아내었다...
잃어버린 괄호.
주어진 수에서,
+, -를 넣은뒤,
어디에 괄호를 넣어야 가장 작은 값을 나오는지 구하는 것인데,
앞부터 순차적으로 -가 있는지 찾아서,
-뒤에 있는 부분에서 괄호를 치면,
최솟값이 나오지 않을까, 라고 얘기해주셨다.
(오!)
그리고 ...
많이 진행을 못 한 이유와
코어타임의 방향성에 영감을 많이 받았다,
여태까지와 많이 달라서 그랬다,
스스로도 코어타임의 실효성에 대해 생각해봤다...
서로 처음에 의견을 조율하는게 확실히 좋을거같다,
라고해서 팀원분이 좀 머쓱해하셨지만(아마도)
잘...된....거..맞나?
그래서 팀원분이괜찮으셨는지 확인하고
코어타임 일정을 조율한 뒤
나가서 편의점 들렀다 산책하고
나만무 어떻게 되는건가 얘기를 하다가
돌아왔다..