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


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.