Other Programming Languages
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me

The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.

Go Back   Dev Shed ForumsProgramming Languages - MoreOther Programming Languages

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old January 24th, 2006, 03:10 PM
LyonHaert's Avatar
LyonHaert LyonHaert is offline
Arcane Scribbler
Dev Shed Intermediate (1500 - 1999 posts)
 
Join Date: Jun 2005
Location: Indianapolis, IN
Posts: 1,907 LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level) 
Time spent in forums: 1 Month 1 Week 1 Day 6 h 33 m 15 sec
Reputation Power: 583
Lisp: Roman Numerals

I was bored for a while Sunday and decided I'd write some Lisp that would take a roman numeral string and give the decimal integer value... just because I could.

So here it is, but I'd like it if anybody who is fluent in Lisp can point out any poor practices so that I no longer repeat them (I'm pretty novice).

Code:
Lisp
(defun romanval (x)
  (cond
    ((eq x #\M) 1000)
    ((eq x #\D) 500)
    ((eq x #\C) 100)
    ((eq x #\L) 50)
    ((eq x #\X) 10)
    ((eq x #\V) 5)
    ((eq x #\I) 1)))

(defun strtolist (str)
  (let ((l (length str)))
    (do ((i 0 (+ i 1))
         (lst nil (push (char str i) lst)))
        ((>= i l) (reverse lst)))))

(defun charstoroman (chars)
  (labels ((rec (src dest)
             (cond
               ((null src) (reverse dest))
               (t
                 (push (romanval (car src)) dest)
                 (rec (cdr src) dest)))))
    (rec chars nil)))

(defun calcroman (lst)
  (labels ((rec (src last sum)
             (cond
               ((null src) sum)
               (t
                 (rec (cdr src) (car src)
                   (if (< (car src) last)
                       (- sum (car src))
                       (+ sum (car src))))))))
    (rec (reverse lst) 0 0)))

(defun romantoi (str)
  (calcroman (charstoroman (strtolist str))))

Reply With Quote
  #2  
Old January 24th, 2006, 05:44 PM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,537 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 17 m 47 sec
Reputation Power: 68
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
I haven't got the time to look at this in detail right now but one thing that stands out right of the bat is naming conventions. Composite names in Lisp/Scheme are usually hyphenated ala something-and-something-else, this makes things easier to read . You may also want to get in the habit of commenting code you write.

I'll do my best to take a proper look at it tomorrow and recommend any improvements.

Good work though ,

Mark.
__________________
programming language development: www.netytan.com Hula


Reply With Quote
  #3  
Old January 24th, 2006, 05:52 PM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,537 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 17 m 47 sec
Reputation Power: 68
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
In the mean time you may like to know about the coerce function; it simply lets you forcefully change one type into another if at all possible.

Code:
(defun implode (list)
  "The inverse of explode; implode returns a string representation of a list
  object."
  (coerce list 'string))

(defun explode (string)
  "The inverse of implode; explode returns a list representation of a string."
  (coerce string 'list))


I wrote these for a project I was working on, they're simple wrappers but they're worth keeping around .

Mark.

Last edited by netytan : January 24th, 2006 at 05:54 PM.

Reply With Quote
  #4  
Old January 25th, 2006, 10:29 AM
LyonHaert's Avatar
LyonHaert LyonHaert is offline
Arcane Scribbler
Dev Shed Intermediate (1500 - 1999 posts)
 
Join Date: Jun 2005
Location: Indianapolis, IN
Posts: 1,907 LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level) 
Time spent in forums: 1 Month 1 Week 1 Day 6 h 33 m 15 sec
Reputation Power: 583
Awesome.
I knew there had to be a built-in functions for conversions, I just need to find a reference to built-in functions. I'm using CLisp 2.37, btw. The only references I have at the moment are the tutorial doc that come with CLisp, On Lisp by Paul Graham (PDF), and a couple HTML pages I found.

Reply With Quote
  #5  
Old January 25th, 2006, 01:38 PM
Yegg`'s Avatar
Yegg` Yegg` is offline
Contributing User
Dev Shed Intermediate (1500 - 1999 posts)
 
Join Date: Dec 2004
Location: Meriden, Connecticut
Posts: 1,797 Yegg` User rank is First Lieutenant (10000 - 20000 Reputation Level)Yegg` User rank is First Lieutenant (10000 - 20000 Reputation Level)Yegg` User rank is First Lieutenant (10000 - 20000 Reputation Level)Yegg` User rank is First Lieutenant (10000 - 20000 Reputation Level)Yegg` User rank is First Lieutenant (10000 - 20000 Reputation Level)Yegg` User rank is First Lieutenant (10000 - 20000 Reputation Level)Yegg` User rank is First Lieutenant (10000 - 20000 Reputation Level)Yegg` User rank is First Lieutenant (10000 - 20000 Reputation Level) 
Time spent in forums: 3 Weeks 6 Days 21 h 54 m 27 sec
Reputation Power: 153
Send a message via AIM to Yegg`
Make sure you have HyperSpec.
Comments on this post
netytan agrees: About to suggest the same thing Yegg
LyonHaert agrees: Thank you.

Reply With Quote
  #6  
Old January 25th, 2006, 02:11 PM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,537 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 17 m 47 sec
Reputation Power: 68
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
Heres a rewritten version of the code you posted. It's the same length with [lots of] comments so it should actually be shorter .

Code:

(defun roman-digit->arabic (v)
  "Converts a given single roman numeral into its equivalent arabic value."
  (case v
    ;; Maps each character used in the roman number system onto their value.
    ;; Returns the value corresponding to V or NIL otherwise.
    (#\M 1000)
    (#\D 500)
    (#\C 100)
    (#\L 50)
    (#\X 10)
    (#\V 5)
    (#\I 1)))

(defun roman->arabic-helper (rest last sum)
  "A none-strict utility that converts roman numerals into equivalent arabic
  numbers; works on a list of numbers :)."
  (if (consp rest)
    (let ((this (car rest))
          (rest (cdr rest)))

      ;; Recursively calls roman->arabic-helper on the rest of the list; if
      ;; the last number was less than this one then subtract the new value,
      ;; else add them 0_o.
      (roman->arabic-helper rest this 
          (funcall (if (< last this) ; Return and evaluate the +/- function.
                     #'-
                     #'+)
                   this sum)))
    sum)) ;Returns sum once the whole list has been processed.

(defun roman->arabic (v)
  "Called to convert a roman numeral into it's fully expanded arabic form."
  (roman->arabic-helper
      ;; Calls roman-digit->arabic-value on each item of the newly coerced
      ;; list of characters.
      (mapcar #'roman-digit->arabic
          (coerce v 'list))
      0 0))


Note though that this is partially stylized, it's not usual for instance that the helper function be defined externally however it can make debugging easier. Aside from that it's this is more often done in Scheme where define/defun's can be nested or a named let can be easily used – kinda like labels but tidier .

I hope this helps man,

Mark.
Comments on this post
LyonHaert agrees: Thank you, too.

Last edited by netytan : January 25th, 2006 at 02:19 PM.

Reply With Quote
  #7  
Old January 25th, 2006, 03:14 PM
LyonHaert's Avatar
LyonHaert LyonHaert is offline
Arcane Scribbler
Dev Shed Intermediate (1500 - 1999 posts)
 
Join Date: Jun 2005
Location: Indianapolis, IN
Posts: 1,907 LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level) 
Time spent in forums: 1 Month 1 Week 1 Day 6 h 33 m 15 sec
Reputation Power: 583
Well, it's shorter by default because the function that converted a string to a list of characters was cut in favor of (coerce string 'list).

Thanks for the link to HyperSpec. Now I just need to figure an easy way to download it so I have an offline copy. (I do most coding on my laptop, which I keep unconnected from networks most of the time).

Reply With Quote
  #8  
Old January 25th, 2006, 03:53 PM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,537 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 17 m 47 sec
Reputation Power: 68
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
That and a lack of 'chartoroman . All in all we just need a function to check if the numerals are in a valid form before computing it to have a pretty tight implementation of Roman to arabic.

Either way I hope it was useful,

Mark.

Reply With Quote
  #9  
Old January 25th, 2006, 04:14 PM
LyonHaert's Avatar
LyonHaert LyonHaert is offline
Arcane Scribbler
Dev Shed Intermediate (1500 - 1999 posts)
 
Join Date: Jun 2005
Location: Indianapolis, IN
Posts: 1,907 LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level) 
Time spent in forums: 1 Month 1 Week 1 Day 6 h 33 m 15 sec
Reputation Power: 583
Quote:
Originally Posted by netytan
All in all we just need a function to check if the numerals are in a valid form before computing it to have a pretty tight implementation of Roman to arabic.

That's a bit harder. Maybe with some Regular Expressions, but that's probably overkill. Perhaps on some day when I want to figure something out, but don't want to work on anything I should be working on, I'll take a go at it.

Reply With Quote
  #10  
Old January 27th, 2006, 02:46 PM
LyonHaert's Avatar
LyonHaert LyonHaert is offline
Arcane Scribbler
Dev Shed Intermediate (1500 - 1999 posts)
 
Join Date: Jun 2005
Location: Indianapolis, IN
Posts: 1,907 LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level)LyonHaert User rank is Colonel (50000 - 60000 Reputation Level) 
Time spent in forums: 1 Month 1 Week 1 Day 6 h 33 m 15 sec
Reputation Power: 583
Well, I finally got around to taking a look at your rewrite last night, and it didn't work. Just three minor bugs, so I have to surmise from the googlie-eyes you had in the comment in roman->arabic-helper (O_o) that the algorithm I was using was not clear.

The first couple in roman->arabic-helper:
Code:
Original
          (funcall (if (< last this)
                     #'-
                     #'+)
                   this sum)))

Code:
Fixed
          (funcall (if (< this last)
                     #'-
                     #'+)
                   sum this)))


The third was that the results of the list that mapcar returns in roman->arabic needs to be reversed before it goes to roman->arabic-helper.

So, if we supply the string "MCMXLV" (just to supply some subtractions), then we get this list out of mapcar:
(1000 100 1000 10 50 5)

For the algorithm to work, that list has to be run from the lowest end, so we reverse it first:
(5 50 10 1000 100 1000)

Then we start with a sum of 0, adding most of the time, but if we encounter a value smaller than the last value, we subtract instead (CM = 1000 - 100, XL = 50 - 10):
5 > 0: sum += 5 -> 5
50 > 5: sum += 50 -> 55
10 < 50: sum -= 10 -> 45
1000 > 10: sum += 1000 -> 1045
100 < 1000: sum -= 100 -> 945
1000 > 100: sum += 1000 -> 1945
Comments on this post
netytan agrees: Good explanation
__________________
Joel B Fant
"An element of conflict in any discussion is a very good thing. Shows everybody's taking part, nobody left out. I like that."

.NET Must-Haves
Tools: Reflector
References: Threading in .NET

Reply With Quote
  #11  
Old January 27th, 2006, 06:07 PM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,537 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 18 h 17 m 47 sec
Reputation Power: 68
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
sorry lion, I only tested it with a handful of values and it worked for them so I thought it was working, apparently not. The googlie eyes were actually because the function gave me a little trouble at first.

I had it working with <= but wanted to make that either < or > for conciseness; I didn't actually look at your code other than to see what it did.

Thanks for the fix man,

Mark.

Reply With Quote
  #12  
Old January 31st, 2006, 04:58 AM
jamieB jamieB is offline
Contributing User
Dev Shed Novice (500 - 999 posts)
 
Join Date: Nov 2002
Posts: 596 jamieB User rank is Sergeant (500 - 2000 Reputation Level)jamieB User rank is Sergeant (500 - 2000 Reputation Level)jamieB User rank is Sergeant (500 - 2000 Reputation Level)jamieB User rank is Sergeant (500 - 2000 Reputation Level)jamieB User rank is Sergeant (500 - 2000 Reputation Level) 
Time spent in forums: 2 Days 3 h 56 m 23 sec
Reputation Power: 22
Quote:
Originally Posted by LyonHaert
Awesome.
I knew there had to be a built-in functions for conversions, I just need to find a reference to built-in functions. I'm using CLisp 2.37, btw. The only references I have at the moment are the tutorial doc that come with CLisp, On Lisp by Paul Graham (PDF), and a couple HTML pages I found.


see also Practical Common Lisp, Cliki and the CL Cookbook. On Lisp? Macro power to you!

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming Languages - MoreOther Programming Languages > Lisp: Roman Numerals

Developer Shed Advertisers and Affiliates



Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump

Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 


Powered by: vBulletin Version 3.0.5
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.

© 2003-2013 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap