Количество перестановок строк, которые являются палиндромами

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 (зависит от модуля) .
Смс

Ответы:

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
Мне определенно нужно реализовать это «найти уникальное» ...
Fatalize
2
@Fatalize: Да! Я думаю, что даже «считать уникальным» случается достаточно часто в задачах, чтобы стоить 1-байтовое представление. С другой стороны, «по модулю 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)

Попробуйте онлайн!

Okx
источник
1
Содержание, E›jпредставляет цифры, [14, 116, 45]которые преобразованы из базы 214, и становится 14*214^2 + 116*214 + 45 = 666013. Я не совсем уверен, где ссылка для цифр, но они, кажется, соответствуют (ish?) Их порядку на информационной странице . @Аднан может просветить нас.
Джонатан Аллан
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. my & f = {[*] 1 .. $ _ div 2}

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

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

    Подсчитайте частоты букв во входной строке и сделайте их темой для остальной части кода. Например, для ввода abcdabcddddddэто будет список(2, 2, 2, 7) .

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

    Если имеется более одной нечетной буквенной частоты, умножьте результат на ноль, потому что в этом случае палиндромы невозможны.

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

    Вычислите количество возможных перестановок символов, которые будут на «одной стороне» каждого палиндрома (что соответствует мультимножеству с кратностями, полученными путем деления пополам и сложения частот входных букв) . Используемая формула взята из этого 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.

SMLS
источник
Приятно видеть, что мой альтернативный метод действителен!
Джонатан Аллан
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. Я должен использовать « оператор сплат » (не настоящее имя), чтобы извлечь элементы из объекта permutations(...). В противном случае набор ({...} ) будет содержать только один элемент, сам объект.
  3. Я использую set ( {...}), чтобы хранить только различные перестановки внутри.

В Floroid это (почти) z(T(a==aDKaIW(cb(L)))%666013), но вместо этого печатает результат и получает ввод через командную строку.

Спасибо @Jonathan Allan за сохранение байта! -> поменял importстиль

Попробуйте онлайн!

Yytsi
источник
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 - более популярный язык, чем Brachylog, и поэтому я должен сначала поработать над этим представлением.
Вау, байт за байтом? У меня есть еще 13, но думаю, что это немного менее эффективно :)
Джонатан Аллан
Номер сжат в другой базе или как? : P
Yytsi
Из моей вкладки TIO Œ!QŒḂ€S%“µɲ€’. Это выглядит идентично для меня.
2

Mathematica, 46 байт

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

Принимает список символов в качестве входных данных.

Ужасно неэффективно, потому что фактически генерирует все перестановки входных данных, а затем подсчитывает палиндромные.

Мартин Эндер
источник
Я думаю, что это неправильно дает положительный ответ, а не 0, если строка состоит из нескольких букв, встречающихся с нечетной кратностью (как "abcdabcddddddeee").
Грег Мартин
@GregMartin Спасибо, исправлено. В любом случае это было слишком сложно.
Мартин Эндер
2

Mathematica, 68 байт

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

Чистая функция, принимающая список символов в качестве входных данных и возвращающая целое число. Не такой короткий, как ответ Mathematica Мартина Эндера , но, тем не менее, это симпатичный подход, который, похоже, такой же, как и в ответе Perls 6 от smls .

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

Если есть, то iпредставляет количество различных символов в левой половине перестановок, которые могут быть расположены произвольно. Число способов сделать это - это как раз Multinomialкоэффициент (фактор определенных факториалов), который встроен в Mathematica.

Грег Мартин
источник
1

к, 23 байта

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

Если вы используете ОК или cmbне существует, используйте prmвместо cmb.

zgrep
источник
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));}

Ungolfed и использование:

#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 должны быть правильными программами / функциями / лямбдами, а не фрагментами . Я не программист на Ruby, но я думаю, что вы можете превратить это в лямбду, завернув его ->s{ }, не так ли?
Смс
Кроме того, основываясь на документации , не является ли (s.size)аргумент избыточным?
Смс
1
Я тестировал его на Ruby 2.4, и он работает без него .to_a.
Смс
@smls Не работает на ruby ​​2.3.3 ( undefined method uniq 'для # <Enumerator`), но верно, работает на ruby ​​2.4, спасибо :)
Дориан,
Нужно ли брать результат mod 666013?
Нелинейные
1

Japt , 20 18 байт

á f_¥Zw} l %666013

Сохранено 2 байта благодаря ETHproductions.

Попробуйте онлайн!

Том
источник
Хорошо, вот что я бы сделал. Вы можете сохранить два байта с помощью f_¥Zw}, как _сокращенноZ{Z
ETHproductions
á fêS â l %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
Suever
источник
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 # Sum (Уменьшить путем сложения).
            666013 e # Push 666013.
                  % e # по модулю.

Эрик Outgolfer
источник
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);
Йорг Хюльсерманн
источник