Inégalité de réarrangement

10

Contexte

L' inégalité de réarrangement est une inégalité basée sur la réorganisation des nombres. Si j'ai deux listes de nombres de même longueur, x 0 , x 1 , x 2 ... x n-1 et y 0 , y 1 , y 2 ... y n-1 de même longueur, où je suis autorisé à réorganiser les nombres dans la liste, un moyen de maximiser la somme x 0 y 0 + x 1 y 1 + x 2 y 2 + ... + x n-1 y n-1 est de trier les 2 listes dans ordre non décroissant.

Lisez l' article Wikipedia ici.

Tâche

Vous écririez un programme qui prend l'entrée de STDIN ou une fonction qui accepte 2 tableaux (ou conteneurs associés) de nombres (qui sont de la même longueur).

En supposant que vous écrivez une fonction qui accepte 2 tableaux (a et b), vous allez trouver le nombre de façons de réorganiser les nombres dans le deuxième tableau (b) pour maximiser:

a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+...+a[n-1]*b[n-1]

Dans ce cas, si le tableau b est [1 0 , 2 1 , 2 2 , 3 3 , 3 4 ] (indices de clarté),

[1 0 , 2 1 , 2 2 , 3 3 , 3 4 ],

[1 0 , 2 1 , 2 2 , 3 4 , 3 3 ], (échangez les deux 3)

[1 0 , 2 2 , 2 1 , 3 3 , 3 4 ] (permutez les deux 2)

[1 0 , 2 2 , 2 1 , 3 4 , 3 3 ] (échangez les deux 3 et échangez les deux 2)

sont considérés comme des arrangements différents. Le tableau d'origine, lui-même, compte également comme un éventuel réarrangement s'il maximise également la somme.

Pour l'entrée STDIN, vous pouvez supposer que la longueur des tableaux est fournie avant les tableaux (veuillez l'indiquer pour que vous l'utilisiez), ou que les tableaux soient fournis sur des lignes différentes (veuillez également l'indiquer).

Voici les 4 entrées possibles (pour plus de commodité):

5 1 1 2 2 2 1 2 2 3 3 (length before arrays)

1 1 2 2 2 1 2 2 3 3 (the 2 arrays, concatenated)

1 1 2 2 2
1 2 2 3 3 (the 2 arrays on different lines)

5
1 1 2 2 2
1 2 2 3 3 (length before arrays and the 2 arrays on different lines)

Pour la sortie, vous êtes autorisé à renvoyer la réponse (si vous écrivez une fonction) ou à imprimer la réponse dans STDOUT. Vous pouvez choisir de sortir la réponse mod 10 9 +7 (de 0 à 10 9 +6) si cela est plus pratique.

Cas de test (et explication):

[1 1 2 2 2] [1 2 2 3 3] => 24

Les 2 premières entrées doivent être 1 et 2. Les 3 dernières entrées sont 2, 3 et 3. Il y a 2 façons d'organiser les 2 entre les 2 premières entrées et les 2 dernières entrées. Parmi les 2 premières entrées, il y a 2 façons de les réorganiser. Parmi les 2 dernières entrées, il y a 6 façons de les réorganiser.

[1 2 3 4 5] [6 7 8 9 10] => 1

Il n'y a qu'une seule façon, qui est l'arrangement donné dans les tableaux.

[1 1 ... 1 1] [1 1 ... 1 1] (10000 numbers) => 10000! or 531950728

Chaque permutation possible du deuxième tableau est valide.

Testcase de Dennis: Pastebin => 583159312 (mod 1000000007)

Notation:

C'est le code-golf, donc la réponse la plus courte l'emporte.

En cas d'égalité, les égalités seront rompues au moment de la soumission, favorisant la soumission antérieure.

Prendre note:

Les conteneurs peuvent ne pas être triés.

Les entiers dans les conteneurs peuvent être nuls ou négatifs.

Le programme doit s'exécuter assez rapidement (au plus une heure) pour les baies de taille modeste (environ 10000 de longueur).

Inspiré par cette question sur Mathematics Stack Exchange.

Element118
la source
2
Veuillez fournir un cas de test avec 10000 éléments par tableau, afin que nous puissions vérifier que notre code fonctionne correctement et est assez rapide.
Dennis
1
Dans l'exemple que vous donnez pour échanger le deuxième tableau [1_0, 2_2, 2_1, 3_4, 3_3] (échanger les deux 2 et échanger les deux 3) est manquant
Willem
acceptez-vous des entrées comme [. . .]plz
respond
Si nous soumettons une fonction, devons-nous prendre deux arguments distincts ou pourrions-nous prendre un tableau de tableaux?
Dennis
Eh bien, le tableau des tableaux semble correct et n'affecte pas trop le défi. Je vais travailler sur le cas de test.
Element118

Réponses:

4

CJam, 30 26 octets

q~](/:$_za+{e`0f=:m!:*}//*

Essayez-le en ligne dans l' interpréteur CJam .

Il complète ce cas de test en moins d'une seconde:

$ time cjam <(echo 'q~](/:$_za+{e`0f=:m!:*}%)\:*\/N') < test-large.in | md5sum
5801bbf8ed0f4e43284f7ec2206fd3ff  -

real    0m0.308s
user    0m0.667s
sys     0m0.044s

Son exécution dans l'interpréteur en ligne devrait prendre moins de 10 secondes.

Algorithme

Le résultat ne dépend pas de l'ordre de A , nous pouvons donc supposer qu'il est trié. Cela signifie que B doit également être trié pour atteindre le produit scalaire maximal.

Maintenant, si r 1 ,… r n sont la longueur des pistes du tri A , il y a ∏r k ! différents réarrangements des éléments de A qui se traduisent toujours par ordre croissant.

De même, si s 1 ,… s n sont la longueur des pistes du B trié , il y a ∏s k ! différents réarrangements des éléments de B qui se traduisent toujours par ordre croissant.

Cependant, cela compte tous les appariements plusieurs fois. Si nous prenons les paires des éléments correspondants de triés A et triés B et définissons t 1 ,… t n comme la longueur des parcours du tableau résultant, ∏t k ! est le multiplicateur susmentionné.

Ainsi, le résultat souhaité est (∏r k !) × (∏s k !) ÷ (∏t k !) .

Code

 q~                          Read and evaluate all input.
   ]                         Wrap the resulting integers in an array.
    (                        Shift out the first (length).
     /                       Split the remainder into chunks of that length.
      :$                     Sort each chunk.
        _z                   Push a copy and transpose rows with columns.
                             This pushes the array of corresponding pairs.
          a+                 Wrap in array and concatenate (append).
            {          }/    For A, B, and zip(A,B):
             e`                Perform run-length encoding.
               0f=             Select the runs.
                  :m!          Apply factorial to each.
                     :*        Reduce by multiplication.
                         /   Divide the second result by the third.
                          *  Multiply the quotient with the first result.
Dennis
la source
6

Pyth, 29 28 octets

M/*FPJm*F.!MhMrd8aFCB,SGSHeJ

Essayez-le en ligne dans le compilateur Pyth .

Algorithme

Le résultat ne dépend pas de l'ordre de A , nous pouvons donc supposer qu'il est trié. Cela signifie que B doit également être trié pour atteindre le produit scalaire maximal.

Maintenant, si r 1 ,… r n sont la longueur des pistes du tri A , il y a ∏r k ! différents réarrangements des éléments de A qui se traduisent toujours par ordre croissant.

De même, si s 1 ,… s n sont la longueur des pistes du B trié , il y a ∏s k ! différents réarrangements des éléments de B qui se traduisent toujours par ordre croissant.

Cependant, cela compte tous les appariements plusieurs fois. Si nous prenons les paires des éléments correspondants de triés A et triés B et définissons t 1 ,… t n comme la longueur des parcours du tableau résultant, ∏t k ! est le multiplicateur susmentionné.

Ainsi, le résultat souhaité est (∏r k !) × (∏s k !) ÷ (∏t k !) .

Code

M/*FPJm*F.!MhMrd8aFCB,SGSHeJ

M                             Define g(G,H):
                      SGSH      Sort G and H.
                     ,          For the pair of the results.
                   CB           Bifurcated zip (C).
                                This returns [[SG, SH], zip([SG, SH])].
                 aF             Reduce by appending.
                                This returns [SG, SH, zip([SG, SH])].
      m                         Map; for each d in the resulting array:
              rd8                 Perform run-length encoding on d.
            hM                    Mapped "head". This returns the lengths.
         .!M                      Mapped factorial.
       *F                         Reduce by multiplication.
     J                          Save the result in J.
    P                           Discard the last element.
  *F                            Reduce by multiplication.
 /                  
                          eJ    Divide the product by the last element of J.
                                Return the result of the division.

Vérification

J'ai généré de manière pseudo-aléatoire 100 cas de test de longueur 6, que j'ai résolus avec le code ci-dessus et cette approche par force brute:

Ml.Ms*VGZ.pH

M             Define g(G,H) (or n(G,H) on second use):
         .pH    Compute all permutations of H.
  .M            Filter .pH on the maximal value of the following;
                 for each Z in .pH:
     *VGZ         Compute the vectorized product of G and Z.
    s             Add the products.
                  This computes the dot product of G and Z.
 l              Return the length of the resulting array.

Voici les résultats:

$ cat test.in
6,9,4,6,8,4,5,6,5,0,8,2
0,7,7,6,1,6,1,7,3,3,8,0
3,6,0,0,6,3,8,2,8,3,1,1
2,3,0,4,0,6,3,4,5,8,2,4
9,1,1,2,2,8,8,1,7,4,9,8
8,3,1,1,9,0,2,8,3,4,9,5
2,0,0,7,7,8,9,2,0,6,7,7
0,7,4,2,2,8,6,5,0,5,4,9
2,7,7,5,5,6,8,8,0,5,6,3
1,7,2,7,7,9,9,2,9,2,9,8
7,2,8,9,9,0,7,4,6,2,5,3
0,1,9,2,9,2,9,5,7,4,5,6
8,4,2,8,8,8,9,2,5,4,6,7
5,2,8,1,9,7,4,4,3,3,0,0
9,3,6,2,5,5,2,4,6,8,9,3
4,2,0,6,2,3,5,3,6,3,1,4
4,8,5,2,5,0,5,1,2,5,9,5
6,8,4,4,9,5,9,5,4,2,8,7
8,9,8,1,2,2,9,0,5,6,4,9
4,7,6,8,0,3,7,7,3,9,8,6
7,5,5,6,3,9,3,8,8,4,8,0
3,8,1,8,5,6,6,7,2,8,5,3
0,9,8,0,8,3,0,3,5,9,5,6
4,2,7,7,5,8,4,2,6,4,9,4
3,5,0,8,2,5,8,7,3,4,5,5
7,7,7,0,8,0,9,8,1,4,8,6
3,9,7,7,4,9,2,5,9,7,9,4
4,5,5,5,0,7,3,4,0,1,8,2
7,4,4,2,5,1,7,4,7,1,9,1
0,6,2,5,4,5,1,8,0,8,9,9
3,8,5,3,2,1,1,2,2,2,8,4
6,1,9,1,8,7,5,6,9,2,8,8
6,2,6,6,6,0,2,7,8,6,8,2
0,7,1,4,5,5,3,4,4,0,0,2
6,0,1,5,5,4,8,5,5,2,1,6
2,6,3,0,7,4,3,6,0,5,4,9
1,4,8,0,5,1,3,2,9,2,6,5
2,7,9,9,5,0,1,5,6,8,4,6
4,0,1,3,4,3,6,9,1,2,7,1
6,5,4,7,8,8,6,2,3,4,1,2
0,3,6,3,4,0,1,4,5,5,5,7
5,4,7,0,1,3,3,0,2,1,0,8
8,6,6,1,6,6,2,2,8,3,2,2
7,1,3,9,7,4,6,6,3,1,5,8
4,8,3,3,9,1,3,4,1,3,0,6
1,4,0,7,4,9,8,4,2,1,0,3
0,4,1,6,4,4,4,7,5,1,4,2
0,0,4,4,9,6,7,2,7,7,5,4
9,0,5,5,0,8,8,9,5,9,5,5
5,7,0,4,2,7,6,1,1,1,9,1
3,1,7,5,0,3,1,4,0,9,0,3
4,4,5,7,9,5,0,3,7,4,7,5
7,9,7,3,0,8,4,0,0,3,1,0
2,4,4,3,1,2,5,2,9,0,8,5
4,8,7,3,0,0,9,3,7,3,0,6
8,9,1,0,7,7,6,0,3,1,8,9
8,3,1,7,3,3,6,1,1,7,6,5
6,5,6,3,3,0,0,5,5,0,6,7
2,4,3,9,7,6,7,6,5,6,2,0
4,8,5,1,8,4,4,3,4,5,2,5
7,5,0,4,6,9,5,0,5,7,5,5
4,8,9,5,5,2,3,1,9,7,7,4
1,5,3,0,3,7,3,8,5,5,3,3
7,7,2,6,1,6,6,1,3,5,4,9
9,7,6,0,1,4,0,4,4,1,4,0
3,5,1,4,4,0,7,1,8,9,9,1
1,9,8,7,4,9,5,2,2,1,2,9
8,1,2,2,7,7,6,8,2,3,9,7
3,5,2,1,3,5,2,2,4,7,0,7
9,6,8,8,3,5,2,9,8,7,4,7
8,8,4,5,5,1,5,6,5,1,3,3
2,6,3,5,0,5,0,3,4,4,0,5
2,2,7,6,3,7,1,4,0,3,8,3
4,8,4,2,6,8,5,6,2,5,0,1
7,2,4,3,8,4,4,6,5,3,9,4
4,6,1,0,6,0,2,6,7,4,9,5
6,3,3,4,6,1,0,8,6,1,7,5
8,3,4,2,8,3,0,1,8,9,1,5
9,6,1,9,1,1,8,8,8,9,1,4
3,6,1,6,1,4,5,1,0,1,9,1
6,4,3,9,3,0,5,0,5,3,2,4
5,2,4,6,1,2,6,0,1,8,4,0
3,5,7,6,3,6,4,5,2,8,1,5
6,3,6,8,4,2,7,1,5,3,0,6
9,1,5,9,9,1,1,4,5,7,3,0
1,6,7,3,5,8,6,5,5,2,6,0
2,8,8,6,5,5,2,3,8,1,9,8
0,4,5,3,7,6,2,5,4,3,2,5
5,1,2,3,0,3,4,9,4,9,4,9
5,8,2,2,0,2,4,1,1,7,0,3
0,6,0,0,3,6,3,6,2,2,2,9
2,4,8,1,9,4,0,8,8,0,4,7
3,9,1,0,5,6,8,8,2,5,2,6
5,3,8,9,1,6,5,9,7,7,6,1
8,6,9,6,1,1,6,7,7,3,2,2
7,2,1,9,8,8,5,3,6,3,3,6
9,9,4,8,7,9,8,6,6,0,3,1
8,3,0,9,1,7,4,8,0,1,6,2
8,2,6,2,4,0,2,8,9,6,3,7
1,0,8,5,3,2,3,7,1,7,8,2
$ while read; do
> pyth -c 'M/*FPJm*F.!MhMrd8aFCB,SGSHeJMl.Ms*VGZ.pHAc2Q,gGHnGH' <<< "$REPLY"
> done < test.in
[4, 4]
[4, 4]
[8, 8]
[4, 4]
[8, 8]
[2, 2]
[4, 4]
[4, 4]
[4, 4]
[36, 36]
[2, 2]
[8, 8]
[24, 24]
[8, 8]
[2, 2]
[2, 2]
[6, 6]
[2, 2]
[8, 8]
[2, 2]
[12, 12]
[2, 2]
[8, 8]
[12, 12]
[4, 4]
[12, 12]
[4, 4]
[6, 6]
[8, 8]
[8, 8]
[6, 6]
[4, 4]
[48, 48]
[8, 8]
[4, 4]
[1, 1]
[4, 4]
[4, 4]
[8, 8]
[4, 4]
[12, 12]
[2, 2]
[96, 96]
[2, 2]
[4, 4]
[2, 2]
[6, 6]
[24, 24]
[24, 24]
[48, 48]
[4, 4]
[8, 8]
[12, 12]
[8, 8]
[4, 4]
[2, 2]
[24, 24]
[16, 16]
[2, 2]
[8, 8]
[24, 24]
[4, 4]
[24, 24]
[4, 4]
[12, 12]
[8, 8]
[12, 12]
[4, 4]
[8, 8]
[4, 4]
[16, 16]
[4, 4]
[8, 8]
[8, 8]
[4, 4]
[4, 4]
[4, 4]
[4, 4]
[72, 72]
[24, 24]
[4, 4]
[4, 4]
[4, 4]
[2, 2]
[12, 12]
[4, 4]
[8, 8]
[4, 4]
[36, 36]
[6, 6]
[12, 12]
[8, 8]
[4, 4]
[2, 2]
[8, 8]
[24, 24]
[6, 6]
[1, 1]
[2, 2]
[2, 2]

Pour vérifier que ma soumission satisfait à l'exigence de vitesse, je l'ai exécutée avec ce scénario de test .

$ time pyth -c 'M/*FPJm*F.!MhMrd8aFCB,SGSHeJAc2QgGH' < test-large.in | md5sum
5801bbf8ed0f4e43284f7ec2206fd3ff  -

real    0m0.233s
user    0m0.215s
sys     0m0.019s
Dennis
la source
2

Matlab, 230 octets

Edit: Beaucoup de choses ont été corrigées pour correspondre aux cas de test de dennis, et nnz est remplacé par numel en raison de valeurs nulles.

f=1;t=-1;q=1;a=sort(input(''));b=sort(input(''));for i=unique(a)c=b(find(a==i));r=numel(c(c==t));f=f*factorial(numel(c))*sum(arrayfun(@(u)nchoosek(max(q,r),u),0:min(q,r)));z=c(end);y=numel(c(c==z));q=(t==z)*(q+r)+(t~=z)*y;t=z;end,f

Exécution

[2 2 1 2 1]
[3 2 3 2 1]

f =

    24

Testcase de Dennis:

   A = importdata('f:\a.csv'); for i=1:100,a=sort(A(i,1:6));b=sort(A(i,7:12));
   f=1;t=-1;q=1;for i=unique(a)c=b(find(a==i));r=numel(c(c==t));f=f*factorial(numel(c))*sum(arrayfun(@(u)nchoosek(max(q,r),u),0:min(q,r)));z=c(end);y=numel(c(c==z));q=(t==z)*(q+r)+(t~=z)*y;t=z;end;
   disp(f);end

Les sorties:

 4

 4

 8

 4

 8

 2

 4

 4

 4

36

 2

 8

24

 8

 2

 2

 6

 2

 8

 2

12

 2

 8

12

 4

12

 4

 6

 8

 8

 6

 4

48

 8

 4

 1

 4

 4

 8

 4

12

 2

96

 2

 4

 2

 6

24

24

48

 4

 8

12

 8

 4

 2

24

16

 2

 8

24

 4

24

 4

12

 8

12

 4

 8

 4

16

 4

 8

 8

 4

 4

 4

 4

72

24

 4

 4

 4

 2

12

 4

 8

 4

36

 6

12

 8

 4

 2

 8

24

 6

 1

 2

 2
Abr001am
la source
Eh bien, cela résout le problème, donc l'entrée ne devrait pas trop d'importance.
Element118
1

C ++, 503 octets

(juste pour le plaisir, une langue non golfique)

#import<iostream>
#import<algorithm>
#define U 12345
#define l long long
using namespace std;int N,X=1,Y=1,Z=1,x[U],y[U],i=1;l p=1,M=1000000007,f[U];l e(l x,int y){return y?y%2?(x*e(x,y-1))%M:e((x*x)%M,y/2):1;}main(){for(f[0]=1;i<U;i++)f[i]=(f[i-1]*i)%M;cin>>N;for(i=0;i<N;i++)cin>>x[i];for(i=0;i<N;i++)cin>>y[i];sort(x,x+N);sort(y,y+N);for(i=1;i<N;i++)x[i]^x[i-1]?p=p*f[X]%M,X=1:X++,y[i]^y[i-1]?p=p*f[Y]%M,Y=1:Y++,x[i]^x[i-1]|y[i]^y[i-1]?p=p*e(f[Z],M-2)%M,Z=1:Z++;cout<<p*f[X]%M*f[Y]%M*e(f[Z],M-2)%M;}

Version non golfée:

#include <cstdio>
#include <algorithm>
#define MOD 1000000007
using namespace std;
int N; // number of integers
int x[1000010]; // the 2 arrays of integers
int y[1000010];
long long product = 1;
long long factorial[1000010]; // storing factorials mod 1000000007
long long factorialInv[1000010]; // storing the inverse mod 1000000007
long long pow(long long x, int y) {
    if (y == 0) return 1;
    if (y == 1) return x;
    if (y%2 == 1) return (x*pow(x, y-1))%MOD;
    return pow((x*x)%MOD, y/2);
}
int main(void) {
    //freopen("in.txt", "r", stdin); // used for faster testing
    //precomputation
    factorial[0] = factorial[1] = 1;
    for (int i=2;i<=1000000;i++) {
        factorial[i] = (factorial[i-1]*i)%MOD;
        factorialInv[i] = pow(factorial[i], MOD-2);
    }
    // input
    scanf("%d", &N);
    for (int i=0;i<N;i++) {
        scanf("%d", &x[i]);
    }
    for (int i=0;i<N;i++) {
        scanf("%d", &y[i]);
    }
    // sort the 2 arrays
    sort(x, x+N);
    sort(y, y+N);
    int sameX = 1;
    int sameY = 1;
    int sameXY = 1;
    for (int i=1;i<N;i++) {
        if (x[i]==x[i-1]) {
            sameX++;
        } else {
            product *= factorial[sameX];
            product %= MOD;
            sameX = 1;
        }
        if (y[i]==y[i-1]) {
            sameY++;
        } else {
            product *= factorial[sameY];
            product %= MOD;
            sameY = 1;
        }
        if (x[i]==x[i-1] && y[i]==y[i-1]) {
            sameXY++;
        } else {
            product *= factorialInv[sameXY];
            product %= MOD;
            sameXY = 1;
        }
    }
    product *= factorial[sameX];
    product %= MOD;
    product *= factorial[sameY];
    product %= MOD;
    product *= factorialInv[sameXY];
    product %= MOD;
    printf("%lld\n", product);
    return 0;
}
Element118
la source