딥러닝'심층학습'이라고도 하며, 용어만 보면 뭔가 심오한 이론인 것처럼 느껴진다. 그러나 기본적으로는 다층 신경망을 이용한 머신러닝에 지나지 않는다.

다만, 단순히 계층을 증가시켜 복잡화하는 것이 아니라 해결해야 할 문제에 맞게 각각의 노드에 특별한 역할을 부여하거나, 노드 간의 연결 방식을 다양하게 연구한 것이다.

무조건 노드를 증가시켜 복잡화하는 것이 아니라 각 노드의 역할을 생각하면서 특정 의도를 갖고 구성한 신경망이라고 할 수 있다.


1. 딥러닝의 특징

아래의 합성곱 신경망(CNN)에서 첫 번째 계층 노드에는 1차 함수가 아닌 '합성곱 필터(Convolution Filter)'라는 함수를 사용합니다.

합성곱 필터란, 딥러닝만을 위해 특별히 고안된 것이 아니라 포토샵과 같은 이미지 처리 소프트웨어에서도 많이 이용되는 이미지 필터의 일종입니다.

사진에서 물체의 윤곽을 추출해서 선으로만 그린 그림처럼 변환하는 필터를 개발하는데 사용됩니다. 이를 통해 이미지에 나타난 물체의 특징을 보다 정확하게 포착할 수 있습니다.

<그림 1-1. CNN 구성>


그 뒤에 존재하는 풀링 계층(Pooling Layer)이라는 부분에서는 이미지의 해상도를 낮추는 처리를 합니다.

이는 이미지의 세밀한 부분을 지우는 것으로, 그려져 있는 물체의 본질적인 특징만을 추출하고자 하는 발상에서 비롯되었습니다.


또한, 노드 간 연결 방식을 연구한 특수한 에로 순환 신경망(RNN, Recurrent Neural Network)이 있습니다.

일반적으로 시계열 데이터를 다루는데, 단어가 나열된 문장을 입력 데이터로 하는 자연어 처리에 응용하는 경우가 좋은 예라고 할 수 있습니다.


<그림 1-2. RNN으로 단어를 예측하는 예>


이는 특정 문장이 흔히 보는 자연스러운 문장인지 뭔가 어색한 부자연스러운 문장인지를 판정하는 데 이용됩니다.

예를 들면, 'This is a pen'이라는 네 개의 단어를 차례로 입력해서 'This' 뒤에 'is'가 올 확률, 'is' 뒤에 'a'가 올 확률을 차례로 구합니다.

전부 높은 확률이 나오면 이는 자연스러운 문장이라고 할 수 있는 것입니다.


RNN에서는 이전 중간 계층의 값을 다음 입력에 재이용하는 특징을 가지고 있습니다.

이전에 입력한 단어 정보는 중간 계층에서 서서히 사라지게 되므로 노드 간 연결 방식을 좀 더 연구해서 과거의 정보를 가능한 한 오래 축적하는 등의 테크닉이 이용됩니다.


위와 같은 예로부터 알 수 있듯이 딥러닝의 이면에는 주어진 데이터가 어떻게 처리될지를 생각하면서 최적의 네트워크를 구성해 가는 방대한 시행착오가 감춰져 있습니다.

또한, 이는 어디까지나 '머신러닝 모델의 3단계' 중 1단계라는 것도 상기할 필요가 있습니다. 아무리 잘 만들어진 모델이라도 실제로 계산을 할 수 없다면 활용할 수 없습니다.

그 이후 단계로 나아가기 위해서는 각 네트워크에 대해 효율적으로 파라미터를 최적화하는 알고리즘의 연구도 필요합니다.


딥러닝은 넓은 의미로 머신러닝 중 '신경망(Neural Network)'이라는 모델의 일종입니다. 

딥러닝을 정확하게 이해하기 위해 머신러닝에서의 '모델'의 역할과 일반적인 신경망의 구조 설명할 예정입니다.


1. 머신러닝(Machine Learning)의 개념

머신러닝은 데이터 속에 있는 '수학적인 구조'를 컴퓨터로 계산하여 발견해 내는 구조입니다.

예를 들어, 아래의 그림 1-1은 어느 특정 도시의 올해 1년간 월별 평균 기온을 나타낸 것입니다.

이 데이터를 기반으로 내년 이후의 월별 평균 기온을 예측한다면 어떻게 해야 할까요?


<그림 1-1. 월별 평균 기온 그래프>


가장 간단한 답은 올해 평균 기온과 동일한 수치로 예측하는 것이지만, 조금 더 연구해 볼 여지가 있습니다.

이 그래프에서는 월별 평균 기온이 직선으로 연결되어 있는데, 기후변화의 원리를 생각해보면 월별 평균 기온은 본질적으로 완만한 곡선으로 변화합니다.

이러한 변화에 대해 월별로 무작위적인 노이즈(Noise)가 더해져 그림 1과 같은 모습이 되었다고 생각할 수 있습니다.


<그림 1-2. 완만한 곡선으로 예측한 평균 기온>


따라서, 전체적인 데이터를 살펴보고 그림 1-2와 같은 부드러운 곡선으로 표현해 보았습니다.

내년 이후의 평균 기온을 이 곡선상의 값으로 예측한다면 정확도가 더 높을 것으로 기대할 수 있습니다.


이처럼 주어진 데이터의 수치를 있는 그대로 받아들이는 것이 아니라 그 속에 있는 '원리'를 생각하는 것을 '데이터의 모델화'라고 합니다.

이렇게 해서 생각해 낸 구조가 바로 데이터의 '모델'입니다. 데이터의 모델은 일반적으로 식으로 표현할 수 있습니다.

예를 들면, 그림 2의 곡선이 다음과 같은 4차 함수로 표현된다고 가정해보도록 하겠습니다.


<수식 1-1. 그림 1-2의 완만한 선 그래프>


x = 1, 2, 3, 4 ... 12가 각각의 월을 나타내며, 식 1-1로 계산된 y가 해당 월의 예상 평균 기온이라고 하겠습니다.

각 항의 계수 w값을 잘 조절하면 그림 1-2와 같은 그럴듯한 곡선을 얻을 수 있습니다.


다만, 계수의 값을 구체적으로 결정하기 위해서는 또 하나의 지표가 필요합니다. 이는 위의 식에서 예상되는 값과 실제 데이터의 오차로 판단합니다.

그림 1-1의 기초 데이터 값을 t1, t2, t3 ... t12라고 하겠습니다. 이때 수식 1-1에 x = 1, 2, 3 ... 12를 대입해서 얻은 예상 평균 기온을 y1, y2, y3 ... y12라 하고 다음 값을 계산합니다.

이는 일반적으로 제곱 오차라고 하는데, 월별 예측값과 실제 데이터 차이의 제곱을 더한 값입니다. 전체를 2로 나누는 것은 계산 상황에 따른 것이며 본질적인 것은 아닙니다.


<수식 1-2. 오차 함수(Error Function)>


지금까지의 과정을 간단히 요약하면 아래와 같습니다.[각주:1]

  1. 주어진 데이터를 기반으로 미지의 데이터를 예측하는 식(수식 1-1)을 생각합니다.

  2. 식에 포함된 파라미터의 좋고 나쁨을 판단하는 오차 함수(수식 1-2)를 준비합니다.

  3. 오차 함수를 최소화할 수 있도록 파라미터값을 결정합니다.


이러한 과정을 거쳐 파라미터값이 구체적으로 결정되면 얻어진 식을 이용해 내년 이후의 평균 기온을 예측할 수 있습니다.

만약, 예측의 정밀도가 좋지 않았다면 처음 생각한 식(수식 1-1), 즉 데이터의 '모델'이 적합하지 않았을 수 있습니다.

미지의 데이터에 대한 예측 정밀도를 향상하기 위해서는 최적의 모델, 즉 예측용 식을 발견하는 것이 주요하다고 할 수 있습니다.



2. 신경망(Neural Network)의 필요성

신경망을 설명할 때에는 다른 예제로 데이터의 분류 문제를 설명하려고 합니다.

특정 바이러스가 감염되었는지를 판정하는 간단한 예비 검사가 있고, 검사 결과는 두 종류의 수치(x1, x2)로 주어집니다.

이 두 가지 수치를 기반으로 바이러스의 감염되었을 확률을 구한 다음, 확률이 어느 정도 높은 환자는 정밀 검사로 전환한다고 가정하도록 하겠습니다.


아래의 그림 1-3은 지금까지 예비 검사를 받은 환자의 검사 결과와 실제로 바이러스에 감염되어 있는지를 나타내는 그래프입니다.

이 예비 검사의 정밀도를 조사하기 위해 모든 환자에 대해 예비 검사와 정밀 검사를 모두 수행해서 얻어진 데이터라고 가정합니다.

이 데이터를 기반으로 새로운 검사 결과(x1, x2)에 대해 감염 확률을 계산하는 식을 구하는 것이 본 예제의 과제입니다.


<그림 1-3. 예비 검사의 결과와 실제 감염 상황을 나타낸 그래프>


그림 1-3을 살펴보면 직관적으로 두 그룹으로 분류할 수 있음을 알 수 있습니다.

직선의 오른쪽 위 영역은 감염되어 있을 확률이 높고, 왼쪽 아래 영역은 감염되어 있을 확률이 낮다고 생각할 수 있습니다.

여기서, 이 경계를 나타내는 직선을 수식 1-3과  같이 수식으로 표현해 보도록 하겠습니다.


<수식 1-3. 그림 1-3을 두 그룹으로 분류하는 직선>


수식 1-3은 (x1, x2)라는 두 개의 값을 입력하면 ƒ(x1, x2)라는 하나의 값을 출력하는 함수이고, 그 값이 크고 작음에 따라 감염 확률이 높거나 낮음을 의미합니다.

평면 상의 직선은 y = ax+ b의 형식으로 많이 알려졌지만, 여기서는 x1과 x2로 이루어진 관계식으로 나타내기 위해 이와 같은 형식을 사용하였습니다.

이 형식의 장점은 ƒ(x1, x2)의 값이 ± ∞ 를 향해 증가(감소)해 가는 성질을 확인할 수 있다는 것입니다.


<그림 1-4. 직선을 이용한 분류와 감염 확률로의 변환>


따라서 0부터 1을 향해 값이 변화하는 함수 σ(x)를 준비하고 ƒ(x1, x2)의 값을 대입하면,  검사 결과 (x1, x2)로부터 감염 확률 P(x1, x2)를 구하는 함수를 만들 수 있습니다.[각주:2].

그림 1-4의 아랫부분은 수식을 그래프로 표현한 것입니다. 이는 '머신러닝 모델의 3단계'에서 1단계에 해당합니다.

이후에는 수식 1-4에 포함된 파라미터인 w0, w1, w2의 좋고 나쁨을 판단하는 오차 함수를 준비하고, 이를 최소화하도록 파라미터를 결정하는 흐름으로 진행됩니다.


<수식 1-4. 검사결과로부터 감염 확률을 구하는 함수>


위와 같은 과정을 거쳐 탄생한 모델의 문제점은 바로 주어진 데이터를 직선으로 분류할 수 있다는 전제 조건입니다. 

예를 들면, 주어진 데이터가 그림 1-5과 같은 경우를 생각해보면, 이는 아무리 생각해도 단순하게 직선으로 분류할 수 없고,

그림에 나타냈듯이 구부러진 직선 혹은 곡선을 이용해 분류해야 합니다.


<그림 1-5. 직선으로 분류할 수 없는 데이터의 해>


식 1-3에 나타낸 직선 방정식을 보다 복잡한 수식으로 치환하여 구부러진 직선이나 곡선으로 표현할 수 있으면 되지만, 이는 그리 간단하지 않습니다.

현실의 머신러닝에서 이용하는 데이터는 그림 1-5와 같이 평면에 그릴 수 있을 정도로 단순한 것이 아니기 때문입니다.

예를 들면, 검사 결과 수치가 두 종류가 아닌 20종류일 때, 이를 그림으로 표현하려면 20차원 공간 그래프가 필요합니다.

이를 그림으로 나타내기는 불가능하며 머릿속으로 상상하기도 곤란합니다.


현재의 머신러닝은 기본적으로 데이터 모델, 즉 1단계에서 준비해야만 하는 식 자체는 사람이 생각해내야 합니다.

다만 그런 와중에도 유연성이 높은, 다양한 데이터에 대응할 수 있는 '수식'을 생각하려는 노력이 이어져 왔습니다.

신경망은 이러한 식 중의 한 가지 형태라고 볼 수 있습니다.


그렇다면 수식 1-3과 같이 하나의 단순한 수식으로 결과를 출력하는 것이 아니라 복수의 수식을 조합한 함수를 만드는 것에 대해 생각해 볼 수 있는데, 이것이 신경망입니다.

신경망은 딥러닝의 핵심이 되는 구조이므로 앞으로 차근차근 설명하도록 하겠습니다.


<그림 1-6. 단일 노드로 구성된 신경망>


그림 1-6은 세상에서 가장 간단한 신경망이라고 할 수 있습니다. 이는 수식 1-4를 신경망 형태로 나타낸 것입니다.

왼쪽부터 (x1, x2)라는 두 값을 입력하면 내부에서 ƒ(x1, x2) 값이 계산되고, 이를 시그모이드 함수 σ(x)로 0~1의 값으로 변환한 것이 변수 z로 출력됩니다.

이는 신경망을 구성하는 최소의 유닛으로, 뉴런(Neuron) 혹은 노드(Node)라고 합니다.


위와 같은 노드를 다층으로 중첩함으로써 더욱 복잡한 신경망이 얻어집니다. 그림 1-7은 2계층 노드로 구성된 신경망의 예시입니다. 

첫 번째 계층의 두 노드에는 ƒ(x1, x2)와 ƒ(x1, x2)라는 1차 함수가 부여되어 있는데, 각각의 계수값은 서로 다릅니다.

이들을 시그모이드 함수 σ(x)로 변환한 값의 쌍인 (z1, z2)를 다시 두 번째 계층의 노드로 입력하여 최종적인 출력값 z가 얻어지는 과정을 나타내고 있습니다.


<그림 1-7. 2계층 노드로 구성된 신경망>


이 신경망에는 w10, w11, w12, w20, w21, w22, w0, w1, w2라는 9개의 파라미터가 존재합니다. 

이 값들을 조정함으로써 단순한 직선이 아닌 복잡한 경계선을 표현할 수 있습니다.

마지막의 z값이 감염 확률 P를 나타낸다고 가정하고 있으므로 z = 0.5가 되는 부분이 경계선에 해당합니다. 


이러한 파라미터 값을 잘 조정하여 z = 0.5가 되는 부분을 그리면 그림 1-10의 결과를 얻을 수 있습니다.

이는 각 (x1, x2)에 의한 z의 값을 색의 농담으로 나타낸 것으로, 오른쪽 위 영역이 z > 0.5에 해당합니다.

그림 1-7의 오른쪽 예를 보면 이것만으로는 아직 대응할 수 없다는 것을 확인할 수 있습니다.

이러한 경우에는 노드의 수를 증가시킨, 더 복잡한 신경망을 이용해야 할 것으로 판단됩니다.


노드를 증가시키는 방법에는 몇 가지 패턴이 있습니다. 하나는 계층의 수를 늘려 신경망을 다층화하는 것이고, 

다른 하나는 하나의 계층에 포함된 노드의 수를 늘리는 것입니다. 그림 1-8과 같은 신경망을 구성할 수 있습니다.


<그림 1-8. 보다 복잡한 다층 신경망>


다만, 여기서 신경망의 난해함이 드러납니다. 원칙적으로는 노드의 수를 늘려가면 아무리 복잡한 경계선이라도 그릴 수 있습니다. 

그러나 아무렇게나 노드를 늘려가면 파라미터의 수가 방대해져 파라미터를 최적화하는 3단계의 계산이 곤란해집니다.

이는 현실적인 시간 내에 계산이 끝나지 않는다는 컴퓨터의 성능 문제와 더불어, 최적인 값을 계산하는 알고리즘 그 자체를 만들 수 없는 경우도 생깁니다.


머신러닝을 통해 신경망에 도전한다는 것은 주어진 문제에 대해 실제로 계산할 수 있으며, 데이터의 특성에 맞는 신경망을 구성한다는 것입니다. 

그리하여 다양한 연구자들이 이런 어려움에 계속 도전해 오면서 등장한 것이 딥러닝(Deep Learning)이라는 특별한 형태의 신경망을 이용한 방법입니다.



Reference

  • 나카이 에츠지, '텐서플로로 시작하는 딥러닝', 제이펍, 2009

  1. 아래의 1~3 단계는 앞으로의 설명에서 자주 등장하게 됩니다. 이를 '머신러닝 모델의 3단계'로 표시하도록 하겠습니다. [본문으로]
  2. *머신 러닝의 세계에서는 일반적으로 σ(x)와 같이 0부터 1까지 완만하게 값이 변화하는 함수를 '시그모이드 함수(Sigmoid Function)'라고 합니다. [본문으로]

Problem


You are given an array of integers representing coordinates of obstacles situated on a straight line.

Assume that you are jumping from the point with coordinate 0 to the right. You are allowed only to make jumps of the same length represented by some integer.

Find the minimal length of the jump enough to avoid all the obstacles.


Example


For inputArray = [5, 3, 6, 7, 9], the output should be
avoidObstacles(inputArray) = 4.

Check out the image below for better understanding:


Input/Output

  • [input] array.integer inputArray

    Non-empty array of positive integers.

    Guaranteed constraints:
    2 ≤ inputArray.length ≤ 10,
    1 ≤ inputArray[i] ≤ 40.

  • [output] integer

    The desired length.



Solution

def avoidObstacles(inputArray):

s = sorted(set(inputArray))

m = max(s)


for size in range(1, m+2):

steps = set([i for i in range(0, m+size+1, size)])

if len(steps.intersection(i)) == 0:

return step


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

[Algorithm] isIPv4Address  (0) 2018.03.02
[Algorithm] arrayMaximalAdjacentDifference  (0) 2018.03.02
[Algorithm] areEquallyStrong  (0) 2018.03.02
[Algorithm] palindromeRearranging  (0) 2018.02.26
[Algorithm] arrayChange  (0) 2018.02.26

Problem


An IP address is a numerical label assigned to each device (e.g., computer, printer) participating in a computer network that uses the Internet Protocol for communication. There are two versions of the Internet protocol, and thus two versions of addresses. One of them is the IPv4 address.

IPv4 addresses are represented in dot-decimal notation, which consists of four decimal numbers, each ranging from 0 to 255 inclusive, separated by dots, e.g., 172.16.254.1.

Given a string, find out if it satisfies the IPv4 address naming rules.


Example


  • For inputString = "172.16.254.1", the output should be
    isIPv4Address(inputString) = true;

  • For inputString = "172.316.254.1", the output should be
    isIPv4Address(inputString) = false.

    316 is not in range [0, 255].

  • For inputString = ".254.255.0", the output should be
    isIPv4Address(inputString) = false.

    There is no first number.


Input/Output

  • [input] string inputString

    Guaranteed constraints:
    1 ≤ inputString.length ≤ 30.

  • [output] boolean

    true if inputString satisfies the IPv4 address naming rules, false otherwise.



Solution

def isIPv4Address(inputString):

splt = inputString.split('.')

return len(splt) == 4 and all(i.isdigit() and 0 <= int(i) <= 255 for i in splt)

*splt : inputString을 점(dot)을 기준으로 나누어 반환한 값을 저장한 변수

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

[Algorithm] avoidObstacles  (0) 2018.03.02
[Algorithm] arrayMaximalAdjacentDifference  (0) 2018.03.02
[Algorithm] areEquallyStrong  (0) 2018.03.02
[Algorithm] palindromeRearranging  (0) 2018.02.26
[Algorithm] arrayChange  (0) 2018.02.26

Problem


Given an array of integers, find the maximal absolute difference between any two of its adjacent elements.


Example


For inputArray = [2, 4, 1, 0], the output should be
arrayMaximalAdjacentDifference(inputArray) = 3.


Input/Output

  • [input] array.integer inputArray

    Guaranteed constraints:
    3 ≤ inputArray.length ≤ 10,
    -15 ≤ inputArray[i] ≤ 15.

  • [output] integer

    The maximal absolute difference.



Solution

def arrayMaximalAdjacentDifference(inputArray):

return max([abs(inputArray[i] - inputArray[i+1]) for i in range(len(inputArray) - 1)])


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

[Algorithm] avoidObstacles  (0) 2018.03.02
[Algorithm] isIPv4Address  (0) 2018.03.02
[Algorithm] areEquallyStrong  (0) 2018.03.02
[Algorithm] palindromeRearranging  (0) 2018.02.26
[Algorithm] arrayChange  (0) 2018.02.26

Problem


Call two arms equally strong if the heaviest weights they each are able to lift are equal.

Call two people equally strong if their strongest arms are equally strong (the strongest arm can be both the right and the left), and so are their weakest arms.

Given your and your friend's arms' lifting capabilities find out if you two are equally strong.


Example


  • For yourLeft = 10yourRight = 15friendsLeft = 15 and friendsRight = 10, the output should be
    areEquallyStrong(yourLeft, yourRight, friendsLeft, friendsRight) = true;
  • For yourLeft = 15yourRight = 10friendsLeft = 15 and friendsRight = 10, the output should be
    areEquallyStrong(yourLeft, yourRight, friendsLeft, friendsRight) = true;
  • For yourLeft = 15yourRight = 10friendsLeft = 15 and friendsRight = 9, the output should be
    areEquallyStrong(yourLeft, yourRight, friendsLeft, friendsRight) = false.


Input/Output

  • [input] integer yourLeft

    A non-negative integer representing the heaviest weight you can lift with your left arm.

    Guaranteed constraints:
    0 ≤ yourLeft ≤ 20.

  • [input] integer yourRight

    A non-negative integer representing the heaviest weight you can lift with your right arm.

    Guaranteed constraints:
    0 ≤ yourRight ≤ 20.

  • [input] integer friendsLeft

    A non-negative integer representing the heaviest weight your friend can lift with his or her left arm.

    Guaranteed constraints:
    0 ≤ friendsLeft ≤ 20.

  • [input] integer friendsRight

    A non-negative integer representing the heaviest weight your friend can lift with his or her right arm.

    Guaranteed constraints:
    0 ≤ friendsRight ≤ 20.

  • [output] boolean

    true if you and your friend are equally strong, false otherwise.



Solution

def areEquallyStrong(yourLeft, yourRight, friendsLeft, friendsRight):

return sorted([yourLeft, yourRight]) == sorted([friendsLeft, friendsRight])


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

[Algorithm] isIPv4Address  (0) 2018.03.02
[Algorithm] arrayMaximalAdjacentDifference  (0) 2018.03.02
[Algorithm] palindromeRearranging  (0) 2018.02.26
[Algorithm] arrayChange  (0) 2018.02.26
[Algorithm] areSimilar  (0) 2018.02.26

앞에서 polls 애플리케이션을 설계할 때 3개의 페이지가 필요했습니다.

이 3개의 페이지를 보여주기 위해 필요한 뷰와 템플릿을 코딩해보도록 하겠습니다.







1. 처리 흐름

URL 패턴                뷰 이름        뷰가 처리하는 내용

/polls/                index()      index.html 템플릿을 보여줍니다.

/polls/5/              detail()     detail.html 템플릿을 보여줍니다.

/polls/5/vote/         vote()       detail.html에 있는 폼을 POST 방식으로 처리합니다.

/polls/5/results/     results()    results.html 템플릿을 보여줍니다.

/admin/                (장고 기능)     Admin 사이트를 보여줍니다. (장고에서 기본적으로 제공)    

* URL 패턴에서 5는 예시로, 질문번호가 채워지는 자리입니다.


위 설계 내용을 개발하기 위해 아래 순서대로 코딩하도록 하겠습니다. 코딩 순서는 정해진 것은 없지만, 일반적으로 URLconf, 뷰, 템플릿, 뷰 순서로 코딩합니다.

urls.py 작성                // URLconf 내용을 작성

views.index() 함수 작성     // index.html 템플릿도 같이 작성

view.detail() 함수 작성     // detail.html 템플릿도 같이 작성

views.vote() 함수 작성       // redirection 처리 들어있음

views.results() 함수 작성    // results.html 템플릿도 같이 작성


URLconf 설계 내용에 따르면, Admin 사이트까지 포함하여 5개의 URL과 뷰가 필요합니다. 그 내용을 기계적으로 urls.py 파일에 코딩합니다. 코드는 아래와 같습니다.


$ cd ch3/mysite

$ vi urls.py

from django.conf.urls import patterns, url -------------------------------------------------- 1

from polls import views --------------------------------------------------------------------- 2


urlpatterns = patterns('', ------------------------------------------------------------------ 3 url(r'^polls/$', views.index, name = 'index'), url(r'^polls/(?P<question_id>\d+)/$', views.detail, name = 'detail'), url(r'^polls/(?P<question_id)\d+)/vote/$', views.vote, name = 'vote'), url(r'^polls/(?P<question_id)\d+)/results/$', views.results, name = 'results'), ----- 4 url(r'^admin/', include(admin.site.urls)), ------------------------------------------ 5 )


위의 코드를 라인별로 설명하면 아래와 같습니다.

1. 장고의 내장 함수인 patterns(), url() 두 개의 함수를 import 합니다.

2. URLconf에서 뷰를 지정하므로, 뷰가 정의되어 있는 views 모듈을 임포트합니다.

3. patterns() 함수는 URL/뷰 매핑을 처리하는 함수로, 동일한 형식으로 사용하기 때문에 보이는 그대로 코딩하면 됩니다.

4. url() 함수는 5개의 인자를 가지고 있습니다. 앞의 2개는 필수 인자이고, 뒤에 3개는 선택 인자입니다.

5. 마지막 줄에는 Admin 사이트 관련 URLconf가 정의되어 있습니다. 이처럼 이미 정의된 URLconf를 include() 함수로 가져와서 사용할 수 있습니다.


url() 함수는 장고 라이브러리 django.conf.url.py 파일에 아래처럼 정의되어 있습니다.

url(regex, view, kwargs = None, name = None, prefix = '')

    • regex : URL을 정규표현식으로 표현합니다. 정규표현식을 통해 뷰 함수에 넘겨줄 파라미터를 추출할 수 있습니다.
    • view : 요청의 URL이 regex 인자에 매칭되면 장고가 뷰 함수를 호출합니다. 뷰 함수에는 HttpRequest와 Regex에서 추출한 항목을 인자로 넘겨줍니다.
    • kwargs : regex 인자에서 추출한 파라미터 외에 추가적인 인자를 파이썬 사전 타입의 키워드 인자로 뷰 함수에 넘겨줄 수 있습니다.
    • name : 각 URL 별로 이름을 붙여줍니다. 여기서 정해준 이름은 템플릿 파일에서 사용되니 기억해 두기 바랍니다.
    • prefix : 뷰 함수에 대한 접두사 문자열입니다. 우리 예제에서는 사용하지 않으니 무시해도 됩니다.

자, 이제 앞에서 코딩한 내용을 살펴보도록 하겠습니다. 각 라인의 의미는 다음과 같습니다.

url(r'^polls/$', views.index, name = 'index'),

만일, 요청의 URL이 /polls/라면 위 라인이 매칭되고, 정규표현식에서 파라미터를 추출하지 않으므로 views.index(request) 처럼 뷰 함수가 호출됩니다. 이 URL 패턴의 이름을 index라고 정했습니다.

url(r'^polls/(?P<question_id>\d+)/$', views.detail, name = 'detail'),

만일, 요청의 URL이 /polls/5/ 라면 위 라인이 매칭되고, 뷰 함수 호출 시 view.detail(request, question_id = '5')처럼 인자가 대입됩니다. 이 URL 패턴의 이름을 detail이라고 정했습니다. 타 라인의 코드의 동작 방식도 이와 같습니다.


url(r'^admin/', include(admin.site.urls)),

만일 요청의 URL이 /admin/이라면 아래 라인이 매칭되고, 장고에서 제공해주는 뷰 함수를 호출합니다. 우리는 아래 라인처럼 include() 함수만으로 Admin 사이트를 그대로 사용할 수 있습니다.


ROOT_URLCONF = 'mysite.urls'

추가적으로, mysite/settings.py 파일에 ROOT_URLCONF 항목이 정의된다는 것을 기억하시기 바랍니다. 장고는 URL 분석 시, 이 항목에 정의된 urls.py 파일을 가장 먼저 분석하시기 바랍니다.




2. URLconf의 코딩 방법

한 가지 더 알아두어야 할 사항은 URLconf를 코딩할 때 앞에서처럼 하나의 urls.py 파일에 작성할 수도 있고, 다음과 같이 mysite/urls.py와 polls/urls.py 2개의 파일에 작성할 수도 있습니다. 


mysite/urls.py 코딩 방법

$ cd ch3/mysite

$ vi urls.py

from django.conf.urls import patterns, url, include

from django.contrib import admin


urlpatterns = patterns('',

url(r'^polls/', include('polls.urls', namespace = "polls")),

url(r'^admin/', include(admin.site.urls)),

)


polls/urls.py 코딩 방법

$ cd ch3/polls

$ vi urls.py

from django.conf.urls import patterns, url

from polls import views


urlpatterns = patterns('', url(r'^polls/$', views.index, name = 'index'), url(r'^polls/(?P<question_id>\d+)/$', views.detail, name = 'detail'), url(r'^polls/(?P<question_id)\d+)/vote/$', views.vote, name = 'vote'), url(r'^polls/(?P<question_id)\d+)/results/$', views.results, name = 'results'), url(r'^admin/', include(admin.site.urls)), - )


그렇다면, 위의 두 가지 방식 중 어떤 방식이 좋을까요?

두 번째 방법을 추천합니다. 즉, URLconf 모듈을 계층적으로 구성하는 것이 변경도 쉬워지고 확장도 용이해지기 때문입니다. 만일 URL의 polls를 vote라고 변경한다고 가정했을 때, 1개의 파일로 URLconf를 코딩한 경우는 모든 패턴마다, 즉 위 예제의 경우 4개의 패턴을 수정해야 하지만, 2개의 파일로 URLconf를 코딩한 경우는 사우이 URLconf에서 1개의 패턴만 수정하면 됩니다. 이것이 재사용을 기본 원칙으로 하는 장고의 장점 중 하나입니다.

그리고 mysite/urls.py 파일의 include() 함수를 정의할 때 사용한 namespace 인자는 URL패턴의 이름이 충돌나는 것을 방지하기 위한 것입니다. 우리 예제에서는 애플리케이션이 polls 하나뿐이지만, 보통의 프로젝트에서는 여러 개의 애플리케이션으로 이뤄지는 경우가 대부분입니다. 예를 들어, polls 애플리케이션의 URL패턴 이르과 blog 애플리케이션 URL 패턴 이름이 detail이 되는 경우가 발생할 수 있습니다. 이 둘을 구별하기 위해 include() 함수의 namespace 인자를 사용합니다.


Problem


Given a string, find out if its characters can be rearranged to form a palindrome.


Example


For inputString = "aabb", the output should be
palindromeRearranging(inputString) = true.

We can rearrange "aabb" to make "abba", which is a palindrome.


Input/Output

  • [input] string inputString

    A string consisting of lowercase English letters.

    Guaranteed constraints:
    1 ≤ inputString.length ≤ 50.

  • [output] boolean

    true if the characters of the inputString can be rearranged to form a palindrome, false otherwise.



Solution

def palindromeRearranging(inputString):

stringCount = [inputString.count(i) % 2 for i in set(inputString)]


return sum(stringCount) <= 1


*stringCount : input된 문자열에서 중복값을 없애고, 해당 문자를 for문으로 반환한 값을 2로 나눈 나머지 값을 리스트로 저장

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

[Algorithm] arrayMaximalAdjacentDifference  (0) 2018.03.02
[Algorithm] areEquallyStrong  (0) 2018.03.02
[Algorithm] arrayChange  (0) 2018.02.26
[Algorithm] areSimilar  (0) 2018.02.26
[Algorithm] addBoarder  (0) 2018.02.26

Solution


You are given an array of integers. On each move you are allowed to increase exactly one of its element by one. Find the minimal number of moves required to obtain a strictly increasing sequence from the input.


Example

For inputArray = [1, 1, 1], the output should be
arrayChange(inputArray) = 3.


Input/Output

  • [input] array.integer inputArray

    Guaranteed constraints:
    3 ≤ inputArray.length ≤ 105,
    -105 ≤ inputArray[i] ≤ 105.

  • [output] integer

    The minimal number of moves needed to obtain a strictly increasing sequence from inputArray.
    It's guaranteed that for the given test cases the answer always fits signed 32-bit integer type.



Solution

def arrayChange(inputArray):

count = 0

for i in range(len(inputArray) - 1):

if inputArray[i+1] <= inputArray[i]:

count += inputArray[i] - inputArray[i+1] + 1

inputArray[i+1] = inputArray[i] + 1


return count


*count : sequence하게 올라가야 하는 횟수를 저장한 변수


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

[Algorithm] areEquallyStrong  (0) 2018.03.02
[Algorithm] palindromeRearranging  (0) 2018.02.26
[Algorithm] areSimilar  (0) 2018.02.26
[Algorithm] addBoarder  (0) 2018.02.26
[Algorithm] alternatingSums  (0) 2018.02.26

Problem


Two arrays are called similar if one can be obtained from another by swapping at most one pair of elements in one of the arrays.

Given two arrays a and b, check whether they are similar.


Example


  • For a = [1, 2, 3] and b = [1, 2, 3], the output should be
    areSimilar(a, b) = true.

    The arrays are equal, no need to swap any elements.

  • For a = [1, 2, 3] and b = [2, 1, 3], the output should be
    areSimilar(a, b) = true.

    We can obtain b from a by swapping 2 and 1 in b.

  • For a = [1, 2, 2] and b = [2, 1, 1], the output should be
    areSimilar(a, b) = false.

    Any swap of any two elements either in a or in b won't make a and b equal.


Input/Output

  • [input] array.integer a

    Array of integers.

    Guaranteed constraints:
    3 ≤ a.length ≤ 105,
    1 ≤ a[i] ≤ 1000.

  • [input] array.integer b

    Array of integers of the same length as a.

    Guaranteed constraints:
    b.length = a.length,
    1 ≤ b[i] ≤ 1000.

  • [output] boolean

    true if a and b are similar, false otherwise.



Solution

def areSimilar(a, b):

return sorted(a) == sorted(b) and sum([i != j for i,j in zip(a,b)]) <= 2:


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

[Algorithm] palindromeRearranging  (0) 2018.02.26
[Algorithm] arrayChange  (0) 2018.02.26
[Algorithm] addBoarder  (0) 2018.02.26
[Algorithm] alternatingSums  (0) 2018.02.26
[Algorithm] reverseParentheses  (0) 2018.02.20

+ Recent posts