Policz hamantaschen ASCII!

18

Dzisiaj jest Purim, w którym jednym ze zwyczajów jest rozdawanie ciasteczek w kształcie trójkąta z nadzieniem zwanych hamantaschen (liczba pojedyncza: hamantasch ). Innym zwyczajem jest picie dużych ilości.

Nie jestem najdoskonalszym piekarzem ... Mam tak wiele nieregularnych rozmiarów hamantaschen do rozdania i tylu przyjaciół, którzy mogą je dać! Jeśli przesłałem Ci zdjęcie moich ciasteczek, czy możesz mi powiedzieć, ile mam ich rozmiarów i wypełnienia? Ale ponieważ jest to Purim i jestem zbyt pijany, aby czytać dużo kodu, musi on być tak mały, jak to tylko możliwe.

Definicje

Rozmiar

Hamantasch może mieć dowolny rozmiar . Najmniejszy hamantasch ma rozmiar 1 i wygląda następująco:

/\  --
--  \/

Czasami wiele hamantaschen może się nakładać . Poniższy kształt liczy się jako dwa hamantaschen (jeden rozmiar 1, jeden rozmiar 2):

 /\
/\ \
----

Niektóre hamantaschen mają nadzienie . Zostanie to wskazane poprzez wypełnienie wszystkich białych znaków wewnątrz znakiem. Pamiętaj, że hamantaschen rozmiar 1 nie może mieć wypełnienia.

Będziemy wymienić Hamantaschen podstawie napełniania i wielkości. Użyjmy formatu, <filling> <size>a jeśli nie zostanie wypełniony - <size>(zamiast spacji możesz użyć spacji -, ale przecena nie lubi tego).

Oto a . 2, a . 4i a - 3:

          /\
         /./\
 ----   /./  \
 \../  /./    \
  \/   --------

Są to: @ 3a . 2oraz a - 4:

          /\
         / /\
  /\    / /@@\
 /..\  / /@@@@\
 ----  --------

Oto coś trudniejszego. Widzisz, jak & 2ma mniej wypełnienia, niż można się spodziewać ze względu na nachylenie nakładania się - 3? Ma a - 1, & 2a - 3i a & 4:

--------
\   \/&/
 \  /\/
  \/&/
   \/

Wejście

Otrzymasz plik tekstowy lub pojedynczy ciąg hamantaschen (opcjonalnie końcowy znak nowej linii i opcjonalnie dopełniony końcowy biały znak, aby być parzystym).

Granice

  • Możesz oczekiwać, że łańcuch będzie prawidłowy - to znaczy, że każda postać niebiałego znaku przyczynia się do cudownie słodkiego hamantascha (po co marnować ciasto?).
  • Można również oczekiwać, iż zostanie poprawnie wypełniony lub nie - to znaczy każdy hamantaszen zostanie całkowicie wypełniony spójny znak ASCII - ASCII 32 niewypełnionych lub cokolwiek 32..127 dla wypełniony (z wyjątkiem /, \i -).
  • Te hamantaschen nieukładane w stosy na 3 pola . Wszystko /i \będzie widoczne. Wszystkie -, które nie są zablokowane /i \będą widoczne. Wypełnianie jest ostatnie.
  • Wszystkie hamantaschen będą miały co najmniej połowę linii poziomej (zaokrąglenie w górę).
  • Każdy ciągły blok wypełnienia wypełnia tylko najmniejszy hamantasch, który go otacza.

Wynik

Zwróć listę „nazw” wszystkich hamantaschen, które można znaleźć spełniające powyższe kryteria. Dane wyjściowe mogą mieć dowolną formę (ciąg, skrót, stdout itp.).

Przypadki testowe

Przypadek testowy nr 1

Wejście nr 1:

          /\
         / /\
  /\    / /@@\
 /..\  / /@@@@\
 ----  --------
    /\
   /**\
  /*/\*\
 /*/..\*\
 --------

Wyjście nr 1:

. 2
. 2
- 4
@ 3
* 4

Przypadek testowy nr 2

Wejście nr 2:

  /\----
 /\/\*\/
/ /\d\/
------

Wyjście nr 2:

- 3
- 2
d 2
- 1    
* 2
- 1

Test nr 3

Wejście nr 3:

----
\/\/
/\/\  /\
---- /::\
     ----

Wyjście nr 3:

- 1
- 1
- 2
- 1
- 1
- 2
: 2

Test nr 4

Wejście nr 4:

 /\/\
/ /\$\
-/--/\\
 --/--\
  /xxx/\
 /xxx/##\
 ---/----\
   /      \
   -------- 

Wyjście 4:

$ 2
x 4
- 3
- 2
- 4
- 1
- 1
# 2

Nieprawidłowy przypadek testowy nr 5

Wejście:

/\
\/

Wynik:

Nie musisz sobie z tym poradzić.

Nie ten Charles
źródło
Co powiesz na przypadek testowy, w którym hamentaschen zachodzą na siebie, ale nie mają tej samej linii poziomej? Można nawet zablokować linię poziomą drugiego.
dumny haskeller
@proudhaskeller Ok, gotowe. Jednak i właśnie umieściłem to w tekście, jest to 2 spacja. Będziemy zawsze widzieć wszystko /i \ , i -zawsze będzie wypełnienie atutem.
Nie to, że Charles
2
@EasterlyIrk Są też inne ważne elementy - czytanie Księgi Estery (i wygwizdywanie złych facetów), rozdawanie biednym - i mniej fundamentalne rzeczy, takie jak ubieranie się w kostiumy.
Nie to, że Charles
1
uczyniło to znowu istotnym!
downrep_nation
1
Na podstawie początkowej kolumny zero wszystkie kolumny wierzchołków, z wyjątkiem (1,0), są wyłączone +1. Wiem jednak, co masz na myśli i nie zgadzam się. Jakie jest wskazanie, że (2, 2)jest to górny środek a, - 2a nie tylko górny prawy i lewy z dwóch górnych - 1s? Brak, który widzę. Ta sama logika dotyczy (3, 2). Chyba że chcesz dodać regułę zakładającą maksymalne możliwe hamantaschen ...
Michael Plotke

Odpowiedzi:

4

C #, 496 452 bajtów

Edycja: znalazłem błąd z sprawdzaniem granic ... ale także rozłożył ładunek bajtów, zmuszony do zrozumienia mojego własnego kodu. Rozwijanie funkcji lokalnej nieco pomogło i usunęło kod specyficzny dla C # 7. To pytanie było świetną zabawą.

using C=System.Console;class P{static void Main(){string D="",L;int W=0,H=0,z=0,d,q,c,j,b;for(;(L=C.ReadLine())!=null;H+=W=L.Length)D+=L;var B=new int[H];for(d=W;(d=-d)>0||++z<H*H;)for(c=1,q=z%H;c<=z/H&q%W+c<W&q>=d&q<H+d&&D[q]==(d>0?92:47)&D[j=q+c]==(d<0?92:47);q-=d+1,c+=2){for(b=0;j>q;)b+=D[--j-d]==45?2:0;for(char h='-',e;c==z/H&b>c;C.WriteLine(h+" "+c/2))for(b=c++;b>1;j=q+=d+1,b-=2)for(;j<q+b;)B[j]=h=B[j]<1&h==45&(e=D[j++])!=47&e!=92&e>32?e:h;}}}

Wypróbuj online

Kompletny program, oczekuje wypełnienia spacją wejścia do standardowego wejścia, wyjścia do standardowego wyjścia. Dane wyjściowe to jeden wpis w wierszu z końcowym przesuwem wiersza. Pliki cookie są wyprowadzane w rosnącej kolejności, od lewej do lewej strony. Zrozumienie zasad zajęło mi sporo czasu, ale myślę, że spełnia wszystkie podane przykłady.

Działa poprzez wielokrotne przeszukiwanie całej siatki pod kątem prawidłowego Hamantaschen, zwiększając „dozwolony” rozmiar. Dla każdej komórki sprawdza w górę i w dół, postępując zgodnie z \i /po obu stronach, o ile to możliwe. Jeśli zauważy, że następny wiersz ma wiele -, a bieżący rozmiar jest „dozwolonym” rozmiarem, wówczas określa wypełnienie i drukuje wpis.

Wypełnienie można znaleźć, badając całą przestrzeń pliku cookie, szukając „nieużywanej” komórki. Gdy nieużywana komórka zostanie znaleziona, jest oznaczona jako używana (ponieważ zwiększamy dozwolony rozmiar, wiemy, że jesteśmy najmniejszym ciasteczkiem, które ją zawiera) i rejestrujemy wypełnienie.

Sformatowany i skomentowany kod:

using C=System.Console;

class P
{
    static void Main()
    {
        //   32
        // - 45
        // / 47
        // \ 92
        // range 32..127 (no mod for you)

        string D="", // the whole map
            L; // initally each line of the map, later each line of output

        int W=0, // width
            H=0, // length (width * height)
            z=0, // search tracker
            d, // check direction (this is backwards (1 byte saving!))
            q, // check tracker
            c, // counter (truely, this is the distance from the right to the left)
            //M, // c max (now inlined as z/H)
            j, // horiontal tracker
            b; // - count, and reverse 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

        var B=new int[H]; // whether this filling has been used already (0 -> false, >0 -> true)

        for(d=W; // init direction
            (d=-d)>0|| // swap direction, else increment z (this allows us to run the check for the same z twice with opposite direction)
            ++z<H*H; // for all M, for all q (z<H -> M=z/H=0 -> no valid cookies, so we can safetly skip them)
            )
            for(//M=z/H, // c allow (now inlined)
                c=1, // reset counter
                q=z%H; // note position
                c<=z/H& // counter check
                // no need for a left check: if we run off the left end, then the right check will necessarily fail
                q%W+c<W& // right check
                q>=d& // high check
                q<H+d&& // low check (short-circuit lookups)
                D[q]==(d>0?92:47)&D[j=q+c]==(d<0?92:47); // /\ or \/ check, and set j=q+c
                    q-=d+1, // move left tracker
                    c+=2) // increase counter (move right tracker)
            {
                // count the number of '-' into b
                for(b=0; // zero b
                    j>q; // for each element in the row below
                        ) // empty
                    b+=D[--j-d]==45?2:0; // add 2 to b if we tap a '-'

                // j = q

                // check valid before looking up cHaracter (so we don't mark unused stuff as taken)
                // if we are at the current max count, and we have enough -, then we are valid and should be commited
                for( // this runs either one or zero times, we only have a for here (rather than an if) so we can ditch a pair of braces
                    char h='-', // default filling
                         e; // filling we are considering
                    c==z/H&b>c;
                        C.WriteLine(h+" "+c/2)) // print filling and count
                    // continuously compute character
                    for(b=c++; // count b backwards, starting from c (add 1 to c so we can /2 in print)
                        b>1;j=q+=d+1,b-=2) // count q backwards toward z%H (where q came from), and b backwards toward 1 (for each row)
                        for(;j<q+b;) // for each cell in row
                            B[j]= // mark cell as taken (h,e > 0)
                            h= // record filling
                                B[j]<1& // check cell not already used
                                h==45& // '-'
                                (e=D[j++])!=47& // '/'
                                e!=92& // '\'
                                e>32 // ' '
                                ?e:h; // take first filling we can
                    // c runs out after this (exists both loops), so no need to action
            }
    }
}

Dane wyjściowe dla 4 przypadków testowych:

testcase #1
. 2
. 2
@ 3
- 4
* 4

testcase #2
- 1
- 1
- 2
d 2
* 2
- 3

testcase #3
- 1
- 1
- 1
- 1
- 2
- 2
: 2

testcase #4
- 1
- 1
- 2
$ 2
# 2
- 3
x 4
- 4
VisualMelon
źródło
Dziwi mnie, jak kompaktowe jest to w C #! Dobra robota!
Nie żeby Charles
Jedyna poprawna odpowiedź! Mam coś, co jest prawie funkcjonalne, ale ma kilka błędów (ale i tak nie ustawiłbym się jako zwycięzca)
Nie to, że Charles