트랙
/
Factor
Factor
/
연습 문제
/
자동차, 조립하자!
자동차, 조립하자!

자동차, 조립하자!

학습 연습 문제

소개

이번 연습 문제에서는 조건문을 소개해요. 조건문은 값에 따라 둘 이상의 행동 중에서 하나를 고르는 거예요. Annalyn's Infiltration에서 만난 불리언과 Currency Conversion에서 다룬 정수 연산을 바탕으로 해요.

비교 단어

이 단어들은 모두 math에 있어요 (=는 kernel에 있고요):

=  ( x y -- ? )    ! equal
<  ( x y -- ? )    ! less than
<= ( x y -- ? )    ! less than or equal
>  ( x y -- ? )    ! greater than
>= ( x y -- ? )    ! greater than or equal
3 3 = .     ! => t
2 3 < .     ! => t
3 3 <= .    ! => t
3 4 = not . ! => t    (inequality: combine = with not)

zero?는 (math에 있어요) 흔히 쓰는 0 = 검사를 줄여 놓은 거예요. 숫자를 소비하고 그 숫자가 0이었는지 여부를 푸시해요:

zero? ( n -- ? )    ! t when n is 0

범위 검사

between?는 (math.order에 있어요) 어떤 값이 양 끝을 포함하는 범위 안에 들어가는지 검사해요. 어떤 행동이 숫자가 어느 구간에 속하는지에 따라 달라질 때 유용해요:

between? ( x lo hi -- ? )    ! lo <= x <= hi (inclusive)
5 1 10 between? .    ! => t
0 1 10 between? .    ! => f
10 1 10 between? .   ! => t   (inclusive at both ends)

값 하나가 아니라 범위로 분기를 고를 때 cond의 조건식으로 dup 1 4 between?처럼 쓰이는 걸 자주 보게 될 거예요.

쿼테이션

위의 비교 단어들은 불리언을 만들어내요. 불리언에 따라 행동하려면 조건문에 쿼테이션을 하나 이상 넘겨줘요. 쿼테이션은 대괄호 [ ... ]로 감싼 코드 조각이에요. 쿼테이션을 쓰면 코드가 실행되는 대신 값으로서 스택에 푸시돼요. 그러면 if 같은 단어가 어느 쿼테이션을 실행할지 정해요.

[ neg ]   ! a quotation that negates the top of the stack
[ ]       ! the empty quotation — does nothing

쿼테이션은 뒤에 나오는 연습 문제에서 자세히 다뤄요. 지금은 [ ... ]를 "이 분기에서 실행할 코드"로 읽으면 돼요.

if, when, unless

if는 (kernel에 있어요) 불리언과 쿼테이션 두 개를 받아요. 불리언이 참이면 첫 번째 쿼테이션을, 거짓이면 두 번째 쿼테이션을 실행해요:

if ( ? then-quot else-quot -- )
: abs ( x -- y ) dup 0 < [ neg ] [ ] if ;

when은 불리언이 참일 때만 쿼테이션을 실행하고, unless는 거짓일 때만 실행해요:

when   ( ? quot -- )
unless ( ? quot -- )

if*, when*, unless*

커널에 있는 이 세 가지 변형은 불리언이 참일 때 그 불리언을 값으로서 남겨 둬요. 어떤 단어가 "그 값, 아니면 f"를 반환할 때 유용해요:

if*     ( ? true false -- )    ! truthy: true is called WITH ? on stack
when*   ( ? true       -- )    ! truthy: true is called WITH ? on stack
unless* ( ? false      -- )    ! falsy: false runs and pushes a default

if*는 두 갈래 형태예요. 참일 때 실행되는 갈래는 값이 스택에 남아 있는 채로 호출되고, 거짓일 때 실행되는 갈래는 값 없이 호출돼요:

42 [ ] [ "nothing" ] if* .   ! prints 42
f  [ ] [ "nothing" ] if* .   ! prints "nothing"

unless*는 "값 또는 기본값"을 나타내는 대표적인 관용구예요. 값이 참이면 그대로 두고, f이면 값을 버리고 쿼테이션을 실행해서 대체할 값을 푸시해요:

"hello" [ "anonymous" ] unless* .   ! => "hello"
f       [ "anonymous" ] unless* .   ! => "anonymous"

when*는 if*의 한 갈래 형태예요. 값이 참일 때만 값이 스택에 남아 있는 채로 쿼테이션을 실행하고, 값이 f이면 그냥 버려요. "그 값, 아니면 f"라는 결과를 f인 경우를 굳이 처리하지 않고 누적 값에 합쳐 넣고 싶을 때 쓰면 돼요:

0 41 [ + ] when* .   ! => 41   (truthy: 41 added to the running total)
0 f  [ + ] when* .   ! => 0    (falsy: f dropped, total left untouched)

cond

여러 대안 중에서 골라야 할 때는 combinators에 있는 cond가 딱 맞아요. { predicate body } 형태의 쌍으로 이루어진 배열을 받아서, 참을 만들어내는 첫 번째 조건의 본문을 실행해요:

USING: combinators ;

: classify ( n -- label )
    {
        { [ dup 0 <  ] [ drop "negative" ] }
        { [ dup 0 =  ] [ drop "zero"     ] }
        [ drop "positive" ]
    } cond ;

몇 가지 눈여겨볼 점이 있어요:

  • 쌍은 순서대로 검사하고, 처음 맞는 것이 선택돼요.
  • 맨 끝에 조건 없이 쿼테이션 하나만 있는 항목은 기본값 역할을 해요.
  • 각 조건은 입력을 살펴보되 데이터 스택은 원래 있던 그대로 남겨 둬야 해요. 보통 dup ... <test> 형태를 써요.
  • 선택된 쌍의 본문은 조건이 봤던 것과 같은 스택을 받아요. 그래서 보통 입력을 drop한 뒤 결과를 푸시하는 것으로 시작해요.

지침

이 연습 문제에서는 자동차 공장 조립 라인의 생산량을 분석하는 코드를 작성해요. 조립 라인의 속도는 0(꺼짐)부터 10(최대)까지 조절할 수 있어요.

0이 아닌 가장 낮은 속도(1)에서는 시간당 221대의 자동차가 생산돼요. 생산량은 속도에 따라 선형적으로 증가하기 때문에, 속도 4에서는 시간당 4 * 221 = 884대의 자동차를 생산해요. 하지만 속도가 높아질수록 결함이 있는 자동차가 생산될 가능성도 커지고, 그런 자동차는 폐기해야 해요.

네 가지 작업이 있어요. 각 작업은 스택에서 조립 라인의 속도, 즉 정수 매개변수 하나를 가져와요.

1. 라인이 가동 중인지 알려주기

production-status를 정의해서 속도가 0이면 "stopped"를, 그 밖의 속도에서는 "running"을 반환하게 해요:

0 production-status .
! => "stopped"
3 production-status .
! => "running"

2. 성공률 계산하기

success-rate를 정의해서 제품이 오류 없이 생산될 확률을 반환하게 해요:

  • 0: 0.0
  • 1부터 4까지: 1.0
  • 5부터 8까지: 0.9
  • 9: 0.8
  • 10: 0.77
10 success-rate .
! => 0.77

3. 시간당 생산량 계산하기

production-rate-per-hour를 정의해서 성공률을 고려한 조립 라인의 시간당 생산량을 반환하게 해요.

먼저 base-speed를 정의해야 해요. 값은 상수 221이에요.

6 production-rate-per-hour .
! => 1193.4

반환되는 값은 실수예요.

4. 분당 정상 작동하는 자동차 수 계산하기

working-items-per-minute를 정의해서 분당 정상 작동하는 자동차가 몇 대 생산되는지 반환하게 해요. 결과는 정수예요. 일부만 완성된 자동차는 세지 않아요.

6 working-items-per-minute .
! => 19
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Factor Exercism

자동차, 조립하자! 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Factor 트랙을 개념 47개연습 문제 163개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.