abstract:
(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))))
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)))
Copy Code Code:
Fixed- (funcall (if (< this last)
- #'-
- #'+)
- sum this)))
Copy Code 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 |