Translated using translate google. The original language is Russian. Original page https://hi-aga.ru/index.php/homepage/boolean-21-40
Example 21. Check that the digits of a three-digit number form an increasing sequence. To do this, we first break this number into numbers, then make a double comparison, i.e. the number ABC must contain: A<B<C.
: BOOL21 ( ABC -> )
10 /MOD 10 /MOD \ ABC -> C B A
OVER < ROT ROT \ C B A -> A<B C B
> AND \ A<B C B -> [A<B]AND[C>B]
B.
;
123 BOOL21
True Ok
111 BOOL21
False Ok
112 BOOL21
False Ok
122 BOOL21
False Ok
321 BOOL21
False Ok
Example 22. Check that the digits of a three-digit number form an increasing or decreasing sequence, that is, the number ABC A<B<C or A>B>C. It differs from the previous one by an additional check.
: BOOL22 ( ABC -> )
DUP\ABC -> ABC ABC
10 /MOD 10 /MOD \ ABC ABC -> ABC C B A
OVER < ROT ROT \ ABC C B A -> ABC A<B C B
> AND \ ABC A<B C B -> ABC [A<B]AND[C>B]
SWAP 10 /MOD 10 /MOD \ ABC [A<B]AND[C>B] -> [A<B]AND[C>B] C B A
OVER > ROT ROT \ [A<B]AND[C>B] C B A -> [A<B]AND[C>B] A>B C B
< AND \ [A<B]AND[C>B] A>B C B -> [A<B]AND[C>B] [A>B]AND[C<B]
OR \ [A<B]AND[C>B] [A>B]AND[C<B] -> {[A<B]AND[C>B]}OR{[A>B]AND[C< B]}
B.
;
123 BOOL22
True Ok
321 BOOL22
True Ok
210 BOOL22
True Ok
211 BOOL22
False Ok
112 BOOL22
False Ok
You can optimize the code. Let's use the previous example for this. Let’s remove the output from there and the first line dividing the number into numbers, now it simply determines “A<B<C” true or false.
: BOOL21 ( C B A -> Bool )
OVER < ROT ROT \ C B A -> A<B C B
> AND \ A<B C B -> [A<B]AND[C>B]
;
Теперь перепишем слово BOOL22.
: BOOL22 ( ABC -> )
DUP 10 /MOD 10 /MOD \ ABC -> ABC C B A
BOOL21 IF 1 B. DROP EXIT THEN \ ABC -> ABC
10 /MOD 10 /MOD SWAP ROT \ ABC -> A B C
BOOL21 IF 1 B. EXIT THEN
0 B.
;
First line standard start
In the second we copy the number then split it into digits
In the third, we send the results of the partition for verification into the word “BOOL21”, receiving the result in the Bool variable at the top of the stack, and if it is true, we print it through the word “B.”, passing it argument one. We delete the number ABC remaining on the stack and exit with the “EXIT” operator.
In the fourth, we check the inequality A>B>C, for which, after dividing the number, we change the order to the reverse.
In the fifth, we again send the numbers for verification to “BOOL21”, with the same operating logic.
The sixth line is triggered when neither of the two inequalities are true, which means the digits of the original number are not sorted in either ascending or descending order, for which we print false by calling "B." with argument zero.
If the code is needed without a conditional operator, then we can rewrite the latter.
: BOOL22 ( ABC -> )
DUP 10 /MOD 10 /MOD \ ABC -> ABC C B A
BOOL21\ABC -> ABC Bool1
SWAP\ABC Bool1->Bool1 ABC
10 /MOD 10 /MOD SWAP ROT \ Bool1 ABC-> Bool1 C B A
BOOL21 OR \ Bool1 ABC -> Bool1&Bool2
B.
;
Decide for yourself which option you like. The code is not very complicated, splitting and placing repeated code into a separate function is not necessary, but for educational purposes I think it will be useful.
Example 23. Check that a four-digit number is read the same from left to right and from right to left. This means that the number must be of the form ABBA.
: BOOL23 ( ABCD -> )
100 /MOD \ ABCD -> CD AB
10 /MOD\CD AB -> CD B A
SWAP 10 * + \ CD B A -> CD BA
=\CD BA -> CD= BA
B.
;
The code “100 /MOD” divides the original number into two halves: the first is tens with ones, the second is thousands with hundreds. Then "10 /MOD" breaks the latter into individual digits, and "SWAP 10 * +" assembles it in reverse order. These manipulations are necessary for the comparison “CD=BA”. In case of equality, the original number is a “palindrome”, that is, it is read the same from left to right and from right to left.
1221 BOOL23
True Ok
1234 BOOL23
False Ok
1001 BOOL23
True Ok
1220 BOOL23
False Ok
The tests are correct.
Example 24. Check the truth of the statement “a quadratic equation with coefficients A, B, C has real roots.” To do this, we calculate the discriminant, and if it is not negative, then we output “true” (True), otherwise “false” (False).
: BOOL24 ( A B C -> )
SWAP DUP *\A B C -> A C B^2
ROT ROT \ A C B^2 -> B^2 A C
-4 * * + \ B^2 A C -> B^2+A*C*(-4)
-1 > B.
;
1 2 1 BOOL24
True Ok
1 3 2 BOOL24
True Ok
1 2 5 BOOL24
False Ok
Checking the discriminant for non-negativity, i.e. D>=0, is replaced by D>-1, naturally assuming that integer coefficients will only give an integer value for D, such a replacement is correct.
Example 25. Is it true that a point with coordinate (x,y) lies in the second quadrant in the Cartesian coordinate system. The second quarter means that x<0, y>0 (we don’t take it equal to zero because it creates ambiguity).
: BOOL25 ( X Y -> )
0 > SWAP 0 < AND
B.
;
1 1 BOOL25
False Ok
-1 1 BOOL25
True Ok
-1 -1 BOOL25
False Ok
1 -1 BOOL25
False Ok
Example 26. Identical to the previous example, only we check whether it belongs to the fourth quarter. The fourth quarter means that x>0, y<0.
: BOOL26 ( X Y -> )
0 <SWAP 0>AND
B.
;
1 1 BOOL26
False Ok
1 -1 BOOL26
True Ok
-1 1 BOOL26
False Ok
-1 -1 BOOL26
False Ok
Example 27. Similar to the two previous examples, we check whether it belongs to the second or third coordinate quarters. And this means x<0, and y is any.
: BOOL27 ( X Y -> ) DROP 0 < B. ; \ Y - discard, check X<0? Print the value of the boolean variable at the top of the stack.
1 1 BOOL27
False Ok
1 -1 BOOL27
False Ok
-1 1 BOOL27
True Ok
-1 -1 BOOL27
True Ok
Example 28. Now we check whether it belongs to the first or third coordinate quarters. A little more complicated than the previous examples. Either x>0 and y>0, or x<0 and y<0.
: BOOL28 ( X Y -> )
2DUP 0 < SWAP 0 < AND \ X Y -> X Y [X<0]AND[Y<0]
ROT ROT \ X Y [X<0]AND[Y<0] -> [X<0]AND[Y<0] X Y
0 > SWAP 0 > AND \ [X<0]AND[Y<0] X Y -> [X<0]AND[Y<0] [Y>0]AND[X>0]
OR \ [X<0]AND[Y<0] [Y>0]AND[X>0] -> [X<0]AND[Y<0]OR[Y>0]AND[X>0]
B.
;
1 1 BOOL28
True Ok
-1 -1 BOOL28
True Ok
1 -1 BOOL28
False Ok
-1 1 BOOL28
False Ok
And now a “live hack”, let’s simplify this “disgrace”. The system of conditions either (x>0 and y>0) or (x<0 and y<0) can be replaced by one x*y>0, i.e., regardless of the sign of the arguments, their product is always positive. An example for clarity: “10*50>0 and -10*(-50)>0”. Let's rewrite the word BOOL28.
: BOOL28 ( X Y -> )
* 0 >\ X*Y>0
B.
;
Previous tests give identical results, check it yourself.
Conclusion: a beautiful and simple mathematical solution gives the same code.
Example 29. Is the point included in the rectangle? Given are the coordinates of the point (X,Y) and two vertices of the rectangle, the top left (X1,Y1) and the opposite one (X2,Y2), the sides are parallel to the abscissa and ordinate. The point is inside the rectangle when X1<=X<=X2 and Y1<=Y<=Y2. The problem comes down to checking these two double inequalities.
Let's create variables
VARIABLE X VARIABLE X1 VARIABLE X2
VARIABLE Y VARIABLE Y1 VARIABLE Y2
But we will only use X1, X2, Y1, Y2.
: BOOL29 ( X Y X1 Y1 X2 Y2 -> )
Y2! X2! Y1! X1! \ X Y X1 Y1 X2 Y2 -> X Y
DUP Y1 @ > \ X Y -> X Y Y>Y1
IF 2DROP 0 B. EXIT THEN \ If Y>Y1 is not inside “false”
Y2 @ < \ X Y -> X Y<Y2
IF DROP 0 B. EXIT THEN \ If Y<Y2 is not inside “false”
DUP X1 @ < \ X -> X X<X1
IF DROP 0 B. EXIT THEN \ If X<X1 – not inside “false”
X2 @ > \ X -> X>X2
IF 0 B. EXIT THEN \ If X>X2 is not inside “false”
1 B. \ Otherwise - inside
;
The first line is a word declaration with stack notation. Everything is as usual.
In the second, we save the coordinates of the rectangle into variables, so as not to complicate stack manipulations and simplify the code.
In the third, we compare the Y coordinate of the point with the ordinate of the upper left point of the rectangle; if it is greater, then the point cannot enter it.
In the fourth, this comparison is checked for truth. True in the case when the point does not belong to the rectangle, print false using the word “B.” with parameter "0". Then we end the program using the “EXIT” statement.
Similarly to the third line, we check the coordinate of the point to see if it belongs to the lower border of the rectangle.
Similar to the fourth line.
The seventh to tenth lines are similar to the third to sixth lines only they relate to the X coordinate.
The eleventh line is triggered if all other conditions for the point not to be in the rectangle are not satisfied. That is, the point is inside, which is what the word “B” indicates. with parameter one, which means true.
1 1 10 10 20 5 BOOL29
False Ok
9 11 10 10 20 5 BOOL29
False Ok
11 9 10 10 20 5 BOOL29
True Ok
21 9 10 10 20 5 BOOL29
False Ok
11 4 10 10 20 5 BOOL29
False Ok
Example 30. Check whether an equilateral triangle has sides A, B, C. The problem boils down to checking the double equality A=B=C.
: BOOL30 ( A B C -> )
OVER = \ A B C -> A B C=B
ROT ROT = AND \ A B C=B -> [C=B]AND[A=B]
B.
;
1 2 3 BOOL30
False Ok
1 2 2 BOOL30
False Ok
2 2 1 BOOL30
False Ok
1 2 1 BOOL30
False Ok
5 5 5 BOOL30
True Ok
Example 31. Check whether the triangle with sides A, B, C is isosceles. Check by the condition A=B or B=C or A=C. Identical to example number 18 without changes.
: BOOL31 ( A B C -> )
2DUP = \ A B C -> A B C B=C
2SWAP OVER = \ A B C B=C -> C B=C A B=A
ROT OR \ C B=C A B=A -> C A [B=A]OR[B=C]
ROT ROT = OR \ C A [B=A]OR[B=C] -> [B=A]OR[B=C]OR[C=A]
B.
;
1 1 2 BOOL31
True Ok
1 2 1 BOOL31
True Ok
1 1 2 BOOL31
True Ok
1 1 1 BOOL31
True Ok
1 2 3 BOOL31
False Ok
Example 32. Check if the triangle with sides A, B, C is right? Using the Pythagorean theorem, let's check 3 equalities A^2=B^2+C^2 or B^2= A^2 +C^2 or C^2= A^2+B^2. If one of them is satisfied, then the answer is positive, otherwise negative.
The first line is a description.
In the second line, we turn the initial data - the lengths of the sides “A B C” into their squares.
In the third we check the first of the equalities: [A^2=C^2+B^2]. By denoting it as BooL1 in the stack comment to reduce its size and improve readability.
In the fourth, we take out the squares of the sides, and remove BooL1 further, we will need it at the end.
In the fifth we compare the next three, the second equality of three. We get BooL
The sixth is similar to the fourth. Ready for the last comparison.
Last comparison.
In the eighth, two “OR” operators, logical or, prepare the answer for the ninth line.
: BOOL32 ( A B C -> )
DUP * SWAP DUP * ROT DUP * \ A B C -> C^2 B^2 A^2
DUP 2OVER + = \ C^2 B^2 A^2-> C^2 B^2 A^2 [A^2=C^2+B^2]=BooL1
SWAP 2SWAP \ C^2 B^2 A^2 BooL1-> BooL1 A^2 C^2 B^2
DUP 2OVER + = \ BooL1 A^2 C^2 B^2-> BooL1 A^2 C^2 B^2 [B^2=A^2+C^2]=BooL2
SWAP 2SWAP \ BooL1 A^2 C^2 B^2 BooL2-> BooL1 BooL2 B^2 A^2 C^2
ROT ROT + = \ BooL1 BooL2 B^2 A^2 C^2 -> BooL1 BooL2 [C^2=B^2+A^2]= BooL3
OR OR \ BooL1 BooL2 BooL3 -> [BooL1]OR[BooL2]OR[[BooL3]
B.
;
3 4 5 BOOL32
True Ok
4 3 5 BOOL32
True Ok
3 5 4 BOOL32
True Ok
4 5 3 BOOL32
True Ok
5 3 4 BOOL32
True Ok
5 4 3 BOOL32
True Ok
1 2 3 BOOL32
False Ok
Example 33. There is a triangle with sides A, B, C? In a triangle 0<A<B+C and 0<B<A+C and 0<C<A+B. Reminiscent of the previous one, without squaring, equality is replaced by inequality, and logical disjunction by conjunction.
The first line is without comment.
From the second to the fourth, all sides are checked for positivity, otherwise the triangle does not exist.
Fifth, if at least one of the sides is not positive, then the result is {[B>0]AND[A>0]AND[C>0]}=0, and the check “0 =” will leave true, which will make the code after “IF” work ", where the stack will be cleared of the remaining arguments "DROP 2DROP", code "0 B." will print "False Ok" and the "EXIT" statement will end the execution of the word. From the sixth to the tenth, the main verification of the problem conditions is performed. The eleventh one combines into the final result, and the twelfth one prints the answer.
: BOOL33 ( A B C -> )
DUP 2OVER 0 > \ A B C -> A B C C A B>0
SWAP 0 > ROT 0 > \ A B C C A B>0 -> A B C B>0 A>0 C>0
AND AND \ A B C B>0 A>0 C>0 -> A B C {[B>0]AND[A>0]AND[C>0]}
0 = IF DROP 2DROP 0 B. EXIT THEN
DUP 2OVER + < \ A B C -> A B C [C<A+B]=BooL1
SWAP 2SWAP \ A B C BooL1 -> BooL1 C A B
DUP 2OVER + < \ BooL1 C A B -> BooL1 C A B [B<C+A]=BooL2
SWAP 2SWAP \ BooL1 C A B BooL2 -> BooL1 BooL2 B C A
ROT ROT + < \ BooL1 BooL2 B C A -> BooL1 BooL2 [A<B+C]=BooL3
AND AND \ BooL1 BooL2 BooL3 -> [BooL1]AND[BooL2]AND[BooL3]
B.
;
1 2 3 BOOL33
False Ok
2 2 2 BOOL33
True Ok
10 5 1 BOOL33
False Ok
5 7 8 BOOL33
True Ok
Example 34. Check the square on the chessboard is white? Given X and Y coordinates (0<[X,Y]<9). It is known that the lower left field with coordinates (1,1) is black. Let’s add the coordinates X+Y, for the field (1,1) – “1+1=2” is even, for the adjacent white one it is odd, for the top white one it is odd. Conclusion: if the sum of the coordinates is odd, then the field is white, that is, true, otherwise false. : BOOL34 ( X Y -> ) + 2 MOD \ Remainder{[X+Y]/2} B. ; 1 1 BOOL34 False Ok 1 2 BOOL34 True Ok 2 1 BOOL34 True Ok 2 2 BOOL34 False Ok
Example 35. Using the coordinates of two squares of a chessboard, can you determine whether they are the same color or not? From the previous example, we found out the connection between color and parity. Same color means same parity. If the parity is the same, then true, otherwise false.
: BOOL35 ( X1 Y1 X2 Y2 -> )
+ 2 MOD \ X1 Y1 X2 Y2 -> X1 Y1 Remainder{[X2+Y2]/2}
ROT ROT \ X1 Y1 Remainder{[X2+Y2]/2} -> Remainder{[X2+Y2]/2} X1 Y1
+ 2 MOD \ Remainder{[X2+Y2]/2} X1 Y1 -> Remainder{[X2+Y2]/2} Remainder{[X1+Y1]/2}
= \ Remainder{[X2+Y2]/2} Remainder{[X1+Y1]/2} -> Remainder{[X2+Y2]/2}=Remainder{[X1+Y1]/2}
B.
;
1 1 2 2 BOOL35
True Ok
1 1 1 2 BOOL35
False Ok
Example 36. Is it true that a rook can move from square (X1,Y1) to square (X2,Y2) in one move? A rook can move in one move only if the X's or Y's are equal. Because the rook moves either horizontally or vertically, which means that in one move either X or Y will change.
: BOOL36 ( X1 Y1 X2 Y2 -> )
ROT = \ X1 Y1 X2 Y2 -> X1 X2 Y2=Y1
ROT ROT = \ X1 X2 Y2=Y1 -> Y2=Y1 X1=X2
OR \ Y2=Y1 X1=X2 -> {Y2=Y1}OR{X1=X2}
B.
;
1 8 3 8 BOOL36
True Ok
3 5 3 8 BOOL36
True Ok
1 1 5 5 BOOL36
False Ok
Example 37. Can a king move from square (X1,Y1) to square (X2,Y2) in one move? Since the king can move one square in any direction in one move, this means that |X1-X2|<2 (<=1) and |Y1-Y2|<2 (<=1).
: BOOL37 ( X1 Y1 X2 Y2 -> )
ROT - ABS 2 < \ X1 Y1 X2 Y2 -> X1 X2 |Y2-Y1|<2=Bool1
ROT ROT - ABS 2 <\X1 X2 Bool1 -> Bool1 |X1-X2|<2= Bool2
AND \ Bool1 Bool2 -> [Bool1]AND[Bool2]
B.
;
1 2 2 1 BOOL37
True Ok
1 1 2 2 BOOL37
True Ok
1 2 2 3 BOOL37
True Ok
1 1 3 3 BOOL37
False Ok
Example 38. Can a bishop move from square (X1,Y1) to square (X2,Y2) in one move? Since the bishop moves diagonally, the transition is possible if |X1-X2|=|Y1-Y2|. We obtain the code from the previous example by removing the “<2” check and replacing the “AND” operator with “=”.
: BOOL38 ( X1 Y1 X2 Y2 -> )
ROT - ABS \ X1 Y1 X2 Y2 -> X1 X2 |Y2-Y1|
ROT ROT - ABS\X1 X2 |Y2-Y1|->|Y2-Y1| |X1-X2|
= \ |Y2-Y1| |X1-X2|-> |Y2-Y1|=|X1-X2|
B.
;
2 3 4 5 BOOL38
True Ok
2 3 1 2 BOOL38
True Ok
2 3 1 4 BOOL38
True Ok
2 3 3 2 BOOL38
True Ok
1 1 5 4 BOOL38
False Ok
Example 39. Can the queen move from square (X1,Y1) to square (X2,Y2) in one move? The queen moves like a rook and bishop combined. This example is a combination of examples 36 and 38.
: BOOL39 ( X1 Y1 X2 Y2 -> )
2OVER 2OVER \ X1 Y1 X2 Y2 -> X1 Y1 X2 Y2 X1 Y1 X2 Y2
ROT = \ X1 Y1 X2 Y2 X1 Y1 X2 Y2 -> X1 Y1 X2 Y2 X1 X2 Y2=Y1
ROT ROT = \ X1 Y1 X2 Y2 X1 X2 Y2=Y1 -> X1 Y1 X2 Y2 Y2=Y1 X1=X2
OR \ X1 Y1 X2 Y2 Y2=Y1 X1=X2 -> X1 Y1 X2 Y2 {Y2=Y1}OR{X1=X2}
IF." True” 2DROP 2DROP EXIT THEN
ROT - ABS \ X1 Y1 X2 Y2 -> X1 X2 |Y2-Y1|
ROT ROT - ABS\X1 X2 |Y2-Y1|->|Y2-Y1| |X1-X2|
= \ |Y2-Y1| |X1-X2|-> |Y2-Y1|=|X1-X2|
B.
;
1 1 8 8 BOOL39
True Ok
1 1 8 1 BOOL39
True Ok
1 1 3 4 BOOL39
False Ok
The resulting code is trivial.
The first line is a title with a description.
Second, we duplicate the parameters to check for the move of a bishop or rook.
From the third to fifth lines - checking the equality of either the abscissa or ordinate “{Y2=Y1}OR{X1=X2}”.
Sixth - if the check is true, then print “True”, delete the remaining parameters, they will no longer be useful, since the second check is not required, then exit.
From the seventh to the ninth, it is performed when the first check is false, then we check the equality of the difference between the ordinate and abscissa modules “|Y2-Y1|=|X1-X2|”.
The tenth line is standard processing of the result of the second check.
We can say that an analogue of “lazy calculations” is implemented here: when the queen’s move is similar to the rook’s move, then nothing further needs to be done (the move is possible). Otherwise, you need to check the bishop's moves and analyze the result in a familiar way.
Example 40. Can a knight move from square (X1,Y1) to square (X2,Y2) in one move? The horse moves with the letter “G”, its mirror image and rotation of the first two options by 90, 180 and 270 degrees. The condition for checking the knight's move will be {|Y2-Y1|=1 and |X1-X2|=2} or {|Y2-Y1|=2 and |X1-X2|=1}.
: BOOL40 ( X1 Y1 X2 Y2 -> )
ROT - ABS \ X1 Y1 X2 Y2 -> X1 X2 |Y2-Y1|
ROT ROT - ABS\X1 X2 |Y2-Y1|->|Y2-Y1| |X1-X2|
* 2 = \ |Y2-Y1| |X1-X2| -> |Y2-Y1|*|X1-X2|=2
B.
;
Possible results |Y2-Y1| and |X1-X2| are equal from 1 to 7, if we assume that X1<>X2 and Y2<>Y1 (otherwise from 0 to 7). We are interested in the option when {|Y2-Y1|=1 and |X1-X2|=2} or {|Y2-Y1|=2 and |X1-X2|=1}. Let's replace this check with |X1-X2|*|Y2-Y1|=2. The equality {1..7}*{1..7}=2 is true in the only case when {|Y2-Y1|=1 and |X1-X2|=2} or {|Y2-Y1|=2) and |X1-X2|=1}. For those to whom this is not obvious, they can go through all the options.
Let's say (X1,Y1)=(3,3), then all the knight's moves will be: (2;5),(4;5),(5;4),(5;2),(2;1),( 4;1),(1;2),(1;4). Let's check the work of the written word using these data:
3 3 2 5 BOOL40
True Ok
3 3 4 5 BOOL40
True Ok
3 3 5 2 BOOL40
True Ok
3 3 5 4 BOOL40
True Ok
3 3 2 1 BOOL40
True Ok
3 3 4 1 BOOL40
True Ok
3 3 1 2 BOOL40
True Ok
3 3 1 4 BOOL40
True Ok
The most interesting thing is that this algorithm correctly processes the “3 3 3 3 BOOL40” option, although it was not provided at the beginning. Check all other moves that do not coincide with the knight's move yourself. Confirm that the result will be “False Ok”. There will be 5*5 such options - 8 knight moves. And to check all 64 cells, you can use the test word:
: TEST-BOOL40 ( -> )
9 1 DO
9 1 DO
3 3 I J BOOL40 9 EMIT
LOOP CR
LOOP
;
The test word “TEST-BOOL40” displays the table from left to right and top to bottom, which means cell (1;1) is the upper left corner, this must be taken into account when checking the results.
For beauty, we can rewrite the word “B.” Thus:
: B. (Bool ->) IF." TO" ELSE." -" THEN;
Please note that after changes in the word “B.”, you need to re-enter the words “BOOL40” and “TEST-BOOL40”, otherwise the result will be the same, without changes. As a result, we will see the following on the screen:
TEST-BOOL40
- K - K - - - -
K - - - K - - -
- - - - - - - -
K - - - K - - -
- K - K - - - -
- - - - - - - -
- - - - - - - -
- - - - - - - -
Ok