Вы находитесь на странице: 1из 14

Solución de la asignación 1 del Curso de R

11 de julio de 2017

1. Soluciones
1.0.1. Solución 1
In [1]: x <-c(1,2,-3, 9, 0)
y <- c(2, 5,6, -1, 3)

min(outer(x, y, function(x, y) abs(x -y)))

In [2]: d = outer(x, y, function(x, y) abs(x - y))


cbind(row(d)[d == min(d)], col(d)[d == min(d)])

1.0.2. Solución 2
In [3]: # Solucion dada por Luis Vasquez Espinoza

par(mfrow = c(2,2), pty = "s", cex = .4)

# Grafica del seno y coseno


x <- seq(0, 6, 0.01)
y1 <- sin(x)
y2 <- cos(x)

plot(c(0,6), c(-1.0,1.0), type = "n", xlab = "x", ylab = "


sin(x) & cos(x)")
title(main = "Seno y Coseno")
lines(x, y1, type = "l", col ="red")
lines(x, y2, type = "l", lty= 3, col="green")
legend("bottomleft", inset = 0.05, c("coseno", "
seno"), lty = c(2, 1), col = c("
blue", "red"), text.width = 1.9)

# Espiral de lineas
plot(c(1,5), c(1,
5), type = "n", xlab = "
Eje X azul", ylab = "Eje Y azul")
title(main = substitute(paste(italic("Espiral de lineas "))))

1
axis(1, col = "blue")
axis(2, col = "blue")
lines(c(1:5), rep(1, 5), col = "green")
lines(rep(5, 5), c(1:5), col = "green")
lines(c(1:5), rep(5, 5), col = "green")
lines(rep(1, 4), c(2:5), col = "green")
lines(c(1:4), rep(2, 4), col = "green")
lines(rep(4, 3), c(2:4), col = "green")
lines(c(2:4), rep(4, 3), col = "green")
lines(rep(2, 2),c(3:4), col = "green")
lines(c(2:3), rep(3, 2), col = "green")

# Funcion logaritmo
x <- seq(1, 10, 0.01)
y3 <- log(x)
plot(c(1,10), c(0.0, 2.5
), type = "n", xlab = "coordenada x", ylab = "coordenada y")
title(main = "Función logaritmo")
lines(x, y3)
legend("bottomright", legend = "f(x) = log(x)", inset = .05)

# Circunferencias concentricas

# Circ. de radio r = 1
x <- seq(-1, 1, 0.001)
c1 <- sqrt(1 - x^2)
c2 <- -c1
plot(c(-4,4), c(-4
,4), type = "n", xlab = "Eje x [-4;4]", ylab = "Eje y [-4;4]")
title(main = "Circunferencias concéntricas")
lines(x, c1, col = "orange")
lines(x, c2, col = "orange")

#Circ. de radio r = 2
x <- seq(-2, 2, 0.001)
c1 <- sqrt(2^2 - x^2)
c2 <- -c1

lines(x, c1, lty = 2, col = "green" )


lines(x, c2, lty = 2 , col ="green")

#Circ. de radio r = 3
x <- seq(-3, 3, 0.001)
c1 <- sqrt(3^2 - x^2)
c2 <- -c1

lines(x, c1, lty = 3)

2
lines(x, c2, lty = 3)

legend("bottomright", inset = 0.05, c("Radio-1",


"Radio-2", "Radio-3"), lty = c(1, 2, 3))

1.0.3. Solución 3
In [4]: # Codigo del problema. Solucio dada por Luis Vasquez Espinoza.

options(width = 60)
sample(c(-1,1), size = 100, replace = TRUE)

win <- sample(c(-1,1), size = 100, replace = TRUE)


cum.win <- cumsum(win)
cum.win

par(mfrow = c(2,2))
for(j in 1:4){
win = sample(c(-1,1), size = 100, replace = TRUE)
plot(cumsum(win), type = "l" , ylim = c(-15,15))
abline(h = 0)
}

Respuesta:

In [5]: #Escribimos función *ResultadoPartida*, que ingresan cantidad


# de lanzamientos de monedas y retorna una ganancia de Pedro

ResultadoPartida <- function(lanzamientos) {


resultado <- sample(c(-1, 1), lanzamientos, replace = T)
return(sum(resultado))
}

# lanzamientos 100 de acuerdo al problema

resultados <- c()


for(i in 1:10000){
resultados <- c(resultados, ResultadoPartida(100))
}

informacion <- table(resultados) # almacenamos en una tabla

perdida <- informacion["0"]

# Calculamos la probabilidad aproximada

perdida1 <- as.numeric(perdida/10000)


print(perdida1)

3
[1] 0.0816

Respuesta:

In [6]: # Hallemos el numero de turnos a favor de Pedro

TurnosAFavor <- function(cant_lanzam) {


resultado <- c(0) # Iniciamos la partida con Pedro teniendo 0 dolares
resultado <- c(resultado, sample(c(
-1, 1), cant_lanzam - 1, replace = T))
resultado_acumulado <- cumsum(resultado)

# Retornamos las veces que se acumulo una cantidad de dinero


return(sum(resultado_acumulado > 0))
}

# Realizamos simulaciones
turnos_victoriosos <- c()
for(i in 1:10000){
turnos_victoriosos <- c(turnos_victoriosos, TurnosAFavor(100))
}
turnos_victoriosos <- table(turnos_victoriosos)
print(turnos_victoriosos)

prob_turnos_victoriosos <- c()


for(i in 1:100) {
prob_turnos_victoriosos <- c(prob_turnos
_victoriosos, turnos_victoriosos[i]/10000)
}

# Calculemos el valor de cantidad que Pedro va ganando


resultado <- 0
for(i in 1:100){
resultado <- resultado + (i - 1)*prob_turnos_victoriosos[i]
}

print(as.numeric(resultado))

In [7]: # Calculamos el valor máximo de la cantidad de Pedro durante un juego

GananciaMax <- function(cant_lanzam) {


resultado <- c(0) # Iniciamos la partida con Pedro teniendo 0 dolares
resultado <- c(resultado, sample(c(-1, 1), cant_lanzam - 1
, replace = T))
resultado_acumulado <- cumsum(resultado)
# Retornamos la cantidad de veces que se tiene dinero
return(max(resultado_acumulado))

4
}

GananciaMax(100)

1.0.4. Solución 4
In [8]: # Esta funcion no tiene casos entremos como len(xVect) = 0

tmpFn1 <- function(xVec)


{
xVec^(1:length(xVec))
}
tmpFn2 <- function(xVec)
{
n <- length(xVec)
(xVec^(1:n))/(1:n)
}

tmpFn1(1:3)
tmpFn2(1:3)

In [9]: # No se coloca la condicion de que n > 0

tmpFn3 <- function(x, n)


{
1 + sum((x^(1:n))/(1:n))
}

1.0.5. Solución 5
In [10]: # Imprimimos la cuadricula. Solución dada por Jesús Rodriguez Felices

s <- matrix(0, ncol = 9, nrow = 9)


s[1,c(6,8)] = c(6,4)
s[2,c(1:3,8)] = c(2,7,9,5)
s[3,c(2,4,9)] = c(5,8,2)
s[4,3:4] = c(2,6)
s[6,c(3,5,7:9)] = c(1,9,6,7,3)
s[7,c(1,3:4,7)] = c(8,5,2,4)
s[8,c(1,8:9)] = c(3,8,5)
s[9,c(1,7,9)] = c(6,9,1)

5
0 0 0 0 0 6 0 4 0
2 7 9 0 0 0 0 5 0
0 5 0 8 0 0 0 0 2
0 0 2 6 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 1 0 9 0 6 7 3
8 0 5 2 0 0 4 0 0
3 0 0 0 0 0 0 8 5
6 0 0 0 0 0 9 0 1
In [11]: pool <- array(TRUE, dim = c(9,9,9))

#Revisamos cada entrada de s para actualizar las entradas de pool


for(i in 1:9)
for(j in 1:9){
if(s[i,j] != 0){
# Descartamos todos los posibles valores en la casilla s[i,j]
pool[i,j,1:9] <- FALSE
# Esto es para descartar el valor s[i,j] de toda la columna j
pool[1:9,j,s[i,j]] <- FALSE
# Esto es para descartar el valor s[i,j] de toda la fila i
pool[i,1:9,s[i,j]] <- FALSE

# Ahora descartaremos el valor de s[i,j] del bloque de 3x3


index1 <- 3*(ceiling(i / 3) -1) + 1
index2 <- 3*(ceiling(j / 3) -1) + 1
for(a in 0:2)
for(b in 0:2)
pool[index1 + a, index2 + b, s[i,j]] <- FALSE
}
}

Respuesta s[i] es la entrada de la matriz s que se encuentra en la columna ceiling(i/9)


y en la fila i -9*(ceiling(i/9)-1), ello lo podemos comprobar ejecutando en el siguiente
codigo R, el cual imprimirá FALSE y el valor del índice en el cual no se cumpla esta igualdad.

In [12]: for(i in 1:81){


if(s[i] != s[i-9*(ceiling(i/9)-1), ceiling(i/9)])
print(c(FALSE, i))
}

Comencemos por explicar que hace la función trunc(), esta función toma un argumento
numerico y retorna el siguiente entero entre dicho numero y el 0, es como un floor para los
positivos y un ceiling para los negativos. Como las entradas de la matriz están numeradas del
1 al 9, los bloques de 3x3 estarán divididos en los valores 1:3, 4:6 y 7:9. Tomando un a cualquiera
de 1:9, se cumplirá que:

3k < a ≤ 3(k + 1),


como a es un entero tenemos que:

6
3k ≤ a − 1 < 3(k + 1) = k ≤ (a − 1)/3 < k + 1,
Entonces, $k = trunc((a-1)/3) $.
De ello, 3*trunc((a-1)/3) nos dará el valor del múltiplo de 3 que está inmediatamente
antes que a. Los valores del bloque de 3 en el que esta contenido a son 3k+1, 3k+2 y 3k+3 y
ello es lo que se obtiene al sumar 1 a boxa y luego crea un vector desde ese valor hasta los dos
siguientes.
Por tanto, boxa nos dá el bloque de 3 en el que está contenido a y boxb nos da el bloque de 3
en el que está contenido b y al juntar ambos obtenemos el bloque de 3x3 en el que está contenida
la entrada (a,b).

In [13]: boxa <- 3 * trunc((a-1)/3) + 1


boxa <- boxa:(boxa + 2)
boxb <- 3 * trunc((b-1)/3) + 1
boxb <- boxb:(boxb + 2)

Respuesta: La instrucción for hará que u tome los valores de los indices para los que se cum-
pla que pool[a,b,u] es diferente de cero, es decir, pool[a,b,u] = TRUE. Debido a ello es
que el bucle solo iterará sobre aquellos posibles valores para la entrada s[a,b] que aún no han
sido descartados. Antes de continuar, cabe resaltar que en una suma de valores lógicos (TRUE,
FALSE) a TRUE se le asocia el valor de 1 y FALSE el valor de 0. La única instrucción dentro del
bucle for verificará si dicho valor, u, aún es un candidato a la casilla (a,b) y modificará el valor
de la entrada pool[a,b,u] a FALSE en caso ya no sea un candidato.
Para ello se hace uso de 3 sumas de valores logicos, la primera verificará que el valor de u
no se repita en ninguna otra entrada de la fila a, la segunda suma verifica que u no este presente
en alguna otra entrada de la columna b y la última suma verifica el bloque de 3x3 en el que se
encuentra la entrada (a,b). Es suficiente que una de las igualdades a verificar sea TRUE para que
el resultado de la suma sea diferente de 0, y por ende, u quedará descartado como un candidato a
la entrada (a,b).
El resultado será 0 únicamente cuando todas las igualdades a verificar son falsas, y por tanto
ninguna otra entrada que pueda restringir el valor de u tiene dicho valor, por consiguiente, u
seguirá siendo un candidato a la entrada (a,b).

In [14]: for(u in (1:9)[pool[a,b,]])


pool[a,b,u] <- (sum
(u == s[a,]) + sum(u == s[,b]) + sum(u == s[boxa,boxb])) == 0

El segundo codigo R mostrado verifica si sólo existe un único candidato para la entrada (a,b),
pues si la suma es mayor o igual a 2 nos indicaría que hay 2 o más entradas TRUE en pool[a,b]
y si fuera 0 nos indicaría que el sudoku no se puede resolver o hicimos alguna mala operación.
Dado que solo existe un valor TRUE en pool[a,b,], (1:9)[pool[a,b,]] solo retornará un
valor, y dicho valor será asignado a la entrada s[a,b] pues es el único candidato a dicha entrada
y por tanto es el valor que debería ir ahí.

In [15]: if (sum(pool[a,b,])==1) s[i]=(1:9)[pool[a,b,]]

In [16]: # Resolvemos la cuadrícula con una exploración de entradas (a, b)


# si um(s == 0)> 0

7
while(sum(s == 0) > 0){
# Seleccionamos la entrada de manera aleatoria
a <- ceiling(runif(1, min = 0, max = 9))
b <- ceiling(runif(1, min = 0, max = 9))

if(s[a,b] == 0 && sum(pool[a,b,]) == 1){


s[a,b] <- (1:9)[pool[a,b,]]
pool[a,b,1:9] <- FALSE
pool[1:9,b,s[a,b]] <- FALSE
pool[a,1:9,s[a,b]] <- FALSE

boxa <- 3 * trunc((a-1)/3) + 1


boxa <- boxa:(boxa + 2)
boxb <- 3 * trunc((b-1)/3) + 1
boxb <- boxb:(boxb + 2)

pool[boxa,boxb,s[a,b]] <- FALSE


}
}
# Mostrando sudoku resuelto
s
1 3 8 5 2 6 7 4 9
2 7 9 3 4 1 8 5 6
4 5 6 8 7 9 3 1 2
7 4 2 6 3 5 1 9 8
9 6 3 1 8 7 5 2 4
5 8 1 4 9 2 6 7 3
8 9 5 2 1 3 4 6 7
3 1 7 9 6 4 2 8 5
6 2 4 7 5 8 9 3 1

1.0.6. Solución 6
In [17]: # version for:
v = 0
for(i in 1:8) {
v = 10 * v + 8
cat(8 * v + 13, "\n")
}

77
717
7117
71117
711117
7111117

8
71111117
711111117

In [18]: # version vectorizada

8 * cumsum(10^(0:7)) * 8 + 13

1.0.7. Solución 7
In [19]: set.seed(50)
xVec <- sample(0:999, 250, replace=T)
yVec <- sample(0:999, 250, replace=T)

yVec[-1] - xVec[-length(xVec)]

In [20]: sin(yVec[-length(yVec)]) / cos(xVec[-1])

In [22]: sum(exp(-xVec[-1])/(xVec[-length(xVec)]+10))

0.0126987204660891

1.0.8. Solución 8
Asumiremos que el palillo tiene longitud 1 (por la opción de unidades). Podemos generar los
cuatro extremos de las partes y las longitudes de las partes de la siguiente manera.

In [23]: extremos = c(0, sort(runif(2)), 1)


longitudes = diff(extremos)

Los palillos se pueden ensamblar en un triángulo si la suma de las longitudes de las dos piezas
más pequeñas es mayor que la longitud del más grande.

In [24]: longitudes = sort(longitudes)


sum(longitudes[1:2]) >= longitudes[3]

TRUE
Todo lo que necesitamos hacer ahora es agrupar esto en una función de simulación.

In [25]: palillosim =function(n) {## seleccionamos los dos puntos de division


u1 = runif(n)
u2 = runif(n)

## Obtenemos la matriz de puntos extremos del palillo


extremos = cbind(0, pmin(u1, u2), pmax(u1, u2), 1)

## Obtenemos las longitudes del palillo


l1 = extremos[,2] - extremos[,1]
l2 = extremos[,3] - extremos[,2]
l3 = extremos[,4] - extremos[,3]

9
## Prueba del triangulo
mean(l1 + l2 >= l3)
}

palillosim(10000000)

0.7497734

In [26]: # Una posible solucion

tmpFn4 <- function(mat)


{
mat[mat%%2 == 1] <- 2 * mat[mat%%2 == 1]
mat
}
mat <- matrix( c(1, 1, 3, 5, 2, 6, -2, -1,
-3), nrow=3, ncol=3, byrow = TRUE)
mat
tmpFn4(mat)

1 1 3
5 2 6
-2 -1 -3
2 2 6
10 2 6
-2 -2 -6

1.0.9. Solución 9
Primero is.na(x) produce un vector lógico que contiene TRUE y FALSE dependiendo de
que si el valor correspondiente de x es NA o NaN. El operador ! invierte los valores TRUE y
FALSE. Finalmente, sum coacciona los valores lógicos a valores numéricos 0-1 y los suma.
El resultado es el número de valores de “no faltantes” en x.

La expresión x[-(1: length(x))] excluye todos los valores de x y produce un resultado


de longitud cero. Cuando x y este se concatenan, el resultado es idéntico a x.

La expresión x[length(x) + 1] produce NA. Cuando se divide por length(x) el resul-


tado es NA.

La expresión x> mean(x) produce un vector de valores TRUE y FALSE que indican si los
valores en x son mayores que su media. Cuando se aplica sum a este valor, los valores se
coaccionan a valores 0-1 y se suman. El resultado es un recuento del número de valores en
x que exceden su media. (Sin embargo, si x contiene valores de NA, el resultado será NA).

In [27]: # Usando un bucle for

X <- matrix( c(2, 4,


3, 1, 5, 7), nrow=2, ncol=3, byrow = TRUE) # Ejemplo

10
fila = NA
for(i in 1:nrow(X))
if (all(!is.na(X[i,]) & X[i,] > 0)) {
fila = i
break
}

In [28]: # Usando apply()

apply(X, 1, function(x) all(!is.na(x) & x > 0))[1]

TRUE

In [29]: # Primera solucion

Hilbert <- function(n) {


A <- matrix(rep(NA, n*n), nrow=n)
for(i in 1:n){
for(j in 1:n){
A[i, j] <- 1/(i+j-1)
}
}
return(A)
}

In [30]: # Segunda solucion

Hilbert <- function(n) {


outer(1:n, 1:n, function(x, y) 1/(x+y-1))
}

Respuesta: Las matrices de Hilbert son invertibles. Toda la información de matrices de Hilbert,
aqui.

In [31]: # Algunos ejemplos

qr.solve(Hilbert(1))

In [32]: qr.solve(Hilbert(4))

16 -120 240 -140


-120 1200 -2700 1680
240 -2700 6480 -4200
-140 1680 -4200 2800

In [33]: qr.solve(Hilbert(6))

11
36 -630 3360 -7560 7560 -2772
-630 14700 -88200 211680 -220500 83160
3360 -88200 564480 -1411200 1512000 -582120
-7560 211680 -1411200 3628800 -3969000 1552320
7560 -220500 1512000 -3969000 4410000 -1746360
-2772 83160 -582120 1552320 -1746360 698544
Respuesta: En el código iguiente ,uno de los autovalores está cerca de 1013 , que es muy peque-
ño, mientras que el autovalor más grande es superior a 1. Por lo tanto, las columnas de la matriz
están cerca de ser linealmente dependientes y eso produce un error.

In [34]: # Si hacemos los valores de los autovalores de Hilbert(10)

eigen(Hilbert(10))$values

1.0.10. Solucion 10
In [35]: # Problema de un juego de tenis. Solución dada por Victor Galvan Oyola.

p <- 0.3
juegos <- 0.0
sets <- 0.0
partidos <- 0.0
tiebreak <- 0.0
tablaj <- matrix(0,nrow = 13,ncol=13)
visj <- matrix(F,nrow = 13,ncol=13)
tablas <- matrix(0,nrow = 7, ncol = 7)
viss <- matrix(F,nrow = 13,ncol=13)

# Se transforman los estados de i,j -> i+1,j+1 para que no haya


# contradiccion con los indices
# Los casos base (0,0) se transforman a (1,1) y se les asigna 1.0
#como valor trivial de multiplicacion

dpj <- function(win, lose){


if(win==1 && lose==1){
return(1.0)
}
if(visj[win,lose]){
return(tablaj[win,lose])
}
ans = 0.0
if(win == 1){
ans = ans + (1-p)*dpj(win,lose-1)
} else if (lose == 1){
ans = ans + p*dpj(win-1,lose)
} else{
ans = ans + p*dpj(win-1,lose)+(1-p)*dpj(win,lose-1)
}

12
visj[win,lose] = T
tablaj[win,lose] = ans
return(ans)
}

dps <- function(win, lose){


if(win==1 && lose==1){
return(1.0)
}
if(viss[win,lose]){
return(tablas[win,lose])
}
ans = 0.0
if(win == 1){
ans = ans + (1-juegos)*dps(win,lose-1)
} else if (lose == 1){
ans = ans + juegos*dps(win-1,lose)
} else{
ans = ans + juegos*dps(win-1,lose)+(1-juegos)*dps(win,lose-1)
}
viss[win,lose] = T
tablas[win,lose] = ans
return(ans)
}

for (i in c(1:3)){
juegos = juegos + p*dpj(4,i)
}
juegos = juegos + dpj(4,4)*p*p/(2*p*p-2*p+1)

for (i in c(1:5)){
sets = sets + juegos*dps(6,i)
}
for (i in c(1:6)){
tiebreak = tiebreak + p*dpj(7,i)
}
tiebreak = tiebreak + dpj(7,7)*p*p/(2*p*p-2*p+1)
sets = sets + dps(6,6)*(juegos*juegos + 2*juegos*(1-juegos)*tiebreak)
partidos = sets*sets + 2*sets*sets*(1-sets)

# Imprimimos los valores de cada respuesta


cat(sprintf(c("Juego=%.11f"
, "Set=%.11f","Partido=%.11f"), c(juegos,sets,partidos)), sep=" ")

13
Juego=0.09921103448 Set=0.00016770463 Partido=0.00000008437

1.0.11. Solución 11
In [36]: # Prueba Experimental

prueba <- sample(0:1, 3, replace=TRUE)


# Exito
if (sum(prueba )==3) 1 else 0

# Repeticion

n <- 10000 # Numero de iteraciones


simlista <- replicate(n, 0) ## Inicializa la lista con 0's

for (i in 1:n)
{
prueba <- sample(0:1, 3, replace=TRUE)
exito <- if (sum(prueba )==3) 1 else 0
simlista[i] <- exito
}
# Resultado simulado
mean(simlista)

0
0.1255

In [37]: # Codigo modificado


n<-10000

simlista<-replicate(n,0)#lista de intentos vacia


for(i in 1:n){
#Se cambia 3 por 4 ya que se requieren cuatro lanzamientos por prueba
prueba<-sample(0:1,4,replace = TRUE)
#Solo necesitamos un 1 para saber que se ha obtenido solo 1 cara
exito<-if(sum(prueba)==1) 1 else 0
simlista[i]<-exito
}
mean(simlista)

0.2532

In [ ]:

14

Вам также может понравиться