कोड रोमनकरण


33

चुनौती किसी भी रोमन अंकों को अपनी चुनी हुई भाषा में मान्य कोड बनाने की है ।

उन्हें स्ट्रिंग्स या कुछ भी समान के अंदर दिखाई नहीं देना चाहिए , लेकिन किसी भी अन्य टोकन, शाब्दिक जैसे ( अरबी ) संख्या, वर्ण या स्ट्रिंग्स की तरह काम करें; या चर / विधि / फ़ंक्शन पहचानकर्ता, आदि।

उदाहरण के लिए, जावा में, निम्नलिखित को उसी तरह संकलित और चलाना होगा जैसे कि iइसके लिए आरंभ किया गया था 42:

int i = XLII;

अंकों की वास्तविक पार्सिंग द्वितीयक है, इसलिए आप चाहें तो एक पुस्तकालय का उपयोग कर सकते हैं, लेकिन यह एक लोकप्रियता प्रतियोगिता है, इसलिए रचनात्मकता को प्रोत्साहित किया जाता है।

आप किसी भी भाषा का उपयोग नहीं कर सकते हैं जो वास्तव में रोमन अंकों का उपयोग करता है, अगर ऐसी कोई चीज है।

सौभाग्य।


1
तो, हमें भाषा के विस्तार को लिखने की जरूरत है, जिससे एक नया निर्माण हो?
केंडल फ्रे

4
अगर मैं चाहता हूं तो मुझे शिकायत होगी, क्योंकि मैं जिन भाषाओं का उपयोग करता हूं, वे उस तरह से एक्स्टेंसिबल नहीं हैं, इसलिए मैं भी भाग नहीं ले सकता।
केंडल फ़्री

3
@KendallFrey स्रोत को संकलित और चलाना होगा। जावा के लिए, आप एक "संकलक" लिख सकते हैं जो स्रोत को संपादित करता है, फिर प्रोग्रामेटिक रूप से संकलित करता है । इस तरह के संकलन का एक तरीका Process
जस्टिन

1
ज्यादातर भाषाओं में बोरिंग लगता है। उदाहरण के लिए अजगर में मैं बस एक स्क्रिप्ट लिखूंगा astजो स्रोत को पार्स करने के लिए उपयोग करता है। एएसटी के शीर्ष पर 1 से 3999 तक रोमन अंकों की परिभाषा डालें। पूरी बात संकलित करें और इसे चलाएं। प्रक्रिया को संभालने के लिए कोड लिखना केवल उबाऊ है।
बाकुरि

2
@ बकुरीउ और आपकी टिप्पणी भी उबाऊ है। यह एक लोकप्रियता प्रतियोगिता है, इसलिए आपको कुछ मजेदार करने की कोशिश करनी चाहिए। मुझे लगता है कि यहां कुछ अच्छे उत्तर हैं जो अधिक कल्पनाशील हैं (एक स्क्रिप्टिंग भाषा को संकलित करने की तुलना में)।
डेनियर

जवाबों:


40

सी

केवल इतने सारे रोमन अंक हैं, क्योंकि 4000 और उच्चतर में कोई मानक संकेतन नहीं है, और प्रीप्रोसेसर एक अद्भुत अपघटन उपकरण है, खासकर यदि आपको इस तथ्य से कोई समस्या नहीं है कि कोड में अपरिभाषित व्यवहार है।

enum{_
#define a_
#define d_
#define g_
#define j_
#define a(x)c(x)b
#define b(x)c(x)a
#define c(x)x,
#define d(x)f(x)e
#define e(x)f(x)d
#define f(x)m(a(x)(x##I)(x##II)(x##III)(x##IV)(x##V)(x##VI)(x##VII)(x##VIII)(x##IX))
#define g(x)i(x)h
#define h(x)i(x)g
#define i(x)m(d(x)(x##X)(x##XX)(x##XXX)(x##XL)(x##L)(x##LX)(x##LXX)(x##LXXX)(x##XC))
#define j(x)l(x)k
#define k(x)l(x)j
#define l(x)m(g(x)(x##C)(x##CC)(x##CCC)(x##CD)(x##D)(x##DC)(x##DCC)(x##DCCC)(x##CM))
#define m(x)n(x)
#define n(...)__VA_ARGS__##_
m(j()(M)(MM)(MMM))
};

इस से सभी रोमन अंकों को परिभाषित करता है Iकरने के लिए MMMCMXCIXगणन स्थिरांक के रूप में, प्लस _शून्य के रूप में (इच्छानुसार द्वारा प्रतिस्थापित किया जा सकता है)।


12
बिल्कुल शानदार, इसे अगले सी रिलीज़ (C2X?) के रूप में जोड़ने का प्रस्ताव <roman.h>! % R और% R प्रिंटफ प्रारूपों के साथ!

3
मैंने सोचा कि मुझे पता है कि प्रीप्रोसेसर का उपयोग कैसे करें, अब तक: | क्या आप इस उत्तर के न्यूनतम उपयोग उदाहरण के साथ अपना उत्तर अपडेट कर सकते हैं?
klingt.net

@YiminRong और scanfभी :) @ klingt.net मुझे यकीन नहीं है कि आप किस प्रकार का उदाहरण देख रहे हैं। एक काफी सरल होगाint main() { return MMMCMXCIX - M - M - M - CM - XC - IX; }
hvd

मुझे यह विचार पसंद है, लेकिन जब परिभाषित व्यवहार काफी सरल था, तो आपने अपरिभाषित व्यवहार के साथ जाने का विकल्प क्यों चुना? न्याय नहीं, सिर्फ जिज्ञासु?
CasaDeRobison

1
@CasaDeRobison मनोरंजन के लिए, मुख्य रूप से। मुझे यह पसंद है क्योंकि यह प्रीप्रोसेसिंग समय पर अपरिभाषित व्यवहार के बहुत कम मामलों में से एक है जिसे वर्तमान संकलक द्वारा त्रुटि के रूप में चिह्नित नहीं किया गया है, और भविष्य में इसकी संभावना नहीं होगी। मैं कभी भी उस कोड में ऐसा कुछ नहीं लिखता जो उपयोगी होने के लिए हो, लेकिन यहां पोस्ट किया गया कोड उपयोगी होने के लिए नहीं है, इसलिए इसे आज़माने के लिए बेहतर अवसर क्या है?
hvd

15

माणिक

def Object.const_missing(const)
  i = const.to_s
  if i =~ /^[IVXLCDM]+$/
    #http://codegolf.stackexchange.com/questions/16254/convert-arbitrary-roman-numeral-input-to-integer-output
    %w[IV,4 IX,9 XL,40 XC,90 CD,400 CM,900 I,1 V,5 X,10 L,50 C,100 D,500 M,1000].map{|s|k,v=s.split ?,;i.gsub!(k,?++v)}
    eval(i)
  else
    super
  end
end

किसी भी (अपरकेस) रोमन अंकों को अब उनके दशमलव समकक्षों की तरह पार्स किया जाएगा। एकमात्र मुद्दा यह है कि वे अभी भी असाइन करने योग्य हैं: आप कर सकते हैं X = 9, लेकिन नहीं 10 = 9। मुझे नहीं लगता कि इसे ठीक करने का कोई तरीका है।


1
यह पूर्ण है। असाइनमेंट बात एक मुद्दा नहीं है; आप सभी प्रकार की बेवकूफी भरी चीजों को करने के लिए असाइनमेंट का उपयोग कर सकते हैं।
डानिएरो

12

जावास्क्रिप्ट (ES6)

Proxyरोमन अंकों को पकड़ने के लिए उपयोग करें ।

पर Firefox (नवीनतम) में परीक्षण योग्य JSFiddle
Proxyकार्यान्वयन टूट जाने के बाद से क्रोम (ट्रेसेर के साथ) में परीक्षण योग्य नहीं है।

// Convert roman numeral to integer.
// Borrowed from http://codegolf.stackexchange.com/a/20702/10920
var toDecimal = (s) => {
  var n = 0;
  var X = {
    M: 1e3, CM: 900, D: 500, CD: 400, C: 100, XC: 90, 
    L: 50,  XL: 40,  X: 10,  IX: 9,   V: 5,   IV: 4,  I: 1
  };

  s.replace(/[MDLV]|C[MD]?|X[CL]?|I[XV]?/g, (d) => n += X[d]);
  return n;
};

// Whether a string is a valid roman numeral.
var isRoman = (s) => s.match(/^[MDCLXVI]+$/);

// Profixy global environment to catch roman numerals.
// Since it uses `this`, global definitions are still accessible.
var romanEnv = new Proxy(this, {
  get: (target, name) => isRoman(name) ? toDecimal(name) : target[name],
  set: (target, name, value) => isRoman(name) ? undefined : (target[name] = value),
  has: (target, name) => isRoman(name) || name in target,
  hasOwn: (target, name) => name in target
});

उपयोग:

with (romanEnv) {
  var i = MIV + XLVIII;
  console.log(i); // 1052
}

10

C & C ++ (अपडेट किया गया उत्तर)

जैसा कि एक टिप्पणी में देखा गया, मेरे मूल समाधान में दो समस्याएं थीं:

  1. वैकल्पिक पैरामीटर केवल C99 और बाद के भाषा परिवार के मानकों में उपलब्ध हैं।
  2. Enum परिभाषा में ट्रेलिंग कॉमा भी C99 और बाद के लिए विशिष्ट है।

चूंकि मैं चाहता था कि मेरा कोड पुराने प्लेटफार्मों पर काम करने के लिए जितना संभव हो उतना सामान्य हो, मैंने इसे एक और छुरा लेने का फैसला किया। यह पहले की तुलना में लंबा है, लेकिन यह C89 / C90 संगतता मोड पर सेट किए गए कंपाइलर और प्रीप्रोसेसर पर काम करता है। सभी मैक्रोज़ को स्रोत कोड में उपयुक्त संख्या में तर्क दिए गए हैं, हालांकि कभी-कभी वे मैक्रोज़ "विस्तार" कुछ नहीं करते हैं।

दृश्य C ++ 2013 (उर्फ संस्करण 12) लापता मापदंडों के बारे में चेतावनी देता है, लेकिन न तो mcpp (एक खुला स्रोत प्रीप्रोसेसर जो मानक के उच्च अनुपालन का दावा करता है) और न ही 4.8.1.1 (-std = iso9899 के साथ: 1990-थप्टैटिक-एरर स्विच) एक प्रभावी खाली तर्क सूची के साथ उन मैक्रो इनवोकेशन के लिए चेतावनी या त्रुटियां।

प्रासंगिक मानक (ANSI / ISO 9899-1990, 6.8.3, मैक्रो रिप्लेसमेंट) की समीक्षा करने के बाद, मुझे लगता है कि पर्याप्त अस्पष्टता है कि इसे गैर-मानक नहीं माना जाना चाहिए। "एक फ़ंक्शन-जैसे मैक्रो के आह्वान में तर्कों की संख्या मैक्रो परिभाषा में मापदंडों की संख्या से सहमत होगी ..."। जब तक मैक्रो को लागू करने के लिए आवश्यक कोष्ठक (और कई मापदंडों के मामले में अल्पविराम) के रूप में एक खाली तर्क सूची को शामिल करने के लिए प्रतीत नहीं होता है

अनुगामी अल्पविराम की समस्या के लिए, जो कि एक अतिरिक्त पहचानकर्ता को संश्लिष्ट में जोड़कर हल किया जाता है (मेरे मामले में, MMMM जो कि पहचानकर्ता के लिए 3999 का पालन करने के लिए कुछ भी उतना ही उचित लगता है, भले ही वह रोमन अंतिम क्रम अनुक्रमण के स्वीकृत नियमों का पालन न करता हो। ठीक ठीक)।

एक छोटे से क्लीनर समाधान में एनम को हिलाना और एक अलग हेडर फाइल को सपोर्ट करना शामिल होगा जैसा कि एक टिप्पणी में कहीं और निहित था, और मैक्रो नामों के अपरिभाषित का उपयोग करने के तुरंत बाद उनका उपयोग किया गया ताकि नाम स्थान को प्रदूषित करने से बचें। बेहतर मैक्रो नामों को बेशक चुना जाना चाहिए, लेकिन यह कार्य के लिए पर्याप्त है।

मेरे मूल समाधान के बाद मेरा अद्यतन समाधान:

#define _0(i,v,x)
#define _1(i,v,x) i
#define _2(i,v,x) i##i
#define _3(i,v,x) i##i##i
#define _4(i,v,x) i##v
#define _5(i,v,x) v
#define _6(i,v,x) v##i
#define _7(i,v,x) v##i##i
#define _8(i,v,x) v##i##i##i
#define _9(i,v,x) i##x

#define k(p,s) p##s,
#define j(p,s) k(p,s)
#define i(p) j(p,_0(I,V,X)) j(p,_1(I,V,X)) j(p,_2(I,V,X)) j(p,_3(I,V,X)) j(p,_4(I,V,X)) j(p,_5(I,V,X)) j(p,_6(I,V,X)) j(p,_7(I,V,X)) j(p,_8(I,V,X)) j(p,_9(I,V,X))
#define h(p,s) i(p##s)
#define g(p,s) h(p,s)
#define f(p) g(p,_0(X,L,C)) g(p,_1(X,L,C)) g(p,_2(X,L,C)) g(p,_3(X,L,C)) g(p,_4(X,L,C)) g(p,_5(X,L,C)) g(p,_6(X,L,C)) g(p,_7(X,L,C)) g(p,_8(X,L,C)) g(p,_9(X,L,C))
#define e(p,s) f(p##s)
#define d(p,s) e(p,s)
#define c(p) d(p,_0(C,D,M)) d(p,_1(C,D,M)) d(p,_2(C,D,M)) d(p,_3(C,D,M)) d(p,_4(C,D,M)) d(p,_5(C,D,M)) d(p,_6(C,D,M)) d(p,_7(C,D,M)) d(p,_8(C,D,M)) d(p,_9(C,D,M))
#define b(p) c(p)
#define a() b(_0(M,N,O)) b(_1(M,N,O)) b(_2(M,N,O)) b(_3(M,N,O))

enum { _ a() MMMM };

#include <stdio.h>

int main(int argc, char** argv)
{
    printf("%d", MMMCMXCIX * MMMCMXCIX);
    return 0;
}

मूल उत्तर (जिसे पहले छह अपवोट प्राप्त हुए थे, इसलिए यदि कोई भी इसे फिर से नहीं बढ़ाता है, तो आपको यह नहीं सोचना चाहिए कि मेरे अपडेट किए गए समाधान को अपवोट मिला है):

पहले के उत्तर के रूप में एक ही भावना में, लेकिन केवल परिभाषित व्यवहार का उपयोग करके पोर्टेबल होना चाहिए (हालांकि विभिन्न वातावरण हमेशा प्रीप्रोसेसर के कुछ पहलुओं पर सहमत नहीं होते हैं)। कुछ मापदंडों को वैकल्पिक मानता है, दूसरों को अनदेखा करता है, इसे प्रीप्रोसेसरों पर काम करना चाहिए जो __VA_ARGS__सी ++ सहित मैक्रो का समर्थन नहीं करते हैं , यह अप्रत्यक्ष मैक्रो का उपयोग करता है ताकि यह सुनिश्चित हो सके कि टोकन चिपकाने से पहले मापदंडों का विस्तार किया जाता है, और अंत में यह छोटा होता है और मुझे पढ़ना आसान लगता है हालांकि यह अभी भी मुश्किल है और शायद पढ़ने में आसान नहीं है , बस आसान है):

#define g(_,__) _, _##I, _##II, _##III, _##IV, _##V, _##VI, _##VII, _##VIII, _##IX,
#define f(_,__) g(_,)
#define e(_,__) f(_,) f(_##X,) f(_##XX,) f(_##XXX,) f(_##XL,) f(_##L,) f(_##LX,) f(_##LXX,) f(_##LXXX,) f(_##XC,)
#define d(_,__) e(_,)
#define c(_,__) d(_,) d(_##C,) d(_##CC,) d(_##CCC,) d(_##CD,) d(_##D,) d(_##DC,) d(_##DCC,) d(_##DCCC,) d(_##CM,)
#define b(_,__) c(_,)
#define a       b(,) b(M,) b(MM,) b(MMM,)
enum { _ a };

1
+1, लेकिन ध्यान दें कि खाली मैक्रो तर्कों का उपयोग, और एन्यूमरेटर सूची के अंत में अल्पविराम, C99 और C ++ 11 की नई विशेषताएं हैं, और C99 और C ++ 11 दोनों समर्थन करते हैं __VA_ARGS__
hvd

अगर तुम ठीक नहीं हो तो डांग! मुझे लगता है कि मैं इसे इस समय एक्सटेंशन के रूप में इस्तेमाल कर रहा हूं। ठीक है। :)
कासाडेयोबिन

8

आम लिस्प

निम्नलिखित एक विस्तृत व्याख्या है कि मैंने किस प्रकार एक मैक्रो बनाया है जिसका उपयोग आप इस तरह कर सकते हैं:

(roman-progn
  (+ XIV XXVIII))

जब एक मैक्रो को कॉमन लिस्प में बुलाया जाता है, तो यह मूल रूप से एक फ़ंक्शन की तरह काम करता है, केवल यह कि तर्क पहले प्राप्त होते हैं मूल्यांकन होते हैं। दरअसल, चूंकि कॉमन लिस्प कोड सिर्फ डेटा है, जो हम प्राप्त करते हैं वह एक अप्रकाशित वाक्यविन्यास ट्री का प्रतिनिधित्व करने वाली एक (नेस्टेड) ​​सूची है जिसे हम जो चाहते हैं, कर सकते हैं और यह संकलन-समय में किया जाता है।

हेल्पर कार्य करता है

योजना का पहला चरण इस पेड़ को लेना है और इसे रोमन न्यूमेरिएंस की तरह दिखने वाली किसी भी चीज के लिए स्कैन करना है। यह लिस्प और सभी होने के नाते, चलो इसे कुछ हद तक कार्यात्मक रूप से करने की कोशिश करते हैं: हमें एक फ़ंक्शन की आवश्यकता है जो एक पेड़ का गहरा आघात करेगा और प्रत्येक वस्तु को searchpलौटाएगा जिसके लिए एक प्रदान फ़ंक्शन सही है। यह एक (अर्ध) पूंछ-पुनरावर्ती भी है।

(defun deep-find-all (searchp tree &optional found)
  (if (null tree)
    found
    (let* ((item (car tree))
           (new-found (if (consp item)
                        (deep-find-all searchp item found)
                        (if (funcall searchp item)
                          (cons item found)
                          found))))

      (deep-find-all searchp (cdr tree) new-found))))

फिर रोशन्टा कोड के सौजन्य से रोमन अंकों को पार्स करने के लिए कुछ कोड :

(defun mapcn (chars nums string)
  (loop as char across string as i = (position char chars) collect (and i (nth i nums))))

(defun parse-roman (R)
  (loop with nums = (mapcn "IVXLCDM" '(1 5 10 50 100 500 1000) R)
        as (A B) on nums if A sum (if (and B (< A B)) (- A) A)))

वास्तविक मैक्रो

हम सिंटैक्स ट्री ( body) लेते हैं , इसे हमारी गहरी-खोज-सभी प्रक्रिया के साथ खोजते हैं और किसी भी तरह रोमन अंकों को बनाते हैं जो हम पाते हैं, उपलब्ध हैं।

(defmacro roman-progn (&body body)
  (let* ((symbols (deep-find-all (lambda (sym)
                                   (and
                                     (symbolp sym)
                                     (loop for c across (string sym)
                                           always (find c "IVXLCDM")))) body))
         (parsed-romans (mapcar (lambda (sym)
                                  (list sym (parse-roman (string sym)))) symbols)))

    (if parsed-romans
      `(let (,@parsed-romans)
         ,@body)  
      `(progn
         ,@body))))

तो, क्या है 1 + 2 + 3 + (4 * (5 + 6)) + 7?

(roman-progn
  (+ I II III (* IV (+ V VI)) VII))
=> 57

और यह देखने के लिए कि मैक्रो के आह्वान पर वास्तव में क्या हुआ:

(macroexpand-1 +)
=> (LET ((VII 7) (VI 6) (V 5) (IV 4) (III 3) (II 2) (I 1))
   (+ I II III (* IV (+ V VI)) VII))

7

लुआ

setmetatable(_G, {
    __index = function(_, k)
        if k:match"^[IVXLCDM]*$" then
            local n = 0
            for _, v in ipairs{{IV = 4}, {IX = 9}, {I = 1}, {V = 5}, {XL = 40}, {X = 10}, {XC = 900}, {CD = 400}, {CM = 900}, {C = 100}, {D = 500}, {M = 1000}} do
                local p, q = next(v)
                local r
                k, r = k:gsub(p, "")
                n = n + r * q
            end
            return n
        end
    end
})

वैश्विक तालिका के लिए बस एक वापसी __index। Gsub का उपयोग करने वाला वास्तविक रूपांतरण जितना मैंने सोचा था, उससे कहीं अधिक सुंदर निकला।


5

परिशिष्ट भाग

मैंने C एक का पालन करने की कोशिश की, लेकिन मुझे यह समझ में नहीं आया। तो मैंने इसे इस तरह किया:

/strcat{
    2 copy length exch length add string % 1 2 3 
    3 2 roll % 2 3 1 
    2 copy 0 exch putinterval % 2 3 1 
    2 copy length % 2 3 1 3 n(1)
    5 4 roll putinterval % 3 1 
    pop 
}def
/S{
    dup length string cvs 
} def 
[
/u {/ /I /II /III /IV /V /VI /VII /VIII /IX}
/t {/ /X /XX /XXX /XL /L /LX /LXX /LXXX /XC}
/h {/ /C /CC /CCC /CD /D /DC /DCC /DCCC /CM}
/m {/ /M /MM /MMM /MMMM}
>>begin
[0
[
[m]{ % M*
    S   
    [h]{ % M* H*
        S
        [t]{ % M* H* T*
            S
            [u]{ % M* H* T* U*
                S
                4 copy
                strcat strcat strcat % M* H* T* U* M*H*T*U*
                5 1 roll % M*H*T*U* M* H* T* U*
                pop % (M*H*T*U*)* M* H* T*
            }forall
            pop % (M*H*T*U*)** M* H*
        }forall
        pop % (M*H*T*U*)*** M*
    }forall
    pop % (M*H*T*U*)****
}forall
]
{exch dup 1 add}forall pop>>end begin

पोस्टस्क्रिप्ट में नहीं है, enumलेकिन हम अनुक्रमिक पूर्णांक मानों के साथ एक शब्दकोश का निर्माण कर सकते हैं और उन्हें एक सरणी में मोड़ सकते हैं। यह क्रम में सभी तारों को उत्पन्न करने के लिए समस्या को कम करता है, जो 4 नेस्टेड छोरों में समवर्ती द्वारा किया जाता है। तो यह सभी तारों को उत्पन्न करता है, फिर एक बढ़ते काउंटर मान के साथ प्रत्येक स्ट्रिंग को इंटरलेव करता है, जिसके परिणामस्वरूप स्टैक पर <string> <int> जोड़े की एक लंबी श्रृंखला होती है जो इसमें लिपटे होते हैं <<...>> एक वस्तु शब्दकोश का निर्माण करने के।

कार्यक्रम रोमन अंकों के लिए सभी नामों को उनके संबंधित मान के लिए एक शब्दकोश का निर्माण और स्थापित करता है। इसलिए स्रोत पाठ में नामों का उल्लेख स्वचालित नाम-खोज को आमंत्रित करता है और स्टैक पर पूर्णांक मान देता है।

II IV MC pstack

प्रिंट

2
4
600

4

स्मॉलटॉक (स्मॉलटॉक / एक्स) (87/101 वर्ण)

बेशक हम आसानी से पार्सर के टोकन को संशोधित कर सकते हैं (क्योंकि यह कक्षा पुस्तकालय का हिस्सा है, और इस तरह के संशोधन के लिए खुला है, और हमेशा मौजूद है), लेकिन एक चुनौती किसी संदर्भ में केवल मूल्यांकन को प्रभावित करना है, ताकि बाकी सिस्टम हमेशा की तरह काम करता है।

संस्करण 1:

मूल्यांकन नाम स्थान में कई चर को परिभाषित करें। तो यह इंटरैक्टिव doIts (उर्फ evals) को प्रभावित करेगा:

(1 to:3999) do:[:n | 
    Workspace workspaceVariables at:(n romanPrintString asUppercase) put:n]

तब मैं कर सकता हूं (एक doIt में, लेकिन संकलित कोड में नहीं):

   |a b|
   a := MMXIV.
   b := V.
   a + b

-> 2019

सूचना: 101 वर्णों में व्हॉट्सएप शामिल है; वास्तव में यह 87 वर्णों के साथ किया जा सकता है।
यह भी ध्यान दें, जब वैश्विक स्मालटाक नेमस्पेस में परिभाषित किया गया है, तो मैं उन स्थिरांक को संकलित कोड में भी देखूंगा।

संस्करण 2:

एक मेकपॉपर हुक का उपयोग करें, जो किसी भी मौजूदा कोड को बिना रीकॉम्पेल किए लपेटने की अनुमति देता है। निम्नलिखित रोम के पहचानकर्ता को स्कैन करने के लिए पार्सर के टोकन को लपेटता है और इसे पूर्णांक बनाता है। मुश्किल हिस्सा गतिशील रूप से यह पता लगाने के लिए है कि कॉलिंग संदर्भ रोमन साम्राज्य से है या नहीं। यह एक क्वेरी सिग्नल (जो तकनीकी रूप से एक उल्लेखनीय अपवाद है) का उपयोग करके किया जाता है:

क्वेरी परिभाषित करें:

InRomanScope := QuerySignal new defaultAnswer:false.

इसलिए हम किसी भी समय ("InRomanScope क्वेरी") को डिफ़ॉल्ट रूप से गलत होने के लिए कह सकते हैं।

फिर स्कैनर की जाँच करें

MessageTracer 
    wrapMethod:(Scanner compiledMethodAt:#checkForKeyword:)
    onEntry:nil
    onExit:[:ctx :ret |
        InRomanScope query ifTrue:[
            |scanner string token n|

            scanner := ctx receiver.
            string := ctx argAt:1.
            (n := Integer readFromRomanString:string onError:nil) notNil
            ifTrue:[
                scanner "/ hack; there is no setter for those two
                    instVarNamed:'tokenType' put:#Integer;
                    instVarNamed:'tokenValue' put:n.
                true
            ] ifFalse:[
                ret
            ].
        ] ifFalse:[
            ret
        ]
    ].

अब स्कैनर हमेशा की तरह काम करता है, जब तक कि हम रोमन साम्राज्य में नहीं हैं:

InRomanScope answer:true do:[
    (Parser evaluate:'MMDXXV') printCR.
].

-> 2525

हम भी कोड संकलित कर सकते हैं:

Compiler 
    compile:'
        inTheYear2525
            ^ MMDXXV
    '
    forClass:Integer.

अच्छा प्रयास; लेकिन यह एक सिंटैक्स त्रुटि के साथ विफल होता है (जो वास्तव में हम चाहते हैं)। हालाँकि, रोमन साम्राज्य में, हम संकलन कर सकते हैं:

InRomanScope answer:true do:[

    Compiler 
        compile:'
            inTheYear2525
                ^ MMDXXV
        '
        forClass:Integer.
]

और अब, हम रोम के अंदर और बाहर से किसी भी पूर्णांक (उस संदेश को भेजना) पूछ सकते हैं:

(1000 factorial) inTheYear2525

-> 2525


स्मालटाक को देखकर अच्छा लगा!

4

हास्केल, टेम्पलेट हास्केल और रोमन-अंकों में मेटा-प्रोग्रामिंग का उपयोग करते हुए :

{-# LANGUAGE TemplateHaskell #-}
import Data.Char (toLower)
import Language.Haskell.TH
import Text.Numeral.Roman

$( mapM (\n -> funD (mkName . map toLower . toRoman $ n)
                    [ clause [] (normalB [| n |]) []]) $ [1..1000 :: Int] )

main = print xlii

हास्केल के पास बिल्डरों के लिए ऊपरी केस अक्षरों से शुरू होने वाले पहचानकर्ता हैं, इसलिए मैंने लोअर-केस का इस्तेमाल किया।


4

जे - 78 चार

यह केवल अन्य समाधानों के साथ MMMCMXCIX = 3999 तक जाता है।

(}.,;L:1{M`CDM`XLC`IVX('';&;:(_1,~3#.inv]){' ',[)&.>841,3#79bc5yuukh)=:}.i.4e3

इसे तोड़ना (याद रखें कि आमतौर पर J को दाएं से बाएं पढ़ा जाता है, जब तक कि कोष्ठक द्वारा अधिरोहित नहीं किया जाता है):

  • M`CDM`XLC`IVX- पत्रों के चार बक्से। हम इन अक्षरों में अनुक्रमणिका में संख्यात्मक सरणियों का उपयोग करने जा रहे हैं और रोमन अंकों के उप-पासवर्ड का निर्माण कर रहे हैं।
  • 841,3#79bc5yuukh - यह संख्यात्मक डेटा है, कसकर एन्कोड किया गया है। *
  • (_1,~3#.inv]) - यह उपरोक्त डेटा को टर्नरी और एपेंडिंग -1 में विस्तारित करके डिकोड करेगा।
  • ('';&;:(...){' ',[)&.>- दाईं ओर के बक्सों के साथ बाईं ओर की संख्याओं को बाँधना ( &.>), संख्याओं की सरणियों को डिकोड करें और उन्हें अक्षरों में अनुक्रमित करने के लिए उपयोग करें। हम अक्षर सूचियों के लिए एक अंतरिक्ष चरित्र को दिखाते हुए 0 को अंतरिक्ष मानते हैं। यह प्रक्रिया जैसे I II III IV V VI VII VIII IXऔर शब्दों की सूची बनाती है M MM MMM
  • {- इन चार बक्सों के कार्टेशियन उत्पाद को शब्दों से भरा लें। अब हमारे पास सभी रोमन अंकों का 4D सरणी है।
  • }.,;L:1- रोमन अंकों की एकल 1D सूची में उस सब को चलाएं, और सामने वाले खाली स्ट्रिंग को हटा दें क्योंकि यह एक त्रुटि पैदा करेगा। ( L:जे गोल्फ में एक दुर्लभ दृश्य है! आमतौर पर इसमें मुक्केबाजी के कई स्तर शामिल नहीं होते हैं।)
  • }.i.4e3- अंतिम बिंदुओं को छोड़कर , पूर्णांक 0 से 4000 तक ।
  • अंत में, हमने एक वैश्विक असाइनमेंट के साथ सब कुछ एक साथ रखा =:। J आपको LHS पर नामों की एक बॉक्सिंग सूची की गणना करने की अनुमति देता है, जो कि एक साथ कई असाइनमेंट के रूप में है, इसलिए यह ठीक काम करता है।

अब जे नेमस्पेस रोमन अंकों का प्रतिनिधित्व करने वाले चर से भरा है।

   XCIX
99
   MMCDLXXVIII
2478
   V * LXIII   NB. 5*63
315
   #4!:1]0     NB. How many variables are now defined in the J namespace?
3999

* मुझे आधार संख्या में पढ़ने के लिए 2933774030998 नंबर की आवश्यकता है। 3. ऐसा होता है कि मैं इसे आधार 79 में 30 से अधिक अंकों का उपयोग करके व्यक्त कर सकता हूं, जो अच्छा है क्योंकि J केवल 35 (0-9) तक के अंकों को समझ सकता है। az)। यह दशमलव पर 3 वर्ण बचाता है।


3

अजगर

आइडिया अन्य उत्तरों की तरह सरल है। लेकिन बस साफ-सुथरा होना और वैश्विक नाम स्थान को प्रदूषित नहीं करना है, एक संदर्भ प्रबंधक का उपयोग किया जाता है। यह भी प्रतिबंध लगाता है, कि आपको हाथ से पहले घोषित करने की आवश्यकता है, जिस रोमन संख्यात्मक का आप उपयोग करने की योजना बना रहे हैं।

नोट बस इसे सरल रखने के लिए, और पहिया को सुदृढ़ करने के लिए नहीं, मैंने रोमन अजगर पैकेज का उपयोग किया है

कार्यान्वयन

class Roman(object):
    memo = [0]
    def __init__(self, hi):
        import rome
        if hi <= len(RomanNumericals.memo):
            self.romans = Roman.memo[0:hi]
        else:
            Roman.memo += [str(rome.Roman(i))
                    for i in range(len(Roman.memo),
                            hi+1)]
            self.romans = Roman.memo
    def __enter__(self):
        from copy import copy
        self.saved_globals = copy(globals())
        globals().update((v,k) for k,v in enumerate(self.romans[1:], 1))
    def __exit__(self,*args ):
        globals().clear()
        globals().update(self.saved_globals)

डेमो

with Roman(5):
    with Roman(10):
        print X
    print V
    print X


10
5

Traceback (most recent call last):
  File "<pyshell#311>", line 5, in <module>
    print X
NameError: name 'X' is not defined

3

अजगर

यह संभवतः पायथन का उपयोग करने वाला सबसे सरल उपाय है:

ns = [1000,900,500,400,100,90,50,40,10,9,5,4,1]
ls = 'M CM D CD C XC L XL X IX V IV I'.split()
for N in range(1, 4000):
    r=''
    p=N
    for n,l in zip(ns,ls):
        while p>=n:
            r+=l
            p-=n
    exec('%s=%d'%(r,N))


i, j = XIX, MCXIV
print i, j

3
बेहतर उपयोग करने के लिए globals()[var] = valueकी तुलना में exec()
रामचंद्र आपटे

3

डी

डी के संकलन समय फ़ंक्शन मूल्यांकन का उपयोग करना

import std.algorithm;
string numerals(){
    auto s = cartesianProduct(["","I","II","III","IV","V","VI","VII","VIII","IX"], 
                              ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"],
                              ["","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"],
                              ["","M","MM","MMM"]);
    s.popFront();//skip first
    char[] result="enum ";
    int i=1;
    foreach(p;s){
        result~=p[3]~p[2]~p[1]~p[0]~"="~i++~",";
    }
    result[$-1]=';';//replace last , with a ;
    return result.idup;
}
mixin(numerals());

3

APL (Dyalog APL) , 77 बाइट्स

रोमन अंक की अधिकतम लंबाई के लिए संकेत और सभी चर को परिभाषित करता है।

t'IVXLCDM',⊂⍬
{⍎⍕⍵'←',+/2(⊣ׯ1*<)/0,⍨(∊1 5∘ר10*⍳4)[t⍳⍵]}¨,/t[⍉8⊥⍣¯1⍳¯1+8*⎕]

t←t हो जाता है

'IVXLCDM', रोमन वर्णों ने पीछा किया

 एक संलग्न

 खाली सूची

t[... ] सूचकांक टी के साथ ...

 प्रत्यारोपित (सही आदेश प्राप्त करने के लिए)

8⊥⍣¯1 उपयुक्त चौड़ाई आधार-आठ का प्रतिनिधित्व

 पहला n सूचकांक, जहां n है

¯1+ से कम है

8*⎕ संख्यात्मक इनपुट की शक्ति के लिए आठ

,/ चपटी पंक्तियाँ (प्रत्येक प्रतिनिधित्व)

{...  प्रत्येक प्रतिनिधित्व पर निम्नलिखित अनाम फ़ंक्शन लागू करें…

(... टी)[t⍳⍵]  में तर्क के आइटम के पदों के अनुरूप , से चुनें ...

   सूचीबद्ध किया गया

  1 5∘ר एक और पाँच बार

  10* की शक्ति से दस

  ⍳4 तीन के माध्यम से शून्य

0,⍨ शून्य जोड़ें

2(…)/ प्रत्येक लंबाई-दो स्लाइडिंग विंडो पर, निम्नलिखित अनाम फ़ंक्शन ट्रेन लागू करें ...

  ⊣× बाएं तर्क समय

  ¯1* की शक्ति के लिए एक नकारात्मक

  < क्या बायाँ तर्क सही तर्क से कम है

+/ योग

⍵'←', तर्क (रोमन अंक) और एक असाइनमेंट तीर को रोकें

 स्वरूप (समतल करने और संख्या को पाठ में बदलने के लिए)

 निष्पादित करें (अनाम फ़ंक्शन के बाहर असाइनमेंट बनाता है)

इसे ऑनलाइन आज़माएं! (अधिकतम लंबाई 5 का उपयोग करके)


2

पीएचपी

वैध रोमन संख्याओं के लिए कई नियम हैं

  1. निचले मूल्यों के लिए सबसे बड़ा मूल्य लिखें

  2. [I,X,C]अगले 2 बड़े मूल्यों से पहले ही घटाएं

  3. [I,X,C]अगले 2 अधिक मूल्यों से पहले डबल घटाना

  4. [I,X,C]अधिक से अधिक मूल्यों से पहले डबल घटाना

  5. 4 + 5 का मिश्रण करें

ऑनलाइन संस्करण

चरण 1 नियम बनाएं

{"M":1000,"IM":999,"IIM":998,"XM":990,"XXM":980,"CM":900,"CCM":800,"D":500,"ID":499,"IID":498,"XD":490,"XXD":480,"CD":400,"C":100,"IC":99,"IIC":98,"XC":90,"XXC":80,"L":50,"IL":49,"IIL":48,"XL":40,"X":10,"IX":9,"IIX":8,"V":5,"IV":4,"I":1}

सभी वैध रोमन संख्याओं के लिए JSON आउटपुट है

$rule_sub_all=$rule_add=$rule_sub_simple=["M"=>1000,"D"=>500,"C"=>100,"L"=>50,"X"=>10,"V"=>5,"I"=>1];
foreach(["I","X","C"]as$roman_letter){
    $rule_sub_simple[$roman_letter.array_search($value=$rule_add[$roman_letter]*5,$rule_add)]=$value-$rule_add[$roman_letter];
    $rule_sub_simple[$roman_letter.array_search($value=$rule_add[$roman_letter]*10,$rule_add)]=$value-$rule_add[$roman_letter];
}
$rule_sub_lower_one=$rule_sub_double=$rule_sub_simple;
foreach(["I","X","C"]as$roman_letter){
    $rule_sub_double[$roman_letter.$roman_letter.array_search($value=$rule_add[$roman_letter]*10,$rule_add)]=$value-2*$rule_add[$roman_letter];

foreach($rule_add as$key=>$value){
    if($value>$rule_add[$roman_letter])$rule_sub_all[$roman_letter.$key]=$value-$rule_add[$roman_letter];
    if($value>5*$rule_add[$roman_letter])$rule_sub_all[$roman_letter.$roman_letter.$key]=$value-2*$rule_add[$roman_letter];
    if($value>10*$rule_add[$roman_letter])$rule_sub_lower_one[$roman_letter.$key]=$value-$rule_add[$roman_letter];
    }
}
arsort($rule_sub_all);
arsort($rule_sub_lower_one);
arsort($rule_sub_double);
arsort($rule_sub_simple);

चरण 2 3999 तक सभी नियमों की सूची बनाएं

$array_sub_lower_one=$array_sub_double=$array_sub_all=$array_add=$array_sub_simple=[];
for($i=1;$i<4000;$i++){
    $number_sub_all=$number_add=$number_sub_simple=$number_sub_double=$number_sub_lower_one=$i;
    $roman_letter_sub_all=$roman_letter_add=$roman_letter_sub_simple=$roman_letter_sub_double=$roman_letter_sub_lower_one="";
    foreach($rule_sub_all as$key=>$value){
        $roman_letter_sub_all.=str_repeat($key,$d=$number_sub_all/$value^0);$number_sub_all-=$value*$d;
        if(in_array($value,$rule_sub_lower_one)){
        $roman_letter_sub_lower_one.=str_repeat($key,$d=$number_sub_lower_one/$value^0);$number_sub_lower_one-=$value*$d;}    
        if(in_array($value,$rule_add)){
        $roman_letter_add.=str_repeat($key,$d=$number_add/$value^0);$number_add-=$value*$d;}
        if(in_array($value,$rule_sub_simple)){
        $roman_letter_sub_simple.=str_repeat($key,$d=$number_sub_simple/$value^0);$number_sub_simple-=$value*$d;}
        if(in_array($value,$rule_sub_double)){
        $roman_letter_sub_double.=str_repeat($key,$d=$number_sub_double/$value^0);$number_sub_double-=$value*$d;}
     }
    $array_sub_lower_one[$roman_letter_sub_lower_one]=$i;   
    $array_sub_all[$roman_letter_sub_all]=$i;
    $array_add[$roman_letter_add]=$i;
    $array_sub_simple[$roman_letter_sub_simple]=$i;
    $array_sub_double[$roman_letter_sub_double]=$i;
}

चरण 3 स्थिरांक बनाएँ

सभी सूचियों को मिलाएं और स्थिरांक को परिभाषित करें

foreach(array_merge($array_add,$array_sub_simple,$array_sub_lower_one,$array_sub_double,$array_sub_all)as$key=>$value){ define($key,$value); }

उत्पादन

उदाहरण में संख्या 8 के दो वैध संस्करणों को परस्पर जोड़कर

echo IIX *  VIII;

अच्छा लगा, लेकिन मैं इसका उपयोग कैसे करूं? मैं PHP में धाराप्रवाह नहीं हूँ; क्या आप कृपया इस बात का उदाहरण दे सकते हैं कि यह कैसे मुझे कोड में रोमन अंक लिखने में सक्षम बनाता है?
डानिएरो

@ डैनियोरो अब कोड को काम करना चाहिए
जोर्ग हल्सरमन

आह, यह बेहतर है :)
daniero

1

REBOL

Rebol []

roman-dialect: func [
    {Dialect which allows Roman numerals as numbers (integer!)}
    block [block!]
    /local word w m1 m2 when-in-rome rule word-rule block-rule
  ][
    when-in-rome: does [
        if roman? w: to-string word [change/part m1 roman-to-integer w m2]
    ]

    word-rule:  [m1: copy word word! m2: (when-in-rome)]
    block-rule: [m1: any-block! (parse m1/1 rule)]
    rule:       [any [block-rule | word-rule | skip]]

    parse block rule
    do block
]

; couple of helper functions used in above parse rules

roman-to-integer: func [roman /local r eval] [
    r: [IV 4 IX 9 XL 40 XC 90 CD 400 CM 900 I 1 V 5 X 10 L 50 C 100 D 500 M 1000]
    eval: join "0" copy roman
    foreach [k v] r [replace/all eval k join " + " v]
    do replace/all to-block eval '+ '+
]

roman?: func [s /local roman-chars] [
    roman-char: charset "IVXLCDM"
    parse/case s [some roman-char]
]


उदाहरण

roman-dialect [
    m: X + V
    print m
    print M + m  ; doesn't confuse the variable m with Roman Numeral M
    if now/year = MMXIV [print "Yes it is 2014"]
    for n I V I [
        print [rejoin [n "+" X "="] n + X]
    ]
]

आउटपुट:

15

1015

हाँ यह 2014 है

1 + 10 = 11

2 + 10 = 12

3 + 10 = 13

4 + 10 = 14

5 + 10 = 15


अस्वीकरण: मुझे यकीन है कि Rebol में भी ऐसा करने के अन्य तरीके (और शायद बेहतर हैं!) हैं।

पुनश्च। मेरा roman-to-integerकार्य रोमन संख्या को एक संख्या में परिवर्तित करने के लिए हिस्टोक्रेट के अच्छे रूबी एल्गोरिथ्म का लिप्यंतरण है । धन्यवाद के साथ लौटा! +1


1

लुआ

local g={}
setmetatable(_G,g)
local romans = {I = 1,
                V = 5,
                X = 10,
                L = 50,
                C = 100,
                D = 500,
                M = 1000}
local larger = {    -- Precalced, for faster computing.
                I = "VXLCDM",
                V = "XLCDM",
                X = "LCDM",
                L = "CDM",
                C = "DM",
                D = "M",
                M = " " -- A space will never be found, and it prevents the pattern matcher from erroring.
}
local storedRomans = {}
function g:__index(key)
    if storedRomans[key] then
        return storedRomans[key]
    end
    if key:match"^[IVXLCDM]+$" then
        local n = 0
        local i = 1
        for s in key:gmatch"." do
            local N = romans[s]
            if key:find('['..larger[s]..']',i) then
                n = n - N
            else
                n = n + N
            end
            i = i + 1
        end
        storedRomans[key] = n
        return n
    end
end

यह वैश्विक तालिका के मेटाबल को प्रभावित करता है, जिससे यह एक नया सूचकांक कार्य करता है। जब एक वैश्विक चर, जिसमें केवल रोमन अंक होते हैं, के लिए कहा जाता है, उदाहरण के लिए XVII, यह इसे पार्स करता है।

परीक्षण करने में आसान;

print(XVII) -- 42
print(VI)   -- 6
print(III)  -- 3
print(MMM)  -- 3000

इसे ऑनलाइन आज़माएं!


1

VBA, 204 बाइट्स

एक सबरूटीन जो कोई इनपुट लेता घोषणा की, और जब चलाने के लिए, बनाता है publicly सुलभ Enum, R, जो रोमन अंक मूल्यों के सभी शामिल हैं। इन मूल्यों का उपयोग सीधे एनम को संदर्भित किए बिना किया जा सकता है।

Enum 1 से 3999 तक मान रखता है।

नोट:" लाइनों 3 और 7 पर टर्मिनल s केवल सिंटैक्स हाइलाइटिंग के लिए शामिल हैं, और बायटेकाउंट में योगदान नहीं करते हैं

Public Sub i
Set c=ThisWorkbook.VBProject.VBComponents.Add(1).CodeModule
c.AddFromString"Public Enum R"
For n=1To 3999
c.AddFromString WorksheetFunction.Roman(n)&"="&n
Next
c.AddFromString"End Enum"
End Sub

अनगढ़ और समझाया हुआ

Public Sub InitializeRomanNumerals()
    Dim c As CodeModule                                            ''  Dim CodeModule
    Set c=ThisWorkbook.VBProject.VBComponents.Add(1).CodeModule    ''  Create Module
    Let c.Parent.Name = "RomanNumeral_Module"                      ''  Name the Module
    Call c.AddFromString("Public Enum RomanNumerals")              ''  Declare the Enum
        For n=1To 3999Step 1                                       ''  Iter from 1 to 3999
            Call c.AddFromString(WorksheetFunction.Roman(n)&"="&n) ''  Add the Roman
                                                                   ''  Numeral to Enum
        Next n                                                     ''  Loop
    Call c.AddFromString("End Enum")                               ''  End The Enum
End Sub
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.