Весело з перестановками


17

Хто абсолютно не любить перестановки, правда? Я знаю, вони дивовижні - так весело!

Ну чому б не взяти цю забаву і зробити її веселішою ?

Ось виклик:

Враховуючи вхід у точній формі:, nPrзвідки nвзятий пул і rкількість вибору з цього пулу ( nі rє цілими числами), виведіть / поверніть точну кількість перестановок. Для тих із вас, хто трохи іржавий термінологією: Перестановка, деф. 2а .

Однак тут грає виклик (робить це не надто просто):

Ви не можете використовувати будь-яку вбудовану бібліотеку, фреймворк або метод для своєї функції перестановки. Ви не можете використовувати факторний метод, метод перестановки чи щось подібне; ви повинні все написати самі.

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


Ось приклад вводу / виводу:

Зразок функції є permute(String) -> int

Вхід:

permute("3P2")

Вихід:

6

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


2
Aww. Я думав, що цей виклик буде перед перестановковими групами . Класні речі. Це теж круто і тісно пов'язане з групами перестановки. Любіть виклик.
Джастін

Якщо ви скажете, що немає вбудованих або бібліотечних методів, ви маєте на увазі перестановки чи щось? Чи можу я використовувати вбудований splitдля розділення входу на P? Як щодо функції, яка перетворює рядок у число?
xnor

3
Може відповіді припускають, що 0 <= r <= n?
Пітер Тейлор

1
@Dopapp Ви маєте на увазі, що r не більше n ?
Денніс

1
@RetoKoradi - Я вважаю, що намагаючись не змусити більшість плакатів повторювати свої відповіді, вам просто не дозволяється використовувати будь-які факторні чи перестановочні методи / функції.
Даніель

Відповіді:


4

CJam, 15 14 байт

r~\;~\),>UXt:*

Спробуйте його в Інтернеті в інтерпретаторі CJam .

Як це працює

r              e# Read a token ("nPr") from STDIN.
 ~             e# Evaluate. This pushes the numbers n, Pi and r on the stack.
  \;           e# Discard Pi.
    ~          e# Take the bitwise NOT of r. Pushes -(r+1).
     \)        e# Increment n.    
       ,       e# Turn n+1 into [0 ... n].
        >      e# Keep only the last r+1 elements.
         UXt   e# Replace the first element with 1.
               e# This avoid dealing with the egde case nP0 separately.
            :* e# Compute their product.

4

Perl, 27 байт

#!perl -pl61
$\*=$`-$%++for/P/..$'}{

Підрахувавши шебанг як 4, вхід береться від stdin.


Використання зразків

$ echo 3P2 | perl npr.pl
6

$ echo 7P4 | perl npr.pl
840

Що це за варіант l61?
feersum

@feersum він встановлює $\значення 1(char 49, восьмикутник 61).
примо

3

Haskell, 71 66 байт

p s|(u,_:x)<-span(/='P')s,(n,k)<-(read u,read x)=product[n-k+1..n]

Досить простий матеріал: розділіть на 'P', потім візьміть продукт між (n-k + 1) і n.

Завдяки німі за їх ідею використовувати шаблони шаблонів, а не whereзастереження, він виголив 5 байт.


2

Minkolang 0,11 , 13 25 19 байт

Дякуємо Sp3000, що запропонували це!

1nnd3&1N.[d1-]x$*N.

Спробуйте тут.

Пояснення

1        Push 1
n        Take integer from input (say, n)
n        Take integer from input (say, k); ignores non-numeric characters in the way
d3&1N.   Output 1 if k is 0
[   ]    Loop k times
 d1-     Duplicate top of stack and subtract 1
x        Dump top of stack
$*       Multiply all of it together
N.       Output as integer

Для цього використовується той же алгоритм, що і у Алекса: n P k= n(n-1)(n-2)...(n-k+1).


2

Джулія, 63 58 48 байт

s->((n,r)=map(parse,split(s,"P"));prod(n-r+1:n))

Це створює неназвану функцію, яка приймає рядок і повертає ціле число. Щоб зателефонувати, дайте ім’я, наприклад f=s->....

Безголовки:

function f(s::AbstractString)
    # Get the pool and number of selections as integers
    n, r = map(parse, split(s, "P"))

    # Return the product of each number between n-r+1 and n
    return prod(n-r+1:n)
end

Для цього використовується той факт, що кількість перестановок дорівнює n ( n -1) ( n -2) ... ( n - k +1).

Збережено 10 байт завдяки Glen O!


Не потрібно Int, тому можна просто користуватися map(parse,...).
Глен О

@GlenO Мій розум роздувся. Я не усвідомлював, що Intце потрібно в цій ситуації. Дуже дякую!
Олексій А.

2

Утиліти Bash + Linux, 33

jot -s\* ${1#*P} $[${1/P/-}+1]|bc

jotстворює послідовність rцілих чисел, починаючи з n-r+1, і відокремлює їх *. Цей вираз призначений bcдля арифметичної оцінки.


1

MATLAB, 54 байти

[n,r]=strread(input(''),'%dP%d');disp(prod((n-r+1):n))

Намагався зробити його меншим, але одна з речей, на яку MATLAB насправді погана, - це отримання коштів. 32 символи знадобляться лише для отримання двох чисел із вхідного рядка!

Досить роз'яснюючий код. Отримайте вхід у формі, %dP%dде% d - ціле число. Розділіть це на nта r. Потім вивести добуток кожного цілого числа в діапазоні n-r+1до n. Цікаво, що це працює навіть за xP0правильну відповідь 1. Це тому, що в MATLAB prod()функція повертає 1, якщо ви спробуєте виконати добуток порожнього масиву. Всякий раз, коли rдорівнює нулю, діапазон буде порожнім масивом, тому бінго ми отримуємо 1.


Це також чудово працює і з Octave . Ви можете спробувати онлайн тут .



1

Java (594 - байти)

import java.util.*;import java.lang.*;public class Perm {private String a;private static int[] nr=new int[2];private static int sum=1;Scanner in=new Scanner(System.in);public String input(){a=in.nextLine();return a;}public void converter(String a){this.a=a;String b=a.substring(0,1);String c=a.substring(2);nr[0]=Integer.parseInt(b);nr[1]=Integer.parseInt(c);}public int param(){for(int counter=0; counter < nr[1]; counter++){sum=sum*nr[0]--;}return sum;}public static void main(String args[]){Perm a;a=new Perm();String k=a.input();a.converter(k);int ans=a.param();System.out.println(ans);}}

1

J, 23 байти

^!._1/@(".;._1)@('P'&,)

Анонімна функція. Приклад:

   f =. ^!._1/@(".;._1)@('P'&,)
   f '10P4'
5040

Пояснення:

       (  ;._1)@('P'&,)   Split over 'P', and on each slice,
        ".                read a number.
      @                   Then,
^!._1/                    fold (/) with the built-in "stope function" (^!.k) for k=1.

Функція " stope", яку я використав, може обмежуватись підрахунком як вбудований ... Він лежить десь між загальністю оператора множення та специфікою оператора факторії.


1

APL, 23

{{×/⍵↑⍳-⍺}/-⍎¨⍵⊂⍨⍵≠'P'}

Приймає рядок як аргумент. Пояснення:

              ⍵⊂⍨⍵≠'P'  ⍝ Split by 'P'.
           -⍎¨          ⍝ Convert to numbers and negate making a vector (−n −r)
 {       }/             ⍝ Reduce it by a defined function, which
      ⍳-⍺               ⍝ makes a vector of numbers from 1 to n (⍺)
    ⍵↑                  ⍝ takes r last elements (⍵←−r)
  ×/                    ⍝ and multiplies them together.

Який це APL? Я отримую помилку зі своєю копією Dyalog.
lirtosiast

1
@ThomasKwa Використання ⎕ML←3в Dyalog.
user46915

1

Пітон 2, 66

def f(s):a,b=map(int,s.split('P'));P=1;exec"P*=a;a-=1;"*b;print P

Досить прямо. Обробляє введення числа як a,b. Зберігає працюючий продукт як P, який множиться на перші bдоданки a, a-1, a-2, ....


2
Я не бачу, як input()не могло призвести до помилки.
feersum

@feersum Я спробував це, і це дійсно видає синтаксичну помилку.
Олексій А.

Я брав дані з цитатами типу "3P2", які, на мою думку, зазвичай дозволені, але тут виклик говорить "введення в точному вигляді", тому я зміню його на функцію, яка займає рядок.
xnor

1

TI-BASIC, 52 байти

Ans→Str1
expr(sub(Ans,1,⁻1+inString(Ans,"P→P        ;n
1
If expr(Str1                               ;If n^2*r ≠ 0
prod(randIntNoRep(P,P+1-expr(Str1)/P²
Ans

TI-BASIC має функцію "продукт списку", тому обійти обмеження на вбудовані не надто складно. Однак TI-BASIC не підтримує порожні списки - тому нам потрібно

Щоб витягнути два числа, я витягую перше число як підрядку. Це дорого ; вона займає весь другий рядок. Щоб уникнути необхідності робити це ще раз для другого числа, я встановлюю змінну P на це число і оцінюю весь рядок, використовуючиexpr( , а потім ділю на P².

Нарешті, я беру випадкову перестановку списку між двома номерами (дбаючи про те, щоб додати одне до другого числа) і беру виріб.


1

Уроборос , 47 45 байт

Дещо з цього досить потворне - я б уявив, що це може бути ще в гольф.

Sr.r-1(
)s.!+S1+.@@.@\<!@@*Ys.!+*S.!!4*.(sn1(

Кожен рядок коду в Ouroboros являє собою змію, яка їсть свій хвіст.

Змія 1

Sперемикається на спільний стек. r.rчитає одне число, дублює його і читає інше. (Нечислові символи на зразок Pпропускаються.) Віднімаємо -два. Якщо вхід був 7P2, ми тепер маємо 7, 5у спільному стеку. Нарешті,1( з'їдає остаточний характер змії. Оскільки це символ, на якому вказується вказівник, змія гине.

Змія 2

)sнічого не робить з першого разу. .!+дублює верхню частину стека змії 2, перевіряє, чи дорівнює нулю, і якщо так додає 1. На першій ітерації стек порожній і обробляється так, ніби він містить нескінченні нулі, тому це натискає1 ; на пізніших ітераціях стек містить ненульове значення, і це не впливає.

Далі Sпереходить на загальний стек, де ми маємо номер nта лічильник для обчислення продукту. 1+приріст лічильника. .@@.@\<!дублює обидва числа і натискає 1, якщо nлічильник все-таки більше або дорівнює 0, інакше 0.@@*Yпотім помножує лічильник на цю кількість і кладе копію на стек змії 2.

s.!+перемикається назад на стек змії 2 і використовує той самий код, що і раніше, щоб перетворити верхнє число в 1, якщо воно було 0, і зберегти його таким же інакше. Потім* множимо результат на частковий продукт, який сидів на цій групі.

Тепер ми повертаємося до спільного стека ( S), дублюємо лічильник чи нуль ( .) і заперечуємо його двічі ( !!), щоб перетворити ненульовий лічильник на 1. 4*.(множимо це на 4, дублює і з'їдає стільки символів із кінець змії.

  • Якщо ми не досягли умови зупинки, у нас є 4 на стеці. Чотири символи після (з'їденого та керують петлями навколо початку коду. Тут )відривається чотири символи, sповертається до змії 2, і виконання триває.
  • Якщо лічильник пройшов n, у нас на стеці 0, і нічого не їдять. snперемикається на стек змії 2 і виводить верхнє значення як число; потім 1(з'їдає останнього персонажа і вмирає.

Результат полягає в тому, що продукт (r+1)*(r+2)*...*nрозраховується і виводиться.

Спробуй

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