Newbie needs help please
Newbie needs help please
Hello all,
I am a big LISP-Newb and am struggling with a program that is supposed to encrypt a string with Caesar's cipher. What I have in mind is a function that takes in 2 arguments: a string and a number to specify the modulus. Something along the lines:
(defun c-encrypt (string number)
("lots of helper functions"))
My thoughts so far are that it would be best to set the alphabet as a parameter and write a function that looks up a chars position in the parameter and then shifts it the wanted Caesar's modulo to the right e.g. A ->modulo 7 -> H
May look something along the lines:
(defun shift (char x) (char *alphabet* (mod(+24 x"being the wanted modulo")27)))
Well, I ran headfirst into a lot of problems. First of all, I can not find a function to split a string into its single chars (convert it to numbers fine, but simply split it...). If I could somehow split the string into its single characters and make a list out of them my first problem would be solved. When trying to concatenate there are always these darn #\ left which make it impossible to use the parameter.
As you see I already fail at the first obstacle of the whole project... Not to speak about the rest...
Any help would be greatly appreciated since I really start to get frustrated about this project and LISP itself. For some reason I find it extremely difficult to "think LISP".
Thanks already for your answers!
I am a big LISP-Newb and am struggling with a program that is supposed to encrypt a string with Caesar's cipher. What I have in mind is a function that takes in 2 arguments: a string and a number to specify the modulus. Something along the lines:
(defun c-encrypt (string number)
("lots of helper functions"))
My thoughts so far are that it would be best to set the alphabet as a parameter and write a function that looks up a chars position in the parameter and then shifts it the wanted Caesar's modulo to the right e.g. A ->modulo 7 -> H
May look something along the lines:
(defun shift (char x) (char *alphabet* (mod(+24 x"being the wanted modulo")27)))
Well, I ran headfirst into a lot of problems. First of all, I can not find a function to split a string into its single chars (convert it to numbers fine, but simply split it...). If I could somehow split the string into its single characters and make a list out of them my first problem would be solved. When trying to concatenate there are always these darn #\ left which make it impossible to use the parameter.
As you see I already fail at the first obstacle of the whole project... Not to speak about the rest...
Any help would be greatly appreciated since I really start to get frustrated about this project and LISP itself. For some reason I find it extremely difficult to "think LISP".
Thanks already for your answers!
Re: Newbie needs help please
First, the language family is called Lisp, and hasn't been called LISP since the, I believe, seventies, when non-capital letters were inventedRaydPanda wrote:I am a big LISP-Newb
That is meaningless. A string is a sequence of characters. It is already as split as it is going to be. All functions in sequences dictionary work on strings. For this application you do not want the list anyway, a vector and hash-table (in theory you could o it without the lookup by manipulating char-codes, but this is not general) is better.RaydPanda wrote:First of all, I can not find a function to split a string into its single chars (convert it to numbers fine, but simply split it...).
Re: Newbie needs help please
Quick and dirty:RaydPanda wrote: Well, I ran headfirst into a lot of problems. First of all, I can not find a function to split a string into its single chars (convert it to numbers fine, but simply split it...). If I could somehow split the string into its single characters and make a list out of them my first problem would be solved. When trying to concatenate there are always these darn #\ left which make it impossible to use the parameter.
Code: Select all
> (loop for c across "foo" collect c)
(#\f #\o #\o)
> (coerce * 'string)
"foo"
Re: Newbie needs help please
Thanks for your posts!
@Ramarren
Well, I guess my university course is not the best since I wasn't told about sequences and my teachers use "LISP" as if it is the correct form... thanks for the enlightenment! I'll try my luck with these, maybe I get some results.
@sinnatag
My problem with the first of your suggestions is that I need a list without the #\, otherwise I can not work with my alphabet parameter. Any suggestions on that?
@Ramarren
Well, I guess my university course is not the best since I wasn't told about sequences and my teachers use "LISP" as if it is the correct form... thanks for the enlightenment! I'll try my luck with these, maybe I get some results.
@sinnatag
My problem with the first of your suggestions is that I need a list without the #\, otherwise I can not work with my alphabet parameter. Any suggestions on that?
Re: Newbie needs help please
Unfortunately many teachers learnt Lisp when it was still a LISP and refused to learn anything more than necessary for their assignments to actually work in modern Lisp. Sometimes.RaydPanda wrote:@Ramarren
Well, I guess my university course is not the best since I wasn't told about sequences and my teachers use "LISP" as if it is the correct form... thanks for the enlightenment! I'll try my luck with these, maybe I get some results.
#\ is just syntax for characters. A string is a sequence of characters. Your alphabet should be a sequence of characters. It will work. If it doesn't work, then you are doing it wrong.RaydPanda wrote:@sinnatag
My problem with the first of your suggestions is that I need a list without the #\, otherwise I can not work with my alphabet parameter. Any suggestions on that?
For the Caesar's cipher you need to look up the source characters position in the alphabet, add to it the shift modulo the length of the alphabet and then get the character from the alphabet. This can be done character by character.
Re: Newbie needs help please
You can convert characters to symbols with something like this:RaydPanda wrote: My problem with the first of your suggestions is that I need a list without the #\, otherwise I can not work with my alphabet parameter. Any suggestions on that?
Code: Select all
(intern (make-string 1 :initial-element (char-upcase #\a)))
-a
-
- Posts: 406
- Joined: Sat Mar 07, 2009 6:17 pm
- Location: Brazil
- Contact:
Re: Newbie needs help please
This way is simpler:sinnatagg wrote:You can convert characters to symbols with something like this:RaydPanda wrote: My problem with the first of your suggestions is that I need a list without the #\, otherwise I can not work with my alphabet parameter. Any suggestions on that?
Code: Select all
(intern (make-string 1 :initial-element (char-upcase #\a)))
Code: Select all
(intern (string (char-upcase #\a)))
Re: Newbie needs help please
Yeah, I was kind of wondering why there wasn't a function like this in CL, aside from coerce() which doesn't work for this case.gugamilare wrote: This way is simpler:
-a
Re: Newbie needs help please
First off, thanks to all of you!
By now I got far enough to encrypt a single character. I try now to get it working on a string but to no avail so far.
The code I have until now looks like this:
I am not sure how to use the map function with this. I tried (map 'string #rotate) but that doesn't seem to be the correct method. How do I get my rotate function to work on a whole string?
By now I got far enough to encrypt a single character. I try now to get it working on a string but to no avail so far.
The code I have until now looks like this:
Code: Select all
; Alphabet as parameter plus one whitespace at index 0
(defparameter *alphabet* " abcdefghijklmnopqrstuvwxyz,.0123456789")
; Finds the index of char in *alphabet*:
(defun alphabet-index (char)
(position char *alphabet*))
; Finds the char shifted n places to the right in the alphabet:
(defun rotate (char n)
(elt *alphabet* (mod (+ (alphabet-index char) n)(length *alphabet*))))
Re: Newbie needs help please
The signature of the map function is:RaydPanda wrote:I am not sure how to use the map function with this. I tried (map 'string #rotate) but that doesn't seem to be the correct method. How do I get my rotate function to work on a whole string?
Code: Select all
map result-type function &rest sequences+ => result
Code: Select all
(defun make-rotator (n)
#'(lambda (char)
(rotate char n)))
Then you can simply use that closure as an argument to map:
Code: Select all
CL-USER> (map 'string (make-rotator 5) "ala ma kota")
"fqferfeptyf"