This is a read-only archive of lispforum.com. The forum was locked to new users and posts and is preserved here as static HTML from a database snapshot taken on 2019-09-07.

Combining digits to make a string

19 posts · 8354 views

Warning: I am completely new to lisp, I started two days ago.

What I want to do is make a 3 digit number, randomly generated and each number can only range from 0 to 3

ex: '301' '123' '000' '333' ...

They way I was trying to do it was use the random funcion (random 3) then append all three of the digits however whenever I get it to work it makes a list not a string (ex: (0 1 2) or (0 0 0))

The code I used to get those results was:
(concatenate 'list (list (random 3)) (list (random 3))(list (random 3))) 
=> (1 0 3)


Yes I know that 'list makes it a list but everything else I tried did not work.

Thank You for your help,
all comments are welcome!

Re: Combining digits to make a string

333 = 3 * 100 + 3 * 10 + 3 * 1

Does that help? ;)

Re: Combining digits to make a string

There is also quite silly solution which, if this is in fact homework of some sort, is not the answer you are looking for, but I just cannot resist:
(format nil "~4,3,'0r" (random 64))

Re: Combining digits to make a string

Ramarren wrote:There is also quite silly solution which, if this is in fact homework of some sort, is not the answer you are looking for, but I just cannot resist:
(format nil "~4,3,'0r" (random 63))
Nice thinking! Just use numbers in base 4. His teacher won't accept this answer, but that is a nice one.

I think you should put (random 64) since (random 63) will not include the number 63 itself (and 63 will generate the string "333").

BTW, instead of
(concatenate 'list (list (random 3)) (list (random 3))(list (random 3)))
it is much simpler and efficient to write
(list (random 3) (random 3) (random 3))
instead (but, again, this is not the correct answer).

Re: Combining digits to make a string

I believe you were implicitly suggesting, "why doesn't it work to do some thing like...
(coerce '(1 2 3) 'string)
...which is basically equivalent to your...
(concatenate 'string '(1 2 3))
?" After all, this works:
(coerce '(1 2 3) 'vector) ==> #(1 2 3)
(concatenate 'string '(#\1 #\2 #\3)) ==> "123"
While it is true that strings are nothing more than vectors made of characters, in Common Lisp (as in most languages) the number 1 and the character 1 (denoted #\1 in Common Lisp) are very distinct. So, if you want to pick random numbers and produce random character versions of those numbers, you need a map (or way to convert) between numbers and characters. Once you have such a map, you can MAPCAR over your list and feed the result to COERCE.

One thing to look at are the functions CHAR-CODE and CODE-CHAR. Another (IMO, cleaner) method is to look into writing a new random-like function that chooses random characters by some means instead of choosing random numbers.

Best,
Zach

Re: Combining digits to make a string

Here are a few things that sprang to mind.
(defun miningold.alphabet (&key (length 3) (alphabet "0123"))
  (let ((output (make-string length)))
    (dotimes (i length output)
      (setf (aref output i)
            (aref alphabet (random (length alphabet)))))))

(defun miningold.numbers (&key (length 3) (limit 3))
  (let ((output (make-string length)))
    (dotimes (i length output)
      (setf (aref output i)
            (digit-char (random limit))))))

Re: Combining digits to make a string

smithzv wrote:I believe you were implicitly suggesting, "why doesn't it work to do some thing like...
(coerce '(1 2 3) 'string)
...which is basically equivalent to your...
(concatenate 'string '(1 2 3))
?" After all, this works:
(coerce '(1 2 3) 'vector) ==> #(1 2 3)
(concatenate 'string '(#\1 #\2 #\3)) ==> "123"
Wait, does "miningold" want a number or a string? Because I thought he wanted a number:
What I want to do is make a 3 digit number, randomly generated [...]
but you are teaching him how to obtain a string instead.

Re: Combining digits to make a string

If you want string representation:
(concatenate 'string (princ-to-string (random 3)) (princ-to-string (random 3)) (princ-to-string (random 3)))
->"112"
Else I don't know how to present for example 012 as number as starting zeros will be removed.
012
->12

bobi
http://www.linkedin.com/pub/dir/slobodan/blazeski

Re: Combining digits to make a string

gugamilare wrote:Wait, does "miningold" want a number or a string?
According to the post title, a string, and according to the post body, a number.

Re: Combining digits to make a string

Paul Donnelly wrote:
gugamilare wrote:Wait, does "miningold" want a number or a string?
According to the post title, a string, and according to the post body, a number.
Yeah, I took his example of '000' in the body to mean he wants to deal with strings. Just because number has a specific meaning in CL doesn't mean I might not refer to a number that is contained in a string. Also, the question of how many digits are in a number is kind of ill formed until you decide on a few details regarding how a number is printed. For instance, whether leading zeros should be printed or what base the number should be printed in.

Zach S

Re: Combining digits to make a string

Actually, if I were an instructor I'd take a format-based solution if I were convinced it were original, but.. I'd sure want to know how the student came up with it. Well, maybe that's why I'm not an instructor.
smithzv wrote:
Paul Donnelly wrote:
gugamilare wrote:Wait, does "miningold" want a number or a string?
According to the post title, a string, and according to the post body, a number.
Yeah, I took his example of '000' in the body to mean he wants to deal with strings. Just because number has a specific meaning in CL doesn't mean I might not refer to a number that is contained in a string. Also, the question of how many digits are in a number is kind of ill formed until you decide on a few details regarding how a number is printed. For instance, whether leading zeros should be printed or what base the number should be printed in.
The way I read it he just wants a string of three characters, each of which is either 0, 1, 2, or 3. So the base, leading zeros, etc. aren't relevant. There a lot of ways to do this in CL, but I'm surprised no one has mentioned DIGIT-CHAR.

This is pretty clearly homework, so I wouldn't normally give a full answer, but since there have been a couple of pretty complete answers so far here's a simple, but not very elegant solution:

(concatenate 'string (mapcar (lambda (x) (digit-char (random x))) '(4 4 4)))

Or at least I think that is correct- haven't really tested it or thought very hard about it so caveat lector.

Re: Combining digits to make a string

If you want to get baroque about it, you could try this:
(parse-integer
  (format nil "~d~d~d"
    (list (random 3) (random 3) (random 3))))

Re: Combining digits to make a string

Maybe if I explain why I want these numbers (or strings I'm not sure what to call them) it might clear up the confusion.

Like I said I am new at this, but I want to make a GA (genetic algorithm) using a representation of DNA instead of using binary for my population.
I was wondering what is the best way to achieve a strand of "DNA" to use in a GA.

I was thinking about these options:

((013) (201)...)
((0 1 3) (2 0 1)...)
or an array (which I do not know how to make)

Note: Duncan is right (I think) the leading zeros should not matter (but maybe they do), and no, this is not homework this is for my entertainment only.

Thank you for all of your responses.

-Miningold

Re: Combining digits to make a string

miningold wrote: I was wondering what is the best way to achieve a strand of "DNA" to use in a GA.

I was thinking about these options:

((013) (201)...)
((0 1 3) (2 0 1)...)
or an array (which I do not know how to make)

Note: Duncan is right (I think) the leading zeros should not matter (but maybe they do), and no, this is not homework this is for my entertainment only.
OK- sorry for assuming it was homework. It really did look like homework ;). I realized I was wrong about that after seeing your other thread. You might do yourself a favor and preface future questions like this with: "THIS IS NOT HOMEWORK" ;). 'Cause there are still a few schools that use CL for some classes and they tend to assign their students exactly this kind of "getting used to lisp" thing. Some percentage of students decide to get clever and hit the forums- I think if you look through the archives of this forum you'll find a number of people with one or two posts who just wanted help with their homework.

Anyway, you really need to decide how you want to represent your data. There's a big difference, in CL, between "334" and ' (334) and '(3 3 4). Each can be converted to the other, if necessary, but... better to start with one format firmly in mind, and then change it if necessary. Of those three the '(( 3 3 4) (1 0 2)) form is the most flexible, and the easiest to process, IMHO. But this depends (obviously) on what you want to do with the data... that would be a poor way to store the data if it had to be interpreted numerically.

Re: Combining digits to make a string

miningold wrote: I was thinking about these options:

((013) (201)...)
((0 1 3) (2 0 1)...)
or an array (which I do not know how to make)
you can use an array (or a vector):

(vector 0 1 3) => #(0 1 3)

see more about it here:
http://gigamonkeys.com/book/collections.html

Pedro

Re: Combining digits to make a string

I decided to use this code:
(setq number-seeds 10)
(let (value)
  (dotimes (num number-seeds value)
    (setq value (cons (list (random 3) (random 3) (random 3))
		      value))))
I get a list of:
((. . .) (. . .) ...)

Is there a way to turn the list into a vector such as:
[(. . .) (. . .) ...]

or a different way to write the code so that i get a vector as shown above?

Re: Combining digits to make a string

miningold wrote:I decided to use this code:
(setq number-seeds 10)
(let (value)
  (dotimes (num number-seeds value)
    (setq value (cons (list (random 3) (random 3) (random 3))
		      value))))
I get a list of:
((. . .) (. . .) ...)

Is there a way to turn the list into a vector such as:
[(. . .) (. . .) ...]
Yes:
(make-array (length some-list) :initial-contents some-list)
You can put NUMBER-SEEDS instead of (length some-list).
or a different way to write the code so that i get a vector as shown above?
Yes, this is simple to do as well:
(let ((array (make-array number-seeds)))
  (dotimes (num number-seeds value)
    (setf (aref array num) (list (random 3) (random 3) (random 3)))))

Re: Combining digits to make a string

gugamilare wrote:
(make-array (length some-list) :initial-contents some-list)
(let ((array (make-array number-seeds)))
  (dotimes (num number-seeds value)
    (setf (aref array num) (list (random 3) (random 3) (random 3)))))
I could not get either of those options working, but i think that it was my fault, as I have already said I am new to lisp

So would you mind giving me the code in the complete form not just additions as well as explanations so that i know what is going on.

Thank you

Re: Combining digits to make a string

Using the first option - transforming a list into an array:
(let ((number-seeds 10) value)
  (dotimes (num number-seeds value)
    (setq value (cons (list (random 4) (random 4) (random 4))
                      value)))
  (make-array number-seeds :initial-contents value))
Using the second option - constructing the array directly:
(let* ((number-seeds 10)
       (array (make-array number-seeds)))
  (dotimes (num number-seeds array)
    (setf (aref array num) (list (random 4) (random 4) (random 4)))))
There was a bug in the second portion of the code, that's why you had trouble using it :)

EDIT: Oops! My bad. Should be (random 4) instead of (random 3), or else the number 3 will never come out. Now it is fixed.