Divertimento con permutazioni


17

Chi non ama assolutamente le permutazioni, giusto? Lo so, sono fantastici - molto divertenti!

Bene, perché non prendere questo divertimento e renderlo più divertente ?

Ecco la sfida:

Dato un input nella forma esatta:, da nPrdove nviene preso il pool ed rè il numero di selezioni da quel pool ( ne rsono numeri interi), output / restituisce il numero esatto di permutazioni. Per quelli di voi che sono un po 'arrugginiti con la terminologia: permutazione, def. 2a .

Tuttavia, è qui che entra in gioco la sfida (non è troppo facile):

Non è possibile utilizzare alcuna libreria, framework o metodo integrato per la funzione di permutazione. Non è possibile utilizzare un metodo fattoriale, un metodo di permutazione o qualcosa del genere; devi scrivere tutto da solo.

Se sono necessari ulteriori chiarimenti, per favore, non esitate a dirmelo nei commenti e agirò prontamente di conseguenza.


Ecco un esempio di I / O:

La funzione di esempio è permute(String) -> int

Ingresso:

permute("3P2")

Produzione:

6

Questo è code-golf, quindi vince il codice più corto!


2
Aww. Ho pensato che questa sfida sarebbe stata per i gruppi di permutazione . Roba forte. Anche questo è interessante e strettamente correlato ai gruppi di permutazione. Adoro la sfida.
Justin

Quando dici nessun metodo incorporato o libreria, intendi per permutazioni o per qualcosa? Posso usare il built-in splitper dividere l'ingresso in P? Che dire di una funzione che converte una stringa in un numero?
xnor

3
Le risposte possono supporre che 0 <= r <= n?
Peter Taylor,

1
@Dopapp Vuoi dire che r non è maggiore di n ?
Dennis,

1
@RetoKoradi - Suppongo che nel tentativo di non forzare la maggior parte dei poster a rifare le loro risposte, non ti è permesso usare metodi / funzioni fattoriali o di permutazione.
Daniel,

Risposte:


4

CJam, 15 14 byte

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

Provalo online nell'interprete CJam .

Come funziona

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 byte

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

Contando lo shebang come 4, l'input viene preso dallo stdin.


Esempio di utilizzo

$ echo 3P2 | perl npr.pl
6

$ echo 7P4 | perl npr.pl
840

Che tipo di opzione è l61?
feersum

@feersum è impostato $\su 1(carattere 49, ottale 61).
primo

3

Haskell, 71 66 byte

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

Roba piuttosto semplice: dividere in 'P' quindi prendere il prodotto tra (n-k + 1) e n.

Grazie a nimi per la loro idea di usare protezioni di motivi piuttosto che una whereclausola, si è rasato 5 byte.


2

Minkolang 0,11 , 13 25 19 byte

Grazie a Sp3000 per avermi suggerito questo!

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

Provalo qui.

Spiegazione

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

Questo utilizza lo stesso algoritmo di Alex: n P k= n(n-1)(n-2)...(n-k+1).


2

Julia, 63 58 48 byte

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

Ciò crea una funzione senza nome che accetta una stringa e restituisce un numero intero. Per chiamarlo, dagli un nome, ad es 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

Questo utilizza il fatto che il numero di permutazioni è n ( n -1) ( n -2) ... ( n - k +1).

Risparmiato 10 byte grazie a Glen O!


Non è necessario Int, quindi puoi semplicemente usarlo map(parse,...).
Glen O

@GlenO La mia mente è stata spazzata via. Non mi ero reso conto che Intera necessario in quella situazione. Grazie mille!
Alex A.

2

Utilità Bash + Linux, 33

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

jotproduce la sequenza di rnumeri interi che iniziano con n-r+1, e li separa con *. Questa espressione viene convogliata bcper la valutazione aritmetica.


1

MATLAB, 54 byte

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

Ho cercato di renderlo più piccolo, ma una delle cose in cui MATLAB è davvero pessima è ottenere input. Ci vogliono 32 caratteri solo per ottenere i due numeri dalla stringa di input!

Codice abbastanza autoesplicativo. Ottieni l'input nel modulo in %dP%dcui% d è un numero intero. Dividilo in ne r. Quindi visualizzare il prodotto di ogni numero intero nell'intervallo n-r+1a n. È interessante notare che funziona anche per xP0dare la risposta corretta di 1. Questo perché in MATLAB la prod()funzione restituisce 1 se si tenta di eseguire il prodotto di un array vuoto. Ogni volta che rè zero, l'intervallo sarà un array vuoto, quindi il bingo otteniamo 1.


Funziona perfettamente anche con Octave . Puoi provarlo online qui .


1

Javascript, 59 57 byte

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

1

Java (594 - byte)

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 byte

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

Una funzione anonima. Esempio:

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

Spiegazione:

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

La funzione stope che ho usato potrebbe rasentare il conteggio come incorporato ... Si basa in qualche modo tra la generalità dell'operatore di moltiplicazione e la specificità dell'operatore fattoriale.


1

APL, 23

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

Prende la stringa come argomento. Spiegazione:

              ⍵⊂⍨⍵≠'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.

Quale APL è questo? Ottengo un errore con la mia copia di Dyalog.
lirtosiast,

1
@ThomasKwa Usa ⎕ML←3in 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

Abbastanza diretto. Elabora il numero immesso come a,b. Mantiene un prodotto in esecuzione come P, che viene moltiplicato per i primi btermini di a, a-1, a-2, ....


2
Non vedo come non sia input()stato possibile generare un errore.
feersum

@feersum L'ho provato e in effetti genera un errore di sintassi.
Alex A.

Stavo prendendo input con virgolette come "3P2", che penso sia generalmente consentito, ma qui la sfida dice "un input nella forma esatta", quindi lo cambio in una funzione che accetta una stringa.
xnor

1

TI-BASIC, 52 byte

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 ha una funzione "prodotto di un elenco", quindi aggirare la limitazione sui builtin non è troppo difficile. Tuttavia, TI-BASIC non supporta elenchi vuoti, quindi è necessario

Per estrarre i due numeri, estraggo il primo numero come sottostringa. Questo è costoso ; occupa l'intera seconda riga. Per evitare di dover ripetere l'operazione per il secondo numero, ho impostato la variabile P su quel numero e ho valutato l'intera stringa usando expr(, quindi diviso per P².

Infine, prendo una permutazione casuale dell'elenco tra i due numeri (avendo cura di aggiungerne uno al secondo numero) e prendo il prodotto.


1

Ouroboros , 47 45 byte

Alcuni di questi sono piuttosto brutti - immagino che potrebbe essere ulteriormente giocato a golf.

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

Ogni riga di codice in Ouroboros rappresenta un serpente che si mangia la coda.

Snake 1

Spassa allo stack condiviso. r.rlegge un numero, lo duplica e ne legge un altro. (I caratteri non numerici come Pvengono saltati.) Sottrae -i due. Se l'input era 7P2, ora abbiamo 7, 5nello stack condiviso. Infine, 1(mangia il personaggio finale del serpente. Poiché questo è il personaggio su cui si trova il puntatore dell'istruzione, il serpente muore.

Snake 2

)snon fa nulla la prima volta. .!+duplica la parte superiore dello stack di snake 2, controlla se è zero e in tal caso aggiunge 1. Alla prima iterazione, lo stack è vuoto e trattato come se contenesse zeri infiniti, quindi questo spinge 1; nelle iterazioni successive, lo stack contiene un valore diverso da zero e questo non ha alcun effetto.

Successivamente, Spassa allo stack condiviso, dove abbiamo il numero ne un contatore per il calcolo del prodotto. 1+incrementa il contatore. .@@.@\<!duplica entrambi i numeri e preme 1 se nè ancora maggiore o uguale al contatore, 0 altrimenti. @@*Yquindi moltiplica il segnalino per questa quantità e ne estrae una copia nella pila di Snake 2.

s.!+ritorna allo stack di snake 2 e usa lo stesso codice di prima per convertire il numero superiore in 1 se fosse 0 e mantenerlo lo stesso altrimenti. Quindi *moltiplica il risultato per il prodotto parziale che si trovava su questa pila.

Ora torniamo allo stack condiviso ( S), dupliciamo il contatore-o-zero ( .) e lo neghiamo due volte ( !!) per trasformare un contatore diverso da zero in un 1. 4*.(moltiplica questo per 4, duplica e mangia quel numero di caratteri dal fine del serpente.

  • Se non abbiamo raggiunto la condizione di arresto, abbiamo un 4 in pila. I quattro caratteri dopo il (segno vengono mangiati e il controllo passa all'inizio del codice. Qui )rigurgita quattro personaggi, sritorna allo stack di Snake 2 e l'esecuzione continua.
  • Se il contatore è passato n, abbiamo uno 0 in pila e non viene mangiato nulla. snpassa allo stack di snake 2 e genera il valore più alto come numero; poi 1(mangia l'ultimo personaggio e muore.

Il risultato è che il prodotto (r+1)*(r+2)*...*nviene calcolato e prodotto.

Provalo

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.