https://www.acmicpc.net/problem/9461

Description

아래와 같이 나선형으로 정삼각형을 그려나간다. (1, 1, 1, 2, 2, 3, 4, 5, 7, 9, 12) 

n번째 삼각형의 한 변의 길이를 구하라.

Idea

직접 삼각형을 그리다 보면 $ a_n = a_{n-1} + a_{n-5} $ 임을 쉽게 알 수 있다.


Code

a = [1, 1, 1, 2, 2]

for _ in range(95):
	# a_n = a_(n-1) + a_(n-5)
	a.append(a[-1] + a[-5])

for _ in range(int(input())):
	print(a[int(input()) - 1])

'Programming > Algorithm' 카테고리의 다른 글

[Dynamic Programming] 포도주 시식  (0) 2016.07.05
[Dynamic Programming] 동전 2  (0) 2016.07.05
[Dynamic Programming] 숫자 삼각형  (0) 2016.07.05
[String] KMP  (0) 2016.07.05
[Dynamic Programming] 동전 1  (0) 2016.07.05

https://www.acmicpc.net/problem/2156

Description

포도주 잔이 일렬로 놓여 있고, 각각의 잔에 들어 있는 포도주의 양이 주어진다. 포도주를 한 개씩 골라서 먹는데, 연속된 세 잔을 모두 마실 수는 없다. 최대로 마실 수 있는 포도주의 양을 구하라.

Idea

n개의 포도주가 있다고 할 때, i : 0~n 마다 zero, one, two를 update한다.

zero : i번째 와인을 안 먹을 때의 최고 점수.
one : i번째 와인을 먹고 i-1번째 와인은 안 먹을 때의 최고 점수.
two : i번째 와인과 i-1번째 와인 모두 먹을 때의 최고 점수.

i번째 와인의 점수를 $ s $라 하면 아래와 같은 식이 성립한다.

$ zero_i = max(zero_{i-1}, one_{i-1}, two_{i-1}) $
$ one_i = zero_{i-1} + s $
$ two_i = one_{i-1} + s $


Code


scores = [int(input()) for _ in range(int(input()))]
# zero : highest score when the one does not choice the last wine
# one : highest score when the one choice the last wine, but not the previous one
# two : highest score when the one choice the last wine and the previous one
# define initial conditions
zero, one, two = 0, scores[0], 0

# starting from index 1, iterate through last wine
for score in scores[1:]:
	zero, one, two = max(zero, one, two), zero + score, one + score

print(max(zero, one, two))
	

'Programming > Algorithm' 카테고리의 다른 글

[Dynamic Programming] 파도반 수열  (0) 2016.07.05
[Dynamic Programming] 동전 2  (0) 2016.07.05
[Dynamic Programming] 숫자 삼각형  (0) 2016.07.05
[String] KMP  (0) 2016.07.05
[Dynamic Programming] 동전 1  (0) 2016.07.05
https://www.acmicpc.net/problem/2294

Description

n가지 가치가 다른 종류의 동전이 있다. 가치의 합이 k원이 되면서 동전의 개수가 최소가 되는 경우를 찾는 문제이다. 동전의 개수의 최솟값을 출력하고 불가능하면 -1을 출력한다.

Idea

dp[k] : k원을 만드는데 필요한 최소 동전 수 dp[k]는 k보다 작은 dp값들로부터 구해질 수 있어서, k 값이 1일때부터 k일때까지 차례로 올라가면 된다.

Pseudocode

for i : 1 ~ k dp[i] = 1 + min(
  1. dp[i - value] ( i > value )
  2. 0 ( i = value )
  3. inf ( i < value )
for value in values) i = value 일때 0값을 갖는 이유는 결국 1을 더해주어 dp[i] 값이 1이 되게 하기 위함이다.

Code

def solve(k, dp, values):
    for i in range(1, k+1):
        dp[i] = min([case(i, dp, value) for value in values]) + 1

    return [dp[k], -1][dp[k] == 10000]

def case(i, dp, value):
    if i > value:
        return dp[i - value]
    elif i == value:
        return 0
    else:
        return 10000

if __name__ == '__main__':
    #parse input
    n, k = [int(i) for i in input().split()]
    values = [int(input()) for _ in range(n)]

    #make dp list
    dp = [10000] * (k+1)

    #answer
    print(solve(k, dp, values))

'Programming > Algorithm' 카테고리의 다른 글

[Dynamic Programming] 파도반 수열  (0) 2016.07.05
[Dynamic Programming] 포도주 시식  (0) 2016.07.05
[Dynamic Programming] 숫자 삼각형  (0) 2016.07.05
[String] KMP  (0) 2016.07.05
[Dynamic Programming] 동전 1  (0) 2016.07.05
https://www.acmicpc.net/problem/1932

Description

아래와 같은 숫자 삼각형이 주어질 때, 맨 위에서 아래로 이동하는 경로 중 숫자의 합이 제일 큰 경로를 찾는 문제.

7

3    8

8    1    0

2    7    4    4

4    5    2    6    5

층 수 n 과 각 층의 숫자가 주어진다. 최댓값을 구하면 된다.

Idea

2차원 list로 하면 index 처리가 간단해지지만 memory overhead가 크다. 1차원 list로 풀어보자.

총 [latex]n(n+1)/2[/latex]개의 숫자가 존재하므로,

dp <- [-1] * n(n+1)/2로 초기화한다.

각 층의 숫자는 triangle이라는 list에 저장한다.

Pseudocode

for i: 0~n-1

for j:0~i

ind = i(i+1)/2 + j

dp[ind] =

  1. dp[i(i-1)/2] + triangle[ind]  ( j = 0 )
  2. dp[i(i-1)/2 + j - 1] + triangle[ind] ( j = i )
  3. max(dp[i(i-1)/2 + j - 1], dp[i(i-1)/2 + j]) + triangle[ind] ( j = 나머지 )
답은 max(dp[n(n-1)/2 + 0, 1, 2 ...., n]).

Code

def solve(triangle, dp, n):
    solveHelper(triangle, dp, n)
    return max([dp[n*(n-1)//2 + j] for j in range(n)])

def solveHelper(triangle, dp, n):
    dp[0] = triangle[0]

    for i in range(1, n):
        for j in range(i+1):
            ind = i*(i+1)//2 + j
            # case 1 : leftmost number of a row
            if j == 0:
                dp[ind] = dp[i*(i-1)//2] + triangle[ind]
            # case 2: rightmost number of a row
            elif j == i:
                dp[ind] = dp[i*(i-1)//2 + j - 1] + triangle[ind]
            # case 3: middle
            else:
                dp[ind] = max(dp[i*(i-1)//2 + j - 1], dp[i*(i-1)//2 + j]) + triangle[ind]

if __name__ == '__main__':
    n = int(input())

    triangle = []
    for i in range(n):
        triangle += [int(v) for v in input().strip().split()]

    dp = [-1] * (n*(n+1)//2)
    print(solve(triangle, dp, n))

'Programming > Algorithm' 카테고리의 다른 글

[Dynamic Programming] 포도주 시식  (0) 2016.07.05
[Dynamic Programming] 동전 2  (0) 2016.07.05
[String] KMP  (0) 2016.07.05
[Dynamic Programming] 동전 1  (0) 2016.07.05
[Dynamic Programming] 계단 오르기  (0) 2016.07.04
https://www.acmicpc.net/problem/2902

Description

Knuth-Morris-Pratt 과 같이 긴 형식을 KMP 와 같이 짧은 형식으로 바꾸는 문제.

Idea

간단하다. 그냥 대문자만 뽑아내면 된다...

Code

print("".join([c for c in input() if c.isupper()]))

https://www.acmicpc.net/problem/2293

Description

n가지 종류의, 가치가 서로 다른 동전이 주어진다. 이 동전들로 총합 k원을 만들고자 할 때 모든 경우의 수를 구하는 문제이다.

Idea

dp : (k * n) 2차원 배열 values: 동전의 가치의 배열 dp[i][j]  : 총합 i원을 만드는데, 가장 큰 가치를 갖는 동전이 values[j]원인 경우의 수 위와 같이 정의하면,
  1. i < values[j] 일때 : dp[i][j] = 0
  2. i =values[j] 일때 : dp[i][j] = 1
  3. i > values[j] 일때 : dp[i][j] = dp[i - j][0] + dp[i - j][1] + ... + dp[i - j][j]
이다.

Code

def solve(k, dp, values):
    #rowwise iteration through dp (it is k * n 2d list!)
    for i in range(k+1):
        for j in range(len(values)):
            #case 1 : i < values[j] -> dp[i][j] = 0
            if i < values[j]:
                dp[i][j] = 0
            #case 2 : i == values[j] -> dp[i][j] = 1
            elif i == values[j]:
                dp[i][j] = 1
            #case 3 : i > values[j] -> dp[i][j] = sum(dp[i-values[j]][0, 1, ..., j])
            else:
                dp[i][j] = sum([dp[i-values[j]][x] for x in range(j+1)])

    return sum([dp[k][x] for x in range(len(values))])


if __name__ == '__main__':
    #parse input
    n, k = [int(i) for i in input().split()]
    values = [int(input()) for _ in range(n)]

    #make dp list
    dp = [[-1] * n for _ in range(k+1)]

    #answer
    print(solve(k, dp, values))

'Programming > Algorithm' 카테고리의 다른 글

[Dynamic Programming] 포도주 시식  (0) 2016.07.05
[Dynamic Programming] 동전 2  (0) 2016.07.05
[Dynamic Programming] 숫자 삼각형  (0) 2016.07.05
[String] KMP  (0) 2016.07.05
[Dynamic Programming] 계단 오르기  (0) 2016.07.04
https://www.acmicpc.net/problem/2579

Description

계단의 수와 각 계단의 점수가 주어지며, 밟는 계단의 점수를 얻는다.
  1.  한 번에 한 계단 또는 두 계단만 이동 가능
  2. 연속된 세 계단을 모두 밟아서는 안 됨. 시작점은 포함하지 않음.
  3. 마지막 계단은 꼭 밟아야
얻을 수 있는 점수의 최댓값?

Idea

n번째 계단으로 오를 수 있는 경우는 n-1번째 계단에서 한 계단 오르거나, n-2번째 계단에서 두 계단 오르는 경우 뿐이다. n번째 계단으로 한 계단 올라와서 얻는 최고 점수들을 dp1에. n번째 계단으로 두 계단 올라와서 얻는 최고 점수들을 dp2에. 구하는 답은 max(dp1[n], dp2[n]). Base case를 생각해 보면, dp1[0] = dp2[0] = 0 dp1[1] = scores[1], dp2[1] = 0 (첫 번째 계단으로 두 계단 올라올 수 없음) dp1[2] = scores[1] + scores[2], dp2[2] = scores[2]  

Code

'Programming > Algorithm' 카테고리의 다른 글

[Dynamic Programming] 포도주 시식  (0) 2016.07.05
[Dynamic Programming] 동전 2  (0) 2016.07.05
[Dynamic Programming] 숫자 삼각형  (0) 2016.07.05
[String] KMP  (0) 2016.07.05
[Dynamic Programming] 동전 1  (0) 2016.07.05
Python에서 t-검정을 하는 방법에 대해 알아보자.

1-Sample T-test(단일 표본 t-검정)

전체 학생들 중 20명의 학생들을 추려 키를 재서 전체 학생들의 평균 키가 175cm인지 아닌지 알아보고 싶다.
  •  귀무 가설: 학생들의 평균 키가 175cm이다.
  •  대립 가설: 학생들의 평균 키가 175cm가 아니다.
scipy.stats의 ttest_1samp 메소드를 이용한다. 
Code
import numpy as np
from scipy import stats

#to get consistent result
np.random.seed(1)

#generate 20 random heights with mean of 180, standard deviation of 5
heights = [180 + np.random.normal(0, 5) for _ in range(20)]

#perform 1-sample t-test
tTestResult = stats.ttest_1samp(heights, 175)

#print result
print("The T-statistic is %.3f and the p-value is %.3f" % tTestResult)

Result
The T-statistic is 3.435 and the p-value is 0.003

p-value 가 0.003으로, 기각역을 p < 0.05로 설정했을 때 귀무 가설을 기각한다. 즉, 귀무 가설이 참일때 (학생들의 실제 평균 키가 175cm일때) 위와 같은 표본을 얻을 확률이 0.003으로, 학생들의 평균 키는 175cm가 아니라고 할 수 있다.

Unpaired T-test(독립 표본 t-검정)

집단 1과 집단 2에서 각각 20명의 학생들을 추려, 각 집단의 키가 같은지, 다른지 알아보고 싶다.
  •  귀무 가설: 두 집단의 평균 키는 같다.
  •  대립 가설: 두 집단의 평균 키는 같지 않다.(양측 검정)

scipy.stats 의 ttest_ind 메소드를 이용한다. (two INDependent sample이라 해서 ttest_ind )

Code

import numpy as np
from scipy import stats

#to get consistent result
np.random.seed(1)

#group 1 heights : mean 170, standard deviation 5
group1Heights = [170 + np.random.normal(0, 5) for _ in range(20)]
#group 2 heights : mean 180, standard deviation 10
group2Heights = [175 + np.random.normal(0, 10) for _ in range(20)]

#perform t-test assuming equal variances
tTestResult = stats.ttest_ind(group1Heights, group2Heights)

#perform t-test NOT assuming equal variances
tTestResultDiffVar = stats.ttest_ind(group1Heights, group2Heights, equal_var=False)

print("The t-statistic and p-value assuming equal variances is %.3f and %.3f." % tTestResult)
print("The t-statistic and p-value not assuming equal variances is %.3f and %.3f" % tTestResultDiffVar)

Result
The t-statistic and p-value assuming equal variances is -2.329 and 0.025.
The t-statistic and p-value not assuming equal variances is -2.329 and 0.026

기각역이 p < 0.05일때 귀무 가설을 기각한다. 즉, 두 집단의 평균 키는 같지 않다. 두 집단의 분산이 같다고 가정했을 때보다 같지 않다고 가정했을 때 p-value가 높게 나타난다. 실제로 분산이 같지 않을 때 등분산을 가정하면 p-value가 낮게 나타나 실제로 그 차이가 유의미하지 않음에도 유의미하다고 해석할 수 있다. 주의하자.

참고) 등분산을 가정하지 않으면 Welch's T-test를 수행한다.

Paired T-test(대응 표본 t-검정)

다이어트 약을 복용한 사람들 중 20명을 추려 복용 전/후의 체중 차이가 유의미한지 알아보고 싶다.
  •  귀무 가설: 복용 전/후의 체중 차이가 없다.
  •  대립 가설: 복용 전/후의 체중 차이가 있다.

scipy.stats 의 ttest_rel 메소드를 이용한다. (two RELated samples)

Code

import numpy as np
from scipy import stats

#to get consistent result
np.random.seed(1)

#before treatment : mean 60, standard deviation 5
beforeWeights = [60 + np.random.normal(0, 5) for _ in range(20)]
#after treatment : mean 0.99-fold decrease, standard deviation 0.02
afterWeights = [w * np.random.normal(0.99, 0.02) for w in beforeWeights]

#perform paired t-test
tTestResult = stats.ttest_rel(beforeWeights, afterWeights)

print("The T-statistic is %.3f and the p-value is %.3f" % tTestResult)

Result
The T-statistic is 2.915 and the p-value is 0.009

기각역 p < 0.05에서 귀무 가설을 기각한다. 즉, 다이어트 약 복용 전/후에 체중 차이는 유의미하다고 할 수 있다.  

단측 검정은?

T-분포는 0을 중심으로 대칭이므로,  기각역을 [latex]\alpha[/latex], T-statistic을 [latex]t[/latex]라고 하면,

 $ t < 0, p/2 < \alpha $

이면 less-than test의 귀무 가설을 기각하며,

$ t > 0, p/2 < \alpha $

이면 greater-than test의 귀무 가설을 기각한다.

참고

http://stackoverflow.com/questions/15984221/how-to-perform-two-sample-one-tailed-t-test-with-numpy-scipy

http://iaingallagher.tumblr.com/post/50980987285/t-tests-in-python


Selection Sort를 시각화 해보았다

'Visualization' 카테고리의 다른 글

[Visualization] Insertion Sort  (0) 2016.07.03
[Visualization] Bubble Sort  (0) 2016.07.03

Insertion sort를 시각화 해보았다

'Visualization' 카테고리의 다른 글

[Visualization] Selection Sort  (0) 2016.07.03
[Visualization] Bubble Sort  (0) 2016.07.03

+ Recent posts