इष्टतम लघु-हाथ रोमन अंक जनरेटर


21

लक्ष्य:
एक फ़ंक्शन लिखें जो संख्या को इनपुट के रूप में लेता है और आउटपुट के रूप में उस संख्या के लिए एक शॉर्ट-हैंड रोमन अंक लौटाता है।

रोमन अंक चिह्न:

Symbol  Value
I       1
V       5
X       10
L       50
C       100
D       500
M       1,000

उदाहरण के लिए कि जब मेरा कहना है कि मैं "शॉर्ट-हैंड रोमन अंक" कहता हूं, तो आइए 1983 के प्रतिनिधित्व के लिए एक रोमन अंक खोजने पर विचार करें, क्योंकि यह वह वर्ष है जब मैं पैदा हुआ था। एक विकल्प यह है कि यह सामान्य तरीके से किया जाए (10 अक्षर):

1983 = MCMLXXXIII = (१००० - १०० + १००० + ५० + ३० + ३)

दूसरा विकल्प यह है कि इसे शॉर्ट-हैंड तरीके से किया जाए (6 अक्षर):

1983 = एमएक्सवीआईएम = (1000 - (10 + 10) + 1000 + 3)

क्या आप इसका मतलब जानते है?!?!!?? अगर मैं रोमन होता तो मैं हर बार अपने जन्म की तारीख लिखी 4 पात्रों को बचा सकता था! हुर्रे हुर्रे!!

हालांकि, इससे पहले कि मैं उत्तेजना में खुद से आगे निकल जाऊं, मेरे पास लिखने का सवाल है, इसलिए मुझे शायद शॉर्ट-हैंड रोमन अंक नियमों को परिभाषित करना चाहिए ताकि हम सभी एक ही पृष्ठ पर हों:

लघु-हाथ रोमन अंक नियम:

  1. हमेशा प्रतीकों को बाएं से दाएं पर तब तक विचार करें जब तक विचार करने के लिए अधिक वर्ण न हों।
  2. यदि वर्तमान प्रतीक के दाईं ओर कोई उच्च-मूल्यवान चिह्न नहीं हैं:
    • इस रोमन अंक के कुल भाग में वर्तमान चिन्ह का मान जोड़ें।
  3. यदि आपके द्वारा विचार किए जा रहे प्रतीक के दाईं ओर उच्च-मूल्यवान चिह्न हैं:
    • वर्तमान चिह्न के दाईं ओर सबसे उच्चतम मूल्यवान मान का पता लगाएँ
    • एक रोमन अंक के रूप में उस प्रतीक तक सभी वर्णों पर विचार करें
    • इन चरणों का उपयोग करके उस रोमन अंक के मूल्य की गणना करें
    • इस रोमन अंक के चल रहे कुल से उस रोमन अंक के मूल्य को घटाएं।
    • समूह पर विचार करने के बाद अगले प्रतीक पर जाएं
  4. प्रत्येक रोमन अंक में कम से कम 1 प्रतीक होना चाहिए।
  5. बस! इन नियमों का पालन करने पर कुछ भी स्वीकार किया जाएगा!

उदाहरण:

IIIIV = (-(1+1+1+1)+5) = 1  //Don't ask me why you'd want to do this!  

VVX = (-(5+5) + 10) = 0  //Who said you couldn't represent 0 with roman numerals?!!?

VVXM = (-(-(5+5) + 10) + 1000) = 1000  //Again...don't ask me why you'd want to do this!

MXIIXMI = (1000-(10-(1+1)+10)+1000+1) = 1983  //Ahhh...such a great year :)

प्रश्न नियम:

  1. एक फ़ंक्शन बनाएं जो इनपुट के रूप में एक एकल संख्या लेता है और उपरोक्त नियमों का उपयोग करके आउटपुट के रूप में उस संख्या के लिए एक रोमन अंक लौटाता है। इस फ़ंक्शन के कोडगोल्फस्कॉर की गणना करें ।

    example input: 2011
    example possible output: MMXI
    another possible output: MMVVIVV     //(2000 + 10 - 4 + 5) 
    
  2. नियम 1 से अपने फ़ंक्शन का उपयोग करते हुए, -1000 (यह सही है, एक हजार) और 3000 के बीच का रोमन अंक उत्पन्न करें। फिर अपने कुलचक्र प्राप्त करने के लिए इन रोमन अंकों की वर्ण लंबाई का योग करें । यहाँ स्पष्ट करने के लिए कुछ छद्मकोश हैं:

    totalCharacterCount = 0;
    for(currentNumber = -1000; currentNumber <= 3000; currentNumber++){
        totalCharacterCount += getRomanNumeral(currentNumber).length;
    }
    return totalCharacterCount;
    
  3. फ़ाइनलकोर = कोडगॉल्फ़स्कोर + टोटलचैकरकाउंट

  4. सबसे कम अंतिम जीत जीत!

नोट: जैसे कुलचक्र गणना दस-हजारों + में होगी, वर्ण-लंबाई एल्गोरिथ्म सर्वोच्च प्राथमिकता होनी चाहिए। कोड-गोल्फ स्कोर सिर्फ टाई-ब्रेकर हैं यदि कई उपयोगकर्ता इष्टतम एल्गोरिदम या एल्गोरिदम पाते हैं जो एक दूसरे के करीब हैं।

गुड लक, और कल रात अपने MMXII समारोह में मज़े करो !!!


1
महान कार्य! हालाँकि, क्या आप एक उदाहरण दे सकते हैं कि एक नकारात्मक रोमन शॉर्टहैंड कैसा दिखता है? के DDDDMलिए खड़ा है -1000?
19

@pimvdb आपको मिल गया!
Briguy37

विशेष केस शून्य के बारे में एक प्रश्न: क्या ""शून्य के लिए अनुमति दी गई है या हमें इसका उपयोग करना है VVXया कुछ समान है?
हावर्ड

@ हॉवर्ड: महान सवाल, मैंने ऐसा नहीं सोचा था! मैंने रोमन अंक नियम 4 जोड़ा है जिसके लिए वह मामला स्पष्ट करता है।
Briguy37 20

1
"वर्तमान प्रतीक के दाईं ओर सबसे उच्चतम मूल्यवान मान का पता लगाएँ" - जो जीतता है, सबसे सही या उच्चतम मूल्य? यानी, IXV = -(-1 + 10) + 5 = -4(सबसे बड़ी जीत है), या IXV = -1 + 10 + 5 = 14(सर्वोच्च-मूल्यवान जीत)?
कीथ रान्डेल

जवाबों:


5

हास्केल, 25637 (= 268 + 25369) 26045 (= 222 + 25823)

r 0="VVX"
r n=s(zip[1000,500,100,50,10,5]"MDCLXV")n ξ
ξ='ξ'
s[]q f
 |q<0=s[](5-q)f++"V"
 |q<1=""
 |r<-q-1='I':s[]r f
s ω@((v,a):l)q f
 |q>=v,f/=a=a:s ω(q-v)ξ
 |f==a,γ<-'I':a:s l(q-v+1)ξ,η γ<η(s l q ξ)=γ
 |f==ξ,γ<-s ω(v-q)a++[a],η γ<η(s l q ξ)=γ
 |True=s l q ξ
η=length

उदाहरण के लिए इस्तेमाल किया जाएगा

GHCi> r 7
"VII"
GHCi> r 39
"XIL"
GHCi> r (-39)
"ICXLC"        --  "LLXILC" in my original version
GHCi> r 1983
"MXVIIM"
GHCi> r 259876
"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMCXXIVM"

आप सीधे के साथ लंबाई राशि का मूल्यांकन कर सकते हैं

GHCi> sum . map(length.r) $ [-1000..3000]
25369

जो एक मिनट के क्रम में कुछ लेता है।


5

C ++, कोड के 345 अक्षर, 25021 रोमन अंक अंक = 25366

int N[]={1,5,10,50,100,500,1000};int V(int s,int L){if(!L)return 0;int K=0,B,m=s%7+1;for(int k=1,b=7;k<L;k++,b*=7){if(s/b%7>=m){K=k;B=b;m=s/b%7;}}return K?V(s/B,L-K)-V(s%B,K):N[s%7]+V(s/7,L-1);}char r[99];char*f(int n){for(int L=1,B=7,i,j;1;L++,B*=7){for(i=0;i<B;i++){if(V(i,L)==n){for(j=0;j<L;j++){r[j]="IVXLCDM"[i%7];i/=7;}r[L]=0;return r;}}}}

एक ड्राइवर के साथ थोड़ा हटकर:

int N[]={1,5,10,50,100,500,1000};
int V(int s,int L){
  if(!L)return 0;
  int K=0,B,m=s%7+1;
  for (int k=1,b=7;k<L;k++,b*=7) {
    if(s/b%7>=m){K=k;B=b;m=s/b%7;}
  }
  return K ? V(s/B,L-K)-V(s%B,K) : N[s%7]+V(s/7,L-1);
}
char r[99];
char *f(int n){
  for(int L=1,B=7;1;L++,B*=7) {
    for(int i=0;i<B;i++) {
      if(V(i,L)==n){
        for(int j=0;j<L;j++) {
          r[j]="IVXLCDM"[i%7];i/=7;
        }
        r[L]=0;
        return r;
      }
    }
  }
}
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
  printf("%s\n", f(atoi(argv[1])));
}

Vकिसी दिए गए रोमन अंक स्ट्रिंग sकी संख्या के संख्यात्मक मान की गणना करता है L। स्ट्रिंग्स एन्कोडेड बेस 7 हैं (पहला अंक s 7% है, दूसरा अंक s / 7% 7, ...) है। प्रत्येक अंक I = 0, V = 1, ..., M = 6 के साथ एन्कोड किया गया है। मूल्यांकन करने के fलिए संभव रोमन अंक तार का एक क्रूर बल गणना Vकरता है n

रोमन अंक अंकों की कुल संख्या इष्टतम है। [-1000,3000] के लिए आवश्यक सबसे लंबा रोमन अंक 11 अंक (जैसे -827 = CMDDMLXXIII) है, जिसमें मेरी मशीन पर लगभग 5 मिनट लगते हैं।


एक क्षण प्रतीक्षा करें, जो निर्दिष्ट तरीके का व्यवहार नहीं करता है। आपका कार्यक्रम उदाहरण LMCLXXIIIके लिए उत्तर देता है -777। मुझे लगता है कि पढ़ा था के रूप में -50+1000-100+50+10+10+3 = 923 ≠ -777, केवल के साथ "सबसे दायीं ओर उच्च -valued" के बदले " उच्चतम " यह देता है -777। लेकिन यह वही था जो आपने टिप्पणियों में पूछा था!
को बंद कर दिया

@leftractionabout: बेशक आप सही हैं। मैं इसे ठीक कर दूंगा, लेकिन अभी समय नहीं ...
कीथ रान्डेल

@leftractionabout: ठीक है, सब ठीक हो गया।
कीथ रान्डेल

ठीक है। यह अब इष्टतम नहीं है , हालांकि (उदाहरण के VVVXIलिए -4जब IXVXवास्तव में छोटा होता है, जैसा कि मैंने अभी देखा) - लेकिन यह पूरी तरह से कानूनी है।
को बंद कर दिया

@leftractionabout: ठीक है, फिर से तय किया गया। उम्मीद है कि यह इस बार सही है ...
कीथ रान्डल

2

रूबी, 25987 (= 164 + 25823)

h=->i,d,v,k{i==0?'':i<v ?(a=h[v-i,x=d[1..-1],v/k,k^7]+d[0];i<0?a:(b=h[i,x,v/k,k^7];a.size<b.size ? a :b)):d[0]+h[i-v,d,v,k]}
r=->i{i==0?'DDM':h[i,'MDCLXVI',1000,2]}

आप rपरिणाम प्राप्त करने के लिए सीधे कॉल कर सकते हैं । निर्दिष्ट श्रेणी की उपज पर योग

> (-1000..3000).map{|i|r[i].size}.reduce &:+
25823

जो अन्य समाधानों के साथ इष्टतम राशि है।


0

C # 23537 (कोड +22898 वर्णों के 639 वर्ण)

class M
{
    public static string R(int n, int? s = new int?())
    {
        var r = "";
        var D = new Dictionary<int, string> {{ 1000, "M"}, { 900, "CM"},{ 800, "CCM"},{ 500, "D"}, { 400, "CD"},{ 300, "CCD"},{100, "C"}, {90, "XC"},{80, "XXC"},{50, "L"}, {40, "XL"}, {10, "X"}, {9, "IX"}, {8, "IIX"}, {5, "V"}, {4, "IV"},{1, "I"}};
        if (n == 0) return "VVX";
        if (n == -1) return "IIIIIIV";
        if (n < 0) return N(n * -1);

        foreach(int k in D.Keys)
        {
            if (s.HasValue && k > s) continue;

            while(k <= n)
            {
                n -= k; 
                r += D[k];
            }
        }

        return r;
    }

    public static string N(int n)
    {
        var D = new Dictionary<int, string> {{1, "I"}, {5, "V"}, {10, "X"}, {50, "L"}, {100, "C"}, { 500, "D"}, {1000, "M"}};

        int i = D.Keys.First(v => v >= n), m = D.Keys.Where(v => v < i).Max();

        return R(n + i, m) + D[i];
    }
}

की गणना करना:

Enumerable.Range(-1000, 3000).Sum(i => M.R(i).Length);


और आपका स्कोर क्या है?
उपयोगकर्ता अज्ञात
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.