บันทึกห่านจากการสูญพันธุ์


13

ห่านสายพันธุ์ที่รู้จักกันในชื่อAlex Aเป็นที่รู้จักกันว่าอาศัยอยู่ในกริดรูปสามเหลี่ยมซึ่งประกอบด้วย 64 เซลล์:

เซลล์
(รูปภาพที่นำมาจากปัญหาเกี่ยวกับ Project Euler ที่ไม่เกี่ยวข้อง )

เราจะติดป้ายเซลล์ที่มีตัวเลขในแต่ละ0ที่จะ63เริ่มต้นจากแถวด้านบนแล้วย้ายจากซ้ายไปขวาในแต่ละแถวด้านล่างที่ ดังนั้นเซลล์ด้านบนเป็นเซลล์ล่างขวาเป็น063

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

ระบบการติดฉลากของเส้นขอบที่ขอบของกริดนั้นแตกต่างกันเนื่องจากเซลล์ที่อยู่บนขอบของกริดนั้นมีเส้นขอบที่ไม่ได้ใช้ร่วมกับเซลล์อื่น หากเส้นขอบเป็นเพียงส่วนหนึ่งของเซลล์เดียวเราจะใช้ตัวอักษรXนั้น ยกตัวอย่างเช่นสามชายแดนของเซลล์0มี0,2, และ0,X0,X

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

ป้อนคำอธิบาย

รายการตัวเลขคั่นด้วยเครื่องหมายจุลภาคจาก0ถึง63แทนเซลล์ที่มีห่าน ตัวอย่าง:

6,12

คำอธิบายผลลัพธ์

รายการของเส้นขอบที่จำเป็นต้องมีรั้วสร้างขึ้นเพื่อป้องกันห่านที่ประสบความสำเร็จ นี่ควรเป็นจำนวนรั้วที่เล็กที่สุดเท่าที่จะทำได้ ตัวอย่าง:

5,6 6,7 11,12 12,13 

"ห่านควรอยู่ในรูปหลายเหลี่ยมที่ล้อมรอบอย่างเต็มที่" ห่านทุกตัวจะต้องอาศัยอยู่ในรูปหลายเหลี่ยมเดียวกันหรืออาจมีหลายรูปหลายเหลี่ยม (หรือ 0)
feersum

@feersum ห่านทุกตัวควรอยู่ในรูปหลายเหลี่ยมเดียวกัน ฉันได้แก้ไขคำถามเพื่อให้ชัดเจน
absinthe

@ Katya รูปหลายเหลี่ยมอาจมีส่วนตัดกันด้วยตนเองหรือส่วนที่มีความกว้างเป็นศูนย์หรือไม่ คิดเหมือนรูปนาฬิกาทราย
orlp

@orlp ส่วนที่มีความกว้างเป็นศูนย์คืออะไร
absinthe

2
@orlp รูปหลายเหลี่ยมไม่ควรมีส่วนความกว้างเป็นศูนย์
absinthe

คำตอบ:


10

C #, 530 ไบต์

เสร็จสิ้นโปรแกรม C # รับอินพุตเป็นบรรทัดเดียวจาก STDIN และส่งออกบรรทัดเดียวไปยัง STDOUT โดยมีส่วนท้าย ""

นี่ค่อนข้างนาน ... และมีวิธีการทำซ้ำ x / y / z มากเกินไป แต่ฉันไม่สามารถลดความรู้สึกที่เหมาะสมลงได้และมีการสอบภายใน 2 ชั่วโมงอาจกลับมาที่พรุ่งนี้

using Q=System.Console;class P{static void Main(){int q=9,w=0,e=9,r=0,t=9,u=0,i=0,x=0,y=0,z=0,p=0;System.Action V=()=>{z=(int)System.Math.Sqrt(i);p=(x=i-z*z)%2;x/=2;y=(++z*z--+~i)/2;},W=()=>{Q.Write(i+","+(x<0|y++<0|z>7?"X":""+(z*z+2*x+1-p))+" ");};foreach(var g in Q.ReadLine().Split(',')){i=int.Parse(g);V();q=q>x?x:q;w=w<x?x:w;e=e>y?y:e;r=r<y?y:r;t=t>z?z:t;u=u<z?z:u;}for(i=64;i-->0;){V();if(!(x<q|x>w|y<e|y>r|z<t|z>u))if(p>0){if(y==r)W();if(x++==w)W();x--;if(z--==t)W();}else{if(y--==e)W();if(x--==q)W();x++;if(z++==u)W();}}}}

แผนภาพนี้จะอธิบายสิ่งที่เกิดขึ้นส่วนใหญ่

กริดอธิบายเป็น x / y / z / (p) แสดงตัวอย่างโซลูชัน

ยอมรับว่าเนื่องจากเราไม่สามารถมีส่วนที่มีความกว้าง 0 ส่วน "หกเหลี่ยม" จะเป็นรูปร่างที่ถูกที่สุดเสมอ (และมีประโยชน์ในการให้ห่านอวกาศมีพื้นที่มากที่สุด)

โปรแกรมทำงานโดยการแปลดัชนีเซลล์อินพุตแรกทั้งหมดเป็น x / y / z coords และค้นหา min / max ของแต่ละ x / y / z

z = floor(root(i))
x = floor((i - z^2) / 2)
y = floor((z+1)^2 - i - 1) / 2)
p = (i - z^2) % 2

ต่อไปจะผ่านแต่ละดัชนีเซลล์และตรวจสอบว่าเหมาะสมกับขอบเขต 'หกเหลี่ยม' ที่เราได้อธิบายไว้หรือไม่ ถ้าเป็นเช่นนั้นมันจะตรวจสอบว่ามันอยู่บนขอบที่รุนแรงของขอบเขต (เช่น x = xmin หรือ y = ymax) และเพิ่มขอบที่สอดคล้องกันถ้ามันเป็น มันต้องหาดัชนีของขอบที่อยู่ข้างๆ สำหรับ x และ z เราแค่เพิ่ม / ลดพวกมันตามที่เราต้องการจากนั้นใช้สูตรต่อไปนี้:

i = z^2 + 2*x + (1-p)

ขอให้สังเกตว่า "ความเท่าเทียมกัน" เปลี่ยนแปลงอยู่เสมอและ y นั้นไม่เกี่ยวข้อง สำหรับ y เราไม่จำเป็นต้องเปลี่ยนแปลงอะไรเลย แต่โค้ดนั้นค่อนข้างยุ่งเพราะมันต้องทำการตรวจสอบขอบเขต "สามเหลี่ยม" เพื่อตรวจสอบว่าเซลล์ถัดไปควรเป็น "X" หรือไม่

ตัวอย่างการแก้ปัญหา (เซลล์ที่มีห่านจากมุมทั้งสาม):

Input
2,50,62

Output
62,63 61,X 59,X 57,X 55,X 53,X 51,X 50,49 48,X 36,X 35,X 25,X 24,X 16,X 15,X 9,X 8,X 4,X 3,X 2,0 1,X 

รหัส Tidier พร้อมความคิดเห็น:

using Q=System.Console;

class P
{
    static void Main()
    {
        int q=9,w=0,e=9,r=0,t=9,u=0, // min/max x/y/z/ (init min high, and max low)
        i=0, // index of cell we are looking at
        x=0,y=0,z=0,p=0; // x,y,z dimension

        System.Action V=()=>
            { // translates the index into x/y/z/p
                z=(int)System.Math.Sqrt(i);
                p=(x=i-z*z)%2; // 'parity'
                x/=2; // see p assignment
                y=(++z*z--+~i)/2; // ~i == -i - 1
            },
            W=()=>
            { // writes out the edge of i, and the cell described by x/z/inverse of p   (the inversion of p handles y +/-)
                Q.Write(i+","+ // write out the edge
                        (x<0|y++<0|z>7?"X":""+(z*z+2*x+1-p)) // either X (if we go out of 'trianlge' bounds), or we translate x/z/inverse of p into an index
                        +" "); // leaves a trailing space (as shown in example output)
            };

        foreach(var g in Q.ReadLine().Split(',')) // for each cell with geese
        {
            i=int.Parse(g); // grab index of cell
            V(); // compute x/y/z/p
            q=q>x?x:q; // sort out mins/maxes
            w=w<x?x:w;
            e=e>y?y:e;
            r=r<y?y:r;
            t=t>z?z:t;
            u=u<z?z:u;

            // code like the above suggests a solution with a couple of arrays would be better...
            // I've not had success with that yet, but maybe in a couple of days I will try again
        }

        for(i=64;i-->0;) // for each cell
        {
            V(); // compute x/y/z/p
            if(!(x<q|x>w|y<e|y>r|z<t|z>u)) // if we are inside the 'hex' bounds
                if(p>0)
                { // x max, y max, z min
                    // these checks check that we are on the extremes of the 'hex' bounds,
                    // and set up the appropriate vars for W calls to put the edges in
                    // must do y first, because W modifies it for us (saves 2 bytes in the next block)
                    if(y==r) // don't need the ++ (can't go out of 'trianlge' bounds)
                        W();
                    if(x++==w)
                        W();
                    x--;
                    if(z--==t)
                        W();
                    //z++; not used again
                }
                else
                { // x min, y min, z max
                    if(y--==e) // do need the -- (used for 'trianlge' bounds checking)
                        W();
                    // y is reset in W, as such
                    if(x--==q)
                        W();
                    x++;
                    if(z++==u)
                        W();
                    //z--; not used again
                }
        }
    }
}

using System;คุณสามารถบันทึกไบต์ด้วย
LegionMammal978

@ LegionMammal978 infact เขาได้รับสองสิ่งนั้น .. เขาใช้มันเพื่อ Q.Write และ Q.ReadLine เท่านั้น สิ่งเหล่านั้นรวมถึงข้อความการใช้ที่เขามีตอนนี้คือusing Q=System.Console;Q.Write();Q.ReadLine()(45 ไบต์) กับข้อเสนอแนะของคุณusing System;Console.Write();Console.ReadLine()(47 ไบต์)
Kade

คุณยังสามารถวาง 10 ไบต์โดยไม่จำเป็นต้องเริ่มต้นi, x, y, zและp0
LegionMammal978

@ LegionMammal978 คุณแน่ใจหรือ ฉันลองมันและมันให้ข้อผิดพลาดในการใช้ vairable ที่ไม่ได้รับมอบหมาย
Kade

@ Vioz- ตัวแปรใดบ้าง บรรทัดใดในเวอร์ชันที่มีคำอธิบายประกอบ
LegionMammal978
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.