도미노 데이 골프


14

도미노 설정이 주어지면 당신의 임무는 어떤 도미노가 떨어지고 그렇지 않은지를 알아내는 것입니다.

입력

도미노 설정의 직사각형 ASCII 표현을 가져옵니다. ASCII 그리드에는 다음 문자가 사용됩니다.

  • (공간) : 빈 셀
  • |, -, /, \: 도미노

도미노는 8 문자로 나눌 수 있으며 다음 문자로 표시됩니다 (WASD 방향과 유사).

Q W E
A   D
Z X C

하나 이상의 도미노가이 문자 중 하나로 대체되어 시작시 도미노가 밀려 났음을 나타냅니다. 예를 들면 다음과 같습니다.

D||||/  
  -   / 
  -    -
  -    -
  /|||||

이 도전이 입력 파싱의 연습으로 바뀌기를 원하지 않기 때문에 다음 입력 형식 중 하나가 허용됩니다.

  • 그리드가있는 문자열 (선택적으로 도움이된다면 치수가 앞에옵니다)
  • 각 줄에 대해 하나의 문자열이있는 배열 / 목록 / 튜플 (선택적으로 너비 및 높이 정수와 함께)
  • 각 격자 셀에 대해 하나의 문자열 / 문자가있는 (중첩 된) 배열 / 목록 / 튜플 (선택적으로 너비 및 높이 변수와 함께)

STDIN에서 읽거나 함수 인수를 가져 오거나 입력이 변수에 저장 될 것으로 예상 할 수 있습니다.

산출

STDOUT에 쓰거나 유효한 입력 형식으로 결과 그리드를 반환 (또는 변수에 저장)하여 도미노가 떨어 졌거나 그렇지 않은 것을 나타냅니다. 즉, 타락한 각 도미노로 교체 #하고 입력 된대로 각 도미노를 그대로 둡니다.

규칙

물론, 도미노는 설정을 통해 가을을 전파합니다. 경쟁 조건이있을 수 있으므로 고정 시간 단계가 있고 하강 시간 단계 당 하나의 그리드 셀을 전파한다고 가정합니다.

도미노는 일반적으로 직관적으로 기대하는 방식을 따르지 않지만 엄격한 상식 사양은 상당히 길다. 죄송합니다. 예제가 도움이 되길 바랍니다. 다음은 모든 고유 한 2 타일 조합 (회전 및 반사까지 )의 요지 입니다. 엄격한 규칙을 읽으십시오.

각 도미노는 두 방향으로 만 떨어질 수 있습니다.

           W       Q          E
A | D      -        /        \
           X         C      Z

도미노가 떨어질 때마다 세포는 가을 방향으로 영향을 미칩니다. 해당 셀에 동일한 방향 또는 45도 다른 방향으로 떨어질 수있는 도미노가 포함되어 있으면 다음 번 단계에서 도미노가 그렇게합니다.

예 :

D|    ->    DD      (falls in same direction)

D/    ->    DC      (falls at 45 degrees)

C     ->    C       (falls at 45 degrees)
 -           X

대각선으로 향한 도미노 ( /또는 \)가 떨어질 때마다 셀과 셀이 떨어지는 방향으로 닿는 두 셀에도 영향을줍니다. 이 셀에 원래 도미노와 같은 방향으로 떨어지거나 축에서 정렬 된 방향으로 떨어질 수있는 도미노가 포함되어 있으면 다음 번 단계에서 도미노가 그렇게합니다.

예 :

C/     ->   CC      (the cell in the direction of the fall is the one below
                     the /, so it falls in the same direction)

C|     ->   CD      (falls in the axis-aligned direction away from the C)

C-     ->   C-       (the direction away from the Q is W, 
  or                  but neither - nor \ can fall to W)
C\     ->   C\     

예외 : 도미노가 한 번에 올바른 방향으로 밀려 나면 (즉, 위의 규칙 중 하나라도 충돌하는 경우) 넘어지지 않습니다.

예 :

D|A   ->    D|A     (central domino in pushed in both directions)

  Z           Z     (although it's pushed in one direction by two dominoes
D\A   ->    D\A      and in the other by only one, it doesn't fall)


 X           X      (the domino is being pushed from two opposing sides
D-A   ->    DXA      D and A, but neither is valid for that domino. Hence,
                     there is no conflict and the X can push the domino over)

 Z           Z      (pushed in the same direction by two dominoes, so falls)
\A    ->    ZA

   Z           Z           Z    (once the conflict arises, the affected
  \   ->      Z   ->      Z      domino is locked in its position and can't
D|A         D|A         D|A      be pushed over by future dominoes)

8 5
D||||/            ######  
  -   /             -   # 
  -    -    -->     -    #
  -    -            -    #
  /|||||            /|||||

===============================================

17 9
E|/|||/                    #######          
  -   -                      #   #          
  -   -                      #   #          
  -   -                      #   #          
  /|||/|||||||||/    -->     ###############
       /        -                 #        #
        /       -                  #       -
         /      -                   #      #
          /|||||\                    #######

===============================================

19 8
       \|/                        ###           
       - -                        # #           
D||||/|\ /|||/             ######## #####       
      /      -                   #      #       
       -    \-       -->          -    \#       
      \-   \ -                   #-   \ #       
D||||\ /  \  /             ###### /  \  #       
        |\    |||||                |\    #####  

==============================================

11 11
-\\\/|\|\-|         -\##/|###-|
-|\\||\-|\-         -|#####-|\-
|\//\//|-/-         |#//\//|#/-
\|//|-|\-\|         #####-|##\|
---||/-\//|         #-######//|
///|||\----   -->   #/#####----
-|/---|-|-\         #|##--|-|-\
--|--\/|///         ####-\/|///
/|//--|//-|         ####--|//-|
|/\-|||-/-\         |/\####-/-\
E||\-|\---/         ####-|\---/

내가 실수했다고 생각되면 알려주십시오 (특히 마지막 실수).

답변:


15

C 번호 1,048 907 850bytes

이제 심하게 골프를 쳤으며 정수 열거 형의 2 차원 배열에서 비트 연산이 뒤죽박죽 일뿐입니다. 아마도 1 차원 배열을 사용하여 다소 짧아 질 수는 있지만 지금은이 작업을 다시 시도 할 준비가되어 있지 않습니다. 예를 들어 stdin에서 치수와 문자열을 읽습니다.

11 11 -\\\/|\|\-|-|\\||\-|\-|\//\//|-/-\|//|-|\-\|---||/-\//|///|||\-----|/---|-|-\--|--\/|////|//--|//-||/\-|||-/-\E||\-|\---/

골프 :

using L=System.Console;class R{static void Main(){int p=255,e,c,E=7,D,C,X,Z,A,m=-1,t=m,f=t,u,i=t;for(;t<0;)for(t=f,f=0;(C=L.Read())>47;)f=f*10+C-48;var T=new int[f,t];for(;++i<f;)for(c=0;c<t;T[i,c++]=(C>99?68:C>91?34:C>89?112:C>87?56:C>86?131:C>80?193:C>68?7:C>67?14:C>66?28:C>64?224:C>46?136:C>44?17:0)*(C>64&C<91?1:257))C=L.Read();for(;i+E>0;E=-E)for(i=c=m;++c<f;)for(C=m;++C<t;){if(E>0&(A=D=T[c,C])>0&D<p){T[c,C]=m; X=C+(i=(D&4)>0?1:(D&64)/-64);Z=c+(u=(D&16)>0?1:D%2*m);System.Action v=()=>{if(Z>m&Z<f&X>m&X<t&&(e=T[Z,X])>p&(e>>8&A)>0)T[Z,X]&=65280|A;};v();if((i&u)!=0){X=i==u?C:X;Z=i==u?Z:c;A=((D&128)/128+D*2)&D;v();X=C+i-X+C;Z=c+u-Z+c;A=(D%2*128+D/2)&D;v();}i=8;}if(E<0&D>p&((D=D&p)&(D-1))<1&D>0)T[c,C]=D<2?131:D>64?193:D/2*7;}for(D=m;++D<f;L.WriteLine())for(c=0;c<t;L.Write(C<0?'#':(C=C>>8)>99?'/':C>67?'|':C>33?'\\':C>9?'-':' '))C=T[D,c++];}}

시간이 너무 많기 때문에 ungolfed 버전을 수정하여 떨어지는 도미노의 애니메이션 GIF를 출력했습니다 ( 이 SO 질문 과이 문서의 도움으로 1 2 ). 여기에는 코드 만 추가되었으며 #if gifness블록 안에 있거나 명확하게 표시되어 있습니다.

gif를 만들려면 프레임 시간, 출력 파일 등을 설명하는 명령 행 인수 쌍을 제공하십시오.

dominoGolf.exe console_delay (out_file_name (gif_frame_time (final_frame_time)))
dominoGolf.exe 0 outfile.gif 1 100

세 번째 인수는 각 프레임의 프레임 시간입니다 (1/100 초). 네 번째 인수는 마지막 프레임의 프레임 시간입니다 (1/100 초). 두 번째 인수는 gif의 출력 파일 이름입니다. 콘솔 출력 만 원하면 파일 이름, 지연 및 최종 지연을 생략 할 수 있습니다. 첫 번째 인수는 밀리 초 단위로 터미널에 렌더링되는 프레임 사이의 지연입니다. 애니메이션을 전혀 원하지 않고 결과를보고자하는 경우 모든 인수를 생략 할 수 있습니다. 골프 버전과 마찬가지로 stdin에서 도미노 데이터를 읽습니다. 이 코드는 자체 방식으로 끔찍합니다 (gif를 반복하여 반복되도록).

Ungolfed gif 생성 코드 :

#define gifness

using L=System.Console;

class R
{
    static void Main(string[] args) // don't need args
    {
        int p=255,P=0xFF00,m=15,M=240, // might be able to inline a couple of these
        w=1,e=2,d=4,c=8,x=16,z=32,a=64,q=128, // most of these are reusable
        W=131,E=7,D=14,C=28,X=56,Z=X*2,A=Z*2,Q=193, // most (all?) of these are reusable
        Y=w+x,U=a+d,N=c+q,B=z+e, // one of these atleast is pre-evalable

        // recognise this?
        t=-1,f=t,k,u,i=t,j,J,K,o,O,b;
        for(;t<0;)
            for(t=f,f=0;(k=L.Read())>47;)
                f=f*10+k-48;

        var T=new int[f,t]; // main arr
        // domino: dir, copy(for render)
        // motion: pickup

        // input
        for(;++i<f;) // values of i and j don't matter, just counters
        {
            for(j=0;j<t;) // increment done 3down
            {
                k=L.Read();
                T[i,j++]=(
                // fallen
                k=='W'?W:k=='E'?E:k=='D'?D:k=='C'?C:k=='X'?X:k=='Z'?Z:k=='A'?A:k=='Q'?Q:
                // dominos
                k==' '?0:k=='-'?Y:k=='/'?N:k=='|'?U:B // ASCII, order for >
                )*(k>64&k<91?1:257);
            }
        }

        #if gifness
        System.Drawing.Font font1 = null;
        System.Windows.Media.Imaging.GifBitmapEncoder genc = null;
        System.Drawing.Bitmap bmp = null;
        System.Drawing.Graphics g = null;
        if (args.Length > 1)
        {
            font1 = new System.Drawing.Font(System.Drawing.FontFamily.GenericMonospace, 12, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);
            genc = new System.Windows.Media.Imaging.GifBitmapEncoder();
            bmp = new System.Drawing.Bitmap(t * 8, f * 14); // I have no clue what these should be in relation to em size
            g = System.Drawing.Graphics.FromImage(bmp);
        }
        #endif

        if (args.Length > 0) // not important
        {
            L.Clear();
        }

        // main
        for(;i>0;) // can do i=1-i and swap setting 1 for 0 to remove {}
        {

            if (args.Length > 0) // non-critical, renders the current state to the console/gif
            {
                var os="";
                for (o=0;o<f;o++) // values of i and j don't matter, just counters
                {
                    for (j=0;j<t;j++)
                    {
                        k=T[o,j];
                        os += k==0?' ':k<p?'#':(k=k>>8)==Y?'-':k==N?'/':k==U?'|':'\\'; // order for >
                    }
                    os+="\n";
                }
                L.SetCursorPosition(0, 0);
                L.Write(os);

                #if gifness
                if (args.Length > 1)
                {
                    g.Clear(System.Drawing.Color.White);
                    g.DrawString(os, font1, System.Drawing.Brushes.Black, 0, 0);
                    System.IO.MemoryStream bms = new System.IO.MemoryStream();
                    bmp.Save(bms, System.Drawing.Imaging.ImageFormat.Gif);
                    var bmpf = System.Windows.Media.Imaging.BitmapFrame.Create(bms);
                    genc.Frames.Add(bmpf);

                    // do I chose the frame duraton1??!?!?! (take from args[2] is present else args[0])
                }
                #endif

                System.Threading.Thread.Sleep(int.Parse(args[0]));
            }

            // back to important stuff
            i=0; // set me to 1 if we do anything (8 in golfed version due to E being 7)

            // move motions
            for (j=0;j<f;j++) // careful!!
            {
                for (k=0;k<t;k++) // careful!!
                {
                    O=o=T[j,k];
                    if (o>0&o<p) // we are motion
                    {
                        T[j,k]=-1; // do this so we can't skip it

                        K=k+(i=((o&d)>1?1:(o&a)>0?-1:0));
                        J=j+(u=((o&x)>1?1:(o&w)>0?-1:0));

                        System.Action v=()=>{
                            if(J>=0&J<f&K>=0&K<t&&(b=T[J,K])>p&&((b>>8)&O)>0)
                            {
                                T[J,K]&=(P|O);
                            }
                        };

                        v();
                        if (i!=0&u!=0)
                        {
                            K=i==u?k:K; // k+i == K
                            J=i==u?J:j; // j+u == J
                            O=(((o&q)>0?w:0)+o*2)&o;
                            v();

                            K=K==k?k+i:k;
                            J=J==j?j+u:j;
                            O=(((o&w)>0?q:0)+o/2)&o;
                            v();
                        }

                        i=1;
                    }
                }
            }

            // move dominos
            for (j=0;j<f;j++) // careful!!
            {
                for (k=0;k<t;k++) // careful!!
                {
                    o=T[j,k];
                    if (o>p) // we are domino
                    {
                        o=o&p;
                        if ((o&m)<1!=(o&M)<1)
                        { // we have motion
                            T[j,k]=o==w?W:o==q?Q:o+o/2+o*2;
                        }
                    }
                }
            }
        }

        if (args.Length > 0)
        {
            L.SetCursorPosition(0, 0);
        }

        // output
        for (o=0;o<f;o++)
        {
            for (j=0;j<t;j++)
            {
                k=T[o,j];
                L.Write(k<0?'#':(k=k>>8)==0?' ':k==Y?'-':k==N?'/':k==U?'|':'\\'); // order for >
            }
            L.WriteLine();
        }


        #if gifness
        if (args.Length > 1)
        {
            g.Dispose();
            bmp.Dispose();

            System.IO.MemoryStream ms = new System.IO.MemoryStream();

            genc.Save(ms);
            byte[] data = ms.GetBuffer();
            byte[] netscape = { 0x21, 0xFF, 0x0B, 0x4E, 0x45, 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2E, 0x30, 0x03, 0x01, 0x00, 0x00, 0x00 };

            if (args.Length > 2)
            {
                int last = -1;
                int duration = int.Parse(args[2]);

                // promise yourself now you will never use this in production code
                // I've not read enough of the GIF spec to know if this is a bad idea or not
                for (i = 0; i < ms.Length - 5; i++)
                {
                    if (data[i] == 0x21 && data[i+1] == 0xF9 && data[i+2] == 0x04 && data[i+3] == 01)
                    {
                        data[i+4] = (byte)(duration & p); // something endian (least significant first)
                        data[i+5] = (byte)((duration & P) >> 8);
                        last = i+4;
                    }
                }

                if (last != -1 && args.Length > 3)
                {
                    duration = int.Parse(args[3]);
                    data[last] = (byte)(duration & p);
                    data[last+1] = (byte)((duration & P) >> 8);
                }
            }

            using (System.IO.FileStream fs = new System.IO.FileStream(args[1], System.IO.FileMode.Create))
            {
                fs.Write(data, 0, 13);

                // behold
                fs.Write(netscape, 0, netscape.Length);

                fs.Write(data, 13, (int)ms.Length - 13); // lets hope these arn't in excess of 2GBs
            }
        }
        #endif
    }
}

세 번째 예제 입력 (및 위에 표시된 것)에 대한 예제 gif

세 번째 예

무작위로 생성 된 100x25 도미노 레이아웃 예

100x25 도미노 레이아웃

도미노의 "도미노"

도미노의 "도미노"


3

파이썬 1188

기본적으로 변경이 멈출 때까지 일부 정규 표현식을 지속적으로 일치시키는 과정을 반복합니다. 실제로 각 방향의 모든 푸시를 개별적으로 (정규식을 통해) 일치시킨 다음 다른 결과를 작성하여 충돌이 발생하지 않도록합니다.

정규식은 아마도 훨씬 간결하게 수행 할 수 있지만 지금은 내가 가진 것입니다 (그리드가 문자열에 저장되고 g치수가 in x및이라고 가정 y) :

import re;L='QWEADZXC';a='';m=(x*y+y);o=[0]*m;X='(.{%s})';t=X%x;u=X%(x+1);v=X%(x-1);R=range
def S(s,l):
 f=s
 for p,r in l:
    n=re.sub(p,r,s,flags=re.DOTALL)
    for i in R(len(n)):
     if n[i]!=s[i]:f=f[:i]+n[i]+f[i+1:]
 return f
while g != a:
 a=g;n='';d=[S(g,[(r'D\|','DD'),(r'D\\','DE'),('D/','DC')]),S(g,[(r'\|A','AA'),(r'\\A','ZA'),('/A','QA')]),S(g,[('-%sW'%t,r'W\1W'),(r'\\%sW'%t,r'E\1W'),('/%sW'%t,r'Q\1W')]),S(g,[('X%s-'%t,r'X\1X'),(r'X%s\\'%t,r'X\1Z'),(r'X%s/'%t,r'X\1C')]),S(g,[('C%s/'%u,r'C\1C'),('C%s-'%u,r'C\1X'),(r'C%s\|'%u,r'C\1D'),('C%s/'%t,r'C\1C'),('C%s-'%t,r'C\1X'),('C/','CC'),(r'C\|','CD')]),S(g,[(r'Z%s\\'%v,r'Z\1Z'),('Z%s-'%v,r'Z\1X'),(r'Z%s\|'%v,r'Z\1A'),(r'Z%s\\'%t,r'Z\1Z'),('Z%s-'%t,r'Z\1X'),(r'\\Z','ZZ'),(r'\|Z','AZ')]),S(g,[('/%sQ'%u,r'Q\1Q'),('-%sQ'%u,r'W\1Q'),(r'\|%sQ'%u,r'A\1Q'),('/%sQ'%t,r'Q\1Q'),('-%sQ'%t,r'W\1Q'),('/Q','QQ'),(r'\|Q','AQ')]),S(g,[(r'\\%sE'%v,r'E\1E'),('-%sE'%v,r'W\1E'),(r'\|%sE'%v,r'D\1E'),(r'\\%sE'%t,r'E\1E'),('-%sE'%t,r'W\1E'),(r'E\\','EE'),(r'E\|','ED')])]
 for i in range(m):
    c=0
    for r in d:
     if r[i]in L:
        if c==0:c=r[i]
        elif r[i]!=c:o[i]=1;break
    n+=g[i]if c==0 or o[i]else c
 g=n
print re.sub(r'\w','#',g)

더 골프하지 않은 :

import re

L = 'QWEADZXC'

def sub_all(string,lst):
    final = string
    for p,r in lst:
        new = re.sub(p,r,string,flags=re.DOTALL)
        for i in range(len(new)):
            if new[i]!=string[i]:
                final=final[:i]+new[i]+final[i+1:]
    return final

def dominoes(grid,x,y):
    print len(grid),x*y+y
    print grid

    last = ''
    locked = [0]*(x*y+y)
    while grid != last:
        last = grid

        Dgrid = sub_all(grid,[(r'D\|','DD'),(r'D\\','DE'),('D/','DC')])
        Agrid = sub_all(grid,[(r'\|A','AA'),(r'\\A','ZA'),('/A','QA')])
        Wgrid = sub_all(grid,[('-(.{%s})W'%x,r'W\1W'),(r'\\(.{%s})W'%x,r'E\1W'),('/(.{%s})W'%x,r'Q\1W')])
        Xgrid = sub_all(grid,[('X(.{%s})-'%x,r'X\1X'),(r'X(.{%s})\\'%x,r'X\1Z'),(r'X(.{%s})/'%x,r'X\1C')])

        Cgrid = sub_all(grid,[('C(.{%s})/'%(x+1),r'C\1C'),('C(.{%s})-'%(x+1),r'C\1X'),(r'C(.{%s})\|'%(x+1),r'C\1D'),
                        ('C(.{%s})/'%x,r'C\1C'),('C(.{%s})-'%x,r'C\1X'),
                        ('C/','CC'),(r'C\|','CD')])

        Zgrid = sub_all(grid,[(r'Z(.{%s})\\'%(x-1),r'Z\1Z'),('Z(.{%s})-'%(x-1),r'Z\1X'),(r'Z(.{%s})\|'%(x-1),r'Z\1A'),
                        (r'Z(.{%s})\\'%x,r'Z\1Z'),('Z(.{%s})-'%x,r'Z\1X'),
                        (r'\\Z','ZZ'),(r'\|Z','AZ')])

        Qgrid = sub_all(grid,[('/(.{%s})Q'%(x+1),r'Q\1Q'),('-(.{%s})Q'%(x+1),r'W\1Q'),(r'\|(.{%s})Q'%(x+1),r'A\1Q'),
                        ('/(.{%s})Q'%x,r'Q\1Q'),('-(.{%s})Q'%x,r'W\1Q'),
                        ('/Q','QQ'),(r'\|Q','AQ')])

        Egrid = sub_all(grid,[(r'\\(.{%s})E'%(x-1),r'E\1E'),('-(.{%s})E'%(x-1),r'W\1E'),(r'\|(.{%s})E'%(x-1),r'D\1E'),
                        (r'\\(.{%s})E'%x,r'E\1E'),('-(.{%s})E'%x,r'W\1E'),
                        (r'E\\','EE'),(r'E\|','ED')])

        grids = [Dgrid,Agrid,Wgrid,Xgrid,Cgrid,Zgrid,Qgrid,Egrid]
        ngrid = ''

        for i in range(x*y+y):
            c = None
            for g in grids:
                if g[i] in L:
                    if c==None: c = g[i]
                    elif g[i] != c:
                        ngrid += grid[i]
                        locked[i]=1
                        break
            else:
                ngrid += grid[i] if c==None or locked[i] else c
        grid = ngrid
        print grid
    return re.sub(r'\w','#',grid)

나열된 입력은 세 번째를 제외하고 모두 출력을 생성합니다. 오차가 있다고 확신 \-/합니다 \|/. 또한 .마지막 것의 왼쪽 하단 모서리가으로 의도 되었다고 가정합니다 D.


당신이 맞습니다, 두 개의 오타가 있었지만 마지막은 E(오히려 차이 가 나는 것은 아닙니다.) 들여 쓰기 깊이를 최소한으로 줄이면 많은 문자를 저장할 수 있습니다.
Martin Ender

세 번째 예제를 복사하여 붙여 넣을 때 실수를했는지 확실하지 않지만 백 슬래시는 떨어지지 않습니다 (네 번째 예제에서는 작동하는 것 같습니다)
Martin Ender

1
@ MartinBüttner, 복사 붙여 넣기에 문제가 있었지만 (줄 끝에 공백이없고 탭이없고 공백이 없는지 확인하십시오) 올바르게 입력하면 작동하는 것 같습니다. 동일한 행에 예상되는 결과없이 예제 입력을 복사하여 붙여 넣기하기 쉬운 형식으로 만드는 것이 도움이 될 수 있습니다.
KSab
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.