+ Reply to Thread
Results 1 to 2 of 2

Thread: Arabic <=> Roman numbers

  1. #1

    Angry Arabic <=> Roman numbers

    Som sa rozhodol, že vám tu niečím prispejem - som sa hral s jednou úlohou. Samozrejme, že to ako správny egoista nerobím nezištne, ale očakávam, že mi tu niekto vynadá aký je to trápny kód a napíše lepšie riešenie, z ktorého sa budem môcť priučiť, a ktoré budem môcť prekonávať
    Code:
    /*
     * Súbor: aRRa.c
     * Dátum: 14.8.2009
     * Autor: m-> 29
     * Názov: Prevod číslic
     * Popis: Prevádza čísla medzi arabským a rímskym zápisom.
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    #define ROMAN_SIZE 16
    #define ROMAN_MAX 3999
    
    typedef struct {
       unsigned value;
       char str[ROMAN_SIZE];
    } roman_t;
    
    enum romeDigits {I, V, X, L, C, D, M};
    
    const struct { unsigned value; char c; } romeDigits[] = {
       [I] = {1,    'I'},
       [V] = {5,    'V'},
       [X] = {10,   'X'},
       [L] = {50,   'L'},
       [C] = {100,  'C'},
       [D] = {500,  'D'},
       [M] = {1000, 'M'},
    };
    
    /**
     * Prevedie číslo z arabskej do rímskej sústavy.
     */
    roman_t roman(int x) {
       if(x < 0) { return (roman_t) {-1, "NaRN"}; } // Not a Roman Number
       if(x == 0) { return (roman_t) {0, "nullae"}; }  // zero
       if(x > ROMAN_MAX) { return (roman_t) {-1, "infinity"}; } // !!! infinity
    
       roman_t result = {
          .value = x,
          .str = "",
       };
       char *str = (char *)&result.str;
    
       unsigned y = 1,
                digit = 0,
                order = 0;
    
       while(x/y > 10) {
          y *= 10;
          order += 2;
       }
    
       while(x > 0) {
          digit = x/y;
          x %= y;
          y /= 10;
    
          if(digit <= 3) {
             for(unsigned i=0; i<digit; i++) {
                *str++ = romeDigits[order].c;
             }
          }
          else if(digit == 4) {
             *str++ = romeDigits[order].c;
             *str++ = romeDigits[order+1].c;
          }
          else if(digit <= 8) {
             *str++ = romeDigits[order+1].c;
             for(unsigned i=5; i<digit; i++) {
                *str++ = romeDigits[order].c;
             }
          }
          else if(digit == 9) {
             *str++ = romeDigits[order].c;
             *str++ = romeDigits[order+2].c;
          }
          order -= 2;
       }
    
       return result;
    }
    
    static int romeChar2digit(char c) {
       switch(toupper(c)) {
          case '\0': return 0;
          case 'I':  return 1;
          case 'V':  return 5;
          case 'X':  return 10;
          case 'L':  return 50;
          case 'C':  return 100;
          case 'D':  return 500;
          case 'M':  return 1000;
          default:   return -1;
       }
    }
    
    int arabic(const char *str) { // !!! CLL != 200
       int result = 0, max = romeDigits[M].value;
       int digits[ROMAN_SIZE] = {0};
    
       for(unsigned i=0; str[i] != '\0'; i++) {
          if((digits[i] = romeChar2digit(str[i])) == -1) { return -1; }
       }
    
       for(unsigned i=0; digits[i]; i++) {
          if(digits[i] < digits[i+1] && digits[i+1]/digits[i] != 5 && digits[i+1]/digits[i] != 10) { return -1; }
          if(str[i]==str[i+1] && str[i+2]==str[i+3] && str[i]==str[i+2] && str[i]==str[i+4]) { return -2; }
          if(digits[i] > max) { return -3; }
          if(digits[i]==digits[i+1] && (digits[i]+digits[i+1]==romeDigits[X].value || digits[i]+digits[i+1]==romeDigits[C].value || digits[i]+digits[i+1]==romeDigits[M].value)) { return -4; }
    
          if(digits[i] < digits[i+1]) {
             result = result - digits[i] + digits[i+1];
             if(digits[i+1] > max) { return -3; }
             max = (unsigned)digits[i++] >> 1;
          }
          else {
             result += digits[i];
             max = digits[i+1];
          }
       }
    
    //   if(strcmp(roman(result).str, str) != 0) { return -29; }
    
       return result;
    }
    
    int main(void) {
    //   unsigned input = 0;
       char romeNum[ROMAN_SIZE];
       FILE *fin = fopen("data.txt", "r");
       while(fscanf(fin, "%16[IVXLCDMivxlcdm]", romeNum) == 1) {
          fgetc(fin);
    //    scanf("%u", &input);
    //    puts(roman(input).str);
    
          printf("%15s = %d\n", romeNum, arabic(romeNum));
       }
    
       return EXIT_SUCCESS;
    }
    Inak, nejako mi nefunguje nahrávanie súborov - neviem či je to vo mne alebo vo vás, tak sa na to mrknite
    Všetci chcú vaše dobro. Nedajte si ho vziať!!

  2. #2

    Re: Arabic <=> Roman numbers

    no nahravani souboru je zakazano

+ Reply to Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts