Combinación matemática


11

Escriba un programa que tome una entrada como:

n,k

que luego calcula:

Combinación de n y k.  (C (n, k))

y luego imprime el resultado.


Un ejemplo numérico:

Entrada:

5,2

Cálculo interno:

(5!) / (3! X2!)

Salida impresa:

10

Me gustaría ver una respuesta que supere mi solución de Python de 65 caracteres, pero todos los idiomas son obviamente bienvenidos.

Aquí está mi solución:

n,k=input();f=lambda x:+(x<2)or x*f(x-1);print f(n)/(f(k)*f(n-k))

Editar:

Admito que esta pregunta es del rompecabezas de combinación matemática del sitio web codegolf . Sé que mi respuesta puede parecer que no se puede hacer mucho progreso al respecto, pero los líderes de este rompecabezas lo han resuelto en casi la mitad de los personajes.

Los recuentos de caracteres más bajos actuales por idioma son:

Perl: 35

Rubí: 36

Python: 39

PHP: 62


Función o programa completo? Su descripción dice función que devuelve el resultado correcto, pero su ejemplo es un programa completo que lo imprime.
Ventero

@Ventero Tienes razón, me refería al programa. Lo siento por eso.
backus

3
En general, los conceptos matemáticos básicos no son buenas preguntas de golf porque J, APL, Maple, Mathematica y muchos otros los incorporarán. Además, sea un poco más específico sobre el formato de entrada y salida, y proporcione ejemplos de resultados. No puedo saber si te refieres a 5 elige 2 o 2 elige 5 aquí.
Jesse Millikan

@Jesse Obtuve este desafío de otro sitio web que solo permite los principales lenguajes de script, recordaré esta guía en el futuro. Edité mi pregunta para tratar de aclarar los requisitos del desafío, avíseme si es lo suficientemente claro o no.
backus

Soy nuevo, así que estamos en el mismo bote. Sin embargo, no resuma los resultados; simplemente quedarán obsoletos. Simplemente vote y (si corresponde) acepte las respuestas. (Además, hará que la gente se sienta infeliz si ignora las respuestas de J y GolfScript sin una razón.)
Jesse Millikan

Respuestas:


11

APL, 3 bytes

⎕!⎕

O para aquellos cuyo navegador no representa lo anterior, en una representación ASCII:

{Quad}!{Quad}

3
Para estar completamente conforme con la n,kentrada, tendría que hacerlo !/⌽⎕.
marinus


10

C 96

Con E / S (que toma alrededor de 34 caracteres). Se agregaron un par de nuevas líneas para que sea legible.

main(a,b,c,d){scanf("%d,%d",&a,&b);
d=a-b;for(c=1;a>b;){c*=a--;}for(;d;)
{c/=d--;}printf("%d",c);}

Ahora, si me disculpa, tengo un ASCII n elegir k cohete para atrapar.

    d;main(a
   ,         b
  ,           c
 )  int        a
 ;   {scanf    (
 (   "%d %d"   )
 ,   &a,  &b   )
 ;   d    =a   -
 b   +     b   -
 b   *     1   ;
 a             -
 a  ;for    (  c
 =  1;a>   b   ;
 )  {c=   c    *
 (  (a-- )     )
 ;  }for(      b
 =  b + 1      ;
 d  ;    )     {
 c  =     c    /
 (  d--    )   ;
  }           {
  }           {
   }         (
  printf("%d",c)
 )      ;       }
/*     *  *   * *\
 * * X   * 8 * * |
|     *      *    \
*/    //       *  */

7

GolfScript, 17 caracteres

Esta solución maneja casos como k = 0 o k = 1 correctamente.

~>.,,]{1\{)*}/}//

La porción de tipo factorial se basa en una respuesta previa .


6

GolfScript 21

~~)>.,,]{{)}%{*}*}%~/

No es particularmente corto, GolfScript carece de una función factorial real, sin embargo, esta tiene que ser la manipulación de datos más perversa que he hecho, esto requiere un seguimiento de la pila:

"5,2" Datos en la pila desde la entrada.
~El comando Eval, tenga en cuenta que, es un operador que convierte un número en una matriz.
[0 1 2 3 4] 2
~Binario no.
[0 1 2 3 4] -3
)Incremento.
[0 1 2 3 4] -2
>Tome el final de la matriz, -2 como parámetro para obtener los últimos 2 elementos.
[3 4]
.Elemento duplicado.
[3 4] [3 4]
,Longitud de la matriz.
[3 4] 2
,Gire el número a la matriz.
[3 4] [0 1]
]Crear matriz.
[[3 4] [0 1]]
{{)}%{*}*}Bloque de código.
[[3 4] [0 1]] {{)}% {*} *}
%Ejecuta el bloque una vez para cada elemento de la matriz. La siguiente parte solo demuestra el primer bucle.
[3 4]
{)}%Incremente cada elemento de la matriz.
[4 5]
{*}Bloque que contiene un comando de multiplicación.
[4 5] {*}
*"Dobla" la matriz usando el comando de bloque, es decir, en este caso crea el producto de todos los elementos.
20
Una vez finalizado el ciclo grande, devuelve una matriz con los resultados.
[20 2]
~Deconstruir la matriz.
20 2
/División.
10


6

Ruby 1.9, 52 46 (42) caracteres

eval"A,B="+gets;i=0;p eval"(A-B+i+=1)/i*"*B+?1

Si se ignora stderr:

eval"A,B=I="+gets;p eval"I/(A-I-=1)*"*B+?1

Ruby 1.8, 43 caracteres, sin salida adicional para stderr:

eval"a,b=i="+gets;p eval"i/(a-i-=1)*"*b+"1"

Ediciones:

  • (52 -> 48) Se encontró una forma más corta de analizar la entrada
  • (48 -> 46) Menos bucles, más evaluación.

4

Pitón (56)

f=lambda n,k:k<1and 1or f(n-1,k-1)*n/k;print f(*input())

Código sin golf y alguna explicación de un atajo para calcular el coeficiente binomial. (Nota: hay algunas ideas que simplemente no he descubierto para llegar a la versión de 39 caracteres; no creo que este enfoque lo lleve allí).

# Since choose(n,k) =
#
#     n!/((n-k)!k!)
#
#          [n(n-1)...(n-k+1)][(n-k)...(1)]
#        = -------------------------------
#            [(n-k)...(1)][k(k-1)...(1)]
#
# We can cancel the terms:
#
#     [(n-k)...(1)]
#
# as they appear both on top and bottom, leaving:
#
#    n (n-1)     (n-k+1)
#    - ----- ... -------
#    k (k-1)       (1)
#
# which we might write as:
#
#      choose(n,k) = 1,                      if k = 0
#                  = (n/k)*choose(n-1, k-1), otherwise
#
def choose(n,k):
    if k < 1:
        return 1
    else:
        return choose(n-1, k-1) * n/k

# input() evaluates the string it reads from stdin, so "5,2" becomes
# (5,2) with no further action required on our part.
#
# In the golfed version, we make use of the `*` unpacking operator, 
# to unpack the tuple returned by input() directly into the arguments
# of f(), without the need for intermediate variables n, k at all.
#
n, k = input()

# This line is left as an exercise to the reader.
print choose(n, k)

¿Podrías proporcionar un ejemplo no escrito de tu guión?
backus

¿Podemos usar *para analizar entradas del formulario 4545 78?
Quixotic

Desafortunadamente, no, pero no es *ese el problema. 4545 78no es una expresión válida de Python, por input()lo que elevará a SyntaxError. Este truco depende completamente del problema que se solicita x,y. Si tenía una función que leía x yy devolvía una tupla, entonces podría usarla *bien.


3

Windows PowerShell, 57

$a,$b=iex $input
$p=1
for($a-=$b;$a-ge1){$p*=1+$b/$a--}$p

3

J, 33 36

(":!~/".;._1}:toJ',',1!:1(3))1!:2(4)

35 caracteres son de entrada, análisis y salida. El otro carácter, !es n elegir k.

No tengo Windows para probar esto en este momento, pero creo que debería funcionar allí.



2

Perl 6 (55)

my ($a,$b)=lines;$_=1;for 1..$a-$b {$_+=$_*$b/$^a};.say

2

RPL (22)

(sin usar la función COMB incorporada)

→ n k 'n!/(k!*(n-k)!)'

2

Q ( 50 45)

 f:{(prd 1.+til x)%((prd 1.+til y)*prd 1.+til x-y)}

Puede eliminar algunos caracteres de los anteriores eliminando paréntesis redundantes y utilizando 1 * / en lugar de prd.

f:{(1*/1.+til x)%(1*/1.+til y)*1*/1.+til x-y}

2

Mathematica 12

Función directa e integrada.

n~Binomial~k

2

Perl 6 , 25 16 bytes

-9 bytes gracias a nwellnhof

+*o&combinations

Pruébalo en línea!

Función anónima que toma dos números y devuelve un int. Esto utiliza el incorporado combinationsy convierte la lista devuelta en un int.



@nwellnhof Ah, no me di cuenta de que combinationspodía tomar un número en lugar de una lista
Jo King

1

PHP (71 79 )

<?$a=fgetcsv(STDIN);$x=1;while($a[1]-$i)$x=$x*($a[0]-++$i+1)/$i;echo$x;

<?php $a=fgetcsv(STDIN);$x=1;while(++$i<=$a[1])$x=$x*($a[0]-$i+1)/$i;echo $x?>


1

Pitón (54)

f=lambda n,k:k<1or f(n-1,k-1)*n/k;print 1*f(*input())

Esencialmente lo mismo que el anterior de Python, pero elimino cuatro bytes al soltar el

and 1

de la definición de la función. Sin embargo, esto da como resultado que la función devuelva True en lugar de 1 si k = 0, pero esto se puede solucionar multiplicando con 1 antes de imprimir, ya que 1 * True = 1, agregando así dos bytes.


1

J, 11 caracteres

!~/".1!:1[1

Toma entrada del teclado.

    !~/".1!:1[1
5,2
10

0

Haskell (80)

f(_,0)=1
f(n,k)=n/k*f(n-1,k-1)
main=getLine>>=putStr.show.f.read.(++")").('(':)

Pero, si x yse permite la entrada en el formato en lugar de en el formato x,y, son 74 caracteres:

f[_,0]=1
f[n,k]=n/k*f[n-1,k-1]
main=interact$show.f.map read.take 2.words


0

Pitón (52)

 f=lambda n,k:k<1or f(n-1,k-1)*n/k;print+f(*input())

Mejorado de los otros dos al usar print+para convertir el resultado de ffrom booleana intin case k==0.

Todavía no tengo idea de cómo reducirlo a 39, me pregunto si están usando lambda en absoluto.


0

(El OP solo especificó libremente el método / formato de entrada y salida, por lo que lo siguiente parece aceptable).

Cuaderno Sabio ( 39 41 40)

En la celda actual,

f=lambda n,k:k<1or f(n-1,k-1)*n/k;+f(*_)

donde n,kse ingresa y evalúa la entrada en el formulario en la celda anterior. Esto simula la "entrada de la línea de comandos" asignándola a _(similar a los argumentos de la línea de comandos).

Cuaderno Sabio ( 42 44 43)

Alternativamente, usando "entrada en la fuente" (con solo los x=caracteres de nueva línea y añadidos a la partitura), por ejemplo,

x=5,2
f=lambda n,k:k<1or f(n-1,k-1)*n/k;+f(*x)

Ambos enfoques son obviamente derivados de respuestas anteriores de otros.



0

Javascript, 27 bytes

Primero mis propias soluciones de 35 bytes:

f=(n,k)=>n-k&&k?f(--n,k)+f(n,k-1):1

O alternativamente,

f=(n,k,i=k)=>i?f(n-1,k-1,i-1)*n/k:1

El primero trabaja de forma recursiva, con la (n,k) = (n-1,k) + (n-1,k-1)regla simple . El segundo usando eso (n,k) = (n-1,k-1) * n/k.

EDITAR

Acabo de notar la solución de Arnould en un duplicado de esto:

f=(n,k)=>k?n*f(n-1,k-1)/k:1

Lo que equivale a 8 bytes menos (27 bytes)


0

TI-BASIC, 16 caracteres (8 bytes)

Ans(1) nCr Ans(2

La entrada es una lista de longitud 2 in Ans.
La salida es el resultado de la fórmula definida aquí .

Si la solución anterior no es suficiente, entonces la siguiente solución de 35 caracteres (24 bytes) también funciona:

Ans(2)!⁻¹(Ans(1)-Ans(2))!⁻¹Ans(1)!

Nota: TI-BASIC es un lenguaje tokenizado. El recuento de caracteres no es igual al recuento de bytes.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.