レゴギアトレイン


13

キース・ランドールによるレゴのギア比チャレンジに触発されました。

私も巨大なレゴロボットを構築し、最終的にはこれまでにない競争で他のロボットを破壊できるようにする予定です。ロボットのさまざまな部分。このような複雑なタスクに必要な複雑なギアトレインを構築するのに役立つ最短のプログラムを書いてほしい。もちろん、半径1、2、3、および5の任意レゴユニットのギアのみを使用します。

歯車列の各歯車には、2Dグリッド上の特定の整数座標があります。最初のギアは(0,0)に配置され、最終ギアは非負の座標に配置されます。最初と最後のギアの位置とサイズが入力として提供されます。プログラムは、どのギアがギャップを埋めるのかを指示する必要があります。

さらに、プログラムは、ギアトレイン内の可能な最小数のギアを使用する必要があります。ギアの数が少ない/列車=列車が多い** =大きくて優れた破壊ロボット。

入力は1行で構成されます。

X,Y,B,A

XとYは最終ギアの座標です。最初のギアは常に(0,0)にあります。BとAは、それぞれ最終ギアと初期ギアの半径です。難易度を上げるには、出力ギアが正しい方向に回転することを確認する必要がありますAとBの符号が同じ場合、出力ギアは同じ方向に回転する必要があり、奇数のギアを使用する必要があります。反対の符号がある場合、偶数個のギアを使用する必要があります。

出力は、各追加ギアのX位置、Y位置、および半径のリストであり、1行に1つのギアがあります。最小ギアソリューションが複数ある場合は、選択したもののうち1つだけを印刷します。出力内のギアの順序は重要ではありません。

例(さらに同等の解決策が考えられる):

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!

以下は、上記の例に対するソリューションを視覚化したものです。

ここに画像の説明を入力してください

私の知る限り、2つの入力ギアが重なるか直接接続されない限り、問題はありません。これに対処する必要はありません。

これはコードゴルフで、最短回答が勝ちます。


*将来のKOTH、誰か?

**汽車ポッポ!!


初期半径と最終半径の両方が負になるように設定します。
wizzwizz4

9
ピピのレゴギアトレインチャレンジへようこそ。サンドボックスでの4年後、うまくいけば、それだけの価値があったことでしょう。
spaghetto

@ 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に出力します。出力は、端から端までのギアです。使用法:

4ギアの問題を1秒未満で解決する単純な幅優先検索を実行します。分岐係数は実際にはそれほど大きくないので、かなり多くの場合に適しているはずです(実際にはテストされていません)。悲しいことにLinqを使用しています。

Q文字列(すなわち、すべての許容ギア接続のテーブルであるr=3とに接続r=1する場合dx=4dy=0、次に他を見つけるために回転されるもの象限において)。3バイトの各セットはdxdy法的な接続のために、半径情報。(オフセットとしての選択は非常に意図的でした:一度強制的にASCII文字の素敵なプロパティを見つけようとするのではなく、素敵なプロパティのASCII文字を選択するのは楽しかったです。

私はおそらく入力を読むのにより良い仕事をすることができますが、私はまだ運がありませんでした。特に、Linqはリストの必要性によって支払われているからです。また、rotateコードには非常に失望しています。かなり少ないバイトでそれができると感じています。

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.