레고 기어 트레인


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, 누구?

**추추!!


초기 반지름과 마지막 반지름이 모두 음수가 될 수 있습니다.
wizzwizz4

9
Phi의 Lego Gear Train Challenge에 오신 것을 환영합니다. 샌드 박스에서 4 년이 지난 지금, 그것은 가치가 있었을 것입니다.
스파게티

@ 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으로 출력. 출력은 끝에서 시작까지 순서대로 기어입니다. 용법:

간단한 너비 우선 검색을 수행하여 1 초 이내에 4 단 문제를 해결합니다. 분기 요소는 실제로 그렇게 크지 않으므로 상당히 더 많은 것이 좋습니다 (실제 테스트하지는 않음). 슬프게도 Linq를 사용합니다.

Q문자열이 허용 된 모든 장비의 연결의 테이블 (AN을 즉 r=3와 연결할 r=1경우 dx=4dy=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.