कितने छेद हैं?


17

चुनौती

किसी आकृति के चित्रमय इनपुट को देखते हुए, निर्धारित करें कि उसमें कितने छेद हैं।

डुप्लिकेट नहीं

यह सवाल काउंट आइलैंड्स के संभावित डुप्लिकेट के रूप में चिह्नित किया गया था । मेरा मानना ​​है कि यह चुनौती काउंट आइलैंड चुनौती से अलग है क्योंकि इस एक में, आपको यह पता लगाना होगा कि सीमा को छूने वाले ब्लॉकों को कैसे खत्म किया जाए।

इनपुट

इनपुट को कुछ 2D फॉर्म के रूप में दिया जाएगा, या तो मल्टीलाइन स्ट्रिंग, स्ट्रिंग की एक सरणी, या वर्ण सरणियों की एक सरणी। यह आकृति का प्रतिनिधित्व करता है। आकार को केवल एक टुकड़े में होने की गारंटी है, जो किनारे से जुड़ा हुआ है। कृपया निर्दिष्ट करें कि आप कैसे इनपुट लेना चाहते हैं।

उत्पादन

आउटपुट एक एकल पूर्णांक है जो बताता है कि आकृति में कितने छेद हैं। अनुगामी न्यूलाइन की अनुमति है, लेकिन कोई अन्य प्रमुख या अनुगामी व्हॉट्सएप नहीं है। दूसरे शब्दों में, आउटपुट को नियमित अभिव्यक्ति से मेल खाना चाहिए ^\d+\n?$

एक छेद क्या है?

ये एकल छिद्र हैं:

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

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

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

ये छेद नहीं हैं:

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

###
#  
###

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

बहुत ज्यादा, अगर यह अंतर बाहरी किनारे से जुड़ता है, तो यह एक छेद नहीं है।

परीक्षण के मामलों

#####
# # # -> 2
#####

#####
#    
# ### -> 1
# # #
#####

####
## # -> 1 (things are connected by edges)
# ##
####

###
### -> 0 (You must handle shapes with no holes, but input will always contain at least one filled space)
###

आप '' '' के स्थान पर और रिक्त स्थान के स्थान पर किसी भी वर्ण का उपयोग कर सकते हैं।

उद्देश्य स्कोरिंग मानदंड

आपके प्रोग्राम में स्कोर को बाइट्स की संख्या के रूप में दिया गया है।

जीतना

विजेता 4 अप्रैल तक सबसे कम स्कोर के साथ जमा होगा।



2
क्या आप ###|# #|## परीक्षण के मामले के रूप में जोड़ सकते हैं ? यह 0सही होना चाहिए ?
मार्टिन एंडर



@SIGSEGV आपको इस ओर इशारा करने के लिए धन्यवाद; हालाँकि, मेरा मानना ​​है कि इस चुनौती में एक महत्वपूर्ण घटक है जो इसे अन्य चुनौती से अलग बनाता है अपने स्वयं के पद को वारंट करने के लिए (मैंने अंतर में संपादित किया है)। कृपया मुझे बताएं कि आप क्या सोचते हैं, और हम यदि आवश्यक हो तो चैट में चर्चा शुरू कर सकते हैं।
हाइपरनेत्रिनो

जवाबों:


12

MATLAB / ऑक्टेव, 18 बाइट्स

@(g)1-bweuler(g,4)

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

यह एक अनाम फ़ंक्शन है जो इनपुट के रूप में एक तार्किक मैट्रिक्स लेता है। ऑब्जेक्ट trueप्रविष्टियों (निर्दिष्ट कनेक्टिविटी के साथ) से बनता है , रिक्त स्थान falseप्रविष्टियां हैं।

bweuler फिर उस मैट्रिक्स द्वारा प्रतिनिधित्व की गई द्विआधारी छवि की यूलर संख्या की गणना करता है, जो कि छिद्रों की संख्या को घटाकर वस्तुओं की संख्या है।


8

गणितज्ञ, ५ ९ ५ by बाइट्स

1/.ComponentMeasurements[#,"Holes",CornerNeighbors->0>1]&

इसके लिए एक बिल्ट-इन है। 1S (दीवारों) और 0s (छेद) के 2D मैट्रिक्स के रूप में इनपुट लेता है । सुविधा के लिए, इस इनपुट प्रारूप में सभी परीक्षण मामले हैं:

{{{1,1,1,1},{1,0,0,1},{1,0,0,1},{1,1,1,1}},
 {{1,1,1,1},{1,0,0,1},{1,0,1,1},{1,1,1,0}},
 {{1,1,1,1,1},{1,0,1,0,1},{1,0,0,0,1},{1,1,1,1,1}},
 {{1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1},{1,0,0,0,1,1,1,1},{1,0,0,0,1,1,1,1},{1,0,1,1,1,1,1,1},{1,0,0,0,0,0,0,0},{1,1,1,1,1,1,1,1}},
 {{1,1,1},{1,0,0},{1,1,1}},
 {{1,1,1,1,1,1,1,1,1,1},{1,0,0,0,0,0,0,0,0,0},{1,0,1,1,1,1,1,1,1,1},{1,0,1,0,0,0,0,0,0,1},{1,0,1,0,1,1,1,1,0,1},{1,0,1,0,0,0,1,1,0,1},{1,0,1,1,1,1,1,1,0,1},{1,0,0,0,0,0,0,0,0,1},{1,1,1,1,1,1,1,1,1,1}},
 {{1,1,1,1,1},{1,0,1,0,1},{1,1,1,1,1}},
 {{1,1,1,1,1},{1,0,0,0,0},{1,0,1,1,1},{1,0,1,0,1},{1,1,1,1,1}},
 {{1,1,1,1},{1,1,0,1},{1,0,1,1},{1,1,1,1}}}

वैकल्पिक समाधान, 59 बाइट्स

यह मेरा मूल दृष्टिकोण था। यह घटक से संबंधित अंतर्निहित इन्स पर भी आधारित है, लेकिन सीधे छिद्रों की गणना नहीं करता है (इसके बजाय यह स्वयं को घटकों के रूप में मानता है)।

Max@*MorphologicalComponents@*DeleteBorderComponents@*Image

ऊपर के रूप में एक ही इनपुट प्रारूप लेता है, लेकिन 0s और 1s स्वैप की भूमिकाओं के साथ ।

इसका कारण यह है कि मुझे इसे Imageपहले बदलने की आवश्यकता है, अन्यथा, गणितज्ञ सभी 1-चलों को एक घटक के हिस्से के रूप में मानेंगे (क्योंकि यह मैट्रिक्स को घटक-लेबल मैट्रिक्स के रूप में मानता है)। इसलिए, यदि कोई भी 1मार्जिन मार्जिन को सीमित करता है , तो यह उन सभी को हटा देगा। जब DeleteBorderComponentsइसके बजाय एक छवि पर उपयोग किया जाता है, तो यह घटकों को खोजने के लिए एक अंतर्निहित कनेक्टिविटी जांच करेगा।

वैकल्पिक रूप से, मैं MorphologicalComponents पहले कॉल कर सकता था , जो इनपुट को एक उपयुक्त लेबल मैट्रिक्स में बदल देगा, लेकिन अगर मैं DeleteBorderComponentsदूसरा करता हूं तो इसकी गारंटी नहीं है कि अधिकतम घटक लेबल घटकों की संख्या से मेल खाता है (क्योंकि मैं एक छोटे घटक को हटा सकता हूं)।


5
वास्तव में, गणितज्ञ को हर चीज के लिए बिल्ट-इन मिला है ...
श्री एक्सकोडर

3
@ Mr.Xcoder मेरे पास एक अच्छा चुनौती विचार है: एक चुनौती का पता लगाएं जिसके लिए गणितज्ञ के पास कोई बिलिन नहीं है।
हाइपरन्यूट्रीनो

@HyperNeutrino अच्छा विचार है, लेकिन मुझे लगता है कि Mathematica के उपयोगकर्ता इसे भारी रूप से कम कर देंगे, दुर्भाग्य से, और मुझे नहीं पता कि क्या समुदाय अच्छी प्रतिक्रिया देगा ... =]
श्री Xcoder

1
@ हेपर न्युट्रीनो, शायद उसके लिए भी एक घर बना हुआ है :-)
ब्रायन मिंटन

@ ब्रायनमिंटन हाहा। वहाँ शायद एक में निर्मित Mathematica कहा जाता है GenerateBuiltin। यह किसी भी चुनौती के लिए बिल्ट-इन जेनरेट करता है जिसमें बिल्ट-इन नहीं होता है। इसके अलावा, मैं मार्टिन एंडर इनबॉक्स के लिए बुरा महसूस करता हूं, इसलिए यदि आप चाहें, तो इस चर्चा को यहां
हाइपरयूट्रीनो

4

पर्ल 5 , 154 बाइट्स

-p0ध्वज के लिए कोड + 152 बाइट्स के 152 बाइट्स ।

s/^ | $/A/gm;s/^.*\K | (?=.*$)/A/&&redo;/.*/;$@="@+"-1;for$%(A,X){$~="(.?.?.{$@})?";(s/$%$~ /$%$1$%/s||s/ $~$%/$%$1$%/s)&&redo}s/ /X/&&++$\&&redo}{$\|=0

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

मुझे लगता है कि कोड काफी आत्म-व्याख्यात्मक है।


यदि आपको समझने के लिए कुछ स्पष्टीकरणों की आवश्यकता है, तो यहां एक सरल इनपुट पर प्रोग्राम द्वारा किए गए परिवर्तनों के कुछ चरण दिए गए हैं ( यहां से आ रहे हैं ), इसके बाद कुछ स्पष्टीकरण bellow:

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

######
# ए
# ####
# # #
#### #
######

######
#AAAAA
#ए####
#ए# #
#### #
######

######
#AAAAA
#ए####
# ए # एक्स #
#### #
######

######
#AAAAA
#ए####
# A # XX #
####एक्स#
######

सबसे पहले, s/^ | $/A/gm;s/^.*\K | (?=.*$)/A/&&redoबॉर्डर में रिक्त स्थान (बाएं / दाएं के लिए 1 रेगेक्स, नीचे / ऊपर के लिए 2) के साथ प्रतिस्थापित करेंगे A(मैं उस चरित्र को काफी मनमाने ढंग से चुनता हूं)।
फिर, हम चौड़ाई को आकार के साथ प्राप्त करते हैं /.*/;$@="@+"-1;
अब, हम हर उस स्थान को बदलना चाहते हैं जो एक के Aसाथ जुड़ा हुआ है A(क्योंकि यदि कोई स्थान किसी से जुड़ा हुआ है A, तो इसका मतलब है कि यह एक छेद का हिस्सा नहीं हो सकता है। ऐसा किया गया है for$%(A,X){(s/$%(.?.?.{$@})? /$%$1$%/s||s/ (.?.?.{$@})?$%/$%$1$%/s)&&redo}। (आप देखेंगे कि यह किया गया है) एक बार As और एक के लिए Xs - स्पष्टीकरण के लिए Xbellow हैं)। यहां दो regex हैं: s/$%(.?.?.{$@})? /$%$1$%/sउन रिक्त स्थान से संबंधित हैं जो एक के दाईं ओर या नीचे हैं A। और s/ (.?.?.{$@})?$%/$%$1$%/sऊपर या बाईं ओर रिक्त स्थान के साथ A
इस बिंदु पर, स्ट्रिंग में छोड़े गए एकमात्र स्थान छेद का हिस्सा हैं।
जबकि अभी भी रिक्त स्थान हैं, हम दोहराते हैं:
- यह जानने के लिए कि वहाँ कितने छेद हैं, हम एक X( s/ /X/) और छेद के काउंटर को बढ़ाते हैं ( $\++), और पूरे कार्यक्रम को फिर से बनाते हैं (वास्तव में, हम केवल forलूप को फिर से करना चाहते हैं। , लेकिन यह पूरे कार्यक्रम को फिर से करने के लिए कम बाइट्स है)।
- फिर, forलूप प्रत्येक स्थान को बदल देगा जो कि ए के Xसाथ जुड़ा हुआ है X, क्योंकि वे एक ही छेद का हिस्सा हैं।
अंत में, $\|=0यह सुनिश्चित करता है कि अगर कोई छेद नहीं है, तो 0खाली स्ट्रिंग के बजाय एक मुद्रित किया जाता है। और झंडे $\के लिए स्पष्ट रूप से मुद्रित है -p


4

पायथन 2, 282 बाइट्स

तिरंगे को संभालने के लिए +100 TT_TT को छूता है (क्या हमें वाकई इसकी आवश्यकता है?)
-119 @Rod मार्गदर्शन के लिए धन्यवाद :)

इसे ऑनलाइन आज़माएं । इनपुट के रूप में वर्ण "#" और व्हॉट्सएप के सरणियों का सरणी लेता है।

A=input()
c=0
X=len(A[0])-1
Y=len(A)-1
def C(T):
 x,y=T
 global g
 if A[y][x]<'#':
    if y<1or y==Y or x<1or x==X:g=0
    A[y][x]='#';map(C,zip([x]*3+[min(x+1,X)]*3+[max(x-1,0)]*3,[y,min(y+1,Y),max(y-1,0)]*3))
while' 'in sum(A,[]):i=sum(A,[]).index(' ');g=1;C((i%-~X,i/-~X));c+=g
print c

पहले व्हॉट्सएप के लिए खोज करता है और इसे गैर-रिक्त ('#') के रूप में चिह्नित करता है। सभी खाली कक्षों को भरते हुए, पुन: इसे चारों ओर से देखें। यदि बॉर्डर काउंटर पर वर्तमान "होल" की कोई भी खाली सेल नहीं दिखती है, अन्यथा इसे 1 से बढ़ाया जाएगा। जब तक अधिक व्हाट्सएप न हो, तब तक इसे दोहराएं।


1
आप उपयोग कर सकते हैं sum(A,[])समतल
रॉड

1
इसके अलावा आप इस उत्तर की जांच कर सकते हैं , इसमें एक ही पुनरावर्ती तर्क है, और कुछ अन्य चालें भी हैं (जैसे कि पहली पंक्ति में "नाम बदलना")
रॉड

@ राशि के साथ ट्रिक बहुत अच्छी है, धन्यवाद। मैं अब इस सभी कुरूपता के बिना सभी 8 दिशाओं पर काम कर रहा हूं, आपका जवाब मदद कर सकता है। मैं उसके बाद अपडेट करूँगा
डेड पोसुम

ध्यान दें कि मेरे जवाब पर मैंने सूची को कम बाइट्स का उपयोग करने के लिए एक सूची समझ के अंदर पुनरावर्ती कार्य कहा था, लेकिन आपके मामले में आप सूची की लंबाई देख सकते हैं कि क्या वर्तमान सेल सीमाओं से संबंधित है (सूची की सामग्री बहुत अधिक होगी Nones, लेकिन वह अप्रासंगिक है)
रॉड

1
आप पर खोल सूची का उपयोग कर सकते x=T[0];y=T[1]-> x,y=T, आप (शायद) की घोषणा करने की जरूरत नहीं है g=13 लाइन पर है, और आप उपयोग कर सकते हैं <या >तार तुलना करने के लिए (लगेगा ord()प्रत्येक चार का मूल्य) आप को बदलने के लिए अनुमति देता है A[y][x]!='#'के साथ A[y][x]<'#', के बाद से ' '<'#'
रॉड

3

पायथन 2, 233 225 222 बाइट्स

math_junkie : -8 बाइट्स

इनपुट के रूप में बूलियन / पूर्णांक (0/1) की 2d सरणी लेता है

s=input()
o=[-1,0,1]
m=lambda x,y:0if x in[-1,len(s[0])]or y in[-1,len(s)]else 1if s[y][x]else(s[y].__setitem__(x,1),all([m(x+a,y+b)for a in o for b in o]))[1]
e=enumerate
print sum(m(x,y)-c for y,l in e(s)for x,c in e(l))

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

प्रारूपित संस्करण:

s = input()
o = [-1, 0, 1]
m = lambda x,y:
    0 if x in [-1, len(s[0])] or y in [-1, len(s)]
      else
        1 if s[y][x]
          else
            (s[y].__setitem__(x, 1),
             all([m(x + a, y + b) for a in o for b in o]))[1]
e = enumerate
print sum(m(x, y) - c for y, l in e(s) for x, c in e(l))

1
आप के print sum(m(x,y)...बजाय a=और के साथ कुछ बाइट्स बचा सकते हैंprint a
गणित नशेड़ी

1
इसके अलावा, कुछ छोटे व्हाट्सएप गोल्फ: टीआईओ
गणित के नशेड़ी

1

सी # 7, 364 बाइट्स

इससे कम खुश ... शायद कोई और इसे सुलझा सकता है ... अगर मेरे पास बाद में ऊर्जा होगी तो मैं पहले लूप को उलट दूंगा, और देखूंगा कि क्या यह सीमा की जाँच को ट्रिम करने में मदद कर सकता है।

using C=System.Console;class P{static void Main(){string D="",L;int W=0,H=0,z;for(;(L=C.ReadLine())!=null;H+=W=L.Length)D+=L;int[]S=new int[H*9];int Q(int p)=>S[p]<p?Q(S[p]):p;void R(int r)=>S[Q(r+=z)]=S[r]>0?z:0;for(z=H;z-->0;)if(D[z]<33){S[z]=z;R(1);R(W);R(W+1);R(W-1);}for(;++z<H;)S[Q(z)]*=z>H-W-2|z%W<1|z%W>W-2?0:1;for(;W<H;)z+=Q(W)<W++?0:1;C.WriteLine(z-H);}}

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

पूरा कार्यक्रम, मानक में इनपुट को स्वीकार करता है, आउटपुट को मानक से बाहर। अनंतिम छिद्रों को निर्धारित करने के लिए डिसऑइंट सेट का उपयोग करता है, और जब कोई स्पर्श सीमाओं को मारता है (शीर्ष-किनारे के लिए कुछ dodgyness के साथ)।

प्रारूपित और टिप्पणी कोड:

using C=System.Console;

class P
{
    static void Main()
    {
        string D="", // the whole map
            L; // initally each line of the map, later each line of output

        // TODO: some of thse might be charable
        int W=0, // width, later position
            H=0, // length (width * height)
            z; // position, later counter

        // read map and width
        for(;(L=C.ReadLine())!=null; // read a line, while we can
                H+=W=L.Length) // record the width, and increment height
            D+=L; // add the line to the map

        // disjoint sets
        int[]S=new int[H*9]; // generousness (relieve some bounds checking)
        // note that S[x] <= x, because we call R with decending values of z

        // returns whatever p points to
        int Q(int p)=>S[p]<p?Q(S[p]):p;
        // points whatever r points to at z if r is empty
        void R(int r)=>S[Q(r+=z)]=S[r]>0?z:0; // note that is never called when z=0

        // fill out disjoint sets
        for(z=H;z-->0;)
            if(D[z]<33) // if cell is empty
            {
                S[z]=z; // point it at itself

                // point the things next  to z at z
                R(1);
                R(W);
                R(W+1);
                R(W-1);
            }

        // zero sets which are against the left, bottom, or right edges
        for(;++z<H;)
            S[Q(z)]*=z>H-W-2|z%W<1|z%W>W-2?0:1; // TODO?: this suggests inverting the first loop (NOTE: would break S[x]<=x)

        // starting from the second row, count all the sets that point to this cell (ignores any non-zeros pointing to first row)
        for(;W<H;)
            z+=Q(W)<W++?0:1;

        C.WriteLine(z-H);
    }
}

Func<List<string>, int>फुल और कंसोल सामान को हटाने के लिए इसे कन्वर्ट करें । हालाँकि, मैंने देखा है कि आपके पास स्थानीय कार्य हैं, ताकि आप उन्हें एक फंक में रखने में सक्षम न हों। बस एक विधि को संकलित कर सकता है int h(string[] s) { }
TheLethalCoder

मुझे यकीन है कि यहाँ और भी बहुत कुछ है जिसे यहाँ सरल बनाया जा सकता है ...
TheLethalCoder

@ TheLethalCoder मैं इसे एक अलग रूप में परिवर्तित नहीं कर सकता, मुझे जवाब पसंद नहीं है, क्योंकि आपको एक मेमने की ज़रूरत नहीं है। हाँ ... पूरी चीज़ फूला हुआ लगता है ... लेकिन मैंने इसे म्यूट करते हुए एक अच्छा खर्च किया और कोई पर्याप्त प्रगति नहीं की, इसलिए मैंने 'बिट्टी' गोल्फिंग के कुछ पास किए और इसे आगे बढ़ाया। एक छोटा संस्करण प्रस्तुत करने के लिए स्वतंत्र महसूस करें, मैं इस एक से जुड़ा हुआ हूं।
विज़ुअलमेल

मेरा मतलब है कि इसे एक विधि में परिवर्तित करने और सभी कंसोल सामानों को हटाने के लिए, क्योंकि अब इसकी आवश्यकता नहीं होगी, 50-100 बाइट्स बंद करने जा रहा है (बस एक अनुमान है लेकिन यह बहुत बंद हो जाएगा)।
द लीथेलकोडर

@TheLethalCoder वास्तव में; मुझे उत्तर के रूप में फ़ंक्शन सबमिट करना पसंद नहीं है। मानक इनपुट सुंदर मानक है, और एक 'पूरा कार्यक्रम' कहीं भी संकलित करने और चलाने के लिए आसान है। मुझ पर शुरू कर दिया मत हो untyped lambdas ... जाहिर है, अगर वहाँ एक प्रतिस्पर्धा जावा जवाब था, तो मैं अपने मानकों थोड़ा slacking होगा ...
VisualMelon

1

घोंघे , 48 बाइट्स

!{\ z`+~}\ {t\ z!.!~=((lu|u.+r)!(.,~},!{t\ z!.!~

Ungolfed:

!{
    (\   z)+
    ~
}
\ 
{
    t \ 
    z !.!~
    ={
        (lu|u.+r)
        !(.,~)
    }
},
!{
    t \ 
    z !.!~
}

0

जावास्क्रिप्ट (ईएस 6), 192 बाइट्स

v=a=>Math.min(...a=a.map(s=>s.length))==Math.max(...a);
f=(s,t=(u=` `.repeat(w=s.search`
`+1))+`
`+s.replace(/^|$/gm,` `)+`
`+u,v=t.replace(RegExp(`( |@)([^]{${w},${w+2}})?(?!\\1)[ @]`),`@$2@`))=>t!=v?f(s,v):/ /.test(t)?f(s,t.replace(` `,`@`))+1:-1
<textarea id=i rows=10 cols=10></textarea><input type=button value=Count onclick=o.textContent=/^[\s#]+$/.test(i.value)*v(i.value.split`\n`)?f(i.value):`Invalid_Entry`><span id=o>

फेलिंग कास्टल्स का पता लगाने के मेरे जवाब के आधार पर । पहले स्ट्रिंग को आकार के चारों ओर एक क्षेत्र बनाने के लिए रिक्त स्थान के साथ गद्देदार किया जाता है। RegExp तब दो आसन्न वर्गों की तलाश करता है, एक जिसमें एक होता है @, जिसमें एक स्थान होता है, और दोनों को एक के साथ बदल देता है@ । यदि यह ऐसा नहीं कर सकता है, तो यह एक अंतरिक्ष में भरता है @और इसे एक नए छेद के रूप में गिना जाता है। अंत में एक को आसपास के क्षेत्र के लिए खाते में घटाया जाता है।


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