Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

from string to list

57 views
Skip to first unread message

val

unread,
Apr 12, 2011, 9:14:42 AM4/12/11
to
Hello all,

I'm trying to switch from a string to a list of the corresponding ASCII
codes with a prog called 'EXPL' :
"ABC" -EXPL-> { 65 66 67 }

and the reverse process with 'IMPL' :
{ 65 66 67 } -IMPL-> "ABC"

The IMPL prog is straightforward : << CHR SUMLIST >>

But for the reverse program I couldn't find a short way to do it with
NUM.

Is there a way to do it without using a FOR loop ?

Thanks for reading.


tomcee

unread,
Apr 12, 2011, 12:19:19 PM4/12/11
to

I was not able to do it without a FOR loop, but the
RPL code is only 117 bytes.

I had just done this in inspecting character strings
being sent to the 82240x printers.

TomC

George Litauszky

unread,
Apr 12, 2011, 1:17:58 PM4/12/11
to
Hello,

Is a library on the hpcalc.org for this problem.
http://www.hpcalc.org/details.php?id=5892

The needed command is:
"
7.13.2 LCHARS
String to List of Characters: Given a string as input, this function returns a list containing each character as a separate item. In order to reverse this, simply use the built-in ΣLIST function.
"

George

tomcee

unread,
Apr 12, 2011, 2:35:47 PM4/12/11
to
> TomC- Hide quoted text -
>
> - Show quoted text -

In case you're interested, here's the code.

With the string (eg "ABCDE") on the stack, executing this code
returns a list of numbers representing the string; leaving the string
just above this list

<< DUP { } -> S L
<< S SIZE 1 SWAP
FOR I
S I I SUB NUM L SWAP +
'L' STO
NEXT
L
>>
>>

Note that L is a local variable in this code. When the input string
gets quite 'long'
(more that 40 characters, the code slows down quite a bit.

TomC

Jimmy John

unread,
Apr 12, 2011, 4:35:37 PM4/12/11
to
In article
<251ad50f-fad7-41d4...@d2g2000yqn.googlegroups.com>,
tomcee <tomcees_c...@yahoo.com> wrote:

Alternately, something like:

\<< DUP { }
WHILE OVER SIZE
REPEAT
OVER NUM + SWAP TAIL SWAP
END
NIP
\>>

val

unread,
Apr 13, 2011, 7:49:30 AM4/13/11
to

I have also something like this, too :

EXPL:
<<
{ }
SWAP DUP SIZE
1 SWAP
FOR
z DUP HEAD SWAP
TAIL ROT ROT + SWAP
NEXT
DROP NUM
>>

But yours is better, shorter and without local variable.

Thank you all for your input.


tomcee

unread,
Apr 13, 2011, 9:31:16 AM4/13/11
to
On Apr 12, 4:35 pm, Jimmy John <Ji...@john.sci> wrote:
> In article
> <251ad50f-fad7-41d4-aac3-7200207b4...@d2g2000yqn.googlegroups.com>,
>    \>>- Hide quoted text -

>
> - Show quoted text -

Very nice!!!
(what is NIP?)
TomC

val

unread,
Apr 13, 2011, 10:13:21 AM4/13/11
to
tomcee a écrit le 13/04/2011 :
>
> Very nice!!!
> (what is NIP?)
> TomC

Looks like a SWAP DROP twice.
val


woddo

unread,
Apr 13, 2011, 2:19:46 PM4/13/11
to

Without using a FOR, WHILE or DO loop

<< DUP SIZE << DUP HEAD SWAP TAIL >> 'LLLL'
1 4 ROLL 1 - 1 SEQ + NUM >>

strictly speaking it does use an internal loop in UserRPL

Nemo

unread,
Apr 13, 2011, 3:51:13 PM4/13/11
to
Hi ! Here is a way to do 'EXPL' :

<< DUP SIZE NDUPN ->LIST 1 << NSUB DUP SUB >> DOSUBS NUM >>

Gilles

Nemo

unread,
Apr 17, 2011, 11:49:44 AM4/17/11
to
Differents ways to do and Benchmark :

@------------------------
«
{ } -> S L
« S SIZE 1. SWAP


FOR I
S I I SUB NUM L SWAP +
'L' STO
NEXT
L

»
»
'Exp1' STO

@------------------------
«


{ }
WHILE OVER SIZE
REPEAT
OVER NUM + SWAP TAIL SWAP
END
NIP

»
'Exp2' STO

@------------------------
«


{ }
SWAP DUP SIZE
1 SWAP
FOR
z DUP HEAD SWAP
TAIL ROT ROT + SWAP
NEXT
DROP NUM

»
'Exp3' STO

@------------------------
«
DUP SIZE « DUP HEAD SWAP TAIL » 'n'


1 4 ROLL 1 - 1 SEQ + NUM

»
'Exp4' STO

@------------------------
«


DUP SIZE NDUPN ->LIST
1 « NSUB DUP SUB » DOSUBS
NUM

»
'Exp5' STO

@------------------------
«
DUP SIZE
-> s
«
WHILE DUP SIZE
REPEAT
DUP NUM SWAP TAIL
END
DROP s ->LIST
»
»
'Exp6' STO

@------------------------
«
DUP SIZE
1 SWAP FOR n
DUP n DUP SUB SWAP
NEXT
SIZE ->LIST NUM
»
'Exp7' STO

@------------------------
«
-> p
«
p DUP BYTES SWAP DROP 1_Bytes ->UNIT
Txt
MEM DROP
TICKS B->R
-> t
«
p EVAL
TICKS B->R t - 8192. / 2 RND 1_s ->UNIT
SWAP DROP
3 ->LIST
»
»
»
'Bench' STO
@------------------------

100 MAKESTR 'Txt' STO
{'Exp1' 'Exp2' 'Exp3' 'Exp4' 'Exp5' 'Exp6' 'Exp7'} 'Bench' DOLIST

@------------------------ with a 100 chars string :
@{
@ { Exp1 '106_Bytes' '2.44_s' }
@ { Exp2 '61.5_Bytes' '2.32_s' }
@ { Exp3 '76.5_Bytes' '2.81_s' }
@ { Exp4 '87_Bytes' '1.59_s' }
@ { Exp5 '62_Bytes' '1.22_s'}
@ { Exp6 '75.5_Bytes' '.61_s' }
@ { Exp7 '60_Bytes' '.73_s' }
@}

500 MAKESTR 'Txt' STO
{'Exp1' 'Exp2' 'Exp3' 'Exp4' 'Exp5' 'Exp6' 'Exp7'} 'Bench' DOLIST

@----Exp5 not enough mem-----------------with a 500 chars string :
@{
@ { Exp1 '106_Bytes' '73.97_s' }
@ { Exp2 '61.5_Bytes' '80.81_s' }
@ { Exp3 '76.5_Bytes' '63.96_s' }
@ { Exp4 '87_Bytes' '8.06_s' }
@ { Exp6 '75.5_Bytes' '3.66_s' }
@ { Exp7 '60_Bytes' '5.13_s' }
@}

tomcee

unread,
Apr 17, 2011, 1:26:33 PM4/17/11
to

Very interesting analysis. I'll have to test these out!
I've also been curious about differences between the value returned of
different 'Bench'/'Timing' codes.
Regards,
TomC

Nemo

unread,
Apr 17, 2011, 5:34:33 PM4/17/11
to
On Apr 17, 7:26 pm, tomcee <tomcees_calcula...@yahoo.com> wrote:
>
> Very interesting analysis.  I'll have to test these out!
> I've also been curious about differences between the value returned of
> different 'Bench'/'Timing' codes.

Hi,

You mean the output values ? Of course they all are the same.

About speed, you can test this :

«
1. 300. FOR n
n
NEXT
300 ->LIST
»
'V1' STO

«
{}
1. 300. FOR n
n +
NEXT
»
'V2' STO

V1 and V2 does the same thing but V1 is _much_ faster !

Nemo

unread,
Apr 18, 2011, 3:39:44 PM4/18/11
to
«
DUP SIZE DUP
-> s
«
1 SWAP START
DUP NUM SWAP TAIL
NEXT
DROP s ->LIST
»
»
'Exp8' STO

The fastest way i find in User RPL. It tooks 2.8 seconds for a 500
chars string

Virgil

unread,
Apr 18, 2011, 5:39:34 PM4/18/11
to

Nemo

unread,
Apr 18, 2011, 6:36:01 PM4/18/11
to
On Apr 18, 11:39 pm, Virgil <vir...@ligriv.com> wrote:
> In article
> <4da20133-74b0-4d95-80ec-f85d44905...@gu8g2000vbb.googlegroups.com>,
>
>  Nemo <carpentier.gil...@free.fr> wrote
> (...)
>
> Nice!
> --

The latest version and i stop here ;) Same speed but more simple
«
DUP SIZE
-> s
«
1 s START


DUP NUM SWAP TAIL
NEXT
DROP s ->LIST
»
»

Too bad that 'GET' and 'GETI' don't work with strings

Virgil

unread,
Apr 18, 2011, 10:09:02 PM4/18/11
to
In article
<bf4fac68-0eb5-44e5...@x10g2000vbn.googlegroups.com>,
Nemo <carpenti...@free.fr> wrote:

I have usually found that 'GET' and 'GETI' they tend to be somewhat
slower than other methods with both arrays and lists.
--


Jacob Wall

unread,
Apr 19, 2011, 12:17:55 AM4/19/11
to
Out of curiosity I wrote the following System RPL program:

::
DUPLEN$
DUP1LAMBIND
ZERO_DO
DUP
CAR$
CHR>#
UNCOERCE
SWAP
CDR$
LOOP
DROP
1GETABND
{}N
;

It's approx ~0.7s with 500 characters, and 46 bytes. No argument checks
or anything, however to add that hardly increases run-time, just code
length. I imagine a HPGCC program would be nearly instantaneous...

Andreas Möller

unread,
Apr 19, 2011, 1:39:14 AM4/19/11
to
Hello,

> I imagine a HPGCC program would be nearly instantaneous...

Yes, but that won't make you a better coder ;-)

There is still room for improving your System RPL program.
Hints:
- avoid LAMs, use the stack
- a BEGIN/UNTIL Loop or BEGIN/AGAIN Loop is usually faster because
they have no overhead
- try to avoid memory shifts wherever possible
- move to Saturn ML, of course fastest would be ARM ML on these
machines :-)

Regards,
Andreas
http://www.software49g.gmxhome.de

Message has been deleted

Nemo

unread,
Apr 19, 2011, 5:02:49 AM4/19/11
to
On Apr 19, 6:17 am, Jacob Wall <jac...@surv50.ca> wrote:
> Out of curiosity I wrote the following System RPL program:
>

> It's approx ~0.7s with 500 characters, and 46 bytes.  No argument checks


> or anything, however to add that hardly increases run-time, just code
> length.  I imagine a HPGCC program would be nearly instantaneous...
>

Hi,

But with what size ? I dont think that HGCC is a good way for this (I
mean for UserRPL extension and interactive usage), but perhaps i'm
wrong. If speed is critical, Saturn ML or ARM are probably best
choices. I'm curious about usable Saturn or ARM codes. I never really
used them, just learn some basics of saturn when i played with HP/
Pascal. I don't know if it's easy to "read" the stack and generate a
list of elements on the stack in Saturn or ARM code. If so, the
algorithm is very simple.

Nemo

unread,
Apr 19, 2011, 5:05:44 AM4/19/11
to
On Apr 19, 6:17 am, Jacob Wall <jac...@surv50.ca> wrote:
> Out of curiosity I wrote the following System RPL program:
>

> ;


>
> It's approx ~0.7s with 500 characters, and 46 bytes.  No argument checks
> or anything, however to add that hardly increases run-time, just code
> length.  I imagine a HPGCC program would be nearly instantaneous...

Hi,

But with what size ? I dont think that HGCC is a good way for this (I
mean for UserRPL extension and interactive usage), but perhaps i'm
wrong. If speed is critical, Saturn ML or ARM are probably best

choices. I'm curious about a usable Saturn ML or ARM codes . I never
really used them, just learn some basics of saturn when i play with HP/
Pascal. I don't know if it is easy to "read" the stack and generate a

oliverue

unread,
Apr 19, 2011, 7:09:57 PM4/19/11
to
Here's the same in RPL+
« =s
{} =list
1 s SIZE FOR i
s[i] NUM =list[i]
NEXT
list
»
This runs in 0.14s on ND1.

The baseline, Gilles' nice version
«
DUP SIZE
-> s
«
1 s START


DUP NUM SWAP TAIL
NEXT
DROP s ->LIST
»
»

takes 0.29s.

There's a new MorphEngine "split" command, which permits this version
« split « NUM » MAP »
which takes 0.13s.

I needed 'split' for GolfScript, which has a built-in operator ('*')
that executes this function combined with instruction block ('{...}')
processing of the char codes (a "fold" op, just like STREAM).
An empty instruction block will just dump all char codes to the stack.
So, with the three character GS program
{}*
stored in a variable 'str2stack', one can write
« =:s str2stack s SIZE ->LIST »
and that completes in 0.04s.
This is a RPL+ program that calls on a GolfScript function.

The highest speed is obtained with
function(x) {
return calculator.unquote(x).split("").map(function(x) { return
x.charCodeAt(0); });
}
which completes in 0.004s. (0.25s for a 100,000 char string I had
lying around ;-))

Jacob Wall

unread,
Apr 20, 2011, 12:00:47 AM4/20/11
to
I was trying to take a example provided in User RPL and almost directly
translate it to System RPL to illustrate a fairly straight-forward
comparison of speed between the two.

The program I posted is very similar to the User RPL versions EXP6 and
EXP7 posted, except it's System RPL.

I'm sure that you could write a much quicker program to do the same in
Saturn ML, but I haven't seen any other System RPL program that is
faster than ~0.7s ;)

I agree with the points made that HPGCC doesn't make sense for this
application, but then again I would definitely be curious to see the
numbers anyways, just because.

Also, just because, a Saturn ML program comparison would be of interest
as well. Didn't mean to hijack the original topic, but since benchmarks
were introduced I felt that it wouldn't hurt to at least throw one
orange into the basket of apples.

Jacob

Raymond Del Tondo

unread,
Apr 20, 2011, 1:49:02 AM4/20/11
to
To throw another orange in:
A few years ago I made a Saturn ML program which is more than
ten times faster than the compiled C solution on the same HP-48;-)

Ray


"Jacob Wall" <jac...@surv50.ca> schrieb im Newsbeitrag news:STsrp.21609$7N3....@newsfe10.iad...

oliverue

unread,
Apr 20, 2011, 4:59:28 AM4/20/11
to
And to throw in another avocado:

I bet if a pre-processor would translate the two instructions
s[i]
and
=list[i]
to equivalent SYSEVAL calls, a substantial speed gain would be
obtained with the RPL+ version, which then could be run on a 48, 49,
50g.

FWIW.

Dave Hayden

unread,
Apr 20, 2011, 6:50:19 AM4/20/11
to
On Apr 19, 5:02 am, Nemo <carpentier.gil...@free.fr> wrote:
> On Apr 19, 6:17 am, Jacob Wall <jac...@surv50.ca> wrote:
> > I imagine a HPGCC program would be nearly instantaneous...
>
> Hi,
>
> But with what size ? I dont think that HGCC is a good way for this

A good rule of thumb is that HPGCC programs are about
100 times larger and about 100 times faster than UserRPL.
The size problem is actually easy to avoid: just store the
program on an SD card and replace it in calculator memory
with a short program that runs it. For example, a program
called TIMER stored in /EXTEND/TIMER becomes
<< 3: "EXTEND/TIMER" EVAL >>.

This adds about 0.2s to the runtime so it certainly isn't
ideal, but it helps.

Dave


oliverue

unread,
Apr 20, 2011, 11:58:18 AM4/20/11
to
For your amusement:

The entire GolfScript for the string-to-list task at hand is: {}*]

Is that believable? (I'm new to the language myself and currently in
the "easily amazed" stage.) Note, that this is not leveraging a built-
in function for this task per se, but rather abducting a (more general/
powerful) operator.

Dave Hayden

unread,
Apr 20, 2011, 9:27:49 PM4/20/11
to
Here is an implementation in HPGCC:

#include <hpgcc49.h>
#include "hpobjects.h"

int main (int argc, char **argv)
{
unsigned rpl_stack_bias = sat_stack_init();
SatAddr str; /* the string in Saturn land */
SatAddr *reals; /* array of saturn reals */
char *cp; /* the string in C land */
int len; /* length of the string */
int i;
if ((str = STACKpop()) && isSTRING(str)) {
cp = STRINGdecode(str, NULL);
len = strlen(cp);
reals = calloc(len, sizeof(SatAddr));
for (i=0; cp[i]; ++i) {
reals[i] = REALencode(cp[i], 0);
}
STACKpush(LISTencodeN(len, reals, 0));
}
sat_stack_exit(rpl_stack_bias);
return 0;
}

14,438 bytes.

String size Run time
100 0.0581s
500 0.1321s

To be honest, I'm surprised at how slow this is.

Dave

oliverue

unread,
Apr 21, 2011, 5:45:10 AM4/21/11
to
Dave,

>         for (i=0; cp[i]; ++i) {
>             reals[i] = REALencode(cp[i], 0);
>         }

> ...


> To be honest, I'm surprised at how slow this is.

I'm guessing as long as there's integration-related code (in this
case, type conversion) in an inner loop, you won't get "true" native
speed. Surely, REALencode() is far more expensive than cp[i].

oliverue

unread,
Apr 21, 2011, 5:52:07 AM4/21/11
to
Suggestion. Changing this

>         for (i=0; cp[i]; ++i) {
to
> for (i=0; i<len; ++i) {
should run a little faster, too (as the compiler can hold 'len' in a
register, whereas cp[i] needs an address look-up), though, it won't do
much, if REALencode() gobbles up 90% of the speed.

Dave Hayden

unread,
Apr 22, 2011, 6:33:34 AM4/22/11
to

Yes, I think it's the REALencode() that does it. The compiler
converts
the character cp[i] to a double, then REALencode() converts the double
to
a calculator REAL object.

Thanks,
Dave

val

unread,
Apr 28, 2011, 9:43:33 AM4/28/11
to
Nemo a exposé le 19/04/2011 :

I made an asm routine (JAZZ style) and the result is that it takes
about ~0.7 s for a 500 byte string to be converted to a list of real
(HP48GX).
The rate limiting step is the conversion from hexa to real as it
requires to encode in BCD and adjusting position depending on the
number of digits of the result.

But there is a bug. String with 100 bytes are well converted but large
strings of 500 bytes are not. The Reals in the list have an offset of
256 (ie "1" will be converted to 306d instead of the correct 50d). The
bug starts to show for size between 200 and 300 bytes (256?). This is
one of my first attempt in ML so there is obviously room for
improvement :)

The prog is as follow : the D1 pointer scans the input string byte
after byte, and converts to a real (the sbr HEXA2BCD) and the output
list is constructed using D0 on the fly. At the end the list is pushed
to the stack.

%%HP: T(1)A(D)F(.);
CODE
* PROG EXPL
*
* INPUT 1 STR
* OUTPUT 1 LIST
*
* "STRN"->{R0 R1..Rn}
* Ri=REAL=NUM(CHARi)
*
* VAR AND POINTERS:
* D1 POINTS TO
* INPUT STR
* D0 WILL POINT
* TO LIST
* D1 SAVED TO R2
* NB BYTE OF STR
* SAVED TO R1
* LIST ADR IN R0
*
* SAVE REGS
GOSBVL #0679B
*
* CHECK IF STRING
* IN LEVEL 1
A=0 W
A=DAT1 A
D1=A
A=DAT1 A
LC(5) #02A2C
?A=C A
GOYES +
GOSBVL #067D2
GOLONG QUIT
*
* SIZE CALC SZ
* =Nb BYTE OF STR
+ D1=D1+ 5
A=DAT1 A
D1=D1+ 5
C=D1
R2=C A
A=A-CON A,5
ASRB
* SAVE SIZE
R1=A.F A
* RES. MEMORY
* =21*SZ+10
* FOR LIST OBJ
ASL A
C=A W
ASRB
ASRB
C=C+A A
ASRB
ASRB
C=C+A A
*= MULT BY 21d + 10d
C=C+CON A,5
C=C+CON A,5
* MEMORY RESERVATION
GOSBVL #039BE
CD0EX
R0=C A
D0=C
* LIST PROLOGUE
LC(5) #02A74
DAT0=C A
D0=D0+ 5
* ADD 1 REAL :
ONEMOREREAL
* REAL PROLOGUE
LC(5) #02933
DAT0=C A
D0=D0+ 5
C=0 W
*
* NBR TO CONVERT
C=R2 A
D1=C
A=DAT1 B
D1=D1+ 2
C=D1
R2=C A
*
* CONVERSION OF A
* TO BCD
GOSUB HEXA2BCD
* EXPO IN D.X
C=D X
DAT0=C X
D0=D0+ 3
* MANTISSA IN A.W
C=A W
* ADDITIONAL SHIFTS
* (1ST NUM OF MANTISSA
* MUST BE IN POS 12
* ie 1 AND 2 DIGIT
* NUMBERS MUST MOVE)
D=D-1 X
D=D-1 X
D=-D X
- ?D=0 X
GOYES +
CSL W
D=D-1 X
GOTO -
* WRITES TO LIST
+ DAT0=C W
D0=D0+ 12
* SIGN=0
LC(1) #0
DAT0=C 1
D0=D0+ 1
* ONE MORE REAL?
A=R1.F A
A=A-1 A
R1=A.F A
?A#0 A
GOYES ONEMOREREAL
* LIST EPILOG
LC(5) #0312B
DAT0=C A
* RESTORE REGS
GOSBVL #067D2
* PUSH TO STACK
D=D-1 A
D1=D1- 5
C=R0 A
DAT1=C A
* RPL LOOP :
QUIT
A=DAT0 A
D0=D0+ 5
PC=(A)
* SBRS
* HEXA TO BCD
* CONVERSION
* INP=A.B
* OUT=A.X 3*BCD
* D.X 3 DIGIT BCD
* A=MANTISSA D=EXPONENT
HEXA2BCD
*SET MANTISSA
D=0 A
* SUB 100d
LC(3) #064
- A=A-C X
?ABIT=1 11
GOYES +
D=D+1 X
GOTO -
+ DSL X
A=A+C X
* SUB 10d
LC(3) #00A
- A=A-C X
?ABIT=1 11
GOYES +
D=D+1 X
GOTO -
+ DSL X
A=A+C X
C=D X
A=C+A X
GOSUB SETEXP
ASL W
ASL W
ASL W
ASL W
ASL W
ASL W
ASL W
ASL W
ASL W
RTN
*SET EXPONENT
* IN BASE 10
SETEXP
D=0 X
?A=0 X
RTNYES
D=D+1 X
D=D+1 X
* NOW IN BCD
LC(3) #100
?A>=C X
RTNYES
D=D-1 X
LC(3) #010
?A>=C X
RTNYES
D=0 X
RTN
ENDCODE


val

unread,
Apr 30, 2011, 9:11:22 AM4/30/11
to
val a présenté l'énoncé suivant :

> *
> * NBR TO CONVERT
> C=R2 A
> D1=C
A=0 X <-- was missing here
> A=DAT1 B <-- 2 bytes field doesn't mix well with 3 bytes !

> D1=D1+ 2
> C=D1
> R2=C A
> *

Bug fixed. Runs a 2k string in a little less than 2 sec on GX.


0 new messages