Back
Close

ASCII Art with Logo Language, Part 3

Statement

 Goal

Your job is to extend again the Logo language developed in ASCII Art with Logo Language, part 2 with variables and giving the Turtle the ability to move in any direction.

Commands from part one and two (not modified):
SETPC pen: uses cyclically the characters in pen as Turtle pen.
CS character: CLEARSCREEN. Clears the screen with the specified symbol (only printable ASCII excluding space).
PU: PENUP. Sets the turtle to move without drawing.
PD: PENDOWN. Turtle leaves a symbol when moving.

Modified commands:
RP expression [commands]: REPEAT. This instruction repeats the commands that are inside the square brackets the number of times indicated by the expression parameter (only positive integer). REPEAT command can be nested. If expression is negative or float, get the absolute value of its integer part.
FD expression: FORWARD. Moves Turtle forward for number of times specified (absolute value of the integer part).
RT expression: RIGHT. Turns Turtle right for number of degrees specified (only integer part). Negative numbers are possible (and they turn the Turtle to the left).
LT expression: LEFT. Turns Turtle left for number of degrees specified (only integer part). Negative numbers turn the Turtle to the right.

New commands:
MK "varname expression: MAKE. Assign the expression's value to the variable varname.
For example:
MK "dummyvar (12+3)-2

expression is a combination of numbers (integer and float with . as decimal separator) and the four operators + - / *, possibly with brackets ( ) to change the order of priority of calculation, and variables referenced by : followed by the variable name (no spaces).
For example:
MK "dummyvar (12+3)-2;MK "dummy2 15*((12+3.5)-:dummyvar)

The value of :dummy2 is 37.5
IF boolean expression [commands]: Conditional. The boolean expression is limited to expression = > < <> expression, where <> means "not equal to". If the boolean expression is true, the commands will be executed, else jump to the next command.

Procedure definition:
All the procedures should be defined at the beginning of the program.
STOP: exit from procedure.
TO procedure_name :param END: procedure definition, with only one fixed parameter. Recursion is possible. To call a procedure simply put the procedure_name and an expression as parameter.
It is not possible to use a parameter with the same name of a variable. Inside a procedure it is possible to use global variables but you can't change their value. The variables defined inside a procedure are locals.
For example
to spiral :size
if :size > 30 [stop]
fd :size; rt 15
spiral :size *1.02
end

Drawing lines:
Since the RT and LT commands now accept expressions, it is possible to draw lines with any integer inclination. You should implement the Bresenham's line algorithm, in particular the version that use Bresenham's principles of integer incremental error to perform all octant line draws, balancing the positive and negative error between the x and y coordinates. See the wikipedia link in reference to see all the details.

To draw a line, you will need to determine the target coordinates using the following formulas, where angle is the current Turtle inclination and steps the parameter of FD command:
x0,y0 = current Turtle position
x1 = x0+round(steps*round(cos(angle),precision))
y1 = y0+round(steps*round(sin(angle),precision))
plotLine(x0,y0,x1,y1)

Please note that the rounding to use is 'Rounding Half Even' and the precision is set to 5 digits.
Also note that the Turtle leaves a symbol in the starting position each time it moves with pen down, but not in the final position.

Additional notes:
Semi-colons ; are used to separate instructions in a line of instructions. It may also be optionally used at the end of a line of instructions. Command keyword or a procedure name and its arguments/parameters are always separated by one or more space characters.
A variable name is always followed by ;, [, ], a newline, an end-of-line, or one or more space characters. Other than the above, all other space characters are optional.
A command keyword may be used as a procedure name or a variable name.
All turtle steps will be drawn using the current PU/PD and SETPC settings.
As is part two, Turtle starts with an angle of 90 degree (heading North), with the pen down and the initial symbol set to #.

References:
Part 1 https://www.codingame.com/training/medium/ascii-art-with-logo-language
Part 2 https://www.codingame.com/training/medium/ascii-art-with-logo-language-part-2
Bresenham's line algorithm
https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
in particular see note 2 Zingl, Alois

https://en.wikipedia.org/wiki/UCBLogo
Input
Line 1: An integer N, indicating the program's number of lines.
Next N lines: lines of text with Logo instructions.
Output
The ASCII Art generated.
Constraints
1 ≤ N ≤ 2000
Example
Input
3
rt 45;setpc *;
mk "a 90;mk "lt 5;mk "lp 4
rp :lp [fd :lt;rt :a]
Output
    *
   * *
  *   *
 *     *
*       *
 *     *
  *   *
   * *
    *

Tags
Ascii ArtInterpretersBresenham's algorithm

Difficulty
Hard

Test cases
Diamond Test
Input
3 rt 45;setpc *; mk "a 90;mk "lt 5;mk "lp 4 rp :lp [fd :lt;rt :a]
Output
* * * * * * * * * * * * * * * *

Validator 1 Validator
Input
3 rt 45;setpc *; mk "a 90;mk "lt 7;mk "lp 4 rp :lp [fd :lt;rt :a]
Output
* * * * * * * * * * * * * * * * * * * *

Star Test
Input
5 rt 90;setpc 4 mk "angle 60; mk "l 4; mk "lp 3 rp :lp [fd :l;lt :angle;fd :l;rt 2*:angle;fd :l;lt :angle;fd :l; rt 2*:angle]
Output
4 4 4 4 4 44444 44444 4 4 4 4 4 4 4 4 4 4 44444 44444 4 4 4 4 4

Validator 2 Validator
Input
5 rt 90;setpc 6 mk "angle 60; mk "l 6; mk "lp 3 rp :lp [fd :l;lt :angle;fd :l;rt 2*:angle;fd :l;lt :angle;fd :l; rt 2*:angle]
Output
6 6 6 6 6 6 6 6 6 6666666 6666666 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6666666 6666666 6 6 6 6 6 6 6 6 6

Circle Test
Input
6 rt 90;setpc * mk "dir 5; mk "l 8; mk "lp :l; mk "angle 360/:l; rp :lp [fd :dir;lt :angle]
Output
****** * * * * * * * * * * * * * * * * * * * * * * * * ******

Validator 3 Validator
Input
6 rt 90;setpc * mk "dir 5; mk "l 10; mk "lp :l; mk "angle 360/:l; rp :lp [fd :dir;lt :angle]
Output
****** ** * * ** * * * * * * * * * * * * * * * * * * * * * * ** * * ** ******

Spiral Test
Input
10 to spiral :size if :size > (6-:char) [stop] fd :size; rt 15 spiral :size*1.02 end mk "char 1; if :char = 1 [setpc *] if :char = 2 [setpc +] mk "l 1 spiral :l
Output
********* *** **** ** ** * ** * * * * * **** * * **** *** * * ** * * * * * ******** * * * ** * * * * ** * * * * * **** * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** * **** * * * * * * * ** * * * * *** * * **** * * * * * ** ** *** ** *******

Validator 6 Validator
Input
10 to spiral :size if :size > (6-:char) [stop] fd :size; rt 15 spiral :size*1.02 end mk "char 2; if :char = 1 [setpc *] if :char = 2 [setpc +] mk "l 1 spiral :l
Output
++++ ++++ +++ + ++ + + + ++++++++ + + ++ + + + ++ + + + + ++++ + + + + + + + + + ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ++++ + + + + + + + ++ + + + + +++ + + ++++ + + + + + ++ ++ +++ ++ +++++++

Square Test
Input
9 to square :lato rp 4[fd :lato;rt 90] end cs . setpc * mk "l 5 if :l = 5 [setpc *+] if :l <> 5 [setpc +*] square :l
Output
+*+*+* *....+ +....* *....+ +....* *+*+*+

Validator 7 Validator
Input
9 to square :lato rp 4[fd :lato;rt 90] end cs . setpc * mk "l 8 if :l = 5 [setpc *+] if :l <> 5 [setpc +*] square :l
Output
+*+*+*+*+ *.......* +.......+ *.......* +.......+ *.......* +.......+ *.......* +*+*+*+*+

Fibonacci Test
Input
13 to fibo :a mk "x 1 mk "y 1 mk "lp (:a-2) if :a < 3 [mk "r 1] if :a > 2 [ rp :lp [ mk "r (:x+:y);mk "x :y;mk "y :r] ] fd :r end setpc 1 cs . mk "a 1 rt 90 rp 10 [pd;fibo :a;pu;fd 1;mk "a :a+1]
Output
1.1.11.111.11111.11111111.1111111111111.111111111111111111111.1111111111111111111111111111111111.1111111111111111111111111111111111111111111111111111111

Validator 4 Validator
Input
13 to fibo :a mk "x 1 mk "y 1 mk "lp (:a-2) if :a < 3 [mk "r 1] if :a > 2 [ rp :lp [ mk "r (:x+:y);mk "x :y;mk "y :r] ] fd :r end setpc 2 cs . mk "a 2 rt 90 rp 10 [pd;fibo :a;pu;fd 1;mk "a :a+1]
Output
2.22.222.22222.22222222.2222222222222.222222222222222222222.2222222222222222222222222222222222.2222222222222222222222222222222222222222222222222222222.22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

Spiral 2 Test
Input
6 rt 90;setpc 2 mk "l 5; mk "lp 10; mk "angle 90; lt :angle/2; rp :lp [fd :l;rt :angle;mk "angle :angle+1;mk "l :l+2]
Output
222 222 2 222 2 2222 22 2 222 2 2 2 222 2 2 2 22 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 22 2 2 2 2 22 2 2 22 22 2 22 2 2 2 2 2 2 2 22 2 2 2 22 2 2 2 22 2 2 2 2 22 2 2 2 2 2 2 22 2 2 22 2 2 22 2 22

Validator 9 Validator
Input
6 rt 90;setpc 3 mk "l 5; mk "lp 10; mk "angle 90; lt :angle/3; rp :lp [fd :l;rt :angle;mk "angle :angle+1;mk "l :l+2]
Output
333333333333 3333333333 3 3 333 3 3 33 3 3 3 33 3 3 3 33 3 3 3 33 3 3 333 33 3 3 33 33 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 33 33 3 3 33 33 3 3 33 333 3 33 3333 3 3 3333 3 3 3333 3 333 3 3 3

Banner Test
Input
32 to letter :l if :l = 1 [letter_l :size] if :l = 2 [letter_o :size] if :l = 3 [letter_g :size] end to letter_l :s rt 180; pd fd :s; lt 90; fd :sx pu; fd 1; lt 90; fd :s end to letter_o :s rt 90; pd fd :sx-1;rt 90;fd :s;rt 90;fd :sx-1;rt 90;fd :s rt 90;pu;fd :sx+1;lt 90 end to letter_g :s rt 90; pd fd :sx-1; lt 180;fd :sx-1; lt 90;fd :s; lt 90;fd :sx-1;lt 90;fd 2 pu;fd :s-2;rt 90;fd 2;lt 90 end setpc @ mk "sx 4 mk "size 3 mk "l 1 mk "o 2 mk "g 3 rp 8 [ letter :l;letter :o;letter :g;letter :o lt 90;fd :sx*5;rt 90 pu;rt 180;fd (:size+1);rt 90;fd 1;rt 180 ]
Output
@@@@ @ @ @ @ @@@@ @ @@ @ @ @ @ @@@@ @@@@ @ @ @ @ @@@@ @ @ @ @@@@ @@@@ @@@@ @@@@ @@@@ @ @@@@ @@@@ @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@@@ @@@@ @@@@ @ @@@@ @@@@ @@@@ @@@@ @@@@ @ @ @ @@@@ @ @ @ @ @@@@ @@@@ @ @ @ @ @@ @ @@@@ @ @ @ @ @@@@

Validator 8 Validator
Input
32 to letter :l if :l = 1 [letter_l :size] if :l = 2 [letter_o :size] if :l = 3 [letter_g :size] end to letter_l :s rt 180; pd fd :s; lt 90; fd :sx pu; fd 1; lt 90; fd :s end to letter_o :s rt 90; pd fd :sx-1;rt 90;fd :s;rt 90;fd :sx-1;rt 90;fd :s rt 90;pu;fd :sx+1;lt 90 end to letter_g :s rt 90; pd fd :sx-1; lt 180;fd :sx-1; lt 90;fd :s; lt 90;fd :sx-1;lt 90;fd 2 pu;fd :s-2;rt 90;fd 2;lt 90 end setpc @ mk "sx 4 mk "size 2 mk "l 1 mk "o 2 mk "g 3 rp 8 [ letter :l;letter :o;letter :g;letter :o lt 90;fd :sx*5;rt 90 pu;rt 180;fd (:size+1);rt 90;fd 1;rt 180 ]
Output
@@@ @ @ @ @ @@@ @@@ @ @ @ @ @@@ @@@ @ @ @ @ @@@ @ @ @ @@@ @@@@ @@@@ @@@@ @@@@ @ @@@@ @@@@ @@@@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @@@@ @@@@ @@@@ @ @@@@ @@@@ @@@@ @@@@ @@@ @ @ @ @@@ @ @ @ @ @@@ @@@ @ @ @ @ @@@ @@@ @ @ @ @ @@@

Numbers Test
Input
34 to printnum :a mk "r 9 mk "w 1 rp :r [mk "w :w*10] rp :r+1 [ mk "c :a/:w if :c < 1 [setpc 0;fd 1;mk "c 10;] if :c < 2 [setpc 1;fd 1;mk "c 10;mk "a :a-1*:w] if :c < 3 [setpc 2;fd 1;mk "c 10;mk "a :a-2*:w] if :c < 4 [setpc 3;fd 1;mk "c 10;mk "a :a-3*:w] if :c < 5 [setpc 4;fd 1;mk "c 10;mk "a :a-4*:w] if :c < 6 [setpc 5;fd 1;mk "c 10;mk "a :a-5*:w] if :c < 7 [setpc 6;fd 1;mk "c 10;mk "a :a-6*:w] if :c < 8 [setpc 7;fd 1;mk "c 10;mk "a :a-7*:w] if :c < 9 [setpc 8;fd 1;mk "c 10;mk "a :a-8*:w] if :c < 10 [setpc 9;fd 1;mk "c 10;mk "a :a-9*:w] mk "w :w/10 ] pu;rt 180;fd :r+1;lt 90;fd 1;lt 90;pd end rt 90 mk "a 10 mk "b 2 mk "c 30 mk "d12 4 rp 20 [ mk "e (:a+:b)*(:c-:d12) mk "r ((:a+:b)*(:a-:b)+(:d12/:a))*:e printnum :r mk "a :a+1 mk "b :b+1 mk "c :c+1 mk "d12 :d12+1 ]
Output
0000030076 0000040933 0000053456 0000067644 0000083497 0000101015 0000120198 0000141045 0000163557 0000187733 0000213574 0000241079 0000270248 0000301082 0000333580 0000367741 0000403568 0000441058 0000480212 0000521031

Validator 5 Validator
Input
34 to printnum :a mk "r 9 mk "w 1 rp :r [mk "w :w*10] rp :r+1 [ mk "c :a/:w if :c < 1 [setpc 0;fd 1;mk "c 10;] if :c < 2 [setpc 1;fd 1;mk "c 10;mk "a :a-1*:w] if :c < 3 [setpc 2;fd 1;mk "c 10;mk "a :a-2*:w] if :c < 4 [setpc 3;fd 1;mk "c 10;mk "a :a-3*:w] if :c < 5 [setpc 4;fd 1;mk "c 10;mk "a :a-4*:w] if :c < 6 [setpc 5;fd 1;mk "c 10;mk "a :a-5*:w] if :c < 7 [setpc 6;fd 1;mk "c 10;mk "a :a-6*:w] if :c < 8 [setpc 7;fd 1;mk "c 10;mk "a :a-7*:w] if :c < 9 [setpc 8;fd 1;mk "c 10;mk "a :a-8*:w] if :c < 10 [setpc 9;fd 1;mk "c 10;mk "a :a-9*:w] mk "w :w/10 ] pu;rt 180;fd :r+1;lt 90;fd 1;lt 90;pd end rt 90 mk "a 20 mk "b 2 mk "c 30 mk "d12 4 rp 20 [ mk "e (:a+:b)*(:c-:d12) mk "r ((:a+:b)*(:a-:b)+(:d12/:a))*:e printnum :r mk "a :a+1 mk "b :b+1 mk "c :c+1 mk "d12 :d12+1 ]
Output
0000226626 0000269716 0000316552 0000367133 0000421460 0000479531 0000541348 0000606909 0000676215 0000749266 0000826061 0000906601 0000990886 0001078914 0001170688 0001266205 0001365468 0001468474 0001575225 0001685720

Solution language

Solution

Stub generator input