Diversão com permutações

17

Quem não ama absolutamente permutações, certo? Eu sei, eles são incríveis - muito divertidos!

Bem, por que não aproveitar essa diversão e torná-la mais divertida ?

Aqui está o desafio:

Dada uma entrada na forma exata:, nPronde né o conjunto retirado e ro número de seleções desse conjunto ( ne rsão inteiros), gera / retorna o número exato de permutações. Para aqueles que estão um pouco enferrujados com a terminologia: Permutação, def. 2a .

No entanto, é aqui que o desafio entra em jogo (o que não é muito fácil):

Você não pode usar nenhuma biblioteca, estrutura ou método interno para sua função de permutação. Você não pode usar um método fatorial, um método de permutação ou qualquer coisa do tipo; você deve escrever tudo sozinho.

Se mais esclarecimentos forem necessários, não hesite em me informar nos comentários e eu agirei prontamente.


Aqui está um exemplo de E / S:

A função de amostra é permute(String) -> int

Entrada:

permute("3P2")

Resultado:

6

Isso é código-golfe, então o código mais curto vence!

Daniel
fonte
2
Aww. Eu pensei que esse desafio seria em grupos de permutação . Coisas legais. Isso também é legal e está intimamente relacionado aos grupos de permutação. Ame o desafio.
7267 Justin
Quando você diz que não tem métodos internos ou de biblioteca, quer dizer permutações ou qualquer coisa? Posso usar o built-in splitpara dividir a entrada no P? Que tal uma função que converte uma string em um número?
Xnor
3
As respostas de maio assumem isso 0 <= r <= n?
Peter Taylor
11
@Dopapp Você quer dizer que r não é maior que n ?
Dennis
11
@RetoKoradi - Suponho que, em um esforço para não forçar a maioria dos pôsteres a refazer suas respostas, você não tenha permissão para usar métodos / funções de fatorial ou de permutação.
Daniel

Respostas:

4

CJam, 15 14 bytes

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

Experimente online no intérprete CJam .

Como funciona

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.
Dennis
fonte
4

Perl, 27 bytes

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

Contando o shebang como 4, a entrada é obtida de stdin.


Uso da amostra

$ echo 3P2 | perl npr.pl
6

$ echo 7P4 | perl npr.pl
840
primo
fonte
Que tipo de opção é l61?
precisa saber é
@feersum define $\para 1(char 49, octal 61).
Primo
3

Haskell, 71 66 bytes

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

Coisas bem simples: divida no 'P' e depois leve o produto entre (n-k + 1) e n.

Graças a nimi por sua idéia de usar protetores de padrões em vez de uma wherecláusula, ele cortou 5 bytes.

arjanen
fonte
2

Minkolang 0.11 , 13 25 19 bytes

Obrigado ao Sp3000 por sugerir isso!

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

Experimente aqui.

Explicação

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

Isso usa o mesmo algoritmo que o de Alex: n P k= n(n-1)(n-2)...(n-k+1).

El'endia Starman
fonte
2

Julia, 63 58 48 bytes

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

Isso cria uma função sem nome que aceita uma sequência e retorna um número inteiro. Para chamá-lo, dê um nome, por exemplo f=s->....

Ungolfed:

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

Isso usa o fato de que o número de permutações é n ( n -1) ( n -2) ... ( n - k +1).

Economizou 10 bytes graças a Glen O!

Alex A.
fonte
Não há necessidade Int, então você pode apenas usar map(parse,...).
Glen O
@GlenO Minha mente está explodida. Eu não percebi que Intera necessário nessa situação. Muito obrigado!
Alex A.
2

Utilitários Bash + Linux, 33

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

jotproduz a sequência de rnúmeros inteiros começando em n-r+1e os separa com *. Essa expressão é canalizada bcpara avaliação aritmética.

Trauma Digital
fonte
1

MATLAB, 54 bytes

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

Tentou diminuí-lo, mas uma das coisas nas quais o MATLAB é realmente ruim é obter entradas. São necessários 32 caracteres apenas para obter os dois números da string de entrada!

Código bastante auto-explicativo. Obtenha a entrada no formato em %dP%dque% d é um número inteiro. Divida isso em ne r. Em seguida, exiba o produto de cada número inteiro no intervalo n-r+1até n. Curiosamente, isso funciona mesmo para xP0fornecer a resposta correta de 1. Isso ocorre porque no MATLAB a prod()função retorna 1 se você tentar fazer o produto de uma matriz vazia. Sempre que rfor zero, o intervalo será um array vazio; portanto, o bingo recebe 1.


Isso também funciona perfeitamente com o Octave também. Você pode experimentá-lo online aqui .

Tom Carpenter
fonte
1

Javascript, 59 57 bytes

s=>(f=(n,k)=>k?(n- --k)*f(n,k):1,f.apply(f,s.split('P')))
Naouak
fonte
1

Java (594 - bytes)

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);}}
Kamalnrf
fonte
1

J, 23 bytes

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

Uma função anônima. Exemplo:

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

Explicação:

       (  ;._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.

A função stope que usei pode ser contada como um built-in ... Ela fica em algum lugar entre a generalidade do operador de multiplicação e a especificidade do operador fatorial.

Lynn
fonte
1

APL, 23

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

Pega a string como argumento. Explicação:

              ⍵⊂⍨⍵≠'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.
user46915
fonte
Qual APL é esse? Eu recebo um erro com minha cópia do Dyalog.
lirtosiast
11
@ThomasKwa Use ⎕ML←3no Dyalog.
user46915
1

Python 2, 66

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

Bem direto. Processa a entrada do número como a,b. Mantém um produto em execução como P, multiplicado pelos primeiros btermos de a, a-1, a-2, ....

xnor
fonte
2
Não vejo como input()não resultou em erro.
precisa saber é
@feersum Eu tentei e realmente lança um erro de sintaxe.
Alex A.
Eu estava usando entradas com aspas como "3P2", o que eu acho que geralmente é permitido, mas aqui o desafio diz "uma entrada na forma exata", então eu a altero para uma função que usa uma string.
Xnor
1

TI-BASIC, 52 bytes

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

O TI-BASIC possui uma função "produto de uma lista", portanto, contornar a restrição de componentes internos não é muito difícil. No entanto, o TI-BASIC não suporta listas vazias - portanto, precisamos

Para extrair os dois números, extraio o primeiro número como uma substring. Isso é caro ; ocupa toda a segunda linha. Para não precisar fazer isso novamente para o segundo número, defino a variável P para esse número e avalio a cadeia inteira usando expr(, depois divido por P².

Finalmente, tomo uma permutação aleatória da lista entre os dois números (tomando o cuidado de adicionar um ao segundo número) e pego o produto.

lirtosiast
fonte
1

Ouroboros , 47 45 bytes

Parte disso é muito feia - eu imagino que poderia ser ainda mais jogado.

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

Cada linha de código em Ouroboros representa uma cobra comendo seu rabo.

Cobra 1

Smuda para a pilha compartilhada. r.rlê um número, duplica e lê outro. (Caracteres não numéricos como Psão ignorados.) -Subtrai os dois. Se a entrada foi 7P2, agora temos 7, 5na pilha compartilhada. Finalmente, 1(come o caráter final da cobra. Como esse é o personagem em que o ponteiro de instrução está, a cobra morre.

Cobra 2

)snão faz nada na primeira vez. .!+duplica a parte superior da pilha do snake 2, verifica se é zero e, se sim, adiciona 1. Na primeira iteração, a pilha está vazia e tratada como se contivesse zeros infinitos 1; nas iterações posteriores, a pilha contém um valor diferente de zero e isso não tem efeito.

Em seguida, Salterna para a pilha compartilhada, onde temos o número ne um contador para calcular o produto. 1+incrementa o contador. .@@.@\<!duplica os números e empurra 1 se nainda for maior ou igual ao contador, 0 caso contrário. @@*Ydepois multiplica o contador por essa quantidade e puxa uma cópia para a pilha da cobra 2.

s.!+volta para a pilha do snake 2 e usa o mesmo código anterior para converter o número superior em 1 se fosse 0 e mantê-lo da mesma forma. Em seguida, *multiplica o resultado pelo produto parcial que estava na pilha.

Agora voltamos à pilha compartilhada ( S), duplicamos o contador-ou-zero ( .) e o negamos duas vezes ( !!) para transformar um contador diferente de zero em um 1. 4*.(multiplica isso por 4, duplica e consome muitos caracteres do fim da cobra.

  • Se não alcançamos a condição de parada, temos um 4 na pilha. Os quatro caracteres após o (são comidos e os loops de controle ficam no início do código. Aqui )regurgita quatro caracteres, svolta para a pilha de snake 2 e a execução continua.
  • Se o contador passou n, temos um 0 na pilha e nada é comido. snmuda para a pilha da cobra 2 e gera o valor superior como um número; então 1(come o último caractere e morre.

O resultado é que o produto (r+1)*(r+2)*...*né calculado e produzido.

Experimente

DLosc
fonte