Лего-шестерня


13

Натхненний викликом передач передач Lego Кітом Рендаллом.

Я теж планую створити гігантського робота-лего, який згодом зможе знищити інших роботів у ніколи не згаданій конкуренції. різні частини робота. Я хочу, щоб ви написали мені найкоротшу програму, яка допоможе мені побудувати складні поїзди, необхідні для такого складного завдання. Я, звичайно, буду використовувати лише передачі з радіусами 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!

Ось варіанти наведених вище прикладів, візуалізовані:

введіть тут опис зображення

Наскільки мені відомо, жодна проблема не є неможливою, якщо дві вхідні передачі не перетинаються або безпосередньо з'єднуються. Вам не доведеться з цим боротися.

Це кодовий гольф, виграє найкоротша відповідь.


* Майбутній КОТ, хтось?

** CHOO CHOO !!


Я б хотів, щоб і початковий, і кінцевий радіуси могли бути негативними.
wizzwizz4

9
Ласкаво просимо до виклику поїздів Phi Lego Gear Train. Через 4 роки перебування в пісочниці, сподіваємось, він вартував би ваги.
спагето

@ wizzwizz4 Внесла зміни.
PhiNotPi

Це було справді в пісочниці 4 роки?
Rɪᴋᴇʀ

@RikerW Більше, як 3 1/3.
PhiNotPi

Відповіді:


2

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. Вихід - це передачі в порядку від кінця до початку. Використання:

Здійснює простий пошук першої ширини, який вирішує проблему з 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
                        }));
        }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.