Ters permütasyon endeksi


17

Giriş

N öğeli bir listenin sözlüksel permütasyonları 0'dan n'ye kadar numaralanabilir ! - 1. Örneğin, 3! = 6 permütasyon (1,2,3)olur (1,2,3), (1,3,2), (2,1,3), (2,3,1), (3,1,2), (3,2,1).

Listeye bir permütasyon uygulandığında, elemanları permütasyondaki sayılarla aynı sırada sıralanır. Örneğin, permütasyon uygulanması (2,3,1)için l = (a,b,c)verim (l[2],l[3],l[1]) = (b,c,a).

Bir permütasyonun tersi, bu işlemi tersine çeviren permütasyon olarak tanımlanır, yani bir permütasyon uygulamak ve ardından bunun tersi (veya tersi) diziyi değiştirmez. Örneğin, ters (2,3,1)IS (3,1,2)bu uygulama için, (b,c,a)verim (a,b,c).

Ayrıca, permütasyonun kendisine uygulanan bir permütasyonun tersi 1… n tamsayılarını verir . Örneğin, uygulama (3,1,2)için (2,3,1)verim (1,2,3).

Şimdi fonksiyonu tanımlayabilir revind ( x indeksi ile permütasyon ters permütasyon indeksi olarak) x . ( İlgileniyorsanız bu A056019'dur .)

İ dizinine sahip bir permütasyon, iff 0 ≤ i < k ! Listesindeki sadece son k öğelerini değiştirdiğinden, revind ( i ) 'yi etkilemeden listenin başına istediğiniz sayıda öğe ekleyebiliriz . Bu nedenle listenin uzunluğu sonucu etkilemez.

Meydan okuma

Göreviniz revind ( x ) uygulamaktır . Girdi / bağımsız değişken olarak tek bir negatif olmayan tamsayı x alan ve sonucu tek bir negatif olmayan tamsayı olarak çıkaran / döndüren tam bir program veya işlev yazacaksınız .

Girdi ve çıktı 0 dizinli veya 1 dizinli olabilir, ancak bu ikisi arasında tutarlı olmalıdır.

Dizine göre permütasyon oluşturan, bir permütasyonun indeksini döndüren veya ters permütasyonu bulan yapıdaki yapılar yasaklanmıştır. (Tüm permütasyonları veya bir sonraki permütasyonu üreten yerleşiklere izin verilir.)

Standart kuralları geçerlidir.

Örnekler

Aşağıdaki örnekler 0 dizinlidir.

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

Referans uygulaması (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
Bu zorluğu anlamak için ters permütasyon tanımına bakmalıydım. (a,b,c)Örneğini son derece belirsiz buluyorum . Lütfen ters permütasyonun ne olduğuna dair uygun bir açıklama ekleyin.
16:59, ölümcül

@Fatalize Bunu açıklamak biraz zor. Şimdi daha iyi?
PurkkaKoodari

Jelly, bir dizinin indekslerini karşılık gelen değerlerine göre sıralayan atomu (derece yukarı) içerir. Bu olur bir permütasyon ters 1, ..., n , ancak diğer permütasyon için çalışmaz. Yerleşik bir yasak var mı ?
Dennis

@Dennis Zor soru. Teknik olarak, kesinlikle artan bir listeye uygulandıktan sonra herhangi bir permütasyonun tersini bulur. Bu yüzden izin verilmeyeceğini söyleyeceğim. (Birisi kesinlikle katılmıyorsa, yorum yapmaktan çekinmeyin. Eğer topluluk isterse bunu değiştirebilirim.)
PurkkaKoodari

Yanıtlar:


5

Jöle , 6 bayt

ịŒ!⁺iR

G / Ç 1 tabanlı indeksleme kullanır. Çok yavaş ve hafızaya aç.

Doğrulama

Giriş 8'i geçmediği sürece ! = 40320 , [1,…, 8] dizisinin tüm permütasyonlarını dikkate almak yeterlidir . Son test durumu için [1,…, 9] permütasyonları yeterlidir.

Sadece ilk 8 veya 9 pozitif tamsayının permütasyonlarını dikkate alan biraz değiştirilmiş kodla, çevrimiçi deneyebilirsiniz! veya kalan tüm test senaryolarını doğrulayın .

Nasıl çalışır

ịŒ!⁺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.

Alternatif yaklaşım, 6 bayt (geçersiz)

Œ!Ụ€Ụi

Bu kadar uzun ve yasak dereceli atomu kullanıyor , ancak (tartışmalı olarak) daha deyimsel.

8 (veya son test senaryosu için 9) ekleyerek , gerçekten çevrimiçi deneyebiliriz!

Nasıl çalışır

Œ!Ụ€Ụ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 bayt

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

1 endeksleme kullanır. Çok verimsiz. (giriş olduğunda ~ 11GB bellek kullanır 11)

açıklama

j=Range@#

1'den N'ye kadar bir liste oluşturun j.

i=Permutations[...]

Kullanıcısının tüm permütasyonlarını bul j. Bunu saklayın i.

k=Position

Positionİşlevi içinde saklayın k. ( Positiontekrar kullanırken bayt sayısını azaltmak için )

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

N'inci permütasyonun ters permütasyonunu bulun.

Max@k[i,...]

(Tüm permütasyonlar) içinde ters permütasyonun k( Position) değerini buluni

Yerleşik öğeleri kullanma, 46 43 bayt

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

1 endeksli.


2
"İnşa ... ters permütasyon yasaklandı"
Greg Martin

@GregMartin, ah, bir şekilde bu kısmı kaçırdım ve sadece "bir permütasyonun indeksini döndür" kısmını gördüm. Aptal bana ... Yeni kodun bu sorunu yok.
JungHwan Min

evet, kaçırmanın kolay olduğuna katılıyorum. 74 byte - hala oldukça etkileyici!
Greg Martin

5

MATL , 15 bayt

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

Giriş ve çıkış 1 tabanlıdır.

Benzer MartinEnder en CJam cevap @ fakat girişi ile belirtilen bununla tüm olası permütasyon oluşturarak ters permütasyon bulur ve kimlik permütasyon haline gelmiştir gören.

Giriş için çevrimiçi derleyicide bellek yetersiz 10.

Çevrimiçi deneyin!

açıklama

:      % 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 bayt

xJ.phQxL@JQh

Test odası

0 endekslendi.

Açıklama:

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 bayt

Bellek yetersiz. Şimdi daha fazla bellek yetersizliği (ancak 1 bayt daha kısa).
0 tabanlı aralık. CP-1252 kodlamasını
kullanır .

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

Çevrimiçi deneyin! veya Modifiye test paketi olarak

açıklama

ƒ               # 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 bayt

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

Endeksler 0 tabanlıdır.

Çevrimiçi deneyin!

Bundan daha fazla verim almıyorum ... daha büyük girişler için Java'nın varsayılan ayarları ile bellek bitiyor 8(ancak prensip olarak yeterli sayıda zaman ve bellek evreni verildiğinde rasgele girişler için çalışıyor).

açıklama

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

GAP , 108 bayt

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

1 endeksli. Yeni satırlar sayılmaz, buna gerek yoktur. Son işlevi gerçekten bir isme atamak zorunda değilim, ama ...

hbu listeye bir permütasyon listesi ve bir indeks alan ve ters permütasyon indeksini döndüren curried bir fonksiyondur. Kısıtlama olmadan, sadece yapardım Position(l,l[n]^-1). fbu işlevi yeterince büyük simetrik bir grubun ve verilen verilen sıralı permütasyonlarla çağırır n.

Sadece yazabilirim SymmetricGroup(n), o zaman fonksiyon 9'a kadar olan değerler için hesaplanabilir. Zaten çok daha küçük çözümler olduğundan, bunu yapmayı tercih ederim:

gap> f(100001);
303017

99'un altındaki argümanlar için çalışan gerçekten verimli bir 0-endeksli çözüm! (ve 999'un altındaki argümanlar için bir bayt pahasına çalışmak için yapılabilir) budur:

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;

Boşlukları sildikten sonra 255 bayt var.


İyi iş! Ben de bazı verimli çözümler elde etmeyi umuyordum.
PurkkaKoodari

3

JavaScript (ES6), 163 , 120 110 bayt

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 endeksli. Dizini bir permütasyona dönüştürerek, tersine çevirip bir dizine geri dönüştürerek çalışır. Düzenleme: fpermütasyon ters ve ters yaparak, daha sonra gters permütasyon bir dizine dönüştürmek yaparak yaklaşık% 25 tasarruf . İki özyinelemeli çağrıyı tek bir işlevde birleştirerek 10 bayt daha kaydetti. Ungolfed:

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 Üzgünüm, 9 baytlık son bir saniye kaydettiğimi sanıyordum ama tam olarak test edemedim. Önceki sürüme geri döndüm.
Neil

Şimdi çok swish uygulaması.
Jonathan Allan

1
@JonathanAllan fBunun yerine permütasyonu tersine çevirirsem daha da kötü olur g...
Neil

3

J, 55 50 bayt

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

Permütasyon Endeksi hakkındaki J makalesine dayanmaktadır .

Bu kod yalnızca sıraya göre bellek gerektirir, nancak liste nsürelerini sıraladığı ve nher dizin için süreleri aradığı için daha fazla zaman kullanır .

/:Bir listenin derecesini ve bir permütasyonun tersini bulabilen yerleşkeyi kullanarak , daha verimli olan 42 baytlık bir çözüm vardır.

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

Bu sürüm, 105 saniye gerektiren diğerine kıyasla son test senaryosunu hesaplamak için sadece 44 saniye gerektirir.

kullanım

   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

Golf dillerinin dokunamayacağı bellek verimliliği için +1.
Sihirli Ahtapot Urn

2

Jöle , 14 13 9 bayt

-4 (o daha da kolay kullanım seçenekleri golfed @Dennis sayesinde bayt içinde onun cevabını )

Œ!ịịŒ!$iR

Başka bir çok yavaş uygulama.
Burada 1 tabanlı endeksleme kullanılmıştır, bu nedenle beklenen sonuçlar şunlardır:

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 bir girişte öldürdüğü için çevrimiçi bir IDE bağlantısı kurmanın bir anlamı yok 10. Yerel sonuçlar (sonuncusu çok yavaş ve bir ton bellek gerekiyor!):

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

Nasıl?

Œ!ịịŒ!$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]

Not: permütasyonları, hem permütasyonu bulmak hem de tersi için aynı sıralamayı kullandığımız için sıralamaya gerek yoktur.


Telefonumdan test edemiyorum, ancak bağlantı 2'den kurtulamadı ve ana olanı yapamadı ÇịịÇ$iRmı?
Dennis

Aslında, Rdaha önce Œ!örtük, bu nedenle Œ!ịịŒ!$iRiş yapmak gerekir.
Dennis

Evet, bu arkadaşlarla buluşmadan önce çok aceleci bir girişti.
Jonathan Allan

2

Piton 2, 116 114 bayt

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

repl.it

0 tabanlı. Yavaş ve bellek aç ama bayt üzerinde kısa.


Permütasyon fonksiyonu kullanma; hem bellek hem de zamandan tasarruf sağlar. 289285 bayt

@Christian Sievers sayesinde -4 bayt (tam permütasyon zaten oluştu)

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

Kod golf biliyorum ama @ Pietu1998 de verimli uygulamalar ile ilgileniyor düşünüyorum.

Repl.it'te iş başında görün

Bu, aşağıdakileri karşılaştıran referans uygulamasından daha fazla bayt kullanıyor olsa da n=5000000:

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

f ters indeks fonksiyonudur.

fİlk sonraki faktöryel yukarıda alır n, tkimin faktöryel tamsayı ve olduğunu, xarayarak h(n)ve setleri g=range(x), permütasyon oluşturacak öğeler, o=g[:]ve permütasyon sahibi,r=[]

O endeksinde permütasyonu inşa Sonraki ntarafından popfaktöryel baz temsilinin endeksleri ing nöğelerinden alınan sırayla ove bunları ekleme r. Faktöriyel taban temsili div ve mod nile tnerede tbölünür xve xazalır 1.

Sonunda ters permütasyon endeksini ters permütasyon ile arayarak bulur i,[r.index(v)for v in g]

h , negatif olmayan bir tamsayının faktöriyelini hesaplamak veya negatif olmayan bir tamsayının üstündeki bir sonraki faktöriyi ve bu faktöriyeli yapan tamsayıyı hesaplamak için çift amaçlı bir fonksiyondur.

'S varsayılan durumda v=1ve çarpılarak ikincisi yapar vtarafından x(aynı zamanda başlangıçta 1) ve artan xkadar nbüyük, o zaman döner en azından gibidir vve x-1bir demet içinde.

Hesaplamak için n!bir çağrı h(n,0)katları x(başlangıçta 1) ile nve bir azalır nkadar nolan 0bu geri döndüğünde x.

iher bir endeksin faktöriyel tabanının faktöriyelinin ürünlerini ve endeksin sağındaki kaç öğenin o endeksteki değerden daha azını toplayarak, bir permütasyonun sözlükçü indeksini p, öğelerin [0,1,...n]sözdizimini sağlar .h(len(p)-j-1,0)sum(k<p[j]for k in p[j+1:])


Ben permütasyon inşa ederken son öğe özel durum gerekmez düşünüyorum. 255 bayt GAP çözümümde yoktu.
Christian Sievers

Sonunda ayrı ayrı ekliyorum çünkü aksi takdirde sıfır hata ile bölünür t/=x.
Jonathan Allan

Bana biraz zaman aldı görmek için: döngü zaten hepsini yapıyor, sen yerini alabilir (r+o)tarafından r.
Christian Sievers

Haklısın! Çok teşekkür ederim.
Jonathan Allan

1

Python 2, 130 129 bayt

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

Aslında , 18 11 bayt

Bu cevap, Dennis'in Jelly cevabındaki algoritmayı kullanır, ancak 0 indekslidir. Golf önerileri hoş geldiniz!Çevrimiçi deneyin!

4╞r;)╨E╨♂#í

Ungolfing

      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.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.