Número de permutaciones de cuerdas que son palíndromos.


13

Su entrada será una cadena que consiste en pequeñas letras en inglés.

Su tarea es determinar el número de permutaciones distintas de la cadena original que son un palíndromo.

La cadena de entrada tiene hasta 100 letras. En el caso de una cadena más larga, el resultado podría ser muy grande, por lo que la salida debería ser el número de permutaciones del módulo 666013.

Por ejemplo,

cababaa -> 3

Las posibles permutaciones son:

aabcbaa
abacaba
baacaab

Este es el , por lo que gana la respuesta más corta.


2
"Dado que la cadena tiene hasta 100 dígitos, el resultado debe ser% 666013". Si es así, sería una buena idea incluir un caso de prueba correspondiente.
Martin Ender

44
No entiendo la línea% 666013. Sin embargo, este es un desafío prometedor, y estaría dispuesto a votar para reabrir una vez que se haya explicado.

12
Oh, ahora que ha sido editado, veo a qué te refieres. No creo que esa línea se sume al desafío; principalmente castiga los idiomas sin enteros de precisión arbitraria. Normalmente hacemos algo como "la respuesta debe ser correcta si se ejecuta en una versión hipotética de su idioma con enteros ilimitados".

77
Esto realmente podría usar más casos de prueba.
sonríe

3
Sugerencias para casos de prueba (por favor verifíquelos): abcdabcddddd -> 120 (sin recuento de caracteres impares) , abcdabcdddddd -> 120 (un recuento de caracteres impares) , abcdabcddddddeee -> 0 (dos recuentos de caracteres impares) , aabbccddeeffgghhiijj -> 298735 (afectados por el módulo) .
sonríe

Respuestas:


5

Brachylog (2), 15 bytes

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

Pruébalo en línea!

Explicación

{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

2
Definitivamente necesito implementar ese "encontrar único" ...
Fatalize

2
@Fatalize: ¡Sí! Creo que incluso "cuenta única" ocurre con suficiente frecuencia en los desafíos como para que valga la pena una representación de 1 byte. Por otro lado, "módulo 666013" es casi seguro que no lo hace ;-)

5

05AB1E , 17 16 13 bytes

-1 byte de Jonathon Allan

-3 bytes de Emigna y Adnan

œÙvyÂQO•E›j•%

Explicación:

œÙ                # 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)

Pruébalo en línea!


1
El contenido, E›jrepresenta los dígitos [14, 116, 45]que se convierten desde la base 214y se convierte en 14*214^2 + 116*214 + 45 = 666013. No estoy muy seguro de dónde está la referencia para los dígitos, pero parecen estar en línea (¿ish?) Con su orden en la página de información . @Adnan puede iluminarnos.
Jonathan Allan

1
@Emigna Easy cuando sabes el idioma: D
Jonathan Allan

1
Puede guardar 2 bytes eliminando la instrucción if, ya que solo tiene los valores necesarios en la pila de todos modos:œÙvyÂQ}O•E›j•%
Emigna

2
@JonathanAllan El rango completo de dígitos (y caracteres) se puede encontrar aquí :).
Adnan

1
Basándose en el comentario de @ Emigna, puede guardar otro byte quitando la llave de cierre: œÙvyÂQO•E›j•%.
Adnan

4

Perl 6 , 104 108 88 84 bytes

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

Pruébalo en línea!

Cómo funciona

No puedo generar fácilmente todas las permutaciones y filtrarlas, incluso si se permiten tiempos de ejecución astronómicos, porque el Perl 6 está incorporado permutations rutina niega a permutar listas de más de 20 elementos y la descripción de la tarea requiere entradas de hasta 100 caracteres.

Entonces, en cambio, uso una fórmula directa basada en las frecuencias de letras de la entrada:

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

    Una función auxiliar que reduce a la mitad un número y lo redondea al entero más cercano, y luego toma el factorial de eso.

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

    Calcule las frecuencias de las letras en la cadena de entrada y conviértalas en el tema del resto del código. Por ejemplo, para la entrada abcdabcddddddesta sería la lista (2, 2, 2, 7).

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

    Si hay más de una frecuencia de letras impares, multiplique el resultado por cero, porque en ese caso no son posibles los palíndromos.

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

    Calcule el número de permutaciones posibles de los caracteres que estarán en "un lado" de cada palíndromo (que corresponde a un conjunto múltiple con las multiplicidades obtenidas al dividir a la mitad y poner en el suelo las frecuencias de las letras de entrada) . La fórmula utilizada es de este PDF :
    (n 1 + ... + n k )! / (n 1 ! ⋅ ... ⋅n k 1)
    Por ejemplo, para las frecuencias de (2,2,2,7)las letras de entrada , las letras en un lado del palíndromo forman un conjunto múltiple con multiplicidades (1,1,1,3), y el número de permutaciones es así (1+1+1+3)! / (1!⋅1!⋅1!⋅3!) = 120.

  5. % 666013

    Tome el resultado módulo 666013.


¡Es bueno ver que mi método alternativo es válido!
Jonathan Allan

3

Python3, 81 80 bytes

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

Esto es lo más corto que se me ocurrió. No estoy seguro si las permutaciones se pueden generar más fácilmente ...

Explicación

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.

Notas

  1. La comprobación a==a[::-1]devuelve un valor booleano, pero la sum(...)función lo convierte implícitamente en un entero (0 o 1) y suma en consecuencia.
  2. Tengo que usar el ' operador splat ' (no el nombre real), para extraer los elementos del objeto permutations(...). De lo contrario, el conjunto ( {...}) contendría solo un elemento, el objeto mismo.
  3. Yo uso un set ( {...}) para mantener solo permutaciones distintas dentro.

En Floroid, esto es (casi) z(T(a==aDKaIW(cb(L)))%666013), pero imprime el resultado en su lugar y toma la entrada a través de la línea de comando.

¡Gracias a @Jonathan Allan por guardar un byte! -> Cambió el importestilo

Pruébalo en línea!


3

Jalea , 13 bytes

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

Pruébalo en línea!

¿Cómo?

Un forzador bruto.

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

Yo creo que esto hará que sea más eficiente, pero es 30 bytes (edit: este pdf parece confirmar que, por cortesía de respuesta de los LMS ):

Ñ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.

Sí, el %mod es.
Jonathan Allan

Gah, estaba a punto de publicar exactamente esta respuesta, pero no llegué a tiempo porque publiqué primero la respuesta de Brachylog. Una cuestión de segundo, creo. Claramente, debo recordar que Jelly es un lenguaje más popular que Brachylog, por lo que primero debería trabajar en esa presentación.

Wow, byte por byte? También tengo otros 13, pero creo que es un poco menos eficiente :)
Jonathan Allan

¿El número está comprimido en una base diferente o qué? : P
Yytsi

Desde mi pestaña TIO, Œ!QŒḂ€S%“µɲ€’. Eso se ve idéntico a mí.

2

Mathematica, 46 bytes

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

Toma una lista de caracteres como entrada.

Terriblemente ineficiente, porque en realidad genera todas las permutaciones de la entrada y luego cuenta las palindrómicas.


Creo que esto da incorrectamente una respuesta positiva, en lugar de 0, si la cadena tiene varias letras que ocurren con una multiplicidad impar (como "abcdabcddddddeee").
Greg Martin

@ GregMartin Gracias, arreglado. Esto fue innecesariamente complicado de todos modos.
Martin Ender

2

Mathematica, 68 bytes

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

Función pura que toma una lista de caracteres como entrada y devuelve un entero. No es tan corto como la respuesta de Mathematica de Martin Ender , pero es un enfoque lindo, que parece ser el mismo enfoque que en la respuesta Perl 6 de smls .

Primero, t=Last/@Tally@#/2calcula los recuentos de todos los caracteres distintos en la entrada, divididos por 2; luego i=Floorredondea las fracciones que ocurran en t. Tenga en cuenta que las permutaciones palindrómicas de la entrada existen exactamente cuando hay como máximo un número impar entre los recuentos originales, es decir, cuando hay como máximo una fracción t. Podemos probar eso simplemente sumando todos los elementos de t-i(usar Tr): si la respuesta es menor que 1, hay permutaciones palindrómicas, de lo contrario no.

Si los hay, irepresenta los recuentos de caracteres distintos en la mitad izquierda de las permutaciones, que se pueden organizar de forma arbitraria. La cantidad de formas de hacerlo es exactamente el Multinomialcoeficiente (un cociente de ciertos factoriales), que Mathematica ha incorporado.


1

k, 23 bytes

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

Si usa oK , o cmbno existe, use en prmlugar de cmb.



1

C ++ 14, 161 bytes

Como lambda sin nombre, suponiendo que la entrada es similar std::stringy regresa a través del parámetro de referencia.

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

Sin golf y uso:

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

1

Ruby, 67 57 52 59 caracteres

->s{s.chars.permutation.uniq.count{|t|t.reverse==t}%666013}

Las presentaciones de Codegolf deben ser programas / funciones / lambdas adecuadas, no fragmentos . No soy un programador de Ruby, pero creo que puedes convertir esto en una lambda envolviéndolo ->s{ }, ¿no?
sonríe

Además, según la documentación , ¿no es (s.size)redundante el argumento?
sonríe

1
Lo probé en Ruby 2.4, y funciona sin el .to_atambién.
sonrisas

@smls No funciona en ruby ​​2.3.3 ( undefined method uniq 'para # <Enumerator`), pero sí funciona en ruby ​​2.4, gracias :)
Dorian

¿El resultado tiene que ser tomado mod 666013?
NonlinearFruit


0

MATL, 13 bytes

Y@Xu!"@tP=Avs

Pruébalo en MATL Online

Explicación

        % 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

0

CJam , 19 bytes

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

Pruébalo en línea!

Explicación:

qe! {_ W% =}%: + 666013% e # Programa completo.
qe # Obtenga todas las entradas.
 ¡mi! e # Obtenga todas las permutaciones únicas.
   {_W% =} e # Función para verificar si una lista es un palíndromo.
    _ e # Duplicar ToS.
     W% e # Reverse ToS (Push -1, índice modular de ToS).
       = e # Verifique si ToS es igual a SToS.
         % e # Mapa.
          : + e # Suma (Reducir por adición).
            666013 e # Empuje 666013.
                  % e # Módulo.


0

Ohm, 17 bytes

I⌐:_₧?¡;;¼,

Explicación:

I⌐:_₧?¡;;¼,  ■Main wire
I⌐:     ;    ■for _ in permutations(input()){
   _₧? ;     ■  if(palindrome(_)){
      ¡      ■    counter++;
       ;     ■  }
        ;    ■}
         ¼,  ■print(counter)

0

PHP, 182 bytes

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

Versión en línea

Descompostura

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);
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.