# HP Calculator Wiki

### Site Tools

rpl:start

About RPL programming and what not.

The page can grow and then be split in different pages, using this as starting point.

## Library of useful commands

%%HP: T(0)A(D)F(.);
@ alternative found online %%HP: T(3)A(R)F(.);
@ You may edit the T(0)A(D)F(.) parts.
@ The earlier parts of the line are used by Debug4x.

@ in npp, just select language "normal" to get rid of the highlight.

DIR

helpTemplate
"
url: '-',
tags: [ 'help', 'template' ],
description:
this is a template for quick use. Feel free to improve it.

Input:
L3:
L2:
L1:
Output
L3:
L2:
L1:

Example(s):
"

@##################################
@#
@# vector or matrix operations

@ url: '-',
@ tags: [ 'vector operations' ],
@ description:
@  see 50g user manual page 9-20
@  it transforms a row vector like [1 2 3]
@  in a column vector that is a matrix
@  and viceversa

@input:
@L1: a row vector like [1 2 3]
rowVtoColV
\<<
OBJ\-> 1 + \->ARRY
\>>

@input:
@L1: a colum  vector like [[1] [2] [3]] (that is, a matrix)
colVtorowV
\<<
OBJ\->  @explode the matrix
OBJ\->  @explode the dimension list
DROP    @keep only the first dimension, the number of rows
\->ARRY @make a vector.
\>>

@ url: '-',
@ tags: [ 'vector operations' ],
@ description:
@  see 50g user manual page 10-11
infoColVtoRowV

@ url: '-',
@ tags: [ 'vector operations' ],
@ description:
@  see 50g user manual page 9-23
@  it transforms a list in a vector like [1 2 3]
listToVector
\<<
OBJ\->  1 \->LIST \->ARRY
\>>

@ url: '-',
@ tags: [ 'vector', 'angle between vectors' ],
@ description:
@  see 50g user manual page 9-16
@  and math.stackexchange.com/questions/1047649/distance-and-angle-between-vectors-in-multiple-dimensions

@input
@L2: row vector
@L1: row vector
angleBetweenTwoVectors
\<<

\->
@input
lvVector1
lvVector2

\<<
lvVector1 lvVector2 DOT

lvVector1 ABS
lvVector2 ABS
*

/
ACOS
\>>
\>>

@ url: '-',
@ tags: [ 'vector', 'angle between vectors' ],
@ description:
@  see 50g user manual page 9-16
@  and math.stackexchange.com/questions/1047649/distance-and-angle-between-vectors-in-multiple-dimensions

@input
@L2: arm of the force vector
@L1: force vector
@output
@L2: moment vector
@L1: angle used to compute the norm of the moment vector
@    between force vector and arm of the force vector

momentOfAForce
\<<
0 @lvVectorMoment

\->
@input
lvVectorArmForce
lvVectorForce
@var
lvVectorMoment

\<<
lvVectorArmForce lvVectorForce CROSS
DUP
'lvVectorMoment' STO
"momentVector" \->TAG

@computing the angle X such that
@ norm(Moment) = norm(Force) * norm(armForce) * sin(X)
lvVectorMoment ABS

lvVectorArmForce ABS
lvVectorForce ABS
*
/
ASIN
"Angle" \->TAG
\>>
\>>

@info
@ tags: [ 'matrix operations' ],
@ description:
infoApplyFuncToMatrix
"[[ -9 0 -1 -4 ]
[ 4 9 3 3 ]
[ 0 4 -9 9 ]
[ 5 -1 -6 -4 ]]

'LN(X)' DIAGMAP XNUM
"

@ url: '-',
@ tags: [ 'vector', 'equation of a plane' ],
@ description:
@  see 50g user manual page 9-17
@  and math.stackexchange.com/questions/753113/how-to-find-an-equation-of-the-plane-given-its-normal-vector-and-a-point-on-the
@  Given a normal vector to a plane and a point in it, return a vector that defines
@  the equation of the plane.

@Remarks:
@ no input check, the vectors should have 3 components otherwise the program
@ does not work as intended.
@input
@L2: normal vector to the plane
@L1: point in the plane
@output
@L1: a vector defining the coefficients for the axis
@    X,Y,Z plus a constant.
@    Say the result will be [4 6 2 -24] if the equation of the plane is
@    4x+6y+2z-24=0 .
eqPlaneNormalVandPoint
\<<

\->
lvNormalVector
lvPointInPlane

\<<
lvNormalVector
lvNormalVector lvPointInPlane DOT
4 @remember it works only for 3 dimensional vectors
COL+
\>>
\>>

@ url: '-',
@ tags: [ 'matrix', 'from a series of list to a matrix' ],
@ description:
@  see 50g user manual page 10-14

@input
@L2-Ln+1: n lists of the same dimension
@L1: number of lists to consider on the stack
@output
@L1: a matrix with the lists as columns
lists2matrixColumns
\<<
DUP
\-> n
\<<
1 SWAP
FOR j
OBJ\-> \->ARRY
IF
j n <
THEN
j 1 +
ROLL
END
NEXT

IF
n 1 >
THEN
1 n 1 -
FOR j
j 1 +
ROLL
NEXT
END
n
COL\->
\>>
\>>

@input
@L2-Ln+1: n lists of the same dimension
@L1: number of lists to consider on the stack
@output
@L1: a matrix with the lists as rows
lists2matrixRows
\<<
DUP
\-> n
\<<
1 SWAP
FOR j
OBJ\-> \->ARRY
IF
j n <
THEN
j 1 +
ROLL
END
NEXT

IF
n 1 >
THEN
1 n 1 -
FOR j
j 1 +
ROLL
NEXT
END
n
ROW\->
\>>
\>>

@alternative solution
@input
@L2-Ln+1: n lists of the same dimension
@L1: number of lists to consider on the stack
@output
@L1: a matrix with the lists as columns
lists2matrixColumnsNo2
\<<
@note that we do not consume as input, immediately,
@all the lists

0     "lvInputLists"   DROP

\->
@input
lvListsNumber
@var
lvInputLists

\<<
lvListsNumber \->LIST
@put the lists in one big list
@ as { 1 } { 2 } 2 \->LIST produces { {1} {2} }
'lvInputLists' STO

lvInputLists
1
\<<
listToVector @program included before
\>>
DOSUBS
@we have a list of row vectors now

@explode the list and make a matrix
OBJ\->
COL\->
\>>
\>>

@alternative solution
@input
@L2-Ln+1: n lists of the same dimension
@L1: number of lists to consider on the stack
@output
@L1: a matrix with the lists as rows
lists2matrixRowsNo2
\<<
@note that we do not consume as input, immediately,
@all the lists

0     "lvInputLists"   DROP

\->
@input
lvListsNumber
@var
lvInputLists

\<<
lvListsNumber \->LIST
@put the lists in one big list
@ as { 1 } { 2 } 2 \->LIST produces { {1} {2} }
'lvInputLists' STO

lvInputLists
1
\<<
listToVector @program included before
\>>
DOSUBS
@we have a list of row vectors now

@explode the list and make a matrix
OBJ\->
ROW\->
\>>
\>>

@alternative solution
@ REMARKS:
@ - using listExt www.hpcalc.org/details/7971
@input
@L2-Ln+1: n lists of the same dimension
@L1: number of lists to consider on the stack
@output
@L1: a matrix with the lists as rows
lists2matrixRowsNo3
\<<
@note that we do not consume as input, immediately,
@all the lists

0     "lvInputLists"       DROP
0     "lvSingleListSize"   DROP

\->
@input
lvListsNumber
@var
lvInputLists
lvSingleListSize

\<<
@get one list size, presuming equal dimension for all.
DUP SIZE 'lvSingleListSize' STO

lvListsNumber \->LIST
@put the lists in one big list
@ as { 1 } { 2 } 2 \->LIST produces { {1} {2} }
'lvInputLists' STO

lvInputLists LXIL @explodes all sublists
listToVector @program included before

@we have one row vector now
lvListsNumber @rows
lvSingleListSize @columns
2 \->LIST
RDM
\>>
\>>

@alternative solution
@input
@L2-Ln+1: n lists of the same dimension
@L1: number of lists to consider on the stack
@output
@L1: a matrix with the lists as columns
lists2matrixColumnsNo3
\<<
lists2matrixRowsNo3
TRAN
\>>

@alternative solution
@input
@L2-Ln+1: n lists of the same dimension
@L1: number of lists to consider on the stack
@output
@L1: a matrix with the lists as rows
lists2matrixRowsNo4
\<<
\->LIST
@put the lists in one big list
@ as { 1 } { 2 } 2 \->LIST produces { {1} {2} }
AXL
\>>

@alternative solution
@input
@L2-Ln+1: n lists of the same dimension
@L1: number of lists to consider on the stack
@output
@L1: a matrix with the lists as columns
lists2matrixColumnsNo4
\<<
lists2matrixRowsNo4
TRAN
\>>

@input
@L1: a matrix
@output
@L1: list representing the rows of a matrix in sublists
matrixRows2list
"just use AXL"

@input
@L1: a matrix
@output
@L1: list representing the columns of a matrix in sublists
matrixColumns2list
\<<
TRAN
AXL
\>>

MTRANSPOSEhelp
"
tags: [ 'matrix', 'transpose' ],
description:
matrix transpose through lists faster than built in TRAN

Remarks: listExt used. See links collection in this file.

Input:
a matrix.
output:
a matrix transposed.
"

MTRANSPOSE
\<<
AXL DUP LXIL SWAP SIZE LDIST AXL
\>>

gpArrayPosHelp
"
url: '-',
tags: [ 'array', 'find element' ],
description:
finds the first position of an element in an array. Similar to POS (for list and strings)

Input:
L2: ARRAY
L1: Element
Output

Example(s):
"
gpArrayPos
\<<
2 PICK SIZE 1 GET @takes the array and compute the size
-1 "lvResult" DROP
\->
lvArrayInput
lvElement
lvArraySize
lvResult
\<<
1 lvArraySize
FOR lvPOS
IF
lvArrayInput lvPOS GET
lvElement ==
THEN
lvPOS 'lvResult' STO
lvPOS lvArraySize + 'lvPOS' STO @we quit the FOR
END
NEXT

lvResult
\>>
\>>

gpArrayPosFromHelp
"
url: '-',
tags: [ 'array', 'find element' ],
description:
finds the first position of an element in an array strating from a given position. Extension of Pos

Input:
L2: ARRAY
L1: starting position
L1: Element
Output

Example(s):
"
gpArrayPosFrom
\<<
3 PICK SIZE 1 GET @takes the array and compute the size
-1 "lvResult" DROP
\->
lvArrayInput
lvStartPos
lvElement
lvArraySize
lvResult
\<<
1 lvArraySize
FOR lvPOS
IF
lvPOS lvStartPos <
THEN
lvStartPos 'lvPOS' STO
END
IF
lvArrayInput lvPOS GET
lvElement ==
THEN
lvPOS 'lvResult' STO
lvPOS lvArraySize + 'lvPOS' STO @we quit the FOR
END
NEXT

lvResult
\>>
\>>

JKMAPHelp
"
tags: [ 'array', 'matrix', 'map' ],
description:
Here is a fast replacement for MAP using ListExt commands.
It works for matrices or vectors but not for lists. It does not change the type of the array.
The function can be a program, a list or a null-tagged object.
remarks:
it requires ListExt https://www.hpcalc.org/details/7971

Input:
L2: an array or a matrix
L1: a program, a list or a null-tagged object.
Output
L1: the array or the matrix with the elements changed by the application of the function or the program.

Example(s):
-
"

JKMAP
\<< SWAP OBJ\-> DUP \-> s
\<< LPROD \->LIST SWAP LXEQ s \->ARRY
\>>
\>>

@##################################
@#
@# 50g filesystem operations

@ tags: [ 'directory management', 'sorting variables', 'file manager' ],
@ description: 'the code orders the contents of a directory and subdirectories',
@
@ !!
@ Recursive program; change ProgName within program to whatever
@ !!
@
@ name is chosen for storing the program.
@ Results from the BYTES command:
@ 48G series:
@   Checksum: # 5394h
@   Size:         129
@ 49 series:
@   Checksum: # C209h
@   Size:        125.
orderDirContents
\<<                     @ Begin program.
VARS                @ Get list of variables.
DUP                 @ Copy of variables list.
IF                  @
SIZE              @ Variables list not empty?
THEN
SORT              @ Sort list to ASCII order.
ORDER             @ Reorder variables.
15 TVARS          @ Get list of subdirectories.
DUP               @ Copy of subdirectories list
SIZE              @ Number of subdirectories.
IF                @
DUP             @ Subdirectories list not empty?
THEN              @
OVER            @ Copy of subdirectory list.
ORDER           @ Move subdirectories to front.
1               @ Loop begin index.
SWAP            @ Move down number of subdirectories.
FOR n           @ For each subdirectory.
DUP           @ Copy of subdirectory list.
n GET         @ Get subdirectory name.
EVAL          @ Make subdirectory current.
ProgName      @ Call this program recursively.
NEXT            @
ELSE              @
DROP2           @ Discard empty subdirectories list and size 0.
END               @
ELSE                @
DROP              @ Discard empty variables list.
END
\>>                     @ End program.

@##################################
@#
@# Math operations

@tags: [ 'polar', 'rectangular', 'coordinate system' ],
@description: 'several userRPL programs to switch from polar to rectangular
@  representation of numbers',

@ 2 dimensional P\->R program.
@ Arguments: 2 reals representing r and theta.
@ Returns: 2 reals representing x and y.
polar2rect
\<<             @ Begin program.
RCLF          @ Get current flags.
ROT ROT       @ Move flags list to level 3.
@ On 49 series, UNROT may be used
CYLIN         @ Force cylindrical display mode.
@ SPHERE would work as well here.
\->V2         @ Combine into vector or complex.
RECT          @ Force rectangular display mode.
V\->          @ Decompose into reals.
ROT           @ Move flags list back to level 1.
STOF          @ Restore original flags.
\>>

@ 2 dimensional R\->P program.
@ Arguments: 2 reals representing x and y.
@ Returns: 2 reals representing r and theta.
rect2polar
\<<             @ Begin program.
RCLF          @ Get current flags.
ROT ROT       @ Move flags list to level 3.
@ On 49 series, UNROT may be used
RECT          @ Force rectangular display mode.
\->V2         @ Combine into vector or complex.
CYLIN         @ Force cylindrical display mode.
@ SPHERE would work as well here.
V\->          @ Decompose into reals.
ROT           @ Move flags list back to level 1.
STOF          @ Restore original flags.
\>>

@ 3 dimensional Cylindrical\->Rectangular program.
@ Arguments: 3 reals representing r, theta, and z.
@ Returns: 3 reals representing x, y, and z.
cylindrical2rectangular
\<<             @ Begin program.
RCLF          @ Get current flags.
4 ROLLD       @ Move flags list to level 4.
CYLIN         @ Force cylindrical display mode.
\->V3         @ Combine into vector.
RECT          @ Force rectangular display mode.
V\->          @ Decompose into reals.
4 ROLL        @ Move flags list back to level 1.
STOF          @ Restore original flags.
\>>

@ 3 dimensional Rectangular\->Cylindrical program.
@ Arguments: 3 reals representing x, y, and z.
@ Returns: 3 reals representing r, theta, and z.
rectangular2cylindrical
\<<             @ Begin program.
RCLF          @ Get current flags.
4 ROLLD       @ Move flags list to level 4.
RECT          @ Force rectangular display mode.
\->V3         @ Combine into vector.
CYLIN         @ Force cylindrical display mode.
V\->          @ Decompose into reals.
4 ROLL        @ Move flags list back to level 1.
STOF          @ Restore original flags.
\>>

@ 3 dimensional Spherical\->Rectangular program.
@ Arguments: 3 reals representing rho, phi, and theta.
@ Returns: 3 reals representing x, y, and z.
spherical2rectangular
\<<             @ Begin program.
RCLF          @ Get current flags.
4 ROLLD       @ Move flags list to level 4.
SPHERE        @ Force spherical display mode.
\->V3         @ Combine into vector.
RECT          @ Force rectangular display mode.
V\->          @ Decompose into reals.
4 ROLL        @ Move flags list back to level 1.
STOF          @ Restore original flags.
\>>

@ 3 dimensional Rectangular\->Spherical program.
@ Arguments: 3 reals representing x, y, and z.
@ Returns: 3 reals representing rho, phi, and theta.
rectangular2spherical
\<<             @ Begin program.
RCLF          @ Get current flags.
4 ROLLD       @ Move flags list to level 4.
RECT          @ Force rectangular display mode.
\->V3         @ Combine into vector.
SPHERE        @ Force spherical display mode.
V\->          @ Decompose into reals.
4 ROLL        @ Move flags list back to level 1.
STOF          @ Restore original flags.
\>>

@ 3 dimensional Cylindrical\->Spherical program.
@ Arguments: 3 reals representing r, theta, and z.
@ Returns: 3 reals representing rho, phi, and theta.
cylindrical2spherical
\<<             @ Begin program.
RCLF          @ Get current flags.
4 ROLLD       @ Move flags list to level 4.
CYLIN         @ Force cylindrical display mode.
\->V3         @ Combine into vector.
SPHERE        @ Force spherical display mode.
V\->          @ Decompose into reals.
4 ROLL        @ Move flags list back to level 1.
STOF          @ Restore original flags.
\>>

@ 3 dimensional Spherical\->Cylindrical program.
@ Arguments: 3 reals representing rho, phi, and theta.
@ Returns: 3 reals representing r, theta, and z.
spherical2cylindrical
\<<             @ Begin program.
RCLF          @ Get current flags.
4 ROLLD       @ Move flags list to level 4.
SPHERE        @ Force spherical display mode.
\->V3         @ Combine into vector.
CYLIN         @ Force cylindrical display mode.
V\->          @ Decompose into reals.
4 ROLL        @ Move flags list back to level 1.
STOF          @ Restore original flags.
\>>

@tags: [ 'Euler totient' ],
@description:
@  See oeis.org/A000010 .
@  Note: the 50g has this function natively implemented.
@
eulerTotient
\<< DUP
IF 1 \=/
THEN { } SWAP FACTORS DUP SIZE 1 SWAP
FOR i DUP i GET ROT + SWAP 2
STEP { } SWAP DUP SIZE 2 SWAP
FOR i DUP i GET ROT + SWAP 2
STEP DROP 1 - OVER SWAP
\<< ^
\>> DOLIST SWAP 1 - + \PILIST
END
\>>
@examples: [
@  'Input: 98765430111
@   Output: 61497371520',
@],

@tags: [ 'farey sequence', 'fractions' ],
@description: '
@  computes the farey sequence
@  en.wikipedia.org/wiki/Farey_sequence
@',
fareySequence
\<< \-> n
\<< { [ 0 1 ] } 0 1 DUP n
WHILE OVER n <
REPEAT \-> a b c d
\<< c d \->V2 +
c d
n b + d / IP
DUP c * a -
SWAP d * b -
\>>
END
DROP2 DROP2
\>>
\>>
@examples: [
@  'Input: the wanted <n> terms of the sequence
@   Output: the farey sequence',
@],

randIntHelp
tags: [ 'random number', 'statistics' ],
description:
returns a random integer number between 1 and the value given

Input: an integer number (as real)
output: an integer (as real) between 1 and the input inclusive
"

randInt
\<<
RAND * CEIL
\>>

randIntRangeHelp
" url: '-',
tags: [ 'random number', 'statistics' ],
description:
returns a random integer in the specified value

Input:
L2: min value
L1: max value
output: an integer (as real) between min and max value included
"
randIntRange
\<<
\->
lvMin
lvMax
\<<
lvMax lvMin - @the distance max-min
1 + @a value that we need to offset CEIL later
RAND * CEIL
1 -
@due to ceil, if the size of the range is, say, 4 large,
@one would expect values in (0,1,2,3,4) but with ceil 0 is never happening.
@Thanks to a larger range we have (0,1,2,3,4,5) where 0 is never happening.
@Thus we have (1,2,3,4,5)
@Then we need to shift of one value on the left, obtaining (0,1,2,3,4) as wished
lvMin
+
\>>
\>>

randCoinHelp
" url: '-',
tags: [ 'random coin number', 'statistics' ],
description:
returns a random integer between 0 and 1

Input: -
output: an integer (as real) between 0 and 1
"

randCoin
\<<
2 RAND * FLOOR
\>>

DEC2FRAChelp
"
tags: [ 'best fraction' ],
description:
Given any decimal fraction in level 2, and a maximum denominator in level 1, it returns the best fraction

input
L2: number to approximate
L1: max denominator
Example:
pi, 1000, DEC2FRAC --> 355/113 in 0.39 seconds
pi, 100000, DEC2FRAC --> 312689/99532 in 0.43 seconds
"

DEC2FRAC
\<< DUP2 @ Must be two arguments.  Exit now if max denominator < 2,
IF 1 > SWAP FP AND @ or if decimal fraction is an integer.
THEN \-> f c @ Store decimal fraction, and max denominator.

\<< 0 1 f @ Calculate only denominators.  Do numerator only at end.
WHILE OVER c < OVER AND @ Do until bigger than max denominator
REPEAT INV DUP FP 4 ROLLD IP OVER * ROT + ROT @ This is the
END DROP DUP2 c @ recursion formula continued fraction expansion.

IF DUP2 > @ Is there a possible "missing" fraction?
THEN - OVER / CEIL * - @ This is the new, fast "jump backwards".
ELSE 3 DROPN @ (Sometimes there's no need to jump.)
END DUP2 1 2 @ Take the new denominator & the previous one, and

START DUP f * 0 RND SWAP / f - ABS SWAP @ turn into fractions.
NEXT @ See which one's closest to the original decimal fraction.

IF > @ Compare the two solutions, and
THEN SWAP @ pick the better one.
END DROP DUP f * 0 RND SWAP @ Calculate the numerator.
\>> @ End of real work; now clean up the output.

IF DUP ABS 1 > @ Is the denominator greater than 1?
THEN -3 CF R\->I SWAP R\->I SWAP / @ If so, make output into 'A/B' form.
ELSE DROP @ Otherwise, get rid of extraneous denominator,
END @ and exit program.

ELSE DROP @ If bad arguments, do nothing to "decimal fraction", but
END @ get rid of "maximum denominator" and exit program.
\>>

iterateContFracHelp
"
tags: [ 'continous fraction' ],
description:
algorithm for converting a decimal into a fraction without storing the partial quotients of the expanded continued fraction.

Instructions:
(1) Clear the stack. Put calculator in exact mode.
(2) Place on level 1 of the stack either a decimal number,
or an algebraic ratio of two integers, e.g. '123/234'.
(3) Run the program repeatedly. Stop when level 4 shows infinity.

Each iteration will display the following on the stack:

4: Current value of N. Stop when it's infinity.
3: Previous Convergent p/q in the form of { p q }
2: Current Convergent a/b in the form { a b }
1: Decimal evaluation of a/b

Warning: Program must be loaded and run in exact mode.
"

iterateContFracHelp
\<<
IF DEPTH 1. SAME
THEN
IF DUP TYPE 0. ==
THEN 1.E50 * R\->I 50 ALOG /
END PROPFRAC { 0 1 } { 1 0 }
ELSE DROP 3. ROLL EVAL FXND SWAP OVER IDIV2 ROT SWAP / PROPFRAC 4. ROLLD OVER 4. ROLLD * ADD
END DUP EVAL SWAP \->NUM SWAP /
\>>

LOGBXhelp
tags: [ 'logarithms' ],
description:
logarithm of X in base b

Input:
L2: base
L1: number
output:
log_b(x)
"

LOGBX
\<< \-> b x \<< x LN b LN / \>> \>>

DoubleFactorialHelp
"
tags: [ 'factorial' ],
description:
this computes the double factorial on a number

Input:
L1: the input number
Output
L1: the double factorial

Example(s):
"

DoubleFactorial
\<<
\pi EVAL DUP2 * COS 1. - .25 * SWAP .5 * SWAP ^ SWAP .5 * DUP 2. SWAP ^ SWAP 1. + GAMMA * *
\>>

ItoSTRHelp
"
tags: [ 'list', 'base change' ],
description:
The first program ItoSTR take an integer n on level 2 and an integer b on level 1 and returns a string representing n in base b.
It requires ListExt

Input:
L1: integer value
L1: base
Output
L1: the integer in base b

Example(s):
257175174
62
ItoSTR

returns HP50g
"

ItoSTR
\<< I\->BL NL\->S
{ 36. 61. 61. } CHR+
{ 10. 35. 55. } CHR+
{ 0. 9. 48. } CHR+
\>>

STRtoIHelp
"
tags: [ 'list', 'base change' ],
description:
The next program STRtoI does the inverse, taking a string on level 2 and b on level 1.
It requires ListExt

Input:
L1: integer value
L1: base
Output
L1: the integer in base b

Example(s):
257175174
62
ItoSTR

returns HP50g
"
STRtoI
\<< SWAP
{ 48. 57. -48. } CHR+
{ 65. 90. -55. } CHR+
{ 97. 122. -61. } CHR+
S\->NL SWAP BL\->I
\>>

nBASEHelp
"
url: 'HP 50g Advanced User Guide v2 page 2-22',
tags: [ 'base change' ],
description:
nBASE converts a positive decimal number (x) into a tagged string representation of the equivalent value
in a different number base (b). Both x and b must be real numbers.
nBASE automatically rounds both arguments to the nearest integer.

Input:
L1: integer value
L1: base
Output
L1: the integer in base b

Example(s):
1000
23
nBASE

returns 1KB
"

nBASE
\<<
1 CF 0 RND SWAP 0 RND RCLF
@Clear flag 1, round both arguments to integers and recall flag settings.
\-> b n f
@Store the base, number and flag settings in local variables.
\<<
@Begin the outer local variable structure.
STD n LOG b LOG /
@Sets “standard” display mode and computes the ratio of the common logarithms of number and base.
10 RND
@Rounds result to remove imprecision in last decimal place.
IP n 0
@Find the integer part of log ratio, recall the original number, and initialize the counter variable k for use in the DO...UNTIL loop.
\-> i m k
@Store the values in local variables.
\<<
""
DO
'm' EVAL b i
'k' EVAL - ^
@Begin inner local variable structure, enter an empty string and begin the DO...UNTIL...END loop.
@Compute the decimal value of the
@(i – k) th position in the string.
DUP2 MOD
@Makes a copy of the arguments and computes the decimal value still remaining that must be accounted for by other positions.
IF DUP 0 ==
'm' EVAL b ≥
AND
@Is the remainder zero and m≥b?
THEN 1 SF
@If the test is true, then set flag 1.
END 'm' STO
/ IP
@Store the remainder in m. Compute the number of times the current position-value goes into the remaining decimal value. This is the “digit” that belongs in the current position.
IF DUP 10 ≥
@Is the “digit” ≥ 10?
THEN 55
ELSE 48
END + CHR
@Then convert the digit into a alphabetic digit (such as A, B, C, …).
+ 'k' 1 STO+
@Append the digit to the current result string and increment the counter variable k.

UNTIL 'm' EVAL 0 ==
@Repeat the DO...UNTIL loop until m = 0 (i.e. all decimal value have been accounted for).
END

IF 1 FS?C
@Is flag 1 set? Clear the flag after the test.
THEN "0" +
@Then add a placeholding zero to the result string.
WHILE i 'k' EVAL
- 0 \=/
@Begin WHILE...REPEAT loop to determine if additional placeholding zeros are needed.
@Loop repeats as long as i≠k.
REPEAT "0" +
1 'k' STO+
@Add an additional placeholding zero and increment k before repeating the test-clause.
END
END
\>>
@End the WHILE...REPEAT...END loop, the IF...THEN...END structure, and the inner local variable structure.
" base" b +
n SWAP + \->TAG @End the outermost IF...THEN...ELSE...END structure and create the label string and tag the result string using the original arguments.
f STOF @Restore original flag settings.
\>>
\>>

@##################################
@#
@# list operations and math on list

@tags: [ 'geometric mean', 'statistics' ],
@description: '
@  computes the geometric mean
@',
geometricMean
\<<
\->
list

\<<
list \PILIST list SIZE XROOT
\>>
\>>
@examples: [
@  'Input: a list of numbers
@   Output: the geometric mean',
@],

@url: '-',
@tags: [ 'harmonic mean', 'statistics' ],
@description: '
@  computes the harmonic mean
@  See also official hp 50g user guide (the large one with 800+ pages) page 8-15
@',
@examples:
@ - See official hp 50g user guide (the large one with 800+ pages) page 8-15

@Input:
@L1: a list of samples of which we want the harmonic mean.
@Output: the harmonic mean
harmonicMean
\<<

DUP SIZE
\->
@input
lvInputList
lvInputListSize

\<<
lvInputList INV \GSLIST
lvInputListSize /
INV
\>>
\>>

@url: '-',
@tags: [ 'weighted average', 'statistics' ],
@description: '
@  See also official hp 50g user guide (the large one with 800+ pages) page 8-17
@',
@examples:
@ - See official hp 50g user guide (the large one with 800+ pages) page 8-17

@Input:
@L2: A list of samples
@L1: A list of weights
@Output: the weighted average
weightedAverage
\<<

\->
@input
lvSampleList
lvWeightList

\<<
lvSampleList lvWeightList * \GSLIST
lvWeightList \GSLIST
/
\>>
\>>

@tags: [ 'average', 'moving average', 'statistics', 'list processing' ],
@description: '
@  computes the moving average and the average of a list
@average
@Input: a list of numbers
@Output: the average
average
\<< DUP \GSLIST SWAP SIZE / \>>

@moving average
@input:
@ L2: a list
@ L1: a number of elements to consider to compute the moving average
@output:
@ L1: the list with moving averages
movingAverage
\<< \-> N
\<< N \<< N \->LIST average \>> DOSUBS \>>
\>>

gpPSDEVlistHelp
"
url: '-',
tags: [ 'list', 'population variance deviation' ],
description:
compute the standard deviation of a list instead of relying on PSDEV and \GSDAT variable in a matrix form

remarks:
- it can be surely improved in speed (not sure about readability)

Input:
L3:
L2:
L1: a non-empty list of number
Output
L3:
L2:
L1: sqrt( 1/n * sum_1_n( (x_i -avg)^2 ) )

Example(s):

"

gpPSDEVlist
\<<
@input
"lvListInput" DROP

@localVar
0 "lvListSize" DROP

\->
@input
lvListInput

@localVar
lvListSize
\<<
@size of the list
lvListInput SIZE 'lvListSize' STO

@compute the average and make it a list
lvListInput \GSLIST lvListSize / lvListSize NDUPN \->LIST
@suptract from the input list
lvListInput -

@now we have a list of avg-x , we need to square the list
SQ @list of (x_i -avg)^2 (the squaring makes the subtraction order irrelevant)

@sum the values: sum_1_n( (x_i -avg)^2 )
\GSLIST

@divide by the size: 1/n * sum_1_n( (x_i -avg)^2 )
lvListSize /

@then we need to take the root of it and that is it.
\v/
\>>
\>>

@tags: [ 'list processing' ],
@description:
@  create a list of zero elements except one in a particular position
@input:
@L3: value to put in the list
@L2: position
@L1: list size
@output: a list of zeroes with the specified value in the given position
listRowIdentity
\<<
0 SWAP
NDUPN \->LIST
SWAP ROT PUT
\>>
@tags: [ 'stack processing' ],
@description: '
@ reverse the order of the last 3 stack elements.

@ tags: [ 'list processing' ],
@ description: 'take a list in input and split it in a list of
@   sublists in output where a sublists first element would be
@   the last element of the previous sublists. Sublists of size 3',
@ userrpl : '
@   ,
@ examples: [
@   'Input: {1 2 3 4 5 }
@    Output: {{ 1 2 3} {3 4 5}}',
@ ],
splitList
\<<
3
\<< 3 \->LIST NSUB 2 MOD NOT DROPN \>>
DOSUBS
\>>

@tags: [ 'list processing' ],
@description: '
@  create a list of n equal objects
@input:
@L2: object to replicate
@L1: number of replications
@output
@a list with the replicated object
nreplication2list
\<<
NDUPN \->LIST
\>>

@tags: [ 'list processing' ],
@description:
@  remove all entries of an element in a list.
@  Requires the listExt of DavidM.

@input:
@L2: a list
@L1: an object to match
removeElementFromList
\<<
OVER SWAP MPOS LRMOV
\>>
@output
@L1: the list in input without the entries that matched the object

shufListHelp
"
tags: [ 'list processing', 'randomize list' ],
description:
randomize a list in input

input:
L1: a list to randomize
output:
L1: the randomized list.
"

shufList
\<<
@ explode the list onto stack and save the size (sz)
OBJ\-> \-> sz

\<<
@ loop: for list item positions 1 to (sz-1), choose a
@ random item from the remaining candidates and move it
@ to the target position

@ note: stack positions (sz...1) are numbered inversely to
@ list positions (1...sz)

@ x represents the current target position
sz 2 FOR x

@ pick a random item position from the remaining pool
x RAND * CEIL

@ move the chosen item to stack level 1
ROLL

@ move the chosen item to the current target position
x ROLLD

@ update target to the next position
-1 STEP

@ implode the resulting list data
sz \->LIST
\>>
\>>

@tags: [ 'random integer list' ],
@description:
@  random integer list without duplicates

@input
@L2: max positive integer (from 1)
@L1: number of integers to get
@example:
@L2: 10 (we want the integers between 1 and 10)
@L1: 5 (we want 5 integers)
randIntListNoDUP
\<< \-> t n
\<< 1 t
FOR x x DUP RAND * CEIL ROLLD
NEXT t n - DROPN n \->LIST
\>>
\>>

listRandSeqHelp
"
tags: [ 'list processing', 'create list', 'list sequence', 'random' ],
description:
given a min and max value in input, creates a random list with N elements from the range [min, max] € N.

input:
L3: min value (integer)
L2: max value (integer)
L1: number of elements
output:
list of random integers in the range.
"

listRandSeq
\<<
\->
lvMin
lvMax
lvCount
\<<
1. lvCount
START
lvMax lvMin - @the distance max-min
1 + @a value that we need to offset CEIL later
RAND * CEIL
1 -
@due to ceil, if the size of the range is, say, 4 large,
@one would expect values in (0,1,2,3,4) but with ceil 0 is never happening.
@Thanks to a larger range we have (0,1,2,3,4,5) where 0 is never happening.
@Thus we have (1,2,3,4,5)
@Then we need to shift of one value on the left, obtaining (0,1,2,3,4) as wished
lvMin
+
NEXT
lvCount \->LIST
\>>
\>>

listRandSeqJKHelp
"
tags: [ 'list processing', 'create list', 'list sequence', 'random' ],
description:
given a min and max value in input, creates a random list with N elements from the range [min, max] € N.
It works for approximate and exact mode.

input:
L3: number of elements
L2: min value (integer)
L3: max value (integer)
output:
list of random integers in the range.
"

listRandSeqJK
\<< 3. \->LIST I\->R EVAL OVER - 1. + \-> s b a
\<<
IF -105. FS?
THEN 1. s
START RAND a * b + FLOOR
NEXT
ELSE 1. s
START RAND a * b + FLOOR R\->I
NEXT
END s \->LIST
\>>
\>>

listMaxHelp
"
tags: [ 'list processing', 'max min' ],
description:
find max in a list

input:
L1: a list of numbers
output:
L1: the max value
"

listMax
\<<
\<< MAX \>>
STREAM
\>>

listMinHelp
"
tags: [ 'list processing', 'max min' ],
description:
find min in a list

input:
L1: a list of numbers
output:
L1: the min value
"

listMin
\<<
\<< MIN \>>
STREAM
\>>

lCumSumHelp
"
tags: [ 'list processing', 'cumulative sum' ],
description:
cumulative sum of elements in a list. author: DavidM

input:
L1: a list of numbers
output:
L1: the list with the comulative sum

example(s):
- input: { 1 2 3 4 5}
output: { 1 3 6 10 15 }
"

lCumSum
\<<
1
\<<
NSUB 1 -
{ OVER + }
IFT
\>>
DOSUBS
\>>

listOneConstantHelp
"
tags: [ 'list processing', 'list of zeroes with constant' ],
description:
list of zeroes with constant

input:
L3: constant
L2: position
L1: list size
output:
L1: list of 0 with the constant in position

example(s):
input:
5
3
5
output: { 0 0 5 0 0 }
"

listOneConstant
\<<
0 SWAP
NDUPN →LIST
SWAP ROT PUT
\>>

listIncrDecrElementHelp
"
tags: [ 'list processing', 'list increase decrease element' ],
description:
given a list increments or decrements an element in position.
author: DavidM

input:
L3: list
L2: position
L1: increment / decrement
output:
L1: list with the element in position modified

example(s):
input:
{ 3 3 3 }
2
-5
output: { 3 -2 3 }
"

listIncrDecrElement
\<<
PICK3 PICK3
GET + PUT
\>>

listFrequencyElements
@using ListEXT
\<<
\->
lvInputList

\<<
lvInputList LDDUP @results without duplicates
1
\<<
DUP @duplicate L1
lvInputList SWAP @bring the single element on L1
LCNT @count the value
\->TAG @tag the element with its frequency
\>>
DOSUBS

@output:
@results without duplicates and their frequency in a list
\>>
\>>

ListPickLastHelp
"
url: -
tags: [ 'list processing', 'last element' ],
description:
given a list picks the last element.

input:
a list

output:
the last element
"
ListPickLast
\<<
\>>

listSumSubListHelp
"
url: -
tags: [ 'list processing', 'sum of sublist' ],
description:
given a list picks the last element.

Input: a list with sublists of the same dimension

Output: the sum of the sublists.
"

listSumSubList
\<<
IF
@ if the list is large enough
DUP SIZE 1 >
THEN
STREAM
ELSE
@otherwise the list itself.
END
\>>

LTRANTKHelp
"
tags: [ 'list processing', 'transpose list' ],
description:
given a list of sublists of the same size, transposes its elements.
As if it was a matrix.
Author
Thomas Klemm

Input: a list with sublists of the same dimension

Output: the list with the sublists with elements transposed.

Example(s):
{ { 1 2 3 } { 3 4 5 } } -> { { 1 4 } { 2 4 } { 3 5 } }
"
LTRANTK
\<<
OBJ\->
\->
n
\<<
n
\<<
n \->LIST
\>>
DOLIST
\>>
\>>

LTRANJKhelp
"
tags: [ 'list processing', 'transpose list' ],
description:
given a list of sublists of the same size, transposes its elements.
As if it was a matrix.
Requires:
ListExt . See in this file the links.
Author
John Keith

Input: a list with sublists of the same dimension

Output: the list with the sublists with elements transposed.

Example(s):
{{ 1 2 3 }{4 5 6 }{ 7 8 9 }} -> {{ 1 4 7 }{ 2 5 8 }{ 3 6 9 }}
"

LTRANJK
\<<
DUP LXIL SWAP SIZE LDIST
\>>

L2OVERLAPSUBHelp
"
tags: [ 'list processing', 'list overlapping sublists' ],
description:
given a list it creates a list of sublists with each sublists having the first and
last element in common with adjacent sulists.
Author
John Keith

Input:
L2: a list
L1: a number to decide the size of the sublists.

Output: a list of sublists with each sublists having the first and
last element in common with adjacent sulists.

Example(s):
{ 1 2 3 4 5 } 2 -> {{ 1 2 }{ 2 3 }{ 3 4 }{ 4 5 }}
"

L2OVERLAPSUB
\<<
\-> n
\<< n
\<< n \->LIST
\>> DOSUBS
\>>
\>>

LPercentileTKHelp
"
tags: [ 'list', 'percentile', 'quartile', 'median' ],
description:
Modified by Thomas Klemm based on a program in the 48 (or 50g) advanced user reference.

Input:
L2: inputList
L1: percentile (integer 0 to 100)
Output
L3: the percentile

Example(s):
{ 6 7 15 36 39 40 41 42 43 47 49 }
25: 25.5
50: 40
75: 42.5
"

LPercentileTK
\<<
SWAP SORT DUP SIZE 1 - ROT % 1 +
\-> p
\<<
DUP p FLOOR GET SWAP p CEIL GET + 2 /
\>>
\>>

LREPLPOS2021Help
"
url: '',
tags: [ 'list', 'replace element' ],
description:
When one has a list of replacements for original list
remarks:
Not much input checks at first, example: giving positions that they don't exists

Input:
L3: originalList
L2: list of position to replace
L1: elements to insert (length should be identical to the list of positions to replace)
Output
L1: the original list with the elements replaced

Example(s):
{ 9 8 7 6 5 4 3 2 1 } { 7 8 } { 11 22 } -> { 9 8 7 6 5 4 11 22 1 }
"

LREPLPOS2021
@ LREPL from ListExtworks works with matching the elements to replace, if one wants to replace
@ with positions one need another routine
\<<
\->
@input
lvOriginList
lvPositionList
lvReplacementsList
@variables
\<<
1 lvPositionList SIZE
FOR lvInd
lvOriginList
lvPositionList lvInd GET @the postion
lvReplacementsList lvInd GET @the replacement
PUT 'lvOriginList' STO @replaced
NEXT
lvOriginList @result
\>>
\>>

LREPLPOS3298Help
"
tags: [ 'list', 'replace element' ],
description:
When one has a list of replacements for original list
remarks:
Not much input checks at first, example: giving positions that they don't exists

Input:
L3: originalList
L2: list of position to replace
L1: elements to insert (length should be identical to the list of positions to replace)
Output
L1: the original list with the elements replaced

Example(s):
{ 9 8 7 6 5 4 3 2 1 } { 7 8 } { 11 22 } -> { 9 8 7 6 5 4 11 22 1 }
"

LREPLPOS3298
\<< 2. \<< PUT \>> DOLIST \>>

@##################################
@#
@# Stack operations

@that is from L3 L2 L1
@one obtains L1 L2 L3
rev3stack
\<<
SWAP ROT
\>>

@info snippet
@tags: [ 'stack processing', 'rule of thumb' ],
@description:
infoSingleArgStackOp
"
stack operations that take a numeric argument (DUPN, ROLL, PICK, etc.)
take about 7 times as long to execute as simple operations
(SWAP, DUP, ROT, etc.)
"

@##################################
@#
@# user input operations

@tags: [ 'input forms', 'inform' ],
@description: '
@  There are alternatives to good old INFORM or INPUT,
@such as INLIST, INMENU, and INPROMPT
@
@INLIST is an INFORM replacement, having all these same features:
@
@o Editing (including a CALC mode for stack calculations)
@o Optional "reset values"
@o Optional object type restriction
@
@
@But INLIST is not limited
@to what can be crammed into one small form,
@because its "form" is open-ended and *scrolls* vertically.
@
@The INLIST arguments are similar to INFORM:
@
@
@"Title" { prompts } { initial values }
@-OR-
@"Title" { prompts } { reset values } { initial values }
@
@
@Note: Lists other than "prompts"
@may be empty or shorter than the "prompts" list.
@
@Each "prompt" in the list of prompts is:
@
@o "Any string" (or any word)
@-OR-
@o A list: { "Prompt" type1 type2 .. } for object type restriction
@
@How to enter data using INLIST:
@Highlight any item; press OK or ENTER to edit.
@
@Individual value "reset" is invoked
@by a blank edit area (press ON once if not yet blank).
@
@Individual value CALC mode is invoked
@by typing only an "equal" command [=3D] into the edit area
@(left-shifted zero on 48G, right-shifted W on 49G/50G);
@return from CALC mode via CONT (left-shifted ON).
@
@
@Also use CALC mode to see the list of valid object TYPES.
@
@"Reset All" is invoked
@by an item at the very end of the form.
@
@
@"<DONE>" provides the normal exit from INLIST;
@ON or "Cancel" (from the form level) aborts.
@
@
@Level | Stack at normal exit:  |    Stack after abort:
@2:      { final values }       |
@1:      1.                     |    0.
@
@
@The use of a full-screen CHOOSE program can improve INLIST,
@by displaying a full line for each item,
@and by using the full height of the screen.
@
@
@Full-screen CHOOSE for any HP48G/49G/50G series calculator:
@ource
@www.hpcalc.org/details.php?id=3D6431 (ROLDXJ, contains binaries)
@
@
@A program INFORML is also provided below,
@which accepts the exact same five arguments as INFORM,
@but calls INLIST instead, so that you may merely
@change INFORM to INFORML in your existing programs that use INFORM.
@
@
@A program INLISTF is also provided below,
@which accepts the fewer arguments needed by INLIST,
@but calls INFORM instead, so that you may merely
@change INLIST to INLISTF in existing programs that use INLIST.
@
@
@If you require all form fields to be filled in,
@to avoid any skipped fields returning NOVAL as their value,
@programs INLISTN and INFORMN are also provided,
@which accept the identical arguments, but automatically
@repeat INLIST or INFORM until the results are free of any NOVAL.

@ Sample program for INPROMPT:
tinp
\<< "Enter X" INPROMPT "X" \->TAG
"Enter Y" INPROMPT "Y" \->TAG
\>>

@ INPROMPT (all HP48/49/50)
INPROMPT
\<< 10. CHR + "then press menu key" + @ optional hint
{ { "OK"  \<< 0. MENU CONT \>> }
{ "(AN(L" \<< 0. MENU KILL \>> } }
\>>

@ ---

tinm
X "X" \->TAG  Y "Y" \->TAG
'X+Y' EVAL "X+Y" \->TAG
'X*Y' EVAL "X*Y" \->TAG
\>>

@ Args: "Title" { labels }      Nothing returned on stack.
@ "One touch" to store, DONE returns, LeftShift DONE aborts,
@ RightShift recalls, RightShift CursorDown reviews values.
@ "Real" numbers stored into "unit" objects preserve the units!
\<< { @ the next line is an optional tweak for up to 5 variables
{ "SHOW"  \<< #A300Eh RCLF SIZE 3. < 2. * + LIBEVAL \>> }
{ "DONE" { \<< 0. MENU CONT \>> \<< 0. MENU KILL \>> } } } +
TMENU RCLF SIZE 3. > #25EFFh #151A6h IFTE SYSEVAL PROMPT
\>>
@ Caution: First back up memory! Incorrect SYSEVALs are harmful!
@ Also note the difference between LIBEVAL and SYSEVAL

@ ---

@ Test program for INLIST[N]:
tinl
\<< "Test INLIST"
{ { "Set VX to" 6. } { "Any Number" 0. 28. } "Required field" }
{ X 123 } DUP INLIST
\>> @ or INLISTN to avoid NOVAL
@ Note that INFORM would throw an error on type code 28

@ Complete INLIST (in UserRPL) for HP48G/49G/50G
INLIST
\<< 3. PICK TYPE 2. == { { } SWAP } IFT @ Omitted resets?
3. PICK 1. \<< DROP NOVAL \>> DOSUBS @ Pad values lists
1. DUP2 6. ROLL REPL 4. ROLLD ROT REPL @ To match prompts
0. RCLF { GET DUP TYPE 2. == { 34. CHR SWAP OVER + + }
IFT DUP NOVAL SAME { DROP "" } IFT \->STR } RCLMENU \-> h.
p. b. a. n. f. c. m. \<< -55. SF 64. STWS STD DO IF h. p.
@ Build a new CHOOSE list (showing current values):
1. \<< { } + 1. GET "=" + a. NSUB c. EVAL + NSUB 2. \->LIST
\>> DOSUBS { "<DONE>" "[Reset All]" } + 'n.' INCR
@ Exit or "reset all" if either was selected:
CHOOSE THEN DUP 'n.' STO IF TYPE THEN IF n. " " POS THEN
b. 'a.' STO 0. DUP 'n.' STO ELSE a. 1. 1. END ELSE
@ Get the prompt and current value for INPUT (editor):
p. n. GET { } + 1. GET \->STR a. n. c. EVAL 28. MENU
IFERR INPUT "{" SWAP + STR\-> DUP SIZE 1. > { DROP 7. DOERR }
@ Reset if null input, halt for CALC if "equal" command:
IFT LIST\-> NOT { b. n. GET } IFT { = } OVER POS { DROP
DEPTH \->LIST a. n. GET RCLF \-> s. v. g. \<< p. n. GET
{ } + TAIL DUP SIZE NOT { { ALL } + } IFT "Types" \->TAG
f. STOF v. HALT g. STOF DEPTH NOT { v. } IFT DEPTH ROLLD
DEPTH 1. - DROPN s. LIST\-> DROP DEPTH ROLL \>> } IFT
@ Object type restrictions:
DUP NOVAL SAME NOT { p. n. GET { } + TAIL DUP SIZE
{ 0. ADD OVER TYPE POS NOT { DROP 7. DOERR } IFT }
{ DROP } IFTE } IFT @ Okay @ 'a.' n. ROT PUT THEN
ERRN B\->R { "Invalid object or type" MSGBOX } IFT
'n.' DECR DROP END m. TMENU 0. END
ELSE 0. 1. END UNTIL END f. STOF \>>
\>>

@ Auxiliary programs:

@ Loop on INLIST until no undefined value (NOVAL) in results
@ [takes the same args as INLIST]
INLISTN
\<< 3. PICK TYPE 2. == { { } SWAP } IFT 4. ROLLD \->
t. p. b. \<< 1. DO DROP t. p. b. 4. ROLL INLIST DUP DUP
{ DROP OVER NOVAL POS } IFT UNTIL NOT END \>>
\>>

@ Loop on INFORM until no undefined value (NOVAL) in results
@ [takes the same args as INFORM]
INFORMN
\<< 5. ROLLD \-> t. p. f. b. \<< 1. DO DROP t. p. f. b.
5. ROLL INFORM DUP DUP { DROP OVER NOVAL POS } IFT
UNTIL NOT END \>>
\>>

@ This takes args for INFORM, but calls INLIST instead
INFORML
\<< ROT DROP ROT 1. \<< { } + DUP SIZE { DUP HEAD SWAP TAIL TAIL
+ } { DROP } IFTE \>> DOSUBS ROT ROT INLIST
\>>

@ This takes args for INLIST, but calls INFORM instead
INLISTF
\<< 3. PICK TYPE 2. == { { } SWAP } IFT ROT 1. \<< { } +
DUP HEAD "" + { "" } + SWAP TAIL + \>> DOSUBS DUP SIZE
DUP 4. MIN / CEIL 4. ROLL 4. ROLL INFORM
\>>

@#############################################################################
@#
@#
@#
@ some expanding data structures speed test
@ as expanding lists is costly

gpListExp
\<< @on an emu48 emulator on a pentium M 1.73ghz , 741 seconds. Woah.
\<< @always expand a list
{}
1 1000
FOR lvK
lvK +
NEXT
\>>
TEVAL
"listExp"
\>>

gpListRepl
\<< @on an emu48 emulator on a pentium M 1.73ghz , 917 seconds. Woah.
\<< @preallocate list and replace elements
0 1000 NDUPN \->LIST
1 1000
FOR lvK
lvK lvK PUT
NEXT
\>>
TEVAL
"listRepl"
\>>

gpVectRepl
\<< @on an emu48 emulator on a pentium M 1.73ghz , 11.43 seconds. that's fast
\<< @preallocate list and replace elements
0 1000 NDUPN \->ARRY
1 1000
FOR lvK
lvK lvK PUT
NEXT
\>>
TEVAL
"vectRepl"
\>>

@##################################
@#

"
- For programs that are not yet ported in this library (including some testing)
at least links to the source may help, as long as the link is valid
and the source is reachable (that, as experience shows, is better not to take
for granted on internet)

- when expanding large lists (over 100 elements) the execution become stuck in the mud.
How is it with arrays? (although arrays are less expressive than lists)
How is it with pre allocated large lists where elements gets replaced from their
dummy value and how it is with pre allocated attays?

Is there some gain in speed?

- arguments check

- An example of thousands separator

- displaying long text in a 'page'

- quicksort
ftp://www.hpmuseum.org/lif/swap/swap10/hp28v6n7.txt

- mirror bits

- digits not in a number

- add also a list to a list, without exploding the added list

- list processing and commands missing from goferlist / listExt and discussion about
list / vector data structures

how many divisors of X. sum of divisors. Sum of proper divisors.
Product of all the divisors.

- improving the angle between vectors

- program to convert ascii text in usrpl for SD card programs and emulators
also on the emu48 official page.
(can be that there are other alternatives around, would be nice to at least list them)
workaround: using com0com for the emulator and conn4x as the virtual calculator
would be a real one.

- create a so called 'anti identity matrix'

doneTodos
(list min, list max)

- need is the main source of motivation to expand one's set of available solutions.
Too long it took to include percentile functions.
"

"
- in general the various online discussion places (see http://www.wiki4hp.com/doku.php?id=resources:start) are full of
math and  programming challenges that are hard to be found, though. So collecting them in a list
(thing that is missing since years) wouldn't be bad.

- How many integers (from 1 to 9999) are evenly divisible by the number of letters in their name?
END