Número de permutações de cadeia de caracteres que são palíndromos

13

Sua entrada será uma sequência composta por pequenas letras em inglês.

Sua tarefa é determinar o número de permutações distintas da sequência original que são um palíndromo.

A sequência de entrada tem até 100 letras. No caso de uma sequência mais longa, o resultado pode ser muito grande, portanto a saída deve ser o número de permutações módulo 666013.

Por exemplo,

cababaa -> 3

As permutações possíveis são:

aabcbaa
abacaba
baacaab

Isso é , então a resposta mais curta vence!

Andrei Mihailescu
fonte
2
"Como a string possui até 100 dígitos, o resultado deve ser% 666013." Nesse caso, seria uma boa ideia incluir um caso de teste correspondente.
Martin Ender
4
Não entendo a linha% 666013. Este é um desafio promissor, porém, e eu estaria disposto a votar para reabrir uma vez explicado.
12
Oh, agora que foi editado, vejo o que você está falando. Eu não acho que essa linha se acrescente ao desafio; na maioria das vezes, apenas pune idiomas sem números inteiros de precisão arbitrária. Normalmente, fazemos algo como "a resposta deve estar correta se for executada em uma versão hipotética do seu idioma com números inteiros ilimitados".
7
Isso realmente poderia usar mais casos de teste.
SMLS
3
Sugestões para casos de teste (por favor, verifique-os): abcdabcddddd -> 120 (sem contagem de caracteres ímpares) , abcdabcdddddd -> 120 (uma contagem de caracteres ímpares) , abcdabcddddddeee -> 0 (duas contagens de caracteres ímpares) , aabbccddeeffgghhiijj -> 298735 (afetada pelo módulo) .
smls 23/02

Respostas:

5

Braquilog (2), 15 bytes

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

Experimente online!

Explicação

{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

fonte
2
Eu definitivamente preciso de implementar que "encontrar único" ...
Fatalize
2
@Fatalize: Sim! Eu acho que até "contar único" acontece com frequência suficiente em desafios para talvez valer uma representação de 1 byte. Por outro lado, o "módulo 666013" quase certamente não ;-) #
5

05AB1E , 17 16 13 bytes

-1 byte de Jonathon Allan

-3 bytes de Emigna e Adnan

œÙvyÂQO•E›j•%

Explicação:

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

Experimente online!

Okx
fonte
1
O conteúdo E›j,, representa os dígitos [14, 116, 45]que são convertidos da base 214e se tornam 14*214^2 + 116*214 + 45 = 666013. Não tenho muita certeza de onde está a referência para os dígitos, mas eles parecem estar alinhados (ish?) Com seu pedido na página de informações . @Adnan pode nos esclarecer.
Jonathan Allan
1
@ Emigna Fácil quando você conhece o idioma: D
Jonathan Allan
1
Você pode salvar 2 bytes removendo a instrução if, pois você só tem os valores necessários na pilha:œÙvyÂQ}O•E›j•%
Emigna 22/02
2
@ JonathanAllan A gama completa de dígitos (e caracteres) pode ser encontrada aqui :).
Adnan
1
Com base @ comentário de Emigna, você pode salvar outro byte, removendo o colchete de fechamento: œÙ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}}

Experimente online!

Como funciona

Não consigo gerar facilmente todas as permutações e filtrá-las, mesmo que sejam permitidos tempos de execução astronômicos, porque a permutationsrotina interna do Perl 6 se recusa a permutar listas de mais de 20 elementos e a descrição da tarefa exige entradas de até 100 personagens.

Então, em vez disso, uso uma fórmula direta com base nas frequências das letras da entrada:

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

    Uma função auxiliar que reduz pela metade um número e o arredonda para o número inteiro mais próximo e leva o fatorial disso.

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

    Registre as frequências das letras na sequência de entrada e faça do tópico para o restante do código. Por exemplo, para entrada, abcdabcddddddessa seria a lista (2, 2, 2, 7).

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

    Se houver mais de uma frequência de letra ímpar, multiplique o resultado por zero, pois nesse caso não são possíveis palíndromos.

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

    Calcule o número de permutações possíveis dos caracteres que estarão em "um lado" de cada palíndromo (o que corresponde a um multiset com as multiplicidades obtidas pela metade e somando as frequências das letras de entrada) . A fórmula usada é deste PDF :
    (n 1 + ... + n k )! / (n 1 ! ⋅ ... kn k 1)
    Por exemplo, para frequências de letras de entrada (2,2,2,7), as letras de um lado do palíndromo formam um multiset com multiplicidades (1,1,1,3), e o número de permutações é assim (1+1+1+3)! / (1!⋅1!⋅1!⋅3!) = 120.

  5. % 666013

    Tome o resultado módulo 666013.

smls
fonte
É bom ver que meu método alternativo é válido!
Jonathan Allan
3

Python3, 81 80 bytes

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

Este é o mais curto que eu pude apresentar. Não tenho certeza se as permutações podem ser geradas com mais facilidade ...

Explicação

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. A verificação a==a[::-1]retorna um valor booleano, mas a sum(...)função o envolve implicitamente em um número inteiro (0 ou 1) e soma em conformidade.
  2. Eu tenho que usar o ' operador splat ' (não o nome real), para extrair os elementos do objeto permutations(...). Caso contrário, o conjunto ( {...}) conteria apenas um elemento, o próprio objeto.
  3. Eu uso um set ( {...}) para manter apenas permutações distintas dentro.

No Floroid, isso é (quase) z(T(a==aDKaIW(cb(L)))%666013), mas imprime o resultado e recebe entrada pela linha de comando.

Agradecemos a Jonathan Allan por salvar um byte! -> Mudou o importestilo

Experimente online!

Yytsi
fonte
3

Gelatina , 13 bytes

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

Experimente online!

Quão?

Um forçador 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

Eu acredito que isso vai fazê-lo de forma mais eficiente, mas é 30 bytes (edit: esse pdf parece confirmar isso, cortesia de resposta das LME ):

Ñ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
fonte
Sim, o %mod é mod.
Jonathan Allan
Gah, eu estava prestes a postar exatamente essa resposta, mas não cheguei a tempo porque postou a resposta Brachylog primeiro. Uma questão de segundo, eu acho. Claramente, devo lembrar que Jelly é uma linguagem mais popular que Brachylog e, portanto, devo trabalhar primeiro nessa submissão.
Uau, byte por byte? Eu tenho outros 13 também, mas acho que é um pouco menos eficiente :)
Jonathan Allan
O número está compactado em uma base diferente ou o quê? : P
Yytsi 22/02
Na minha guia TIO Œ!QŒḂ€S%“µɲ€’,. Parece bytewise idêntico para mim.
2

Mathematica, 46 bytes

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

Leva uma lista de caracteres como entrada.

Terrivelmente ineficiente, porque na verdade gera todas as permutações da entrada e depois conta as palindrômicas.

Martin Ender
fonte
Eu acho que isso incorretamente dá uma resposta positiva, em vez de 0, se a seqüência de caracteres tem várias letras que ocorrem com multiplicidade ímpar (como "abcdabcddddddeee").
Greg Martin
@GregMartin Obrigado, corrigido. Isso era desnecessariamente complicado de qualquer maneira.
Martin Ender
2

Mathematica, 68 bytes

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

Função pura pegando uma lista de caracteres como entrada e retornando um número inteiro. Não é tão curto quanto a resposta Mathematica de Martin Ender , mas é uma abordagem atraente, que parece ser a mesma abordagem da resposta Perl 6 do smls .

Primeiro, t=Last/@Tally@#/2calcula as contagens de todos os caracteres distintos na entrada, divididos por2 ; então i=Floorarredonda para baixo todas as frações que ocorrem t. Observe que as permutações palindrômicas da entrada existem exatamente quando existe no máximo um número ímpar entre as contagens originais, ou seja, quando há no máximo uma fração t. Podemos testar isso somando todos os elementos de t-i(using Tr): se a resposta for menor que 1, existem permutações palindrômicas, caso contrário não.

Se houver, irepresenta a contagem de caracteres distintos na metade esquerda das permutações, que podem ser organizadas arbitrariamente. O número de maneiras de fazer isso é exatamente oMultinomial coeficiente (um quociente de certos fatoriais) que o Mathematica incorporou.

Greg Martin
fonte
1

k, 23 bytes

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

Se estiver usando oK , ou cmbnão existir, use em prmvez de cmb.

zgrep
fonte
1

C ++ 14, 161 bytes

Como lambda sem nome, assumindo que a entrada é semelhante std::stringe retornando via parâmetro de referência.

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

Ungolfed e 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;
}
Karl Napf
fonte
1

Ruby, 67 57 52 59 caracteres

->s{s.chars.permutation.uniq.count{|t|t.reverse==t}%666013}
Dorian
fonte
Os envios do Codegolf devem ser programas / funções / lambdas apropriados, não trechos . Eu não sou um programador de Ruby, mas acho que você pode transformar isso em um lambda, envolvendo-o ->s{ }, não é?
SMLS
Além disso, com base na documentação , o (s.size)argumento não é redundante?
SMLS
1
Eu testei no Ruby 2.4 e funciona sem o .to_amesmo.
smls 23/02
@smls Não funciona no ruby ​​2.3.3 ( undefined method uniq 'para # <Enumerator`), mas funciona corretamente no ruby ​​2.4, obrigado :) #
317 Dorian
O resultado precisa ser obtido mod 666013?
NonlinearFruit
1

Japonês , 20 18 bytes

á f_¥Zw} l %666013

Economizou 2 bytes graças ao ETHproductions.

Experimente online!

Tom
fonte
Bom, é isso que eu teria feito. Você pode salvar dois bytes com f_¥Zw}, como _é a abreviação deZ{Z
ETHproductions
á fêS â l %666013economizaria um byte.
powelles 29/07
0

MATL, 13 bytes

Y@Xu!"@tP=Avs

Experimente no MATL Online

Explicação

        % 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
fonte
0

CJam , 19 bytes

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

Experimente online!

Explicação:

qe! {_ W% =}%: + 666013% e # Programa completo.
qe # Obtenha todas as informações.
 e! e # Obtenha todas as permutações exclusivas.
   {_W% =} e # Função para verificar se uma lista é um palíndromo.
    _ e # ToS duplicados.
     W% e # ToS reverso (Push -1, índice modular de ToS).
       = e # Verifique se ToS é igual a SToS.
         % e # Mapa.
          : + e # Sum (Reduzir por adição).
            666013 e # Pressione 666013.
                  % e # Módulo.

Erik, o Outgolfer
fonte
0

Ohm, 17 bytes

I⌐:_₧?¡;;¼,

Explicação:

I⌐:_₧?¡;;¼,  ■Main wire
I⌐:     ;    ■for _ in permutations(input()){
   _₧? ;     ■  if(palindrome(_)){
      ¡      ■    counter++;
       ;     ■  }
        ;    ■}
         ¼,  ■print(counter)
Roman Gräf
fonte
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);

Versão Online

Demolir

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
fonte