Author Topic: Decimal to roman numbers converter  (Read 10522 times)

0 Members and 1 Guest are viewing this topic.

Offline Juan Tamarit

  • Newbie
  • Posts: 53
    • View Profile
Decimal to roman numbers converter
« on: August 28, 2020, 04:01:29 am »
Hello everyone. My first time here. I will like to start by thanking to the QB64 creators, and also to Terry Ritchie, i´ve learned a lot from his site, and still going. I have to confess that i'm not a programmer, i'm a chemistry technician, but i'm a hobbist entusiast, so i want to check out if i'm taking the right direction.

I was wandering if i could make a program to turn decimal numbers to roman, just for the challenge, and i came up with this:

Code: QB64: [Select]
  1. COLOR _RGB(255, 0, 0)
  2. PRINT STRING$(43, "Û")
  3. PRINT "Û Conversor de n£meros ar bicos a romanos Û"
  4. PRINT STRING$(43, "Û")
  5. COLOR _RGB(255, 255, 255)
  6.     INPUT " 1 a 3999, 0 para salir > ", numero% '                       obtener el numero del usuario
  7.     IF numero% > 0 AND numero% < 4000 THEN '                            verificar si el numero esta en rango
  8.         numero$ = LTRIM$(STR$(numero%)) '                               si esta, lo convertimos en string y le sacamos el espacio de adelante
  9.         digitos% = LEN(numero$) '                                       medimos cuantos digitos tiene el numero
  10.         REDIM array%(digitos%) '                                        hacemos un array de esa cantidad de digitos (no vamos a usar el indice 0)
  11.         REDIM resultado$(digitos%) '                                    preparamos otro array para armar la respuesta como string, pero tiene la misma longitud que el de digitos
  12.         FOR i% = 1 TO digitos% '                                        ciclamos por cada digito, desde atras hacia adelante array(1) son las unidades array(3) son las centenas
  13.             array%(i%) = VAL(MID$(numero$, (digitos% + 1) - i%, 1)) '   y vamos guardando en el array sus valores individuales como integer
  14.         NEXT i%
  15.         SELECT CASE array%(1) '                                         caso de las unidades
  16.             CASE 1: resultado$(1) = "I"
  17.             CASE 2: resultado$(1) = "II"
  18.             CASE 3: resultado$(1) = "III"
  19.             CASE 4: resultado$(1) = "IV"
  20.             CASE 5: resultado$(1) = "V"
  21.             CASE 6: resultado$(1) = "VI"
  22.             CASE 7: resultado$(1) = "VII"
  23.             CASE 8: resultado$(1) = "VIII"
  24.             CASE 9: resultado$(1) = "IX"
  25.             CASE 0: resultado$(1) = ""
  26.         END SELECT
  27.         IF digitos% > 1 THEN '                                          no meterse en una dimension que el array no tenga
  28.             SELECT CASE array%(2) '                                     caso de las decenas
  29.                 CASE 1: resultado$(2) = "X"
  30.                 CASE 2: resultado$(2) = "XX"
  31.                 CASE 3: resultado$(2) = "XXX"
  32.                 CASE 4: resultado$(2) = "XL"
  33.                 CASE 5: resultado$(2) = "L"
  34.                 CASE 6: resultado$(2) = "LX"
  35.                 CASE 7: resultado$(2) = "LXX"
  36.                 CASE 8: resultado$(2) = "LXXX"
  37.                 CASE 9: resultado$(2) = "XC"
  38.                 CASE 0: resultado$(2) = ""
  39.             END SELECT
  40.             IF digitos% > 2 THEN '                                      no meterse en una dimension que el array no tenga
  41.                 SELECT CASE array%(3) '                                 caso de las centenas
  42.                     CASE 1: resultado$(3) = "C"
  43.                     CASE 2: resultado$(3) = "CC"
  44.                     CASE 3: resultado$(3) = "CCC"
  45.                     CASE 4: resultado$(3) = "CD"
  46.                     CASE 5: resultado$(3) = "D"
  47.                     CASE 6: resultado$(3) = "DC"
  48.                     CASE 7: resultado$(3) = "DCC"
  49.                     CASE 8: resultado$(3) = "DCCC"
  50.                     CASE 9: resultado$(3) = "CM"
  51.                     CASE 0: resultado$(3) = ""
  52.                 END SELECT
  53.                 IF digitos% > 3 THEN
  54.                     SELECT CASE array%(4) '                             no meterse en una dimension que el array no tenga
  55.                         CASE 1: resultado$(4) = "M" '                   caso de las unidades de mil
  56.                         CASE 2: resultado$(4) = "MM"
  57.                         CASE 3: resultado$(4) = "MMM"
  58.                     END SELECT
  59.                 END IF
  60.             END IF
  61.         END IF
  62.     ELSEIF numero% = 0 THEN '                                           el usuario ingreso 0 y quiere salir del programa
  63.         COLOR _RGB(255, 0, 0)
  64.         PRINT "Los romanos no conocian el 0!"
  65.         PRINT "            "
  66.         SLEEP 3
  67.         SYSTEM
  68.     ELSE '                                                              el usuario ingreso un numero fuera de rango
  69.         PRINT "N£mero fuera de rango"
  70.     END IF
  71.     PRINT " ";
  72.     FOR i% = digitos% TO 1 STEP -1
  73.         PRINT resultado$(i%); '                                         imprimir el resultado digto a digito trasformados
  74.     NEXT i%
  75.     PRINT
  76.     PRINT

I have two questions for the community:

1) How does this program looks to you? Could have I done any better? I'ts a horrible mess? Looks fine?

2) As i learned from Terrie's class I ususally use a DO...LOOP UNTIL _KEYDOWN(27), but in this case i have an INPUT statement inside the loop, pausing it and making these useless. Any way that i can be waiting for a INPUT and if i press ESC go straight to a SYSTEM?

I'm very interested in your replies and critics about these. I'm always trying to learn.
Cheers, people!

JT-chem

(yeah, i know, my english is not very good, but that's another thing to keep learning! Cool! :-)

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Decimal to roman numbers converter
« Reply #1 on: August 28, 2020, 09:36:38 am »
2) As i learned from Terrie's class I ususally use a DO...LOOP UNTIL _KEYDOWN(27), but in this case i have an INPUT statement inside the loop, pausing it and making these useless. Any way that i can be waiting for a INPUT and if i press ESC go straight to a SYSTEM?

2 routes you might take;
 1. Use the input to control that, your range is 1 to 3999 so make 0 (or blank) the same as ESC key. Rather than giving the message
     that there is no roman numeral for 0

 2. Write your own input handler. Like a function where it returns 1 of 2 values, the first being -1 which would cause the program to
     exit, the other would be the value to convert to roman numerals.


Rather interesting program though!  If you want to further it some you might try to find a way to use arrays to control the output rather than using SELECT CASE.
Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Decimal to roman numbers converter
« Reply #2 on: August 28, 2020, 01:01:04 pm »
Welcome Juan Yamarit

May I ask what language you are using in program?

It works fine and you might like to add:
Code: QB64: [Select]
  1. _TITLE "Convert Decimal Number to Roman 1 to 3999"
for the title bar of screen.

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Decimal to roman numbers converter
« Reply #3 on: August 28, 2020, 01:20:33 pm »
Welcome to the forum Juan! Great little app you made there. I made something similar back in the 1990's but I think mine was just a graph for people to convert it in their heads. If you remove the INPUT command and go with INKEY$ then I suggest adding a _LIMIT 20 command right after Line 7 at the start of your DO/LOOP because the INPUT command slows down the computer processing which is good. Without that, the CPU usage would be very high, which you can see in your Windows Task Manager (if you use Windows). _LIMIT 20 slows it down to 20 cycles a second for the whole program. You can use any number, larger programs would need 100, or even larger ones might need 1000, etc. The most I've ever used was 2000. And then there's some programs, which need the full strength of the CPU (which is very uncommon) and those times you just don't use _LIMIT. But like I said, if you keep the INPUT in your LOOP, you don't need it, because INPUT does it's own slowing down.

Offline Juan Tamarit

  • Newbie
  • Posts: 53
    • View Profile
Re: Decimal to roman numbers converter
« Reply #4 on: August 28, 2020, 09:17:21 pm »
Thank you for the warm welcome and suggestions!

I'm an argetinian, so the program is written in spanish.

I'll keep a bit more on the Terrie's Ritchies Course, and i will come back over this program with these suggestions. The array sounds interesting. I also was thinking if it was posible to use DATA...READ, or maybe reading a .txt file. But i agree that the CASE SELECT...END CASE looks awfull, was just a very BASIC way to do it. I came in this programming stuff after playing TIS-100, were my rule "make it work first, then optimize".

I'll set the INKEY$ ways soon, i just wondered if can be done simply with INPUT, but you guys are right, untill ENTER is pressed the program is paused, no chance this way.

No title or too many fancy thisng for the moment, but it can be more user friendly. Im more focused at start on a fully operational, clean code program, then we lit the fireworks. XD
The idea would actually be to make a function/snippet that other people of the community can use inside they own programs.

The funny part is gonna be make it work the opposite way: ROMAN in > INTEGER out hehehe

Again thenk you, and sorry for my english. (feel free to correct me on this as well if you like)


Offline Juan Tamarit

  • Newbie
  • Posts: 53
    • View Profile
Re: Decimal to roman numbers converter
« Reply #5 on: August 28, 2020, 10:39:01 pm »
Ok, I tried the following:

Code: QB64: [Select]
  1. DATA "","I","II","III","IV","V","VI","VII","VIII","IX","","X","XX","XXX","XL","L","LX","LXX","LXXX","XC","","C","CC","CCC","CD","D","DC","DCC","DCCC","CM","","M","MM","MMM"
  2. DIM resultPieces$(3, 9)
  3. '
  4. '
  5. FOR i% = 0 TO 3
  6.     FOR ii% = 0 TO 9
  7.         READ resultPieces$(i%, ii%)
  8.     NEXT ii%
  9. NEXT i%

And I'm getting a "Unhandled Error #4: Out of DATA

I'm missing something here? have to confess that never used DATA...READ before, but looks cleany to me

'-------------- * EDIT * --------------

Sorry, posted before activating the other brain cell, i already got the thing working

Code: QB64: [Select]
  1. FOR i% = 0 TO 3
  2.     IF i% < 3 THEN
  3.         FOR ii% = 0 TO 9
  4.             READ resultPieces$(i%, ii%)
  5.         NEXT ii%
  6.     ELSE
  7.         FOR ii% = 0 TO 3
  8.             READ resultPieces$(i%, ii%)
  9.         NEXT ii%
  10.     END IF
  11. NEXT i%
« Last Edit: August 28, 2020, 10:47:49 pm by Juan Tamarit »

Offline Juan Tamarit

  • Newbie
  • Posts: 53
    • View Profile
Re: Decimal to roman numbers converter
« Reply #6 on: August 29, 2020, 01:36:35 am »
Couldn't sit on class today at Terrie's, this code was coming back to me, so we struggled each other a bit more for today

V 1.1 includes:
-set as a function
-array to avoid the CASE SELECT...END SELECT stataments (man... those were really awfull)
-smaller window
-title
-instructions are shown in the program
-no INKEY$ or _LIMIT used, tooked the "zero exit option"
-program warns if conversion can't be made
-sucesful conversion on green, unsuccesfull on red
-goodbye message

Code: QB64: [Select]
  1. '--------------* Setup *--------------
  2. DATA "","I","II","III","IV","V","VI","VII","VIII","IX","","X","XX","XXX","XL","L","LX","LXX","LXXX","XC","","C","CC","CCC","CD","D","DC","DCC","DCCC","CM","","M","MM","MMM"
  3.  
  4. DIM SHARED resultPieces$(3, 9)
  5.  
  6. FOR i% = 0 TO 3
  7.     IF i% < 3 THEN
  8.         FOR ii% = 0 TO 9
  9.             READ resultPieces$(i%, ii%)
  10.         NEXT ii%
  11.     ELSE
  12.         FOR ii% = 0 TO 3
  13.             READ resultPieces$(i%, ii%)
  14.         NEXT ii%
  15.     END IF
  16. NEXT i%
  17.  
  18. SCREEN _NEWIMAGE(250, 96, 32)
  19.  
  20. _TITLE "Arabic to Roman Converter"
  21.  
  22. CONST RED = _RGB32(255, 0, 0)
  23. CONST WHITE = _RGB32(255, 255, 255)
  24. CONST GREEN = _RGB32(0, 255, 0)
  25.  
  26. LOCATE 4, 1
  27.  
  28. '--------------* Program *--------------
  29.     COLOR WHITE
  30.     PRINT "Give me a number from 1 to 3999"
  31.     PRINT "      Enter 0 to leave"
  32.     INPUT "          > ", num%
  33.     CLS
  34.     PRINT num%; "= "; turnIntegerToRoman$(num%)
  35.     PRINT
  36. LOOP UNTIL num% = 0
  37. sayGoodbye
  38.  
  39. '--------------* Functions *--------------
  40. FUNCTION turnIntegerToRoman$ (inputNumber%)
  41.  
  42.     numberAsString$ = LTRIM$(STR$(inputNumber%))
  43.     IF inputNumber% > 0 AND inputNumber% < 4000 THEN
  44.         digits% = LEN(numberAsString$)
  45.         REDIM tmpArray%(digits%)
  46.         REDIM subResult$(digits%)
  47.         FOR i% = 0 TO digits% - 1
  48.             tmpArray%(i%) = VAL(MID$(numberAsString$, digits% - i%, 1))
  49.             subResult$(i%) = resultPieces$(i%, tmpArray%(i%))
  50.             result$ = subResult$(i%) + result$
  51.         NEXT i%
  52.         COLOR GREEN
  53.         turnIntegerToRoman$ = result$
  54.     ELSE
  55.         COLOR RED
  56.         turnIntegerToRoman$ = "I can't convert " + numberAsString$
  57.     END IF
  58.  
  59.  
  60. '--------------* Subroutines *--------------
  61. SUB sayGoodbye ()
  62.  
  63.     CLS
  64.     COLOR RED
  65.     LOCATE 3, 7
  66.     PRINT CHR$(3)
  67.     LOCATE 3, 26
  68.     PRINT CHR$(3)
  69.     COLOR GREEN
  70.     LOCATE 3, 9
  71.     PRINT "Have a nice day!"
  72.  

I really had a lot of fun doing this! =) Any other suggestions? I tried to set the DATA inside the function but didnt worked for a second request, and collapse came (first one works). Any way to improve this?

'------------* EDIT *-----------
forgotten feature: IT'S IN ENGLISH! XD
« Last Edit: August 29, 2020, 01:48:11 am by Juan Tamarit »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Decimal to roman numbers converter
« Reply #7 on: August 29, 2020, 02:05:22 pm »
READ can only be used once on the DATA unless you also use the RESTORE <name> command. Here is an example, let's say I want to have data for every day of the week, and want to use it a second time. <name> is a name you want to use right before the DATA lines, like in my example below I use weekdays. Copy/Paste my code below to QB64 so you can see what it does and learn by it. DATA can also use numbers for variables, like READ A and then in the DATA lines it could be: DATA 1,2,3,4,5  without the quotation marks.

Code: QB64: [Select]
  1. FOR weeks = 1 to 2
  2. FOR days = 1 to 7
  3. READ day$
  4. PRINT day$
  5. NEXT days
  6. RESTORE weekdays
  7. NEXT weeks
  8. weekdays:
  9. DATA "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
  10.  



Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Decimal to roman numbers converter
« Reply #8 on: August 29, 2020, 02:58:38 pm »
Hey @Juan Tamarit

You got me curious. Roman to Decimal very doable.

 
Roman2Decimal Test.PNG

Offline Juan Tamarit

  • Newbie
  • Posts: 53
    • View Profile
Re: Decimal to roman numbers converter
« Reply #9 on: August 29, 2020, 06:13:36 pm »
Nice! Reversing the program with INSTR ? I WANNA SEE THAT CODE! XD

We should get them togheter, make two separate functions, and a starting menu to select mode: arabic>roman OR roman>arabic

INKEY$ could get on the spotlight at that point...

We should also do some cheking is case user miss-spell the roman number on the string variable you gettin. Things like IC or MIMX

SierraKen: when you say <name> you mean something like a <label>, like in a GOTO ?

Nice to meet you guys! You are cool people! =)
« Last Edit: August 29, 2020, 06:22:09 pm by Juan Tamarit »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Decimal to roman numbers converter
« Reply #10 on: August 29, 2020, 07:14:39 pm »
Quote
We should also do some cheking is case user miss-spell the roman number on the string variable you gettin. Things like IC or MIMX

Yes the way my converter code works with 0 checking, you can get 3999 like this IMMMM or I before any of the M because whenever it finds a lesser letter value before a greater (going left to right) that value will be subtracted to total.  You could do this for 344 = IVLCDM (I just checked) ;(

We could maybe do rebuses with this kind of math and letters! LIVID = 553


Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Decimal to roman numbers converter
« Reply #11 on: August 29, 2020, 08:41:48 pm »
Juan yes, just a label like GOTO. You can see it in my example. :)

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Decimal to roman numbers converter
« Reply #12 on: August 30, 2020, 12:11:29 am »
Update:

By far and away the hardest part of this whole deal is checking the Roman Numeral strings for the proper order of letters. I whipped through my own version of converting decimals to Roman then spent rest of night checking. One last run through check tomorrow with fresh eyes and I will post code for comparisons.

Offline Juan Tamarit

  • Newbie
  • Posts: 53
    • View Profile
Re: Decimal to roman numbers converter
« Reply #13 on: August 30, 2020, 12:36:28 am »
I was thinkg in cheking with INST using the DATA on backwars as searchString$

First look for MMM, if not find look for MM, if not find look for M, if not find look for <null>, look for CM, if not found look for DCCC... iterate

Right now im working on the menu and INKEY$ stuff. I'm a bit newbie on this one but im experimenting, soon i'll find the answer

Back to the DATA thing: can the data be cleared from RAM by some order? I think that a good function should load the data, use it and send the answer, and then leave the data occupied free for other things that may be happening

« Last Edit: August 30, 2020, 12:59:50 am by Juan Tamarit »

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Decimal to roman numbers converter
« Reply #14 on: August 30, 2020, 01:17:16 am »
Back to the DATA thing: can the data be cleared from RAM by some order? I think that a good function should load the data, use it and send the answer, and then leave the data occupied free for other things that may be happening

Well if you are loading the data into an array you could just ERASE array. then you have to RESTORE the data to read it again.

DIM SHARED ROMANNUMERALS(27)
MyData:
Data M,MM,MMM,MMMM,C,L,D,X,V,I,blah,blah,blah
'load the data into the ROMANNUMERALS array
'use it
ERASE ROMANNUMERALS
RESTORE MyData

That would allow you to reload the data over and over.
Though If you load it into an array just reuse the array. no need to clear it out to be reloaded again. Lets face it this program is not sucking up the memory like a vampire(one hopes). So no need to worry about it.
Granted after becoming radioactive I only have a half-life!