강의영상

- (1/4) 프로그래밍의 중요성

- (2/4) 숫자 카드 게임 apply함수를 이용한 풀이, 매트릭스 선언방법, 매트릭스에서 원소를 추출하는 방법

- (3/4) 매트릭스를 사용할시 얻는 이점, apply함수 사용법 (1)

- (4/4) apply함수 사용법 (2), for와 apply코드시간비교, 과제설명

숫자 카드 게임 (2019 국가 교육기관 코딩테스트)

숫자 카드 게임은 여러개의 숫자중에서 가장 높은 숫자가 쓰인 카드를 한장 뽑는 게임이다.

단, 게임의 룰을 지키며 카드를 뽑아야 하고 룰은 다음과 같다.

  • 숫자가 쓰인 카드들이 N$\times$M 형태로 놓여 있다.
  • 먼저 뽑고자 하는 카드가 포함되어 있는 행을 선택한다.
  • 그 다음 선택된 행에 포함된 카드들 중에서 가장 숫자가 낮은 카드를 뽑아야 한다.
  • 따라서 처음에 카드를 골라낼 행을 선택할때, 이후에 해당 행에서 가장 숫자가 낮은 카드를 뽑을 것을 고려하여 최종적으로 가장 높은 숫자의 카드를 뽑을 수 있도록 전략을 세워야 한다.

- 예시1

입력
3 1 2 
4 1 4 
2 2 2 
출력 
2

- 예시2

입력
7 3 1 8 
3 3 3 4 
출력
3

숙제

입력구조가

3 4 5 1 
7 7 7 2 
8 1 8 2
3 3 4 5

와 같을 때 출력을 구하는 코드를 작성하시오.

(숙제풀이)

library(tidyverse)
── Attaching packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.1 ──

 ggplot2 3.3.5      purrr   0.3.4
 tibble  3.1.3      dplyr   1.0.7
 tidyr   1.1.3      stringr 1.4.0
 readr   1.4.0      forcats 0.5.1

── Conflicts ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
 dplyr::filter() masks stats::filter()
 dplyr::lag()    masks stats::lag()

A=rbind(c(3,4,5,1),c(7,7,7,2),c(8,1,8,2),c(3,3,4,5))
A
     [,1] [,2] [,3] [,4]
[1,] 3    4    5    1   
[2,] 7    7    7    2   
[3,] 8    1    8    2   
[4,] 3    3    4    5   

step1 apply 함수를 사용하여 각 row의 min을 구한다.

apply(A,1,min) # A=입력매트릭스, 1=입력매트릭스의 각 row에 어떠한 함수를 적용
[1] 1 2 1 3
A %>% apply(1,min)
[1] 1 2 1 3

step2. step1의 결과에 max를 취한다.

max(apply(A,1,min))
[1] 3
A %>% apply(1,min) %>% max
[1] 3

카드뽑기 풀이에서 우리가 얻을만한 프로그래밍 문법들

매트릭스를 선언하는 방법

- 방법1: 벡터를 만들고, 그것을 row-vector로 해석한뒤 $\to$ bind

rbind(c(1,2,3,4),c(2,3,4,5))
     [,1] [,2] [,3] [,4]
[1,] 1    2    3    4   
[2,] 2    3    4    5   

- 방법2: 벡터를 만들고, 그것을 col-vector로 해석한뒤 $\to$ bind

cbind(c(1,2,3,4),c(2,2,3,4))
     [,1] [,2]
[1,] 1    2   
[2,] 2    2   
[3,] 3    3   
[4,] 4    4   

참고: 만들어진 매트릭스의 차원을 살펴보는 방법

A=rbind(c(1,2,3,4),c(2,3,4,5))
dim(A)
[1] 2 4
A=cbind(c(1,2,3,4),c(2,2,3,4))
dim(A)
[1] 4 2

- 방법3: 벡터를 선언하고 dim()을 이용하여 차원을 강제셋팅

A = 1:8
A
[1] 1 2 3 4 5 6 7 8
dim(A)
NULL
dim(A) <- c(2,4)
dim(A)
[1] 2 4
A
     [,1] [,2] [,3] [,4]
[1,] 1    3    5    7   
[2,] 2    4    6    8   
dim(A) <- c(4,2)
A
     [,1] [,2]
[1,] 1    5   
[2,] 2    6   
[3,] 3    7   
[4,] 4    8   
dim(A) <- c(3,3)
Error in dim(A) <- c(3, 3): dims [product 9] do not match the length of object [8]
Traceback:

- 일단 이정도 까지만..

매트릭스의 원소를 뽑는 방법

- 아래와 같은 매트릭스가 있다고 하자.

A=rbind(c(1,2,3,4),c(5,6,7,8),c(9,10,11,12))
A
     [,1] [,2] [,3] [,4]
[1,] 1     2    3    4  
[2,] 5     6    7    8  
[3,] 9    10   11   12  

- 1열을 뽑고싶다.

A[,1]
[1] 1 5 9

- 1열,4열을 뽑고싶다.

A[,c(1,4)]
     [,1] [,2]
[1,] 1     4  
[2,] 5     8  
[3,] 9    12  

- 2행을 뽑고싶다.

A[2,]
[1] 5 6 7 8

- 1행과 2행을 뽑고싶다.

A[c(1,2),]
     [,1] [,2] [,3] [,4]
[1,] 1    2    3    4   
[2,] 5    6    7    8   

- 2행3열의 원소를 뽑고싶다. 즉 (2,3)의 위치에 있는 원소를 뽑고싶다.

A[2,3]
[1] 7

- 일단 이정도만..

매트릭스를 왜 써야하는가?

- 바둑판구조의 자료형을 표현하기 위해서 = 자료를 바둑판 구조로 저장하기 위해서

- 자료를 바둑판(2d-array), 나아가 큐브형태(3d-array)로 저장하면 어떠한 이점이 있는가?

- 자료를 벡터(1d-array)로 저장하면 어떠한 이점이 있는가? 와 같은 질문

  • 프로그래밍 구조상의 이점
  • 계산상의 이점

(예시) 초항이 1이고 공차가 2인 등차수열을 100개 만들어라.

(풀이1)

a<-c()
for (n in 1:100) a[n] = 2*n-1 
a
  [1]   1   3   5   7   9  11  13  15  17  19  21  23  25  27  29  31  33  35
 [19]  37  39  41  43  45  47  49  51  53  55  57  59  61  63  65  67  69  71
 [37]  73  75  77  79  81  83  85  87  89  91  93  95  97  99 101 103 105 107
 [55] 109 111 113 115 117 119 121 123 125 127 129 131 133 135 137 139 141 143
 [73] 145 147 149 151 153 155 157 159 161 163 165 167 169 171 173 175 177 179
 [91] 181 183 185 187 189 191 193 195 197 199

위와 같은 간단한 코드도 결국 벡터형태로 자료를 저장하고 관리하기 때문에 for를 쓸 수 있는것임

(풀이2)

n=1:100
2*n-1
  [1]   1   3   5   7   9  11  13  15  17  19  21  23  25  27  29  31  33  35
 [19]  37  39  41  43  45  47  49  51  53  55  57  59  61  63  65  67  69  71
 [37]  73  75  77  79  81  83  85  87  89  91  93  95  97  99 101 103 105 107
 [55] 109 111 113 115 117 119 121 123 125 127 129 131 133 135 137 139 141 143
 [73] 145 147 149 151 153 155 157 159 161 163 165 167 169 171 173 175 177 179
 [91] 181 183 185 187 189 191 193 195 197 199

이것역시 벡터의 개념이 있기 때문에 가능함

- 자료를 벡터로 관리하면 어떠한 이점이 생기듯이 자료를 매트릭스로 관리해도 이점이 생긴다.

apply 함수

- 우선 아래를 기억하자.

apply(매트릭스,1,특정함수)

를 쓰면 어떠한 특정함수가 각각의 row에 적용되어서 결과가 array로 저장된다.

- 여기에서 특정함수는 "벡터입력-스칼라출력" 이라 생각하자. 즉 벡터입력-스칼라출력인 함수만 apply가 가능하다고 생각하자. (사실 그렇지는 않음) 예를들면 아래와 같다.

sum(c(1,2,3,4))
[1] 10
mean(c(1,2,3,4))
[1] 2.5

- 아래와 같은 함수는 벡터입력-벡터출력 이므로 조건에 해당하지 않는다.

sqrt(c(1,2,3,4))
[1] 1.000000 1.414214 1.732051 2.000000

- 이제 매트릭스 A에 다양한 함수를 적용해보자.

A
     [,1] [,2] [,3] [,4]
[1,] 1     2    3    4  
[2,] 5     6    7    8  
[3,] 9    10   11   12  
apply(A,1,sum)
[1] 10 26 42
apply(A,1,mean)
[1]  2.5  6.5 10.5
apply(A,1,min)
[1] 1 5 9
apply(A,1,max)
[1]  4  8 12

사용자가 임의로 정의한 함수도 가능하다.

f = function(a) (min(a)+1)**2-3
apply(A,1,f)
[1]  1 33 97

- 숫자1을 2로 바꾸면 특정함수가 각각의 col에 적용되어서 결과가 array로 저장된다.

A
     [,1] [,2] [,3] [,4]
[1,] 1     2    3    4  
[2,] 5     6    7    8  
[3,] 9    10   11   12  
apply(A,2,sum)
[1] 15 18 21 24
apply(A,2,mean)
[1] 5 6 7 8
apply(A,2,min)
[1] 1 2 3 4
apply(A,2,max)
[1]  9 10 11 12
apply(A,2,f)
[1]  1  6 13 22

%>% 연산자 ($\star\star\star$)

Note: 진짜 중요한 문법입니다. 너무편해요.

- 아래는 같은코드이다.

sum(1:10)
[1] 55
1:10 %>% sum()
[1] 55
1:10 %>% sum
[1] 55

- 아래와 같이 2개의 입력을 받는 함수를 생각하자.

myfun = function(x,y) x**2+y
myfun(2,3)
[1] 7

- 아래는 같은코드이다.

myfun(2,3)
[1] 7
2 %>% myfun(3)
[1] 7

- 동일한 논리로 아래도 같은코드이다.

myfun(3,2)
[1] 11
3 %>% myfun(2)
[1] 11

- 입력이 3개인 함수를 만들자.

myfun2= function(x,y,z) x**2 + y*z

- 아래는 같은코드이다.

myfun2(2,1,1)
[1] 5
2 %>% myfun2(1,1)
[1] 5

- 왜 이러한 일을 해야하는가? (합성함수 처리에 유리)

2:5 %>% log %>% sqrt %>% sum %>% myfun2(1,1) %>% sqrt
[1] 4.440805
sqrt(myfun2(sum(sqrt(log(2:5))),1,1))
[1] 4.440805
2:5 %>% log %>% myfun(3) %>% sqrt %>% sum %>% myfun2(1,1) %>% sqrt
[1] 8.558202
sqrt(myfun2(sum(sqrt(myfun(log(2:5),3))),1,1))
[1] 8.558202

- 아래의 개념차이

  • $g(h(f(x)))$
  • $x \to f \to h \to g$

시간비교

- 시간비교하는 방법

t1=Sys.time()
t2=Sys.time()
t2-t1
Time difference of 4.949846 secs

- 큰 매트릭스 만듬

A=sample(1:9,size=100*2000000,replace=TRUE)
dim(A)<-c(2000000,100)
A
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
 [1,] 4    5    1    3    4    3    7    9    2    3     ⋯     2     7    
 [2,] 8    2    6    9    9    9    7    2    5    5     ⋯     7     4    
 [3,] 6    9    2    6    5    8    2    3    6    7     ⋯     7     4    
 [4,] 5    8    2    4    6    3    6    8    1    8     ⋯     3     7    
 [5,] 5    2    6    2    1    6    5    8    9    5     ⋯     1     7    
 [6,] 1    8    8    3    5    2    8    4    9    6     ⋯     5     8    
 [7,] 2    9    2    9    8    4    5    2    9    4     ⋯     6     1    
 [8,] 4    5    4    4    9    8    1    3    6    2     ⋯     2     8    
 [9,] 2    6    3    9    7    1    6    7    1    4     ⋯     7     1    
[10,] 2    1    4    3    3    1    9    8    2    8     ⋯     7     4    
[11,] 7    7    3    1    1    3    7    9    6    2     ⋯     5     6    
[12,] 4    5    2    3    8    3    5    7    9    1     ⋯     2     3    
[13,] 3    9    5    9    2    5    2    7    2    8     ⋯     9     3    
[14,] 1    5    9    2    9    9    4    3    1    2     ⋯     8     6    
[15,] 8    5    1    9    9    2    1    1    2    7     ⋯     8     5    
[16,] 9    4    1    8    9    4    7    7    6    1     ⋯     8     4    
[17,] 1    4    1    1    2    7    6    4    2    1     ⋯     7     9    
[18,] 3    1    9    5    7    5    4    2    3    9     ⋯     7     7    
[19,] 7    3    4    1    2    9    8    1    6    6     ⋯     1     2    
[20,] 4    8    7    7    3    4    3    7    3    6     ⋯     7     7    
[21,] 9    5    6    2    8    4    7    8    7    1     ⋯     4     4    
[22,] 7    5    1    5    3    7    8    3    9    5     ⋯     6     1    
[23,] 4    8    7    7    4    3    1    5    9    4     ⋯     9     5    
[24,] 2    1    9    1    4    7    2    9    2    8     ⋯     7     2    
[25,] 5    2    9    8    5    3    5    7    2    7     ⋯     7     7    
[26,] 5    2    3    6    3    5    4    3    7    2     ⋯     5     3    
[27,] 1    9    5    2    6    3    8    3    2    6     ⋯     6     6    
[28,] 6    3    5    5    2    5    7    7    9    8     ⋯     3     1    
[29,] 8    8    7    5    2    2    7    3    1    7     ⋯     5     5    
[30,] 7    3    8    6    4    4    6    4    4    5     ⋯     5     8    
[31,] ⋮    ⋮    ⋮    ⋮    ⋮    ⋮    ⋮    ⋮    ⋮    ⋮     ⋱     ⋮     ⋮    
[32,] 8    4    7    5    5    4    9    4    6    7     ⋯     3     8    
[33,] 5    5    5    1    9    7    9    1    2    4     ⋯     7     1    
[34,] 3    8    1    9    8    8    6    1    5    1     ⋯     9     6    
[35,] 3    8    2    6    6    6    4    5    1    2     ⋯     9     7    
[36,] 8    3    7    5    3    9    9    5    5    8     ⋯     9     1    
[37,] 3    3    8    3    4    9    1    4    8    9     ⋯     3     1    
[38,] 6    6    2    6    7    1    7    9    5    3     ⋯     9     1    
[39,] 8    6    2    2    7    6    3    1    9    2     ⋯     2     9    
[40,] 7    3    7    7    2    2    6    6    4    8     ⋯     4     2    
[41,] 9    1    1    9    7    1    5    3    5    2     ⋯     9     1    
[42,] 8    4    2    1    3    3    7    9    5    9     ⋯     3     1    
[43,] 9    6    7    1    4    8    5    4    9    8     ⋯     5     6    
[44,] 8    7    8    1    9    5    1    8    6    7     ⋯     7     8    
[45,] 3    3    4    8    6    1    6    9    3    1     ⋯     5     3    
[46,] 2    1    6    7    1    2    8    1    1    6     ⋯     3     4    
[47,] 5    2    1    7    7    1    7    6    3    1     ⋯     6     8    
      [,14] [,15] [,16] [,17] [,18] [,19] [,20] [,21]
 [1,] 1     1     3     2     4     7     3     5    
 [2,] 4     8     7     7     8     1     2     5    
 [3,] 8     8     2     3     9     4     9     4    
 [4,] 1     7     9     3     9     9     6     8    
 [5,] 9     6     3     6     2     8     8     5    
 [6,] 9     2     9     7     7     9     2     2    
 [7,] 2     4     3     8     3     3     6     5    
 [8,] 7     3     8     6     8     4     4     1    
 [9,] 4     4     6     6     8     8     1     8    
[10,] 3     7     6     9     2     2     8     3    
[11,] 4     3     4     3     5     5     4     3    
[12,] 2     1     4     5     1     3     2     4    
[13,] 5     7     7     7     8     9     3     9    
[14,] 8     9     6     2     3     2     6     2    
[15,] 4     1     2     4     8     7     5     3    
[16,] 4     1     9     4     1     1     3     5    
[17,] 9     9     4     2     5     3     3     5    
[18,] 7     8     5     5     4     1     6     4    
[19,] 5     2     4     6     3     6     9     6    
[20,] 2     8     1     2     5     7     6     8    
[21,] 2     6     5     3     3     7     4     3    
[22,] 9     9     8     1     6     2     2     6    
[23,] 3     8     1     6     1     1     9     9    
[24,] 1     2     1     3     9     9     3     8    
[25,] 6     9     5     4     7     6     3     3    
[26,] 6     3     9     9     8     4     3     5    
[27,] 1     8     4     8     4     3     2     7    
[28,] 9     7     2     2     7     2     9     6    
[29,] 8     1     7     5     2     5     5     2    
[30,] 1     3     8     2     5     9     4     7    
[31,] ⋮     ⋮     ⋮     ⋮     ⋮     ⋮     ⋮     ⋮    
[32,] 8     9     6     2     6     8     4     3    
[33,] 8     1     6     2     7     6     7     4    
[34,] 4     8     9     8     9     8     8     1    
[35,] 5     1     2     6     3     6     2     7    
[36,] 1     9     4     6     1     6     5     6    
[37,] 8     4     1     9     6     8     5     5    
[38,] 1     3     8     6     8     9     1     9    
[39,] 2     8     5     3     6     6     7     1    
[40,] 7     1     6     2     3     1     6     8    
[41,] 9     9     8     9     1     2     1     3    
[42,] 6     3     5     3     8     3     6     7    
[43,] 2     4     3     9     9     4     1     6    
[44,] 7     9     9     2     6     2     2     9    
[45,] 9     2     7     3     3     3     8     7    
[46,] 5     2     4     7     6     4     2     3    
[47,] 2     7     7     8     5     6     3     4    
 [ reached getOption("max.print") -- omitted 14 rows ]
t1=Sys.time() 
A %>% apply(1,min) %>% max 
t2=Sys.time() 
t2-t1
[1] 2
Time difference of 4.850609 secs
t1=Sys.time() 
vec<-c()
for(i in 1:(dim(A)[1])) vec[i]<-min(A[i,]) 
max(vec)
t2=Sys.time() 
t2-t1
[1] 2
Time difference of 3.032909 secs

- for문이 좀더 빠르지만 코드는 apply가 더 간결해보인다.

숙제

- 아래의 코드를 실행하고 실행결과를 제출

t1=Sys.time() 
A %>% apply(1,min) %>% max 
t2=Sys.time() 
t2-t1
[1] 2
Time difference of 4.850609 secs
t1=Sys.time() 
vec<-c()
for(i in 1:(dim(A)[1])) vec[i]<-min(A[i,]) 
max(vec)
t2=Sys.time() 
t2-t1
[1] 2
Time difference of 3.032909 secs