Numero di permutazioni di stringa che sono palindromi


13

Il tuo input sarà una stringa composta da piccole lettere inglesi.

Il tuo compito è determinare il numero di permutazioni distinte della stringa originale che sono un palindromo.

La stringa di input ha fino a 100 lettere. Nel caso di una stringa più lunga il risultato potrebbe essere molto grande, quindi l'output dovrebbe essere il numero di permutazioni modulo 666013.

Per esempio,

cababaa -> 3

Le possibili permutazioni sono:

aabcbaa
abacaba
baacaab

Questo è , quindi vince la risposta più breve!


2
"Dato che la stringa ha fino a 100 cifre, il risultato deve essere% 666013." In tal caso, sarebbe una buona idea includere un caso di test corrispondente.
Martin Ender,

4
Non capisco la riga% 666013. Questa è una sfida promettente, però, e sarei disposto a votare per riaprire una volta spiegato.

12
Oh, ora che è stato modificato, vedo a cosa stai arrivando. Non credo che questa linea aumenti la sfida; punisce principalmente le lingue senza numeri interi di precisione arbitraria. Normalmente facciamo qualcosa del tipo "la risposta dovrebbe essere corretta se eseguita in una versione ipotetica della tua lingua con numeri interi illimitati".

7
Questo potrebbe davvero utilizzare più casi di test.
smls

3
Suggerimenti per casi di test (verificarli comunque): abcdabcddddd -> 120 (nessun conteggio dei caratteri dispari) , abcdabcdddddd -> 120 (un conteggio dei caratteri dispari) , abcdabcddddddeee -> 0 (due conteggi dei caratteri dispari) , aabbccddeeffgghhiijj -> 298735 (influenzato dal modulo) .
smls

Risposte:


5

Brachylog (2), 15 byte

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

Provalo online!

Spiegazione

{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
Devo assolutamente implementare quel "trova unico" ...
Fatalizza il

2
@Fatalize: Sì! Penso che anche il "conteggio unico" si verifichi abbastanza spesso nelle sfide da meritare forse una rappresentazione a 1 byte. D'altra parte, "modulo 666013" quasi certamente no ;-)

5

05AB1E , 17 16 13 byte

-1 byte da Jonathon Allan

-3 byte da Emigna e Adnan

œÙvyÂQO•E›j•%

Spiegazione:

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

Provalo online!


1
Il contenuto, E›jrappresenta le cifre [14, 116, 45]che vengono convertite dalla base 214e diventa 14*214^2 + 116*214 + 45 = 666013. Non sono sicuro di dove sia il riferimento per le cifre, ma sembrano essere in linea (ish?) Con il loro ordine nella pagina delle informazioni . @Adnan potrebbe illuminarci.
Jonathan Allan,

1
@Emigna Facile quando conosci la lingua: D
Jonathan Allan,

1
Puoi salvare 2 byte rimuovendo l'istruzione if poiché hai comunque solo i valori necessari nello stack:œÙvyÂQ}O•E›j•%
Emigna

2
@JonathanAllan La gamma completa di cifre (e caratteri) è disponibile qui :).
Adnan,

1
Sulla @ commento di Emigna, è possibile salvare un altro byte togliendo la parentesi di chiusura: œÙvyÂQO•E›j•%.
Adnan,

4

Perl 6 , 104 108 88 84 byte

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

Provalo online!

Come funziona

Non riesco facilmente a generare tutte le permutazioni e a filtrarle, anche se i runtime astronomici sono consentiti, poiché la permutationsroutine di routine incorporata di Perl 6 si rifiuta di consentire elenchi di oltre 20 elementi e la descrizione dell'attività richiede input fino a 100 personaggi.

Quindi, invece, utilizzo una formula diretta basata sulle frequenze delle lettere dell'input:

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

    Una funzione di supporto che dimezza un numero e lo arrotonda al numero intero più vicino, quindi ne prende il fattoriale.

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

    Calcola le frequenze delle lettere nella stringa di input e rendile l' argomento per il resto del codice. Ad esempio per l'input abcdabcddddddquesta sarebbe la lista (2, 2, 2, 7).

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

    Se è presente più di una frequenza di lettere dispari, moltiplicare il risultato per zero, poiché in questo caso non sono possibili palindromi.

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

    Calcola il numero di possibili permutazioni dei caratteri che saranno su "un lato" di ogni palindromo (che corrisponde a un multiset con le molteplicità ottenute dimezzando e pavimentando le frequenze delle lettere di input) . La formula utilizzata è tratta da questo PDF :
    (n 1 + ... + n k )! / (n 1 ! ⋅ ... ⋅n k 1)
    Ad esempio per le frequenze (2,2,2,7)delle lettere di input , le lettere su un lato del palindromo formano un multiset con molteplicità (1,1,1,3), e quindi il numero di permutazioni è (1+1+1+3)! / (1!⋅1!⋅1!⋅3!) = 120.

  5. % 666.013

    Prendi il risultato modulo 666013.


Bello vedere che il mio metodo alternativo è valido!
Jonathan Allan,

3

Python3, 81 80 byte

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

Questo è il più breve che potrei inventare. Non sono sicuro che le permutazioni possano essere generate più facilmente ...

Spiegazione

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.

Appunti

  1. Il controllo a==a[::-1]restituisce un valore booleano, ma la sum(...)funzione lo cast implicitamente su un numero intero (0 o 1) e somma di conseguenza.
  2. Devo usare l ' " operatore splat " (non il vero nome), per estrarre gli elementi dall'oggetto permutations(...). Altrimenti il ​​set ( {...}) conterrebbe solo un elemento, l'oggetto stesso.
  3. Uso un set ( {...}) per mantenere solo permutazioni distinte all'interno.

In Floroid, questo è (quasi) z(T(a==aDKaIW(cb(L)))%666013), ma stampa invece il risultato e accetta input dalla riga di comando.

Grazie a @Jonathan Allan per aver salvato un byte! -> Modificato lo importstile

Provalo online!


3

Gelatina , 13 byte

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

Provalo online!

Come?

Un forcer brutale.

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

Io credo che questo lo farà in modo più efficiente, ma è di 30 byte (edit: questo pdf sembra confermare che, per gentile concessione di risposta di 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ì sì, %è mod.
Jonathan Allan,

Gah, stavo per pubblicare esattamente questa risposta, ma non ci sono arrivato in tempo perché ho pubblicato prima la risposta di Brachylog. Una questione di secondo, penso. Chiaramente dovrei ricordare che Jelly è una lingua più popolare di Brachylog e quindi dovrei lavorare prima su quella proposta.

Wow, byte per byte? Ne ho anche altri 13, ma penso che sia leggermente meno efficiente :)
Jonathan Allan il

Il numero è compresso in una base diversa o cosa? : P
Yytsi,

Dalla mia scheda TIO, Œ!QŒḂ€S%“µɲ€’. Sembra identico a me per byte.

2

Mathematica, 46 byte

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

Accetta un elenco di caratteri come input.

Terribilmente inefficiente, perché in realtà genera tutte le permutazioni dell'input e quindi conta quelle palindromiche.


Penso che questo dia erroneamente una risposta positiva, piuttosto che 0, se la stringa ha più lettere che si verificano con strana molteplicità (come "abcdabcddddddeee").
Greg Martin,

@GregMartin Grazie, risolto. Ciò è stato inutilmente complicato comunque.
Martin Ender,

2

Mathematica, 68 byte

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

Funzione pura che prende un elenco di caratteri come input e restituisce un numero intero. Non breve come la risposta di Mathematica di Martin Ender , ma è comunque un approccio carino, che sembra essere lo stesso approccio della risposta Perl 6 di smls .

Innanzitutto, t=Last/@Tally@#/2calcola i conteggi di tutti i caratteri distinti nell'input, divisi per 2; quindi i=Floorarrotonda per difetto tutte le frazioni che si verificano in t. Si noti che le permutazioni palindromiche dell'input esistono esattamente quando c'è al massimo un numero dispari tra i conteggi originali, cioè quando c'è al massimo una frazione in t. Possiamo provarlo semplicemente sommando tutti gli elementi di t-i(usando Tr): se la risposta è inferiore a 1, ci sono permutazioni palindromiche, altrimenti no.

Se ci sono, quindi irappresenta i conteggi di caratteri distinti nella metà sinistra delle permutazioni, che possono essere organizzati in modo arbitrario. Il numero di modi per farlo è esattamente il Multinomialcoefficiente (un quoziente di alcuni fattoriali), che Mathematica ha incorporato.


1

k, 23 byte

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

Se si utilizza oK o cmbnon esiste, utilizzare prminvece di cmb.



1

C ++ 14, 161 byte

Come lambda senza nome, supponendo che l'input sia simile std::stringe che ritorni tramite il parametro di riferimento.

#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 utilizzo:

#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

Rubino, 67 57 52 59 caratteri

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

Le presentazioni di Codegolf dovrebbero essere programmi / funzioni / lambdas adeguati, non frammenti . Non sono un programmatore di Ruby, ma penso che puoi trasformarlo in un lambda avvolgendolo ->s{ }, vero?
smls

Inoltre, in base alla documentazione , l' (s.size)argomento non è ridondante?
smls

1
L'ho provato su Ruby 2.4 e funziona anche senza .to_a.
smls

@smls Non funziona su ruby ​​2.3.3 ( undefined method uniq 'per # <Enumerator`), ma funziona su ruby ​​2.4, grazie :)
Dorian,

Il risultato deve essere preso mod 666013?
NonlinearFruit

1

Japt , 20 18 byte

á f_¥Zw} l %666013

Risparmiato 2 byte grazie a ETHproductions.

Provalo online!


Bello, è quello che avrei fatto. È possibile salvare due byte con f_¥Zw}, come _è l'abbreviazione diZ{Z
ETHproductions

á fêS â l %666013ti farebbe risparmiare un byte.
Powelles,

0

MATL, 13 byte

Y@Xu!"@tP=Avs

Provalo su MATL Online

Spiegazione

        % 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 byte

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

Provalo online!

Spiegazione:

qe! {_ W% =}%: + 666013% e # Programma completo.
qe # Ottieni tutti gli input.
 e! e # Ottieni tutte le permutazioni uniche.
   {_W% =} e # Funzione per verificare se un elenco è un palindromo.
    _ e # Duplica ToS.
     W% e # Reverse ToS (Push -1, indice modulare di ToS).
       = e # Controlla se ToS è uguale a SToS.
         % e # Mappa.
          : + e # Sum (Riduci per aggiunta).
            666013 e # Push 666013.
                  % e # Modulo.


0

Ohm, 17 byte

I⌐:_₧?¡;;¼,

Spiegazione:

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

0

PHP, 182 byte

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

Versione online

Abbattersi

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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.