# Tips for golfing in TI-BASIC

What general tips do you have for golfing in TI-BASIC for the TI-83/84+ series calculators? I'm looking for ideas which can be applied to code-golf problems and which are also at least somewhat specific to TI-BASIC (e.g. "remove comments" is not an answer).

• Please always include which version you are refering to! – flawr Jun 24 '15 at 11:39

Your calculator is pretty smart at inferring the end of lines for you, and thus you can omit quite a few characters.

:Disp "HELLO WORLD    //is the same as...
:Disp "HELLO WORLD"


For( loops have a syntax like this - For(variable, start, end, increment), but you can omit the increment and it will use 1:

:For(A,1,5     //is the same as...
:For(A,1,5,1)


and you can omit ending parentheses (at the end of lines) across the board:

:Output(1,1,A
:int(A
:round(A
etc.


Tested on my TI-84 Silver Edition calculator

If you think this is more than one idea (inferring endings) then I'll split them up

• ....this is just wrong 😭 – Beta Decay Jun 23 '15 at 12:36
• Also, try to rewrite code so you use the least number of closing parentheses. On only the last expression of every line, you get the parentheses for free, so move the most nested statements to the end. That is, not(iPart(B))+(A=5 can be (A=5)+not(iPart(B. – lirtosiast Jun 23 '15 at 16:17
• This applies for everything that needs closing, not just parentheses (namely {lists}, "strings" and [[matrices]]). Expressions will automatically be closed when you reach a newline, colon (a stand-in for the newline; doesn't apply to strings, though, as they can contain colons) or the variable assignment arrow (→, typed with the STO▶ button). Such a weird feature of the language. – M. I. Wright Jun 23 '15 at 20:49

# Use Ans

If you will only use an expression in the next line, don't store it to a variable! The special Ans variable is a one-byte token that stores the value of the last expression evaluated. Thus:

Xsin(A)->R
Disp R+tanh(R


can be

Xsin(A)
Disp Ans+tanh(Ans


saving two bytes.

# Use a lookup table encoded in floating-point numbers

Small lookup tables are useful for code golf: it's very often that we need a function that maps, for example, 0 to 1, 1 to 2, 2 to 1, and everything else to 0. However, TI-BASIC arrays are not suited for this purpose: for one thing, they're one-based, and for another, a value cannot be extracted until the array is stored in Ans or a list variable.

In my answer here, I store a small lookup table in a magic constant in base 11. Simply list the values you want to use,

{0,-1,5,-1,-1,2,9,-1,8,6}


convert to a useful form

{1,0,6,0,0,3,10,0,9,7}


write in your desired base (base 11)

.106003A097


and convert to base 10

-1+int(11fPart(11^Ans.0954191904


The shortest array approach is 8 bytes longer!

{1,0,6,0,0,3,10,0,9,7}-1:Ans(X+1


TI-BASIC only stores floats to 14 decimal digits, so you can store up to 44ish bits but only 14 decimal digits.

This technique can often be improved further by using brute-force search to find a magic constant rather than base-N encoding. I'm still in the process of golfing the answer above, but the lengendary TI-BASIC golfer Weregoose used this method to generate the differences between numbers coprime with 30 (that is, a repeating list of 6, 4, 2, 4, 2, 4, 6, 2 ) on the wiki/forum TI-BASIC Developer with this snippet:

2+2iPart(3fPart(576e^(fPart(I/8


The magic constant 576 was found using Mathematica, but if you don't own a copy use a script in your favorite language.

Put repeated expressions equation variables.

EX:

Remainder(randInt(1,9),1
Remainder(randInt(1,9),5
Remainder(randInt(1,9),10


Can be:

"randInt(1,9→u
Remainder(u,1
Remainder(u,5
Remainder(u,10


Note: it is hard to find a good use for this, but that does not mean you should forget equation variables :P

-c4ooo from Omnimaga

• In this example, you could save more by adding n to the first expression, along with the Remainder( function. – Conor O'Brien Oct 5 '15 at 3:08

# Skip unnecessary variable initialization

Current consensus is to allow all code to be run on a fresh interpreter. We can take advantage of this—all uninitialized real variables start at 0 in TI-BASIC, and Xmin starts as the possibly useful value -10. So if you ever need to take a running total in a program that doesn't take input from Ans, or you really need a -10 in one less byte, this tip can help you.

• Xmax is 10 and Ymin and Ymax behave similarly, right? Also there are some other graph parameters that have some other values, I think. – Fabian Röling Jun 12 '18 at 10:49

# Smaller list generation

If you need a list {1,2,...,N}, where N is, say, 42, the obvious way to create it is

seq(X,X,1,42.


However, one byte smaller than that is a neat hack using the binomcdf( (cumulative binomial distribution) command.

cumSum(binomcdf(41,0


This only works when N is a constant, because the savings comes from replacing N-1 with its value in the code.

There are two cases that allow even shorter code.

If you already have a list L1 of dimension N:

cumSum(1 or L1


If you don't care about order:

randIntNoRep(1,N     ;random permutation of numbers from 1 to N

• Guaranteed to be one byte smaller (and stupidly slower) than seq(X,X,1,N even when N isn't constant is cumSum(1 or rand(N. – Misha Lavrov Sep 30 '17 at 3:40

# Eliminate End statements for If blocks at the end of a program

Saves two bytes: one for the End and one for the linebreak. It also allows you to use the implied Disp on the last line, often saving an additional byte.

[code]
If A>5
Then
Output(1,1,Ans²+Ans+A
Disp 3ln(A
End
//end of program


Can be:

[code]
If A>5
Then
Output(1,1,Ans²+Ans+A
3ln(A
//end of program

• It should be noted that this tip doesn't work for loop blocks. +1 for the good tip though – Tau Apr 30 '19 at 13:28

Here are some snippets I commonly use in code golf:

• Convert to truth-value (0/1): not(not(Ans, or Ans and 1. Which one to use depends on the parentheses needed.
• Add one to a truth-value: int(e^(Ans. Saves an open-paren over 1+(Ans. Very useful, because TI-BASIC has one-based arrays.
• Map {0,1} to {1,-1}: cos(πAns. Saves one byte over 1-2Ans.

• Sign function of a number: tanh(ᴇ9Ans
• Round towards positive infinity: -int(-Ans
• Number of digits in a positive integer: 1+int(log(Ans
• Complex number to list {Re,Im}: imag(Ans{i,1

• Convert string to list: seq(inString("...",sub(Ans,X,1)),X,1,length(Ans (where ... is the search string)
• Chop off first element of a list: ΔList(cumSum(Ans
• Chop off last element of a list: ΔList(cumSum(Ans)-Ans
• Check if all elements of list L1 are unique: SortA(L1:min(ΔList(L1
• Search for the number X in a list (returns first occurrence): 1+sum(not(cumSum(Ans=X
• Mode of a list when a single mode exists, and the list has at most 10 elements: (ugly, but short): median(Ans,10^(seq(sum(Ans=Ans(X)),X,1,dim(Ans
• I really don't understand why the tanh(ᴇ9Ans one works. – SuperJedi224 Oct 6 '15 at 22:27
• @SuperJedi224 Well, tanh(0 is zero, and the limits to infinity on the left and right are -1 and 1. It gets exponentially close to those values, so past +-17 or so it's within rounding error of +-1. If the absolute values are greater than 17ish already, we just use tanh( alone. – lirtosiast Oct 6 '15 at 22:34

If you find yourself using

0→G ;or any other variable
;other lines of code


Then, you could use (to save a byte):

DelVar G;other lines of code


This is because when you delete a variable (G), it becomes its default value, in this case, 0. Then, you could put another line after the DelVar statement, without a newline. Be careful when putting crucial control statements directly after a DelVar statement.

(Tested on TI-84)

• This is rarely useful; variables are initialized to 0 by default, and you can zero Y by doing a ZStandard. – lirtosiast Oct 4 '15 at 23:38
• @ThomasKwa It's been useful to me on many instances, esp. when a reset is required partway through execution. – Conor O'Brien Oct 5 '15 at 2:59
• In code golf? When? If you show me the program I think I'll be able to optimize out the DelVar. – lirtosiast Oct 5 '15 at 3:02
• @ThomasKwa Not xode golf per se, rather, programming on low disk space (TI-83). I don-t have the program right now. I'll get back to you on that. – Conor O'Brien Oct 5 '15 at 3:16
• After a few minutes of thought, I can think of a couple of scenarios when DelVar can possibly be shortest, like after single-line If statements. – lirtosiast Oct 5 '15 at 3:17

# Which list variables to use?

When using lists, avoid the default lists L₁ through L₆ in favor of named lists with one-letter names: ᶫA through ᶫZ (where ᶫ is the little L).

Either one costs two bytes to reference (though L₁ is a single token, it is a two-byte token) but when storing values in a list, you can drop the ᶫ symbol, saving a byte:

{1,2,3,4,5→ᶫA


can be

{1,2,3,4,5→A


The calculator checks the data type of the expression when deciding where the result is stored.

Similarly, Input A or Prompt A will store to ᶫA if the user enters a list instead of a number.

Several other commands can be used without the ᶫ, though most of them are rarely used in golfing. For example, Matr►list( allows the ᶫ to be removed in its third, fourth, and higher arguments.

The general rule is that, if the command takes a list variable name and not a list expression, and if there is no alternative syntax that could put a different kind of variable there, then the command might work with the ᶫ left off.

This doesn't work with modifying a single entry of a list: 1→ᶫA(3 cannot be changed to 1→A(3.

Of course, the best list variable to use is always Ans.

• Wait, what? "Input A" stores to ᶫA if the user enters a list." That means that many of my programs are pretty easy to break. Then it's good that I don't have that many Input programs anyway, I mostly have either small tools with no error checking or complete games that use GetKey instead of Input. – Fabian Röling Jun 12 '18 at 10:53
• If you are really keen on user-proofing your programs against this, you can always store a random value to A and check if it has changed after Input A. – Misha Lavrov Jun 12 '18 at 13:24

# Know your variable assignment costs

If you use a B-byte expression N times, should you assign it to a variable?

Ans costs 1+N bytes to use (one for the linebreak and one for each time it's used, so use Ans when (B-1)*(N-1)>2. There can be only one Ans per line, so try all values for Ans that might be useful.

Real variables (e.g. X) cost 3+N bytes, so use them when (B-1)*(N-1)>4.

List variables cost 3+2N bytes, so use them when (B-2)*(N-1)>5.

Equation variables are the least useful: they need 4+2N bytes. Use them when (B-2)*(N-1)>6.

Min. bytes in an expression to save
N \ var. | Ans | Real | List | Eqn
------------------------------------
2           4     5      8      9
3           3     4      5      6
4           2     3      4      5


When a function evaluates to a list, store it to a list rather than an equation variable like u; this saves one byte.

Keep in mind that the presence or absence of close parentheses can often cause storing expressions to be advantageous if they're rearranged.

Now I'll contradict myself and say that one should write code on one line as much as possible. Why? Usually when there's a long repeated expression on a line, it can be simplified.

## int(rand over randInt(

X+int(Yrand is equal to or fewer bytes than randInt(X,Y as randInt is a 2 byte token. Some potential benefits:

X+ can be left out when lower bound is 0, saving two bytes

X+ is necessary before randInt( anyway in certain situations, for example random from a step function like {2,5,8,11}

X+int(Yrand(N can be used just as randInt(X,Y,N to generate a list of N random numbers

## Graphscreen initialization

To use functions like Line( easily with pixel coordinates it's necessary to initialize the graphscreen axes to square pixels and remove axes:

AxesOff
84→Xmin
72→Ymax
ZInteger


## Clamp

min(U,max(L,N


Where N is the number or algorithm and U and L are upper and lower bounds

## Is N in List

max(N={X,Y,Z


## More List math

L1*L2→L3

for(A,1,dim(L1
L1(A)*L2(A→L3(A
End

This also works for things like this:
not(L1
L1 and L2
`

## Output

Disp and Text( can both be chained, so Disp A,B will Display A then B on separate lines and Text(28,40,A,B will print A next to B on one line

## Tech from the optimal movement loop

A lot of these optimizations are part of the tech used to move a character around the screen in the fewest bytes

http://tibasicdev.wikidot.com/movement

## Token Size Lists

http://tibasicdev.wikidot.com/tokens

For help scoring