उच्चतम परिधि पॉलोमिनो


14

यह कोड गोल्फ है। विजेता बाइट्स की सबसे छोटी संख्या के साथ मान्य कोड है।


चुनौती

इनपुट M और N को देखते हुए , चौकों की एक आयताकार ग्रिड की चौड़ाई और ऊंचाई, एक बहुभुज का उत्पादन करता है जो निम्नलिखित को संतुष्ट करता है:

  • बहुभुज किनारों को केवल चौकोर किनारों से बनाया जाता है: कोई विकर्ण किनारे नहीं हैं - सभी ऊर्ध्वाधर या क्षैतिज हैं।
  • बहुभुज के पास कोई छेद नहीं है: बहुभुज के बाहर प्रत्येक वर्ग बहुभुज के बाहर वर्गों पर रूढ़िवादी कदमों से पहुंच सकता है, आयत की बाहरी सीमा पर बहुभुज के बाहर एक वर्ग से शुरू होता है।
  • बहुभुज का कोई आत्म-चौराहा नहीं है: वर्टिक्स पर मिलने वाले वर्ग किनारों की बैठक, 2 से अधिक कोई भी बहुभुज परिधि का हिस्सा नहीं हो सकता है।
  • बहुभुज जुड़ा हुआ है: बहुभुज में किसी भी वर्ग को बहुभुज में किसी भी अन्य वर्ग से रूढ़िवादी चरणों के माध्यम से पहुंच योग्य होना चाहिए जो बहुभुज के भीतर रहते हैं।
  • बहुभुज की अधिकतम संभव परिधि है: नीचे दिखाए गए सूत्र के अनुसार।

आपके कोड को M और N के लिए 1 से 255 तक काम करना होगा ।


अधिकतम परिधि के लिए सूत्र

यहां चुनौती उन बहुभुजों को सबसे अधिक परिधि के साथ मिल रही है। स्वयं अधिकतम परिधि हमेशा सूत्र द्वारा परिभाषित की जाती है:

यह सच है क्योंकि अधिकतम परिधि के लिए प्रत्येक वर्ग शीर्ष को परिधि पर होना चाहिए। विषम संख्या के लिए यह संभव नहीं है और जो सबसे अच्छा हो सकता है वह एक शीर्ष कम है (चूंकि परिधि हमेशा होती है)।


उत्पादन

न्यूलाइन से अलग किए गए वर्णों की एक स्ट्रिंग के रूप में आकार को आउटपुट करें ( बिल्कुल एम वर्णों की एन पंक्तियाँ )। यहाँ मैं बहुभुज के बाहर वर्गों के लिए जगह का उपयोग कर रहा हूँ, और बहुभुज के अंदर वर्गों के लिए '#', लेकिन आप किसी भी दो अलग-अलग वर्णों का उपयोग कर सकते हैं, बशर्ते उनका अर्थ सभी आदानों के अनुरूप हो।

आप एक प्रमुख न्यूलाइन और एक अनुवर्ती न्यूलाइन तक शामिल हो सकते हैं।

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


उदाहरण

एक छेद के कारण अमान्य :

###
# #
###

चौराहे के कारण अवैध (तिरछे को छूते हुए - परिधि पर 4 वर्ग किनारों के साथ एक शीर्ष) और, संयोग से, एक छेद:

##
# #
###

काट दिए जाने के कारण अमान्य :

#
# #
  #

अधिकतम परिधि के वैध बहुभुज:

# #
# #
###

क्रेडिट

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

विशेष रूप से धन्यवाद:

स्पर्म , ज़र्गब , फ़ेरसुम , जिम्मी 23013


मैं इस सवाल को पॉलीमिनोस या पॉलीगॉन (दोनों लागू होने के बाद से) का नाम दे सकता था। क्या किसी को वरीयता है? आप निम्नलिखित पर टिप्पणी मतदान के साथ संकेत कर सकते हैं:
ट्राइकोप्लाक्स

5
उच्चतम परिधि
पॉलोमिनो

1
उच्चतम परिधि जुड़ा बहुभुज
ट्राइकोप्लाक्स

बिल्कुल एम वर्णों की एन पंक्तियाँ: क्या हम दो इनपुट वैल्यू को इंटरचेंज कर सकते हैं यदि हम इसे कुछ इनपुट के लिए सुविधाजनक पाते हैं?
लेवल रिवर सेंट

3
@steveverrill मैंने आउटपुट अनुभाग संपादित किया है। क्या यह आपके अनुरोध पर फिट बैठता है?
ट्राइकोप्लाक्स

जवाबों:


4

CJam, 47 बाइट्स

l~_2%{\}|_'#:H*@({N+1$(2md\HS+*H+\SH+R=*++}fR\;

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

स्पष्टीकरण:

l~      Get and convert input.
_2%     Calculate second value modulo 2.
{\}|    If value is even, swap the two inputs. This puts odd on top if one is odd.
_'#:H*  Create top row of all # signs. Also save away # character as shortcut for later.
@(      Pull number of rows to top, and decrement because first is done.
{       Start loop over rows.
N+      Add newline.
1$      Copy row length to top of stack.
(2md    Decrement, and calculate mod/div with 2.
\       Swap mod and div, will use div first.
HS+     "# "
*       Repeat it based on div 2 of row length.
H+      Add one more #.
\       Swap mod of earlier division to top.
SH+     " #"
R=      Pick space or # depending on even/odd row number.
*       Repeat 0 or 1 times depending on mod 2 of row length.
+       Add the possible extra character to line.
+       Add line to result.
}fR     End of for loop over lines.
\;      Remove row length from stack, leaving only result string.

परिणाम के लिए दो मुख्य मामले हैं। यदि कम से कम एक आकार विषम है, तो पैटर्न एक सादा "रेक" है। उदाहरण के लिए, इनपुट के लिए 7 6:

#######
# # # #
# # # #
# # # #
# # # #
# # # #

यदि दोनों आकार समान हैं, तो एक अतिरिक्त स्तंभ है जहां हर दूसरा वर्ग "चालू" है। उदाहरण के लिए, इनपुट के लिए 8 6:

########
# # # # 
# # # ##
# # # # 
# # # ##
# # # # 

अब, यह दिखाने के लिए कि ये पैटर्न समस्या विवरण में दी गई परिधि के सैद्धांतिक अधिकतम तक पहुँचते हैं, हमें यह पुष्टि करने की आवश्यकता है कि पहले पैटर्न में परिधि है (M + 1) * (N + 1), और दूसरा समान मान शून्य 1।

पहले पैटर्न के लिए, हमारे पास परिधि के लिए Mएक विषम आयाम है:

  1. M शीर्ष बढ़त के लिए।
  2. 2 शीर्ष पंक्ति के किनारे पर।
  3. (M - 1) / 2 दांतों के बीच अंतराल के लिए।
  4. (M + 1) / 22 * (N - 1) + 1प्रत्येक परिधि वाले दांत ।

यह ऊपर जोड़ता है:

M + 2 + (M - 1) / 2 + (M + 1) / 2 * (2 * (N - 1) + 1) =
M + 2 + (M - 1) / 2 + (M + 1) * (N - 1) + (M + 1) / 2 =
2 * M + 2 + (M + 1) * (N - 1) =
(M + 1) * 2 + (M + 1) * (N - 1) =
(M + 1) * (N + 1)

दूसरे मामले के लिए जहां दोनों हैं Mऔर Nयहां तक ​​कि परिधि भी इसमें शामिल है:

  1. M शीर्ष बढ़त के लिए।
  2. 2 शीर्ष पंक्ति के किनारे पर।
  3. M / 2 शीर्ष पंक्ति में खुले # के लिए।
  4. M / 22 * (N - 1) + 1सादे दांतों के लिए परिधि वाले दांत।
  5. सबसे दाएं दांत में गुड़ के लिए एक अतिरिक्त 2 * (N / 2 - 1)परिधि के टुकड़े होते हैं।

यह सब एक साथ जोड़ना:

M + 2 + M / 2 + (M / 2) * (2 * (N - 1) + 1) + 2 * (N / 2 - 1) =
M + 2 + (M / 2) * (2 * (N - 1) + 2) + N - 2 =
M + M * N + N =
(M + 1) * (N + 1) - 1

मुझे लगता है कि मैं दांतेदार भाग को बाईं ओर रखकर कुछ बाइट्स बचा सकता हूं। कुछ कम स्टैक फेरबदल की आवश्यकता होनी चाहिए। लेकिन यह सोने का समय है ...
रेटो कोराडी

5

रूबी, रेव १, ६६

->(m,n){n.times{|i|puts ("#"*m**(1-i%2)).rjust(m,i>n-2?"# ":" ")}}

m1 या 1 m #प्रिंट करने के लिए तय करने के लिए 0 o 1 को बढ़ाने के लिए उपयोग किया जाता है।

के >बजाय अंतिम पंक्ति के लिए परीक्षण करने के लिए उपयोग किया जाता है ==

डाल के बाद अंतरिक्ष से छुटकारा नहीं मिल सकता है, न ही कोई कोष्ठक!

रूबी, रेव ०, ६ ९

->(m,n){n.times{|i|puts ("#"*(i%2==0?m:1)).rjust(m,i==n-1?"# ":" ")}}

यह एक अनाम मेमने का कार्य है। इसे इस तरह उपयोग करें:

f=->(m,n){n.times{|i|puts ("#"*(i%2==0?m:1)).rjust(m,i==n-1?"# ":" ")}}

M=gets.to_i
N=gets.to_i
f.call(M,N)

अंत में, यह पूछने के बाद कि क्या M और N आपस में जुड़ सकते हैं, मुझे इसकी आवश्यकता नहीं है।


N विषम के लिए विशिष्ट आउटपुट। यदि हम #दाहिने हाथ की तरफ अपने दम पर हटाते हैं , तो स्पष्ट रूप से हमारे पास (N + 1) (M + 1) होगा। आकार में शामिल होने के लिए उन्हें शामिल करना क्षैतिज परिधि के 2 वर्गों को हटाता है और ऊर्ध्वाधर परिधि के 2 वर्गों को जोड़ता है, इसलिए कोई बदलाव नहीं है।

यहां हम "#"*(i%2==0?m:1)एम #प्रतीकों और एक #प्रतीक की वैकल्पिक पंक्तियों को देने के लिए अभिव्यक्ति पर भरोसा करते हैं , और एम वर्णों को सही ठहराते हैं।

5                        6
5                        5
#####                    ######
    #                         #
#####                    ######
    #                         #
#####                    ######

एन के लिए विशिष्ट आउटपुट भी। 5 6स्पष्ट रूप से एक ही परिधि है 6 5, या 5 5नीचे पंक्ति के उन्मूलन के कारण ऊर्ध्वाधर परिधि के अलावा की तुलना में M + 1 = 6 का वेतन वृद्धि है । ऊर्ध्वाधर परिधि में (M + 1) -1 = 6 का वेतन वृद्धि के 6 6समान है 6 5। इस प्रकार वे सूत्र के अनुसार हैं।

5                        6
6                        6
#####                    ######
    #                         #
#####                    ######
    #                         #
#####                    ######
# # #                    # # ##

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

यहां इसकी जांच कीजिए।


@ Vioz- विचारधारा के लिए धन्यवाद! मैंने N और M के निम्न मानों के लिए प्रोग्राम का परीक्षण किया, यह देखने के लिए कि क्या कोई किनारे के मामले हैं, लेकिन मैंने यह जाँचने में परेशान नहीं किया कि क्या यह उन मानों के लिए काम करेगा। जाहिरा तौर पर crenellation और crenelation दोनों सही हैं, इसलिए मैं इसे छोड़ दूँगा। बाद में यह देखने के लिए वापस आऊंगा कि क्या मैं कुछ कोष्ठक और व्हाट्सएप को हटा सकता हूं।
स्तर नदी सेंट

लिंक के लिए कोई समस्या नहीं है? मुझे लगा कि यह दूसरों के लिए उपयोगी होगा क्योंकि मैंने इसे परीक्षण करने के लिए उपयोग किया था: पी वर्तनी संपादन के संबंध में, मैंने इसे पहली बार मिलने वाले परिणाम में बदल दिया, क्योंकि मैंने कभी भी उस शब्द को नहीं देखा है जो वास्तव में उपयोग किया गया है। मैं रूबी (कुछ भी नहीं, वास्तव में) के बारे में ज्यादा पता नहीं है, लेकिन आप बदल सकते हैं i%2==0करने के लिए i%2<1एक बाइट (मैं ideone लिंक को यह परिवर्तन किया है) को बचाने के लिए।
काडे

क्या आपको वास्तव में #अंतिम पंक्ति के लिए भी पैडिंग की आवश्यकता है ? उदाहरण के लिए, बहुत अंतिम आकृति #में, नीचे दाएं कोने में परिधि समान नहीं है ?
रेटो कोराडी

@RetoKoradi यह वास्तव में एक ही परिधि होगी - ऐसा लगता है कि कोड में अतिरिक्त शामिल है #क्योंकि यह पहले से ही हर पंक्ति को समाप्त करने का तरीका है, इसलिए यह एक जगह डालने से कम बाइट्स है। (मैं रूबी नहीं जानता, हालांकि ...)।
ट्राइकोप्लाक्स

1
@trichoplax आपका अंतर्ज्ञान सही है। पैडिंग इसलिए "# "नहीं है " #"क्योंकि उत्तरार्द्ध #विषम एम के लिए 2 आसन्न देगा जो निश्चित रूप से नहीं चाहता है। #एम के लिए 2 आसन्न कोई नुकसान नहीं करता है, इसलिए मैं उस के साथ चला गया। मैंने कोशिश नहीं की है ljust, यह उस के साथ अधिक सफाई से करना संभव हो सकता है, लेकिन यह इतना स्पष्ट नहीं होगा कि मैं प्रति पंक्ति बिल्कुल एम अक्षर प्रिंट कर रहा हूं।
स्तर नदी सेंट

5

सी, 109 97 बाइट्स और शुद्धता प्रमाण

मैं अपना समाधान लिख रहा था, लेकिन @steveverrill ने मुझे हरा दिया। मुझे लगा कि मैं इसे सभी को साझा करूँगा, क्योंकि मैंने इस्तेमाल की गई रणनीति के लिए एक शुद्धता प्रमाण शामिल किया है।

कम किया गया कोड:

m,n,x;main(){for(scanf("%i%i",&m,&n); n;)putchar(x<m?"# "[x%2*(++x^m||~n&1)&&n^1]:(x=0,n--,10));}

कटौती से पहले:

m,n,x;

main(){
    for(scanf("%i%i",&m,&n); n;) 

        /* If x == m, prints out a newline, and iterates outer 
         * loop (x=0,n--) using comma operator.
         * Otherwise, paints a '#' on :
         *     Every even column (when x%2 is 0)
         *     On odd columns of the last row (++x^m||~n&1 is 0)
         *     On the first row (when n^1 is 0)
         * And a ' ' on anything else (when predicate is 1) */
        putchar(x<m?"# "[x%2*(++x^m||~n&1)&&n^1]:(x=0,n--,10));
}

रणनीति और प्रमाण:

अधिकतम क्रमिक समीकरण (M + 1) (N + 1) - ((M + 1) (N + 1)) mod 2 की शुद्धता को मानते हुए , निम्नलिखित उपयोग की गई इष्टतम रणनीति के बारे में बताता है और प्रेरण द्वारा इसकी शुद्धता को सिद्ध करता है:

विषम एम के लिए, हम एम / 2 + 1 उंगलियों के साथ हाथ जैसी आकृति बनाते हैं, उदाहरण के लिए:

3x2
# # 
###

5x3
# # #
# # #
#####

अब हम यह साबित करते हैं कि यह रणनीति प्रेरण द्वारा सभी विषम एम के लिए इष्टतम है:

बेस केस: M = N = 1
एकल कक्ष भरा हुआ है। समाधान (1 + 1) * (1 + 1) = 2 * 2 = 4 के बाद से सही है, और एक वर्ग में 4 पक्ष हैं।

चौड़ाई पर इंडक्शन:
मान लें कि हाथ के आकार की रणनीति (N, M-2) के लिए काम करती है , जहाँ M विषम है, अर्थात, इसका पेरिमिटर इष्टतम है और (N + 1) (M - 2 + 1) + (M) -1) (एन + 1)) मॉड 2 । अब हम दिखाते हैं कि यह (N, M) के लिए काम करेगा ।

एक उंगली जोड़ने की प्रक्रिया बहुभुज से एक किनारे को हटा देती है, और 3 + 2 एन को जोड़ती है । उदाहरण के लिए:

 5x3 -> 7x3
 # # # $
 # # # $
 #####$$

इसे हमारी परिकल्पना के साथ जोड़ते हुए कि पिछली परिधि इष्टतम थी, नई परिधि है:

(N + 1)*(M - 2 + 1) - ((M+1)*(N+1)) mod 2 - 1 + 3 + 2*N
(N + 1)*(M + 1) - ((M-1)*(N+1)) mod 2 - 2(N + 1) - 1 + 3 + 2*N
(N + 1)*(M + 1) - ((M-1)*(N+1)) mod 2

चूँकि हम modulo 2 अंकगणितीय के साथ काम कर रहे हैं,

((M-1)*(N+1)) mod 2 = ((M+1)*(N+1)) mod 2

इस प्रकार, यह साबित करना कि उंगलियों को जोड़कर चौड़ाई बढ़ाना एक इष्टतम परिधि की ओर जाता है।

ऊंचाई पर इंडक्शन:
मान लें कि हैंड-शेप स्ट्रेटेजी काम करती है (N-1, M) , जहां M विषम है, यानी इसकी परिधि इष्टतम है और N (M + 1) + ((M + 1) N) mod है २ । अब हम दिखाते हैं कि यह (N, M) के लिए काम करेगा ।

हाथ की ऊंचाई बढ़ाने से केवल पहले और हर दूसरे एक्स-इंडेक्स पर स्थित उंगलियां लम्बी हो जाती हैं। प्रत्येक ऊंचाई वृद्धि के लिए, प्रत्येक उंगली परिधि के दो जोड़ता है, और देखते हैं (एम + 1) / 2 उंगलियों, इस प्रकार, में वृद्धि एन की वृद्धि हो जाती है 2 (एम + 1) / 2 = एम + 1 में परिमाप।

इस परिकल्पना के साथ संयोजन करते हुए, हमारे पास यह है कि नई परिधि है:

N*(M + 1) + ((M+1)*N) mod 2 + M + 1
(N + 1)*(M + 1) + ((M+1)*N) mod 2

मॉड्यूलर अंकगणित हमें अंतिम अवधि को सरल बनाने की अनुमति देता है, ताकि हम प्राप्त करें:

(N + 1)*(M + 1) + ((M+1)*(N+1)) mod 2

यह मानते हुए कि समाधान सभी N> 0 और विषम M> 0 के लिए इष्टतम है।

एम के लिए भी, हम बोर्ड को उसी तरह से भरते हैं जैसे हम विषम एम के लिए करते हैं, लेकिन हम अंतिम खंड में crenelations जोड़ते हैं, उदाहरण के लिए:

4x3
# ##
# # 
####

6x4
# # #
# # ##
# # #
######

अब हम साबित करते हैं कि यह रणनीति इष्टतम है।

यहां तक ​​कि एम के लिए प्रेरण:
मान लें कि समाधान एम (-1, जैसा कि अंतिम एम में साबित हुआ) के साथ (एन, एम -1) के लिए सही है, जिसमें एक इष्टतम परिधि (एन + 1) एम है - ( एम (एन + 1)) मॉड 2 । अब हम दिखाते हैं कि यह (N, M) के लिए काम करेगा।

उंगलियों को बढ़ाने की तरह, प्रत्येक crenelation दो को बहुभुज की परिधि में जोड़ता है। जोड़ा गया एन + एन मॉड 2 परिधि के कुल के लिए crenelations की कुल संख्या (एन + एन मॉड 2) / 2 है

इस परिकल्पना के साथ संयोजन करते हुए, हमारे पास यह है कि नई परिधि है:

(N + 1)*M - (M*(N+1)) mod 2 + N + N mod 2
(N + 1)*(M + 1) - (M*(N+1)) mod 2 + N mod 2 - 1
(N + 1)*(M + 1) - (M*(N+1)) mod 2 - (N + 1) mod 2

हमारे पास वह है

(M*(N+1)) mod 2 - (N + 1) mod 2 = ((M+1)*(N+1)) mod 2

क्योंकि यदि N विषम है, तो यह 0 = 0 पर कम हो जाता है, और यदि N सम है, तो यह घट जाता है

- A mod 2 - 1 = -(A + 1) mod 2

इस प्रकार रणनीति सभी M, N> 0 के लिए इष्टतम है ।


2
यह बहुत गणित है! क्या आप अपने द्वारा बनाई गई आकृति की परिधि की गणना नहीं कर सकते हैं, और यह दिखा सकते हैं कि यह प्रदान की गई अधिकतम कीमत से मेल खाती है? आप जानते हैं कि आपके पास कितनी "उंगलियां" हैं, प्रत्येक उंगली कितनी लंबी है, आदि इसलिए परिधि की गणना करना काफी आसान होना चाहिए।
रेटो कोराडी

सच। कुछ मामलों में, मुझे लगता है कि प्रेरण मार्ग अधिक सहज है, क्योंकि यह योगात्मक है, लेकिन हां, यह अधिक लंबी व्याख्या को जन्म देता है।
एंड्रे हार्डर

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