마칭 사각형 조회


9

Marching Squares 는 컴퓨터 그래픽의 알고리즘으로, 샘플 그리드에서 2D 등고선을 복구하는 데 사용됩니다 ( 3D 설정을위한 큰 형 Marching Cubes 참조 ). 아이디어는 그리드의 각 셀을 독립적으로 처리하고 모서리의 값을 기반으로 해당 셀을 통과하는 윤곽을 결정하는 것입니다.

이 프로세스의 첫 번째 단계는 모서리가 형상 값보다 큰지 또는 낮은 지에 따라 윤곽으로 연결된 모서리를 결정하는 것입니다. 간단하게하기 위해 값을 따라 윤곽선 만 고려 0하여 모서리가 양수인지 음수인지에 관심을 갖습니다. 구별해야 할 경우 가 있습니다 .24 = 16

여기에 이미지 설명을 입력하십시오
이미지 출처 : Wikipedia

흰색과 검은 색을 식별하는 것은 실제로 중요하지 않지만 명확성을 위해 흰색은 양이고 검은 색은 음이라고 말합니다. 모퉁이 중 하나가 정확히 일치하는 경우는 무시합니다 0.

새들 포인트 (케이스 5 및 10)는 약간의 추가 어려움을 제공합니다. 모서리를 보면서 만 사용해야하는 대각선은 확실하지 않습니다. 이것은 네 모서리의 평균 (즉, 중심 값의 근사값)을 찾아 윤곽선이 중심에서 반대 부호로 모서리를 분리하도록 대각선을 선택하여 해결할 수 있습니다. 평균이 정확히 0인 경우 두 경우 모두 선택할 수 있습니다.

일반적으로이 16 가지 경우는 단순히 조회 테이블에 저장됩니다. 이것은 효율성에는 좋지만 물론 여기서는 코드가 짧은 것이 좋습니다. 따라서이 조회 단계를 수행하고 사례의 ASCII 표현을 가능한 한 적은 코드로 인쇄해야합니다.

도전

고정 된 순서대로 네 모퉁이 (0이 아닌 정수)의 값이 제공됩니다. 그런 다음 새들 포인트 케이스를 올바르게 해결하여 윤곽선의 올바른 레이아웃을 생성해야합니다.

STDIN (또는 가장 가까운 대안), 명령 행 인수 또는 함수 인수를 통해 입력을 받고 STDOUT (또는 가장 가까운 대안), 함수 리턴 값 또는 함수 (out) 매개 변수를 통해 결과를 출력하는 프로그램 또는 함수를 작성할 수 있습니다.

편리한 문자열 또는 목록 형식으로 입력 할 수 있습니다.

16 가지 경우는 다음 5x5 블록 중 하나를 사용하여 ASCII 형식으로 표현됩니다.

o---o  o---o  o---o
|   |  |   |  | | |
|   |  |---|  | | |
|   |  |   |  | | |
o---o  o---o  o---o

o---o  o---o  o---o  o---o
|/  |  |  \|  |   |  |   |
|   |  |   |  |   |  |   |
|   |  |   |  |\  |  |  /|
o---o  o---o  o---o  o---o

o---o  o---o
|/  |  |  \|
|   |  |   |
|  /|  |\  |
o---o  o---o

선행 또는 후행 공백을 인쇄해서는 안되지만 단일 선택적 개행을 인쇄 할 수 있습니다.

이것은 코드 골프이므로 가장 짧은 대답 (바이트)이 이깁니다.

테스트 사례

테스트 케이스는 입력 순서에 제시되어 가정 왼쪽 위 , 오른쪽 위 , 왼쪽 아래 , 오른쪽 아래 . 테스트 사례는 9 개의 그룹으로 제공되며, 하나는 위에 주어진 9 개의 표현에 해당합니다 (빈 셀에서 시작하여 두 개의 새들 포인트로 끝남).

[1, 2, 1, 3]
[-9, -2, -2, -7]

[4, 5, -1, -2]
[-1, -2, 3, 4]

[7, -7, 7, -7]
[-5, 5, -5, 5]

[1, -6, -4, -1]
[-2, 3, 3, 4]

[-1, 6, -4, -1]
[2, -3, 3, 4]   

[-1, -6, 4, -1]
[2, 3, -3, 4]

[-1, -6, -4, 1]
[2, 3, 3, -4]

[3, -8, -9, 2]
[-3, 8, 9, -2]

[8, -3, -2, 9]
[-8, 3, 2, -9]

또한 다음 테스트 사례는 새들 포인트 중 하나를 반환 할 수 있습니다 (선택).

[1, -4, -2, 5]
[-1, 4, 2, -5]

답변:


5

루비 201 180 176

이것은 익명의 람다 함수이며, ungolfed 예제에 표시된 방식으로 호출됩니다.

변수가 없습니다 s. ungolfed 버전에서는 s사용하기 전에 명확성 을 위해 복잡한 표현식이 지정 됩니다. 4 바이트는 인라인으로 넣어 골프 버전으로 저장됩니다. 버전 사이의 다른 차이점은 공백과 주석입니다.

stdout으로 인쇄하는 대신 출력을 5 개의 문자열 5 개 배열로 반환하는 것이 허용되는 경우 1 바이트를 더 저장할 수 있습니다.

->a{p=t=0
4.times{|i|t+=a[i]*=a[3];p+=a[i]>>9&1<<i}
q=p==6&&t>0?19:'@AC@P*10'[p].ord
puts c='o---o',(0..2).map{|i|b=p*i==3?'|---|':'|   |';b[q%4]='|/|\|/'[q%4+(i&2)];q/=4;b},c}

배열 구문 분석에 만족하지만 출력을 형성하는 방법이 더 짧을 수 있다고 생각합니다.

입력 배열의 네 가지 요소 모두 마지막 요소로 곱해집니다. 이를 통해 마지막 요소가 양수임을 보장하고 사례 수를 16에서 8로 줄입니다. 요소는 9 자리 오른쪽으로 이동하여 모든 양수가 0이되고 모든 음수가 -1이됩니다 (적어도 입력 범위에서) 그런 다음 1<<array index패턴을 나타내는 3 비트 이진수를 제공하기 위해 AND로 AND됩니다 (실제로 4 비트이지만 마지막 요소가 항상 양수이므로 4 번째 비트는 항상 0입니다).

그런 다음 0..7의이 숫자는 (sigh) 조회 테이블에 공급되어 공백이 아닌 각 행의 문자를 판별합니다. 이 단계에서는 총합이 양수인 경우 조회 테이블의 숫자 대신 사용되는 새들 케이스에 대한 두 개의 서로 다른 디스플레이가 처리됩니다 (질문은 "평균"을 고려하지만, 우리는 단지 부호에 관심이 있다면 총계를 고려해도 문제가되지 않습니다.)

출력이 표시되는 방식은 코드의 주석에서 명확하게 나타납니다.

테스트 프로그램에서 ungolfed

f=->a{p=t=0
  4.times{|i|                      #for each number in the input
    t+=a[i]*=a[3];                   #multiply each number by a[3]; totalize the sum in t
    p+=a[i]>>9&1<<i                  #shift right to find if negative; AND with 1<<i to build index number for pattern 
  }                                #q is a 3-digit base 4 number indicating which character of each line is non-whitespace (if any). 
  q=p==6&&t>0?19:'@AC@P*10'[p].ord #It's encoded in the magic string, except for the case of saddles with a positive total, which is encoded by the number 19.
  s=(0..2).map{|i|                 #build an array of 3 strings, indexes 0..2
    b=p*i==3?'|---|':'|   |';        #IF p is 3 and we are on row 1, the string is |---| for the horizontal line case. ELSE it is |   |.
    b[q%4]='|/|\|/'[q%4+(i&2)];      #The numbers in q indicate which character is to be modified. The characters in the string indicate the character to replace with.
    q/=4;                            #If q%4=0, the initial | is replaced by | (no change.) i&2 shifts the string index appropriately for the last row.
    b                                #divide q by 4, and terminate the loop with the expression b so that this is the object loaded into array s.  
  }
puts c='o---o',s,c}                #print the array s, capped with "o---o" above and below.


[[1, 2, 1, 3],
[-9, -2, -2, -7],

[4, 5, -1, -2],
[-1, -2, 3, 4],

[7, -7, 7, -7],
[-5, 5, -5, 5],

[1, -6, -4, -1],
[-2, 3, 3, 4],

[-1, 6, -4, -1],
[2, -3, 3, 4],

[-1, -6, 4, -1],
[2, 3, -3, 4],

[-1, -6, -4, 1],
[2, 3, 3, -4],

[3, -8, -9, 2],
[-3, 8, 9, -2],

[8, -3, -2, 9],
[-8, 3, 2, -9],

[1, -4, -2, 5],
[-1, 4, 2, -5]].each{|k|f.call(k)}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.