Lego Dişli Treni


13

Keith Randall'ın Lego dişli oranları meydan okuma esinlenerek .

Ben de, daha önce hiç bahsetmediğim yarışmada diğer robotları yok edebilecek dev bir lego robotu inşa etmeyi planlıyorum. robotun farklı bölümleri. Bana böylesine karmaşık bir görev için gerekli olan karmaşık dişli trenlerini inşa etmeme yardımcı olacak en kısa programı yazmanızı istiyorum. Tabii ki, sadece yarıçap 1, 2, 3 ve 5 keyfi-lego birimi olan dişliler kullanacağım.

Dişli grubundaki her dişli 2B ızgarada belirli bir tamsayı koordinatına sahiptir. İlk vites (0,0) konumunda ve son vites negatif olmayan koordinatlarda yer alacaktır. İlk ve son dişlilerin yeri ve boyutu giriş olarak sağlanacaktır, programınız hangi dişlilerin boşlukları doldurmak için nereye gittiğini söylemelidir.

Ayrıca, programınız dişli dizisinde mümkün olan en az sayıda dişli kullanmalıdır. Daha az vites / tren = daha fazla tren ** = daha büyük ve daha iyi yıkım robotu.

Giriş bir satırdan oluşur:

X,Y,B,A

X ve Y son vitesin koordinatlarıdır. İlk vites daima (0,0) konumunda bulunur. B ve A sırasıyla son ve ilk dişlilerin yarıçaplarıdır. Biraz zorluk eklemek için, çıkış dişlisinin doğru yönde döndüğünden emin olmanız gerekir . A ve B aynı işarete sahipse, çıkış dişlisinin aynı yönde dönmesi gerekir ve tek sayıda vites kullanılmalıdır. Ters işaretlere sahiplerse, çift sayıda dişlinin kullanılması gerekir.

Çıkış , her ek dişlinin X konumu, Y konumu ve yarıçaplarının, her satıra bir dişli bir listesi olmalıdır. Birden çok minimal dişli çözümü varsa, yalnızca istediğiniz birini yazdırın. Çıkıştaki dişlilerin sırası önemli değil.

Örnekler (daha eşdeğer çözümler mümkün olabilir):

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!

Görselleştirilen yukarıdaki örneklerin çözümleri:

resim açıklamasını buraya girin

Bildiğim kadarıyla, iki giriş dişlisi üst üste gelmediği veya doğrudan bağlanmadıkça hiçbir sorun imkansız değildir. Bununla uğraşmak zorunda kalmayacaksınız.

Bu kod golf, en kısa cevap kazanır.


* Gelecekteki bir KOTH, kimse?

**ÇUF ÇUF!!


Hem başlangıç ​​hem de son yarıçapların negatif olabilmesi için olurdu.
wizzwizz4

9
Phi'nin Lego Gear Tren Yarışmasına hoş geldiniz. Sandbox'ta 4 yıl geçirdikten sonra, umarım ki buna değecektir.
bir spaghetto

@ wizzwizz4 Değişiklik yaptı.
PhiNotPi

Bu gerçekten 4 yıldır kum havuzunda mıydı?
Rɪᴋᴇʀ

@RikerW Daha çok 3 1/3 gibi.
PhiNotPi

Yanıtlar:


2

C #, 660 bayt

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

Çevrimiçi Deneyin

Bu çok eğlenceliydi! Komple program, STDIN'den girişi, STDOUT'a çıkışı kabul eder. Çıkış, uçtan başa doğru sırasıyla dişlilerdir. Kullanımı:

4 vitesli bir sorunu bir saniyeden daha kısa sürede çözen basit bir Genişlik İlk Arama gerçekleştirir. Dallanma faktörü aslında o kadar büyük değil, bu yüzden önemli ölçüde daha fazlası için iyi olmalı (gerçekten test edilmedi). Ne yazık ki Linq kullanıyor.

QDize tüm izin dişli bağlantılarının bir tablodur (bir yani r=3ve bir bağlanmak r=1eğer dx=4ve dy=0) daha sonra diğerlerini bulmak için döndürülür bir kadranda, içinde. 3 bayt Her kümesidir dx, dyyasal bir bağlantı için, ve yarıçap bilgileri. (Bir ofset olarak seçim çok kasıtlıydı: bir kereliğine, empoze edilen ASCII karakterleri için güzel özellikler bulmaya çalışmak yerine, güzel özellikler için bir ASCII karakteri seçmek eğlenceliydi.

Muhtemelen girdiyi okumak için daha iyi bir iş yapabilirim, ama henüz şansım olmadı, en azından Linq'e bir liste ihtiyacı nedeniyle ödeniyor. Ayrıca döndürme kodu ile çok hayal kırıklığına uğradım, bu çok daha az bayt içinde yapılabilir gibi hissediyorum.

QJeneratör ile Biçimlendirilmiş ve Yorumlanmış Kod :

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