Nombre de permutations de chaînes qui sont des palindromes

13

Votre entrée sera une chaîne composée de petites lettres anglaises.

Votre tâche consiste à déterminer le nombre de permutations distinctes de la chaîne d'origine qui sont un palindrome.

La chaîne d'entrée contient jusqu'à 100 lettres. Dans le cas d'une chaîne plus longue, le résultat peut être très grand, donc la sortie doit être le nombre de permutations modulo 666013.

Par exemple,

cababaa -> 3

Les permutations possibles sont:

aabcbaa
abacaba
baacaab

Il s'agit de , donc la réponse la plus courte l'emporte!

Andrei Mihailescu
la source
2
"Étant donné que la chaîne contient jusqu'à 100 chiffres, le résultat doit être% 666013." Si c'est le cas, ce serait une bonne idée d'inclure un cas de test correspondant.
Martin Ender
4
Je ne comprends pas la ligne% 666013. C'est un défi prometteur, cependant, et je serais prêt à voter pour la réouverture une fois cela expliqué.
12
Oh, maintenant que ça a été édité, je vois où tu veux en venir. Je ne pense pas que cette ligne ajoute au défi; il punit principalement les langues sans nombres entiers de précision arbitraire. Normalement, nous faisons quelque chose comme "la réponse devrait être correcte si elle est exécutée dans une version hypothétique de votre langue avec des entiers non bornés".
7
Cela pourrait vraiment utiliser plus de cas de test.
smls
3
Suggestions pour les cas de test (veuillez les vérifier cependant): abcdabcddddd -> 120 (pas de nombre de caractères impairs) , abcdabcdddddd -> 120 (un nombre de caractères impairs) , abcdabcddddddeee -> 0 (deux nombres de caractères impairs) , aabbccddeeffgghhiijj -> 298735 (affectés par le modulo) .
smls

Réponses:

5

Brachylog (2), 15 octets

{p.↔}ᶠdl%₆₆₆₀₁₃

Essayez-le en ligne!

Explication

{p.↔}ᶠdl%₆₆₆₀₁₃
{   }ᶠdl          Count (l) the number of distinct (d) results (ᶠ) obtainable by:
 p                  permuting {the input}
  .                 to produce an output
   ↔                that, if reversed, is still the output
        %₆₆₆₀₁₃   then take that number modulo 666013

la source
2
Je dois absolument implémenter cette "découverte unique" ...
Fatalize
2
@Fatalize: Oui! Je pense que même le «compte unique» se produit assez souvent dans les défis pour peut-être valoir une représentation sur 1 octet. D'un autre côté, "modulo 666013" ne le fait presque certainement pas ;-)
5

05AB1E , 17 16 13 octets

-1 octet de Jonathon Allan

-3 octets depuis Emigna et Adnan

œÙvyÂQO•E›j•%

Explication:

œÙ                # Unique permutations of [implicit] input
  vy              # For each permutation...
    ÂQ            # Check if it is a palindrome
      O           # If so, increment the counter
       •E›j•%     # Modulo 666013 (no clue why this number, or even why this rule is in place)

Essayez-le en ligne!

Okx
la source
1
Le contenu,, E›jreprésente les chiffres [14, 116, 45]qui sont convertis à partir de la base 214, et devient 14*214^2 + 116*214 + 45 = 666013. Je ne sais pas trop où est la référence pour les chiffres, mais ils semblent être en ligne (ish?) Avec leur commande sur la page d'informations . @Adnan peut nous éclairer.
Jonathan Allan
1
@Emigna Facile quand vous connaissez la langue: D
Jonathan Allan
1
Vous pouvez économiser 2 octets en supprimant l'instruction if car vous n'avez de toute façon que les valeurs nécessaires sur la pile:œÙvyÂQ}O•E›j•%
Emigna
2
@JonathanAllan La gamme complète des chiffres (et des caractères) peut être trouvée ici :).
Adnan
1
S'appuyant sur @ commentaire de Emigna, vous pouvez enregistrer un autre octet en supprimant le support de fermeture: œÙvyÂQO•E›j•%.
Adnan
4

Perl 6 , 104 108 108 88 84 octets

{my &f={[*] 1..$_ div 2}
.comb.Bag{*}.&{(2>.grep(*%2))*f(.sum)/[*]($_».&f)%666013}}

Essayez-le en ligne!

Comment ça fonctionne

Je ne peux pas facilement générer toutes les permutations et les filtrer, même si les temps d'exécution astronomiques sont autorisés, car la permutationsroutine intégrée de Perl 6 refuse directement de permuter des listes de plus de 20 éléments et la description de la tâche nécessite des entrées allant jusqu'à 100 personnages.

Au lieu de cela, j'utilise une formule directe basée sur les fréquences des lettres de l'entrée:

  1. mon & f = {[*] 1 .. $ _ div 2}

    Une fonction d'assistance qui divise par deux un nombre et l'arrondit à l'entier le plus proche, puis prend la factorielle de cela.

  2. .comb.Bag {*}. & {};

    Comptez les fréquences des lettres dans la chaîne d'entrée et faites-en le sujet pour le reste du code. Par exemple, pour la saisie, abcdabcddddddce serait la liste (2, 2, 2, 7).

  3. (2> .grep (*% 2)) *

    S'il y a plus d'une fréquence de lettres impaires, multipliez le résultat par zéro, car aucun palindrome n'est possible dans ce cas.

  4. f (.sum) / [*] ($ _ ». & f)

    Calculez le nombre de permutations possibles des caractères qui seront sur "un côté" de chaque palindrome (ce qui correspond à un multiset avec les multiplicités obtenues en divisant par deux et en parquetant les fréquences des lettres d'entrée) . La formule utilisée est issue de ce PDF :
    (n 1 + ... + n k )! / (n 1 ! ⋅ ... ⋅n k 1)
    Par exemple pour les fréquences (2,2,2,7)des lettres d' entrée , les lettres d' un côté du palindrome forment un multiset avec des multiplicités (1,1,1,3), et le nombre de permutations est donc (1+1+1+3)! / (1!⋅1!⋅1!⋅3!) = 120.

  5. % 666013

    Prenez le résultat modulo 666013.

smls
la source
Bon de voir que ma méthode alternative est valable!
Jonathan Allan
3

Python3, 81 80 octets

from itertools import*
lambda s:sum(a==a[::-1]for a in{*permutations(s)})%666013

C'est le plus court que j'ai pu trouver. Je ne sais pas si les permutations peuvent être générées plus facilement ...

Explication

lambda s:                       # Anonymous function taking a parameter <s>. 
    sum(                        # Sum the following terms.
        a==a[::-1]              # Check whether the permutation <a> is a palindrome,
        for a in                # for each element <a>,
        {                       # inside a set that can only contain distinct elements.
            *                   # Splat the elements of the following object:
            permutations(s)     # the permutations of the input parameter <s>.
        }                       #
    )%666013                    # Modulo the sum by 666013.

Remarques

  1. La vérification a==a[::-1]renvoie une valeur booléenne, mais la sum(...)fonction la convertit implicitement en un entier (0 ou 1) et additionne en conséquence.
  2. Je dois utiliser 'l' opérateur splat ' (pas le vrai nom) pour extraire les éléments de l'objet permutations(...). Sinon, set ( {...}) ne contiendrait qu'un seul élément, l'objet lui-même.
  3. J'utilise un set ( {...}) pour ne garder que des permutations distinctes à l'intérieur.

Dans Floroid, c'est (presque) z(T(a==aDKaIW(cb(L)))%666013), mais imprime le résultat à la place et prend la saisie via la ligne de commande.

Merci à @Jonathan Allan d' avoir enregistré un octet! -> Changement de importstyle

Essayez-le en ligne!

Yytsi
la source
3

Gelée , 13 octets

Œ!QŒḂ€S%“µɲ€’

Essayez-le en ligne!

Comment?

Un forceur brutal.

Œ!QŒḂ€S%“µɲ€’ - Main link: string
Œ!            - all permutations
  Q           - unique
     €        - for each
   ŒḂ         - isPalindromic? (yep a built-in!)
      S       - sum
       %      - mod
        “µɲ€’ - base 250 compressed number 666013

Je crois que cela le fera plus efficacement, mais c'est 30 octets (modifier: ce pdf semble le confirmer, gracieuseté de la réponse de smls ):

ÑHḞµS!÷!P$ - Link 1, palindrome count: string a    e.g. 'abcabcd'
Ñ          - call the next link (2) as a monad(a)  e.g. [2, 2, 2, 1]
 H         - halve                                 e.g. [1, 1, 1, 0.5]
  Ḟ        - floor (get pair counts)               e.g. [1, 1, 1, 0]
   µ       - start a new monadic chain - call that p
    S      - sum(p)                                e.g. 3
     !     - factorial                             e.g. 6
         $ - last 2 links as a monad:
       !   -     factorial(p) (vectorises)         e.g. [1, 1, 1, 1]
        P  -     product                           e.g. 1
      :    - integer division                      e.g. 6

ĠL€ - Link 2, count characters: string a           e.g. 'abcabcd'
Ġ   - group indexes                                e.g. [[1, 4], [2, 5], [3, 6], 7]
 L€ - length of €ach                               e.g. [2, 2, 2, 1]

ÇḂS⁼LḂ$aÑ%“µɲ€’ - Main link: string a              e.g. 'abcabcd'
                - first check to see if any palindromes will be possible:
Ç               - last link (2) as a monad         e.g. [2, 2, 2, 1]
 Ḃ              - mod 2                            e.g. [0, 0, 0, 1]
  S             - sum                              e.g. 1
      $         - last two links as a monad:
    L           -     length(a string)             e.g. 7
     Ḃ          -     mod 2                        e.g. 1
   ⁼            - equal?                           e.g. 1 (1 when palindromes are possible)
       a        - and
        Ñ       - next link as a monad             e.g. 6
         %“µɲ€’ - mod 666013, as in the brute force version.
Jonathan Allan
la source
Oui, c'est le %mod.
Jonathan Allan
Gah, j'étais sur le point de poster exactement cette réponse, mais je n'y suis pas arrivé à temps parce que j'ai posté la réponse Brachylog en premier. Une question de seconde, je pense. De toute évidence, je devrais me rappeler que la gelée est une langue plus populaire que Brachylog et je devrais donc travailler sur cette soumission en premier.
Wow, octet par octet? J'en ai 13 autres aussi, mais je pense que c'est un peu moins efficace :)
Jonathan Allan
Le nombre est-il compressé dans une base différente ou quoi? : P
Yytsi
De mon onglet TIO, Œ!QŒḂ€S%“µɲ€’. Cela me semble tout à fait identique.
2

Mathematica, 46 octets

Permutations@#~Count~_?PalindromeQ~Mod~666013&

Prend une liste de caractères en entrée.

Terriblement inefficace, car il génère en fait toutes les permutations de l'entrée et compte ensuite les palindromes.

Martin Ender
la source
Je pense que cela donne incorrectement une réponse positive, plutôt que 0, si la chaîne a plusieurs lettres se produisant avec une multiplicité étrange (comme "abcdabcddddddeee").
Greg Martin
@GregMartin Merci, corrigé. C'était de toute façon inutilement compliqué.
Martin Ender
2

Mathematica, 68 octets

If[i=Floor[t=Last/@Tally@#/2];Tr[t-i]<1,Multinomial@@i,0]~Mod~666013

Fonction pure prenant une liste de caractères en entrée et retournant un entier. Pas aussi courte que la réponse Mathematica de Martin Ender , mais c'est quand même une approche mignonne, qui semble être la même approche que dans la réponse Perl 6 de smls .

Tout d'abord, t=Last/@Tally@#/2calcule le nombre de tous les caractères distincts dans l'entrée, divisé par 2; puis i=Floorarrondit les fractions se produisant dans t. Notez que les permutations palindromes de l'entrée existent exactement quand il y a au plus un nombre impair parmi les chefs d' accusation d' origine, qui est, quand il y a au plus une fraction t. Nous pouvons tester cela en additionnant simplement tous les éléments de t-i(en utilisant Tr): si la réponse est inférieure à1 , il y a des permutations palindromiques, sinon non.

S'il y en a, alors ireprésente le nombre de caractères distincts dans la moitié gauche des permutations, qui peuvent être arrangées arbitrairement. Le nombre de façons de le faire est exactement le Multinomialcoefficient (un quotient de certaines factorielles), que Mathematica a intégré.

Greg Martin
la source
1

k, 23 octets

{666013!+/{x~|x}'cmb x}

Si vous utilisez oK , ou cmbn'existe pas, utilisez à la prmplace de cmb.

zgrep
la source
1

C ++ 14, 161 octets

En tant que lambda sans nom en supposant que l'entrée est similaire std::stringet en retournant via le paramètre de référence

#import<algorithm>
[](auto s,int&n){auto a=s.begin(),b=s.end();std::sort(a,b);n=0;do n=(n+std::equal(a,b,s.rbegin()))%666013;while(std::next_permutation(a,b));}

Non golfé et utilisation:

#include<iostream>
#include<string>

#import<algorithm>
auto f=
[](auto s,int&n){
 auto a=s.begin(),b=s.end();
 std::sort(a,b);
 n=0;
 do
  n=(n+std::equal(a,b,s.rbegin()))%666013;
 while(std::next_permutation(a,b));
}
;

using namespace std;


int main(){
 string s;
 s = "cababaa";
 s = "abcdabcddddd";
 int n;
 f(s,n);
 cout << n << endl;
}
Karl Napf
la source
1

Ruby, 67 57 52 59 caractères

->s{s.chars.permutation.uniq.count{|t|t.reverse==t}%666013}
Dorian
la source
Les soumissions de codegolf doivent être des programmes / fonctions / lambdas appropriés, pas des extraits . Je ne suis pas un programmeur Ruby, mais je pense que vous pouvez transformer cela en lambda en l'enveloppant ->s{ }, n'est-ce pas?
smls
De plus, d'après la documentation , l' (s.size)argument n'est-il pas redondant?
smls
1
Je l'ai testé sur Ruby 2.4, et cela fonctionne sans .to_atrop.
smls
@smls ne fonctionne pas sur ruby ​​2.3.3 (undefined method uniq 'pour # <Enumerator`), mais ça marche sur ruby ​​2.4, merci :)
Dorian
Faut-il prendre le résultat mod 666013?
NonlinearFruit
1

Japt , 20 18 octets

á f_¥Zw} l %666013

Sauvegardé 2 octets grâce à ETHproductions.

Essayez-le en ligne!

À M
la source
Bien, c'est ce que j'aurais fait. Vous pouvez économiser deux octets avec f_¥Zw}, comme _c'est court pourZ{Z
ETHproductions
á fêS â l %666013vous ferait économiser un octet.
powelles
0

MATL, 13 octets

Y@Xu!"@tP=Avs

Essayez-le sur MATL Online

Explication

        % Implicitly grab input as a string
Y@      % Compute all permutations of the inputs (one per row)
Xu      % Determine the unique rows
!       % Take the transpose so each permutation is a column
"       % For each unique permutation
  @     % Take this permutation
  tP=A  % Duplicate it, reverse it, and compare (yields 1 for palindrome and 0 otherwise)
  v     % Vertically concatenate the entire stack
  s     % Compute the sum of all elements
        % Implicitly end for loop and display the result
Suever
la source
0

CJam , 19 octets

qe!{_W%=}%:+666013%

Essayez-le en ligne!

Explication:

qe! {_ W% =}%: + 666013% e # Programme complet.
qe # Obtenez toutes les entrées.
 e! e # Obtenez toutes les permutations uniques.
   {_W% =} e # Fonction permettant de vérifier si une liste est un palindrome.
    _ e # ToS en double.
     W% e # Reverse ToS (Push -1, Index modulaire de ToS).
       = e # Vérifiez si ToS est égal à SToS.
         Carte% e #.
          : + e # Sum (réduire par addition).
            666013 e # Poussez 666013.
                  % e # Modulo.

Erik le Outgolfer
la source
0

Ohm, 17 octets

I⌐:_₧?¡;;¼,

Explication:

I⌐:_₧?¡;;¼,  ■Main wire
I⌐:     ;    ■for _ in permutations(input()){
   _₧? ;     ■  if(palindrome(_)){
      ¡      ■    counter++;
       ;     ■  }
        ;    ■}
         ¼,  ■print(counter)
Roman Gräf
la source
0

PHP, 182 octets

function f($a,$b=1){return$a?f($a-1,bcmul($a,$b)):$b;}$a=count_chars($argv[1],$r=1);foreach($a as$v){$c+=$v%2?:0;$c>1?die("0"):$z+=$f=$v/2^0;$r=bcmul(f($f),$r);}echo bcdiv(f($z),$r);

Version en ligne

Panne

function f($a,$b=1){  #Factorial
    return$a?f($a-1,bcmul($a,$b)):$b;
}
$a=count_chars($argv[1],$r=1); # Array count for every char
foreach($a as$v){
    $c+=$v%2?:0; # counter mod 2 ==1
    $c>1?die("0"):$z+=$f=$v/2^0; # end program if there are 2 chars which cannot divide by 2
    $r=bcmul(f($f),$r);
}
echo bcdiv(f($z),$r);
Jörg Hülsermann
la source