Перерахуйте всі можливі унікальні поєднання літер у слові


12

Вам надається рядок, який буде містити звичайні символи az. (Ви можете припустити, що це завжди буде в будь-якому тесті, і припустити, що всі літери будуть також малі). Ви повинні визначити, скільки унікальних комбінацій може бути складено з окремих символів у рядку та надрукувати це число.

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

Найкоротший виграш байтів, з нетерпінням чекаю творчих рішень на мовах, що не належать до гольфу!

Приклади:

hello -> 60
aaaaa -> 1
abcde -> 120


4
@Giuseppe Я не вважаю, що це глуза; специфіка цього питання передбачає набагато коротші реалізації
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.


itertools дуже багатослівний у своїх назвах функцій
qwr



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виклику з невідомих причин.


2
function(s,! =factorial)(!nchar(s))/prod(!table(strsplit(s,""))) буду працювати. el () надлишковий - таблиця знає шукати елементи ....
Zahiro Mor

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
Shieru Asakoto

@ShieruAsakoto Назва змінена; рахувати набагато краще. Дякую, і приємна відповідь!
SimpleGeek








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

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

Досить прямий Whateverблок вперед . combрозбиває рядок на літери, permutationsотримує всі можливі комбінації. Через спосіб примусу Setпотрібно joinредагувати спочатку ( »стосується joinкожного елемента у списку).

+*.comb.permutations».join.Set

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

(попередня відповідь використана, .uniqueале Setгарантує унікальність, і чисельність однакова, тому вона економить 3).


2

K (oK) , 12 байт

Рішення:

#?x@prm@!#x:

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

Пояснення:

Використовується вбудований oK prm:

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

... що, в x^/:xосновному, генерує перестановки "helo"не "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 (#)

Чи є prm нормальним оператором? Я не думаю, що у ванілі k є?
Генрі Генрінсон

Так - існує тільки відповідно до ОК вручну
streetster

@HenryHenrinson afaik це не в k4. на початку k5 це було !-n. в кінці k5 і k6 це сталоprm . k7 (shakti) prmтеж.
ngn

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

Порт відповіді Python 2 @ArBo .
-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 Дякую! Btw, чи бачите ви щось, щоб другий підхід (генерування всіх унікальних перестановок у наборі) коротший? У мене є відчуття, що деякі байти можна зберегти, але спробував деякі речі, а більшість були трохи довші замість коротших .. Але це все ще виглядає занадто довгим tbh.
Kevin Cruijssen

Я працював над цим, намагаючись використовувати потоки і рахувати так: 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

Октава / 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повернулися унікальні рядки? Або це лише для tables?
Джузеппе

@Giuseppe Для числових / знакових 2D-масивів 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?
Ad Hoc Hunter Hunter

Так, хороша ідея, дякую.
Генрі Генрінсон

1
І, можливо, відредагуйте пояснення, щоб відобразити і цю зміну?
Сельчук

1

Мова Вольфрама (Mathematica) , 32 байти

Characters/*Permutations/*Length

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

Пояснення: Право-композиція з /*застосовує ці три оператори один за одним до аргументу функції зліва направо:

  • Characters перетворює рядок введення у список символів.

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

  • Length повертає довжину цього списку унікальних перестановок.

Цей метод є дуже марним для довгих рядків: унікальні перестановки фактично перераховані та підраховані, замість того, щоб використовувати Multinomialдля обчислення їх кількості без списку.



1

Pyth , 5 4 байти

l{.p

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

Це передбачає, що вхід є буквальним рядком python. Якщо для введення повинен бути необроблений текст, ця 5-байтна версія буде працювати:

l{.pz

Так чи інакше, він просто обчислює всі перестановки вхідних даних у вигляді списку, дедублює його та отримує кількість елементів у ньому та неявно друкує це число.

-1 байт завдяки @ hakr14


{виводить список на байт менше, ніж .{.
hakr14




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