Sắp xếp lại danh sách chính dựa trên tập hợp con được sắp xếp lại


19

Gần đây tôi có một vấn đề cần giải quyết trong công việc khi tôi có hai danh sách: danh sách chính và danh sách nhỏ hơn chứa tập hợp con của các mục trong danh sách chính có khả năng theo thứ tự khác. Tôi cần sắp xếp lại danh sách chính theo cách các mục trong tập hợp con sẽ xuất hiện theo cùng một thứ tự mà không thay đổi thứ tự của các mục không tìm thấy trong danh sách và giữ các mục ở cùng một vị trí bất cứ khi nào có thể. Được rồi, điều đó có vẻ khó hiểu, vì vậy tôi sẽ phá vỡ nó:

  • Danh sách chính xác định thứ tự mặc định của các mục.
  • Danh sách tập hợp con xác định thứ tự tương đối của các mục nhất định.
  • Trong danh sách chính có hai phần tử không theo thứ tự theo danh sách tập hợp con, mục được đặt trước trong danh sách chính sẽ được chuyển đến chỉ mục sớm nhất trong đó vị trí chính xác so với các mục khác trong danh sách tập hợp con. (tức là ngay sau mục sau)

Nhiệm vụ của bạn là thực hiện thuật toán sắp xếp lại này.

Ví dụ trường hợp kiểm tra

Master: [1, 2, 3]
Subset: []
Result: [1, 2, 3]

Master: [9001, 42, 69, 1337, 420]
Subset: [69]
Result: [9001, 42, 69, 1337, 420]

Master: [9001, 42, 69, 1337, 420, 99, 255]
Subset: [69, 9001, 1337]
Result: [42, 69, 9001, 1337, 420, 99, 255]

Master: [1, 2, 3, 4, 5]
Subset: [2, 5]
Result: [1, 2, 3, 4, 5]

Master: [apple, banana, carrot, duck, elephant]
Subset: [duck, apple]
Result: [banana, carrot, duck, apple, elephant]

Master: [Alice, Betty, Carol, Debbie, Elaine, Felicia, Georgia, Helen, Ilene, Julia]
Subset: [Betty, Felicia, Carol, Julia]
Result: [Alice, Betty, Debbie, Elaine, Felicia, Carol, Georgia, Helen, Ilene, Julia]

Master: [snake, lizard, frog, werewolf, vulture, dog, human]
Subset: [snake, werewolf, lizard, human, dog]
Result: [snake, frog, werewolf, lizard, vulture, human, dog]

Master: [Pete, Rob, Jeff, Stan, Chris, Doug, Reggie, Paul, Alex]
Subset: [Jeff, Stan, Pete, Paul]
Result: [Rob, Jeff, Stan, Pete, Chris, Doug, Reggie, Paul, Alex]

Master: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Subset: [8, 1, 2, 12, 11, 10]
Result: [3, 4, 5, 6, 7, 8, 1, 2, 9, 12, 11, 10]

Master: [lol, rofl, lmao, roflmao, lqtm, smh, jk, wat]
Subset: [wat, lmao, rofl]
Result: [lol, roflmao, lqtm, smh, jk, wat, lmao, rofl]

Quy tắc

  • Sơ hở tiêu chuẩn, yadda yadda, I / O thuận tiện, blah blah.
  • Mặc dù các ví dụ sử dụng số và chuỗi, bạn chỉ cần hỗ trợ một loại phần tử, cho dù đó là số nguyên, chuỗi hoặc bất kỳ thứ gì khác có ngữ nghĩa đẳng thức được xác định rõ, bao gồm các danh sách không đồng nhất nếu thuận tiện trong ngôn ngữ của bạn.
  • Bạn có thể giả sử cả danh sách chính và danh sách tập hợp con không chứa các mục trùng lặp
  • Bạn có thể cho rằng tất cả các mục được tìm thấy trong danh sách tập hợp con được tìm thấy trong danh sách chính
  • Danh sách có thể trống
  • Tối thiểu, bạn phải hỗ trợ các mảng dài tối đa 100 phần tử.
  • Sắp xếp lại có thể được thực hiện tại chỗ hoặc thông qua việc tạo ra một danh sách / mảng mới.

Chúc bạn chơi golf vui vẻ!


1
Một vấn đề tốt đẹp, khó khăn.
Giô-na

8 1 3 4 5 6 7 2 9 12 11 10một giải pháp hợp lệ cho giải pháp thứ hai đến cuối cùng?
Ven

@Ven Không. Mặc dù phù hợp với các ràng buộc của việc giữ các mục con theo cùng một thứ tự tương đối, tôi muốn đảm bảo chỉ có một câu trả lời đúng, do đó, mục không theo thứ tự trước đó nên được chuyển sang sau mục ngoài đơn đặt hàng sau.
Beefster

Tại sao vấn đề có nhiều hơn một câu trả lời đúng? Vui lòng thêm các ràng buộc cho các quy tắc của thách thức xin vui lòng.
Ven

Câu trả lời:


4

Võng mạc 0.8.2 , 51 byte

+`(\b(\w+),(\w+)\b.*¶.*\b)\3,(.*\b\2\b)
$1$4,$3
1A`

Hãy thử trực tuyến! Đưa đầu vào dưới dạng danh sách từ khóa được phân tách bằng dấu phẩy trên dòng đầu tiên và danh sách từ chính được phân tách bằng dấu phẩy trên dòng thứ hai. Giải trình:

(\b(\w+),(\w+)\b.*¶.*\b)\3,(.*\b\2\b)

Tìm hai từ khóa liền kề trong đó từ thứ hai đứng trước từ đầu tiên trong danh sách chính.

$1$4,$3

Di chuyển từ thứ hai để xuất hiện sau từ đầu tiên trong danh sách chính.

+`

Lặp lại cho đến khi không có từ nào xuất hiện ngoài trật tự.

1A`

Xóa các từ khóa phụ.


4

JavaScript (ES6),  96 89 74  71 byte

Điều này bắt đầu như một mớ hỗn độn cồng kềnh và cuối cùng được thu nhỏ lại thành một hình thức khá súc tích và thanh lịch. Tôi muốn cảm ơn .splice () phương thức vì sự hợp tác hiệu quả của nó trên phương thức đó. ;)

Đưa đầu vào là (master)(subset). Đầu ra bằng cách cập nhật danh sách chính.

m=>s=>s.map(p=x=>m.splice(p,0,...m.splice(i=m.indexOf(x),p>i||!(p=i))))

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

Làm sao?

tôip

m.splice(p, 0, ...m.splice(i, condition))

1

  • tôi[etôiement]
  • p

0

  • .splice () bên trong không xóa gì và trả về một mảng trống
  • kết quả là .splice () bên ngoài nhận được không xác định là đối số thứ 3 của nó và không có gì được chèn vào

Đã bình luận

m => s =>                 // m[] = master list, s[] = subset list
  s.map(                  //
    p =                   // p = position in the master list of the last element from
                          //     the subset list (initialized to a non-numeric value)
    x =>                  // for each element x in the subset list:
    m.splice(             //   insert in the master list:
      p,                  //     at position p
      0,                  //     without removing any element
      ...m.splice(        //     remove from the master list and flatten:
        i = m.indexOf(x), //       i = position of x in the master list
        p > i             //       if p is greater than i, remove x from its current
                          //       position and insert it at position p
        || !(p = i)       //       otherwise, set p to i and don't remove/insert anything
      )                   //     end of inner splice()
    )                     //   end of outer splice()
  )                       // end of map()

1
"Tôi muốn cảm ơn phương pháp .splice () cho ..." Cue PPCG Oscar's Music ... :)
Chas Brown

Chính xác hơn, lệnh gọi mối nối bên ngoài nhận được 3 hoặc 2 đối số tương ứng, điều này làm cho nó thực hiện đúng.
Neil

2

Haskell, 79 byte

(m:n)#u@(s:t)|m==s=m:n#t|all(/=m)u=m:n#u|(x,_:z)<-span(/=s)n=(x++s:m:z)#u
m#_=m

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

(m:n)#u@(s:t)                 -- m: head of master list
                              -- n: tail of master list
                              -- s: head of subset
                              -- t: tail of subset
                              -- u: whole subset
   |m==s                      -- if m==s
        =m:n#t                -- return 'm' and append a recursive call with 'n' and 't'
   |all(/=m)u                 -- if 'm' is not in 'u'
             =m:n#u           -- return 'm' and append a recursive call with 'n' and 'u'
   |                          -- else (note: 's' is element of 'n')
    (x,_:z)<-span(/=s)n       -- split 'n' into a list 'x' before element 's' and
                              -- a list 'z' after element 's' and
       = (x++s:m:z)#u         -- make a recursive call with
                              -- x++s:m:z as the new master list (i.e. 'm' inserted into 'n' after 's') 
                              -- and 'u'
m # _ = m                     -- if either list is emtpy, return the master list

2

Ruby , 73 68 byte

->a,b{0while b.zip(a&b).find{|m,n|m!=n&&a=a[0..a.index(m)]-[n]|a};a}

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

Làm sao?

  • Giao điểm giữa abchứa tất cả các phần tử của b, nhưng theo cùng thứ tự như chúng ta sẽ tìm thấy chúng tronga
  • Vì vậy, nếu chúng ta lặp đi lặp lại trên bvà trên giao lộ song song, ngay khi chúng ta tìm thấy một sự khác biệt, chúng ta có thể di chuyển một yếu tố duy nhất.
  • Việc di dời được thực hiện bằng cách cắt avào vị trí của phần tử mà chúng ta đã tìm thấy b, sau đó loại bỏ phần tử mà chúng ta tìm thấy trong giao lộ, và sau đó thêm phần còn lại của a.
  • Lặp lại từ đầu, cho đến khi tất cả các yếu tố btheo đúng thứ tự tronga

0 đang làm gì 0while?
Giô-na

Nó chỉ là một NOP.
GB

tại sao cần thiết
Giô-na

1
Bởi vì việc so sánh và thao tác được thực hiện trong một khối duy nhất, để tránh khai báo một biến trước khi bắt đầu vòng lặp. Nó có nghĩa là: "không làm gì trong khi hoạt động trả về đúng.", Mã ngắn hơn "thực hiện thao tác trong khi kết quả là đúng"
GB


1

Perl 6 , 40 byte

{*.permutations.first(*.grep(.any)eq$_)}

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

Khối mã ẩn danh lấy đầu vào được xử lý (như f(subList)(masterList)và tìm hoán vị từ vựng đầu tiên của các chỉ mục của danh sách chính trong đó các phần tử từ danh sách phụ theo đúng thứ tự.

Theo trực giác, hoán vị thỏa mãn đầu tiên sẽ để các phần tử được sắp xếp chính xác theo thứ tự ban đầu, trong khi di chuyển các phần tử được đặt không chính xác khoảng cách tối thiểu cần thiết về phía trước để có chúng theo đúng thứ tự, đặt chúng trực tiếp sau phần tử trước trong tập hợp con.

Giải trình:

{*                                     } # Anonymous code block that returns a lambda
  .permutations                          # In all permutations of the master list
               .first(                )  # Find the first permutation
                     (*.grep(.any)       # Where the order of the subset
                                  eq$_   # Is the same as the given order


1

Thạch , 9 byte

Œ!iⱮṢƑ¥ƇḢ

Hãy thử trực tuyến! hoặc bộ kiểm tra

Không hiệu quả, đặc biệt với danh sách tổng thể lớn. Tạo tất cả các hoán vị có thể, lọc ra những nơi mà tập hợp con sai thứ tự và sau đó trả về cái đầu tiên.

Giải trình

Œ!        | Generate all permutations of the master list
      ¥Ƈ  | Filter including only those where...
  iⱮ      |   the index of each sublist item in this permutation...
     Ƒ    |   is...
    Ṣ     |   in order. 
        Ḣ | Finally take the first item

Điều này có vẻ như nó sẽ phù hợp với các quy tắc "ở đâu trong danh sách tổng thể có hai yếu tố ra khỏi trật tự theo danh mục nhóm, mặt hàng đó là trước đó trong danh sách tổng thể nên được chuyển đến chỉ số sớm nhất , nơi nó đang ở trong vị trí chính xác liên quan đến các mục khác trong danh sách tập hợp con. (tức là ngay sau mục sau) "
Beefster

@Beefster nó hoạt động trên những cái tôi đã thử cho đến nay. Tôi nghĩ rằng thứ tự của hoán vị là như vậy đây là kết quả chính xác. Hạnh phúc khi được chứng minh là sai nếu có một ví dụ.
Nick Kennedy

@Beefster Bây giờ tôi đã thử tất cả các ví dụ của bạn ngoại trừ tên nữ và 1..12 và thứ tự kết quả là chính xác.
Nick Kennedy

2
@Beefster Câu trả lời của tôi có một phần giải thích cho lý do tại sao điều này hoạt động
Jo King

1

J , 49 byte

[:(<@({:+i.@>:@-/)@i.~C.])^:(>/@i.~)&.>/]|.@;2<\[

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

giải trình

Chúng ta lấy tập hợp con làm đối số bên trái và đầu vào đầy đủ làm bên phải.

Chúng tôi sẽ làm việc thông qua mã với một ví dụ cụ thể để rõ ràng:

5 2 4 f 1 2 3 4 5

Lấy các phần tử đóng hộp có kích thước hai trong tập hợp con:

2 <\ [

sản xuất:

┌───┬───┐
│5 2│2 4│
└───┴───┘

nối chúng vào đầu vào ban đầu và đảo ngược toàn bộ:

] |.@;

Chúng tôi nhận được:

┌───┬───┬─────────┐
│2 4│5 2│1 2 3 4 5│
└───┴───┴─────────┘

Giải quyết vấn đề trở thành giảm từ phải sang trái ở trên. Chúng ta chỉ cần tìm động từ đúng để chèn /giữa các mục.

Mỗi lần lặp giảm sẽ cập nhật hộp ngoài cùng bên phải (đầu vào đầy đủ, chúng tôi đang chuyển đổi) để phù hợp với ràng buộc đặt hàng được đại diện bởi cặp bên trái. Khi quá trình giảm kết thúc, đầu vào sẽ tuân theo thứ tự tập hợp con hoàn chỉnh.

Nếu thứ tự của cặp giống như thứ tự trong đầu vào, sau đây sẽ ước tính thành 0 và chúng tôi sẽ không làm gì:

^:(>/@i.~)

Nếu không, nó sẽ đánh giá là 1 và chúng tôi sẽ áp dụng động từ ở bên trái của ^:

   {: + i.@>:@-/)@i.~ C. ]

mà di chuyển mục bên trái sang bên phải của mục bên phải. Chuyển động này chỉ đơn giản là một hoán vị tuần hoàn của tất cả các mục giữa (và bao gồm) hai yếu tố trong câu hỏi.

J có nguyên thủy để áp dụng một hoán vị tuần hoàn như vậy:

<cyclic permutation definition> C. ]

và phần còn lại của động từ không làm gì ngoài việc chọn ra các chỉ mục chúng ta cần xoay vòng:

{: + i.@>:@-/)@i.~

có vẻ dài hơn nó nên, nhưng tôi không thể đánh gôn thêm cụm từ đó.

Cuối cùng chúng tôi rebox kết quả <@và chúng tôi đã hoàn thành.


0

Thạch , 24 byte

i@€MƤFṬœṗƲḊ;JḟF}W€ʋ@¥ṢFị

Hãy thử trực tuyến! hoặc bộ kiểm tra

Giải trình

Một liên kết dyadic lấy tập hợp con làm danh sách bên trái và danh sách chính làm đối số bên phải. Ví dụ dưới đây sử dụng 9001, 42, 69, 1337, 420, 99, 255 làm chủ và 69, 9001, 1337 làm tập hợp con.

i@€                      | Find the index of each subset item in the master list [3, 1, 4]
         Ʋ               | Previous 4 links as a monad
   MƤ                    | Find the index of the maximum for each prefix of this list [1, 1, 3]
     F                   | Flatten (because the previous result are actually each length one lists)
      Ṭ                  | Convert to a boolean list [1,0,1]
       œṗ                | Partition the [3, 1, 4] list before each 1 [[], [3, 1], [4]]
          Ḋ              | Remove the empty first list [[3, 1], [4]]
                    ¥    | Previous two links as a dyad
                  ʋ@     | Previous 4 links as a dyad with reversed arguments
            J            | Sequence along the master list [1, 2, 3, 4, 5, 6, 7]
             ḟF}         | Filter out items in the flattened [3, 1, 4] list
                W€       | Wrap each item as a list [[2], [5], [6], [7]]
           ;             | Concatenate rhis to the [[3, 1], [4]] list
                     Ṣ   | Sort (effectively by first item in each list) [[2], [3, 1], [4], [5], [6], [7]]
                      F  | Flatten
                       ị | Look up in original master list (and implicitly output)

0

C # (Trình biên dịch tương tác Visual C #) , 118 byte

a=>b=>{for(int j;b.Any();)foreach(var e in b.Intersect(a.Take(j=a.IndexOf(b.Dequeue())))){a.Remove(e);a.Insert(j,e);}}

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

Tận dụng một số lớp trong System.Collections.Generickhông gian tên. Bậc thầy là a List<T>và tập hợp con là a Queue<T>.

// a: master
// b: subset
a=>b=>{
  // continue until b is empty
  for(int j;b.Any();)
    // iterate over values that are out of order in a
    // per the head of b using loop variable e
    foreach(var e in
      // the out of order values are determined by
      // intersecting remaining values in b with
      b.Intersect(
        // values in a occurring before the current head of b
        // save the position in a to variable j and remove the head of b
        a.Take(j=a.IndexOf(b.Dequeue()))
      )
    ){
      // push back the out of order element in a
      a.Remove(e);
      a.Insert(j,e);
    }
}
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.