นับ ASCII hamantaschen!


18

วันนี้ Purim ที่หนึ่งประเพณีคือการให้คุกกี้รูปสามเหลี่ยมที่มีการกรอกที่เรียกว่าhamantaschen (เอกพจน์: hamantasch ) ประเพณีอีกอย่างคือการดื่มหนัก

ฉันไม่ใช่คนทำขนมปังที่สมบูรณ์แบบที่สุด .... ฉันมี hamantaschen ขนาดผิดปกติมากมายที่จะให้ออกไปและเพื่อนมากมายที่จะให้พวกเขา! ถ้าฉันส่งรูปคุกกี้มาให้คุณคุณบอกฉันได้ไหมว่าฉันมีขนาดและขนาดเท่าไร? แต่เนื่องจากเป็น Purim และฉันเมาเกินกว่าที่จะอ่านรหัสได้มากจึงต้องมีรหัสขนาดเล็กเท่าที่คุณสามารถทำได้

คำนิยาม

ขนาด

hamantasch สามารถใด ๆขนาด hamantasch ที่เล็กที่สุดคือขนาด 1 และมีลักษณะดังนี้:

/\  --
--  \/

บางครั้ง hamantaschen หลายตัวสามารถซ้อนทับกันได้ รูปร่างด้านล่างนับเป็นสอง hamantaschen (หนึ่งขนาด 1, หนึ่งขนาด 2):

 /\
/\ \
----

hamantaschen บางคนมีไส้ นี้จะถูกระบุโดยการกรอกช่องว่างทั้งหมดภายในด้วยตัวละคร โปรดทราบว่าขนาด 1 hamantaschen ไม่สามารถเติมได้

เราจะตั้งชื่อ hamantaschen ตามขนาดและการบรรจุ ลองใช้รูปแบบ<filling> <size>และหากไม่ได้กรอกข้อมูล- <size>(คุณสามารถใช้ช่องว่างแทน a -ได้ แต่ markdown ไม่เป็นเช่นนั้น)

ที่นี่มี. 2เป็น. 4และ- 3:

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

เหล่านี้คือ@ 3a . 2และ a - 4:

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

นี่คือสิ่งที่ยากขึ้น มาดูกันว่าการ& 2เติมมีน้อยกว่าที่คุณคาดหวังเนื่องจากความเอียงจากการทับซ้อนกัน- 3อย่างไร มันมี- 1, & 2a - 3และ a & 4:

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

อินพุต

คุณจะได้รับไฟล์ข้อความหรือสตริงเดี่ยวของ hamantaschen (ขึ้นบรรทัดใหม่ที่เป็นตัวเลือกและช่องว่างที่ต่อท้ายแบบเป็นทางเลือกซึ่งจะเป็นทางเลือก)

ขีด จำกัด

  • คุณสามารถคาดหวังได้ว่าสายอักขระนั้นใช้ได้ - นั่นคือตัวละครที่ไม่ใช่ช่องว่างทุกตัวมีส่วนในแฮมแมนเทคแสนหวาน (ทำไมต้องเป็นแป้งเสีย)
  • นอกจากนี้คุณยังสามารถคาดหวังที่จะเต็มไปอย่างถูกต้องหรือไม่ - นั่นคือแต่ละ hamantasch มันจะเต็มไปทั้งหมดด้วยตัวอักษร ASCII ที่สอดคล้องกัน - ASCII 32 ไม่สำเร็จหรืออะไร 32..127 สำหรับเต็ม (ไม่รวม/, \และ-)
  • hamantaschen เหล่านี้ไม่ได้ซ้อนใน 3 ช่องว่าง ทั้งหมด/และ\จะสามารถมองเห็นได้ ทั้งหมด-ที่ไม่ได้ถูกบล็อกโดย/และ\จะปรากฏให้เห็น การเติมจะมาถึงขั้นสุดท้าย
  • hamantaschen ทั้งหมดจะมีเส้นแนวนอนอย่างน้อยครึ่ง (ปัดเศษขึ้น)
  • บล็อกที่ต่อเนื่องกันของการเติมจะเติม Hamantasch ที่เล็กที่สุดที่อยู่รอบ ๆ มัน

เอาท์พุต

ส่งคืนรายการ "ชื่อ" ของ hamantaschen ทั้งหมดที่สามารถพบได้ตามเกณฑ์ด้านบน เอาต์พุตสามารถอยู่ในรูปแบบใดก็ได้ที่คุณต้องการ (สตริงแฮช stdout และอื่น ๆ )

กรณีทดสอบ

กรณีทดสอบ # 1

อินพุต # 1:

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

เอาท์พุท # 1:

. 2
. 2
- 4
@ 3
* 4

กรณีทดสอบ # 2

อินพุต # 2:

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

เอาท์พุท # 2:

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

ทดสอบ # 3

อินพุต # 3:

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

เอาท์พุท # 3:

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

ทดสอบ # 4

อินพุต # 4:

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

เอาท์พุท # 4:

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

กรณีทดสอบไม่ถูกต้อง # 5

การป้อนข้อมูล:

/\
\/

เอาท์พุท:

คุณไม่จำเป็นต้องจัดการกับสิ่งนี้


กรณีทดสอบที่ hamentaschen ซ้อนทับกัน แต่ไม่มีเส้นแนวนอนเหมือนกันหรือไม่? หนึ่งอาจปิดกั้นเส้นแนวนอนของผู้อื่น
ภูมิใจ haskeller

@proudhaskeller ตกลงเสร็จแล้ว อย่างไรก็ตามและฉันเพิ่งใส่ลงไปในข้อความนี่คือ 2 สเปซ เราจะเสมอดูทั้งหมด/และ\ และ-จะเสมอคนที่กล้าหาญไส้
ไม่ใช่ Charles

2
@EasterlyIrk มีบิตที่สำคัญอื่น ๆ เช่นกัน - การอ่านหนังสือเอสเธอร์ (และโห่ที่คนเลว) ให้กับคนยากจน - และสิ่งพื้นฐานน้อยกว่าเช่นการแต่งกายในชุด
ไม่ใช่ Charles

1
ทำให้มีความเกี่ยวข้องอีกครั้ง!
downrep_nation

1
ขึ้นอยู่กับคอลัมน์เริ่มต้นของศูนย์คอลัมน์จุดสุดยอดของคุณยกเว้นจะปิดโดย(1,0) +1ยังฉันรู้ว่าคุณหมายถึงอะไรและฉันไม่เห็นด้วย มีข้อบ่งชี้อะไรบ้างที่(2, 2)เป็นจุดศูนย์กลางด้านบนของ a - 2และไม่ใช่แค่ด้านบนขวาและซ้ายของสองตัวบน- 1? ไม่มีเลยที่ฉันเห็น (3, 2)และตรรกะเดียวกันกับ ถ้าคุณไม่ต้องการเพิ่มกฎให้ถือว่าเป็นไปได้สูงสุด hamantaschen ...
Michael Plotke

คำตอบ:


4

C #, 496 452 ไบต์

แก้ไข:พบข้อผิดพลาดที่มีการตรวจสอบขอบเขต ... แต่ยังลายโหลดไบต์ที่ถูกบังคับให้เข้าใจรหัสของตัวเอง การยกเลิกการลงทะเบียนฟังก์ชันโลคัลช่วยสักหน่อยและลบรหัสเฉพาะ C # 7 ออก คำถามนี้สนุกมาก

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

ลองออนไลน์

โปรแกรมที่สมบูรณ์คาดว่าอินพุตที่มีพื้นที่ว่างในมาตรฐานจะส่งออกไปยังมาตรฐานออก เอาต์พุตเป็นหนึ่งรายการต่อบรรทัดโดยมีการป้อนบรรทัดต่อท้าย คุกกี้จะแสดงผลตามลำดับขนาดที่เพิ่มขึ้นส่วนบนซ้ายเป็นอันดับแรก ฉันใช้เวลาพอสมควรในการเข้าใจกฎ แต่ฉันคิดว่ามันผ่านตัวอย่างทั้งหมดที่มีให้

มันทำงานได้โดยการค้นหาตารางทั้งหมดซ้ำ ๆ เพื่อหา Hamantaschen ที่ถูกต้องซึ่งจะเป็นการเพิ่มขนาด 'ที่อนุญาต' สำหรับแต่ละเซลล์มันจะตรวจสอบขึ้นและลงตาม\และ/ในทั้งสองด้านเท่าที่จะทำได้ หากสังเกตว่าแถวถัดไปมีจำนวนมาก-และขนาดปัจจุบันคือขนาด 'อนุญาต' ก็จะเป็นตัวกำหนดการบรรจุและพิมพ์รายการ

การเติมถูกค้นพบโดยการสำรวจพื้นที่ทั้งหมดของคุกกี้เพื่อค้นหาเซลล์ 'ไม่ได้ใช้' เมื่อพบเซลล์ที่ไม่ได้ใช้เซลล์จะถูกทำเครื่องหมายว่าใช้แล้ว (เนื่องจากเราเพิ่มขนาดที่อนุญาตเรารู้ว่าเราเป็นคุกกี้ที่เล็กที่สุดที่มีอยู่) และเราบันทึกการเติม

รูปแบบและรหัสความคิดเห็น:

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 เคส:

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

ฉันประหลาดใจที่ความกะทัดรัดใน C #! ทำได้ดี!
ไม่ใช่ Charles

คำตอบที่ถูกต้องเท่านั้น! ฉันมีบางสิ่งบางอย่างที่เกือบจะทำงานได้ แต่มีข้อผิดพลาดเล็กน้อย (แต่ฉันจะไม่ตั้งตัวเป็นผู้ชนะต่อไป)
ไม่ใช่ Charles
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.