Wyzwanie
Biorąc pod uwagę graficzny kształt kształtu, określ, ile otworów jest w nim.
Nie duplikat
To pytanie zostało oznaczone jako możliwy duplikat Hrabiów . Uważam, że to wyzwanie różni się od wyzwania Count Island, ponieważ w tym musisz wymyślić, jak wyeliminować bloki dotykające granicy.
Wejście
Dane wejściowe będą podawane jako forma wprowadzania 2D, albo ciąg wielowierszowy, tablica ciągów lub tablica znaków. To reprezentuje kształt. Gwarantowany jest kształt w jednym kawałku, połączony krawędzią. Podaj sposób, w jaki chcesz pobierać dane wejściowe.
Wynik
Dane wyjściowe to pojedyncza liczba całkowita określająca, ile otworów ma kształt. Końcowy znak nowej linii jest dozwolony, ale nie ma innych początkowych lub końcowych białych znaków. Innymi słowy, wynik musi być zgodny z wyrażeniem regularnym ^\d+\n?$
.
Co to jest dziura?
Są to pojedyncze otwory:
####
# #
# #
####
####
# #
# ##
###
#####
# # #
# #
#####
To nie są dziury:
########
########
# ####
# ####
# ######
#
########
###
#
###
##########
#
# ########
# # #
# # #### #
# # ## #
# ###### #
# #
##########
Właściwie, jeśli szczelina łączy się z zewnętrzną krawędzią, nie jest to dziura.
Przypadki testowe
#####
# # # -> 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)
###
Możesz użyć dowolnej postaci zamiast „#” i zamiast spacji.
Kryteria punktacji obiektywnej
Wynik jest podawany jako liczba bajtów w twoim programie.
Zwycięski
Zwycięzcą zostanie zgłoszenie o najniższym wyniku do 4 kwietnia.
###|# #|##
jako przypadek testowy? To powinno być0
, prawda?Odpowiedzi:
MATLAB / Octave, 18 bajtów
Wypróbuj online!
Jest to anonimowa funkcja przyjmująca logiczną macierz jako dane wejściowe. Obiekt jest tworzony przez
true
wpisy (o określonej łączności), puste miejsce tofalse
wpisy.bweuler
następnie oblicza liczbę eulerową obrazu binarnego reprezentowanego przez tę macierz, czyli liczbę obiektów minus liczbę otworów.źródło
Mathematica,
5957 bajtówJest do tego wbudowany. Pobiera dane wejściowe jako macierz 2D
1
s (ściany) i0
s (dziury). Dla wygody oto wszystkie przypadki testowe w tym formacie wejściowym:Alternatywne rozwiązanie, 59 bajtów
To było moje oryginalne podejście. Opiera się również na wbudowanych komponentach, ale nie liczy bezpośrednio otworów (zamiast tego traktuje same otwory jako komponenty).
Przyjmuje taki sam format wejściowy jak powyżej, ale z zamianą ról
0
s i1
s.Powodem, dla którego muszę przekonwertować to na
Image
pierwsze, jest to, że w przeciwnym razie Mathematica rozważyłaby wszystko1
komórki jako część pojedynczego komponentu (ponieważ traktuje matrycę jako matrycę składową-etykietę). Dlatego jeśli jakakolwiek1
komórka przekroczy margines, usunie wszystkie z nich. GdyDeleteBorderComponents
zamiast tego zostanie użyty na obrazie, przeprowadzi niejawną kontrolę łączności, aby znaleźć komponenty.Alternatywnie, mógłbym zadzwonić jako
MorphologicalComponents
pierwszy , co zmieniłoby dane wejściowe w odpowiednią matrycę etykiet, ale jeśli to zrobięDeleteBorderComponents
, nie jest już zagwarantowane, że maksymalna etykieta komponentu odpowiada liczbie komponentów (ponieważ mógłbym usunąć mniejszy komponent).źródło
GenerateBuiltin
. Generuje wbudowane dla każdego wyzwania, które nie ma wbudowanego. PonadtoPerl 5 , 154 bajtów
152 bajty kodu + 2 bajty na
-p0
flagę.Wypróbuj online!
Myślę, że kod jest dość zrozumiały.
Jeśli potrzebujesz kilku wyjaśnień, aby zrozumieć, oto kilka kroków transformacji wykonanych przez program na prostym wejściu (pochodzącym stąd ), a następnie kilka wyjaśnień poniżej:
Najpierw
s/^ | $/A/gm;s/^.*\K | (?=.*$)/A/&&redo
zastąpi spacje na ramce (1. regex dla lewej / prawej, 2 dla dolnej / górnej) zA
(wybieram tę postać dość dowolnie).Następnie otrzymujemy szerokość kształtu
/.*/;$@="@+"-1;
.Teraz chcemy zastąpić każde miejsce, które jest połączone
A
z aA
(ponieważ spacja jest podłączona do aA
, oznacza to, że nie może być częścią dziury. To zrobione przezfor$%(A,X){(s/$%(.?.?.{$@})? /$%$1$%/s||s/ (.?.?.{$@})?$%/$%$1$%/s)&&redo}
. (Zauważysz, że to zrobiono raz dlaA
s i jeden dlaX
s - wyjaśnieniaX
poniżej podano poniżej. Istnieją dwa wyrażenia regularne:s/$%(.?.?.{$@})? /$%$1$%/s
zajmuje się spacjami po prawej lub na dole aA
. Is/ (.?.?.{$@})?$%/$%$1$%/s
spacjami na górze lub po lewej stronieA
.W tym momencie jedyne spacje, które pozostały w sznurek jest częścią otworów.
Podczas gdy są jeszcze spacje, powtarzamy:
- Aby wiedzieć, ile jest dziur, zastępujemy spację znakiem
X
(s/ /X/
) i zwiększamy licznik otworów ($\++
) i ponawiamy cały program (w rzeczywistości chcemy tylko powtórzyćfor
pętlę , ale jest mniej bajtów, aby powtórzyć cały program).- Następnie
for
pętla zastąpi każdą przestrzeń, która jest połączona zX
literą aX
, ponieważ są one częścią tego samego otworu.Na końcu
$\|=0
zapewnia, że jeśli nie ma otworów,0
zamiast pustego łańcucha drukowany jest znak a. I$\
jest domyślnie drukowane dzięki-p
flagom.źródło
Python 2, 282 bajtów
+100 do obsługi dotyków ukośnych TT_TT (czy naprawdę tego potrzebujemy?)
-119 dzięki wytycznym @Rod :)
Wypróbuj online . Pobiera na wejściu tablicę tablic znaków „#” i białych znaków.
Wyszukuje pierwsze białe znaki i oznacza je jako niepuste („#”). Rekurencyjnie sprawdź całe otoczenie, wypełniając wszystkie puste komórki. Jeśli jakakolwiek pusta komórka obecnego „dołka” wydaje się znajdować na liczniku obramowania, nie zmieni się, w przeciwnym razie zostanie zwiększona o 1. Powtarzaj proces, aż nie będzie już białych znaków.
źródło
sum(A,[])
do spłaszczeniaNone
s, ale to nie ma znaczenia)x=T[0];y=T[1]
->x,y=T
, to (prawdopodobnie) nie trzeba zadeklarowaćg=1
na 3 linii, można użyć<
albo>
do porównywania ciągów znaków (zajmieord()
wartość każdego char) pozwala zastąpićA[y][x]!='#'
zA[y][x]<'#'
, ponieważ' '<'#'
.Python 2,
233225222 bajtówmath_junkie : -8 bajtów
Pobiera na wejściu tablicę 2d logicznych / liczb całkowitych (0/1)
Wypróbuj online!
Wersja sformatowana:
źródło
print sum(m(x,y)...
zamiasta=
iprint a
C # 7, 364 bajty
Nie jestem zadowolony z tego ... może ktoś inny może to rozwiązać ... Jeśli będę miał energię później, odwrócę pierwszą pętlę i zobaczę, czy to może pomóc w przycięciu sprawdzania granic.
Wypróbuj online
Kompletny program, akceptuje wejście do standardowego wejścia, wyjście do standardowego wyjścia. Używa rozłącznych zestawów do określania tymczasowych dziur, a gdy zabija dowolne, dotykaj granic (z pewną unikalnością dla górnej krawędzi).
Sformatowany i skomentowany kod:
źródło
Func<List<string>, int>
aby usunąć puch i konsolę. Widziałem jednak, że masz funkcje lokalne, więc możesz nie mieć ich w func. Można po prostu skompilować do metodyint h(string[] s) { }
.Ślimaki , 48 bajtów
Nie golfowany:
źródło
JavaScript (ES6), 192 bajty
Na podstawie mojej odpowiedzi na Wykrywanie nieudanych zamków . Najpierw sznurek jest wypełniony spacjami, aby utworzyć obszar wokół kształtu. RegExp następnie wyszukuje dwa sąsiednie kwadraty, jeden zawierający
@
, jeden zawierający spację i zamienia je oba na@
. Jeśli nie może tego zrobić, wypełnia pole znakiem@
i liczy to jako nową dziurę. Na koniec odejmuje się jeden, aby uwzględnić otaczający obszar.źródło