그리드를 삼각형으로 분할


18

이 문제의 목표는 삼각형의 모든 정점이 그리드 점에 n있는 n X 1그리드를 삼각형 으로 분할하는 방법의 수를 계산 하는 함수를 생성하는 것입니다 .

예를 들어, 파티션이 각각 2, 2, 2, 2, 4 및 2 개의 서로 다른 방향 f(2) = 14을 갖는 다음 파티션을 통해 2 x 1 그리드를 분할하는 14 가지 방법이 2 x 1의 파티션있습니다.

채점

이것은 이므로 가장 짧은 코드가 승리합니다.


10
일부 추가 테스트 사례가 도움이되므로 제출 내용이 올바른지 확인할 수 있습니다.
AdmBorkBork

8
축퇴하지 않은 삼각형 을 지정할 수 있습니다 .
Arnauld

1
이 해석을 반영하기 위해 OEIS 시퀀스 A051708 을 편집했습니다 .
피터 카게이

답변:


2

05AB1E , 13 바이트

·LÉœÙεÅγo;P}O

@ 버블 러 의 젤리 답변 포트 .

내장 된 순열로 인해 매우 느립니다.

온라인으로 시도 하거나 처음 네 개의 입력을 확인하십시오 .

설명:

·                # Double the (implicit) input
 L               # Create a list in the range [1, doubled_input]
  É              # Check for each if they're odd (1 if truthy, 0 is falsey)
                 # We now have a list of n 0s and n 1s (n being the input)
   œ             # Get all permutations of that list
    Ù            # Only leave the unique permutations
     ε     }     # Map each permutation to:
      Åγ         #  Run-length encode the current value (short for `γ€g`)
        o        #  Take 2 to the power for each
         ;       #  Halve each
          P      #  Take the product of the mapped permutation
            O    # Sum all mapped values together (and output implicitly)

19

하스켈 , 60 55 54 52 바이트

많은 예제를 그리고 프로그래밍 한 후에, 이것은 루크의 문제와 동일하다는 것이 나에게 발생했습니다.

에 체스 판에서 갈 루크를 위해 얼마나 많은 방법이있다 에 바로 이동하여 또는 최대 ?(n+1)×(n+1)(0,0)(n,n)+(1,0)+(0,1)

기본적으로 그리드 의 맨 위와 맨 아래 줄이 있습니다. 이제 수평이 아닌 선을 채워야합니다. 각 삼각형에는 두 개의 수평이 아닌 선이 있어야합니다. 측면 중 하나가 상단 또는 하단 라인의 일부인지 여부는 루크 문제에서 갈 방향과 길이에 해당합니다. 이다 OEIS A051708 . 이 서신의 실례로서 다음 예를 고려하십시오. 여기에서 맨 위 줄은 위쪽으로 이동하고 맨 아래 줄은 오른쪽으로 이동합니다.1×n

-6 바이트의 경우 @PeterTaylor와 -2 바이트의 경우 @PostLeftGarfHunter에게 감사합니다!

b 0=1
b 1=2
b n=div((10*n-6)*b(n-1)-9*(n-2)*b(n-2))n

온라인으로 사용해보십시오!


처음 몇 값으로 검색하여 OEIS 시퀀스를 찾았습니다. 왜 일치하는지에 대한 좋은 설명. 이 대체 조합 해석에 대한 의견을 추가하기 위해 편집 하시겠습니까? 그렇지 않다면 나는 할 수있다.
피터 테일러

BTW 여기에 정답이 있기 때문에 인덱싱을 조정해야합니다 A051708(n+1). 내가 처음 게시 그래서 올바른 응답 - P
피터 테일러

위쪽 및 아래쪽 가장자리가있는 삼각형을 위 또는 오른쪽으로 대응시켜 루크 이동을 삼각형으로 이동합니까?

@PeterTaylor 젠장, 내 실수를 지적 해 주셔서 감사합니다 :)
flawr

5
@Neil 그래픽 설명을 추가했습니다.
flawr

8

하스켈 , 42 바이트

0?0=1
a?b=sum[a?i+i?a|i<-[0..b-1]]
f n=n?n

온라인으로 사용해보십시오!

2 개 이상의 변수를 재귀 적으로 구현하는 상당히 직접적인 구현입니다.

이 솔루션을 얻는 방법은 다음과 같습니다. 직접 재귀 공식을 구현하는 코드로 시작하십시오.

54 바이트

0%0=1
a%b=sum$map(a%)[0..b-1]++map(b%)[0..a-1]
f n=n%n

온라인으로 사용해보십시오!

사용 flawr의 루크 이동 해석을 , a%b에서 루크를 얻는 경로의 수 (a,b)(0,0)사용이 만 좌표 감소를 이동합니다. 첫 번째 이동은 감소 a하거나 감소 b하여 다른 하나는 동일하게 유지하므로 재귀 공식은 유지됩니다.

49 바이트

a?b=sum$map(a%)[0..b-1]
0%0=1
a%b=a?b+b?a
f n=n%n

온라인으로 사용해보십시오!

우리는 map(a%)[0..b-1]++map(b%)[0..a-1]두 반쪽이 동일 a하고 b서로 바뀌 었다는 점을 지적함으로써 반복을 피할 수 있습니다 . 보조 통화가 a?b첫 번째 이동이 감소 경로를 계산 a하고, 그래서 b?a제 움직임이 감소 여기서 그 카운트 b. 이들은 일반적으로 다르며에 추가됩니다 a%b.

의 요약은 a?b목록 이해로 작성 될 수도 있습니다 a?b=sum[a%i|i<-[0..b-1]].

42 바이트

0?0=1
a?b=sum[a?i+i?a|i<-[0..b-1]]
f n=n?n

온라인으로 사용해보십시오!

마지막으로, 우리는 없애 %단지의 관점에서 재귀를 쓰기 ?로 대체하여 a%i함께 a?i+i?a재귀 호출한다.

새로운 기본 케이스는이 원인 ?출력 줄의 두 배에 ?49 바이트 버전과 이후 0?0=1, 우리가 가지고있는 것입니다 0%0=0?0+0?0=2. 이것은 f n=n?n우리가해야 할 일없이 절반을 정의 하여 사용할 수있게합니다 .


49 바이트 솔루션은 내 답변과 동일한 재귀를 사용하지만 아직 42 바이트 솔루션을 찾지 못했습니다. 설명이 좋을 것입니다.
피터 테일러

필자는 이전 프로그램 중 하나에서 동일한 접근 방식을 사용했다고 생각합니다. 아이디어는 오른쪽에서 왼쪽으로 수평이 아닌 행을 생성하여 모든 파티션을 생성하거나 계산하는 것입니다. 당신은 세로선으로 시작합니다. 그런 다음 되풀이 할 수 있습니다. 이전 줄의 끝 노드 중 하나를 가져 와서이 줄의 모든 이전 노드의 왼쪽에있는 반대쪽 수평선의 노드에 연결하십시오.
flawr

연산자 a%b0,1,...,a맨 위 줄 의 노드 와 0,1,..,b맨 아래 줄 의 노드 를 사용하여 파티션 수를 계산합니다 . 운영자 a?ba맨 아래 노드 b가 이미 사용중인 경우 맨 위 노드에서 새 줄을 추가 할 수있는 방법의 수를 계산합니다 . ( a모든 노드에 연결할 수 [0,1,...,b-1]있지만 각 노드 에 대해 재귀를 수행해야합니다.)
flawr

@ flawr, 이것이 49 바이트입니다. 그것은 ?내가하지 않은 42 바이트 중 하나이며, 특히 흥미로운 것은 대칭이 아니라는 것입니다.
피터 테일러

@PeterTaylor 혼란을 끼쳐 드려 죄송합니다. 어떻게 든 두 솔루션을 혼합했습니다. 두 솔루션을 서로 쉽게 변환 할 수 있다고 생각합니다. 첫 번째 단계에서는 map...목록 이해로 대체 할 수 있으며 두 번째 단계에서는 다음과 같이 정의를 연결합니다 %.a?b=sum$map(a%)[0..b-1], a%b=a?b+b?a a?b=sum[a%i|i<-[0..b-1]], a%b=a?b+b?a a?b=sum[a?i+i?a|i<-[0..b-1]]
flawr

7

CJam (24 바이트)

{2,*e!{e`0f=:(1b2\#}%1b}

온라인 데모

이것은 0과 1의 순열을 합산 하는 Bubbler의 접근 방식 을 사용합니다 .nn

해부

{         e# Define a block
  2,*     e#   Given input n, create an array of n 0s and n 1s
  e!      e#   Generate all permutations of that array
  {       e#   Map:
    e`    e#     Run-length encode
    0f=:( e#     Extract just the lengths and decrement them
    1b    e#     Sum
    2\#   e#     Raise 2 to the power of that sum
  }%
  1b      e#  Sum the mapped values
}

대체 접근 방식 (28 바이트)

{_1aa{_2$,f{j}@@,f{j}+1b}2j}

온라인 데모

해부

삼각형에는 모두 수평선을 연결하는 하나의 가로 가장자리와 두 가장자리가 있습니다. 수평이 아닌 모서리에 두 x 좌표의 튜플로 레이블을 지정하고 사전 식으로 정렬합니다. 그런 다음 첫 번째 가장자리는 (0,0)이고 마지막 가장자리는 (n,n)이며 두 개의 연속 가장자리는 두 위치 중 하나가 정확하게 다릅니다. 이것은 간단한 재귀를 만들어 주며, 나는 메모 된 재귀 연산자를 사용하여 구현했습니다 j.

{            e# Define a block
  _          e#   Duplicate the argument to get n n
  1aa        e#   Base case for recursion: 0 0 => 1
  {          e#   Recursive body taking args a b
    _2$,f{j} e#     Recurse on 0 b up to a-1 b
    @@,f{j}  e#     Recurse on a 0 up to a b-1
    +1b      e#     Combine and sum
  }2j        e#   Memoised recursion with 2 args
}

노트

fjCJam에서 처음으로 지원 받기를 원했던 것은 아닙니다. 여기에서 점수는 24 바이트로 줄어 듭니다. 아마도 패치를 작성해야합니다 ...


야호, 나는 10 초를 이길, 나는 내가 생각하지 않는 그 가까운 :)
flawr

@flawr, 나는 해부를 작성하기 전에 게시를 고려했지만 신속하게 게시를 중단 할 시간이 있다고 생각했습니다. 그런 다음 "새 답변"을 보았으므로 부분 작성 해부를 삭제하고 게시하고 편집했습니다.
피터 테일러

1
-5 바이트 감사합니다 btw : D
flawr

4

젤리 , 15 14 바이트

Ø.xŒ!QŒɠ€’§2*S

온라인으로 사용해보십시오!

Peter Taylor의 의견에 따라 -1 바이트.

결과 수식 대신 flawr의 그림을 직접 사용합니다 .

작동 원리

Ø.xŒ!QŒɠ€’§2*S    Main link (monad). Input: positive integer N.
Ø.x               Make an array containing N zeros and ones
   Œ!Q            All unique permutations
      Œɠ€         Run-length encode on each permutation
         ’§       Decrement and sum each
           2*S    Raise to power of 2 and sum

가능한 모든 경로를 정사각형 그리드로 가져 가십시오. 루크로서 L 유닛을 한 방향으로 이동시키는 방법의 수는 2**(L-1)입니다. 이것을 모든 경로에 적용하고 각 경로를 통과하는 방법의 수를 합산하십시오.


좋은 접근법. CJam으로 포팅 할 때 길이를 줄이고 합계를 줄인 다음 2를 합계로 올리는 것이 더 짧았습니다. 길이를 2로 늘리고 반으로 곱한 다음 곱하는 대신 바이트를 절약 할 수 있는지 여부를 모릅니다.
피터 테일러

3

, 44 31 바이트

44를 넘어 여전히 여전히 44입니다

F⊕θ«≔⟦⟧ηF⊕θ⊞ηΣ∨⁺ηEυ§λκ¹⊞υη»I⊟⊟υ

온라인으로 사용해보십시오! 설명 : 반대쪽 길이의 사다리꼴 m,n을 정수 오프셋에있는 삼각형 으로 분할하는 방법의 수를 계산하여 작동 합니다. 이것은 단순히 n문제 의 크기 사각형의 일반적인 경우입니다 . 파티션들의 수는 모든 측면에 대한 분할 영역의 개수의 합으로서 재귀 부여 m,0..n-1하고 n,0..m-1. 이는 루크의 일반화 된 문제인 OEIS A035002와 동일 합니다. 이 코드는 단순히 이전에 계산 된 값 0,0n,n사용하여 작업하는 파티션 수를 계산합니다.

F⊕θ«

행을 반복합니다 0..n.

≔⟦⟧η

빈 행으로 시작하십시오.

F⊕θ

행의 열을 반복합니다 0..n.

⊞ηΣ∨⁺ηEυ§λκ¹

지금까지 행과 현재 열의 이전 행 값을 가져 와서 합계를 현재 행에 추가하십시오. 그러나 값이 전혀 없으면 1합계 대신 대체 하십시오.

⊞υη»

완료된 행을 지금까지 행 목록에 추가하십시오.

I⊟⊟υ

계산 된 최종 값을 출력합니다.




당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.