Vấn đề tách vòng cổ


19

Lý lịch

Tôi đã được truyền cảm hứng từ video gần đây của 3Blue1Brown về vấn đề tách vòng cổ (hay như ông gọi nó là vấn đề vòng cổ bị đánh cắp) và mối quan hệ của nó với định lý Borsuk-Ulam .

Trong vấn đề này, hai tên trộm đã đánh cắp một chiếc vòng cổ có giá trị bao gồm nhiều loại trang sức khác nhau. Có một số lượng chẵn của từng loại trang sức và những tên trộm muốn chia đều từng loại trang sức giữa hai loại. Điều hấp dẫn là họ phải làm như vậy bằng cách chia vòng cổ thành một số phân đoạn liền kề và phân phối các phân đoạn giữa hai người họ.

Dưới đây là một ví dụ với bốn loại ngọc ký hiệu S, E, D, và R(cho sapphire, ngọc lục bảo, kim cương, ruby và, tương ứng). Hãy nói rằng vòng cổ như sau:

[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]

8ngọc bích, 10ngọc lục bảo, 4kim cương và 6hồng ngọc. Chúng ta có thể chia vòng cổ như sau:

[[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]]

Sau đó, nếu chúng ta đưa các phân đoạn thứ nhất, thứ ba và thứ năm cho một tên trộm và các phân đoạn thứ hai và thứ tư cho kẻ trộm khác, mỗi phân đoạn sẽ kết thúc bằng 4ngọc bích, 5ngọc lục bảo, 2kim cương và 3hồng ngọc:

[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],

Sử dụng 0-indexing, những vết cắt này xảy ra tại các chỉ số [1,2,9,22].

Mục tiêu

Nó chỉ ra rằng một phân chia công bằng như vậy luôn có thể được thực hiện bằng cách sử dụng tại hầu hết các nvết cắt, trong đó nsố lượng các loại trang sức. Nhiệm vụ của bạn là viết một chương trình hoặc chức năng hoàn chỉnh, lấy một vòng cổ làm đầu vào và đưa ra một phép chia tối thiểu như vậy (số lần cắt ít nhất).

Đầu vào

Đầu vào có thể ở bất kỳ định dạng thuận tiện. Vòng cổ nên là một chuỗi trang sức và không có gì hơn; ví dụ: danh sách các số nguyên, từ điển với các khóa đại diện cho các loại trang sức và giá trị là danh sách các chỉ số. Bạn có thể tùy ý bao gồm chiều dài của vòng cổ hoặc số loại trang sức riêng biệt, nhưng bạn không nên lấy bất kỳ đầu vào nào khác.

Bạn có thể cho rằng vòng cổ đầu vào là hợp lệ. Bạn không cần phải xử lý trường hợp có một số lượng trang sức lẻ của một loại nhất định hoặc vòng cổ trống.

Đầu ra

Một lần nữa, đầu ra có thể ở bất kỳ định dạng thuận tiện; ví dụ: danh sách các phân đoạn, danh sách các vị trí cắt, từ điển với các khóa đại diện cho hai tên trộm và giá trị là danh sách các phân đoạn, v.v. Các phân đoạn có thể được biểu thị bằng chỉ mục bắt đầu, chỉ mục kết thúc, danh sách các chỉ số liên tiếp, danh sách trang sức, độ dài của chúng, v.v. Bạn có thể sử dụng 0- hoặc 1- lập chỉ mục. Nếu thứ tự không quan trọng đối với định dạng của bạn, thì đầu ra của bạn có thể theo bất kỳ thứ tự nào. Đây là đầu ra ở trên trong một số định dạng khác nhau:

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)]}

Lưu ý rằng thứ tự rất quan trọng trong danh sách các phân đoạn (phân đoạn xen kẽ giữa những tên trộm) và danh sách độ dài (để xác định các phân đoạn), nhưng không có trong danh sách cắt giảm hoặc từ điển. Chỉnh sửa: Greg Martin chỉ ra rằng đây sẽ không phải là kết quả đầu ra hợp lệ vì có thể thu được sự phân chia công bằng trong hai lần cắt

Các trường hợp thử nghiệm

[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]]

Ghi chú

  1. Sơ hở tiêu chuẩn bị cấm.
  2. Đây là ; câu trả lời ngắn nhất (tính bằng byte) thắng.

2
Là vòng cổ tròn?
Dennis

1
@Dennis Không, vòng cổ là tuyến tính.
ngenisis

1
Chúng ta có thể lấy đầu vào là chữ cái / mã thông báo chỉ ra các loại trang sức khác nhau, thay vì số nguyên không?
Greg Martin

3
Nếu thứ tự của các phân đoạn không thay đổi, các phần xen kẽ giữa phần A và phần B. Như vậy, bao gồm thông tin trong đầu ra là không cần thiết. Chúng ta có thể bỏ qua dấu hiệu theif nếu câu trả lời không thay đổi thứ tự của đồ trang sức không? Bạn có một số trường hợp thử nghiệm?
Luke

2
Ví dụ của bạn [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], có vẻ như đầu ra phải như vậy [[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]], vì nó có ít vết cắt hơn [[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]]. Tôi có hiểu đúng thông số kỹ thuật không?
Greg Martin

Câu trả lời:


3

Brachylog , 13 byte

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

Hãy thử trực tuyến!

Lưu ý: metapredicate mới hơn thử thách này.

Giải trình

~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.

Các phân vùng được liệt kê theo thứ tự tăng dần về số lượng các khối, do đó kết quả sẽ có càng ít khối càng tốt.


3

Thạch , 18 byte

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

Hãy thử trực tuyến!

Không hiệu quả - ví dụ có 28 trang sức sẽ không hoạt động nếu không có tài nguyên lớn vì bước đầu tiên của việc triển khai này là xây dựng danh sách 2 27 phân vùng có thể.

Trả về một danh sách các danh sách - các phân đoạn để sắp xếp chúng giữa các tên trộm thay thế. (Re đầu ra TIO: khi một danh sách chỉ có một mục duy nhất, bản in ngầm không làm phiền với dấu ngoặc, [])

Làm sao?

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

Toán học, 118 byte

Gần như đánh bại Jelly ... chỉ 1 lần;)

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

Hàm thuần túy lấy ba đối số: vòng cổ, như một danh sách các mã thông báo như {A, A, A, A, B, C, D, B, C, D, B, B}; chiều dài của vòng cổ; và số lần ngọc khác biệt. Nó trả về một danh sách các danh sách con trong biểu mẫu {{A, A}, {-A, -A, -B, -C, -D, -B}, {C, D, B, B}}, trong đó các mã thông báo không có dấu hiệu tiêu cực sẽ chuyển đến một tên trộm và các mã thông báo có dấu hiệu tiêu cực sẽ chuyển đến tên trộm kia. (Mặc dù đây là thông tin dư thừa, thuật toán dẫn đến biểu diễn này và loại bỏ các dấu hiệu tiêu cực sẽ tốn vài byte.)

Đầu tiên chúng ta phải thực hiện một chức năng lấy một danh sách và một tập hợp các vị trí ncắt và trả về danh sách các n+1danh sách con thu được bằng cách cắt danh sách đầu vào tại các nvị trí cắt đó ; toán tử infix nhị phân ±được sử dụng cho mục đích này và được định nghĩa đệ quy thông qua l_±c_:=Append[-#±Most@c,#2]&@@l~TakeDrop~Last@c;l_±{}:={l};. Do dấu hiệu tiêu cực ngay sau đó Append, kết quả là các danh sách con thay thế làm và không có dấu hiệu tiêu cực được gắn vào mỗi mã thông báo.

Sau đó, chúng tôi tạo ra tất cả các bộ vị trí cắt có thể có chiều dài nhiều nhất là số loại trang sức, sử dụng Range@#2~Subsets~#3và sử dụng i=#;(i±#)&/@để áp dụng ±toán tử (với danh sách đồ trang sức đầu vào) lần lượt cho từng bộ vị trí cắt này.

Cuối cùng, SelectFirst[...,Tr[Tr/@#]==0&]&chọn ra sự phân chia vòng cổ đầu tiên là công bằng. Nó làm như vậy bằng cách thêm vào tất cả các yếu tố trong tất cả các danh sách con theo nghĩa đen; Mathematica đủ khôn ngoan để hủy các bản sao tích cực và tiêu cực của mỗi mã thông báo theo cách rõ ràng.


3

Bình thường, 16 byte

hfqFSMsM.TcT2t./

Dùng thử trực tuyến: Trình diễn hoặc Test Suite

Giải trình:

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 byte

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

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

                # 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]]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.