Blinking Text

Creates a blinking effect on the home screen.

*Str1* - the text to blink on the screen

*A,B* - the Output( coordinates for the text

*N* - the length of the text to be displayed

None

Str1, N, A, B, Ans

TI-83/84/+/SE

```
:length(Str1→N:1
:Repeat getKey
:If dim(rand(15
:Output(A,B,sub(Str1+" (N spaces) ",1+NAns,N
:not(Ans
:End
```

By leaving 1 by itself on one line, we store it to Ans, which will be easier to work with. Then, the Repeat getKey loop will keep blinking the text until a key — any key — is pressed.

Output(A,B,sub(Str1+" (N spaces) ",1+NAns,N will display either the text or the equivalent number of spaces on the screen at coordinates (A,B). If you want to blink the text "Hello", for example, then you would need to use five spaces. We negate Ans's value with not(, which acts as a flag to control the blinking.

If dim(rand(15 is a clever way of delaying the blinking, so that it doesn't blink too fast. rand(15 generates a list of 15 random numbers, which is a slightly time-consuming process. If dim( is just a way of wrapping this list so it doesn't change Ans. Since dim(rand(15 is always 15, the If statement will always be true, so we don't have to worry about the next line being skipped. By changing 15 to a lower or higher number, you can make the blinking go faster or slower, respectively.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/blinking-text

Custom Menu Multi Page

A custom menu with up to 9 switchable pages.

*Str1-Str9* - one string per page

*A* - Number of pages the menu includes

*B* - the page they're on

*X* - the # choice they made

Ans, B, C, D, X, Str#

TI-83/84/+/SE

Mr Dino

```
:1→B
:While 1
:If B=1:Str1
:If B=2:Str2
:If B=3:Str3
:If B=4:Str4
:If B=5:Str5
:If B=6:Str6
:If B=7:Str7
:If B=8:Str8
:If B=9:Str9
:ClrHome
:Output(1,1,Ans
:length(Ans)/16
:If fPart(Ans
:1+iPart(Ans
:Ans→D
:2→X
:Repeat C=24 or C=26
:Output(X,2,">
:Repeat Ans
:getKey→C
:End
:If Ans=21
:Then
:X-1→X
:Return
:End
:Output(X,2," " // space
:X-(Ans=25)+(Ans=34→X
:2(X>D)+D(X≤1)+X(X≤D and X>1→X
:max(1,min(A,B+(C=26)-(C=24→B
:End
:End
```

To use this code, store an integer to A 1-0 representing the number of pages that will be in your menu. It will use all strings Str1-StrA. Next, store the menu pages into the strings. They will be shown with 'Output(1,1,StrA)', so make sure that the menu looks right before using it. Make sure there are 16 characters in each line (starting with the title). Use spaces to make the words fit right, and you should probably test it to make sure it works. There should probably also be something in the title that signifies what page you're on. Finally, run the code as a subprogram.

Here's how it works:

B represents what page number it's on, so we start off by storing 1 to B to put us on page 1. Then we have a While 1 loop to manage page changes. Based on the value of B, it will put one of the strings into Ans. It will output Ans onto the home screen, then determine how many rows are in the menu and store that to D. And the user will always start out on option 1 - row 2 (because of the title screen).

Now we start the choice loop: We display the cursor, then wait for a keypress. If the use presses [2nd], we subtract 1 from X (for the offset from the title) and Return back to the parent program, with B as the page number and X as the choice number. But if not, it continues: The cursor is erased, X and B are changed according to the keypress, and if the use changed the page, it exits the choice loop and enters the page loop where it displays the new page and sets up for another choice loop.

# Error Conditions

It won't work properly if A isn't an integer within the bounds 1-9 or if the strings don't represent the menu pages correctly.

**ERR:UNDEFINED**is thrown if you don't define the strings.

# Related Routines

There are several routines that are similar in functionality or are used in a similar context. Make a bulleted list of them, with links to the other routines' pages. It will often be the case that several routines all link to each other.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/custom-menu-multi-page

Day of Week

Calculates the day of week of a date, without using dayOfWk( (because it's only available on the 84+ and 84+SE)

*D* - The day

*M* - The month

*Y* - The year (1950 through 2049)

*Ans* - 0-6 = the day of week (Sunday - Saturday)

D, M, Y, Ans

TI-83/84/+/SE

`:round(7fPart(dbd(101.5,DE2+M+fPart(.01Y))/7`

Using the dbd( command, we return the number of days between the given date and January 1, 1950, our base date. dbd('s argument, in this case, is of the form DDMM.YY, so we put the date we're given in that form with DE2+M+fPart(.01Y. Once we have the number of days between the two dates, we divide it by seven (as there are seven days in a week) to get the number of weeks.

However, we are not interested in the number of weeks between two dates, we are interested in how far into the week we are. That would be the fractional part of the number of weeks. For example, if there was fourteen days between two dates (the first date being a Sunday) and we divide that by seven, we would have the equation 14/7=2.00. The .00 means that the week hasn't yet begun (and so, the day is Sunday).

If there was 15 days between two dates, the equation would give 15/7=2.1428571. The .1428571 means that we are .1428571 into the week, and if we multiply that by seven, we get the equation .1428571*7=1. This means that we are one day into the week (and so, the day is Monday). So in our formula, after finding out the number of days between two dates, we find the fractional part of it, and multiply that by seven. Finally, round( gets rid of any minor rounding errors.

As the 1^{st} of January, 1950 was a Sunday (which is the date we have inputed into the above routine), so the number of days into the week will always be relative to Sunday. That is, the output 0 through 6 is relative to the days Sunday through Saturday respectively. If you want 0 to be Monday instead, make the base date January 2 instead by changing 101.5 to 201.5.

This routine can handle dates from January 1, 1950 to December 31, 2049. For other dates, it will assume the year is in that range instead. There is also an alternative routine that handles dates in an unlimited range.

# Display Day

Append the following code to display the day of the week:

`:Disp sub("SUNDAY***MONDAY***TUESDAY**WEDNESDAYTHURSDAY*FRIDAY***SATURDAY*",9Ans+1,9 //replace *s with spaces`

Or this code, which should display the day of the week, only the display method takes less space and space pads it.

`Disp sub("***SUN***MON**TUESWEDNES*THURS***FRI*SATUR",6Ans+1,6)+"DAY //replace *s with spaces`

# Error Conditions

**ERR:DOMAIN**if the date is invalid.

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/day-of-week

Decimal to Fraction

Converts a decimal number to a fraction.

*Ans* - the number you want to convert to a fraction

*Ans* - the fraction in list format

Ans, X

TI-83/84/+/SE

Weregoose

*URL:* United TI

```
:Ans→X:{1,abs(Ans
:Repeat E‾9>Ans(2
:abs(Ans(2){1,fPart(Ans(1)/Ans(2
:End
:round({X,1}/Ans(1),0
:Ans/gcd(Ans(1),Ans(2
```

Although there is a ►Frac command available for converting a decimal number to a fraction, this is only a formatting command and doesn't actually give you the numerator and denominator as separate numbers. This limits your choices for using fractions, especially since ►Frac only works with the Disp and Pause commands. In addition, it does not work very well, and fails for several inputs that you would think are within its ability to figure out (such as -1.3427625). Fortunately, you can improve upon the ►Frac command by using your own routine.

The basic algorithm that you use when converting a number to a fraction is commonly known as the Euclidean algorithm. While it has been around for literally millennia, it is still one of the best algorithms because of its sheer simplicity (it doesn't require any factoring or other complex math operations).

The way it works is that you have two numbers (in our routine, it's one and the decimal number you input), and you divide the first number by the second number, and check to see if there is a remainder. If there is a remainder, you then repeat the process again, except this time you swap the numbers. This process is repeated over and over again until the second number is equal to zero, at which point you will have your desired fraction.

One thing you will probably notice is that we aren't actually checking for zero in the Repeat loop. Because of the way that TI designed the TI-Basic language, each number has a limited amount of precision. As a result, any math calculations that involve extremely small or large numbers will produce rounding errors that don't return the right number. The easiest way to deal with this problem is by checking for a really small number (in this case, _{E}‾9).

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/decimal-to-fraction

Deck of Cards

Simulates a standard 52-card deck of cards.

None

*∟DECK* - the cards, in the format:

Value.Suit

Value is 1..13

Suit is 0, .25, .5, .75

L₁, ∟DECK

TI-83/84/+/SE

**Creating the deck**

`seq(X/4,X,4,55→DECK`

**Shuffling the deck**

```
rand(52→L₁
SortA(L₁,∟DECK
```

**Accessing individual cards**

```
∟DECK(I
Disp "VALUE:",sub("A23456789TJQK",int(Ans),1
Disp "SUIT:",sub("SHCD",4fPart(Ans)+1, 1
```

The cards in the deck are stored in the form Value.Suit, where the value of the card (Ace through King) is encoded as a number 1 through 13; and the suit of the card is the fractional part, encoded as one of 0, 0.25, 0.5, or 0.75. In the above code (accessing individual cards), the convention is that 0=Spades, 0.25=Hearts, 0.5=Clubs, 0.75=Diamonds; however, you can pick any order as long as you're consistent.

Since any value from 1.00 to 13.75, that's 1/4 of an integer, is a valid card, we can generate the entire deck as 1/4 of the values {4,5, …, 54, 55}.

When shuffling the deck, we generate a random list in L₁, then use SortA( to sort ∟DECK by the values in L₁. Since the values in L₁ are random, this has the effect of sorting ∟DECK in a random order.

The main overhead of this shuffling method, however, is that generating a random list might take a long time (around a second or two). To avoid this, you can generate individual elements of L₁ randomly in a getKey loop, while waiting for a key, then use L₁ to shuffle later. Since shuffling isn't done often, by the time you need to shuffle, L₁ will most likely be fully randomized already.

Finally, accessing the cards is done using fPart( and int(. If a variable X is encoded in the same way that we encode cards, int(X) will return its value (1-13) and 4fPart(X)+1 will return its suit as a number 1-4.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/deck-of-cards

Draw Ellipse

Draws an ellipse with specified coordinates.

(A,B) - upper left corner, in pixels

(C,D) - lower right corner, in pixels

Ellipse inscribed in the rectangle from (A,B) to (C,D)

A,B,C,D for input

∟X and ∟Y store a sin/cos look-up table

Plot1 to store the unit circle

Pic1 to preserve background

All

Mikhail Lavrov (DarkerLine)

**Setup:**

```
:cos(.1πcumSum(binomcdf(20,0→X
:sin(.1πcumSum(binomcdf(20,0→Y
:Plot1(xyLine,∟X,∟Y,(dot)
:PlotsOff
```

**Main code:**

```
:StorePic 1
(:ZoomSto)
:-(B+D)/abs(D-B→Xmin
:(A+C-124)/abs(C-A→Ymin
:2/abs(D-B→ΔX
:2/abs(C-A→ΔY
:PlotsOn 1
:RecallPic 1
:StorePic 1
:PlotsOff
(:ZoomRcl)
:RecallPic 1
```

To use the routine, add the setup code to the beginning of your program. Then, to draw an ellipse, initialize (A,B) and (C,D) to be opposite corners of an imagined rectangle, in pixel coordinates, and run the main code of the routine. The ellipse will be drawn inside this rectangle (much like the functionality of the circle tool in Paint). Unlike built-in pixel commands, this routine doesn't require the pixels to be on-screen: you can use negative coordinates, and coordinates past the 62nd row and 94th column - of course, if you do, then the off-screen part of the ellipse won't be drawn.

As for speed, the routine is far faster than the Circle( command. If you use Circle( with its undocumented fourth argument, that is a bit faster still - but doesn't allow you as much control over the shape of the ellipse as this routine does.

This routine draws an ellipse given its pixel coordinates in two overall steps:

- First, it calculates the window dimensions so that the unit circle (centered at the origin, with radius 1) will be stretched to the required pixel coordinates.
- Next, it draws the unit circle.

If the unit circle is stretched to fit in the rectangle from (A,B) to (C,D) then we know the following:

- The vertical distance from A to C (in pixel rows) should be equivalent to the window distance 2 (from -1 to 1). This allows us to solve for ΔY.
- The horizontal distance from B to D (in pixel columns) should also be equivalent to the window distance 2. This allows us to solve for ΔX.
- The pixel most nearly corresponding to the midpoint between (A,B) and (C,D) should be equivalent to the point (0,0), the center of the circle. Given ΔX and ΔY, this allows us to solve for Xmin and Ymin.

The exact math isn't significant, but it gives rise to the formulas you see in the routine. Note that by using the abs( command, we ensure that the order of the two points (A,B) and (C,D) isn't important: you can switch A and C, or B and D, and still get the same circle.

The code for actually drawing the circle uses a look-up table for sine and cosine (which defines 20 points spaced around the circle). The table is calculated in the setup code, and then an xyLine plot is initialized, which will connect these 20 points when graphed. Now, to draw the unit circle, all that needs to be done is to enable the plot, using the PlotsOn command. This actually draws a 20-gon, rather than a circle, but the difference is imperceptible even on large circles.

The rest of the code is necessary to preserve the graph screen as the window changes and Plot1 is enabled and disabled (which causes the screen to be cleared), using StorePic and RecallPic. Optionally, you can also preserve the window dimensions, using ZoomSto and ZoomRcl — this is useful if your program mixes pixel and point commands.

The routine uses three fairly large variables to do its work: ∟X, ∟Y, and Pic1. ∟X and ∟Y need to be preserved from the setup code to whenever the routine is called; Pic1 is only used temporarily. It's a good idea to clean up all three by deleting them at the end of the program.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/draw-ellipse

Highlighting Text

Highlights text, displaying it in white on a black background.

*Str1* - text to be displayed

*A* - row coordinate of the text

*B* - column coordinate of the text

*W* - pixel width of the text

None

Str1, A, B, C, W

TI-83/84/+/SE

```
:Text(A,B,Str1
:For(A,A,A+6
:For(C,B-1,B+W
:Pxl-Change(A,C
:End:End
```

First, we display the string using Text( on the graph screen. This displayed it normally, using black on white. To switch it to white on black, we need to flip the pixels from white to black and black to white — this can be done using Pxl-Change(. We chose the pixel command over the point command for two reasons: first, it is slightly faster, and second, it uses the same coordinate system as Text( — pixels (if we used Pt-Change, we'd need to convert from pixels to points to be sure of drawing in the same location).

We loop A from above to below the text, and C from just before the text to immediately after it. Note that because of the way the For( loop works — it saves the lower and upper bound before doing the loop — we can reuse the variable A. But we can't reuse B in the same way in the second For( loop, because the loop is done multiple times — it would work correctly the first time, but then B would have changed for the second.

Since Text( uses variable-width font, we need the W variable to tell us how long the string is in pixels. For uppercase letters, the width is 4 pixels; for spaces, the width is 1 pixel, and for lowercase letters, the width varies from 2 to 6 pixels.

Because Pxl-Change( must not go off the screen, check to see that the string fits on the screen entirely (with a border of 1 pixel around it) before displaying it.

# Error Conditions

**ERR:DOMAIN**is thrown if the string does not fit on the screen entirely.

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/highlighting-text

Key Code Retriever

```
:Repeat Ans
:getKey
:End
:Disp Ans
```

This routine loops until a key is pressed. When a key is pressed, the key code for that specific key is displayed.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/key-code-retriever

List Frequency

Returns a list of the frequency of values in another list.

*L₁* - the list you want to find the frequency of

*L₂* - the values of L₁ without repetition

*L₃* - the frequencies of the values in the list L₂

L₁, L₂, L₃, I

TI-83/84/+/SE

DarkerLine

*URL:* United TI

```
:{L₁(1→L₂
:{1→L₃
:For(I,2,dim(L₁
:If max(L₂=L₁(I:Then
:L₃+(L₂=L₁(I→L₂
:Else
:augment(L₂,{L₁(I→L₂
:augment(L₂,{1→L₃
:End:End
```

With our list of values stored in L₁, we store the first element of L₁ to L₂ to initialize it, and store a value of one to L₃ because that value has appeared once in the list (by default it is the first value and thus we know it appeared). We then begin looping in the second element to avoid an extra increment and then through all of the elements of L₁.

When determining the frequency of a value, we need to check to see if the particular element (in this case, L₁(I)) has already appeared in L₂. If it has, we increment (add one) to its respective frequency in L₂. However, if the value has never appeared in L₁, we add that value as a new element to the end of L₂ and also set its frequency to one. We repeat this until we have the frequency of all of the values in L₁ stored in L₂.

When you are done using L₁, L₂, and L₃, you should clean them up at the end of your program.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/deleted:list-frequency

List Frequency Fast

Returns a list of the frequency of values in another list sorted.

*L₁* - the list you want to find the frequency of

*L₂* - the values of L₁ without repetition sorted

*L₃* - the frequencies of the values in the list L₂ sorted

L₁, L₂, L₃, θ

TI-83/84/+/SE

Galandros

*URL:* United TI

```
:DelVar L₂DelVar L₃SortA L₁
:For(θ,1,dim(L₁
:L₁(θ→L₂(1+dim(L₂
:sum(L₁=Ans→L₃(dim(L₂
:θ-1+Ans→θ
:End
```

In the first line we initialize L₁, L₂, and L₃. We sort L₁ so like values will be adjacent.

Then we start looping by storing the first value encountered to the next element of list L₂.

In the next line we find the frequency of the value already stored in L₂ and is stored to the correspondent element in L₃. θ is increased by the frequency found minus 1 to pass to next number, but then incremented by 1 in the For loop.

We loop we reach the end of L₁.

And that's it. The output is put on L₂ and L₃ already sorted. Notice how well Ans is used for speed and size optimization.

When you are done using L₁, L₂, and L₃, you should clean them up at the end of your program.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/list-frequency2

List to String

Converts a list of numbers to a string.

*L₁* - The list you want to convert

*Str1* - The string that the text is stored to

L₁, A, Ans, Str1

TI-83/84/+/SE

**Note:** If you have a TI-84+ CE with OS 5.2 or higher, you can ignore this entire routine and just use the toString( command.

```
:"?
:For(A,1,dim(L₁
:Ans+sub("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ",1+L₁(A),1
:End
:sub(Ans,2,length(Ans)-1→Str1
```

With our list of values stored in L₁, we loop through each element of L₁ and store the character to our string that is at the matching position in our substring. In order to construct a string with all of the characters from L₁, we first need to create a dummy string. This is what the "? is used for.

Each time through the For( loop, we concatenate the string from before (which is still stored in the Ans variable) to the next character that is found in the list. Using Ans allows us to not have to use another string variable, since Ans can act like a string and it gets updated accordingly, and Ans is also faster than a string variable.

By the time we are done with the For( loop, all of our characters are put together in Ans. However, because we stored the dummy character as the first character at the beginning of the string, we now need to remove it, which we do by simply getting the substring from the second character to the end of the string. Finally, we store the string to a more permanent variable (in this case, Str1) for future use.

This routine allows for values from 0 to 36 in the list, since our string of characters is the ten digits and 26 uppercase letters, plus a space, and each list value must match up to one of the string positions. If you add more characters to the string, such as lowercase letters, however, you can increase the range of values in the list; if you need fewer characters you can simply remove them. This routine uses L₁, so you should clean it up at the end of your program.

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/list-to-string

Marquee

Scrolls a string across one line, in marquee fashion, on the home screen.

*Str1* - the text to be scrolled

*A,B* - the Output( coordinates for the text

*N* - the number of characters to display at a time

None

Str1, A, B, N, Ans

TI-83/84/+/SE

Weregoose

*URL:* United TI

```
:Str1
:Repeat getKey
:Output(A,B,sub(Ans,1,N
:sub(Ans,2,length(Ans)-1)+sub(Ans,1,1
:If dim(rand(4
:End
```

By leaving Str1 by itself on one line, we store it to Ans, which will be easier to work with. Then, the Repeat getKey loop will display the marquee until a key — any key — is pressed.

Output(A,B,sub(Ans,1,N will display N characters of Str1 at A,B. Then, the next line will rotate Str1, so that the next time we're at this point in the loop, the string shifts one character.

Finally, If dim(rand(4 is a clever way of delaying the marquee, so it doesn't scroll too fast. rand(4 generates a list of 4 random numbers, which is a slightly time-consuming process. If dim( is just a way of wrapping this list so it doesn't change Ans. Since dim(rand(4 is always 4, the If statement will always be true, so we don't have to worry about the next line being skipped. By changing 4 to a lower or higher number, you can make the marquee go faster or slower, respectively.

# Error Conditions

**ERR:INVALID DIM**is thrown if the length N is longer than the number of characters in Str1.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/marquee

Matrix to String

Converts a matrix to a string.

*[A]* - The matrix you want to convert

*Str1* - The string that the text is stored to

[A], L₁, A, B, Ans, Str1

TI-83/84/+/SE

**Note:** If you have a TI-84+ CE with OS 5.2 or higher, you can ignore this entire routine and just use the toString( command.

```
:dim([A]→L₁:"?
:For(A,1,L₁(1
:For(B,1,L₁(2
:Ans+sub("ABCDEFGHIJKLMNOPQRSTUVWXYZ",[A](A,B),1
:End:End
:sub(Ans,2,length(Ans)-1→Str1
```

With our values stored in [A], we get the dimensions (row x column) of the matrix, which are stored in a list. We then loop through each row and column, and store the character at the respective element to our string that is at the matching position in our substring. In order to construct a string with all of the characters from [A], we first need to create a dummy string. This is what the "? is used for.

Each time through the For( loops, we concatenate the string from before (which is still stored in the Ans variable) to the next character that is found in the matrix. Using Ans allows us to not have to use another string variable, since Ans can act like a string and it gets updated accordingly, and Ans is also faster than a string variable.

By the time we are done with the For( loops, all of our characters are put together in Ans. However, because we stored the dummy character as the first character at the beginning of the string, we now need to remove it, which we do by simply getting the substring from the second character to the end of the string. Finally, we store the string to a more permanent variable (in this case, Str1) for future use.

This routine only allows for values from 1 to 26 in the matrix, since our string of characters is the uppercase alphabet, and each matrix value must match up to one of the string positions. If you add more characters to the string, however, you can increase the range of values in the matrix. This routine uses [A] and L₁, so you should clean them up at the end of your program.

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/matrix-to-string

Modular Arithmetic Solver

Finds the remainder of a division between two numbers.

A,M

A,M

TI-83/84/+/SE

`:A-Mint(A/M`

This program takes modular equations of the form X ≡ A (mod M) and solves them for the common residue, which is equal to the remainder after A has been divided by M. Among other things, it can be useful for finding the day of the week (with Sunday–Saturday matching up with 0–6) after M number of days has passed, or the time on a clock after a number of hours has passed.

For example, if we were on a Saturday (which is day 6, given that Sunday is day 0), and we wanted to figure out what it will be in 18 days, we would store 6+18→A, then 7→M as the appropriate number of days in a week, and finally we would calculate MfPart(A/M to get 3, which translates to a Wednesday.

This simpler version can be used if A is guaranteed to be positive:

`:MfPart(A/M`

It may fail due to rounding precision errors.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/modular-arithmetic-solver

Number Concatenation

Concatenates two whole numbers together.

*M* - the first number

*N* - the second number

*O* - the concatenated number

M, N, O

TI-83/84/+/SE

DarkerLine

*URL:* United TI

`:N+M10^(1+int(log(N→O`

With our two numbers stored in M and N respectively, we add the first number to the second number by raising it to the 10^{th} power, with the exponent being how many digits are in the number. We then store this result to a new variable for later use.

We can figure out how many digits are in a number by using the 1+int(log( trick. This trick works with any positive whole numbers, and if you add abs( after log(, it will also work with negative numbers. Unfortunately, it does not work with decimals.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/number-concatenation

Number Factorization

Returns the factors of a number.

*X* - the number you want to factor

*L₁* - the factors of the number

X, L₁, Ans

TI-83/84/+/SE

Weregoose

*URL:* United TI

```
:{1→L₁
:Repeat Ans=1
:2:While fPart(X/Ans
:Ans+1
:End
:Ans→L₁(1+dim(L₁
:X/Ans→X
:End
```

Number factorization breaks a number up into its *factors* - smaller numbers that that are multiplied together to create the number. For example, the number 100 can be broken up into the factors 2*2*5*5. It can also be represented as 10*10, or 5*20, but for the sake of completeness, this routine finds *prime factors* — which can't be broken down themselves (2*2*5*5 is such a factorization, since there's no way to factor 2 or 5, but 5*20 isn't, since 20 can still be factored).

In order to start collecting the factors of the number, we create a list with the initial factor of 1 (because 1 is a factor for every number). We then begin looping through numbers, starting with 2, to find the next factor. The way we determine if we have a factor is by dividing the original number by the respective number we are at, and checking if there is a remainder.

If there is a remainder, we know that the number is not a factor, and we then increment it and continue looping. If there is no remainder, however, we have found a factor, and thus the loop will end. We then add that factor as the next element in our factors list, and divide the original number by that factor and set the result as the new number. This gets repeated over and over again until we have our list of factors.

The factors list should be generated pretty quickly, but it all depends on the original value that you chose for X; a smaller value will be faster, and likewise a larger value will be slower. In addition, if you try starting with a negative number or a number with a decimal part, then the program will not work correctly.

When you are done using L₁, you should clean it up at the end of your program.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/factorization

Number Subset

Returns a subset of a number.

*A* - the number to get the subset from

*B* - the starting position of the subset

*C* - the length of the subset

*Ans* - the subset of the number

A, B, C, Ans

TI-83/84/+/SE

Weregoose

*URL:* United TI

```
:10^(2-B+int(log(A
:int((A-int(A/Ans)Ans)/Ans10^(C
```

With our number stored in A, and the staring position and length of the subset stored in B and C respectively, we get the subset of the number by first subtracting the number divided by 10 to the power of 2-B+int(log(A (which is used to get how many digits are in the number), and then dividing that result by multiplying 10 to the power of 2-B+int(log(A and 10 to the power of C (which is the length of the subset).

A simple example should help you understand this routine. Say you input the number 123, with a starting position of 2 and a length of 2, it will return a result of 23. You can also use negative and decimal numbers with the routine, and it will still work correctly: a number of 13579.02468 with a starting position of 4 and length 4 will return 7902.

This routine is comparable to the sub( command that works with strings.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/number-subset

Number to String

Converts a real number to a string.

*N* - the number you want to convert

*Str1* - the number N in string form

L₁, L₂, Y₁, Str1, N

TI-83/84/+/SE

**Note:** If you have a TI-84+ CE with OS 5.2 or higher, you can ignore this entire routine and just use the toString( command.

```
:{0,1→L₁
:{0,N→L₂
:LinReg(ax+b) Y₁
:Equ►String(Y₁,Str1
:sub(Str1,1,length(Str1)-3→Str1
```

This code works because it creates two points with a known best fit line: the best fit line through (0,0) and (1,N) is y=Nx+0. LinReg(ax+b) calculates this best fit line, and stores its equation to Y₁.

Then, we use Equ►String( to store this equation to Str1, which now contains "NX+0" with N replaced by the numerical value of N. After that, the sub( command get rids of the "X+0" at the end, leaving only the string representation of N.

This routine uses L₁, L₂, and Y₁, so you should clean up those variables at the end of your program. If you're working with the graph screen in function mode, storing to Y₁ can be a problem since it will draw an unwanted line through your graphics. Use r₁ instead but make sure the calculator isn't in polar mode.

**Note:** This only works for real numbers. With complex numbers, such as imaginary numbers, you can use this code at the end of the first to get the same effect with *i* in it.

`:Str1+"i"→Str1`

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/number-to-string

Pad a String

Pad a string with spaces on the left and right.

*Ans* - The string you want to pad

*N* - How many spaces you want

*Str1* - The padded string

X, N, Ans, Str1

TI-83/84/+/SE

```
:For(X,1,N
:" "+Ans+"
:End
:Ans→Str1
```

With our string stored in Ans, we concatenate (add) a space to the beginning and end of the string. At the same time, the new string is stored to Ans, which is what we use next time through the For( loop. The loop gets repeated over and over again until we have added however many spaces we wanted. If you only want spaces on one side of the string, edit the second line accordingly.

Using Ans allows us to not have to use another string variable, since Ans can act like a string and it gets updated accordingly, and Ans is also faster than a string variable.

We store the string to a more permanent variable (in this case, Str1) for future use. When you are done using Str1, you should clean it up at the end of your program.

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/deleted:pad-a-string

Repeat a String

Repeats a string however many times you want.

*Ans* - The string you want to repeat

2^{N} - How many times you want the string repeated

*Str1* - The repeated string

X, N, Ans, Str1

TI-83/84/+/SE

```
:For(X,1,N
:Ans+Ans→Str1
:End
```

With our string stored in Ans, we concatenate (add) another copy to the end of the string, and store the new string to Str1. At the same time, the new string is also stored to Ans, which is what we use next time through the loop. The loop gets repeated over and over again until we have added however many copies we wanted. If you want to add more than one copy of the string each time through the loop, edit the second line accordingly.

Using Ans allows us to not have to use another string variable, since Ans can act like a string and it gets updated accordingly, and Ans is also faster than a string variable. In addition, by storing the string to Str1 inside the loop, we avoid having to add an additional storage to the routine.

We store the string to a more permanent variable (in this case, Str1) for future use. When you are done using Str1, you should clean it up at the end of your program.

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/deleted:repeat-a-string

Reverse a String

Reverses the characters in a string.

*Str1* - The string you want to reverse

*Str1* - The reversed string

Str1, I, Ans

TI-83/84/+/SE

```
:Str1
:For(I,1,length(Ans)-1
:sub(Ans,2I,1)+Ans
:End
:sub(Ans,1,I→Str1
```

With our string stored in Str1 and Ans, we loop through each character, starting from the beginning to the end, and add it to the beginning of the string, building the reversed string up at the beginning as we go:

```
12345 (original string - the first character is the first reversed character)
212345 (add then second character before the first, reversing the string)
3212345 (continue adding characters in reverse)
543212345 (this is what the end result looks like)
```

Since adding to the beginning of the string alters the indices, we must take that into account — this is where the 2I in the formula comes from. It adds the 2nd character the first time, the 4th character (which was originally the 3rd) next, the 6th character (originally the 4th) after that, and so on.

Using Ans allows us to not have to use another string variable, since Ans can act like a string and it gets updated accordingly, and Ans is also faster than a string variable.

By the time we are done with the For( loop, all of our characters are put together in Ans in reverse order, before the original string. To finish, we take the first (reversed) half as a substring and store it back in Str1 for further use. We can use I for this purpose because it looped from 1 to length(Str1)-1, so its value will be length(Str1) when exiting.

If you want to preserve the original string, store it to a different string variable in the first line of the code.

When you are done using Str1, you should clean it up at the end of your program.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/reverse-a-string

Run-Length Encoding (RLE) Compression

Compresses a list of numbers using RLE compression.

*L₁* - The list of numbers you want to compress

*L₁* - The list of compressed numbers

L₁, I, J

TI-83/84/+/SE

```
:1→J
:For(I,2,dim(L₁
:If L₁(I)=L₁(J:Then
:.002+L₁(J→L₁(J
:Else
:If L₁(I)=int(L₁(J:Then
:.001+L₁(J→L₁(J
:Else
:J+1→J
:L₁(I→L₁(J
:End:End:End
:J→dim(L₁
```

Run-length encoding (RLE) is a very easy compression algorithm that you can use for compressing a list of numbers. The way it works is that you remove all of the consecutive repeated numbers from the list, and modify the first instance of the numbers with how many repeated numbers there were.

For example, say you have a list of numbers 1,2,2,3,3,3,4. You start with the 1, and since there is only one 1, it wouldn't be modified. There are two 2's, however, so you would remove the second two, and add a decimal part (using fPart() of how many 2's there were (in this case, just two, which we represent as .002). You would do this for the rest of the list, and the final list would be 1,2.002,3.003,4.

To save memory (which is of course the reason we're compressing) we will store the result to L₁, the same list the uncompressed data is in. Throughout the loop, J is the index of the last element of the compressed part of the list, and I is the index in the uncompressed part. We don't have to worry about the indices colliding, since I is always bigger than J.

We loop over the list with I, and check if the current element has the same value as the last element of the compressed list. If it is, then it's the beginning of a run, so we add .002 to that last element.

If it isn't there's another possibility — the last element could represent an existing run of the same element. We check for this with the code If L₁(I)=int(L₁(J)). If this turns out to be the case, we add .001 to increase the length of the run. Otherwise, the element really is different, and we increase J and add a new element.

At the end, we store J to the size of L₁. This gets rid of all the unnecessary data, leaving us only with the compressed portion of the list.

Note that we never store anything to L₁ itself, only to its elements. This is a useful technique to avoid using too much memory while the program is running: if we stored to L₁, a copy of the list would be stored to Ans, which could easily give a ERR:MEMORY if the list is too large. As the program is now, the only additional memory used is contained in three real variables (I, J, and Ans).

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/rle-compress

Run-Length Encoding (RLE) Decompression

Decompresses a run length-encoded list.

*L₁* - The compressed list

*L₁* - The decompressed list

L₁, I, J

TI-83/84/+/SE

```
:dim(L₁→J
:sum(E3fPart(L₁)+not(fPart(L₁→dim(L₁
:For(I,Ans,1,-1
:int(L₁(J→L₁(I
:If .001<fPart(L₁(J:Then
:L₁(J)-.001→L₁(J
:Else
:J-1→J
:End:End
```

Run-length encoding (RLE) is a very easy compression algorithm that you can use for compressing a list of numbers. The way it works is that you remove all of the consecutive repeated numbers from the list, and modify the first instance of the numbers with how many repeated numbers there were.

For example, say you have a list of numbers 1,2,2,3,3,3,4. You start with the 1, and since there is only one 1, it wouldn't be modified. There are two 2's, however, so you would remove the second two, and add a decimal part (using fPart() of how many 2's there were (in this case, just two, which we represent as .002). You would do this for the rest of the list, and the final list would be 1,2.002,3.003,4.

This routine could loosely be described as the RLE compression routine, but backwards. We start by calculating the length of the decompressed list. This is the sum of the length of the runs — E3fPart(L₁) — plus the number of elements with no runs — not(fPart(L₁)). Here E represents the scientific E.

Then, the decompression begins. The routine keeps the following loop invariants (things that stay true after each iteration of the loop):

- Every element after the Ith element is the correct decompressed element in that spot.
- The portion of the list up to and including the Jth element is the compressed version of the list elements that will be 1 through I.

We "unpack" one element from the end of the compressed portion: int(L₁(J→L₁(I. Then we test if this compressed portion is a run that still contains more elements. If it is, we subtract .001, reducing the number of elements in the run by 1. If it's not, we decrease J by 1 to move on to the previous compressed element. As you can see, the conditions listed above are still true.

Once the loop ends, the first condition of the ones above ensures that all elements have been correctly decompressed.

Note that we never store anything to L₁ itself, only to its elements. This is done to avoid using any more memory than necessary: if we stored to L₁, a copy of the list would get temporarily stored to Ans, and we would be using twice the memory we need. This way, the routine will work even for large lists. As a bonus, the only time we change the size of the list is the very beginning. So if the decompressed list wouldn't fit in memory, the routine crashes immediately and keeps the list intact.

# Error Conditions

**ERR:MEMORY**is thrown if there is not enough space to store the decompressed list.**ERR:INVALID DIM**is thrown if the decompressed list would be longer than 999 elements.

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/rle-decompress

Scramble a String

Scrambles a string

*Str1* - The string you want to scramble

*Ans* - The scrambled string

Ans, Str1, L, θ, L₁, L₂

TI-83/84/+/SE

seb83, Edward H, Timothy Foster

This routine takes a string stored in Str1 and scramble it. The results is contained in Ans. For example, "ABCDE12345" could be scrambled to "B34AC1DE25".

```
:rand(length(Str1→L₁
:cumSum(1 or Ans→L₂
:SortA(L₁,L₂
:sub(Str1,L₂(1),1
:For(N,2,length(Str1
:Ans+sub(Str1,L₂(N),1
:End
```

With your string stored in Str1, it creates L₁={1,2,3,4,…,length(Str1)}. After that, L₂ is created randomly to sort L₁ in function of L₂. L₁ now could look like {5,3,4,1,2} if you entered a 5 character string. In the For( loop, it takes one by one the character of Str1 accordingly to L₁ to store it to Ans. Your scrambled string is now in Ans.

For the TI-84+ and higher with a MathPrint or color OS, use this code instead:

```
:randIntNoRep(1,length(Str1→L₁
:sub(Str1,Ans(1),1
:For(N,2,length(Str1
:Ans+sub(Str1,L₁(N),1
:End
```

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/scramble-a-string

Shading Circles

Shades in a circle.

*R* - the radius of the circle

*A* - the X coordinate of the circle's center

*B* - the Y coordinate of the circle's center

None

N, R, A, B

TI-83/84/+/SE

Jutt

*URL:* United TI

```
:For(N,0,R,ΔX
:√(R²-N²
:Line(A+N,B-Ans,A+N,B+Ans
:Line(A-N,B-Ans,A-N,B+Ans
:End
```

Although it is possible to shade in a circle using the Shade( command (i.e., Shade(-√(R²-(X-A)²)+B,√(R²-(X-A)²)+B)), that is actually quite impractical in a real program because of its slow speed. Fortunately, you can improve upon that by using your own routine.

When graphing a circle, there are a few main things you need to know: the radius and the (X,Y) coordinates of the center. In our routine, the R variable is the radius, the A variable is the circle's X coordinate and the B variable is the circle's Y coordinate.

Rather than displaying the circle as one big circle, we are going to display it line by line using a For( loop, starting from the center. The √(R²-N² formula is based on the circle formula R^{2}=(X–H)^{2}+(Y–K)^{2}, with the formula rearranged to get the respective part of the circle.

The circle should display pretty quickly, but it all depends on the values that you chose for the variables; smaller values will be faster, and likewise larger values will be slower. In addition, the circle may not display correctly if you don't have the right graph settings, so you should set your calculator to a friendly graphing window.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/shading-circles

String to List

Converts a string to a list of numbers.

*Str1* - The string you want to convert

*L₁* - The list that the numbers are stored to

L₁, A, Str1

TI-83/84/+/SE

`:1+seq(inString("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ",sub(Str1,A,1)),A,1,length(Str1→L₁`

With our characters stored in Str1, we loop through each character and store its position in our reference string (the uppercase alphabet) to the respective element of L₁.

This routine only allows for values from 1 to 26 in the list, since our string of characters is the uppercase alphabet, and each list value must match up to one of the string positions. If you add more characters to the string, however, you can increase the range of values in the list. This routine uses Str1, so you should clean it up at the end of your program.

# Advanced Routine

Since a list element can store up to 14 digits, you can use int(, fPart(, and exponents to compress an additional 7 letters per element (2 digits for each letter), thus increasing your total number of characters to 6993.

```
" ABCDEFGHIJKLMNOPQRSTUVWXYZ->Str0
DelVar L1
For(A,0,dim(L1
0
For(B,1,min(7,length(Str1)-7A
Ans+.1^(2B)inString(Str0,sub(Str1,B+7A,1
End
Ans->L1(A+1
End
"
```

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/string-to-list

Strip a String

Strip a string of its spaces on the left and right.

*Ans* - The string you want to strip

*Str1* - The stripped string

Ans, Str1

TI-83/84/+/SE

```
:While " "=sub(Ans,1,1) or " "=sub(Ans,length(Ans),1
:sub(Ans,1+(" "=sub(Ans,1,1)),length(Ans)-1→Str1
:End
```

With our string stored in Ans, we check to see if there is a space at the beginning or end of the string. If there is a space, then we remove it by storing the substring of the string that doesn't include the first character (for a space at the beginning) or the last character (for a space at the ending), and store the new string to Str1.

At the same time, the new string is stored to Ans, which is what we use next time through the While loop. The loop gets repeated over and over again until we have stripped all of the spaces from the beginning and end of the string. If you only want to remove spaces on one side of the string, edit the first and second lines accordingly.

Using Ans allows us to not have to use another string variable, since Ans can act like a string and it gets updated accordingly, and Ans is also faster than a string variable. In addition, by storing the string to Str1 inside the loop, we avoid having to add an additional storage to the routine.

We store the string to a more permanent variable (in this case, Str1) for future use. When you are done using Str1, you should clean it up at the end of your program.

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/strip-a-string

Sum of Digits

Returns the sum of digits of a number.

*X* - the number you want

*Ans* - the sum of X's digits

X, Ans

TI-83/84/+/SE

DarkerLine

*URL:* United TI

`:sum(int(10fPart(Xseq(10^(-I-1),I,0,log(X`

With our number stored in X, we loop through each of the digits of the number starting from the right using the seq( command. We get the respective digit by raising the number to the respective power of 10 and then multiplying the result by 10. The digits are returned separately in a list, and then we take the sum of them using the sum( command.

For example, if the number is 1234, we get a list of {1,2,3,4}, which then returns a sum of 10. You should note, though, that this routine only works with positive and negative whole numbers, and will return incorrect results if you try to use a decimal number. You could fix this problem by using the code below instead:

`:abs(E13(X/10^(int(log(abs(X+not(X→X`

Here, we obtain the appropriate power of ten by which to divide the number so as to leave only one digit to the left of the decimal point. Because a real variable may contain only 14 digits, the answer is multiplied by 10^13 to guarantee the removal of any fractional part. From taking the absolute value of this new result, our number can be safely entered into the routine above.

Note: It should be understood that this routine is only capable of adding the first 14 digits of a number. An input of π, for instance, would return 69 even though the sum of all digits of π is infinite.

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/sum-of-digits

Sum of Matrix Elements

Returns the sum of the elements of a matrix.

*[A]* - the matrix whose elements you want to sum

*Ans* - the sum of the matrix elements

[A], L₁, Ans

TI-83/84/+/SE

zada

*URL:* United TI

:dim([A]

:Matr►list(cumSum([A])^{T},Ans(1),L_{1}

:sum(L_{1}

The cumSum( command gets the cumulative sum of each column in the matrix, adding the value of the previous element to the next element, and repeating this for each consecutive element in the column. When the cumSum( command is finished, the last element in each column will contain the sum of that column. Taking the ^{T} (transpose) of the resulting matrix switches columns and rows.

Then, using the Matr►list( command, the last column of this result is stored to L₁. This column was originally the last row of cumSum('s output, so it contains all the column sums. Finally, by calculating the sum of that list, we get the total of the matrix elements. L₁ is no longer necessary, and can be deleted.

If you want to use the sum for future use, you can store it to a more permanent variable, such as A or X. When you are done using [A], you should clean it up at the end of your program.

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/sum-of-matrix

Typewriter Routine

Makes text appear letter by letter

*Str1* - Text to be displayed.

*A,B* - Row and colum to display text.

*A, B, T, Str1*

All TI calculators

```
:For(T,1,length(Str1
:Text(A,B,sub(Str1,1,T
:rand(5
:End
```

We use a For( loop over the length of the string to go through the string letter by letter. In order to make the spacing come out right, instead of figuring out the right coordinate to display each character at, we display the first T characters of the string starting from the beginning. The rand(5) provides a split-second delay to achieve the typewriter effect.

For multiple lines with the typewriter effect, you can combine this routine with the one to wordwrap text.

# Error Conditions

**ERR:DOMAIN**is thrown if the string doesn't fit entirely on the screen.

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/typewriter

Wordwrapping Text on the Graphscreen

Displays text on several lines on the graph screen.

*Str1* - text to display

*A* - starting row

*B* - starting column

None

Str1, A, B, C, Ans

TI-83/84/+/SE

```
:1→C
:For(A,A,57,6
:inString(Str1,"/",Ans
:Text(A,B,sub(Str1,C,Ans-C
:If Ans=length(Str1:57→A
:Ans+1→C
:End
```

This routine displays a string on the graph screen, with line breaks after every slash "/" character. The routine requires there to be a slash at the end of the string (so, a sample string would be "THIS TEXT IS TOO LONG TO/DISPLAY ON ONE LINE/").

The row and column (A and B) inputs determine the upper and left boundaries of the text. You determine the right boundary by where you put the slash characters. The lower boundary is 57, hardcoded into the routine (this is the lowest that text can be displayed), but you could change this if you wanted a different boundary.

The variable C is used for an index inside Str1, that tells us which character we're currently on. We're starting at the beginning of the string, so we store 1 to C.

The For( loop will increment A by 6 each time we display a line (small font characters are 6 pixels tall). We start at the current value of A, and end at 57 because beyond that, Text( will throw a domain error.

Now, we search for the next slash "/" character using the inString( command. Then, using Text(, we display the line between C and the "/", not including the slash itself. Ans+1→C will move the C index to the next character after the slash.

The line If Ans=length(Str1:57→A will end the loop early as soon as we reach the end of the string. This command can modify Ans, which would be bad, but it only does so when we're ready to exit anyway — at that point, we won't be needing Ans anymore.

# Error Conditions

**ERR:INVALID DIM**is thrown if Str1 is improperly formatted (check for the backslash at the end).**ERR:DOMAIN**is thrown if text goes off the screen. This shouldn't happen unless B is very close to the right edge, if A or B are negative, or if the calculator is in Horiz mode (in which case, replace 57 with 25).

# Related Routines

For the most up-to-date version of this routine, see http://tibasicdev.wikidot.com/wordwrap-text