Translated using translate google. The original language is Russian. Original page https://hi-aga.ru/index.php/homepage/case-1-20

In this group of tasks, a construction with the CASE keyword is used. It conveniently structures the code and increases the readability of programs, of course, all examples can be rewritten using the IF statement, so some programmers adhere to this option, considering CASE a bad programming style, but they are wrong, bad code can be written with any constructs, operators and in any programming language, besides, the more constructs you know, the better you will understand programming.

For the keywords of the CASE construct to work on SP-Forth, you need to connect the library in which it is defined by writing the following code at the beginning of the file:
S" C:\Program Files (x86)\SP-Forth\devel\~moleg\lib\util/case.f" INCLUDED

In your case, part of the path to SP-Forth may be different, depending on where you installed your Forth system. Or by relative path:

S" \devel\~moleg\lib\util/case.f" INCLUDED

The syntax of this construct is simple, starting with the CASE keyword and ending with ENDCASE. Inside these operator brackets we write the value and actions that need to be performed if our parameter matches it. Let's describe in more detail: first comes the parameter value, then the keyword OF and ENDOF, these are also operator brackets, inside of which there will be code for a given parameter value, that is, Forth language operators and/or calls to other words already defined earlier. Below is a diagram of the template:

Parameter_Value OF < language operators and/or previously defined words > ENDOF

The final structure of the CASE design will take the form:

CASE
    Option-1 OF <actions with option-1> ENDOF
    Option-2 OF <actions for option-2> ENDOF
Etc.
ENDCASE

If everything looks too abstract and unclear, then with examples everything should become clear and obvious. First, we will connect two libraries that we will use in all examples, in this group of tasks, in order to avoid errors “-2003 WORD OR FILE NOT FOUND”, which means the word is not defined.

S" C:\Program Files (x86)\SP-Forth\devel\~moleg\lib\util/case.f" INCLUDED

S" lib/include/float2.f" INCLUDED

The first library, as mentioned above, defines the operation of the CASE construct, and the second one should be familiar to you from previous tasks, as before for working with real-type numbers.

In the first example, use the number of the day of the week to display its name.

: CASE1 ( DAY-> ) \ SLOVESNOE_OPISANIE. - the dot after SLOVESNOE_OPISANIE means printing to the screen
CASE
    1 OF "Monday" ENDOF
    2 OF "Tuesday" ENDOF
    3 OF "Wednesday" ENDOF
    4 OF "Thursday" ENDOF
    5 OF "Friday" ENDOF
    6 OF "Saturday" ENDOF
    7 OF "Sunday" ENDOF
ENDCASE ;

Examples of the word CASE1

1 CASE1
Monday Ok
2 CASE1
Tuesday OK
7 CASE1
Sunday Ok
8 CASE1
 Ok Ok

Since the input range is stated in the condition, we did not do “foolproofing” - processing incorrect data, but this is provided for by the system, which we will show later, if necessary. In our case, when you enter an eight, the program does not react in any way, ignoring an incorrect case not provided for by the conditions of the task.

But in example two we have to process incorrect input, unacceptable according to the logic of the task, in which we need to display the names of the assessment 1 - “bad”, 2 - “poor”, 3 - “ud”, 4 - “good” and 5 - “excellent” " Actions for incorrect data are written before the ENDCASE keyword, but after ENDOF of the last option. To avoid future problems with encoding, you can translate the text into English or use Russian with the encoding of your console, otherwise strange characters will be displayed on the screen. If you still have questions about the logic of how the word CASE works, then let’s look at it, sum it up, and translate it into IF language.
CASE takes a number from the stack and compares it with the first option, if there is a match, it executes the corresponding code and all the work of the word is completed, if there is a difference, it compares with the second, and so on until it is equal to one of the provided options. When none of the options match, the "default" code (if any) between ENDCASE and the last ENDOF is executed, completing the description of the design.
: CASE2 ( OCENKA -> ) \ SLOVESNOE_OPISANIE.
CASE
    1 OF "Bad" ENDOF
    2 OF "Unsatisfactory" ENDOF
    3 OF "Satisfactory" ENDOF
    4 OF "Okay" ENDOF
    5 OF "Excellent" ENDOF
    ." Error"
ENDCASE ;

Test the program on various data

-1 CASE2
Error Ok
0 CASE2
Error Ok
1 CASE2
Bad Ok
2 CASE2
Unsatisfactory Ok
3 CASE2
Satisfactory Ok
4 CASE2
Okay Ok
5 CASE2
Excellent Ok
6 CASE2
Error Ok

An almost complete analysis of all options shows the correct operation of the code on all test data.

In example three, you need to determine the time of year by the month number and display it on the screen: winter - December (12), January (1), February (2), similarly for spring, summer and autumn.

: CASE3 ( MONTH -> ) \ SEASON.
CASE
    12 OF "Winter" ENDOF
    3 < uOF "Winter" ENDOF
    6 < uOF "Spring" ENDOF
    9 < uOF ." Summer " ENDOF
    12 < uOF ." Autumn" ENDOF
ENDCASE ;

First, we compare with 12 (December), and output Winter if true, then a new comparison construction is introduced - less than three. The result will be true if 1 (January) or 2 (February) is entered and, accordingly, we also print Winter. Next comes a check for less than six, that is, if the month number is 3,4 or 5 (March, April, May, respectively), then we print spring. And so on for summer and autumn.

If you don’t understand the example with comparisons, then you can write as before:

: CASE3 ( MONTH -> )  \ SEASON.
CASE
    12 OF ." Зима" ENDOF
    1  OF ." Зима" ENDOF
    2  OF ." Зима" ENDOF
    3  OF ." Весна" ENDOF
    4  OF ." Весна" ENDOF
    5  OF ." Весна" ENDOF
    6  OF ." Лето" ENDOF
    7  OF ." Лето" ENDOF
    8  OF ." Лето" ENDOF
    9  OF ." Осень" ENDOF
    10 OF ." Осень" ENDOF
    11 OF ." Осень" ENDOF
ENDCASE ;

This option is worse, due to the large number of comparisons, it is provided solely for understanding. Once you get used to it, don’t write such “shit code.”

To check the operation of this example, we will write a test word (which in a loop iterates through parameter I from 1 inclusive to 13 not inclusive - this is a feature of the loop in SP-Forth, the work of which we will get acquainted with later in the corresponding group of tasks, then we call the CASE3 word for each case and after outputting the result, the word CR moves the cursor to a new line so that the data is beautifully structured):

: TEST-CASE3 13 1 DO I . I CASE3 CR LOOP ;
TEST-CASE3
1 Winter
2 Winter
3 Spring
4 Spring
5 Spring
6 Summer
7 Summer
8 Summer
9 Autumn
10 Autumn
11 Autumn
12 Winter
 Ok

All options are processed correctly.

In example four, use the month number to determine the number of days for a non-leap year.

: CASE4 ( MONTH -> ) \ N. – Number of days in a month
CASE
    1 OF." 31" ENDOF
    2 OF." 28" ENDOF
    3 OF." 31" ENDOF
    4 OF." 30" ENDOF
    5 OF." 31" ENDOF
    6 OF." 30" ENDOF
    7 OF." 31" ENDOF
    8 OF." 31" ENDOF
    9 OF." 30" ENDOF
    10 OF." 31" ENDOF
    11 OF." 30" ENDOF
    12 OF." 31" ENDOF
ENDCASE ;

There is nothing new here, we go through all the numbers and print the corresponding number of days. You can replace the output of strings (like <." 31">) with <31 .> (printing the number sent to the stack), that is:

: CASE4 ( MONTH -> ) \ N. – Number of days in a month
CASE
    1 OF 31 ENDOF
    2 OF 28 ENDOF
    3 OF 31 ENDOF
    4 OF 30 ENDOF
    5 OF 31 ENDOF
    6 OF 30 ENDOF
    7 OF 31 ENDOF
    8 OF 31 ENDOF
    9 OF 30 ENDOF
    10 OF 31 ENDOF
    11 OF 30 ENDOF
    12 OF 31 ENDOF
ENDCASE. ;

Let's check by writing a test word on all valid values ​​(which can be used for both options):

: TEST-CASE4 13 1 DO I DUP . CASE4 CR LOOP ;

Final conclusion:

TEST-CASE4
1 31
2 28
3 31
4 30
5 31
6 30
7 31
8 31
9 30
10 31
11 30
12 31
 Ok

In example five, we perform one of four arithmetic operations on two real numbers, encrypted with the numbers 1 - addition, 2 - subtraction, 3 - multiplication, 4 - division. Of course, the second number cannot be entered as zero, so as not to provoke a division by zero error. Since here we are working with two stacks at once (integer and real), two stack notations are described in two brackets, which are designated “I:” (Integer) and “F:” (Float), respectively.

: CASE5 ( I: N -> )  ( F: A B -> )  \ A[N]B. – результат работы, выводимый на экран, 1 1E 2E CASE5 – формат работы слова
CASE
    1 OF F+ ENDOF
    2 OF F- ENDOF
    3 OF F* ENDOF
    4 OF F/ ENDOF
ENDCASE F. ;
1 1E-1 2E-1 CASE5
0.3000000  Ok
2 1E-1 2E-1 CASE5
-0.1000000  Ok
3 1E-1 2E-1 CASE5
0.0200000  Ok
4 1E-1 2E-1 CASE5
0.5000000  Ok

The results of operations on these real numbers are correct, the test is successful.

To put it simply, in example six, the length of the segment in decimeters (encrypted 1), kilometers (2), meters (3), millimeters (4) and centimeters (5) must be converted into meters. The result is achieved by dividing by 10, multiplying by 1000, no changes required, by dividing by 1000 and 100, respectively. Everything is coded simply, the only difference from the previous tasks in this block is that we started working with real numbers again.

: CASE6 ( I: N -> ) ( F: L -> )  \ Ln.
CASE
    1 OF 10E F/ ENDOF
    2 OF 1000E F* ENDOF
    3 OF ENDOF
    4 OF 1000E F/ ENDOF
    5 OF 100E F/ ENDOF
ENDCASE F. ;
\ Тест CASE6
1 1234E-2 CASE6
1.2340000  Ok
2 1234E-2 CASE6
12340.000  Ok
3 1234E-2 CASE6
12.340000  Ok
4 1234E-2 CASE6
0.0123400  Ok
5 1234E-2 CASE6
0.1234000  Ok


We translate 12.340000 and get 1.2340000, 12340.000, 12.340000, 0.0123400 and 0.1234000 respectively.

Example seven is completely similar to the previous one and therefore we will omit detailed explanations.

: CASE7 ( I: N -> ) ( F: M -> )  \ Mn.
CASE
    1 OF ENDOF
    2 OF 1000000E F/ ENDOF
    3 OF 1000E F/ ENDOF
    4 OF 1000E F* ENDOF
    5 OF 100E F* ENDOF
ENDCASE F. ;
1 1234E-2 CASE7
12.340000  Ok
2 1234E-2 CASE7
0.0000123  Ok
3 1234E-2 CASE7
0.0123400  Ok
4 1234E-2 CASE7
12340.000  Ok
5 1234E-2 CASE7
1234.0000  Ok


In example eight, we determine the previous date if given D M (day and month of a non-leap year). If day D > 1, then simply decrease D by one and the result is ready, otherwise the month will change, then you need to determine how many days there are in the month, as in the example there are four. In the second line we check that the month does not become zero, then we replace it with December, that is, we write 12.

: CASE8 ( D M -> ) \ D2M2. - Previous date
OVER 1 >
IF SWAP 1- . . ELSE
1- DUP 0 = IF DROP 12 THEN DUP
CASE
    1 OF." 31" ENDOF
    2 OF." 28" ENDOF
    3 OF." 31" ENDOF
    4 OF." 30" ENDOF
    5 OF." 31" ENDOF
    6 OF." 30" ENDOF
    7 OF." 31" ENDOF
    8 OF." 31" ENDOF
    9 OF." 30" ENDOF
    10 OF." 31" ENDOF
    11 OF." 30" ENDOF
    12 OF." 31" ENDOF
ENDCASE. DROP
THEN ;

In the test word we will go through all the first numbers of twelve months, because in other cases the result is not so interesting, check it yourself.

: TEST-CASE8 13 1 DO 1 DUP . I DUP. CASE8 CR LOOP ;
TEST-CASE8
1 1 31 12
1 2 31 1
1 3 28 2
1 4 31 3
1 5 30 4
1 6 31 5
1 7 30 6
1 8 31 7
1 9 31 8
1 10 30 9
1 11 31 10
1 12 30 11
 Ok

The first two numbers are the original date, and the second two are the previous day.

Example nine. Differs from example eight by replacing the previous day with the next. We increase the day number by one and compare it with the number of days in the month; if it becomes larger, then we replace it with the first day of the next month. If the month number becomes more than twelve, then we replace it with one (January), otherwise everything is fine, you don’t need to do anything, just print the results.

: CASE9 ( D M -> )  \ D2M2. - следующая дата
OVER 1+ OVER        \ D M -> D M (D+1) M
CASE
    1 OF  31 ENDOF  \ D M (D+1) M -> D M (D+1) (Последний День Месяца)
    2 OF  28 ENDOF
    3 OF  31 ENDOF
    4 OF  30 ENDOF
    5 OF  31 ENDOF
    6 OF  30 ENDOF
    7 OF  31 ENDOF
    8 OF  31 ENDOF
    9 OF  30 ENDOF
    10 OF 31 ENDOF
    11 OF 30 ENDOF
    12 OF 31 ENDOF
ENDCASE
> IF SWAP DROP 1+ 1 ELSE SWAP 1+ THEN
        \ Если (D+1)>(Последний День Месяца), то
        \ D M -> (M+1) 1 , иначе
        \ D M -> M (D+1)
 . DUP  \ Печатаем День ,
12 > IF DROP 1 THEN . ;  \ если месяц стал больше 12, то заменяем на 1
31 1 CASE9
1 2  Ok
28 2 CASE9
1 3  Ok
31 3 CASE9
1 4  Ok
30 4 CASE9
1 5  Ok
31 5 CASE9
1 6  Ok
30 6 CASE9
1 7  Ok
31 7 CASE9
1 8  Ok
31 8 CASE9
1 9  Ok
30 9 CASE9
1 10  Ok
31 10 CASE9
1 11  Ok
30 11 CASE9
1 12  Ok
31 12 CASE9
1 1  Ok


The above are tests when changing months; in other cases, experiment on your own.

Example ten. Here we control a robot moving in four directions (North, West, South, East) and controlled by three commands “0” - forward, “1” - turn left, “-1” - turn right. Using the initial direction C and command N, determine the direction of the robot after executing the command. The code came out with two “CASE” constructs nested inside each other. In the outer one we process the N command, and in the nested (inner) direction the “C” direction.

: CASE10 ( N C -> ) \ C2. “N CASE10 C” - word work format
CHAR SWAP \ convert the character into code
CASE
    0 OF EMIT ENDOF \ command "0" does not change direction
    -1 OF \ command "-1" changes direction
        CASE
            78 OF 69 EMIT ENDOF\N -> E
            69 OF 83 EMIT ENDOF \ E -> S
            83 OF 87 EMIT ENDOF\S -> W
            87 OF 78 EMIT ENDOF \ W -> N
        ENDCASE
    ENDOF
    1 OF
        CASE
            78 OF 87 EMIT ENDOF \ N -> W
            87 OF 83 EMIT ENDOF \ W -> S
            83 OF 69 EMIT ENDOF\S -> E
            69 OF 78 EMIT ENDOF \ E -> N
        ENDCASE
    ENDOF
ENDCASE ;

Test of word operation with command “0” (direction does not change):

0 CASE10 N
N Ok
0 CASE10E
E Ok
0 CASE10 S
S Ok
0 CASE10 W
W Ok

When turning left.

1 CASE10 N
W Ok
1 CASE10W
S Ok
1 CASE10 S
E Ok
1 CASE10 E
N Ok

When turning right.

-1 CASE10 N
E Ok
-1 CASE10W
N Ok
-1 CASE10 S
W Ok
-1 CASE10 E
S Ok

Improved version

: CASE10 ( C N -> C2 ) ( N CASE10 C ) CHAR SWAP
CASE
    0 OF ENDOF
    1 OF
        CASE
            78 OF 87 ENDOF \ N -> W
            69 OF 78 ENDOF \ E -> N
            83 OF 69 ENDOF \ S -> E
            87 OF 83 ENDOF \ W -> S
        ENDCASE
    ENDOF
    -1 OF
        CASE
            78 OF 69 ENDOF \ N -> E
            69 OF 83 ENDOF \ E -> S
            83 OF 87 ENDOF \ S -> W
            87 OF 78 ENDOF \ W -> N
        ENDCASE
    ENDOF
ENDCASE EMIT ;

We cleaned up unnecessary repetitions and got clean code (By removing "EMIT").

Example eleven. Unlike the previous example, one more command has been added, and “0” - continuing to move forward, has been replaced by a 180-degree turn. To solve this example, we first modify example ten by adjusting the command “0” and denoting it with “COM” (short for COMMAND).

: COM  \ Переделанный CASE11
CASE
    1 OF
        CASE
            78 OF 87 ENDOF \ N -> W
            69 OF 78 ENDOF \ E -> N
            83 OF 69 ENDOF \ S -> E
            87 OF 83 ENDOF \ W -> S
        ENDCASE
    ENDOF
    -1 OF
        CASE
            78 OF 69 ENDOF \ N -> E
            69 OF 83 ENDOF \ E -> S
            83 OF 87 ENDOF \ S -> W
            87 OF 78 ENDOF \ W -> N
        ENDCASE
    ENDOF
    2 OF
        CASE
            78 OF 83 ENDOF \ N -> S
            69 OF 87 ENDOF \ E -> W
            83 OF 78 ENDOF \ S -> N
            87 OF 69 ENDOF \ W -> E
        ENDCASE
    ENDOF
ENDCASE ;
: CASE11 ( C N1 N2 -> )  \ C2.  - N1 N2 CASE11 C - формат работы команды
CHAR
SWAP COM
SWAP COM
EMIT ;

Examples of tests:

1 1 CASE11 N
S Ok
-1 -1 CASE11 N
S Ok
2 2 CASE11 N
N Ok

Example twelve. The elements of a circle are coded with numbers: 1 - radius, 2 - diameter, 3 - length and 4 - area. Calculate one of them and display the others in the same order. Take pi accurate to two decimal places. To do this, we will write 3 auxiliary words that calculate the diameter, length and area, respectively.

: D. ( R -> 2*R )." D=" 2E F* F. ; \D=2*R
: L. ( R -> 2*3.14*R ) " L=" 2E F* 3.14E F* F. ; \ L=2*PI*R
: S. ( R -> 3.14*R*R )." S=" FDUP F* 3.14E F* F. ; \ S=PI*R*R

The main word, which solves the condition of the problem, executes the corresponding code depending on the element number.

: CASE12 ( I: N -> ) ( F: X -> ) \ {1,2,3,4} 10E CASE12 – формат работы слова
CASE
    1 OF
        FDUP FDUP \ DANO R - вспомогательные слова решают задачу
        D. CR
        L. CR
        S. CR
    ENDOF
    2 OF
        \ DANO D – вычисляем R, сводим задачу к предыдущему
        ." R=" 2E F/ FDUP FDUP F. CR
        L. CR
        S. CR
    ENDOF
    3 OF
        \ DANO L – аналогично, вычисляем R через L
        ." R=" 2E 3.14E F* F/ FDUP FDUP F. CR
        D. CR
        S. CR
    ENDOF
    4 OF
        \ DANO S - идентично, вычисляем R теперь через S
        ." R=" 3.14E F/ FSQRT FDUP FDUP F. CR
        D. CR
        L. CR
    ENDOF
ENDCASE ;

In the first case, all the auxiliary words have already been written, in the others, the radius is first calculated (through D in the second, through L in the third and through S in the fourth case), then the problem is reduced to the first. And at the end there are a couple of tests.

1 10E CASE12
D=20.000000
L=62.800000
S=314.00000
Ok
2 10E CASE12
R=5.0000000
L=31.400000
S=78.500000
Ok
3 10E CASE12
R=1.5923567
D=3.1847134
S=7.9617834
Ok
4 10E CASE12
R=1.7845765
D=3.5691531
L=11.207141
Ok

Example thirteen. Completely similar to the previous one, with the same operating logic. Let's write the code for each case without additional words. The only difference is in the formulas.

: CASE13 ( I: N -> ) ( F: X -> )  \ {1,2,3,4} 10E CASE13 – формат работы слова
CASE
    1 OF
        \ DANO A
        ." C=" 2E FSQRT F* FDUP F. CR ( C )
        ." H=" 2E F/ FDUP F. CR ( H )
        ." S=" FDUP F* F. CR
    ENDOF
    2 OF
        \ DANO C
        ." A=" FDUP 2E FSQRT F/ F. CR ( C )
        ." H=" 2E F/ FDUP F. CR ( H )
        ." S=" FDUP F* F. CR
    ENDOF
    3 OF
        \ DANO H
        ." A=" 2E F* FDUP 2E FSQRT F/ F. CR ( C )
        ." C=" FDUP F. CR ( C )
        ." S=" FDUP F* 4E F/ F. CR
    ENDOF
    4 OF
        \ DANO S
        ." A=" FSQRT FDUP 2E F* FDUP 2E FSQRT F/ F. CR ( H C )
        ." C=" F. CR ( H )
        ." H=" F. CR
    ENDOF
ENDCASE ;

Example fourteen. Similar to example thirteen, like example twelve, it also differs only in formulas.

: CASE14 ( I: N -> ) ( F: X -> ) \ {1,2,3,4} 10E CASE14 - формат работы слова
CASE
    1 OF
        \ DANO A
        ." R1=" FDUP 3E FSQRT F* 6E F/ FDUP F. CR ( A R1 )
        ." R2=" 2E F* F. CR ( A )
        ." S =" FDUP F* 3E FSQRT F* 4E F/ F. CR
    ENDOF
    2 OF
        \ DANO R1
        ." A=" FDUP 6E F* 3E FSQRT F/ FDUP F. CR ( R1 A )
        ." R2=" FSWAP 2E F* F. CR ( A )
        ." S=" FDUP F* 3E FSQRT F* 4E F/ F. CR
    ENDOF
    3 OF
        \ DANO R2
        ." A=" FDUP 3E FSQRT F* FDUP F. CR ( R2 A )
        ." R1=" FSWAP 2E F/ F. CR ( A )
        ." S=" FDUP F* 3E FSQRT F* 4E F/ F. CR
    ENDOF
    4 OF
        \ DANO S
        ." A=" 4E F* 3E FSQRT F/ FSQRT FDUP F. CR ( A )
        ." R1=" 3E FSQRT F* 6E F/ FDUP F. CR ( R1 )
        ." R2=" 2E F* F. CR
    ENDOF
ENDCASE ;

Example fifteen is quite simple. Two numbers are given: the suit number and the card number. Display a message describing the name of the card, for example, “six of spades”.

: CASE15 ( 6<=N<=14 1<=M<=4 -> ) SWAP \ “Six of Spades”
CASE
    6 OF." Six "ENDOF
    7 OF." Seven" ENDOF
    8 OF." Eight" ENDOF
    9 OF." Nine "ENDOF
    10 OF." Ten "ENDOF
    11 OF." Jack "ENDOF
    12 OF "Lady" ENDOF
    13 OF "King" ENDOF
    14 OF." Ace" ENDOF
    "Map error"
ENDCASE
CASE
    1 OF "peak" ENDOF
    2 OF "clubs" ENDOF
    3 OF "tambourine" ENDOF
    4 OF "worms" ENDOF
    "suit error"
ENDCASE ;

The word test TEST-CASE15 checks all correct variants of the word CASE15.

: TEST-CASE15 15 6 DO 5 1 DO J DUP . I DUP. CASE15 CR LOOP LOOP ;

What you can verify by running it.

TEST-CASE15
6 1 Шестерка пик
6 2 Шестерка треф
6 3 Шестерка бубен
6 4 Шестерка червей
7 1 Семерка пик
7 2 Семерка треф
7 3 Семерка бубен
7 4 Семерка червей
8 1 Восьмерка пик
8 2 Восьмерка треф
8 3 Восьмерка бубен
8 4 Восьмерка червей
9 1 Девятка пик
9 2 Девятка треф
9 3 Девятка бубен
9 4 Девятка червей
10 1 Десятка пик
10 2 Десятка треф
10 3 Десятка бубен
10 4 Десятка червей
11 1 Валет пик
11 2 Валет треф
11 3 Валет бубен
11 4 Валет червей
12 1 Дама пик
12 2 Дама треф
12 3 Дама бубен
12 4 Дама червей
13 1 Король пик
13 2 Король треф
13 3 Король бубен
13 4 Король червей
14 1 Туз пик
14 2 Туз треф
14 3 Туз бубен
14 4 Туз червей
Ok

Example sixteen assumes little knowledge of the Russian language. In general, the logic of operation is also simple.

: CASE16 ( A-> )
10 /MOD \ A -> [A MOD 10] [A/10]
\ Сначала выводим десятки
CASE
    2 OF ." Двадцать " ENDOF
    3 OF ." Тридцать " ENDOF
    4 OF ." Сорок " ENDOF
    5 OF ." Пятьдесят " ENDOF
    6 OF ." Шестьдесят " ENDOF
    7 OF ." Семьдесят " ENDOF
    ." Ошибка ввода, нужно ввести возраст от 20 до 69 "
ENDCASE
\ затем единицы
CASE
    0 OF ." Лет " ENDOF
    1 OF ." один год" ENDOF
    2 OF ." два года" ENDOF
    3 OF ." три года" ENDOF
    4 OF ." четыре года" ENDOF
    5 OF ." пять лет" ENDOF
    6 OF ." шесть лет" ENDOF
    7 OF ." семь лет" ENDOF
    8 OF ." восемь лет" ENDOF
    9 OF ." девять лет" ENDOF
ENDCASE ;

Test word, which checks all input options in the specified range:

: TEST-CASE16 70 20 DO I DUP . CASE16 CR LOOP ;

The word test displays a large amount of text that is not presented here, experiment on your own.

Example seventeen. As in the previous one, we divide the original number into tens and units, then we carry out the analysis. First, we consider the case when one ten (“1 OF”), a complete search with an exit. Then we work out tens, and finally ones.

: CASE17 ( N[10-40] -> )
10 /MOD
CASE ( Десятки )
    1 OF
        CASE
            0 OF ." Десять учебных заданий " ENDOF
            1 OF ." Одиннадцать учебных заданий " ENDOF
            2 OF ." Двенадцать учебных заданий " ENDOF
            3 OF ." Тринадцать учебных заданий " ENDOF
            4 OF ." Четырнадцать учебных заданий " ENDOF
            5 OF ." Пятнадцать учебных заданий " ENDOF
            6 OF ." Шестнадцать учебных заданий " ENDOF
            7 OF ." Семнадцать учебных заданий " ENDOF
            8 OF ." Восемнадцать учебных заданий " ENDOF
            9 OF ." Девятнадцать учебных заданий " ENDOF
        ENDCASE
        EXIT
    ENDOF
    2 OF ." Двадцать " ENDOF
    3 OF ." Тридцать " ENDOF
    4 OF ." Сорок " ENDOF
ENDCASE
CASE
    0 OF ." учебных заданий " ENDOF
    1 OF ." одно учебное задание " ENDOF
    2 OF ." два учебных задания " ENDOF
    3 OF ." три учебных задания " ENDOF
    4 OF ." четыре учебных задания " ENDOF
    5 OF ." пять учебных заданий " ENDOF
    6 OF ." шесть учебных заданий " ENDOF
    7 OF ." семь учебных заданий " ENDOF
    8 OF ." восемь учебных заданий " ENDOF
    9 OF ." девять учебных заданий " ENDOF
ENDCASE ;
: TEST-CASE17 50 10 DO I DUP . CASE17 CR LOOP ;

I hope you can correct any errors in grammar (if any) yourself. The logic of the program should not cause any difficulties.

Example eighteen. To display numbers in the range from 100 to 999, you must first divide by one hundred, having received the quotient, we display the number of hundreds, the remainder will be tens with ones, which we get separately by dividing again by 10. We divide using the command “/MOD”, which leaves both the remainder and the quotient on the stack at the same time. If there are zero tens, then we do not print anything (this option can be skipped and not considered; it is written here in the code for the integrity of the picture), we separately consider the number of tens equal to one, and at the end of each we exit the word. Next, nothing new, we go through the remaining options for tens, and then end with ones.

: CASE18 ( A -> )
100 /MOD
    CASE \ Сотни
        1 OF ." Сто " ENDOF
        2 OF ." Двести " ENDOF
        3 OF ." Триста " ENDOF
        4 OF ." Четыреста " ENDOF
        5 OF ." Пятьсот " ENDOF
        6 OF ." Шестьсот " ENDOF
        7 OF ." Семьсот " ENDOF
        8 OF ." Восемьсот " ENDOF
        9 OF ." Девятьсот " ENDOF
    ENDCASE
10 /MOD
    CASE \ Десятки
        0 OF ENDOF \ число десяток ноль, ничего не делаем (можно удалить его)
        1 OF \ число десяток один, обрабатываем каждую в отдельности и завершаем
            CASE
                0 OF ." десять" EXIT ENDOF
                1 OF ." одиннадцать" EXIT ENDOF
                2 OF ." двенадцать" EXIT ENDOF
                3 OF ." тринадцать" EXIT ENDOF
                4 OF ." четырнадцать" EXIT ENDOF
                5 OF ." пятнадцать" EXIT ENDOF
                6 OF ." шестнадцать" EXIT ENDOF
                7 OF ." семнадцать" EXIT ENDOF
                8 OF ." восемнадцать" EXIT ENDOF
                9 OF ." девятнадцать" EXIT ENDOF
            ENDCASE
        ENDOF
        2 OF ." двадцать " ENDOF
        3 OF ." тридцать " ENDOF
        4 OF ." сорок " ENDOF
        5 OF ." пятьдесят " ENDOF
        6 OF ." шестьдесят " ENDOF
        7 OF ." семьдесят " ENDOF
        8 OF ." восемьдесят " ENDOF
        9 OF ." девяносто " ENDOF
    ENDCASE
CASE \ Единицы
    1 OF ." один" ENDOF
    2 OF ." два" ENDOF
    3 OF ." три" ENDOF
    4 OF ." четыре" ENDOF
    5 OF ." пять" ENDOF
    6 OF ." шесть" ENDOF
    7 OF ." семь" ENDOF
    8 OF ." восемь" ENDOF
    9 OF ." девять" ENDOF
ENDCASE ;

Word test to display all numbers in the range from one hundred to nine hundred and ninety nine. I hope everything is in order with the grammar, otherwise it will not be difficult to fix it, because the logic of the work should not cause difficulties in the work.

: TEST-CASE18 1000 100 DO I CASE18 CR LOOP ;

Example nineteen. Note that colors with animals will be combined in two variants (green, green, red, red...), for this we will write two variants of the color output word - COLOR1, COLOR2. Let's divide 1984 by 60, we get a remainder of 4. We add the number 56 to 1984, then dividing (1984+56) = 2040 by 60 gets 34 exactly, without a remainder. The code “60 MOD” highlights the sixty-year cycle, and “12 /MOD” the twelve-year cycle with color. By executing the following “1984 56 + 60 MOD 12 /MOD SWAP”, we get ( “0 0”), that is, the color is zero (green), and the animal is 0 (rat), so we synchronized with the calendar for the year 1984 (the year of the green rat ). Next, it’s a matter of technique to simply process all the options for twelve animals and five colors.

: COLOR1 ( COLOR -> ) \ COLOR.
CASE
    0 OF ." зеленой " ENDOF
    1 OF ." красной " ENDOF
    2 OF ." желтой " ENDOF
    3 OF ." белой " ENDOF
    4 OF ." черной " ENDOF
ENDCASE ;
: COLOR2 ( COLOR -> ) \ COLOR.
CASE
    0 OF ." зеленого " ENDOF
    1 OF ." красного " ENDOF
    2 OF ." желтого " ENDOF
    3 OF ." белого " ENDOF
    4 OF ." черного " ENDOF
ENDCASE ;
: CASE19 ( Y -> )
\ 1984 - Год зеленой крысы
56 + 60 MOD 12 /MOD SWAP ( цвет животное )
." Год "
CASE ( животное )
    0 OF COLOR1 ." крысы " ENDOF
    1 OF COLOR1 ." коровы " ENDOF
    2 OF COLOR2 ." тигра " ENDOF
    3 OF COLOR2 ." зайца " ENDOF
    4 OF COLOR2 ." дракона " ENDOF
    5 OF COLOR1 ." змеи " ENDOF
    6 OF COLOR1 ." лошади" ENDOF
    7 OF COLOR1 ." овцы" ENDOF
    8 OF COLOR1 ." обезьяны " ENDOF
    9 OF COLOR1 ." курицы " ENDOF
    10 OF COLOR1 ." собаки " ENDOF
    11 OF COLOR1 ." свиньи " ENDOF
    ." Неправильная дата"
ENDCASE ;
: TEST-CASE19 2000 1983 DO I DUP . CASE19 CR LOOP ;

Example twenty. We multiply the month by one hundred and add the day. Thus, we get the encryption of the day and month in one number, the meaning of which is that now we can compare the date and month not twice separately, but in one operation (making our life easier). So all the days of January will be from 101 to 131. For example, for Capricorn, the cutoff date of 19.01 is, in our opinion, the 119th day, and all dates before it (from 101 to 119) are guaranteed to be less than 120 - the first value in "CASE", which will output "Zodiac sign - Capricorn" for any day value in this range. Comparisons for other signs look similar. The last value is “1221 > uOF” for a complete check of Capricorn, and closure of all possible, correctly entered dates.

: CASE20 ( D M -> ZOD. )
100 * +
CASE
    120 < uOF ." Козерог " ENDOF
    219 < uOF ." Водолей " ENDOF
    321 < uOF ." Рыбы " ENDOF
    420 < uOF ." Овен " ENDOF
    521 < uOF ." Телец " ENDOF
    622 < uOF ." Близнецы " ENDOF
    723 < uOF ." Рак " ENDOF
    823 < uOF ." Лев " ENDOF
    923 < uOF ." Дева " ENDOF
    1023 < uOF ." Весы " ENDOF
    1123 < uOF ." Скорпион " ENDOF
    1222 < uOF ." Стрелец " ENDOF
    1221 > uOF ." Козерог " ENDOF
ENDCASE ;

The word test shows the correctness of its operation on the correct dates.

1 1 CASE20
Козерог Ok
19 1 CASE20
Козерог Ok
20 1 CASE20
Водолей Ok
18 2 CASE20
Водолей Ok
19 2 CASE20
Рыбы Ok
20 3 CASE20
Рыбы Ok
21 3 CASE20
Овен Ok
19 4 CASE20
Овен Ok
20 4 CASE20
Телец Ok
20 5 CASE20
Телец Ok
21 5 CASE20
Близнецы Ok
21 6 CASE20
Близнецы Ok
22 6 CASE20
Рак Ok
22 7 CASE20
Рак Ok
23 7 CASE20
Лев Ok
22 8 CASE20
Лев Ok
23 8 CASE20
Дева Ok
22 9 CASE20
Дева Ok
23 9 CASE20
Весы Ok
22 10 CASE20
Весы Ok
23 10 CASE20
Скорпион Ok
22 11 CASE20
Скорпион Ok
23 11 CASE20
Стрелец Ok
21 12 CASE20
Стрелец Ok
22 12 CASE20
Козерог Ok

Since we have not implemented “fool protection” and when entering, for example, the date January 35, the result will be: 35 1 CASE20 Aquarius Ok