library(tidyverse)

징검다리문제풀이

(풀이1)

- (유리, 강화유리)

set = c('tempered glass','glass')
set
[1] "tempered glass" "glass"         

- sample을 이용하여 0.8의 확률로 강화유리를 뽑음

sample(size=5, set, prob=c(0.8,0.2),replace=T)
[1] "tempered glass" "tempered glass" "tempered glass" "glass"         
[5] "tempered glass"

- 함수로 보기좋게 만들자.

simulate_once = function() sample(size=5, set, prob=c(0.8,0.2),replace=T) #입력이 없는 함수
simulate_once()
[1] "glass"          "tempered glass" "tempered glass" "tempered glass"
[5] "tempered glass"

- 뽑은결과를 바탕으로 사망유무를 판단

a = simulate_once()
a
[1] "tempered glass" "tempered glass" "tempered glass" "glass"         
[5] "tempered glass"
a[1] == "tempered glass" & 
a[2] == "tempered glass" & 
a[3] == "tempered glass" & 
a[4] == "tempered glass" & 
a[5] == "tempered glass"
[1] FALSE
  • 조건

- 위의 조건이 참이면 b=1, 참이 아니라면 b=0

if (a[1] == "tempered glass" &
    a[2] == "tempered glass" & 
    a[3] == "tempered glass" & 
    a[4] == "tempered glass" & 
    a[5] == "tempered glass"){
    b=1
    }else{
    b=0}
b
[1] 0

- 함수로 정리하자.

test = function(a){
    if (a[1] == "tempered glass" &
        a[2] == "tempered glass" & 
        a[3] == "tempered glass" & 
        a[4] == "tempered glass" & 
        a[5] == "tempered glass") b=1 else b=0 
    b
}
a=simulate_once()
print(a)
test(a)
[1] "tempered glass" "tempered glass" "tempered glass" "tempered glass"
[5] "tempered glass"
[1] 1

- 답을 구해보자

sum_ = 0 
for (i in 1:1000) sum_ = sum_ + test(simulate_once())
sum_
[1] 322

(풀이2)

- 시행결과를 벡터로하는 편이 좋겠다.

set = c('tempered glass','glass')
simulate_once = function() sample(size=5, set, prob=c(0.8,0.2),replace=T) #입력이 없는 함수
test = function(a){
    if (a[1] == "tempered glass" &
        a[2] == "tempered glass" & 
        a[3] == "tempered glass" & 
        a[4] == "tempered glass" & 
        a[5] == "tempered glass") b=1 else b=0 
    b
}
# sum_ = 0 
# for (i in 1:1000) sum_ = sum_ + test(simulate_once())  컨트롤+/ (Rstudio: 컨트롤+쉬프트+c) 
rslt = c()
for (i in 1:1000) rslt[i] = test(simulate_once())
rslt
  [1] 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0
 [38] 0 0 0 1 0 0 0 1 1 0 0 1 0 1 0 0 1 0 1 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 1
 [75] 0 1 1 1 1 0 1 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0
[112] 0 0 1 0 1 0 1 0 1 0 0 0 0 1 0 0 0 1 1 1 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 1 1
[149] 1 0 0 0 0 1 0 0 1 1 1 0 0 1 1 1 0 1 0 1 0 0 1 0 1 1 0 1 0 1 0 0 1 1 1 0 0
[186] 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0
 [ reached getOption("max.print") -- omitted 800 entries ]
sum(rslt)
[1] 317

(풀이3)

- 시뮬레이션 결과를 매트릭스에 저장하면 더 디버깅이 용이하다.

mat = rep(0,1000*5) 
dim(mat) = c(1000,5) 
head(mat)
     [,1] [,2] [,3] [,4] [,5]
[1,] 0    0    0    0    0   
[2,] 0    0    0    0    0   
[3,] 0    0    0    0    0   
[4,] 0    0    0    0    0   
[5,] 0    0    0    0    0   
[6,] 0    0    0    0    0   
mat[1,]
[1] 0 0 0 0 0
mat[1,] = simulate_once()
head(mat)
     [,1]  [,2]           [,3]           [,4]           [,5] 
[1,] glass tempered glass tempered glass tempered glass glass
[2,] 0     0              0              0              0    
[3,] 0     0              0              0              0    
[4,] 0     0              0              0              0    
[5,] 0     0              0              0              0    
[6,] 0     0              0              0              0    
for (i in 1:1000) mat[i,] = simulate_once()
head(mat)
     [,1]           [,2]           [,3]           [,4]           [,5]          
[1,] tempered glass tempered glass tempered glass tempered glass tempered glass
[2,] glass          tempered glass tempered glass tempered glass glass         
[3,] tempered glass tempered glass tempered glass tempered glass tempered glass
[4,] tempered glass tempered glass tempered glass tempered glass tempered glass
[5,] tempered glass tempered glass glass          glass          tempered glass
[6,] tempered glass tempered glass tempered glass glass          tempered glass
rslt=c() 
for (i in 1:1000) rslt[i] = test(mat[i,])
rslt[1:5]
[1] 1 0 1 1 0
mat[1:5,]
     [,1]           [,2]           [,3]           [,4]           [,5]          
[1,] tempered glass tempered glass tempered glass tempered glass tempered glass
[2,] glass          tempered glass tempered glass tempered glass glass         
[3,] tempered glass tempered glass tempered glass tempered glass tempered glass
[4,] tempered glass tempered glass tempered glass tempered glass tempered glass
[5,] tempered glass tempered glass glass          glass          tempered glass

- 정리하면

set = c('tempered glass','glass')
simulate_once = function() sample(size=5, set, prob=c(0.8,0.2),replace=T) #입력이 없는 함수
test = function(a){
    if (a[1] == "tempered glass" &
        a[2] == "tempered glass" & 
        a[3] == "tempered glass" & 
        a[4] == "tempered glass" & 
        a[5] == "tempered glass") b=1 else b=0 
    b
}
mat = rep(0,1000*5) 
dim(mat) = c(1000,5) 
rslt = c()
# for (i in 1:1000) rslt[i] = test(simulate_once())
for (i in 1:1000){
    mat[i,] = simulate_once() 
    rslt[i] = test(mat[i,])
}
sum(rslt)
[1] 329

(풀이4)

- 어차피 mat 매트릭스만 만들면 되니까

set = c('tempered glass','glass')
mat= sample(size=1000*5, set, prob=c(0.8,0.2),replace=T) #입력이 없는 함수
dim(mat)=c(1000,5)
head(mat)
     [,1]           [,2]           [,3]           [,4]           [,5]          
[1,] glass          tempered glass glass          tempered glass tempered glass
[2,] tempered glass tempered glass glass          tempered glass glass         
[3,] tempered glass tempered glass tempered glass glass          glass         
[4,] tempered glass tempered glass tempered glass glass          tempered glass
[5,] tempered glass tempered glass tempered glass tempered glass tempered glass
[6,] tempered glass tempered glass tempered glass tempered glass tempered glass
test = function(a){
    if (a[1] == "tempered glass" &
        a[2] == "tempered glass" & 
        a[3] == "tempered glass" & 
        a[4] == "tempered glass" & 
        a[5] == "tempered glass") b=1 else b=0 
    b
}
rslt = c()
for (i in 1:1000){
    rslt[i] = test(mat[i,])
}
sum(rslt)
[1] 326

(풀이5)

- 매트릭스의 원소가 꼭 문자열일 필요는 없는것 같음

set = c(1,0)
mat= sample(size=1000*5, set, prob=c(0.8,0.2),replace=T) #입력이 없는 함수
dim(mat)=c(1000,5)
head(mat)
     [,1] [,2] [,3] [,4] [,5]
[1,] 1    1    1    1    1   
[2,] 1    0    1    1    1   
[3,] 1    1    1    1    1   
[4,] 0    1    1    0    1   
[5,] 1    1    1    1    1   
[6,] 0    1    1    1    1   
test = function(a){
    if (a[1] == 1 &
        a[2] == 1 & 
        a[3] == 1 & 
        a[4] == 1 & 
        a[5] == 1) b=1 else b=0 
    b
}
rslt = c()
for (i in 1:1000){
    rslt[i] = test(mat[i,])
}
sum(rslt)
[1] 355

- 조건도 아래와 같이 간소화할 수있다.

test = function(a){
    if (sum(a)==5) b=1 else b=0 
    b
}
rslt = c()
for (i in 1:1000){
    rslt[i] = test(mat[i,])
}
sum(rslt)
[1] 355

- 아래와 같이 바꿔도 가능

test = function(a){
    if (prod(a)==1) b=1 else b=0 
    b
}
rslt = c()
for (i in 1:1000){
    rslt[i] = test(mat[i,])
}
sum(rslt)
[1] 355

- test함수 자체도 아래와 같이 간소화 가능

test = function(a){
    prod(c(1,0,1,1,1))==1
}

- 정리하면

set = c(1,0)
mat= sample(size=1000*5, set, prob=c(0.8,0.2),replace=T) #입력이 없는 함수
dim(mat)=c(1000,5) 
head(mat)
     [,1] [,2] [,3] [,4] [,5]
[1,] 1    1    1    1    1   
[2,] 1    1    1    0    1   
[3,] 0    0    1    1    1   
[4,] 1    1    1    1    1   
[5,] 1    0    1    0    1   
[6,] 0    1    0    1    1   
test = function(a) prod(a)==1
rslt = c()
for (i in 1:1000){
    rslt[i] = test(mat[i,])
}
sum(rslt)
[1] 334

(풀이6)

- 숫자로 만들고 보니까 베르누이로 뽑아도 괜찮을 것 같다.

rbinom(5,size=1,prob=0.8) # 하나의행
[1] 1 1 1 1 1
  • set을 만들 필요가 없음
mat = rbinom(1000*5,size=1,prob=0.8) 
dim(mat)=c(1000,5) 
head(mat)
     [,1] [,2] [,3] [,4] [,5]
[1,] 1    1    1    1    0   
[2,] 1    1    1    1    1   
[3,] 1    1    1    1    1   
[4,] 1    1    0    1    1   
[5,] 1    1    1    1    0   
[6,] 1    1    1    1    1   
test = function(a) prod(a)==1
rslt = c()
for (i in 1:1000){
    rslt[i] = test(mat[i,])
}
sum(rslt)
[1] 341

(풀이7)

- 매트릭스 옆에 결과를 붙여보자.

mat = rbinom(1000*5,size=1,prob=0.8) 
dim(mat)=c(1000,5) 
head(mat)
     [,1] [,2] [,3] [,4] [,5]
[1,] 1    1    1    1    1   
[2,] 1    0    1    1    1   
[3,] 1    1    1    0    1   
[4,] 1    1    0    0    1   
[5,] 1    0    0    1    0   
[6,] 0    1    1    0    1   
test = function(a) prod(a)==1
rslt = c()
for (i in 1:1000){
    rslt[i] = test(mat[i,])
}
cbind(mat,rslt)[1:20,]
                rslt
 [1,] 1 1 1 1 1 1   
 [2,] 1 0 1 1 1 0   
 [3,] 1 1 1 0 1 0   
 [4,] 1 1 0 0 1 0   
 [5,] 1 0 0 1 0 0   
 [6,] 0 1 1 0 1 0   
 [7,] 1 1 0 0 1 0   
 [8,] 0 1 1 1 1 0   
 [9,] 1 1 1 1 1 1   
[10,] 0 1 1 0 1 0   
[11,] 1 1 1 0 1 0   
[12,] 0 1 1 1 0 0   
[13,] 1 1 1 1 1 1   
[14,] 1 1 1 0 0 0   
[15,] 1 1 1 1 1 1   
[16,] 1 1 1 1 1 1   
[17,] 1 1 1 1 1 1   
[18,] 1 1 1 1 1 1   
[19,] 0 1 1 1 1 0   
[20,] 0 1 1 1 0 0   

(풀이8) for문을 하나도 사용하지 않은 풀이

- 매트릭스의 각 row에 어떠한 함수를 반복적으로 적용하는 형태임 $\to$ apply

mat = rbinom(1000*5,size=1,prob=0.8) 
dim(mat)=c(1000,5) 
head(mat)
     [,1] [,2] [,3] [,4] [,5]
[1,] 0    1    1    1    1   
[2,] 0    1    0    1    1   
[3,] 1    1    0    1    1   
[4,] 1    1    1    1    1   
[5,] 0    1    1    0    0   
[6,] 1    1    0    1    1   
sum(apply(mat,1,test))
[1] 331
apply(mat,1,test) %>% sum
[1] 331
mat %>% apply(1,test) %>% sum
[1] 331

(풀이9)

- 바이노미알 이용: 어차피 베르누이의 합은 바이노미알이라고 했음

sum(rbinom(1000,size=5,p=0.8)==5)
[1] 344

숙제

징검다리 문제

강화유리와 유리를 랜덤으로 찍는 참가자가 2명 있다고 하자. (따라서 강화유리를 고를 확률이 50%이다.)

(강화유리, 유리)의 징검다리가 3개 있다고 하자. (따라서 총 6개의 유리가 있고, 3번연속으로 강화유리를 고르면 2명 모두 살아남는다)

8000번의 시뮬레이션을 하였을 경우 아래의 질문에 답하라.

(질문1) 2명 모두 살아남는 경우는 몇번인가? 약 1000번

(질문2) 1명만 살아남는 경우는 몇번정도인가? 약 3000번 정도..

(풀이)

질문1: 확률이 0.5인 시행을 3번하여 3번 모두 성공하는 경우

sum(rbinom(8000,size=3,p=0.5)==3)
1003

질문2: 확률이 0.5인 시행을 3번하여 2번 성공하는 경우

sum(rbinom(8000,size=3,p=0.5)==2)
3003