Кількість рядкових перестановок, які є паліндромами


13

Вашим вкладом буде рядок, що складається з маленьких англійських букв.

Ваше завдання - визначити кількість чітких перестановок оригінального рядка, який є паліндром.

Вхідний рядок містить до 100 літер. У випадку більш тривалого рядка результат може бути дуже великим, тому вихід повинен бути кількістю перестановок по модулю 666013.

Наприклад,

cababaa -> 3

Можливі перестановки:

aabcbaa
abacaba
baacaab

Це , тому найкоротша відповідь виграє!


2
"Враховуючи, що рядок має до 100 цифр, результат повинен бути% 666013." Якщо так, то було б корисно включити відповідний тестовий випадок.
Мартін Ендер

4
Я не розумію рядок% 666013. Однак це є багатообіцяючим завданням, і я хотів би проголосувати за повторне відкриття, як тільки це буде пояснено.

12
О, зараз це було відредаговано, я бачу, до чого ти звертаєшся. Я не думаю, що ця лінія не викликає труднощів; він здебільшого просто карає мови без довільних точних цілих чисел. Зазвичай ми робимо щось на кшталт "відповідь має бути правильною, якщо працювати в гіпотетичній версії вашої мови з необмеженими цілими числами".

7
Це дійсно може використовувати більше тестових випадків.
smls

3
Пропозиції для тестових випадків (будь-ласка, перевірте їх): abcdabcddddd -> 120 (немає непарних підрахунків символів) , abcdabcdddddd -> 120 (один непарний кількість символів) , abcdabcddddddeee -> 0 (два непарні символи) , aabbccddeeffgghhiijj -> 298735 (впливає модуль) .
smls

Відповіді:


5

Брахілог (2), 15 байт

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

Спробуйте в Інтернеті!

Пояснення

{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
Мені, безумовно, потрібно втілити те, що "знайти унікальне" ...
Підтвердити

2
@Fatalize: Так! Я думаю, що навіть "підрахунок унікального" трапляється досить часто у викликах, щоб, можливо, вартувати 1-байтове представлення. З іншого боку, "modulo 666013" майже точно не відповідає ;-)

5

05AB1E , 17 16 13 байт

-1 байт від Джонатана Аллана

-3 байти від Еміньї та Аднана

œÙvyÂQO•E›j•%

Пояснення:

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

Спробуйте в Інтернеті!


1
Зміст, E›jявляє собою цифри [14, 116, 45], перетворені з бази 214, і стає 14*214^2 + 116*214 + 45 = 666013. Я не зовсім впевнений, де посилання на цифри, але вони, здається, відповідають їхньому порядку на інформаційній сторінці . @Adnan може нас освітити.
Джонатан Аллан

1
@Emigna Легко, коли знаєш мову: D
Джонатан Аллан

1
Ви можете зберегти 2 байти, видаливши if-оператор, оскільки у стеку в будь-якому випадку є лише необхідні значення:œÙvyÂQ}O•E›j•%
Emigna

2
@JonathanAllan Повний набір цифр (та символів) можна знайти тут :).
Аднан

1
Спираючись на @ коментар Emigna, ви можете зберегти ще один байт, видаливши дужку: œÙvyÂQO•E›j•%.
Аднан

4

Perl 6 , 104 108 88 84 байт

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

Спробуйте в Інтернеті!

Як це працює

Я не можу легко генерувати всі перестановки і фільтрувати їх, навіть якщо дозволені астрономічні періоди виконання, тому що вбудована програма Perl 6 permutationsвідмовляється переставляти списки з більш ніж 20 елементів, а опис завдання вимагає введення до 100 символів.

Тому замість цього я використовую пряму формулу, засновану на частотах букв введення:

  1. мій & f = {[*] 1 .. $ _ div 2}

    Допоміжна функція, яка вдвічі зменшує число і округляє його до найближчого цілого числа, а потім бере фактор цього числа.

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

    Обчистіть частоту букв у рядку введення та зробіть їх темою для решти коду. Наприклад, для введення abcdabcddddddце був би список (2, 2, 2, 7).

  3. (2> .греп (*% 2)) *

    Якщо є більше однієї непарної літери частоти, помножте результат на нуль, тому що в цьому випадку не можливі паліндри.

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

    Обчисліть кількість можливих перестановок символів, які будуть знаходитись на "одній стороні" кожного паліндрому (що відповідає мультисету з множинами, отриманими вдвічі та настилом частот вхідних літер) . Формула, що використовується, з цього PDF :
    (n 1 + ... + n k )! / (n 1 ! ⋅ ... ⋅n k 1)
    Напр. для частоти вхідних (2,2,2,7)літер букви на одній стороні паліндром утворюють мультисети з кратністю (1,1,1,3), і кількість перестановок таким чином (1+1+1+3)! / (1!⋅1!⋅1!⋅3!) = 120.

  5. % 666013

    Візьміть результат по модулю 666013.


Приємно бачити, що мій альтернативний метод діє!
Джонатан Аллан

3

Python3, 81 80 байт

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

Це найкоротший, який я міг придумати. Не впевнений, чи можна перестановки генерувати легше ...

Пояснення

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.

Примітки

  1. Перевірка a==a[::-1]повертає булеве значення, але sum(...)функція неявно перекидає її на ціле число (0 або 1) і підсумовує відповідно.
  2. Мені доводиться використовувати оператор splat (не справжнє ім'я), щоб витягти елементи з об'єкта permutations(...). Інакше набір ( {...}) міститиме лише один елемент, сам об’єкт.
  3. Я використовую набір ( {...}), щоб зберігати лише окремі перестановки всередині.

У Floroid це (майже) z(T(a==aDKaIW(cb(L)))%666013), але друкує результат замість цього та здійснює введення через командний рядок.

Дякуємо @Jonathan Allan за збереження байта! -> Змінив importстиль

Спробуйте в Інтернеті!


3

Желе , 13 байт

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

Спробуйте в Інтернеті!

Як?

Жорстокий форсер.

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

Я вірю, що це зробить це більш ефективно, але це 30 байт (редагувати: цей pdf, здається, підтверджує це, люб’язно відповідь 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.

Так, це, %мод.
Джонатан Аллан

Га, я ось-ось збирався опублікувати саме цю відповідь, але не потрапив туди вчасно, тому що першим я опублікував відповідь Брахілога. Справа в другому, я думаю. Ясно, що я повинен пам’ятати, що Jelly є більш популярною мовою, ніж Брахілог, і тому я повинен спершу попрацювати над цим уявленням.

Вау, байт за байт? У мене теж 13, але думаю, що це трохи менш ефективно :)
Джонатан Аллан

Чи число стиснене в іншій базі чи що? : P
Yytsi

З моєї вкладці Тіо Œ!QŒḂ€S%“µɲ€’. Це виглядає на два рази однаково мені.

2

Математика, 46 байт

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

Візьме список символів як вхідний.

Страшенно неефективно, тому що він фактично генерує всі перестановки вхідних даних і потім підраховує паліндромні.


Я думаю, що це неправильно дає позитивну відповідь, а не 0, якщо рядок має кілька літер, що зустрічаються з непарною кратністю (як "abcdabcddddddeee").
Грег Мартін

@GregMartin Спасибі, виправлено. Це все одно було складно.
Мартін Ендер

2

Математика, 68 байт

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

Чиста функція, що приймає список символів як вхідний і повертає ціле число. Не такий короткий, як відповідь Mathematica Мартіна Ендера , але все-таки милий підхід, який здається таким же підходом, як і у відповіді Perl 6 smls .

По-перше, t=Last/@Tally@#/2обчислює підрахунок усіх окремих символів у введенні, поділених на 2; потім i=Floorокругляє будь-які дроби, що трапляються в t. Зауважте, що паліндромні перестановки вхідних даних існують саме тоді, коли серед початкових підрахунків є щонайменше одне непарне число, тобто коли в ньому є щонайбільше один дріб t. Ми можемо перевірити це, просто додавши всі елементи t-i(використовуючи Tr): якщо відповідь менше 1, є паліндромні перестановки, інакше ні.

Якщо вони є, то iпредставляється кількість відрізних символів у лівій половині перестановок, які можна розташувати довільно. Кількість способів зробити це саме Multinomialкоефіцієнт (коефіцієнт певних факторіалів), який вбудував Mathematica.


1

k, 23 байти

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

Якщо ви використовуєте oK або cmbне існує, використовуйте prmзамість cmb.



1

C ++ 14, 161 байт

Як безіменна лямбда, якщо припустити, що вхід подібний std::stringі повертається за допомогою еталонного параметра.

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

Безголівки та використання:

#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

Рубі, 67 57 52 59 ч

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

Подання Codegolf повинні бути належними програмами / функціями / лямбдами, а не фрагментами . Я не програміст Рубі, але я думаю, ви можете перетворити це на лямбда, загорнувши його ->s{ }, чи не так?
smls

Також, виходячи з документації , (s.size)аргумент не є зайвим?
smls

1
Я тестував його на Ruby 2.4, і він працює і без того .to_a.
smls

@smls Не працює на рубіні 2.3.3 ( undefined method uniq 'для # <Перелік], але правильно, він працює на рубіні 2.4, дякую :)
Доріан,

Чи потрібно брати результат mod 666013?
Нелінійний


0

MATL, 13 байт

Y@Xu!"@tP=Avs

Спробуйте в MATL Online

Пояснення

        % 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 байт

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

Спробуйте в Інтернеті!

Пояснення:

qe! {_ W% =}%: + 666013% e # Повна програма.
qe # Отримати всі дані.
 е! e # Отримайте всі унікальні перестановки.
   {_W% =} e # Функція, щоб перевірити, чи є список паліндром.
    _ e # Дублікат ToS.
     W% e # Зворотний ToS (Push -1, Модульний індекс ToS).
       = e # Перевірте, чи ToS дорівнює SToS.
         % e # Карта.
          : + e # сума (зменшити на додавання).
            666013 е # Push 666013.
                  % e # Модуло.


0

Ом, 17 байт

I⌐:_₧?¡;;¼,

Пояснення:

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

0

PHP, 182 байт

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

Інтернет-версія

Зламатися

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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.