Lego Gear Train


13

แรงบันดาลใจจากอัตราส่วนความท้าทายเกียร์เลโก้โดย Keith Randall

ฉันก็วางแผนที่จะสร้างหุ่นยนต์เลโก้ยักษ์ที่จะสามารถทำลายหุ่นยนต์ตัวอื่นในการแข่งขันที่ไม่เคยพูดถึง * ในขั้นตอนการสร้างหุ่นยนต์ฉันจะใช้รถไฟเกียร์จำนวนมากเพื่อเชื่อมต่อ ส่วนต่าง ๆ ของหุ่นยนต์ ฉันต้องการให้คุณเขียนโปรแกรมสั้นที่สุดที่จะช่วยฉันสร้างรถไฟเกียร์ที่ซับซ้อนซึ่งจำเป็นสำหรับงานที่ซับซ้อนเช่นนี้ แน่นอนว่าฉันจะใช้เฉพาะเกียร์ที่มีรัศมี 1, 2, 3 และ 5 ตามอำเภอใจเลโก้เท่านั้น

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

นอกจากนี้โปรแกรมของคุณจะต้องใช้จำนวนเกียร์ขั้นต่ำที่เป็นไปได้ในรถไฟเกียร์ ลดเกียร์ / รถไฟ = รถไฟมากขึ้น ** = หุ่นยนต์ที่มีขนาดใหญ่และดีกว่าของการทำลาย

อินพุตจะประกอบด้วยหนึ่งบรรทัด:

X,Y,B,A

X และ Y เป็นพิกัดของเฟืองท้าย เกียร์แรกอยู่เสมอที่ (0,0) B และ A เป็นรัศมีของเกียร์สุดท้ายและเกียร์เริ่มต้นตามลำดับ ในการเพิ่มความยากลำบากคุณต้องแน่ใจว่าอุปกรณ์ส่งออกหมุนไปในทิศทางที่ถูกต้อง หาก A และ B มีเครื่องหมายเหมือนกันดังนั้นเกียร์ขาออกจะต้องหมุนไปในทิศทางเดียวกันและต้องใช้จำนวนเกียร์คี่ หากพวกเขามีอาการตรงกันข้ามต้องใช้เกียร์คู่กัน

เอาต์พุตควรเป็นรายการตำแหน่ง X, ตำแหน่ง Y และรัศมีของเฟืองเพิ่มเติมแต่ละเกียร์หนึ่งเฟืองต่อบรรทัด หากมีการแก้ปัญหาด้วยเกียร์ขั้นต่ำหลายตัวให้พิมพ์เพียงตัวเลือกเดียว คำสั่งของเกียร์ในการส่งออกไม่สำคัญ

ตัวอย่าง (อาจแก้ปัญหาที่เทียบเท่าได้มากขึ้น):

in
4,0,1,1
out
2,0,1

in
7,7,-2,-2
out
4,3,3
OR
0,7,5
OR
the above reflected over y=x line

in
7,8,-1,2
out
7,0,5
7,6,1
OR
7,0,5
1,8,5

in
7,7,2,-2
out
4,-3,3
7,1,2
12,1,3
12,7,3
OR
any permutation of the above, or reflected over y=x line
Now you're thinking with gear trains!

นี่คือวิธีแก้ปัญหาสำหรับตัวอย่างด้านบนซึ่งแสดงให้เห็น:

ป้อนคำอธิบายรูปภาพที่นี่

เท่าที่ฉันรู้ไม่มีปัญหาเป็นไปไม่ได้เว้นแต่ว่าทั้งสองเกียร์อินพุตซ้อนทับหรือเชื่อมต่อโดยตรง คุณไม่ต้องจัดการกับเรื่องนี้

นี่คือรหัสกอล์ฟคำตอบที่สั้นที่สุดชนะ


* อนาคต KOTH ทุกคน?

** CHOO CHOO !!


ฉันจะได้มันเพื่อให้รัศมีเริ่มต้นและรอบชิงชนะเลิศเป็นลบ
wizzwizz4

9
ยินดีต้อนรับสู่ Lego Gear Train Challenge หลังจาก 4 ปีใน Sandbox หวังว่ามันจะคุ้มค่ากับน้ำหนัก
ปาเก็ตตี้

@ wizzwizz4 ทำการเปลี่ยนแปลง
PhiNotPi

นี่เป็นเรื่องจริงในกล่องทรายเป็นเวลา 4 ปีหรือไม่?
Rɪᴋᴇʀ

@RikerW เหมือน 3 1/3
PhiNotPi

คำตอบ:


1

C #, 660 ไบต์

using System.Linq;using System;class P{int p=1,x,y,r;P l;static void Main(){var Q="$&.$'7$(@$*R$'/$(8$)A'(A('A$+S$(0$)9'(9('9$*B$,T$*2$+;$,D$.V*,V,*V";var I=Console.ReadLine().Split(',').Select(int.Parse).ToList();int i=0,t,s=7,u,v,w,p=I[3]*I[2];for(var D=new[]{new P{r=Math.Abs(I[3]),l=new P{r=Math.Abs(I[2]),x=I[0],y=I[1],p=3}}}.ToList();i>=0;){P c=D[i++],l=c.l;for(;(l=l?.l)!=null&&(s=(t=c.x-l.x)*t+(t=c.y-l.y)*t-(t=c.r+l.r)*t)>0;);if(s==0&&l.p>2&p*c.p<0)for(i=-1;c.l.p<3;c=c.l)Console.WriteLine(c.x+","+c.y+","+c.r);for(t=0;s>0&t<66;t++)for(u=Q[t++]-36,v=Q[t++]-36,s=1;s++<5&Q[t]%9==c.r;w=u,u=v,v=-w,D.Add(new P{l=c,r=Q[t]/9-4,x=c.x+u,y=c.y+v,p=-c.p}));}}}

ลองออนไลน์

มันสนุกมาก !! โปรแกรมเสร็จสมบูรณ์รับอินพุตจาก STDIN, ส่งออกไปยัง STDOUT เอาท์พุทเป็นเกียร์ตามลำดับตั้งแต่ต้นจนจบ การใช้งาน:

ค้นหา Breadth First Search อย่างง่ายซึ่งแก้ปัญหา 4 เกียร์ในเวลาไม่ถึงหนึ่งวินาที ปัจจัยการแตกแขนงนั้นไม่ใหญ่มากดังนั้นจึงควรดีกว่ามาก น่าเศร้าที่มันใช้ Linq

Qสตริงเป็นตารางของการเชื่อมต่อเกียร์ได้รับอนุญาต (เช่นr=3และเชื่อมต่อกับr=1ถ้าdx=4และdy=0) ในหนึ่งวอดซึ่งเป็นแล้วหมุนไปหาคนอื่น ๆ ชุดของ 3 ไบต์ทุกคนเป็นdx, dyและข้อมูลรัศมีสำหรับการเชื่อมต่อทางกฎหมาย ทางเลือกใน(ฐานะออฟเซ็ตนั้นเป็นการพิจารณาที่ดีมาก : มันสนุกสำหรับการเลือกอักขระ ASCII หนึ่งครั้งสำหรับคุณสมบัติที่ดีแทนที่จะพยายามค้นหาคุณสมบัติที่ดีสำหรับอักขระ ASCII ที่กำหนด

ฉันอาจจะทำได้ดีกว่าในการอ่านอินพุต แต่ฉันยังไม่มีโชค แต่อย่างน้อยก็ไม่ได้เพราะ Linq จ่ายโดยความต้องการรายการ ฉันรู้สึกผิดหวังกับรหัสหมุนฉันรู้สึกว่าสามารถทำได้ในจำนวนไบต์น้อยกว่ามาก

รูปแบบและรหัสความคิดเห็นพร้อมกับตัวQกำเนิด:

using System.Linq; // seems to pay today
using System;

class P
{
    static void GenQ()
    {
        int t, k = 0, m = 0;
        Func<P, P, int> C = (P c, P l) => (t = c.x - l.x) * t + (t = c.y - l.y) * t - (t = c.r + l.r) * t; // ==0 -> touching, <0 -> not touching, >0 -> overlap

        string str = "";

        string T(int i) => "" + (char)('$' + i); // $ is zero, '$' == 36, so we can mod and div by 9, and greater than " so we don't have to escape it

        foreach (int r in new[] { 1, 2, 3, 5 }) // at 0,0 (current gear)
            foreach (int s in new[] { 1, 2, 3, 5 }) // gear to place
                for (int i = 0; i <= r + s; i++) // x
                    for (int j = 1; j <= r + s; j++, m++) // y
                        if (C(new P { r = r }, new P { r = s, x = i, y = j }) == 0) // 
                        {
                            str += T(i) + T(j) + T(r + s * 9);
                            k++;
                        }

        System.Console.WriteLine("K : " + k);
        System.Console.WriteLine("M : " + m);
        System.Console.WriteLine(str);
        System.Console.ReadKey(true);
        return;
    }

    int p=1, // parity
        x, // x
        y, // y
        r; // radias (TODO: store radias^2 ?)
    P l; // previous in search list

    static void Main()
    {
        //GenQ();

        // '$' == 36 (4*9)
        // 3char blocks: x,y,r+9*s
        var Q="$&.$'7$(@$*R$'/$(8$)A'(A('A$+S$(0$)9'(9('9$*B$,T$*2$+;$,D$.V*,V,*V"; // quarter table

        // primative read ints
        var I=Console.ReadLine().Split(',').Select(int.Parse).ToList();

        int i=0, // position in Due
            t, // check differential cache, position in Q
            s=7, // check cache, rotation counter (>0)
            u, // rotation x
            v, // rotation y
            w, // rotation x cache
            p=I[3]*I[2]; // parity (>0 -> same, even ; <0 -> different, odd)

        // due (not point using a queue, the search space grows exponentially)
        for(var D=new[]{
                new P{r=Math.Abs(I[3]), // start (p==1)
                    l=new P{r=Math.Abs(I[2]),x=I[0],y=I[1],p=3} // terminal (detect with p==3)
                }}.ToList();
            i>=0;) // infinite number of configurations, no bounds, i is escape term
        {
            P c=D[i++], // current
                l=c.l; // check, initially the one before the previous (we know we are touching last already)

            // 'checks' c against l
            //Func<int>C=()=>(t=c.x-l.x)*t+(t=c.y-l.y)*t-(t=c.r+l.r)*t; // ==0 -> touching, >0 -> not touching, <0 -> overlap

            // check we arn't touching any before us (last thing we check is terminal)
            for(;(l=l?.l)!=null&& // for each before us (skipping the first one)
                (s=(t=c.x-l.x)*t+(t=c.y-l.y)*t-(t=c.r+l.r)*t)>0;); // check c against l and cache in s, ==0 -> touching, >0 -> not touching, <0 -> overlap

            if(s==0&& // touching last checked?
                l.p>2& // stopped on terminal?
                p*c.p<0) // correct parity? -> win
                for(i=-1; // escape
                    c.l.p<3;c=c.l) // for each that wasn't the first
                    Console.WriteLine(c.x+","+c.y+","+c.r);

            // enumerate possible additions, and queue them in due
            for(t=0;
                s>0& // not touching or overlapping anything (including terminal)
                t<66;t++) // 66 = Q.Length
                for(
                    u=Q[t++]-36, // '$'
                    v=Q[t++]-36,
                    s=1;s++<5& // rotate 4 times
                    Q[t]%9==c.r; // our raidus matches
                        w=u, // chache y value
                        u=v, // rotate
                        v=-w,
                        D.Add(new P // add
                        {
                            l=c,
                            r=Q[t]/9-4, // radius
                            x=c.x+u,
                            y=c.y+v,
                            p=-c.p // flip parity
                        }));
        }
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.