재정렬 된 하위 집합을 기반으로 마스터 목록 재정렬


19

나는 최근에 두 가지 목록, 즉 마스터 목록과 잠재적으로 다른 순서로 마스터 목록에있는 항목의 하위 집합을 포함하는 작은 목록을 가진 직장에서 해결하는 데 문제가있었습니다. 목록에없는 항목의 순서를 변경하지 않고 가능한 한 항상 동일한 위치에 항목을 유지하지 않고 하위 집합의 항목이 동일한 순서로 표시되도록 마스터 목록을 다시 정렬해야했습니다. 좋아, 아마 혼란 스러울 것 같아, 나는 그것을 분해 할 것이다 :

  • 마스터리스트는 기본 품목 순서를 정의합니다.
  • 하위 집합 목록은 특정 항목의 상대 순서를 정의합니다.
  • 마스터리스트가 서브 세트리스트에 따라 순서가 다른 두 가지 요소를 갖는 경우, 마스터리스트의 이전 항목은 서브 세트리스트 내의 다른 항목과 비교하여 올바른 위치에있는 가장 빠른 색인으로 이동되어야합니다. (즉, 후자의 항목 바로 뒤에)

당신의 임무는이 재정렬 알고리즘을 구현하는 것입니다.

테스트 사례 예

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]

규칙

  • 표준 허점, yadda yadda, 편리한 I / O, blah blah.
  • 예제에서 숫자와 문자열을 사용하더라도 정수, 문자열 또는 언어에서 편리한 경우 이기종 목록을 포함하여 등식 시맨틱이 정의 된 요소이든 하나의 요소 유형 만 지원하면됩니다.
  • 마스터리스트와 서브 세트리스트에 중복이 없다고 가정 할 수 있습니다
  • 서브 세트 목록에있는 모든 항목이 마스터 목록에 있다고 가정 할 수 있습니다.
  • 목록이 비어있을 수 있습니다
  • 최소한 최대 100 개의 요소 길이의 배열을 지원해야합니다.
  • 재정렬은 제자리에서 또는 새로운 목록 / 배열을 통해 구현 될 수 있습니다.

행복한 골프!


1
좋고 비프는 문제.
요나

8 1 3 4 5 6 7 2 9 12 11 10마지막에서 두 번째 하나에 유효한 해결책은?
Ven

@Ven 아니요. 하위 집합 항목을 동일한 상대 순서로 유지 해야하는 제약 조건에 부합하더라도 정답이 하나만 있는지 확인하고 싶기 때문에 이전 순서가 잘못된 항목은 다음 항목으로 이동해야합니다. 나중에 고장난 품목.
Beefster

정답이 둘 이상인 것이 왜 중요합니까? 도전 규칙에 제약을 추가하십시오.
Ven

답변:


4

레티 나 0.8.2 , 51 바이트

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

온라인으로 사용해보십시오! 첫 번째 줄에는 쉼표로 구분 된 하위 단어 목록을, 두 번째 줄에는 쉼표로 구분 된 단어의 마스터 목록으로 입력을받습니다. 설명:

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

마스터 목록에서 두 번째 단어가 첫 번째 단어보다 앞에 나오는 두 개의 인접한 하위 단어를 찾으십시오.

$1$4,$3

마스터 목록에서 첫 번째 단어 다음에 나타날 두 번째 단어를 이동하십시오.

+`

순서가 잘못된 단어가 표시되지 않을 때까지 반복하십시오.

1A`

하위 단어를 삭제하십시오.


4

자바 스크립트 (ES6),  96 89 74  71 바이트

이것은 부피가 큰 혼란으로 시작되어 결국 간결하고 우아한 형태로 축소되었습니다. .splice () 메소드가 그에 대한 유익한 협업에 감사드립니다 . ;)

로 입력을 (master)(subset)받습니다. 마스터 목록을 업데이트하여 출력합니다.

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

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

어떻게?

ip

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

1

  • i[element]
  • 스프레드 구문 덕분 에이 요소는 외부 .splice () 의 세 번째 인수로 확장되어 위치 다시 삽입됩니다.p

0

  • 내부 .splice () 는 아무것도 제거하지 않고 빈 배열을 반환합니다.
  • 결과적으로 외부 .splice () 는 세 번째 인수로 undefined 를 받고 아무것도 삽입되지 않습니다.

댓글

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
" .splice () 메서드에 감사드립니다 ." Cue PPCG Oscar 's Music ... :)
Chas Brown

보다 정확하게는 외부 스플 라이스 호출이 각각 3 개 또는 2 개의 인수를 수신하여 올바른 작업을 수행합니다.
Neil

2

하스켈, 79 바이트

(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

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

(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

루비 , 73 68 바이트

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

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

어떻게?

  • 사이의 교차점 ab의 모든 요소를 포함 b하지만, 같은 순서로 우리는 그들을 찾을 것 같이a
  • 따라서 b교차점과 교차점을 병렬로 반복 하면 차이를 발견하자마자 단일 요소를 재배치 할 수 있습니다.
  • 재배치는 a에서 찾은 요소의 위치를 잘라낸 b다음 교차점에서 찾은 요소를 제거한 다음 나머지를 추가하여 수행됩니다.
  • 모든 요소가 b올바른 순서로 정렬 될 때까지 처음부터 반복a

0은 무엇을하고 0while있습니까?
요나

그것은 단지 NOP입니다.
GB

왜 필요한가요?
요나

1
비교 및 조작은 단일 블록에서 수행되므로 루프를 시작하기 전에 변수를 선언하지 마십시오. "작업이 true를 반환하는 동안 아무 것도하지 마십시오"라는 의미입니다. 코드는 "결과가 true 인 경우 작업을 수행합니다"
GB


1

펄 6 , 40 바이트

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

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

입력이 카레를받는 익명 코드 블록 (과 같은 f(subList)(masterList))과 하위 목록의 요소가 올바른 순서로있는 마스터 목록의 색인에 대한 첫 번째 사전 순열을 찾습니다.

직관적으로 첫 번째 만족 순열은 올바른 순서로 정렬 된 요소를 원래 순서대로 유지하고, 잘못 배치 된 요소를 올바른 순서로 정렬하기 위해 필요한 최소 거리만큼 앞으로 이동하여 하위 요소의 이전 요소 바로 뒤에 배치합니다.

설명:

{*                                     } # 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

젤리 , 9 바이트

Œ!iⱮṢƑ¥ƇḢ

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

특히 마스터 목록이 큰 경우 비효율적입니다. 가능한 모든 순열을 생성하고 부분 집합의 순서가 잘못된 순열을 필터링 한 다음 첫 번째를 반환합니다.

설명

Œ!        | 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

규칙에 따르지 않는 것 같습니다. "마스터 목록에 하위 목록에 따라 두 가지 요소가 순서가 다른 경우 마스터 목록의 이전 항목 은 가장 오래된 색인 으로 이동 해야합니다 . 부분 집합리스트 내의 다른 항목들에 대한 정확한 위치. (즉, 이후의 항목 직후) "
Beefster

@Beefster 그것은 지금까지 시도한 것들에서 작동합니다. 순열의 순서는 이것이 올바른 결과라고 생각합니다. 반례가 있다면 잘못되었다는 것이 행복합니다.
Nick Kennedy

@Beefster 나는 이제 여자 이름과 1..12를 제외한 모든 예제를 시도했으며 결과의 순서는 정확합니다.
Nick Kennedy

2
@Beefster 내 대답 은 왜 이것이 작동하는지에 대한 부분 설명이 있습니다
Jo King

1

J , 49 바이트

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

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

설명

우리는 하위 집합을 왼쪽 인수로, 전체 입력을 오른쪽으로 취합니다.

명확성을 위해 특정 예제를 사용하여 코드를 살펴 보겠습니다.

5 2 4 f 1 2 3 4 5

부분 집합의 크기가 2 인 박스형 접두사를 가져옵니다.

2 <\ [

생산 :

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

원래 입력에 추가하고 모든 것을 뒤집습니다.

] |.@;

우리는 얻는다 :

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

위의 문제를 해결하는 것은 오른쪽에서 왼쪽으로 축소됩니다. 우리 /는 항목들 사이 에 삽입하기 위해 올바른 동사 만 찾으면 됩니다.

축소의 각 반복은 가장 오른쪽 상자 (우리가 변환하는 전체 입력)를 업데이트하므로 왼쪽에 쌍으로 표시되는 순서 제약 조건을 준수합니다. 축소가 완료되면 입력은 전체 하위 세트 순서를 따릅니다.

쌍의 순서가 입력의 순서와 동일하면 다음은 0으로 평가되며 아무것도하지 않습니다.

^:(>/@i.~)

그렇지 않으면 1로 평가되고 왼쪽에 동사를 적용합니다. ^:

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

왼쪽 항목을 오른쪽 항목의 오른쪽으로 이동합니다. 이 운동은 단순히 문제의 두 요소 사이에 (그리고 포함하는) 모든 항목 의 순환 순열 입니다.

J는 이러한 순환 순열을 적용 할 기본 요소를 가지고 있습니다.

<cyclic permutation definition> C. ]

동사의 나머지 부분은 우리가 순환 해야하는 색인을 선택하는 것 외에는 아무것도하지 않습니다.

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

그 길이보다 길어 보이지만 그 문구를 더 이상 골프화 할 수 없었습니다.

마지막으로 결과를 수정 <@하고 완료했습니다.


0

젤리 , 24 바이트

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

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

설명

서브 세트를 왼쪽 및 마스터 목록으로 사용하고 오른쪽 인수로 사용하는 2 진 링크. 아래 예제는 9001, 42, 69, 1337, 420, 99, 255를 마스터로 사용하고 69, 9001, 1337을 서브 세트로 사용합니다.

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 # (Visual C # 대화식 컴파일러) , 118 바이트

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

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

System.Collections.Generic네임 스페이스의 일부 클래스 활용 마스터는 a List<T>이고 서브 세트는입니다 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);
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.