एक लिस्प की तरह सिंटेक्स तैयार करना


23

पृष्ठभूमि

(एक सच्ची, दिल दहला देने वाली कहानी पर आधारित)

अपने समय में, मैंने लिस्प और इसी तरह की भाषाओं के साथ अक्सर खेला है। मैंने उनके साथ लिखा है, उन्हें दौड़ाया, उनकी व्याख्या की, उन्हें डिज़ाइन किया, और मशीनों ने मेरे लिए उनके साथ लिखा ... और अगर कोई चीज मुझे परेशान करती है, तो वह लिस्प को देख रही है जो मेरी विशिष्ट प्रारूपण शैली का अनुपालन नहीं करता है।

दुर्भाग्य से, कुछ पाठ संपादकों ( खांसी XCode खांसी ) कोड और कॉपी किया जाता है जब भी मेरी सुंदर टैब और रिक्त स्थान स्ट्रिप करने के लिए करते हैं ... इस सुंदर ढंग से लिस्प-जैसे सिंटैक्स ले लो:

(A
    (B
        (C)
        (D))
    (E))

(जहां ABCDEमनमाने कार्य हों)

कुछ पाठ संपादक कसाई इस प्यारे कोड को निम्न अंत तक ले जाते हैं:

(A
(B
(C)
(D))
(E))

क्या झंझट है! यह पठनीय नहीं है!

मेरी मदद करो, यहाँ?

चुनौती

इस चुनौती में आपका लक्ष्य नीचे वर्णित प्रारूप में newlines द्वारा अलग किए गए कार्यों की एक श्रृंखला लेना है और एक अधिक सुंदर व्यवस्था को वापस करना है जो पठनीयता और लालित्य को उजागर करता है।

इनपुट

हम निम्न के समान निर्माण के रूप Fमें आर्गिटी Nतर्कों के एक कार्य को परिभाषित करते हैं:

(F (G1 ...) (G2 ...) (G3 ...) ... (GN ...))

जहां G1, G2, ..., GNसभी कार्य अपने आप में हैं। एक एरिटी 0फंक्शन Aबस है (A), जबकि एक एरिटी 2फंक्शन Bफॉर्म का है(B (...) (...))

आपके कोड को प्रत्येक फ़ंक्शन के प्रमुख कोष्ठक (पहले फ़ंक्शन को छोड़कर) से पहले एक नई पंक्ति के साथ फ़ंक्शन की एक श्रृंखला के रूप में इनपुट लेना चाहिए। ऊपर दिया गया उदाहरण वैध इनपुट है।

आप मान सकते हैं:

  • कोष्ठक संतुलित हैं।
  • एक फ़ंक्शन को 250 से अधिक बार इंडेंट नहीं करना पड़ेगा।
  • हर समारोह कोष्ठकों से घिरा हुआ है: ()
  • एक फ़ंक्शन के नाम में केवल मुद्रण योग्य ASCII वर्ण होंगे।
  • एक फ़ंक्शन के नाम में कोष्ठक या रिक्त स्थान कभी नहीं होंगे।
  • इनपुट पर एक वैकल्पिक अनुगामी न्यूलाइन है।

उत्पादन

आपके कोड को फ़ंक्शंस के उसी सेट को आउटपुट करना चाहिए , जहां किए गए एकमात्र परिवर्तन फ़ंक्शंस के प्रमुख कोष्ठक से पहले रिक्त स्थान या टैब के जोड़ हैं। आउटपुट को निम्नलिखित नियमों का पालन करना चाहिए:

  • दिए गए पहले फ़ंक्शन (और बाद में शीर्ष-स्तरीय फ़ंक्शन) में कोई पूर्ववर्ती स्थान नहीं होना चाहिए
  • किसी फ़ंक्शन के क्षैतिज स्थान पर एक तर्क उस फ़ंक्शन के क्षैतिज स्थान के दाईं ओर एक टैब है।
  • एक टैब कार्यान्वयन-परिभाषित है, लेकिन कम से कम 3 स्थान होना चाहिए।
  • आप वैकल्पिक रूप से प्रत्येक पंक्ति के बाद अधिकतम दो स्थान प्रिंट कर सकते हैं।

नियम

उदाहरण

इनपुट:

(A
(B
(C)
(D))
(E))

आउटपुट:

(A
    (B
        (C)
        (D))
    (E))

इनपुट:

(!@#$%^&*
(asdfghjklm
(this_string_is_particularly_long
(...))
(123456789)))
(THIS_IS_TOP_LEVEL_AGAIN
(HERE'S_AN_ARGUMENT))

आउटपुट:

(!@#$%^&*
    (asdfghjklm
        (this_string_is_particularly_long
            (...))
        (123456789)))
(THIS_IS_TOP_LEVEL_AGAIN
    (HERE'S_AN_ARGUMENT))

इनपुट:

(-:0
(*:0
(%:0
(Arg:6)
(Write:0
(Read:0
(Arg:30))
(Write:0
(Const:-6)
(Arg:10))))
(%:0
(Const:9)
(/:0
(Const:-13)
(%:0
(Arg:14)
(Arg:0)))))
(WriteArg:22
(-:0
(Const:45)
(?:0
(Arg:3)
(Arg:22)
(Arg:0)))))

आउटपुट:

(-:0
    (*:0
        (%:0
            (Arg:6)
            (Write:0
                (Read:0
                    (Arg:30))
                (Write:0
                    (Const:-6)
                    (Arg:10))))
        (%:0
            (Const:9)
            (/:0
                (Const:-13)
                (%:0
                    (Arg:14)
                    (Arg:0)))))
    (WriteArg:22
        (-:0
            (Const:45)
            (?:0
                (Arg:3)
                (Arg:22)
                (Arg:0)))))

हॉट नेटवर्क प्रश्न सूची बनाने के लिए बधाई! : डी
एलेक्स ए

@AlexA। हुर्रे! मेरे सपनों को साकार किया गया है। : D
ब्रेनसैट

क्या होगा अगर कोई फ़ंक्शन नाम नहीं है, जैसे ()?
coredump

क्या इंडेंटेशन को> = 3 स्थान होना चाहिए, या एक टैब स्वीकार्य है?
इसहाक

@isaacg आप मान सकते हैं कि सभी कार्य इस मामले में नामित किए गए हैं। और जो कुछ भी आपके ओएस / भाषा को एक क्षैतिज टैब के रूप में परिभाषित करता है वह ठीक है। यदि आप रिक्त स्थान का उपयोग करते हैं, तो कम से कम 3 होना चाहिए। मैं स्पष्ट करता हूं कि जब मैं कंप्यूटर पर पहुंच सकता हूं। धन्यवाद!
ब्रेनसैट

जवाबों:


9

पायथ, 24 20 19 18 बाइट्स

FN.z+*ZC9N~Z-1/N\)

प्रत्येक पंक्ति के लिए एक काउंटर बढ़ाता है, अब तक सामने आए समापन कोष्ठकों की कुल संख्या को गिनता है, और इसे काउंटर से घटाता है। तब हम counterटैब द्वारा इंडेंट करते हैं।


@Downvoter की व्याख्या करना है?
orlp

मैं नीचे नहीं था, लेकिन *4एक हार्डकोड और निरर्थक वरीयता है। FN.z+*ZC9N~Z-1/N\)आपको अपने संपादक की इंडेंट चौड़ाई का उपयोग करने देता है और एक बाइट बचाता है।
सीस टिमरमैन

मैं सहमत हूं, एक टैब एक वर्ण छोटा होगा। \<tab>या C9
इसहाक

9

आम लिस्प - 486 414 बाइट्स (रुब गोल्डबर्ग संस्करण)

(labels((p(x d)(or(when(listp x)(#2=princ #\()(p(car x)d)(incf d)(dolist(a(cdr x))(format t"~%~v{   ~}"d'(t))(p a d))(#2# #\)))(#2# x))))(let((i(make-string-input-stream(with-output-to-string(o)(#1=ignore-errors(do(b c)(())(if(member(setq c(read-char))'(#\( #\) #\  #\tab #\newline):test'char=)(progn(when b(prin1(coerce(reverse b)'string)o))(#2# c o)(setq b()))(push c b))))))))(#1#(do()(())(p(read i)0)(terpri)))))

पहुंच

हर किसी की तरह करने और हाथ से कोष्ठक गिनने के बजाय, चलो लिस्प पाठक को आमंत्रित करें और इसे सही तरीके से करें :-)

  • इनपुट स्ट्रीम से पढ़ें और अस्थायी आउटपुट स्ट्रीम पर लिखें ।
  • ऐसा करने से, वहीं कुल पात्रों से अलग (, )तारों के रूप में खाली स्थान या।
  • मध्यवर्ती आउटपुट का उपयोग स्ट्रिंग बनाने के लिए किया जाता है, जिसमें सिंटैक्टिक रूप से अच्छी तरह से गठित कॉमन-लिस्प फॉर्म होते हैं: स्ट्रिंग्स की नेस्टेड लिस्ट।
  • इनपुट स्ट्रीम के रूप में उस स्ट्रिंग का उपयोग करके readवास्तविक सूची बनाने के लिए मानक फ़ंक्शन को कॉल करें ।
  • pउन सूचियों में से प्रत्येक पर कॉल करें , जो उन्हें अनुरोधित प्रारूप के साथ मानक आउटपुट पर पुन: लिखते हैं। विशेष रूप से, तार बिना मुद्रित किए जाते हैं।

इस दृष्टिकोण के परिणामस्वरूप:

  1. इनपुट प्रारूप पर कम प्रतिबंध हैं: आप मनमाने ढंग से स्वरूपित इनपुट पढ़ सकते हैं, न कि केवल "प्रति पंक्ति एक कार्य" (यूएचबी)।
  2. साथ ही, यदि इनपुट अच्छी तरह से नहीं बना है, तो एक त्रुटि का संकेत दिया जाएगा।
  3. अंत में, सुंदर प्रिंटिंग फ़ंक्शन को पार्सिंग से अच्छी तरह से डिकोड किया जाता है: आप आसानी से सुंदर प्रिंटिंग एस-एक्सप्रेशन के दूसरे तरीके पर स्विच कर सकते हैं (और यदि आपको अपने ऊर्ध्वाधर स्थान का मूल्य देना है)।

उदाहरण

एक फ़ाइल से पढ़ना, इस आवरण का उपयोग करना:

(with-open-file (*standard-input* #P"path/to/example/file")
    ...)

यहाँ परिणाम है:

(!@#$%^&*
    (asdfghjklm
        (this_string_is_particularly_long
            (...))
        (123456789)))
(THIS_IS_TOP_LEVEL_AGAIN
    (HERE'S_AN_ARGUMENT))
(-:0
    (*:0
        (%:0
            (Arg:6)
            (Write:0
                (Read:0
                    (Arg:30))
                (Write:0
                    (Const:-6)
                    (Arg:10))))
        (%:0
            (Const:9)
            (/:0
                (Const:-13)
                (%:0
                    (Arg:14)
                    (Arg:0)))))
    (WriteArg:22
        (-:0
            (Const:45)
            (?:0
                (Arg:3)
                (Arg:22)
                (Arg:0)))))

(ऐसा लगता है कि टैब यहां रिक्त स्थान में परिवर्तित हो गए हैं)

सुंदर-मुद्रित (गोल्फ संस्करण)

सुरक्षित मूल संस्करण के विपरीत, हम इनपुट के वैध होने की उम्मीद करते हैं।

(labels ((p (x d)
           (or
            (when (listp x)
              (princ #\()
              (p (car x) d)
              (incf d)
              (dolist (a (cdr x)) (format t "~%~v{  ~}" d '(t)) (p a d))
              (princ #\)))
            (princ x))))
  (let ((i
         (make-string-input-stream
          (with-output-to-string (o)
            (ignore-errors
             (do (b
                  c)
                 (nil)
               (if (member (setq c (read-char)) '(#\( #\) #\  #\tab #\newline)
                           :test 'char=)
                   (progn
                    (when b (prin1 (coerce (reverse b) 'string) o))
                    (princ c o)
                    (setq b nil))
                   (push c b))))))))
    (ignore-errors (do () (nil) (p (read i) 0) (terpri)))))

7

रेटिना , 89 83 बाइट्स

s`.+
$0<tab>$0
s`(?<=<tab>.*).
<tab>
+ms`^((\()|(?<-2>\))|[^)])+^(?=\(.*^((?<-2><tab>)+))
$0$3
<tab>+$
<empty>

कहा पे <tab> एक वास्तविक टैब वर्ण (0x09) <empty>के लिए खड़ा है और एक खाली लाइन के लिए खड़ा है। उन प्रतिस्थापनों को बनाने के बाद, आप -sध्वज के साथ उपरोक्त कोड चला सकते हैं । हालाँकि, मैं उस ध्वज की गिनती नहीं कर रहा हूँ, क्योंकि आप प्रत्येक पंक्ति को उसके स्वयं के स्रोत फ़ाइल में भी डाल सकते हैं, उस स्थिति में अतिरिक्त स्रोत फ़ाइलों के लिए 7 दंडों को 7 दंडों द्वारा प्रतिस्थापित किया जाएगा।

यह एक पूर्ण कार्यक्रम है, STDIN पर इनपुट लेना और परिणाम को STDOUT में प्रिंट करना।

व्याख्या

लाइनों की हर जोड़ी एक रेगेक्स प्रतिस्थापन को परिभाषित करती है। मूल विचार किसी दिए गए वर्तमान गहराई को गिनने के लिए .NET के संतुलन समूहों का उपयोग करना है (, और फिर उससे पहले कई टैब सम्मिलित करना है (

s`.+
$0<tab>$0

सबसे पहले, हम इनपुट तैयार करते हैं। हम वास्तव में टैब की एक सशर्त संख्या वापस नहीं लिख सकते हैं, अगर हम उन्हें पकड़ने के लिए इनपुट स्ट्रिंग में कहीं नहीं ढूंढ सकते हैं। इसलिए हम टैब द्वारा अलग किए गए पूरे इनपुट को डुप्लिकेट करके शुरू करते हैं। ध्यान दें कि s`बस सिंगल-लाइन (या "डॉट-ऑल") संशोधक को सक्रिय करता है, जो यह सुनिश्चित करता है कि यह .भी नईलाइन्स से मेल खाता है।

s`(?<=<tab>.*).
<tab>

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

+ms`^((\()|(?<-2>\))|[^)])+^(?=\(.*^((?<-2><tab>)+))
$0$3

यह समाधान का मांस है। mऔर sबहु लाइन मोड (कि इतने सक्रिय करें ^लाइनों की शुरुआत से मेल खाता है) और एकल लाइन मोड। +रेटिना बताता है इस प्रतिस्थापन दोहरा जब तक उत्पादन बदल रहा बंद हो जाता है (इस मामले में साधन पैटर्न नहीं रह गया है स्ट्रिंग से मेल खाता है जब तक कि,) रखने के लिए।

पैटर्न स्वयं एक अप्रमाणित तक इनपुट के एक उपसर्ग से मेल खाता है ((अर्थात, (इसके पहले कोई टैब नहीं है, लेकिन होना चाहिए)। एक ही समय में यह संतुलन समूहों के साथ उपसर्ग की गहराई को निर्धारित करता है, जैसे कि स्टैक की ऊंचाई 2वर्तमान गहराई के अनुरूप होगी, और इसलिए टैब की संख्या हमें संलग्न करने की आवश्यकता है। यह हिस्सा है:

((\()|(?<-2>\))|[^)])+

यह या तो एक से मेल खाता है (, इसे 2स्टैक पर धकेलता है , या यह एक से मेल खाता है ), 2स्टैक से अंतिम कैप्चरिंग को पॉप करता है , या यह कुछ और से मेल खाता है और स्टैक को अछूता छोड़ देता है। चूंकि कोष्ठक संतुलित होने की गारंटी है, हमें खाली स्टैक से पॉप करने की कोशिश करने की चिंता करने की आवश्यकता नहीं है।

जब हम इस तरह से स्ट्रिंग से गुज़रे (, तब तक रुकने के लिए एक असंसाधित पाया गया, लुकहेड फिर स्ट्रिंग के अंत तक आगे निकल जाता है, और स्टैक 3से पॉपिंग करते समय समूह में टैब को पकड़ता है 2जब तक कि यह खाली न हो जाए:

(?=\(.*^((?<-2><tab>)+))

+वहां एक का उपयोग करके , हम यह सुनिश्चित करते हैं कि पैटर्न केवल कुछ से मेल खाता है यदि कम से कम एक टैब को मैच में डाला जाना चाहिए - यह एक अनंत लूप से बचा जाता है जब कई रूट-स्तरीय फ़ंक्शन होते हैं।

<tab>+$
<empty>

अंत में, हम केवल परिणाम को साफ करने के लिए स्ट्रिंग के अंत में उन सहायक टैब से छुटकारा पा लेते हैं।


यह बहुत अच्छा है। बहुत बढ़िया! रेटिना को देखना हमेशा खुशी की बात होती है।
ब्रेनसटेल

6

C: 95 94 वर्ण

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

i,j;main(c){for(;putchar(c=getchar()),c+1;i+=c==40,i-=c==41)if(c==10)for(j=i;j--;putchar(9));}

Ungolfed:

i,j;
main(c){
  for(
    ;
    putchar(c=getchar()),
    c+1;
    i+=c==40,
    i-=c==41
  )
    if(c==10)
      for(
        j=i;
        j--;
        putchar(9)
      );
}

संपादित करें: इसे बनाया ताकि यह EOF पर चलता रहे।


टैब पूरी तरह से स्वीकार्य हैं।
ब्रेनसेल

2
के if(c<11)बजाय आप का उपयोग कर सकते हैं if(c==10)?
डिजिटल ट्रॉमा

5

जूलिया, 103 99 97 97 94 88 बाइट्स

p->(i=j=0;for l=split(p,"\n") i+=1;println("\t"^abs(i-j-1)*l);j+=count(i->i=='\)',l)end)

यह एक अनाम फ़ंक्शन को परिभाषित करता है जो एक स्ट्रिंग को स्वीकार करता है और इंडेंट संस्करण को प्रिंट करता है। इसे कॉल करने के लिए, इसे एक नाम दें, जैसे f=p->...। ध्यान दें कि इनपुट एक वैध जूलिया स्ट्रिंग होना चाहिए, ताकि डॉलर के संकेत ( $) बच जाए।

असंगठित + स्पष्टीकरण:

function f(p)
    # Set counters for the line number and the number of close parens
    i = j = 0

    # Loop over each line of the program
    for l in split(p, "\n")
        # Increment the line number
        i += 1

        # Print the program line with |i-j-1| tabs
        println("\t"^abs(i-j-1) * l)

        # Count the number of close parens on this line
        j += count(i -> i == '\)', l)
    end
end

उदाहरण, चार स्थानों के प्रत्येक सेट का दिखावा एक टैब है:

julia> f("(A
(B
(C)
(D))
(E))")

(A
    (B
        (C)
        (D))
    (E))

किसी भी सुझाव का स्वागत से अधिक है!



3

पर्ल, 41

$_="\t"x($i-$j).$_;$i+=y/(/(/;$j+=y/)/)/

40पात्रों +1के लिए -p

साथ दौड़ो:

cat input.txt | perl -pe'$_="\t"x($i-$j).$_;$i+=y/(/(/;$j+=y/)/)/'

3

पायथन 2 - 88 78 बाइट्स

बहुत सीधा (और बहुत कम नहीं) समाधान:

l=0
for x in raw_input().split():g=x.count;d=l*'\t'+x;l+=g("(")-g(")");print d

कुछ सुझाव: 1) आप एक बाइट के '\t'बजाय उपयोग कर सकते हैं ' 'और बचा सकते हैं ; 2) input.split()एक चर को निर्दिष्ट करने की आवश्यकता नहीं है , क्योंकि यह केवल एक बार उपयोग किया जाता है (उसी के लिए c, साथ ही d- printकथन को स्थानांतरित करें ); 3) ऑपरेटर पूर्वता का मतलब है कि चारों ओर कोष्ठक की l*cजरूरत नहीं है। इसके अलावा, ऐसा लगता fहै कि किसी भी चीज के लिए उपयोग नहीं किया जाता है - क्या यह पिछले संस्करण का अवशेष है?
DLosc

इसके अलावा, अगर यह पायथन 2 है, तो आपको raw_inputइसके बजाय input(और इसके बाद कोष्ठक मत भूलना!) का उपयोग करने की आवश्यकता होगी ।
DLosc

2

CJam, 20 बाइट्स

r{_')e=NU)@-:U9c*r}h

CJam दुभाषिया में इसे ऑनलाइन आज़माएं ।

यह काम किस प्रकार करता है

r                    e# Read a whitespace-separated token R from STDIN.
{                 }h e# Do, while R is truthy: 
  _')e=              e#   Push C, the number of right parentheses in R. 
       NU            e#   Push a linefeed and U (initially 0).
         )@-         e#   Compute U + 1 - C.
            :U       e#   Save in U.
              9c*    e#   Push a string of U tabulators.
                 r   e#   Read a whitespace-separated token R from STDIN.
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.