Подсчитайте все возможные уникальные комбинации букв в слове

12

Вам дана строка, которая будет содержать обычные символы z. (Вы можете предположить, что это всегда будет иметь место в любом тесте, и предположить, что все буквы также будут строчными). Вы должны определить, сколько уникальных комбинаций можно сделать из отдельных символов в строке, и распечатать это число.

Однако дублирующие буквы можно игнорировать при подсчете возможных комбинаций. Другими словами, если заданная строка является «привет», то просто переключение позиций двух ls не считается уникальной фразой и, следовательно, не может быть засчитано в общую сумму.

Побеждает самое короткое число байтов, с нетерпением ждем новых креативных решений на неигровых языках!

Примеры:

hello -> 60
aaaaa -> 1
abcde -> 120
SimpleGeek
источник
4
@ Джузеппе Я не думаю, что это обманка; специфика этого вопроса допускает гораздо более короткие реализации
ArBo
4
Добавление некоторых тестовых случаев может помочь.
TSH
1
@JonathanAllan Хорошее предложение! Название изменилось соответственно.
SimpleGeek

Ответы:

29

Python 2 , 50 48 байтов

f=lambda s:s==''or len(s)*f(s[1:])/s.count(s[0])

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

Нет скучных встроенных модулей! К моему удивлению, это даже короче, чем метод грубой силы, вычисляющий все перестановки с itertoolsучетом длины.

Эта функция использует формулу

# of unique permutations=(# of elements)!unique elements(# of occurences of that element)!

и вычисляет это на лету. Факториал в числителе рассчитывается путем умножения на len(s)в каждом вызове функции. Знаменатель немного более тонкий; в каждом вызове мы делим на число вхождений этого элемента в том, что осталось от строки, обеспечивая, чтобы для каждого символа cвсе числа между 1 и количеством вхождений c(включительно) были разделены ровно один раз. Поскольку мы делим только в самом конце, у нас гарантированно не возникнет никаких проблем с делением по умолчанию в Python 2.

ARBO
источник
itertools очень многословен в своих именах функций
qwr
7

CJam , 4 байта

le!,

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

объяснение

Чтение строки в виде строки ( l), уникальные перестановки в виде массива строк ( e!), длина ( ,), неявное отображение.

Луис Мендо
источник
4
Выглядит как "лель", +1! : D
KeyWeeUsr
5

R , 69 65 байт

function(s,`!`=factorial)(!nchar(s))/prod(!table(strsplit(s,"")))

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

4 байта сохранены благодаря Захиро Мор в обоих ответах.

Вычисляет коэффициент многочлена напрямую.

R , 72 68 байт

function(s,x=table(strsplit(s,"")))dmultinom(x,,!!x)*sum(1|x)^sum(x)

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

Использует полиномиальную функцию распределения, предоставленную dmultinomдля извлечения полиномиального коэффициента.

Обратите внимание, что обычный (игрок в гольф) x<-table(strsplit(s,""))не работает внутри dmultinomзвонка по неизвестной причине.

Giuseppe
источник
2
function(s,! =factorial)(!nchar(s))/prod(!table(strsplit(s,""))) буду работать. el () является избыточным - таблица знает, как искать элементы ....
Захиро Мор
1
@ ZahiroMor ах, конечно. Я намеревался проверить это, но так и не удосужился.
Джузеппе
5

JavaScript (Node.js) , 49 байт

t=t*используется вместо того, t*=чтобы избежать ошибки округления (округления |tдо числа), поскольку t=t*гарантирует, что все промежуточные (операторные) результаты являются целыми числами.

a=>[...a].map(g=x=>t=t*y++/(g[x]=-~g[x]),t=y=1)|t

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

a=>
 [...a].map(        // Loop over the characters
  g=x=>
   t=t*             // using t*= instead may result in rounding error 
    y++             // (Length of string)!
    /(g[x]=-~g[x])  // divided by product of (Count of character)!
  ,t=y=1            // Initialization
 )
 |t
Сиеру Асакото
источник
2
(Потенциальная ошибка округления с плавающей точкой; используйте, t=t*если хотите избежать этого.)
Нейл
@Neil Да, это не удалось, когда ввод произошел aaadegfbbbcccименно из-за ошибки округления с плавающей точкой
Shieru Asakoto
А как ты нашел этот тест?
Нил
@Neil Продолжайте добавлять символы в строку до тех пор, пока не произойдет такая ошибка округления.
Lol
@ShieruAsakoto Название было изменено; считать намного лучше. Спасибо и хороший ответ!
SimpleGeek
4

Japt , 5 3 байта

-2 байта благодаря @Shaggy

á l

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

Луис Фелипе Де Иисус Муньос
источник
TIO, кажется, работает на старой версии Japt, что позволяет отказаться от â.
Лохматый
@ Shaggy Lol, я этого не заметил. благодаря!
Луис Фелипе Де Иисус Муньос
2

APL (Dyalog Unicode) , 24 байта

CY'dfns'
{≢∪↓⍵[pmat≢⍵]}

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

Простой Dfn, принимает строку в качестве аргумента.

Как:

CY'dfns'       Copies the 'dfns' namespace.
{≢∪↓⍵[pmat≢⍵]}  Main function
          ≢⍵    Number of elements in the argument (⍵)
      pmat      Permutation Matrix of the range [1..≢⍵]
    ⍵[      ]   Index the argument with that matrix, which generates all permutations of 
               Convert the matrix into a vector of strings
               Keep only the unique elements
               Tally the number of elements
Ж. Салле
источник
2

Рубин , 41 байт

f=->s{s.chars.permutation.to_a.uniq.size}

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

thowawayacc89023489
источник
1
Я не думаю, что вам нужноto_a
ArBo
1
И анонимные функции / лямбда-выражения приемлемы, так что вы можете удалить f=часть. (В TIO переместите его в заголовок, чтобы его не засчитали.)
manatwork
2

Perl 6 , 33 30 символов ( 34 31 байт)

Довольно прямолинейный Whateverблок. combразбивает строку на буквы, permutationsполучает все возможные комбинации. Из-за способа принуждения Setнужно joinсначала »редактировать ( применяется joinк каждому элементу в списке).

+*.comb.permutations».join.Set

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

(использовался предыдущий ответ, .uniqueно Sets гарантирует уникальность и нумерует то же самое, поэтому сохраняет 3).

user0721090601
источник
2

K (ок) , 12 байт

Решение:

#?x@prm@!#x:

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

Объяснение:

Использует встроенный ОК prm:

{[x]{[x]$[x;,/x ,''o'x ^/:x;,x]}@$[-8>@x;!x;x]}

... который, в x^/:xосновном, генерирует перестановки "helo"not "hello", следовательно, нам нужно генерировать перестановки 0 1 2 3 4, использовать их для индексации, "hello"а затем считать количество уникальных.

#?x@prm@!#x: / the solution
          x: / store input as x
         #   / count (#) length
        !    / range (!) 0..n
    prm@     / apply (@) to function prm
  x@         / apply permutations to input x
 ?           / take the distinct (?)
#            / count (#)
streetster
источник
Prm нормально определенный оператор? Я не думаю, что Vanilla K имеет это?
Генри Хенринсон
Да - существует только в соответствии с ОК вручную
streetster
@HenryHenrinson afaik это не в k4. в начале к5 было !-n. в конце к5 и к6 сталоprm . К7 (Шакти) prmтоже.
нгн
2

Java 8, 103 102 байта

s->{int r=1,i=s.length();for(;i>0;)r=r*i/~-s.substring(--i).split(s.charAt(i)+"",-1).length;return r;}

Порт ответа @ArBo 's Python 2 .
-1 байт благодаря @ OlivierGrégoire , сделав его итеративным, а не рекурсивным.

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

Фактически генерация всех уникальных перестановок в наборе и получение его размера будет 221 байт :

import java.util.*;s->{Set S=new HashSet();p(s,S,0,s.length()-1);return S.size();}void p(String s,Set S,int l,int r){for(int i=l;i<=r;p(s.replaceAll("(.{"+l+"})(.)(.{"+(i++-l)+"})(.)(.*)","$1$4$3$2$5"),S,l+1,r))S.add(s);}

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

Кевин Круйссен
источник
Хорошо, я мог бы гольфы байт, сделав его итерационный вместо рекурсивного: s->{int r=1,i=s.length();for(;i>0;)r=r*i/~-s.substring(--i).split(s.charAt(i)+"",-1).length;return r;}.
Оливье Грегуар
@ OlivierGrégoire Спасибо! Кстати, вы видите что-то, чтобы сделать второй подход (создание всех уникальных перестановок в наборе) короче? Я чувствую, что некоторые байты могут быть сохранены, но пробовали некоторые вещи, и большинство из них были немного длиннее, а не короче. Но это все равно выглядит слишком длинным.
Кевин Круйссен
Я работал над этим, пытаясь использовать потоки и считать, как это: s->{long r=1,i=s.length();for(;i>0;)r=r*i/(s.chars().skip(--i).filter(c -> c==s.charAt(i)).count()+1);return r;} но пока безуспешно ...
Оливье Грегуар
1

MATL , 9 байт

jY@XuZy1)

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

Объяснение:

j input as string
Y@ get permutations
Xu unique members
Zy size matrix
1) first member of size matrix
OrangeCherries
источник
2
Вы можете взять ввод с кавычками, так jстановится i, который можно оставить неявным. Кроме того, &nxсохраняет байт в течение Zy1) tio.run/##y00syfn/P9IholQtr@L/f/WM1JycfHUA
Луис Мендо
1

Октава / MATLAB, 35 байт

@(s)size(unique(perms(s),'rows'),1)

Анонимная функция, которая принимает символьный вектор и создает число.

В MATLAB это можно сократить до size(unique(perms(s),'ro'),1)(33 байта).

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

объяснение

@(s)                                  % Anonymous function with input s
                perms(s)              % Permutations. Gives a char matrix
         unique(        ,'rows')      % Deduplicate rows
    size(                       ,1)   % Number of rows
Луис Мендо
источник
1
Я думал, что uniqueвернулся уникальные строки уже? Или это только для tableс?
Джузеппе
@Giuseppe Для числовых / char двумерные массивы uniqueбудут линеаризованы первыми. Для таблиц я думаю, что вы правы; Я этого не знал!
Луис Мендо
1
Ах, я знаю, откуда у меня возникла идея - uniqueв MATLAB для этого нужны строки tables; R uniqueпринимает уникальные строки матриц или фреймы данных. Слишком много языков массивов с одними и теми же командами, которые делают немного разные вещи ...
Джузеппе
1

Сетчатка 0.8.2 , 73 байта

(.)(?=(.*?\1)*)
/1$#2$*1x1$.'$*
^
1
+`1(?=1*/(1+)x(\1)+$)|/1+x1+$
$#2$*
1

Попробуйте онлайн! Использует формулу @ ArBo, но оценивает справа налево, поскольку это можно сделать в целочисленной арифметике, при этом минимизируя размер участвующих унарных значений. Объяснение:

(.)(?=(.*?\1)*)
/1$#2$*1x1$.'$*

Для каждого символа подсчитайте, сколько осталось дубликатов и сколько еще символов, добавьте по одному каждому для учета текущего символа и разделите значения, чтобы мы знали, какие из них следует разделить, а какие - умножить. ,

^
1

Префикс 1 для создания полного выражения.

+`1(?=1*/(1+)x(\1)+$)|/1+x1+$
$#2$*

Повторно умножайте последние и третьи последние числа, делясь на второе последнее число. Это заменяет последние три числа.

1

Преобразовать в десятичную.

Нил
источник
1

К, 27 байт

*/[1+!#:x]%*/{*/1+!x}'#:'x:

К, 16 байт - не реальный ответ

#?(999999#0N)?\:

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

Улучшено благодаря @Sriotchilism O'Zaic, @Selcuk

Генри Хенринсон
источник
2
Добро пожаловать на сайт! Действительно ли не имеет значения , поскольку он является недействительным , но не могли бы вы сделать ваш недопустимый ответ более точным, используя 999999вместо 100000?
Специальный охотник на Гарф
Да, хорошая идея, спасибо.
Генри Хенринсон
1
И, возможно, изменить объяснение, чтобы отразить это изменение тоже?
Сельчук
1

Wolfram Language (Mathematica) , 32 байта

Characters/*Permutations/*Length

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

Объяснение: Композиция справа с /*применяет эти три оператора один за другим к аргументу функции слева направо:

  • Characters преобразует входную строку в список символов.

  • Permutations делает список всех уникальных перестановок этого списка символов.

  • Length возвращает длину этого списка уникальных перестановок.

Этот метод очень расточителен для длинных строк: уникальные перестановки фактически перечислены и подсчитаны, вместо того, чтобы использовать их Multinomialдля вычисления их числа без перечисления.

Роман
источник
1

Pyth , 5 4 байта

l{.p

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

Это предполагает, что ввод является строковым литералом Python. Если ввод должен быть необработанным текстом, эта 5-байтовая версия будет работать:

l{.pz

В любом случае, он просто вычисляет все перестановки входных данных в виде списка, дедуплицирует его, получает количество элементов в нем и неявно печатает это число.

-1 байт благодаря @ hakr14

randomdude999
источник
{дедуплицирует список для байта меньше, чем .{.
hakr14
1

J , 14  13 байт

#(%*/)&:!#/.~

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

1 байт благодаря милям

#                  length
         #/.~      counts of each unique character
 (%*/)             divide left by the product of right
      &:!          after applying ! to both
FrownyFrog
источник
1
#(%*/)&:!#/.~должен сохранить другие байты
мили