Jumlah permutasi string yang merupakan palindrom


13

Masukan Anda akan berupa string yang terdiri dari huruf-huruf bahasa Inggris kecil.

Tugas Anda adalah untuk menentukan jumlah permutasi yang berbeda dari string asli yang merupakan palindrom.

String input memiliki hingga 100 huruf. Dalam kasus string yang lebih panjang hasilnya mungkin sangat besar sehingga output harus berupa jumlah permutasi modulo 666013.

Sebagai contoh,

cababaa -> 3

Permutasi yang mungkin adalah:

aabcbaa
abacaba
baacaab

Ini , jadi jawaban terpendek menang!


2
"Mengingat bahwa string memiliki hingga 100 digit, hasilnya harus% 666013." Jika demikian, merupakan ide bagus untuk memasukkan test case yang sesuai.
Martin Ender

4
Saya tidak mengerti baris% 666013. Ini adalah tantangan yang menjanjikan, dan saya bersedia memilih untuk membuka kembali begitu dijelaskan.

12
Oh, sekarang sudah diedit, saya mengerti apa yang Anda maksud. Saya tidak berpikir garis itu menambah tantangan; sebagian besar hanya menghukum bahasa tanpa bilangan bulat presisi arbitrer. Biasanya kami melakukan sesuatu seperti "jawabannya harus benar jika dijalankan dalam versi hipotetis bahasa Anda dengan bilangan bulat tak terikat".

7
Ini benar-benar dapat menggunakan lebih banyak kasus uji.
smls

3
Saran untuk kasus uji (harap verifikasi meskipun): abcdabcddddd -> 120 (tidak ada jumlah karakter ganjil) , abcdabcdddddd -> 120 (satu jumlah karakter ganjil) , abcdabcddddddeee -> 0 (dua jumlah karakter ganjil) , aabbccddeeffgghhiijj -> 298735 (dipengaruhi oleh modulo) .
smls

Jawaban:


5

Brachylog (2), 15 byte

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

Cobalah online!

Penjelasan

{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
Saya pasti perlu mengimplementasikan "temukan keunikan" itu ...
Fatalkan

2
@Fatalize: Ya! Saya pikir bahkan "menghitung unik" cukup sering terjadi dalam tantangan untuk mungkin bernilai representasi 1 byte. Di sisi lain, "modulo 666013" hampir pasti tidak ;-)

5

05AB1E , 17 16 13 byte

-1 byte dari Jonathon Allan

-3 byte dari Emigna dan Adnan

œÙvyÂQO•E›j•%

Penjelasan:

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

Cobalah online!


1
Konten,, E›jmewakili digit [14, 116, 45]yang dikonversi dari basis 214, dan menjadi 14*214^2 + 116*214 + 45 = 666013. Saya tidak yakin di mana referensi untuk digit, tetapi mereka tampaknya sejalan (ish?) Dengan pesanan mereka di halaman info . @Adnan dapat mencerahkan kami.
Jonathan Allan

1
@Emigna Mudah ketika Anda tahu bahasa: D
Jonathan Allan

1
Anda dapat menyimpan 2 byte menghapus pernyataan-if karena Anda hanya memiliki nilai-nilai yang diperlukan pada stack anyways:œÙvyÂQ}O•E›j•%
Emigna

2
@JonathanAllan Berbagai digit (dan karakter) dapat ditemukan di sini :).
Adnan

1
Membangun @ komentar Emigna, Anda dapat menyimpan byte lain dengan menghapus braket penutupan: œÙ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}}

Cobalah online!

Bagaimana itu bekerja

Saya tidak dapat dengan mudah menghasilkan semua permutasi dan memfilternya, bahkan jika run-time astronomi diizinkan, karena built-in Perl 6 permutations operasi langsung-lurus rutin menolak untuk mengubah daftar dari lebih dari 20 elemen dan deskripsi tugas memerlukan input hingga 100 karakter.

Jadi alih-alih saya menggunakan rumus langsung berdasarkan frekuensi huruf dari input:

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

    Fungsi helper yang membagi dua angka dan membulatkannya ke bilangan bulat terdekat, dan kemudian mengambil faktorial dari itu.

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

    Hitung-hitung frekuensi huruf dalam string masukan, dan jadikan itu topik untuk sisa kode. Misalnya untuk input, abcdabcddddddini akan menjadi daftar (2, 2, 2, 7).

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

    Jika ada lebih dari satu frekuensi huruf ganjil, gandakan hasilnya dengan nol, karena tidak ada palindrom yang memungkinkan dalam kasus tersebut.

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

    Hitung jumlah permutasi yang mungkin dari karakter yang akan berada di "satu sisi" dari masing-masing palindrome (yang sesuai dengan multiset dengan multiplisitas yang diperoleh dengan membagi dua dan meratakan frekuensi huruf input) . Rumus yang digunakan adalah dari PDF ini :
    (n 1 + ... + n k )! / (n 1 ! ⋅ ... ⋅n k 1)
    Misalnya untuk frekuensi huruf input (2,2,2,7), huruf-huruf di satu sisi palindrome membentuk multiset dengan banyak (1,1,1,3), dan jumlah permutasi demikian (1+1+1+3)! / (1!⋅1!⋅1!⋅3!) = 120.

  5. % 666013

    Ambil hasilnya modulo 666013.


Senang melihat bahwa metode alternatif saya valid!
Jonathan Allan

3

Python3, 81 80 byte

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

Ini adalah yang terpendek yang bisa saya lakukan. Tidak yakin apakah permutasi dapat dihasilkan dengan lebih mudah ...

Penjelasan

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.

Catatan

  1. Cek a==a[::-1]mengembalikan nilai boolean, tetapisum(...) fungsi secara implisit melemparkannya ke integer (0 atau 1) dan menjumlahkannya.
  2. Saya harus menggunakan ' operator percikan ' (bukan nama sebenarnya), untuk mengekstrak elemen dari objek permutations(...). Jika tidak diatur ({...} ) akan berisi hanya satu elemen, objek itu sendiri.
  3. Saya menggunakan set ( {...}) untuk menyimpan hanya permutasi yang berbeda di dalam.

Di Floroid, ini (hampir) z(T(a==aDKaIW(cb(L)))%666013), tetapi mencetak hasilnya sebagai gantinya, dan mengambil input melalui baris perintah.

Terima kasih kepada @Jonathan Allan karena telah menghemat satu byte! -> Mengubah importgaya

Cobalah online!


3

Jelly , 13 byte

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

Cobalah online!

Bagaimana?

Forcer kasar.

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

Saya percaya bahwa ini akan melakukannya dengan lebih efisien, tetapi 30 byte (sunting: pdf ini tampaknya mengonfirmasi hal itu, berkat jawaban 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.

Ya, %mod.
Jonathan Allan

Gah, aku baru saja hendak mengirim persis jawaban ini, tapi tidak sampai di sana dalam waktu karena saya diposting jawaban Brachylog pertama. Masalah kedua di dalamnya, saya pikir. Jelas saya harus ingat bahwa Jelly adalah bahasa yang lebih populer daripada Brachylog dan jadi saya harus mengerjakan kiriman itu terlebih dahulu.

Wow, byte demi byte? Saya punya 13 lagi juga, tapi pikir itu sedikit kurang efisien :)
Jonathan Allan

Apakah angka dikompresi di pangkalan yang berbeda atau apa? : P
Yytsi

Dari tab TIO saya Œ!QŒḂ€S%“µɲ€’,. Itu terlihat identik dengan saya.

2

Mathematica, 46 byte

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

Mengambil daftar karakter sebagai input.

Sangat tidak efisien, karena sebenarnya menghasilkan semua permutasi input dan kemudian menghitung yang palindromik.


Saya pikir ini salah memberikan jawaban positif, daripada 0, jika string memiliki beberapa huruf yang terjadi dengan multiplisitas ganjil (seperti "abcdabcddddddeee").
Greg Martin

@GregMartin Terima kasih, sudah diperbaiki. Lagipula ini tidak perlu rumit.
Martin Ender

2

Mathematica, 68 byte

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

Fungsi murni mengambil daftar karakter sebagai input dan mengembalikan integer. Tidak sesingkat jawaban Martin Ender's Mathematica , tapi tetap saja ini pendekatan yang imut, yang tampaknya merupakan pendekatan yang sama dengan jawaban Perl 6 dari smls .

Pertama, t=Last/@Tally@#/2hitung jumlah semua karakter berbeda dalam input, dibagi dengan 2; kemudian i=Floorbulatkan setiap pecahan yang terjadi di t. Perhatikan bahwa permutasi palindromic dari input ada persis ketika ada paling banyak satu angka ganjil antara jumlah yang asli, yaitu, ketika ada paling banyak satu fraksi di t. Kita dapat menguji untuk itu dengan hanya menambahkan semua elemen t-i(menggunakan Tr): jika jawabannya kurang dari 1, ada permutasi palindrom, jika tidak tidak.

Jika ada, maka imewakili jumlah karakter yang berbeda di bagian kiri permutasi, yang dapat diatur secara sewenang-wenang. Jumlah cara untuk melakukannya adalah persis Multinomialkoefisien (hasil bagi faktorial tertentu), yang telah dibangun oleh Mathematica.


1

k, 23 byte

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

Jika menggunakan oK , atau cmbtidak ada, gunakan prmsebagai ganti cmb.



1

C ++ 14, 161 byte

Sebagai lambda tanpa nama, anggaplah input seperti std::stringdan kembali melalui parameter referensi.

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

Tidak digabungkan dan digunakan:

#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 karakter

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

Pengajuan Codegolf harus berupa program / fungsi / lambdas yang tepat, bukan cuplikan . Saya bukan programmer Ruby, tapi saya pikir Anda bisa mengubahnya menjadi lambda dengan membungkusnya ->s{ }, bukan?
smls

Juga, berdasarkan pada dokumentasi , bukankah (s.size)argumen itu berlebihan?
smls

1
Saya mengujinya di Ruby 2.4, dan itu bekerja tanpa itu .to_ajuga.
smls

@smls Tidak berfungsi pada ruby ​​2.3.3 ( undefined method uniq 'untuk # <Enumerator`), tetapi benar itu bekerja pada ruby ​​2.4, terima kasih :)
Dorian

Apakah hasilnya harus diambil mod 666013?
NonlinearFruit

1

Japt , 20 18 byte

á f_¥Zw} l %666013

Disimpan 2 byte berkat produk ETH.

Cobalah online!


Bagus, itulah yang akan saya lakukan. Anda dapat menyimpan dua byte dengan f_¥Zw}, seperti _kependekan dariZ{Z
ETHproduksi

á fêS â l %666013akan menghemat satu byte.
powelles

0

MATL, 13 byte

Y@Xu!"@tP=Avs

Cobalah di MATL Online

Penjelasan

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

Cobalah online!

Penjelasan:

qe! {_ W% =}%: + 666013% e # Program lengkap.
qe # Dapatkan semua input.
 e! e # Dapatkan semua permutasi unik.
   {_W% =} e # Berfungsi untuk memeriksa apakah suatu daftar adalah palindrome.
    _ e # Duplikat ToS.
     W% e # Reverse ToS (Tekan -1, indeks Modular ToS).
       = e # Periksa apakah ToS sama dengan SToS.
         % e # Peta.
          : + e # Jumlah (Kurangi dengan penambahan).
            666013 e # Tekan 666013.
                  % e # Modulo.


0

Ohm, 17 byte

I⌐:_₧?¡;;¼,

Penjelasan:

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 Online

Kerusakan

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);
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.