# Función f1
<- function(x1, x2, x3) {
f1 <- x1 / x2 + x3^2 + x2 * x3
resultado return(resultado)
}
# Ejemplo de su uso
f1(5, 2, 3)
[1] 17.5
Instrucciones generales para resolver los problemas de esta práctica:
unidad3
, para guardar allí todos los archivos que usaremos. Asegurarse de que RStudio esté trabajando con este proyecto abierto.ejercicio_*.R
para almacenar de manera organizada la solución de cada problema (por ejemplo, ejercicio_01.R
, ejercicio_02.R
, etc.)Escribimos la función y la usamos:
# Función f1
<- function(x1, x2, x3) {
f1 <- x1 / x2 + x3^2 + x2 * x3
resultado return(resultado)
}
# Ejemplo de su uso
f1(5, 2, 3)
[1] 17.5
Escribimos la función y la usamos:
# Función f2
<- function(x1, x2 = 1, x3 = 1) {
f2 <- x1 / x2 + x3^2 + x2 * x3
resultado return(resultado)
}
# Ejemplos de su uso
f2(5, 2, 3)
[1] 17.5
f2(5)
[1] 7
f2(5, 2)
[1] 5.5
f2(5, x3 = 3)
[1] 17
f2(x2 = 2, x3 = 3)
Error in f2(x2 = 2, x3 = 3): argument "x1" is missing, with no default
Escribimos la función y la usamos:
# Función f3
<- function(x1, x2 = 1, x3 = 1) {
f3 if (x1 < 0 || x2 < 0 || x3 < 0) {
return(-100)
else {
} <- x1 / x2 + x3^2 + x2 * x3
resultado return(resultado)
}
}
# Ejemplos de su uso
f3(5, 2, 3)
[1] 17.5
f3(-5, 2, 3)
[1] -100
f3(-5)
[1] -100
f3(5, x3 = -3)
[1] -100
Sin importar el signo de a
y b
ni cuál es mayor o menor, la secuencia de todos los enteros se puede generar fácilmente con la expresión a:b
que usamos como parte de la estructura for
:
1:4
[1] 1 2 3 4
4:1
[1] 4 3 2 1
3:3
[1] 3
-2:4
[1] -2 -1 0 1 2 3 4
-2:-8
[1] -2 -3 -4 -5 -6 -7 -8
Por lo tanto, si iteramos con un for
a través de la secuencia a:b
, la función puede definirse así:
#' Suma de una secuencia de números enteros
#'
#' @description
#' Calcula la suma de un rango de números enteros, incluyendo los extremos.
#'
#' @param a,b números enteros
#'
#' @return suma de la secuencia
#'
#' @examples
#' suma_secuencia(1, 3)
#' suma_secuencia(-2, 3)
#' suma_secuencia(-3, -5)
#' suma_secuencia(3, 3)
#'
<- function(a, b) {
suma_secuencia <- 0
suma for (i in a:b) {
<- suma + i
suma
}return(suma)
}
Ejemplos de su uso:
suma_secuencia(1, 3)
[1] 6
suma_secuencia(30, 40)
[1] 385
suma_secuencia(5, 2)
[1] 14
suma_secuencia(-2, 3)
[1] 3
suma_secuencia(-7, -5)
[1] -18
suma_secuencia(-3, -5)
[1] -12
suma_secuencia(-3, -3)
[1] -3
suma_secuencia(3, 3)
[1] 3
#' Clasificación de un triángulo
#'
#' @description
#' Clasifica a un triángulo según las longitudes de sus lados, en escaleno, isósceles
#' o equilátero.
#'
#' @details
#' Se evalúa la desigualdad triangular. Si las medidas de los lados no corresponden
#' a un triángulo, la función devuelve "no es un triángulo".
#'
#' @param a,b,c números reales positivos
#'
#' @return valor carácter que indica el tipo de triángulo.
#'
#' @examples
#' triangulos(2, 3, 4)
#' triangulos(2, 3, 10)
#'
<- function(a, b, c) {
triangulos if (a > b + c || b > a + c || c > a + b) {
return("no es triángulo")
else if (a == b & a == c) {
} return("equilátero")
else if (a == b || a == c || b == c) {
} return("isósceles")
else {
} return("escaleno")
} }
Alternativamente, podemos prescindir de las estructuras anidadas, gracias a la existencia de las sentencias return
en cada camino posible. Si alguna condición es TRUE
, enseguida se devuelve el valor que corresponda y se detiene la ejecución de la función. El resto no se evalúa, lo cual hace innecesario usar else if
o estructuras anidadas:
<- function(a, b, c) {
triangulos if (a > b + c || b > a + c || c > a + b) {
return("no es triángulo")
}if (a == b & a == c) {
return("equilátero")
}if (a == b || a == c || b == c) {
return("isósceles")
}return("escaleno")
}
Ejemplos de uso:
triangulos(2, 3, 4)
[1] "escaleno"
triangulos(2, 3, 10)
[1] "no es triángulo"
#' Punto dentro de la elipse
#'
#' @description
#' Determina si un punto está contenido dentro de la elipse definida por la fórmula
#' (x - 6)^2 / 36 + (y + 4)^2 / 16 = 1
#'
#' @details
#' Por defecto se evalúa al origen de coordenadas.
#'
#' @param x,y coordenadas, números reales. Por defecto valen 0.
#'
#' @return valor lógico indicando si el punto está dentro de la elipse descripta.
#'
#' @examples
#' elipse(3, 7)
#' elipse(6, -4)
#' elipse()
#'
<- function(x = 0, y = 0) {
elipse <- (x - 6)^2 / 36 + (y + 4)^2 / 16
valor return(valor <= 1)
}
Ejemplos de uso:
elipse(3, 7)
[1] FALSE
elipse(6, -4)
[1] TRUE
elipse()
[1] FALSE
Si bien hay muchas formas de resolver este ejercicio, tal vez usando estructuras iterativas y condicionales, conviene pensarlo desde un punto de vista matemático. La suma de los números impares de la fila \(n\) resulta igual a \(n^3\). Para darse cuenta, conviene pensar en los siguientes puntos:
\[ \Big(\frac{n(n+1)}{2}\Big)^2 - \Big(\frac{(n-1)n}{2}\Big)^2 = n^3 \]
El código de la función puede ser sencilamente:
#' Suma de fila de la pirámide
#'
#' @description
#' La pirámide se arma con números impares, empezando con el 1 en la cima, el 3 y 5
#' en la segunda fila, y así sucesivamente. Devuelve la suma de los números ubicados
#' en la fila ingresada.
#'
#' @details
#' Se puede demostrar que la suma de los números en la n-ésima fila es igual a
#' n al cubo.
#'
#' @param n Número natural
#'
#' @return suma de los números ubicados en la n-ésima fila de la pirámide.
#'
#' @examples
#' suma_piramide(1)
#' suma_piramide(2)
#' suma_piramide(3)
#'
<- function(n) {
suma_piramide return(n^3)
}
Ejemplos:
suma_piramide(1)
[1] 1
suma_piramide(2)
[1] 8
suma_piramide(3)
[1] 27
# Evaluamos la suma de cada una de las primeras 10 filas
for (n in 1:10) {
<- suma_piramide(n)
suma cat("Los impares de la fila", n, "suman", suma, "\n")
}
Los impares de la fila 1 suman 1
Los impares de la fila 2 suman 8
Los impares de la fila 3 suman 27
Los impares de la fila 4 suman 64
Los impares de la fila 5 suman 125
Los impares de la fila 6 suman 216
Los impares de la fila 7 suman 343
Los impares de la fila 8 suman 512
Los impares de la fila 9 suman 729
Los impares de la fila 10 suman 1000
Paso a paso:
f
y g
y las variables globales a
y b
, con los valores 6 y 1, respectivamente.g(a, b)
, resultando en que en el ambiente local de g
, x
recibe el valor 6 e y
el valor 1.g
se crea la variable local b
, con valor 6 - 2 * 1 = 4
.g
se invoca f(b)
, donde b
vale 4
.f
, a
recibe el valor 4, el cual es actualizado por (4-10)*(4+10)=-84
para finalmente devolver -84
.g
, la variable c
recibe el valor b*f(b)=4*f(4)=4*(-84)=-336
y se devuelve -336
.d
se vuelve a invocar f
esta vez sin argumentos explícitos, por lo que en el ambiente local de f
, a
recibe el valor 10 y f() = 0
. El valor final de d
es f() - c = 0 - (-336) = 336
.g(a, b)
es 336
.En este ejemplo, el identificador a
representa dos variables distintas: una de ellas definida en el Global Environment y la otra en el ámbito local de la función f1
. Lo mismo ocurre con x
: representa a una variable en el ambiente global, a otra en el ambiente de la función f1
y a una tercera en el ambiente de la función f2
. Al ejecutar el algoritmo se obtendrían los siguientes resultados:
f1
y f2
y las variables x
e y
con valores: x = 3
e y = 5
.f1
, donde el parámetro formal a
recibe el valor del parámetro real x
(a = 3
), mientras que el parámetro formal b
recibe el valor del parámetro real y
(b = 5
). Dentro de la función f1
:
x
que recibe el valor x = a + b = 8
. Esta x
no tiene nada que ver con la del ambiente global.y
que recibe el valor y = x + 2 = 8 + 2 = 10
. Esta y
no tiene nada que ver con la del ambiente global.y = 10
.a
el valor recién devuelto: a = 10
. Esta a
no tiene nada que ver con la variable local de la función f1
.f2
, donde el parámetro formal x
recibe el valor del parámetro real a
(x = 10
). Esta x
no tiene nada que ver con las anteriores. Dentro de la función f2
:
x
: \(10^2\) = 100100
.x + f2(a) = 3 + 100 = 103
y se asigna este valor a z
.z
, 103.a + b = 10 + ?
, pero produce error, puesto que b
no está definida en el ambiente global, no tiene asignado ningún valor. La única variable b
que existe está en el ámbito de la función f1
, no en el Global Environment.Primero, en el ambiente global se define la función f
con tres argumentos: x
(sin valor por defecto), y
y z
(opcionales). La función devuelve una combinación lineal de estas tres cantidades. En segundo lugar, se invoca sucesivamente la función f
para definir cuatro variables globales en el siguiente orden:
a = f(10) = f(10, 5, 10 + 5) = (10+5) - 10 - 5 = 0
b = f(10, 10) = f(10, 10, 10 + 10) = (10+10) - 10 - 10 = 0
c = f(10, 10, 10) = 10 - 10 - 10 = -10
d = f(10, z = 10) = f(10, 5, 10) = 10 - 10 - 5 = -5
Finalmente, se imprime el resultado de sumar las cuatro cantidades: 0 + 0 - 10 - 5 = -15
Hemos definido a las funciones como subalgoritmos que devuelven un objeto. En este caso no nos interesa devolver nada, sino sólo escribir mensajes en la consola, por eso podemos omitir el uso de return()
:
#' Resolviendo ecuaciones de segundo grado
#'
#' @description
#' Encuentra las soluciones de una ecuación de segundo grado a partir del uso de
#' la formula resolvente. Se deben ingresar los coeficientes del polinomio de
#' segundo grado asociado.
#'
#' @details
#' La función imprime un mensaje con el detalle de las soluciones, incluyendo si
#' esta ecuación tiene dos soluciones distintas, una solución doble o ninguna
#' solución dentro de los números reales. La función devuelve un mensaje de error
#' si el coeficiente cuadrático es 0.
#'
#' @param a,b,c Números reales
#'
#' @return NULL, junto con un mensaje con el detalle de las soluciones.
#'
#' @examples
#' resolvente(1, -1, -2)
#' resolvente(1, 2, 1)
#' resolvente(1, 1, 1)
#' resolvente(0, 1, 1)
#'
<- function(a, b, c) {
resolvente if (a == 0) {
stop("(a) debe ser distinto de cero")
}<- b^2 - 4 * a * c
discriminante if (discriminante > 0) {
<- (-b - sqrt(discriminante)) / (2 * a)
x1 <- (-b + sqrt(discriminante)) / (2 * a)
x2 cat("Hay dos soluciones reales", x1, "y", x2, "\n")
else if (discriminante == 0) {
} <- -b / (2 * a)
x1 cat("Hay una solución real doble:", x1, "\n")
else {
} cat("Las soluciones son complejas.\n")
} }
Ejemplo de uso:
resolvente(1, -1, -2)
Hay dos soluciones reales -1 y 2
resolvente(1, 2, 1)
Hay una solución real doble: -1
resolvente(1, 1, 1)
Las soluciones son complejas.
resolvente(0, 1, 1)
Error in resolvente(0, 1, 1): (a) debe ser distinto de cero
Comentarios adicionales. Como hemos mencionado, cuando no se incluye un return()
, igualmente la función devuelve algo, que es el resultado de la última expresión ejecutada. En todas las situaciones, en esta función la última expresión ejecutada es un cat()
. Además de escribir un texto, esta función devuelve un valor NULL
invisible (no se imprime en la consola, pero está). Podemos corrobar este comportamiento si usamos la función de esta forma:
# Imprime texto en la consola y devuelve un NULL, que se guarda enresultado
<- resolvente(1, -1, -2) resultado
Hay dos soluciones reales -1 y 2
# Imprimimos resultado y encontramos que tiene guardado un NULL
resultado
NULL
Sería interesante que esta función pueda devolver las soluciones. Hasta acá sabemos que las funciones pueden devolver un único objeto. Esto puede ser un inconveniente para este problema, ya que nos interesa devolver dos valores (dos soluciones reales), un valor (una solución real doble) o ningún valor (ninguna solución real). Más adelante veremos cómo hacer para poder devolver distinta cantidad de objetos, agrupándolos en otra estructura de datos.
La solución propone chequear primeramente que el número de entrada sea entero y positivo. Si detecta que una de estos requisitos no se cumple, emite un warning y devuelve FALSE
.
En caso de que se cumplan estos requisitos, el programa directamente devuelve TRUE
si el número analizado es 2 o 3, ya que sabemos que estos primeros naturales son primos. Para el resto de los números, divide a n
por todos los naturales desde el 2
hasta n - 1
. Si al hacer esta división, encuentra un resto igual a cero, significa que n
es compuesto. Si ninguna división produce resto cero, entonces n
es primo.
Por ejemplo, para n = 7
, se hace:
7 %% 2 = 1
, sigue.7 %% 3 = 1
, sigue.7 %% 4 = 3
, sigue.7 %% 5 = 2
, sigue.7 %% 6 = 1
, termina la iteración.TRUE
Para n = 9
, se hace:
9 %% 2
= 1, sigue.9 %% 3
= 0, devuelve FALSO.FALSE
.#' Evaluación de números primos
#'
#' @description
#' Determina si un número entero es primo o no.
#'
#' @details
#' La función devuelve un mensaje de advertencia si no se ingresa un número natural
#' mayor que 1. El resultado en este caso será FALSO.
#'
#' @param n Número natural
#'
#' @return Un valor lógico, TRUE si el número es primo, FALSE si no lo es.
#'
#' @examples
#' es_primo(47)
#' es_primo(253)
#' es_primo(2)
#'
<- function(n) {
es_primo if (n %% 1 != 0) {
warning("(n) no es entero")
return(FALSE)
}
if (n <= 1) {
warning("(n) no es mayor a 1")
return(FALSE)
}
if (n > 3) {
for (i in 2:(n - 1)) {
if (n %% i == 0) {
return(FALSE)
}
}
}
# solo se llega acá si no se devolvió FALSE antes, es decir, si n es primo
return(TRUE)
}
Ejemplos de uso:
es_primo(47)
[1] TRUE
es_primo(253)
[1] FALSE
es_primo(2)
[1] TRUE
es_primo(7.18)
Warning in es_primo(7.18): (n) no es entero
[1] FALSE
es_primo(0)
Warning in es_primo(0): (n) no es mayor a 1
[1] FALSE
Observación: se puede plantear un algoritmo más eficiente, que realice menos iteraciones. No es necesario iterar hasta n - 1
, si no hasta el entero inmediato menor a \(\sqrt{n}\). Si no se encontró que n
sea múltiplo de ningún valor menor a \(\sqrt{n}\), tampoco lo será con los que siguen. Por otro lado, sería suficiente hacer las divisiones con respecto a los números primos menores \(\sqrt{n}\). Se deja propuesto elaborar esta solución alternativa.
Para poder resolver una división usando solamente sumas y restas, tenemos que pensar que, por ejemplo, hacer 14 dividido 3 nos da cociente 4 y resto 2, porque el 3 “entra” 4 veces en el 14 y todavía sobran 2. Es decir, a 14 le podemos restar el 3 cuatro veces hasta que ya no se lo podamos restar más, quedando un resto de 2. Entonces la idea es empezar diciendo que el resto es el dividendo (al principio, nos resta todo el dividendo) y restarle iterativamente el valor del divisor hasta que el resto se haga menor que el divisor. Mientras tanto, tenemos que ir contando cuántas restas se hacen, puesto que eso será el valor del cociente. Ejemplo:
dividendo = 14
, divisor = 3
, resto = 14
.14 - 3 = 11
, digo que el resto
es 11 y cuento que ya hice una resta con cociente = 1
.11 - 3 = 8
, digo que el resto
es 8 y cuento que ya hice dos restas con cociente = 2
.8 - 3 = 5
, digo que el resto
es 5 y cuento que ya hice tres restas con cociente = 3
.5 - 3 = 2
, digo que el resto
es 2, cuento que ya hice cuatro restas con cociente = 4
.resto
menor que el divisor
, me detengo, con este resultado: cociente = 4
y resto = 2
.Como a priori no sabemos cuántas iteraciones de este proceso tenemos que hacer, empleamos un while
.
#' Cociente de la división de números naturales
#'
#' @description
#' Obtiene el cociente entero y el resto en la división de dos números naturales
#'
#' @details
#' La función imprime un mensaje con todos los detalles de la división, con el
#' dividendo, divisor, cociente y resto. Sin embargo, la función devuelve solo el
#' cociente entero.
#'
#' @param dividendo,divisor Números naturales.
#'
#' @return El cociente entero de la división de ambos números.
#'
#' @examples
#' cociente(1253, 4)
#' cociente(3, 4)
#'
<- function(dividendo, divisor) {
cociente <- dividendo
resto <- 0
cociente while (resto >= divisor) {
<- cociente + 1
cociente <- resto - divisor
resto
}cat("Dividendo:", dividendo, "\n")
cat("Divisor:", divisor, "\n")
cat("Cociente:", cociente, "\n")
cat("Resto:", resto, "\n")
return(cociente)
}
Ejemplos de uso:
cociente(1253, 4)
Dividendo: 1253
Divisor: 4
Cociente: 313
Resto: 1
[1] 313
cociente(3, 4)
Dividendo: 3
Divisor: 4
Cociente: 0
Resto: 3
[1] 0
#' Cálculo del máximo común divisor
#'
#' @description
#' Calcula el máximo común divisor entre dos números naturales
#'
#' @details
#' Aplica el algoritmo de Euclides para encontrar el MCD. Dividir al mayor por el
#' menor y registrar el resto. Si el resto es cero, el divisor es el MCD. Si el
#' resto no es cero, hay que dividir el divisor por el resto y hacer la misma
#' evaluación. Es decir, el divisor pasa a ser el nuevo dividendo y el resto, el
#' nuevo divisor. Así hasta obtener el resto cero y tener el MCD.
#'
#' @param a,b Números naturales.
#'
#' @return El máximo común divisor de ambos números.
#'
#' @examples
#' max_com_div(100, 24)
#' max_com_div(25, 100)
#' max_com_div(24, 24)
#'
<- function(a, b) {
max_com_div
# Establecer como dividendo al mayor y como divisor al menor
if (a > b) {
<- a
dividendo <- b
divisor else {
} <- b
dividendo <- a
divisor
}
# Iniciar al resto como igual al dividendo
<- dividendo
resto
# Aplicar algortimo de Euclides
while (resto != 0) {
# Dividir al mayor por el menor y registrar el resto
<- dividendo %% divisor
resto
# Si el resto es cero (lo chequearemos en la condición del while), el
# divisor es el mcd, por las dudas nos preparamos para entregarlo.
<- divisor
mcd
# Si el resto no es cero (lo chequearemos en la condición del while), hay
# que dividir el divisor por el resto y hacer la misma evaluación. Es decir,
# el divisor pasa a ser el nuevo dividendo y el resto, el nuevo divisor
<- divisor
dividendo <- resto
divisor
}
# Devolver mcd
return(mcd)
}
Ejemplos de uso:
max_com_div(100, 24)
[1] 4
max_com_div(25, 100)
[1] 25
max_com_div(24, 24)
[1] 24
Otra forma:
<- function(a, b) {
max_com_div # Establecer como dividendo al mayor y como divisor al menor
if (a > b) {
<- a
dividendo <- b
divisor else {
} <- b
dividendo <- a
divisor
}# Iniciar al resto como igual al dividendo
<- dividendo
resto # Aplicar algortimo de Euclides
while (resto > 0) {
<- dividendo %% divisor
resto if (resto == 0) return(divisor)
<- divisor
dividendo <- resto
divisor
} }
En el script funciones_unidad3.R
se implementa la función combinatorio(m,n)
y se guarda junto con fact()
. Su contenido debe ser:
# ---------------------------------------------------------------
# DEFINICIÓN DE FUNCIONES (funciones.R)
# ---------------------------------------------------------------
#' Cálculo de factoriales
#'
#' @description
#' Calcula el factorial de números enteros no negativos.
#'
#' @details
#' Produce un error si se quiere calcular el factorial de un número negativo.
#'
#' @param n Número entero no negativo para el cual se calcula el factorial.
#'
#' @return El factorial de n.
#'
#' @examples
#' fact(5)
#' fact(0)
#'
<- function(n) {
fact if (n < 0 || n != floor(n)) {
stop("n debe ser entero no negativo.")
}<- 1
resultado if (n > 0) {
for (i in 1:n) {
<- resultado * i
resultado
}
}return(resultado)
}
#' Cálculo de números combinatorios
#'
#' @description
#' Calcula números combinatorios invocando a la función fact()
#'
#' @param m,n números naturales
#'
#' @return El número combinatorio m en n
#'
#' @examples
#' combinatorio(3, 1)
#'
<- function(m, n) {
combinatorio return(fact(m) / (fact(m - n) * fact(n)))
}
El contenido del script ejercicio11.R
puede ser:
# ---------------------------------------------------------------
# PROGRAMA: "Ejemplificar propiedades de los nros combinatorios"
# ---------------------------------------------------------------
# Cargar funciones
source("funciones_unidad3.R")
cat("Propiedad 1: C(m, 0) = 1. Ejemplo:\n")
<- combinatorio(5, 0)
res1 cat("C(5, 0) =", res1, "\n\n")
cat("Propiedad 2: C(m, m) = 1. Ejemplo:\n")
<- combinatorio(5, 5)
res1 cat("C(5, 5) =", res1, "\n\n")
cat("Propiedad 3: C(m, 1) = m. Ejemplo:\n")
<- combinatorio(5, 1)
res1 cat("C(5, 1) =", res1, "\n\n")
cat("Propiedad 4: C(m, n) = C(m, m-n). Ejemplo:\n")
<- combinatorio(5, 2)
res1 <- combinatorio(5, 3)
res2 cat("C(5, 2) =", res1, "\n")
cat("C(5, 3) =", res2, "\n\n")
cat("Propiedad 5: C(m, n) = C(m-1, n-1) + C(m-1, n). Ejemplo:\n")
<- combinatorio(5, 2)
res1 <- combinatorio(4, 1) + combinatorio(4, 2)
res2 cat("C(5, 2) =", res1, "\n")
cat("C(4, 1) + C(4, 2) =", res2)
Propiedad 1: C(m, 0) = 1. Ejemplo:
C(5, 0) = 1
Propiedad 2: C(m, m) = 1. Ejemplo:
C(5, 5) = 1
Propiedad 3: C(m, 1) = m. Ejemplo:
C(5, 1) = 5
Propiedad 4: C(m, n) = C(m, m-n). Ejemplo:
C(5, 2) = 10
C(5, 3) = 10
Propiedad 5: C(m, n) = C(m-1, n-1) + C(m-1, n). Ejemplo:
C(5, 2) = 10
C(4, 1) + C(4, 2) = 10
A continuación, se prueba pasando un valor de n
mayor que m
:
combinatorio(4, 5)
Error in fact(m - n): n debe ser entero no negativo.
Como se observa, la función falla porque internamente se invoca a la función fact()
con un número negativo, y la misma fue programada para disparar un error en ese caso. El mensaje n debe ser entero no negativo
no es demasiado claro, dado que es emitido por la función fact()
y se refiere a su argumento n
, no al n
de combinatorio()
. Podríamos mejorar esta situación de varias formas. Una de ellas podría ser disparar un error antes, dentro de la función combinatorio()
, para evitar cualquier procesamiento si \(n>m\):
<- function(m, n) {
combinatorio if (n > m) {
stop("m debe ser menor o igual que n ")
}return(fact(m) / (fact(m - n) * fact(n)))
}
Se generaliza la función combinatorio(m, n)
para calcular números combinatorios con y sin reposición. Para esto se incluye el argumento r
, que toma el valor lógico TRUE
si el cálculo es con reposición o FALSE
en caso contrario.
Agregamos lo siguiente al archivo unidad3_funciones.R
. Notar que esta vez no usamos return()
, pero igualmetne se devuelve el resultado deseado por ser lo último que se evalúa:
#' Cálculo de números combinatorios
#'
#' @description
#' Calcula el número combinatorio m en n, con o sin reposición según r
#'
#' @param m,n números naturales
#' @param r valor lógico, sobre si el cálculo es con o sin repetición, F por defecto
#'
#' @return El número combinatorio m en n, con o sin reposición
#'
#' @examples
#' combinatorio2(10, 2, TRUE)
#' combinatorio2(10, 2)
#'
<- function(m, n, r = FALSE) {
combinatorio2 if (r) {
combinatorio(m + n - 1, n)
else {
} combinatorio(m, n)
} }
En el script ejercicio_11.R
probamos la nueva función:
# Números combinatorios con y sin reposición
<- 5
m <- 2
n cat(m, "tomados de a", n, "sin resposición:", combinatorio2(m, n), "\n")
cat(m, "tomados de a", n, "con resposición:", combinatorio2(m, n, TRUE))
5 tomados de a 2 sin resposición: 10
5 tomados de a 2 con resposición: 15
La cantidad de combinaciones con reposición siempre es mayor, salvo para n = 1
donde ambas coinciden.
La documentación se ha incluido en cada una de las respuestas anteriores.