역 순열 인덱스


17

소개

n 개의 요소 를 가진리스트의 사전 식 순열은 0에서 n 까지 번호가 매겨 질 수 있습니다 ! -1. 예를 들어, 3! = 6 순열 (1,2,3)(1,2,3), (1,3,2), (2,1,3), (2,3,1), (3,1,2), (3,2,1).

순열이 목록에 적용되면 해당 요소는 순열의 숫자와 동일한 순서로 정렬됩니다. 예를 들어 순열 (2,3,1)l = (a,b,c)yields에 적용합니다 (l[2],l[3],l[1]) = (b,c,a).

순열의 역수는이 연산을 반대로하는 순열로 정의됩니다. 즉 순열을 적용한 다음 그 반대의 경우 (또는 그 반대) 배열을 수정하지 않습니다. 예를 들면, 역 (2,3,1)IS (3,1,2)에 그 적용하기 때문에, (b,c,a)수율 (a,b,c).

또한 순열 자체에 적용된 순열의 역수는 정수 1… n을 산출합니다 . 예를 들어 yield에 적용 (3,1,2)합니다 .(2,3,1)(1,2,3)

이제 함수 revind ( x )를 인덱스 x를 사용한 순열의 역 순열의 인덱스로 정의합니다 . ( 관심 이 있으시면 A056019 입니다.)

인덱스 i를 사용한 순열 은리스트 iff 0 ≤ i < k ! 의 마지막 k 항목 만 수정하므로 revind ( i )에 영향을주지 않으면 서 목록의 시작 부분에 여러 요소를 추가 할 수 있습니다 . 따라서 목록의 길이는 결과에 영향을 미치지 않습니다.

도전

당신의 임무는 재생 ( x ) 을 구현하는 입니다. 음이 아닌 단일 정수 x 를 입력 / 인수로 사용하고 결과를 단일의 음이 아닌 정수로 출력 / 반환 하는 전체 프로그램 또는 함수를 작성합니다 .

입력과 출력은 0- 인덱싱 또는 1- 인덱싱 될 수 있지만, 이것은 서로 일치해야합니다.

인덱스별로 순열을 생성하거나 순열 인덱스를 반환하거나 역 순열이 금지 된 것을 찾는 기본 제공 (모든 순열 또는 다음 순열을 생성하는 내장이 허용됩니다.)

표준 규칙이 적용됩니다.

아래 예제는 0 인덱스입니다.

Input    Output
0        0
1        1
2        2
3        4
4        3
5        5
6        6
13       10
42       51
100      41
1000     3628
2000     3974
10000    30593
100000   303016

참조 구현 (Python 3)

def revind(n):
    from math import factorial
    from itertools import permutations, count
    l = next(filter(lambda x: factorial(x) > n, count(1)))
    pms = list(permutations(range(l)))
    return [k for k in range(len(pms)) if tuple(pms[n][i] for i in pms[k]) == pms[0]][0]


1
이 도전을 이해하기 위해 역 순열의 정의를 찾아야했습니다. 나는 당신의 모범이 (a,b,c)매우 불분명하다고 생각합니다. 역 순열이 무엇인지에 대한 적절한 설명을 포함하십시오.
Fatalize

@ Fatalize 이것은 간단히 설명하기가 다소 어렵습니다. 더 나은 지금?
PurkkaKoodari

젤리는 배열의 인덱스를 해당 값으로 정렬 하는 원자 (그레이드 업)를 가지고 있습니다. 이것은 1,…, n 의 순열 반전시키는 것이지만 다른 순열에서는 작동하지 않습니다. 되어 A를 내장 금지 된?
Dennis

@ 데니스 하드 질문. 기술적으로 엄격하게 증가하는 목록에 적용된 순열의 역수를 찾습니다. 그러므로 나는 허용되지 않는다고 말할 것입니다. (누군가 동의하지 않으면 의견을 말하십시오. 커뮤니티가 원하면 변경할 수 있습니다.)
PurkkaKoodari

답변:


5

젤리 , 6 바이트

ịŒ!⁺iR

I / O는 1 기반 인덱싱을 사용합니다. 매우 느리고 메모리가 부족합니다.

확인

입력이 8을 초과하지 않는 한 ! = 40320 이면 배열 [1,…, 8] 의 모든 순열을 고려하면 충분합니다 . 마지막 테스트 사례의 경우 [1,…, 9] 의 순열 만으로 충분합니다.

처음 8 또는 9 양의 정수 의 순열만을 고려한 약간 수정 된 코드를 사용하면 온라인으로 시도 할 수 있습니다! 또는 나머지 모든 테스트 사례를 확인하십시오 .

작동 원리

ịŒ!⁺iR  Main link. Argument: n

 Œ!     Yield all permutations of [1, ..., n].
ị       At-index; retrieve the n-th permutation.
   ⁺    Duplicate the Œ! atom, generating all permutations of the n-th permutation.
     R  Range; yield [1, ..., n].
    i   Index; find the index of [1, ..., n] in the generated 2D array.

대체 접근 방식, 6 바이트 (유효하지 않음)

Œ!Ụ€Ụi

그것은 길고 금지 된 등급의 up atom 을 사용하지만, 더 관용적입니다.

8 (또는 마지막 테스트 케이스의 경우 9) 을 앞에두면 실제로 온라인으로 시도 할 수 있습니다!

작동 원리

Œ!Ụ€Ụi  Main link. Argument: n

Œ!      Yield all permutations of [1, ..., n].
  Ụ€    Grade up each; sort the indices of each permutation by the corresponding
        values. For a permutation of [1, ..., n], this inverts the permutation.
    Ụ   Grade up; sort [1, ..., n!] by the corresponding inverted permutations
        (lexicographical order).
     i  Index; yield the 1-based index of n, which corresponds to the inverse of
        the n-th permutation.

6

Mathematica, 74 바이트

Max@k[i,Flatten@Outer[i=Permutations[j=Range@#];k=Position,{i[[#]]},j,1]]&

1- 인덱싱을 사용합니다. 매우 비효율적입니다. (입력이 ~ 11GB 인 경우 사용 11)

설명

j=Range@#

1에서 N까지의 목록을 생성하십시오.에 저장하십시오 j.

i=Permutations[...]

의 모든 순열을 구합니다 j. 에 저장하십시오 i.

k=Position

Position기능을 저장하십시오 k. ( Position다시 사용할 때 바이트 수를 줄이기 위해 )

Flatten@Outer[...,{i[[#]]},j,1]

N 번째 순열의 역 순열을 구합니다.

Max@k[i,...]

(모든 순열) 에서 역 순열 의 k( Position)를 i구합니다.

내장 사용, 46 43 바이트

a[(a=Ordering)/@Permutations@Range@#][[#]]&

1- 색인.


2
"역 순열을 발견 한 내장은 금지되어 있습니다"
Greg Martin

@GregMartin, 아, 어떻게 든 그 부분을 놓 쳤고 "순열의 색인을 반환"부분 만 보았습니다. 바보 야 ... 새 코드에는 그 문제가 없습니다.
JungHwan Min

네, 놓치기 쉽다는 데 동의합니다. 74 바이트 — 여전히 인상적입니다!
그렉 마틴

5

MATL , 15 바이트

:Y@tGY)Z)G:=!Af

입력 및 출력은 1 기반입니다.

@MartinEnder의 CJam answer 와 유사 하지만 가능한 모든 순열을 입력에 의해 지정된 순열로 구성하고 어느 것이 신분 순열인지 확인하여 역 순열을 찾습니다.

온라인 컴파일러의 입력 메모리가 부족합니다 10.

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

설명

:      % Implicitly input N. Push range [1 2 ... N]
Y@     % Matrix witll all permutations of size N. Each permutation is a row
tGY)   % Duplicate. Get the N-th row
Z)     % Use that as a column index into the matrix of all permutations
G:=    % Compare each row with [1 2 ... N]
!Af    % Find index of the row that matches. Implicitly display

5

Pyth, 12 바이트

xJ.phQxL@JQh

테스트 스위트

인덱스가 0입니다.

설명:

xJ.phQxL@JQh
xJ.phQxL@JQhQ    Implicit variable introduction
                 Q = eval(input())
  .phQ           Form all permutations of range(Q+1), namely [0, 1, .. Q]
 J               Save to J.
        @JQ      Take the Qth element of J.
      xL   hQ    Map all elements of [0, 1, ..., Q] to their index in above
x                Find the index in J of the above.

5

05AB1E , 14 13 바이트

매우 메모리 비효율적입니다. 이제 더 많은 메모리 비효율적이지만 1 바이트 더 짧습니다.
0부터 시작합니다. CP-1252 인코딩을
사용합니다 .

ƒ¹ÝœD¹èNkˆ}¯k

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

설명

ƒ               # for N in range[0 .. x]
 ¹ÝœD           # generate 2 copies of all permutations of range[0 .. x]
     ¹è         # get permutation at index x
       Nkˆ      # store index of N in that permutation in global list
         }      # end loop
          ¯k    # get index of global list (inverse) in list of permutations

4

CJam , 16 바이트

ri_)e!_@=_$\f#a#

인덱스는 0부터 시작합니다.

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

나는 이것보다 훨씬 비효율적이지 않습니다 ... 입력보다 큰 Java의 기본 설정으로 메모리가 부족합니다 8(그러나 원칙적으로 충분한 수의 시간과 메모리가 주어진 임의의 입력에 대해서는 작동합니다).

설명

ri    e# Read input and convert to integer N.
_)e!  e# Duplicate N, get all permutations of [0 1 ... N].
_@=   e# Duplicate permutations, get the Nth permutation.
_$    e# Duplicate and sort to get the sorted range [0 1 ... N].
\f#   e# For each of these values, get its index in the Nth permutation.
      e# This inverts the permutation.
a#    e# Find the index of this new permutation in the list of all permutations.

3

간격 , 108 바이트

h:=l->n->PositionProperty(l,p->l[n]*p=());
f:=n->h(Set(SymmetricGroup(First([1..n],k->Factorial(k)>=n))))(n);

1- 색인. 줄 바꿈은 계산되지 않으며 필요하지 않습니다. 실제로 최종 기능을 이름에 할당 할 필요는 없지만 ...

h순열 목록과 해당 목록에 대한 색인을 가져와 역 순열의 색인을 반환하는 카레 함수입니다. 제한없이, 나는 단지 할 것 Position(l,l[n]^-1)입니다. f충분히 큰 대칭 그룹과 주어진 정렬 된 순열을 사용하여 함수를 호출합니다 n.

방금 쓸 SymmetricGroup(n)수 있고 최대 9까지의 값에 대해 함수를 계산할 수 있습니다. 이미 훨씬 작은 솔루션이 있으므로이 작업을 수행하는 것이 좋습니다.

gap> f(100001);
303017

99 미만의 인수에 작동하는 정말 효율적인 0 인덱스 솔루션! (1 바이트의 비용으로 999 이하의 인수에 대해 작동하도록 만들 수 있습니다)는 다음과 같습니다.

f:=function(n)
 local m,l,p,i,g;
 m:=First([1..99],k->Factorial(k)>n);
 g:=List([m-1,m-2..0],Factorial);
 l:=[1..m];
 p:=[];
 for i in g do
  Add(p,Remove(l,QuoInt(n,i)+1));
  n:=n mod i;
 od;
 return Sum(ListN(List([1..m],i->Number([1..Position(p,i)],j->p[j]>i)),g,\*));
end;

공백을 삭제하면 255 바이트가됩니다.


잘 했어! 나는 효율적인 솔루션을 원했습니다.
PurkkaKoodari

3

자바 스크립트 (ES6) 163 120 110 바이트

f=(n,a=[],i=0,r=0,[j,...b]=a)=>n?a.splice(n%-~i,0,i)|f(n/++i|0,a,i):i?f(n,b,i-1,b.reduce((r,k)=>r+=k>j,r*i)):r
<input type=number min=0 oninput=o.textContent=f(+this.value)><pre id=o>

인덱스가 0입니다. 인덱스를 순열로 변환하고 반전시킨 다음 다시 인덱스로 변환하여 작동합니다. 편집 : f순열 을 반전하고 역순으로 바꾸고 g반전 순열을 다시 색인으로 변환하여 약 25 %를 절약했습니다 . 두 개의 재귀 호출을 단일 함수로 결합하여 추가로 10 바이트를 절약했습니다. 언 골프 드 :

function index(n) {
    var a = [0];
    for (var i = 1; n = Math.floor(n / i); i++) {
        var j = i - n % (i + 1);
        for (var k = 0; k < i; k++) {
            if (a[k] > j) a[k]++;
        }
        a.push(j);
    }
    a = [...a.keys()].map(k => a.indexOf(k));
    while (i) {
        n *= i--;
        j = a.pop();
        for (k = 0; k < i; k++) {
            if (a[k] > j) n++;
        }
    }
    return n;
}

1
@JonathanAllan 죄송합니다. 마지막 2 바이트 저장을 발견했다고 생각했지만 철저히 테스트하지 못했습니다. 이전 버전으로 되돌 렸습니다.
Neil

지금 매우 사악한 구현.
Jonathan Allan

1
@JonathanAllan 내가 f대신 순열을 뒤집어 놓으면 더 wish 한 것으로 밝혀졌습니다 g.
Neil

3

J, 55 50 바이트

g=:/:~i.@#
[:(#\.#.+/@(<{.)\.)@g(-i.)@>:g@g@,/@#:]

순열 지수 에 관한 J 에세이에 근거 .

이 코드는 순서대로 메모리 만 필요 n하지만 목록 n시간을 정렬하고 n각 인덱스에 대해 시간을 검색하므로 시간이 더 걸립니다 .

/:목록의 등급과 순열의 역수를 찾을 수 있는 내장 을 사용하면 더 효율적인 42 바이트 솔루션이 있습니다.

[:(#\.#.+/@(<{.)\.)@/:(-i.)@>:/:@/:@,/@#:]

이 버전은 105 초가 소요되는 다른 테스트와 비교할 때 마지막 테스트 사례를 계산하는 데 44 초만 소요됩니다.

용법

   g =: /:~i.@#
   f =: [:(#\.#.+/@(<{.)\.)@g(-i.)@>:g@g@,/@#:]
   (,.f"0) 0 1 2 3 4 5 6 13 42 100 1000 2000 10000
    0     0
    1     1
    2     2
    3     4
    4     3
    5     5
    6     6
   13    10
   42    51
  100    41
 1000  3628
 2000  3974
10000 30593
   timex 'r =: f 100000'
105.787
   r
303016

골프 언어가 만질 수없는 메모리 효율성을 위해 +1.
매직 문어 Urn

2

젤리 , 14 13 9 바이트

-4 (그는 더 빠른를 사용하여 golfed @Dennis 덕분 바이트 그의 대답을 )

Œ!ịịŒ!$iR

또 다른 매우 느린 구현.
여기에 1 기반 인덱싱이 사용되었으므로 예상되는 결과는 다음과 같습니다.

input:  1 2 3 4 5 6 7 8  9 10 11
output: 1 2 3 5 4 6 7 8 13 19  9

TIO가의 입력에서 죽이기 때문에 온라인 IDE 링크를 설정해도 아무런 의미가 없습니다 10. 지역 결과 (마지막 속도가 매우 느리고 메모리 톤이 필요합니다!) :

C:\Jelly\jelly-master>python jelly -fu D:\jelly_scripts\revPerm.txt 1
1
C:\Jelly\jelly-master>python jelly -fu D:\jelly_scripts\revPerm.txt 2
2
C:\Jelly\jelly-master>python jelly -fu D:\jelly_scripts\revPerm.txt 3
3
C:\Jelly\jelly-master>python jelly -fu D:\jelly_scripts\revPerm.txt 4
5
C:\Jelly\jelly-master>python jelly -fu D:\jelly_scripts\revPerm.txt 5
4
C:\Jelly\jelly-master>python jelly -fu D:\jelly_scripts\revPerm.txt 6
6
C:\Jelly\jelly-master>python jelly -fu D:\jelly_scripts\revPerm.txt 7
7
C:\Jelly\jelly-master>python jelly -fu D:\jelly_scripts\revPerm.txt 8
8
C:\Jelly\jelly-master>python jelly -fu D:\jelly_scripts\revPerm.txt 9
13
C:\Jelly\jelly-master>python jelly -fu D:\jelly_scripts\revPerm.txt 10
19
C:\Jelly\jelly-master>python jelly -fu D:\jelly_scripts\revPerm.txt 11
9

어떻게?

Œ!ịịŒ!$iR - Main link 1: n
      $   - last two links as a monad
    Œ!    -     permutations of implicit range [1,2,3,...,n]
   ị      -     value at index n (the nth permutation)
Œ!        - permutations of implicit range [1,2,3,...,n]
  ị       - value at index (the indexes of the permuted values in the nth permutation)
       i  - index of
        R - range [1,2,3,...,n]

참고 : 순열을 찾는 데 동일한 순서를 사용하므로 순열을 정렬 할 필요가 없습니다.


내 휴대 전화에서 테스트 할 수는 없지만 링크 2를 제거하고 주 전화 번호를 만들 수 ÇịịÇ$iR없습니까?
Dennis

실제로 R이전 Œ!은 암시 적이므로 Œ!ịịŒ!$iR작업을 수행해야합니다.
Dennis

예, 이것은 친구를 만나기 전에 매우 서두른 입장이었습니다.
Jonathan Allan

2

파이썬 2, 116114 바이트

from itertools import*
def f(n):r=range(n+1);l=list(permutations(r));print l.index(tuple(l[n].index(v)for v in r))

반복

0부터 시작합니다. 느리고 메모리가 부족하지만 바이트는 짧습니다.


순열 함수를 사용하지 않습니다. 메모리와 시간 효율적. 289 285 바이트

@Christian Sievers 덕분에 -4 바이트 (완전한 순열이 이미 형성됨)

h=lambda n,v=1,x=1:v and(n>=v and h(n,v*x,x+1)or(v,x-1))or n and h(n-1,0,n*x)or x
i=lambda p,j=0,r=0:j<len(p)and i(p,j+1,r+sum(k<p[j]for k in p[j+1:])*h(len(p)-j-1,0))or r
def f(n):t,x=h(n);g=range(x);o=g[:];r=[];exec"t/=x;x-=1;r+=[o.pop(n/t)];n%=t;"*x;return i([r.index(v)for v in g])

코드 골프라는 것을 알고 있지만 @ Pietu1998은 효율적인 구현에도 관심이 있다고 생각합니다.

에서 실제로 확인하십시오 repl.it 실제로보기

이것은 다음을 비교하는 참조 구현보다 많은 바이트를 사용합니다 n=5000000.

ref:    6GB 148s  
this: 200KB <1ms

f 역 인덱스 기능입니다.

f먼저 위의 다음 요인을 얻는다 n,t 그 계승 정수가, 그리고 즉, x호출에 의해 h(n), 그리고 세트 g=range(x), 순열을 만들 것입니다 항목 o=g[:]및 순열 홀더,r=[]

이 인덱스의 순열을 구성 옆 n으로 pop의 계승 기본 표현의 인덱스를 보내고 n항목에서 차례로 o, 그리고 그들을 추가 r. 계승 기본 표현은 DIV에 의해 발견의의 MOD ntt으로 div'd됩니다 xx아래로 감소 1.

마지막으로 호출하여 역 순열의 인덱스를 발견 i반대 순열과,[r.index(v)for v in g]

h 음수가 아닌 정수의 계승을 계산하거나 음이 아닌 정수 위의 다음 계승과 계승을 만드는 정수를 모두 계산하는 이중 목적 함수입니다.

그것은 기본 상태의에서 v=1그리고 곱하여 후자를 수행 v하여 x(처음도 1) 및 증가 x할 때까지n 적어도 합니다.vx-1 튜플에.

계산하기 위해 n!하나 개의 통화를 h(n,0)하는 배수 x(초기 1)에 의해 n및 감소 n까지 nIS0 때 반환x .

i각 색인의 계승 기준 계승의 곱을 곱하여 p항목 의 순열에 대한 사전 사전 색인을 제공하고 색인 오른쪽의 항목이 해당 색인의 값보다 적은 수를 제공합니다 .[0,1,...n]h(len(p)-j-1,0)sum(k<p[j]for k in p[j+1:])


순열을 구성 할 때 마지막 항목을 특수하게 처리 할 필요가 없다고 생각합니다. 내 255 바이트 GAP 솔루션에 없었습니다.
Christian Sievers

그렇지 않으면 0으로 나누기 오류가 발생하기 때문에 마지막에 별도로 추가합니다 t/=x.
Jonathan Allan

나에게 잠시 툭하면 볼 : 루프가 이미 모든 것을 않습니다, 당신은 대체 할 수 있습니다 (r+o)r.
Christian Sievers

어, 맞아! 정말 고맙습니다.
Jonathan Allan

1

파이썬 2 130 129 바이트

p=lambda x,k,j=1:x[j:]and p(x,k/j,j+1)+[x.pop(k%j)]
n=input();r=range(n+2);k=0
while[p(r*1,n)[i]for i in p(r*1,k)]>r:k+=1
print k

1

실제로 , 18 11 바이트

이 답변은 Dennis 'Jelly 답변 의 알고리즘을 사용 하지만 인덱스는 0입니다. 골프 제안을 환영합니다! 온라인으로 사용해보십시오!

4╞r;)╨E╨♂#í

언 골핑

      Implicit input n.
4╞    Push 4 duplicates of n. Stack: n, n, n, n
r;)   Push the range [0...n], and move a duplicate of that range to BOS for later.
╨E    Push the n-length permutations of [0...n] and get perm_list[n].
        Stack: perm_list[n], n, [0...n]
╨     Push the n-length permutations of perm_list[n].
♂#    Convert every "list" in the zip to an actual list.
        Stack: perm(perm_list[n]), [0...n]
í     Get the index of [0...n] in the list of permutations of perm_list[n].
      Implicit return.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.