Golf (A)

From Esolang
Jump to navigation Jump to search

Golf is a language created by User:A. This language is created to only have one loop: the repeat loop, because Logo only has this kind of loop other than recursion. (This language is inspired by Logo, by the way.)

The overall syntax used in this document

  • * stands for degree(s)
  • [abc...] stands for pick any character inside this blocked string
  • (operand_name) gives a name to the operand(s) (if any) to an instruction.

The golfing language called "Golf"

The codepage of Golf is ↑ ↓ ← → ↖ ↙ ↗ ↘ a a b b c c d d e e f f g g h h i i j j k k l l m m n n o o p p q q r r s s t t u u v v w w x x y y z z A A B B C C D D E E F F G G H H I I J J K K L L M M N N O O P P Q Q R R S S T T U U V V W W X X Y Y Z Z 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 ` ` ” " ’ ' “ " ‘ ' _ _ - - ~ ~ = = + + \ \ | | / / ( ( ) ) [ [ ] ] 【 [ 】 ] { { } } < < > > . . , , ; ; : : ! ! ^ ^ % % # # @ @ $ $ & & ? ? * * 。 ., with potential extensions.

Recently I was thinking about making an ASCII-art language called Golf. The idea is based on turtles and copying them.

In order to answer questions like creating a pyramid, e.g. for the input 3, output

  #
 ###
#####

An ASCII-art language is obviously neccecary. The first solution that came into my mind is:

S↙↘#F

The instruction means that the current turtle (looking like #) gets split into two turtles. The original turtle gets kept and is still the current turtle. E.g. if you apply S↙↘ over a turtle:

#

You get:

 #
# #

See, two new duplicate turtles!

How does filling work though?

The next part of my notes about Golf is how should filling work. Initially the idea was that you get to move to the closest turtle 90 degrees upright from the current turtle, left being first than the right. But I later abandoned this confusing and useless idea, because it makes

#   #

  #

#   #

Render like:

#   #
|\ /|
| # |
|   |
#---#

Which obvously is not a useful ASCII picture.

#   #
|\ /|
|@#@|
|@@@|
#---#

Our desired picture was:

#---#
 \ / 
  #  
 / \
#---#

So, here's our current idea:

Step 1. Determine the angle.

The direction of a point is like this:

2 3 4
 \|/
1-#-5
 /|\
8 7 6

Where the order of the connected points strictly follow the numbered points. (The closer points are selected first, of course!)

Step 2. The logic.

In this section * is a shorthand for "degree(s)".

We take a real example here (turtles count as a point, of course! :) ):

.   .

  #

.   .

We start from the turtle. Since we don't have a point at 0*, we select the point 45* (all four points are of equal distance):

#   .
 \
  .

.   .

Now the closest point is the right one (we don't select the bottom one because it is further away in the direction table above):

.---#
 \
  .

.   .

The closest point is the initial point (we don't select the bottom one because it's further away character-wise):

.---.
 \ /
  #

.   .

Since the top two points are selected, we select the point at 225*:

.---.
 \ /
  .
   \
.   #

And after 2 iterations:

.---.
 \ /
  #
 / \
.---.

And then it came to our fill instruction

Hope you enjoyed the clear description of the process!

#####
 ###
  #
 ###
#####

Modifying the answer to the pyramid problem

Our answer was this:

S↙↘#F

What if we want to have this for an input of 4?

.
..
...
....

Fortunately the answer to that is quite simple (You need a flag that turns off the turtle's visibility to run this correctly):

S↓↘.F

Sum-up time!

  • S(a)(b) "splits" the current turtle into two different turtles. We make two different new turtles while the original is kept; the two operations (a) and (b) are applied to the two new turtles separately.
  • (a)[↑↓←→↖↙↗↘] stands for moving the turtle (a) ASCII characters in the pointed direction.
  • (a)F Fills the result of the canvas with the character(s) (a). The grouping and filling is already documented above.
  • is a shorthand for S↙↘.

The implicit input

I feel the neccecity of documenting the implicit input. If the stack is empty and a command requires more operands, the input would be taken as operands. So for our example program:

S↓↘.F

Obviously, the and needs operands, right? The implicit input is provided like this:

S{I↓}{I↘}.F

The {} brackets here is an invalid grouping signifyer for clarification purposes. Now you can see that the two turtles move the input number of ASCII characters respectively. (Golf has its own kind of grouping operations, but normally that is unneccecary.)

The string syntax

Normally Golf's string syntax is unneccecary, since most strings are written in pure ASCII, e.g.

Hello, World!

If they aren't used, these characters are automatically appended (from left to right) into the first position before the current turtle, as the turtle moves right a position. (i.e. the turtle makes the current character its trail as it moves right)

Since the turtle art begins at the 0x0 position, that's why the program Hello, World! prints the exact text given:

#
H#
He#
...
Hello, World#
Hello, World!#

Golf doesn't provide a string syntax. However, we would never need to type in characters in Golf's codepage.

Canvas extension

The Golf canvas automatically extends itself when neccecary. For example, if we need to paint this:

\   
 \  
  \ 
foo\

We need to do: foo4↖

Before the <gcode>4↖ the canvas looks like this:

foo#

After:

\
 \
  \
foo\

The action of fill over a string (i.e. "rainbow-paint")

Of course we need to make an action of Fill over >1-lengthed strings, to prevent errors. Say we have this program (Strings in Golf are denoted using “...“):

....
....
....
....“# “F

This false-paints a checkerboard:

# # 
# # 
# # 
# # 

However, for a 3x3 grid:

# #
 # 
# #

This feature is rarely useful for actual golfing competitions.

Task: Create a 10x10 grid of asterisks.

Here comes our notation for numbers! It is exactly decimal notation, the catch is that you need to use full-width text to denote them:

10

This number denotes exactly what it looks like - ten.

To do this successfully we need to introduce another brand-new operation:

  • J(a)(b) - Performs (a) and (b) respectively (and sequentially) to all of the turtles. If the number of turtles on the canvas <= the number of instructions performed, (n) new turtles are created at the same position as the current turtle (n is the number of instructions performed), where turtles follow the top-to-bottom priority rule. The bottom turtle is left untouched; it is made for a copy of the current turtle.

But, what is the sequence of execution of the turtles?

Don't be over excited, let's take 9 turtles as an example:

1 2 3
4 5 6
7 8 9

You will see that the execution is quite obvious: left to right, with the top item as a priority.

A pretty ungolfed program and explanation

10S↓→10J↓→

Here is a sample execution:

(S↓→)      (10→)
   #--------#
   |        |
   |        |
   |        |
   |        |
   |        |
   |        |
   |        |
   |        |
   #--------#
(10↓)     (J↓→)

Golfing our program

Our program is quite short, but we see that there are lots of repetition inside our program. What can be done to this?

A boring solution would be to assign the number 10 to the instruction , but that doesn't help much:

TS↓→TJ↓→

However, we soon find that the thing that does is already done by , yielding the following program with even more repetition:

TJ↓→TJ↓→

Golf has an instruction for repeating a block twice - the instruction. (Blocks are denoted as parentheses, i.e. (...), in Golf.)

Let's first do this in a block:

(TJ↓→)

Next we apply the twice function:

(TJ↓→)t

Note that the function is an automatic block-ender, this program can be golfed into:

(TJ↓→t

And since there is a block-starting mechanism at the beginning of the program, this turns into:

TJ↓→t

Wow, 6 bytes. But what can be done to it?

A pretty simple optimisation is to use shorthands provided by Golf. That's right, use to do J↓→. So this program becomes:

T@t

But I feel that this is pretty optimal. Anyway, it even beats the compressed Stax answer!

Task: Make an ASCII Christmas tree!

A Christmas tree with an input of 3 looks like this:

  *
 ***
*****
  *

Our answer to that challenge would be (9 bytes):

S↙↘*F1+↓*

The explanation

Step 1 (S↙↘):

  #
 / \
#---#

Step 2 (*F):

The position of # is the current turtle.
  #
 ***
*****

Step 3 (1+↓):

Stack: 
[I]
[I,1] (+)
[I+1] (↓)
Canvas:
  |
 *|*
**|**
  #

Step 4 (*):

  *
 ***
*****
  *#

All turtles are hidden (turn on via a flag). The +1 built-in will (probably) come in a later release of the language, but here is a preview. (Did you forget that is a shorthand of S↙↘?)

X*Fi↓*

Summary of the remaining (useless) instructions on the page

  • (a)(b)G - Draw a side-(a) polygon with a width of (b). I doubt that this would be useful at all.
  • (a)Q - Draws a square of side length (a), with the turtle on the top left corner. Example (3Q):
#**
***
***
  • - horizontally flips the canvas. You need an example? This:
#
##
###

Gets turned into this (note the white-space padding of the canvas):

  #
 ##
###
  • - Palindromization horizontally. For example, the above result gets turned into this:
  #
 ###
#####
  • +-*/ - does arithmetic over the two items upon the stack. “abc““123“+ would yield “abc123“ (i.e. string concatenation), and “abc“3* would yield “abcabcabc“ (i.e. string repetition).
  • (n)s - Set the current turtle to the (n)-th turtle on the canvas. The turtle numbering sequence is left to right and up to down.

Task: draw a cube

E.g. for a cube size of 2, this yields

  +----+
 /    /|
+----+ |
|    | +
|    |/
+----+

So, here's our code:

+pDI2*→(DI2/↙)A(DI↓5d)Aj

Introducing some more instructions:

  • (a)p, when given a length-one string, sets the turtle to that shape.
  • duplicates all turtles on the canvas.
  • (a)d means delete the selected (a)-th turtle, including all of its trails.
  • means join the unjoined nodes (including turtles).
  • ()A means apply to all turtles on the canvas.

The explanation of that

Let's say we have an input of 2. First let's make the turtle look like +...

1:input * 2
 /-1\
+----+

Task: draw an ASCII chessboard

  • s(a)(b)(c) - It's similar to , but it adds three more turtles to the canvas.
  • (a)R - Restrict the canvas to an (a)x(a) square. Any out-of-bounds drawing will be ignored.
  • (a)(...)X - Repeat the blocked program (a) times.
  • - Clear all the trails the turtles make.

Back to the program. To do that, we need to make a recursing turtle that does this over the whole chessboard (out of bounds painting is ignored):

[X][ ][/][ ]
[ ][X][ ][/]
[/][ ][X][ ]
[ ][/][ ][ ]

That's quite simple. Here's our code:

#pIRI(s↙↗↘)X

Hmm. That just seems too long. Explanation first:

#p - Set the turtle's shape to the hash.
IR - Restrict the canvas to (input)x(input).
I()X - Repeat input times ...
s↙↗↘ - Spit out 3 turtles, each moving in different directions

A simple optimization: and don't do anything upon the stack (remember, input is implicit when the stack is empty). So this can be golfed into:

#pR(s↙↗↘)X

Also, I've made a shorthand just for this situation - the instruction. Great!

#pR(y)X

Remember that brackets auto-complete at the end... (We don't need to clear the canvas because the turtles cover up all the trails!)

#pR(yX