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

Integer to Character conversion

17 views
Skip to first unread message

Bob Felts

unread,
Jan 27, 2007, 4:08:36 PM1/27/07
to
Many months ago a co-worker and I were having a contest to see whose
programming language was bigger^H^H^H^H^H^H better. Someone had an
e-mail sig of binary numbers, e.g.:

01000001 01110101 01110100 00100000 01110110 ...

The task was to convert this to ASCII to see what it said. He chose C
while I used Lisp. My solution was:

(defun dcb-to-ascii (dcb)
"Convert a list of decimal-coded-binary to ASCII"
(map 'string 'character
(mapcar #'(lambda (n) (parse-integer (write-to-string n) :radix
2)) dcb)))

This worked on my PowerBook using OpenMCL and my friend conceeded the
contest.

But now that I have a MacBook and have switched to SBCL, this no longer
runs. I don't remember how I ever got the idea that (character ...)
would accept an integer as an argument, since the Hyperspec says that it
doesn't.

Kent Pittman describes a way to do this conversion at
http://www.nhplace.com/kent/PS/EQUAL.html, but I'm lazy. I don't want
to have to type in an ASCII table.

Is there an easy solution or am I going to have to do some actual work?

Michael

unread,
Jan 27, 2007, 4:36:20 PM1/27/07
to
On 2007-01-27 16:08:36 -0500, wr...@stablecross.com (Bob Felts) said:

> But now that I have a MacBook and have switched to SBCL, this no longer
> runs. I don't remember how I ever got the idea that (character ...)
> would accept an integer as an argument, since the Hyperspec says that it
> doesn't.

code-char

Kaz Kylheku

unread,
Jan 27, 2007, 4:40:49 PM1/27/07
to
On Jan 27, 1:08 pm, w...@stablecross.com (Bob Felts) wrote:
> Is there an easy solution or am I going to have to do some actual work?

Are you looking for CODE-CHAR?

Bob Felts

unread,
Jan 27, 2007, 4:41:25 PM1/27/07
to
Michael <spam...@ectospheno.com> wrote:

D'oh! Thanks.

Bob Felts

unread,
Jan 27, 2007, 4:51:12 PM1/27/07
to
Kaz Kylheku <kkyl...@gmail.com> wrote:

Yes. And now I feel stupid. I did a Google search on "lisp integer
character conversion" and didn't see anything. I did try to find it
before asking.

Thanks, everyone.

Pascal Bourguignon

unread,
Jan 27, 2007, 5:20:06 PM1/27/07
to
wr...@stablecross.com (Bob Felts) writes:

> Many months ago a co-worker and I were having a contest to see whose
> programming language was bigger^H^H^H^H^H^H better. Someone had an
> e-mail sig of binary numbers, e.g.:
>
> 01000001 01110101 01110100 00100000 01110110 ...
>
> The task was to convert this to ASCII to see what it said. He chose C
> while I used Lisp. My solution was:
>
> (defun dcb-to-ascii (dcb)
> "Convert a list of decimal-coded-binary to ASCII"
> (map 'string 'character
> (mapcar #'(lambda (n) (parse-integer (write-to-string n) :radix
> 2)) dcb)))

or:

(with-input-from-string (inp " 01000001 01110101 01110100 00100000 01110110")
(coerce
(loop :for n = (let ((*read-base* 2)) (read inp nil nil)) :while n
:collect (code-char n))
'string))

--> "Aut v"

(assuming CODE-CHAR uses the ASCII map).

--
__Pascal Bourguignon__ http://www.informatimago.com/

Nobody can fix the economy. Nobody can be trusted with their finger
on the button. Nobody's perfect. VOTE FOR NOBODY.

Ken Tilton

unread,
Jan 27, 2007, 5:55:28 PM1/27/07
to

Did you try (apropos "CHAR")? Granted, you have to know enough not to do
it on "CHARACTER"), and the output would be voluminous. The groovy ACL
apropos dialogue lets me specify exported symbols for functions of just
CL, and that knocks it down to a couple dozen. If you are not blessed
with access to ACL on win32 or Wilson rackets or Nike tennis outfits*,
there is always the "character dictionary" of the hyperspec:

http://www.lisp.org/HyperSpec/Body/sec_the_chara_s_dictionary.html

ken

* Serena Williams used her championship speech to shill both. After the
way she looked destroying Sharapova, no one was going to try to stop her. k

--
Well, I've wrestled with reality for 35 years, Doctor, and
I'm happy to state I finally won out over it.
-- Elwood P. Dowd

In this world, you must be oh so smart or oh so pleasant.
-- Elwood's Mom

Bob Felts

unread,
Jan 27, 2007, 6:08:15 PM1/27/07
to
Ken Tilton <kent...@gmail.com> wrote:

> Bob Felts wrote:
> > Kaz Kylheku <kkyl...@gmail.com> wrote:
> >
> >
> >>On Jan 27, 1:08 pm, w...@stablecross.com (Bob Felts) wrote:
> >>
> >>>Is there an easy solution or am I going to have to do some actual work?
> >>
> >>Are you looking for CODE-CHAR?
> >
> >
> > Yes. And now I feel stupid. I did a Google search on "lisp integer
> > character conversion" and didn't see anything. I did try to find it
> > before asking.
>
> Did you try (apropos "CHAR")? Granted, you have to know enough not to do
> it on "CHARACTER"),

That's the problem. I tried (apropos <various guesses>), but obviously
I didn't try the right things.

> and the output would be voluminous. The groovy ACL
> apropos dialogue lets me specify exported symbols for functions of just
> CL, and that knocks it down to a couple dozen. If you are not blessed
> with access to ACL on win32

"win32"? What is that? Some kind of cabbage? ;-)

> or Wilson rackets or Nike tennis outfits*,
> there is always the "character dictionary" of the hyperspec:
>
> http://www.lisp.org/HyperSpec/Body/sec_the_chara_s_dictionary.html
>

That was helpful. I'll try to remember that.

> ken
>
> * Serena Williams used her championship speech to shill both. After the
> way she looked destroying Sharapova, no one was going to try to stop her. k

I'd buy tickets to a Tilton v. Williams matchup on c.l.l. ;-)

Ken Tilton

unread,
Jan 27, 2007, 6:27:19 PM1/27/07
to

Bob Felts wrote:
> Ken Tilton <kent...@gmail.com> wrote:
>

>>CL, and that knocks it down to a couple dozen. If you are not blessed
>>with access to ACL on win32
>
>
> "win32"? What is that? Some kind of cabbage? ;-)

Oh, sorry, in a sense, yes. win32 (or os x) is a luxury OS for us rich /
famous lifestyle folks who can throw away a couple hundred bucks (aka
"cabbage") instead of a hundred hours (of "free" time) to get an OS up
and running, or blow eight benjamins on a proper Lisp environment.

> I'd buy tickets to a Tilton v. Williams matchup on c.l.l. ;-)

That is just about the only place I would escape with my life.

kzo

Kaz Kylheku

unread,
Jan 27, 2007, 9:37:06 PM1/27/07
to
On Jan 27, 1:08 pm, w...@stablecross.com (Bob Felts) wrote:
> Many months ago a co-worker and I were having a contest to see whose
> programming language was bigger^H^H^H^H^H^H better. Someone had an
> e-mail sig of binary numbers, e.g.:
>
> 01000001 01110101 01110100 00100000 01110110 ...
>
> The task was to convert this to ASCII to see what it said. He chose C
> while I used Lisp.

This is an actual utility you could use as a filter from a text editor
over such article bodies to decode them. If it works. It's completely
untested, since I don't have a C compiler installed on my machine!
Lisp only around here. :)

#include <stdio.h>
#include <stdlib.h>

/*
* Filter a text stream, replacing sequences of seven consecutive
* 1's and 0's with the corresponding character in the execution
* environment's character set. All other text is passed through,
* including incomplete sequences of 1's and 0's.
*/

int main(void)
{
int ch, acc = 0;
char lexeme[7], *lp = lexeme;

while ((ch = getchar()) != EOF) {
switch (ch) {
case '0': case '1':
acc = (acc << 1) | (ch - '0');
*lp++ = ch;
if (lp - lexeme < 7)
break;
ch = acc;
acc = 0;
lp = lexeme;
/* fall through */
default:
if (lp > lexeme)
printf("%.*s", lp - lexeme, lexeme);
putchar(ch);
}
}
return 0;
}

Harald Hanche-Olsen

unread,
Jan 28, 2007, 4:13:28 AM1/28/07
to
+ wr...@stablecross.com (Bob Felts):

| Many months ago a co-worker and I were having a contest to see whose
| programming language was bigger^H^H^H^H^H^H better. Someone had an
| e-mail sig of binary numbers, e.g.:
|
| 01000001 01110101 01110100 00100000 01110110 ...
|
| The task was to convert this to ASCII to see what it said. He chose C
| while I used Lisp. My solution was:
|

| [...]

Now that you got the code-char thing sorted out, how about this
solution:

cl-user> (map 'string #'code-char (let ((*read-base* 2)) (read)))
(01000001 01110101 01110100 00100000 01110110)
"Aut v"

--
* Harald Hanche-Olsen <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
when there is no ground whatsoever for supposing it is true.
-- Bertrand Russell

christophe...@gmail.com

unread,
Jan 28, 2007, 10:25:38 AM1/28/07
to

> Kent Pittman describes a way to do this conversion athttp://www.nhplace.com/kent/PS/EQUAL.html, but I'm lazy. I don't want


> to have to type in an ASCII table.
>

Speaking of Kent Pittman, this is quite interesting: http://
www.nhplace.com/kent/PS/Ambitious.html . It talks about the use of an
ambitious eval so we can (among other things) parse binary numbers as
we intend without transforming them into strings first.

(INVOKE-RUBOUT-HANDLER #'EVAL-WHILE-READING)
(PROGN (SETQ *READ-BASE* 8.) 10)
=> 8. ; not 10.

tayssi...@googlemail.com

unread,
Jan 28, 2007, 11:09:30 AM1/28/07
to
Harald Hanche-Olsen wrote:
> cl-user> (map 'string #'code-char (let ((*read-base* 2)) (read)))
> (01000001 01110101 01110100 00100000 01110110)
> "Aut v"

A measure of Lisp's popularity is when we start seeing strings like
this sent to webapps:

#.(error "~S" 'pwnd!)

I'm sure the same teams which ignore thousands of compiler warnings
scrolling by will take care to use principled versions of read-from-
string...

Tayssir

mark.h...@gmail.com

unread,
Jan 28, 2007, 4:59:33 PM1/28/07
to

That's a good point -- is there a version of READ that only accepts,
say, certain "trusted" data types?

mfh

Pascal Bourguignon

unread,
Jan 28, 2007, 5:51:17 PM1/28/07
to
"mark.h...@gmail.com" <mark.h...@gmail.com> writes:

READ-CHAR, READ-LINE and READ-SEQUENCE do.
The parsing is up to you!

--
__Pascal Bourguignon__ http://www.informatimago.com/

Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay

John Thingstad

unread,
Jan 28, 2007, 6:39:54 PM1/28/07
to

setting *read-eval* to nil will flag the above as a error.
(let ((*read-eval* nil) (*read-base* 2)) (read))


--
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

tayssi...@googlemail.com

unread,
Jan 29, 2007, 11:30:16 AM1/29/07
to
On Jan 28, 11:51 pm, Pascal Bourguignon <p...@informatimago.com>
wrote:

> "mark.hoem...@gmail.com" <mark.hoem...@gmail.com> writes:
> > That's a good point -- is there a version of READ that only accepts,
> > say, certain "trusted" data types?
>
> READ-CHAR, READ-LINE and READ-SEQUENCE do.
> The parsing is up to you!

Yeah, I think if we're talking about stuff like getting data out of
webapp forms, maybe the biggest use of READ is to conveniently parse
numbers. But is READ's semantics what we necessarily want in this
situation? For example, should 23.12 be a float or a rational?


Tayssir

robert maas, see http://tinyurl.com/uh3t

unread,
Jan 29, 2007, 2:27:10 PM1/29/07
to
> From: w...@stablecross.com (Bob Felts)

> > Are you looking for CODE-CHAR?
> Yes. And now I feel stupid. I did a Google search on "lisp integer
> character conversion" and didn't see anything. I did try to find it
> before asking.

IMO there should be a nice organization of lisp functions that
relate various data types, such as integer related to character
here, plus a search engine to directly go to the appropriate
atype-rel-btype section. I'm working on the first part now (but
it'll be a long while before it's ready for your purpose), and if
anybody pays me I'd work on the search engine too.

For an example of a two-level browsing version, it might look
something like this on-screen (Web page):
[Numbers]
[Integers]
and [Rationals] [Characters] [Symbols] [Floats] [Complexes]
[Rationals]
and [Integers] [Floats] [Complexes]
[Floats]
and [Rationals] [Integers] [Complexes]
[Complexes]
and [Real/Rational/Integer]
[Sequences]
[Strings]
and [Characters] [Lists] [Symbols] [Sequences]
[Lists]
and [Strings] [DottedPairs] [Sequences] [LambdaExpressions]
[Characters]
and [Strings] [Integers] [Symbols]
[Symbols]
and [Strings] [Packages] [PropertyLists] [Functions] [Values]
[Packages]
and [Symbols]
etc. (things inside [brackets] are buttons you can click)
So in the sub-menu for Characters you can click Integers, or vice
versa, to arrive at the same WebPage describing conversions between
those two types in either direction or coordinating them in
parallel.

One caveat: I'm doing this "cookbook" for several different
languages together, currently six (php/perl/lisp/c/c++/java), so
you can not only see mappings from English descriptions to the
appropriate library call or operator primitive in each language,
but also mapping from what you already know how to do in one
language to how to do "the same thing" (or nearly equivalent) in
another language. See my posting in comp.programming for link to
link to this project, and general discussion. Proofreaders (for
technical content and also typos) would be appreciated if anyone
thinks the project is worthwhile.

robert maas, see http://tinyurl.com/uh3t

unread,
Jan 29, 2007, 5:13:10 PM1/29/07
to
> From: christopher.m.russ...@gmail.com

> Speaking of Kent Pittman, this is quite interesting:
> http://www.nhplace.com/kent/PS/Ambitious.html
... From the user's point of view, it is as if
the editing process backed up or was changed, but really it has been
started over with fewer or different characters.
I don't like his approach there. IMO the *right* way to do this is
to implement screen refresh as a virtual object which can be
updated in log(n) time and traversed in linear time, such as a
balanced binary tree of some sort (AVL etc.), where the virtual
object is pointed at from a standard place the screen-refresh
mechanism knows about. Then you can perform all screen updates in
undoable fashion:
- Perform a log(n) time operation to rebuild the part of the tree
that changes, sharing all side-branches that haven't changed.
- Overwrite the master pointer to point to that updated version
instead of the just-previous version. The next screen update
will see this new virtual screen instead of the previous, and
the user will see the change appear within one video scan frame
(1/30 sec).
Whenever you need to back up over an error, you simply overwrite
the master pointer to point to the previous state of the display.
No need to recompute the display from the very start of the line or
other major transaction group.

So to make this work with backspace and parser together, you write
your parser the same way. It uses a balanced binary tree to keep
the current parse state. As it works its way through the stream of
incoming data, at each point it rebuilds the changed part of the
parser-state tree, sharing side breanches that haven't changed. If
the parser controller gets an UNDO-CHAR event, it simply reverts to
the previous parse-state tree. If it gets an UNDO-LINE event, it
simply reverts to the checkpoint at the very start of that line. If
UNDO-LINE saves the undone state, then UNDO-UNDO could also be
implemented, like if the user accidently presses the UNDO-LINE
button on the keyboard (CTRL-U on some systems, which is right next
to CTRL-Y for yank text, CTRL-K on other systems, which is right
next to CTRL-L for refresh-screen-and-center-cursor).

Of course all side-effects must likewise be binary-tree undoable.
This may limit the kinds of read-time evaluation that are allowed.
If you keep your master program state also as a binary tree, then
undoing horrendous things like SETQ of a global would likewise be
possible. If you keep your entire filesystem in that form, even
more horrendous things like deleting files or whole directories may
be equally undoable. The original discussion was about a LISP
machine, so the idea of re-inventing the whole way filesystems are
implemented would be quite possilble in this context.

As to whether (SETQ *READ-BASE* 8.) should take effect immediately
upon being completely read (and undone the moment that last
character, the close-parens, is backspaced over, and redone if the
close-parens is typed again), thereby side-effecting the parse
in-progress, or whether parsing should run to completetion before
any of the parsed stuff is executed, should be a configuration
option settable by the user. Of course if the user says:
(PROGN (SETQ $SIDE-EFFECT-IMMEDIATE$ T)
we get a sort of paradox however we implement it.

Good thing lisp isn't like some languages, where you can say
something like:
DO {stuff; more stuff; even more stuff; yet even more stuff; } UNLESS mumble;
where you can't possibly know in the middle of parsing that input
whether it's an uncoditional block or conditional on something you
won't know until the end.

Hmm, what if you say (this is CMUCL if it makes any difference):
(PROGN (QUIT)
and then how exactly do you get back into the system so you can
type rubout to avoid quitting the whole lisp environment?

Thomas A. Russ

unread,
Jan 29, 2007, 6:16:58 PM1/29/07
to
"mark.h...@gmail.com" <mark.h...@gmail.com> writes:

>
> That's a good point -- is there a version of READ that only accepts,
> say, certain "trusted" data types?

Are you thinking about something like:

(let ((*read-eval* nil))
....)

--
Thomas A. Russ, USC/Information Sciences Institute

WJ

unread,
Apr 24, 2011, 4:50:48 AM4/24/11
to
Pascal Bourguignon wrote:

> wr...@stablecross.com (Bob Felts) writes:
>
> > Many months ago a co-worker and I were having a contest to see whose
> > programming language was bigger^H^H^H^H^H^H better. Someone had an
> > e-mail sig of binary numbers, e.g.:
> >
> > 01000001 01110101 01110100 00100000 01110110 ...
> >
> > The task was to convert this to ASCII to see what it said. He chose C
> > while I used Lisp. My solution was:
> >
> > (defun dcb-to-ascii (dcb)
> > "Convert a list of decimal-coded-binary to ASCII"
> > (map 'string 'character
> > (mapcar #'(lambda (n) (parse-integer (write-to-string n) :radix
> > 2)) dcb)))
>
> or:
>
> (with-input-from-string (inp " 01000001 01110101 01110100 00100000
> 01110110") (coerce
> (loop :for n = (let ((*read-base* 2)) (read inp nil nil)) :while n
> :collect (code-char n))
> 'string))
>
> --> "Aut v"
>
> (assuming CODE-CHAR uses the ASCII map).

Using Scheme (requires srfi-13 for "string-tokenize").

(define (dcb->ascii str)
(list->string
(map (lambda (s) (integer->char (string->number s 2)))
(string-tokenize str))))

(dcb->ascii " 01000001 01110101 01110100 00100000 01110110")
==>
"Aut v"

0 new messages