목걸이 분할 문제


19

배경

내가 영감을받은 3Blue1Brown 의 최근 영상 정보] 목걸이 분할 문제 (또는 그는, 훔친 목걸이 문제 전화로)과의 관계 보르 수크 - 울람 정리를 .

이 문제에서는 두 강도는 보석의 여러 가지 유형으로 구성된 소중한 목걸이를 훔쳤다. 이 보석의 각 유형의 짝수이며, 도둑은 두 사람 사이에 균등하게 각 보석 유형을 분리하고 싶습니다. 캐치은 연속 몇몇 개수의 세그먼트로 분할하여 그렇게 목걸이를하고 두 사람 사이의 세그먼트를 배포해야한다는 것입니다.

여기서 표시된 네 보석 유형의 예는 S, E, D, 및 R(각각 사파이어, 에메랄드, 다이아몬드, 루비 용). 목걸이가 다음과 같다고 가정 해 봅시다.

[S,S,S,E,S,D,E,R,S,R,E,S,S,S,D,R,E,E,R,E,D,E,R,R,D,E,E,E]

있다 8사파이어, 10에메랄드, 4다이아몬드와 6루비. 목걸이를 다음과 같이 나눌 수 있습니다.

[[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]

우리는 하나 개 도둑 다른 도둑에 제 2 및 제 4 세그먼트에 제 1, 제 3, 제 5 세그먼트를 제공한다면, 각각으로 끝날 4 사파이어, 5에메랄드, 2다이아몬드 및 3루비로 .

[S],    [S,E,S,D,E,R,S],                            [R,R,D,E,E,E]
    [S],                [R,E,S,S,S,D,R,E,E,R,E,D,E],

사용 0-indexing를,이 상처는 인덱스에서 발생 [1,2,9,22].

그러한 공정 분할은 항상 보석 종류의 수 인 최대 n컷을 사용하여 수행 할 수 n있습니다. 당신의 임무는 목걸이를 입력으로 사용하고 최소한의 그러한 분할 (최소 컷 수)을 출력하는 완전한 프로그램이나 기능을 작성하는 것입니다.

입력

입력은 편리한 형식 일 수 있습니다. 목걸이는 일련의 보석이어야하며 그 이상은 아닙니다. 예를 들어 정수 목록, 보석 종류 및 값을 나타내는 키가있는 사전은 색인 목록입니다. 선택적으로 목걸이의 길이 또는 별개의 보석 유형 수를 포함 할 수 있지만 다른 입력은하지 마십시오.

입력 목걸이가 유효하다고 가정 할 수 있습니다. 거기에 지정된 유형의 보석의 홀수 또는 목걸이가 비어 어디 있는지 경우를 처리 할 필요가 없습니다.

산출

다시, 출력은 임의의 편리한 형식 일 수있다; 예를 들어, 세그먼트의 목록은, 절단 위치의리스트가 상기 두 강도를 나타내는 키와 세그먼트의 목록 인 값으로 사전이 등 세그먼트 보석 인덱스 연속 인덱스리스트 목록을 종료 선발 인덱스로 나타낼 수있다, 길이 등 . 0또는 1인덱싱을 사용할 수 있습니다 . 순서가 형식에 중요하지 않은 경우 출력 순서가 달라질 수 있습니다. 다음은 여러 가지 형식의 위 출력입니다.

list of segments: [[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]
list of cuts:     [1,2,9,22]
list of lengths:  [1,1,7,13,6]
dictionary:       {'thief1' : [(R,R,D,E,E,E),(S),(S,E,S,D,E,R,S)], 'thief2' : [(S),(R,E,S,S,S,D,R,E,E,R,E,D,E)]}

순서가 아니라 상처 또는 사전의 목록에서 세그먼트 목록 (세그먼트 도둑 교대)와 (세그먼트를 식별하기 위해) 길이의 목록에서 중요합니다. 편집 : 그렉 마틴 (Greg Martin)은 공정 분할을 두 번의 컷으로 얻을 수 있기 때문에 이것이 유효한 결과가 아니라고 지적했습니다.

테스트 사례

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

노트

  1. 표준 허점 은 금지되어 있습니다.
  2. 이것은 . 최단 답변 (바이트)이 이깁니다.

2
목걸이가 원형인가요?
Dennis

1
@ 데니스 아니, 목걸이는 선형입니다.
ngenisis

1
정수 대신 다른 보석 유형을 나타내는 문자 / 토큰으로 입력을 취할 수 있습니까?
그렉 마틴

3
세그먼트 순서가 변경되지 않은 경우 조각은 if A와 if B 사이에서 번갈아 나타납니다. 따라서 출력에 해당 정보를 포함하면 중복됩니다. 우리는 대답은 보석의 순서를 변경하지 않는 경우 도둑 표시를 생략 할 수 있습니까? 테스트 사례가 있습니까?
Luke

2
귀하의 예를 들어 [S,S,S,E,S,D,E,R,S,R,E,S,S,S,D,R,E,E,R,E,D,E,R,R,D,E,E,E], [[S,S,S,E,S,D,E,R],[S,R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]그보다 더 적은 컷이 있기 때문에 출력이 있어야합니다 [[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]. 나는 제대로 스펙을 이해하고 있습니까?
그렉 마틴

답변:


3

Brachylog , 13 바이트

~c.ġ₂z₁Ċcᵐoᵛ∧

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

참고 : metapredicate는 이 도전보다 최신 버전입니다.

설명

~c.ġ₂z₁Ċcᵐoᵛ∧  Input is a list, say L = [1,2,2,2,1,2,3,3]
~c.            Output is a partition of the input: [[1,2,2],[2,1,2],[3],[3]]
  .ġ₂          Split the output into chunks of length 2: [[[1,2,2],[2,1,2]],[[3],[3]]]
     z₁        Zip (transpose) the chunks: [[[1,2,2],[3]],[[2,1,2],[3]]]
       Ċ       This is a 2-element list (forbid the trivial partition).
        cᵐ     Concatenate both: [[1,2,2,3],[2,1,2,3]]
          oᵛ   If you sort both lists, they are equal.
            ∧  Don't unify with the output.

파티션은 블록 수의 순서대로 증가하므로 결과적으로 가능한 적은 블록을 갖게됩니다.


3

젤리 , 18 바이트

s2ZFṢ$€E¬,L
ŒṖṖÇÞḢ

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

효율적이지는 - 예제가있다 (28 개) 이 구현의 첫 번째 단계는 목록을 구축하는 것 때문에 엄청난 자원이없는 거예요 작업 보석 2 개 27 가능한 파티션을.

대체 도둑들 사이에서 그들을 요리하기 위해 순서대로 목록의 목록을 반환합니다. (TIO 출력 다시 : 목록에 단일 항목 만있는 경우 암시 적 인쇄는 괄호로 묶이지 않습니다. [])

어떻게?

s2ZFṢ$€E¬,L - Link 1, get (isUnfair, Slices): A possible partition
s2          - split into slices of length 2 (any odd one on it's own at the end)
  Z         - transpose (first item is one thief's slices, second is the others)
     $€     - last two links as a monad for €ach
   F        -     flatten
    Ṣ       -     sort
       E    - equal? (theif1's jewels == theif2's jewels)
        ¬   - not
          L - length (number of slices in the partition)
         ,  - pair

ŒṖṖÇÞḢ - Main link: necklace
ŒṖ     - all partitions
  Ṗ    - pop, we must remove the rightmost one...
              because Link 1 will say it is fair, and it will have length 1!
              (a list of one thing has all entries equal)
    Þ  - sort by
   Ç   -     last link (1) as a monad
     Ḣ - head (get the first one, i.e. minimal isUnfair, then minimal length)

3

수학, 118 바이트

거의 젤리를 이길 ... 단지 1 오프;)

SelectFirst[l_±c_:=Append[-#±Most@c,#2]&@@l~TakeDrop~Last@c;l_±{}:={l};i=#;(i±#)&/@Range@#2~Subsets~#3,Tr[Tr/@#]==0&]&

세 가지 인수를 취하는 순수 함수 : 목걸이와 같은 토큰 목록 {A, A, A, A, B, C, D, B, C, D, B, B}; 목걸이의 길이; 별개의 보석 시간의 수. {{A, A}, {-A, -A, -B, -C, -D, -B}, {C, D, B, B}}음수 부호가없는 토큰은 한 도둑으로 이동하고 음수 부호가있는 토큰은 다른 도둑으로 이동 하는 양식의 하위 목록을 반환합니다 . (이것은 중복 정보이지만 알고리즘은이 표현으로 이어지고 음수 부호를 제거하면 몇 바이트가 소요됩니다.)

먼저리스트와 n컷- n+1플레이트 세트를 가져 와서 그 n컷-플레이스 에서 입력리스트를 잘라서 얻은 서브 리스트리스트를 리턴 하는 함수를 구현해야합니다 . 이진 접두사 연산자 ±는이 목적으로 사용되며를 통해 재귀 적으로 정의됩니다 l_±c_:=Append[-#±Most@c,#2]&@@l~TakeDrop~Last@c;l_±{}:={l};. 바로 뒤에 마이너스 부호가 있기 때문에 Append하위 목록에 각 토큰에 마이너스 부호가 교대로 붙어 있고 포함되지 않습니다.

다음 우리는 길이가 보석의 종류, 사용의 수가 많아야 모든 가능한 절단 장소 세트를 생성 Range@#2~Subsets~#3및 사용 i=#;(i±#)&/@적용 할 ±차례대로 절단 장소 세트 각각 (보석의 입력리스트) 연산자.

마지막으로 SelectFirst[...,Tr[Tr/@#]==0&]&공정한 결과 목걸이 부문 중 첫 번째를 선택합니다. 문자 그대로 모든 하위 목록에있는 모든 요소를 ​​합산하여 수행합니다. Mathematica는 각 토큰의 긍정 및 부정 사본을 명백한 방식으로 취소 할 수있을 정도로 현명합니다.


3

Pyth, 16 바이트

hfqFSMsM.TcT2t./

온라인으로 사용해보십시오 : 데모 또는 테스트 스위트

설명:

hfqFSMsM.TcT2t./Q   implicit Q (=input) at the end
              ./Q   create all partitions of the input list 
                    (they are already sorted by number of cuts)
             t      remove the partition with zero splits
 f                  filter for partitions T, which satisfy:
          cT2          chop into pieces of length 2
        .T             transpose to get the pieces of each thieve
    SMsM               combine all pieces for each thieve and sort the results
  qF                   check if they got the same jewels
h                   print the first such partition

1

05AB1E , 14 바이트

.œ¨ʒ2ôζε˜{}Ë}¤

온라인으로 시도 하거나 모든 테스트 사례를 확인하십시오 .

설명:

                # All partitions of the (implicit) input
                  #  i.e. [2,3,2,1,3,1]
                  #   → [[[2],[3],[2],[1],[3],[1]],[[2],[3],[2],[1],[3,1]],
                  #      ...,[[2,3,2,1,3,1]]]
  ¨               # Remove the last one
   ʒ        }     # Filter this list by:
    2ô            # Split it into parts of 2
                  #  i.e. [[2,3],[2],[1],[3,1]] → [[[2,3],[2]],[[1],[3,1]]]
                  #  i.e. [[2,3,2],[1,3],[1]] → [[[2,3,2],[1,3]],[[1]]]
      ζ           # Swap rows and columns (using space as filler if necessary)
                  #  i.e. [[[2,3],[2]],[[1],[3,1]]] → [[[2,3],[1]],[[2],[3,1]]]
                  #  i.e. [[[2,3,2],[1,3]],[[1]]] → [[[2,3,2],[1]],[[1,3]," "]]
       ε  }       # Map each inner list to:
        ˜         # Flatten the list
                  #  i.e. [[2,3],[1]] → [2,3,1]
                  #  i.e. [[1,3]," "] → [1,3," "]
         {        # Sort the list
                  #  i.e. [2,3,1] → [1,2,3]
                  #  i.e. [1,3," "] → [1,3," "]
           Ë      # Check if both sorted lists are equal
                  # (if not, remove them from the partitions)
             ¤    # After filtering, take the last one as result (and output implicitly)
                  #  i.e. [[[2],[3,2],[1,3],[1]],[[2,3],[2],[1],[3,1]]]
                  #   → [[2,3],[2],[1],[3,1]]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.