16
\$\begingroup\$

Vyxal is a golfing language that has 500+ different commands (achieved through overloads), and is a known beater of Jelly, 05AB1E and most golfing languages.

Henceforth, it seems like a good idea to share some of the tips and tricks of the industry used to get terse programs in Vyxal.

One tip per answer, and no stupid tips like "oh remove comments and whitespace".

\$\endgroup\$
2
  • 7
    \$\begingroup\$ Can we actually enforce the "one tip per answer" please, unlike every other tips question ever? Even if answers are good, please downvote them if they contain more than one tip \$\endgroup\$
    – pxeger
    Apr 20, 2021 at 6:55
  • \$\begingroup\$ @pxeger I think that seems reasonable \$\endgroup\$
    – lyxal
    Apr 20, 2021 at 6:55

15 Answers 15

10
\$\begingroup\$

Brackets/Structures autocomplete

Totally not stolen from Tips for golfing in keg because Vyxal totally isn't supposed to be keg but 69 times better

If you have a structure (e.g. if/for/while/function/lambda) at the end of your program, and EOF follows, you can leave the closing bracket/semicolon off. Note that this only applies if you are submitting a full program.

For example:

9(0,)

Can be shortened to:

9(0,

And:

{:1=[1,]}

Can be shortened to:

{:1=[1,
\$\endgroup\$
8
\$\begingroup\$

Compress your strings and numbers

Nobody likes long strings. And nobody likes long numbers either. Luckily there's two ways of compressing strings and one way to compress numbers.

Dictionary Compression

Fun fact: Vyxal has access to a roughly 20k word "dictionary" (read: a list of words) which can be used to shorten strings with a) common English words or b) common 3 letter combinations.

To access the words in this dictionary, you need to get the String Compression Code (SCC) of the word and place it inside a normal string (the backtick ones). String Compression Code is simply a way of saying "the base 10 index of the word within the dictionary list converted to a bijective base-1611".

You can get the SCC of a word by using øD. For example:

`Hello`øD

(Try it Online!)

Tells you the SCC for Hello is ƈṡ. However, øD will also return the dictionary compression of a given string:

`Hello, World!`øD

Is turned into ƈṡ, ƛ€!.

øD is fully optimised and will always give you the shortest possible result. For example, compressing abcdef will return ėġḣ².

Base-255 Compression

But what if your string is a bunch of random letters that aren't in the dictionary at all? øD becomes useless for obvious reasons. In this case, you would use « delimited strings.

These strings take everything inside of them, converts it from a bijective base-255 (the vyxal codepage minus «) to base 10. It then converts that result to a bijective base-27 (the lower case alphabet plus space). Important: only stings containing lower case letters and spaces can be Base255 compressed3.

To get the Base255 compression of a string, you can use øc:

`ahroebeodbslnwksozlzbeoxbeodbsonwkdbdi`øc

Tells you that the compression is «∧pŀQb⟨ż₄∑ṄḞḊjẎɾ71(⁼~∇Ċβ«.

But what about numbers???

» strings have got you covered. øC will take an integer and return it converted to a bijective base-255 (the vyxal code page minus »:

69694204206969øC

Gives you »A⟩¾Ǐø7»

1: The bijective base 161 is simply the vyxal code page minus all printable ascii. This is so that SCCs can be embedded inside strings without creating a new string type.

2: Yeah, SCCs don't need to be surrounded by spaces - they can be inside ascii (a÷×b) or even next to each other (£÷¬¶). This is very intentional.

3: I originally allowed for upper and lower case inside base 255 strings, but found that strings are usually shorter when only allowing lower case.

\$\endgroup\$
6
\$\begingroup\$

Remember that mapping/filtering/reducing all cast numbers to ranges

Okay so say you want to apply something over the range [1, n] using Map, Filter or Reduce (or nverse reduce/foldr). Your first instinct might be to do this:

ɾλ....;M # or whatever command you're using

This is unnecessary, as the functional programming commands all cast numbers to range before doing their job, so:

λ....;M

is equivalent.

"But what if my range isn't [1, n], but instead [0, n] or [1, n) for example? Won't I need the corresponding range command?"

Well yes, but actually no if you use flags:

M Make implicit range generation start at 0 instead of 1

m Make implicit range generation end at n-1 instead of n

(source: flag help generated using the -h flag).

\$\endgroup\$
6
\$\begingroup\$

Use and for certain length checks

Say you have a string and you want to check whether its length is greater than 1, and the output only needs to be truthy or falsy.

You could go L1> for three bytes. Or, you could go for 1 byte.

Ḣ slices off the first character of a string and returns the rest, so running on a length 1 string returns an empty string, which is falsy; on a length ≥2 string, it returns a truthy non-empty string.

What about length >2? Just use ḢḢ, with the same logic as before, and still saving a byte.

Length = 1? There's literally a builtin for this - on strings or lists returns true only if the length is 1.

Length = 2? Just combine the two (Ḣ₃) - if you lop off a character and that string becomes length 1, it must've been length 2.

\$\endgroup\$
5
\$\begingroup\$

Use the multi-element lambdas if your lambda body is 1-3 bytes

Say you have the following:

λǐṅ;Ẋ

You can turn this into

‡ǐṅẊ

Because combines the next two elements (built-ins) into a single lambda. is for 1 element lambdas (good for when you want to reduce/filter/map a built-in without using v) and is for 3 element lambdas.

\$\endgroup\$
5
\$\begingroup\$

Use \ for single byte strings and for two byte strings

Sometimes you'll need a string of either one or two characters. You could do the following:

`A`
`AB`

But that has an extra backtick at the end. Instead, you can do this:

\A
‛AB

Important

\ pushes the next character as a string no matter what it is. will treat it as if the next two characters were wrapped in backticks (meaning that it will dictionary uncompress a single string compression code).

\$\endgroup\$
5
\$\begingroup\$

Use the nameless variable

Vyxal has variables, set by and accessed by . But did you know that there's a nameless variable?

You can access this by just going followed by a non-alphabetic character (it doesn't matter what, and that will still be run). Ditto with setting.

It works in for loops - try 4(|←,).

In other words, it's an extra register that can easily save you a couple of bytes.

\$\endgroup\$
5
\$\begingroup\$

Use - as a check for recursive functions

When recursing over a deep list, - will return a falsy value (0 / empty string) for scalars and a truthy value (list of 0) for lists.

Example of this in use

Note that this only works when you don't have empty lists.

does work for empty lists, returning a falsy value (empty string) for integers and a truthy value (list of lists) for lists. Thanks to lyxal for this one.

\$\endgroup\$
4
\$\begingroup\$

Custom base decompression

When you're compressing a large amount of data with a limited charset, as in here, you can use a base-255 integer (»...») and the custom base decompression function τ.

For example, say you want to compress this ascii-art:

  /    
 / \   
\   \  
 \ / \ 
  /   /
 / \ / 
\   \  
 \ / \ 
  /   /
 / \ / 
\   \  
 \ / \ 
  /   /
 / \ / 
\   \  
 \ /   
  /    

You can just map 0 to \, 1 to /, and 2 to to get 576780841113635223227691120919222477677740273185690732841 in base-3, which compresses to »ɾĠ^;√⟑•ȮṙDǓ…⟩P½≠1⅛²ė"÷₆Ŀ».

Then, you can take out your compression guide \/ , and append τ to turn it into base-3 with those as values.

Finally, you can split into 17 pieces (for 17 lines) and output joined by newlines - Try it Online!

\$\endgroup\$
3
\$\begingroup\$

Use of filter lambda

Filter lambda (') can filter out the items which are not truthy from the stack, so you don't need a lambda map and close it and then find out the Truthy indices.

This is a code using the lambda map

ƛǐG5>;T›

But if you use filter lambda, it can be shortened to

'ǐG5>

the last 3 commands are no longer needed!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ This also applies for map lambdas too \$\endgroup\$
    – lyxal
    Apr 20, 2021 at 7:46
3
\$\begingroup\$

Use the register instead of a variable

Sometimes, you're using a variable over and over again, and it's using so many bytes, right? Well, if you only have 1 variable, you can use the register instead, and save a byte every time you use it!

For example, say you want to do x * 2 and x ^ x. You could do:

3→x ←xd, ←x←xe,

This saves 3 to x, then retrieves it and doubles it, then retrieves twice, and exponentiates. However, x is being used 4 times, so that's 8 bytes in variable references alone! Using the register will shorten this code a lot:

3£ ¥d, ¥¥e,

Instead of saving to and retrieving from a variable, we're using the register, which can be accessed using only 1 byte. Anytime you're using variables, you can replace one of the variables with the register to save some bytes!

\$\endgroup\$
3
\$\begingroup\$

Converting characters to numbers in

When you want to convert characters to numbers, you have to use C, right? Well, there's another way. You can also use b. The b command, when used on a string, will convert each character to its ASCII value, then convert that to binary. You can then use B to convert that back to a decimal value!

`EEEE` b vB

Try it Online!

It's not too often that you'll be able to use bB and not be able to use C, but this can be quite useful in the right circumstances.

\$\endgroup\$
2
\$\begingroup\$

Utilise the Short Dictionary

Note: This is a 2.6.x+ feature only

Newer versions of Vyxal have a neat little feature where 1 character SCCs are indexed into a special "short" dictionary of overlyspecialised "words". Here's a list of all the current entries:

\d+ λ
-?\d+ ƛ
\d+\.\d+ ¬
-?\d+(\.\d*)? ∧
[A-Za-z0-9\.,;:!?()"'%\-]+ ⟑
^\S+@\S+$ ∨
[A-Za-z0-9] ⟇
[A-Za-z] ÷
[a-z] ×
[A-Z] «
[0-9] »
[aeiou] °
[aeiouy] •
[bcdfghjklmnpqrstvwxyz] ß
\w+ †
.* €
[^A-z0-9] ½
[^A-Z] ∆
[^a-z] ø
[^0-9] ↔
[^aeiou] ¢
[^aeiouy] ⌐
[^bcdfghjklmnpqrstvwxyz] æ
(.+) ʀ
\W ʁ
\w ɾ
\S ɽ
\s Þ
\W+ ƈ
\w+ ∞
\S+ ¨
\s+ ↑
((www\.|(http|https|ftp|news|file)+\:\/\/)[_.a-z0-9-]+\.[a-z0-9\/_:@=.+?,##%&~-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)]) ↓
?<= ∴
?!= ∵
?<! ›
https://www.google.com ‹
https://www.google.com/query?q= ∷
https://www.duckduckgo.com ¤
https://www.duckduckgo.com/?q= ð
https://www.bing.com →
https://www.bing.com/?q= ←
https://codegolf.stackexchange.com/q/ β
https://codegolf.stackexchange.com/a/ τ
https://stackoverflow.com/q/ ȧ
https://stackoverflow.com/a/ ḃ
₁ƛ₍₃₅kF½*∑∴, ċ
:ɾ:Ẋv∑Ȯẇ ḋ
:ɾ:Ẋƛ⁽=R;Ȯẇ ė
isdo ḟ
›‹²… ġ
n't ḣ
cos(x) ḭ
sin(x) ŀ
tan(x) ṁ
acos(x) ṅ
asin(x) ȯ
atan(x) ṗ
x^2 ṙ
x^3 ṡ
x+1 ṫ
x-1 ẇ

So for example:

`β223918`

would return the address of this question (because β decompresses as https://codegolf.stackexchange.com/q/).

\$\endgroup\$
2
\$\begingroup\$

For reverse sorting, use µ...⌐

If the last operation you do in a program is to sort something in a certain way then reverse it, you can save a byte by using µ...⌐ - take the one's complement before sorting. This only works when the preceding value is numeric.

An example.

\$\endgroup\$
1
\$\begingroup\$

If there are not enough arguments on the stack, fillers will be taken based on the context

What I mean: if there are not enough arguments on the stack to perform an action, the extra arguments will come either from the input (in the "main" program), or from the function/lambda arguments. I discovered this while golfing this answer. I was trying to find a way to tie with 05AB1E, and I had this code:

:↵':²"Ṡ≈;i

I was wondering how I could remove those duplicate elements, and I decided to look at the source code. And then I found the docstring for pop(): Pops (count) items from iterable. If there isn't enough items within iterable, input is used as filler. Looking at get_input(), you see that it either reads the input from STDIN, or from the lambda arguments. That allowed me to shave off two bytes and my code became this:

↵'²"Ṡ≈;i
\$\endgroup\$
1
  • \$\begingroup\$ This is exactly what the whole idea of context was based on - the fact 05AB1E doesn't have nice ways of retaining what's being operated on inside structures inspired things like n being the context variable \$\endgroup\$
    – lyxal
    Mar 15 at 13:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.