# 동료도움 방법 + 예시
## 방법
* 동료의 답안에서 틀린부분을 찾아 코멘트를 적어줍니다.
+ 각 설명은 이와 같이 + 항목으로 적어주세요.
* 코드가 틀렸다고 해서 옳은 답을 뭉터기로 적어주지 말고, 틀린 코드가 왜
틀렸는지, 그리고 어디를 고치면 옳게 될지 알려줍니다.
* 코드 줄을 지칭하여 코멘트가 필요한 경우, 다음과 같이
[함수이름:줄번호.코멘트] 형식으로 나타내주세요.
foo:n. foo함수의 n번째 줄에 대한 코멘트
foo:n-m. foo함수의 n번째에서 m번째 줄까지의 코멘트
foo:-n. foo함수의 뒤에서 n번째 줄에 대한 코멘트
foo:-n-m. foo함수의 뒤에서 n번째 줄에서 뒤에서 m번째 줄까지의 코멘트
예를 들어,
(define (abs x)
(if (< 0 x)
y
(- 0 x)))
와 같은 코드의 경우 y에 대한 코멘트를 하고 싶을 때,
abs:3. y에 대한 코멘트
와 같이 하면 됩니다.
## 예시
### 문제 1
; gcd: greatest common divisor
; 두 수 lhs, rhs의 gcd는 (lhs-rhs), rhs의 gcd와 같다.
; 참고: Euclidean division
(define (gcd x y)
(gcd (- x y) y))
다음은 도움 예시입니다.
+ 코드에 Euclidean 호제법의 아이디어가 녹아있음.
+ 하지만 끝나지 않는 케이스 존재함.
예를 들어 (gcd 3 0)은 (gcd 3 0) 자기 자신을 부름.
+ gcd:2. (- x y)를 계산하기 전에 x가 y보다 큰지 확인해야 함.
만일 그렇지 않다면 (gcd y x)를 부르도록 고쳐야함.
+ 또한 y가 0이라면 x를 답으로 반환해야 함.
+ 코드가 무엇을 하는지, 그리고 어떤 원리에 입각해 작성되었는지 모두 잘
드러나 있음.
### 문제 2
(define (t2 n)
(define (absolute x) ; function to calculate absolute value of input
(if (equal? 0 x)
0
(if (< 0 x) x (- 0 x))))
(define (s n) ; define number depend on n
(if (> n 0)
(string-append (s (- n 1)) "1") ; if n is bigger than 0, append n number of 1
(string-append "0") ; if n is smaller than 0, append 0 to string(start of string)
)
)
(if (or (equal? n 0) (equal? (absolute n) 1))
(if (equal? n 0) "0" "001") ; if n is 0 or 1, make string manually
(string-append (t2 (- (absolute n) 1)) (s (absolute n))) ; append strings start from 001 if n is bigger than 0
)
)
다음은 도움 예시입니다.
+ 제공된 모든 테스트 케이스에서 올바르게 동작함.
+ 주어진 문제(t2)를 해결하기 위해 작은 문제들(절대값 absolute와 숫자
하나에 대한 문자열을 만드는 s)을 이용했다는 아이디어가 명확히 드러나
있음.
+ 각 함수에도 적절한 주석이 달려 있어 무슨 일을 하는 함수인지 쉽게 알
수 있음.
+ 그러나 함수 s에 대한 주석이 조금 부족. 예제가 있었다면 더 좋았을
것.
### 문제 3
;(lst n m) defines a number of nth row and mth column in pascal triangle
(define (lst n m)
(if (= m 1) 1
(if (= n m) 1
(+ (lst (- n 1) (- m 1)) (lst (- n 1) m)))))
;(row x) prints a number from xth row
(define (row x)
(let rec ((k 2) (row (string #\1)))
(if (= x 1) row
(if (= x k) (string-append (string #\1) row)
(rec (+ k 1) (string-append (number->string (lst x k)) row))))))
(define (yanghui n)
(if (< n 0) (yanghui (* n -1))
(if (= n 0) (void)
(let rec ((f 2) (yanghui (string #\1)))
(if (= n 1) yanghui
(if (= n (- f 1)) yanghui
(rec (+ f 1) (string-append yanghui (row f)))))))))
다음은 도움 예시입니다.
+ 인자가 0인 경우를 제외하고는 모두 올바른 결과를 출력함. 인자가 0인
경우 (void)를 실행하여 아무 출력도 하지 않음.
+ yanghui:3. 빈문자열을 출력하도록 (void)를 빈 문자열 ""로 수정해야
함.
+ 각 보조함수가 하는 일을 잘 설명하고 있음.
+ if문을 중첩해서 사용하기 보다는 cond명령을 사용하는 것이 더 깔끔함.
yanghui:2-7. (cond ((< n 0) (yanghui (* n -1)))
((= n 0) (void))
(else ...))
### 문제 4
(define (digit n) ; this function convert the '+', '-', '0' to 1, -1 0
(if (equal? '+ n)
1
(if (equal? '- n)
-1
(if (equal? '0 n)
0
"Wrong input"))))
(define (crazy2val n)
(if (null? n)
null
(if (equal? (cdr n) '()) ; If only one element is remained in the list, (cdr n) returns '()
(digit (car n))
(+ (digit (car n)) (* 2 (crazy2val (cdr n)))))))
; by the recursive function, the binary number is converted to the decimal.
다음은 도움 예시입니다.
+ digit가 기대하는 인자의 타입이 틀림.
digit 함수는 '+, '-, '0을 1, -1, 0으로 변환하는 함수인데,
문제에서 기대하는 입력은 'p, 'n, 'z임.
+ digit:2. '+을 'p로 바꾸어야 함.
+ crazy2val가 기대하는 인자의 타입이 틀림.
정의된 함수는 인자로 'z, 'n, 'p를 원소로 가지는 리스트를 기대하고 있는데,
문제에서 제시된 인자는 예를 들면 'z, 'n, 'p, (cons 'z 'n)와 같은 값임.
+ 예를 들어, (crazy2val 'z)를 실행하면 0을 출력해야 하지만 정의된
함수는 다음과 같은 에러를 냄:
cdr: contract violation
expected: pair?
given: 'n
+ crazy2val:2. null? 대신 pair?를 사용해야 함.
+ crazy2val:2-6. 입력 타입에 맞게 수정해야 함.
+ 코멘트로 각 함수가 하는 일을 잘 설명하고 있음.
### 문제 5
(define (crazy2add lhs rhs)
(add lhs rhs 0)
)
(define (add lhs rhs m)
(if(and (null? lhs)(null? rhs))
(if(equal? 0 m)
'z
(if(equal? 1 m)
'p
'n))
(if(or (symbol? lhs)(null? lhs))
(if (or (symbol? rhs)(null? rhs))
(if (equal? 0 (+ m (+ (char lhs) (char rhs))))
'z
(if (equal? 1 (+ m (+ (char lhs) (char rhs))))
'p
(if(equal? 2 (+ m (+ (char lhs) (char rhs))))
(cons 'z (add null null 1))
(if(equal? 3 (+ m (+ (char lhs) (char rhs))))
(cons 'p (add null null 1))
(if(equal? -1(+ m (+ (char lhs) (char rhs))))
'n
(if(equal? -2(+ m (+ (char lhs) (char rhs))))
(cons 'z (add null null -1))
(cons 'n (add null null -1))
))))))
(symsum lhs rhs m))
(if(or (symbol? rhs)(null? rhs))
(symsum rhs lhs m)
(sum lhs rhs m)))))
(define (symsum lhs rhs m)
(if (equal? 0 (+ m (+ (char lhs) (char (car rhs)))))
(cons 'z (add null (cdr rhs) 0))
(if (equal? 1 (+ m (+ (char lhs) (char (car rhs)))))
(cons 'p (add null (cdr rhs) 0))
(if (equal? 2 (+ m (+ (char lhs) (char (car rhs)))))
(cons 'z (add null (cdr rhs) 1))
(if(equal? 3 (+ m (char lhs) (char (car rhs))))
(cons 'p (add null (cdr rhs) 1))
(if (equal? -1 (+ m (+ (char lhs) (char (car rhs)))))
(cons 'n (add null (cdr rhs) 0))
(if (equal? -2 (+ m (+ (char lhs) (char (car rhs)))))
(cons 'z (add null (cdr rhs) -1))
(cons 'n (add null (cdr rhs) -1)))))))))
(define (sum lhs rhs m)
(if (equal? 0 (+ m (+ (char (car lhs)) (char (car rhs)))))
(cons 'z (add (cdr lhs) (cdr rhs) 0))
(if (equal? 1 (+ m (+ (char (car lhs)) (char (car rhs)))))
(cons 'p (add (cdr lhs) (cdr rhs) 0))
(if (equal? 2 (+ m (+ (char (car lhs)) (char (car rhs)))))
(cons 'z (add (cdr lhs) (cdr rhs) 1))
(if(equal? 3 (+ m (+ (char (car lhs))(char (car rhs)))))
(cons 'p (add (cdr lhs) (cdr rhs) 1))
(if (equal? -1 (+ m (+ (char (car lhs)) (char (car rhs)))))
(cons 'n (add (cdr lhs) (cdr rhs) 0))
(if(equal? -2 (+ m (+ (char (car lhs))(char (car rhs)))))
(cons 'z (add (cdr lhs) (cdr rhs) -1))
(cons 'n (add (cdr lhs) (cdr rhs) -1)))))))))
(define (char lst)
(if(equal? lst null)
0
(if(equal? lst 'z)
0
(if(equal? lst 'p)
1
-1))))
다음은 도움 예시입니다.
+ 제공된 모든 테스트 케이스에서 올바르게 동작함.
+ 큰 문제(crazy2add)를 작은 문제들(add, sum, char)로 나눠서 풀었다는
아이디어가 명확히 드러나 있음.
+ 함수 sum과 add는 설명이 없으면 무엇을 하는 함수인지 알아보기가 힘듦.
각 함수가 어떤 목적을 가지고 있는지, 그리고 왜 동작하는지에 관한
설명이 있었으면 좋았을 듯.