ASCII hamantaschen'i sayın!


18

Bugün Purim, bir geleneğin hamantaschen (tekil: hamantasch ) adı verilen dolgu ile üçgen şekilli kurabiye vermektir . Başka bir gelenek de ağır içmektir.

Ben en mükemmel fırıncı değilim .... Vermek için çok düzensiz boyutlu hamantaschen ve onlara vermek için çok arkadaş var! Size çerezlerimin bir resmini gönderirsem, kaç tane boyut ve doldurma yaptığımı söyleyebilir misiniz? Ama Purim ve çok fazla kod okumak için çok sarhoş olduğum için, yapabileceğiniz kadar küçük bir kod olması gerekiyor.

Tanımlar

Boyut

Bir hamantasch herhangi bir boyutta olabilir . En küçük hamantasch boyut 1'dir ve şuna benzer:

/\  --
--  \/

Bazen birden fazla hamantaschen çakışabilir . Aşağıdaki şekil iki hamantaschen (bir boyut 1, bir boyut 2) olarak sayılır:

 /\
/\ \
----

Bazı hamantaschen doldurma var . Bu, içerideki tüm boşlukları bir karakterle doldurarak belirtilecektir. 1 numara hamantaschen doldurma yapamaz unutmayın.

Biz edecek isim dolum ve büyüklüğüne göre hamantaschen. Biçimi kullanalım <filling> <size>ve doldurulmamışsa, - <size>(a yerine bir boşluk kullanabilirsiniz -, ancak işaretleme bundan hoşlanmaz).

İşte a . 2, a . 4ve a - 3:

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

Bunlar a @ 3, a . 2ve a - 4:

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

İşte daha zor bir şey. & 2Üst üste binen eğim nedeniyle beklediğinizden daha az dolgunun nasıl olduğunu görün - 3? Bir - 1, & 2a - 3ve bir & 4:

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

Giriş

Size bir metin dosyası veya tek bir hamantaschen dizesi verilecektir (isteğe bağlı son satırsonu ve isteğe bağlı olarak dolgulu son boşluk).

Sınırları

  • İpin geçerli olmasını bekleyebilirsiniz - yani, boşluk olmayan her karakter lezzetli tatlı bir hamantasch'a katkıda bulunur (neden hamur dökülür?).
  • Ayrıca yapılmasını bekleyebilirsiniz düzgün dolu olduğunu, her tamamen tutarlı bir ASCII karakter ile dolu olacak hamantasch - - doldurulmamış için ASCII 32 veya doldurulmuş (hariç bir şey 32..127 ya da değil /, \ve -).
  • Bu hamantaschen 3 boşlukta istiflenmez . Hepsi /ve \görünür olacak. Tüm -tarafından engellenmediğini /ve \görünür olacaktır. Doldurma sonuncudur.
  • Tüm hamantaschen yatay çizgilerinin en az yarısına (yuvarlama) sahip olacak.
  • Herhangi bir bitişik dolum bloğu sadece onu çevreleyen en küçük hamantasch'i doldurur .

Çıktı

Yukarıdaki kriterleri karşılayan tüm hamantaschen "isimleri" listesini döndürün. Çıktı istediğiniz biçimde olabilir (dize, karma, stdout vb.).

Test senaryoları

Test örneği # 1

Giriş # 1:

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

Çıktı # 1:

. 2
. 2
- 4
@ 3
* 4

Test Çantası # 2

Giriş # 2:

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

Çıktı # 2:

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

Test # 3

Giriş # 3:

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

Çıktı # 3:

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

Test # 4

Giriş # 4:

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

Çıktı # 4:

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

Geçersiz Test Durumu # 5

Giriş:

/\
\/

Çıktı:

Bunu halletmenize gerek yok.


Hamentaschen'in çakıştığı ancak aynı yatay çizgiye sahip olmadığı bir test senaryosuna ne dersiniz? Hatta biri diğerinin yatay çizgisini bile engelleyebilir.
gururlu haskeller

@proudhaskeller Tamam, bitti. Ancak, bunu metne koydum, bu 2 boşluk. Biz olacaktır her zaman görmek /ve \ ve -koz dolum hep olacak.
Charles

2
@EasterlyIrk Başka önemli bitler de var - Esther Kitabı'nı okumak (ve kötü adamlara yuhalamak), fakirlere vermek - ve kostüm giyinmek gibi daha az temel şeyler.
Charles

1
yeniden alakalı oldu!
downrep_nation

1
İlk sıfır sütununa göre, hariç tüm köşe sütunlarınız (1,0)kapalıdır +1. Yine de ne demek istediğini biliyorum ve katılmıyorum. İki üst s'nin sadece sağ üst ve sol üst değil (2, 2), a'nın üst merkezi olan hangi gösterge var ? Göremediğim bir şey yok. Ve aynı mantık için de geçerlidir . Mümkün olan maksimum hamantaschen varsaymak için bir kural eklemek istemiyorsanız ...- 2- 1(3, 2)
Michael Plotke

Yanıtlar:


4

C #, 496452 bayt

Düzenleme: sınırları kontrol ile bir hata bulundu ... ama aynı zamanda kendi kodumu anlamak zorunda zorunda bayt bir yük çizgili. Yerel işlevin açılması biraz yardımcı oldu ve C # 7'ye özgü kodu kaldırdı. Bu soru çok eğlenceli oldu.

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;}}}

Çevrimiçi Deneyin

Komple program, boşluk dolgulu girişi standart girişe, çıkışları standart çıkışa bekler. Çıktı, her satır için bir giriş ve sondaki satır beslemesi ile. Çerezler, artan boyut sırasına göre, en sol üstteki soldan çıkarılır. Kuralları anlamam çok zaman aldı, ancak sağlanan tüm örnekleri geçtiğini düşünüyorum.

Tüm ızgarayı geçerli Hamantaschen için tekrar tekrar arayarak çalışır ve 'izin verilen' boyutunu artırır. Her bir hücre için, aşağıdaki, yukarı ve aşağı kontrol eder \ve /her iki tarafında kadarıyla olabildiğince. Bir sonraki satırın çok sayıda olduğunu fark ederse -ve geçerli boyut 'izin verilen' boyutsa, dolguyu belirler ve girdiyi yazdırır.

Doldurma, 'kullanılmayan' bir hücre arayarak çerezin tüm alanını keşfederek bulunur. Kullanılmayan bir hücre bulunduğunda, kullanılmış olarak işaretlenir (izin verilen boyutu artırdığımız için, onu içeren en küçük çerez olduğumuzu biliyoruz) ve dolguyu kaydediyoruz.

Biçimlendirilmiş ve yorumlanmış 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
            }
    }
}

4 test durumu için çıktılar:

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

Bu C # ne kadar kompakt olduğuna şaşırdım! Aferin!
O Charles

Tek geçerli cevap! Neredeyse işlevsel olan bir şeyim var, ancak birkaç hata var (ama yine de kendimi kazanan olarak ayarlamam)
Charles
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.