CtCI_Ch3_스택과큐

Ch3. 스택과 큐

코딩 인터뷰 완전 분석(저 : 게일 라크만 맥도웰) 참조

  • 스택 구현하기

    • 스택은 데이터를 쌓아올리는 자료구조이다. 스택은 LIFO(Last-In-First-Out)에 따라 자료를 배열한다.

    • 즉, 가장 최근에 스택에 추가한 항목이 가장 먼저 제거될 항목이 된다.

    • 스택에는 다음과 같은 연산이 존재한다.

      • pop(): 스택에서 가장 위에 있는 항목을 제거한다.

      • push(item): item을 스택의 가장 위에 추가한다.

      • peek(): 스택의 가장 위에 있는 항목을 반환한다.

      • isEmpty(): 스택이 비어있을 때에 True를 반환한다.

    • 파이썬을 통해 스택을 아래와 같이 구현할 수 있다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      class Stack():

      def __init__(self):
      self.stack = []

      def __len__(self):
      return len(self.stack)

      def isempty(self):
      if self.stack:
      return False
      else:
      return True

      def push(self, num):
      self.stack.append(num)

      def pop(self):
      if self.stack:
      return self.stack.pop()
      else:
      raise Exception("stack is empty")

      def peek(self):
      if self.stack:
      return self.stack[-1]
      else:
      raise Exception("stack is empty")
  • 큐 구현하기

    • 큐는 FIFO(First-In-First-Out)에 따라 자료를 배열한다.

    • 즉, 큐에 저장되는 항목들은 추가되는 순서대로 제거된다.

    • 큐에는 다음과 같은 연산이 존재한다.

      • add(item): item을 리스트의 끝부분에 추가한다.

      • remove(item): 리스트의 첫 번쨰 항목을 제거한다.

      • peek(): 큐에서 가장 위에 있는 항목을 반환한다.

      • isEmpty(): 큐가 비어있을 때 True를 반환한다.

    • 파이썬을 통해 아래와 같이 큐를 구현할 수 있다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      class Queue():

      def __init__(self):
      self.queue = []

      def push(self, num):
      self.queue.append(num)

      def pop(self):
      if self.queue:
      item = self.queue[0]
      self.queue = self.queue[1:]
      return item
      else:
      raise Exception("Queue is empty")

      def peek(self):
      if self.queue:
      return self.queue[0]
      else:
      raise Exception("Queue is empty")

      def isEmpty(self):
      if not self.queue:
      return True
      else:
      return False

Ch3. 연습문제 코드

CtCI_Ch3_Python

CtCI_Ch1_배열과_문자열

Ch1. 배열과 문자열

코딩 인터뷰 완전 분석(저 : 게일 라크만 맥도웰) 참조

  • 해시테이블

    • 해시테이블(파이썬의 dict)은 키와 값으로 대응되는 자료구조이다.

    • 해시코드 충돌로 인해 최악의 수행 시간은 O(N)이지만, 일반적으로 탐색 시간은 O(1)이다.

    • python dict time complexity에서 시간 복잡도를 확인할 수 있다.

  • 리스트

    • 가변 크기의 자료구조를 원할 때는 리스트(배열)을 사용하게 된다.

    • 리스트는 O(1)의 접근 시간을 유지한다.

    • 리스트의 크기를 두배로 늘리는 시간은 O(n)이지만, 자주 발생하는 일이 아니라서 상환 입력 시간은 O(1)이 된다.

      • Go 를 생각해보자. 슬라이스에 아이템을 하나씩 append 하다가 처음에 정의한 슬라이스의 크기보다 더 들어가야 된다면 그때, 슬라이스의 크기가 두배 늘어나는 상황이다.
    • 상환 입력 시간이 O(1)인 이유

      • 크기가 N인 배열을 생각해보자. N개의 원소를 삽입하기 위해 얼마나 많은 원소를 복사해야 하는지 역으로 계산할 수 있다.

        1
        2
        3
        4
        5
        6
        7
        8
        마지막 배열 크기 증가 : n/2 개의 원소 복사
        이전 배열 크기 증가 : n/4 개의 원소 복사
        이전 배열 크기 증가 : n/8 개의 원소 복사
        .
        .
        .
        두 번쨰 배열 크기 증가 : 2 개의 원소 복사
        첫 번째 배열 크기 증가 : 1 개의 원소 복사
      • 즉, N개의 원소를 삽입하기 위해 복사해야 하는 원소의 총 개수는 1+2+…N/8+N/4+N/2 이며 이는 N보다 작다.

      • 따라서, O(N)이 소요되는 삽입 연산도 존재하기는 하지만 평균적으로 삽입 연산은 O(1)이 소요된다.

Ch1. 연습문제 코드

CtCI_Ch1_Python

탑_2493번

[Python] 백준 2493번 풀이

  • 순서대로 주어지는 탑의 높이를 기준으로 전파가 닿는곳을 구하기 혹은 닿지 않는지를 판단하는 스텍 문제이다.

  • 입력되는 탑의 높이를 스텍에 담아두고 판별한다.

  • 스텍에 특정 높이의 탑이 있을 때, 다음에 들어가는 탑의 높이가 더 높다면 스텍에서 top을 지우면 된다.

    • 왜냐하면, 스텍의 top보다 높은 높이의 탑을 입력받았다면 그 이후에 입력받는 모든 탑들의 전파는 스텍 top에 있는 탑에는 절대 도달할 수 없기 때문이다.

    • 만약 스텍에 판단할 수 있는 top이 없다면 스텍에 입력을 집어넣고 0 을 출력하면 된다.

  • 스텍에 특정 높이의 탑이 있을 때, 다음에 들어가는 탑의 높이가 더 낮다면 스텍에 입력받은 탑의 높이를 top으로 입력하고 이전 top의 위치를 출력해준다.

    • 왜냐하면, 이후에 입력받은 탑의 높이까지 판단해야 하기 때문에 출력과 동시에 스텍의 top으로 저장해준다.

    • 주의할점은, 이렇게 전파가 가로막혀 위치를 출력했다면 while 루프를 벗어나서 다음에 입력받는 탑의 높이로 돌아가야 한다는 것이다.

  • 전파가 가로막혔을 때, 해당 탑의 위치를 출력해야 하는 문제이므로 스텍안에 “(인덱스, 탑의 높이)” 를 갖는 튜플을 저장했다.

  • python 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import sys

n = int(sys.stdin.readline())

tower = list(map(int, sys.stdin.readline().split()))

stack = []


for idx,i in enumerate(tower):
# print(stack)

while stack:
if i > stack[-1][1]:
stack.pop()
elif i < stack[-1][1]:
print(stack[-1][0], end=" ")
stack.append((idx+1,i))
break


if not stack:
stack.append((idx+1,i))
print(0, end=" ")

else: continue

Full Code

Full Code - Python

시간복잡도_big-O

시간 복잡도(big-O)

코딩 인터뷰 완전 분석(저 : 게일 라크만 맥도웰) 참조

  • 실행 시간을 나타내기 위해 사용되는 개념이 시간 복잡도이다.

  • 변수 N을 통해 O(logN), O(NlogN),… 등과 같이 표현하기도 하지만 이외에도 다양한 변수가 포함될 수 있다.

    • 예를 들어, 너비가 w이고 높이가 h인 울타리를 칠한다고 할 때 소요 시간은 O(wh)로 표현할 수 있고 p번 덧칠한다면 O(pwh)로 표현할 수 있다.
  • 상수항과 지배적이지 않은 항은 무시하자.

    • big-O는 단순히 증가하는 비율을 나타내는 개념으로 수행 시간에 지배적이지 않은 항은 무시할 수 있다.

    • 두 개의 중첩되지 않은 루프로 이루어진 코드의 수행 시간을 O(2N) 과 같이 표현할 수도 있지만 이는 결국 O(N)과 같은 의미이다.

    • 마찬가지로, O(N^2 + N)과 같은 수행 시간이 있을 때, N^2이 지배적인 항이므로(N에 비해 빠르게 증가하기 떄문) O(N^2 + N) 은 O(N^2) 이 된다.

    • 즉, big-O 는 수행 시간이 어떻게 변화하는지를 표현해주는 도구이다.

  • 덧셈? 곱셈??

    • 두 단계로 이루어진 알고리즘이 있을 경우, 수행 시간을 어떤 경우에는 더하고 혹은 곱해야 하는걸까?

      1
      2
      3
      4
      5
      6
      7
      ### 덧셈 수행 시간 : O(A+B)
      for (int a : arrA) {
      print(a);
      }
      for (int b : arrB) {
      print(b);
      }
    • 위와 같이 A의 일을 모두 끝마친 후 B의 일을 시행하는 형태라면 A와 B의 수행 시간을 더해야 한다.

      1
      2
      3
      4
      5
      6
      ### 곱셈 수행 시간 : O(A*B)
      for (int a : arrA) {
      for (int b : arrB) {
      print(a + "," + b);
      }
      }
    • 위와 같이 A의 일을 할 때마다 B의 일을 시행하는 형태라면 A와 B의 수행 시간을 곱해야 한다.

  • log N 수행 시간

    • logN 수행 시간이 어떻게 나오는지 알기 위해 이진 탐색을 생각해보자. 이진 탐색은 N개의 정렬된 원소가 들어있는 배열에서 원소 x를 찾을 때, 배열의 중간값과 x의 값을 비교하여 배열의 부분을 재탐색하는 것이다.

    • 예를 들어, 16개의 원소를 가진 배열을 생각해보자. N = 16

    • 이진 탐색을 통해 각 단계별로 탐색해야 하는 원소의 개수는 다음과 같다.

      1
      2
      3
      4
      5
      N = 16 # 처음
      N = 8 # 나누기 2
      N = 4 # 나누기 2
      N = 2 # 나누기 2
      N = 1 # 나누기 2, 찾고자하는 원소 x를 찾았다.
    • 즉, 총 수행 시간은 N을 절반씩 나누는 과정을 몇단계 거쳐서 1이 되는지에 따라서 결정된다.

    • 위의 경우를 반대로 생각해보자. 1에서 16으로 증가하려면 1에서 2를 몇번 곱해야 할까?

      1
      2
      3
      4
      5
      N = 1  # 처음
      N = 2 # 곱하기 2
      N = 4 # 곱하기 2
      N = 8 # 곱하기 2
      N = 16 # 곱하기 2
    • 다시 말해, 절반씩 나누는 과정(나누기2)을 1에서 2를 곱해가는 과정으로도 표현할 수 있다는 뜻이다.

    • 이는, 2를 k번 곱해서 N이 된다고 말할 수 있으며 다음과 같은 수식으로 나타낼 수 있다.

      1
      2^k = N
    • 위 수식을 만족하는 k는 무엇인가? k를 찾기 위해 양 변에 밑이 2인 로그를 취해주자.

      1
      2
      3
      4
      ### <밑이 2인 로그입니다.>
      ---> log(2^k) = logN
      ---> k * log2 = logN
      ---> k = logN (∵ log2 = 1)
    • big-O 에서는 로그의 밑을 고려할 필요가 없다. 위에서 밑이 10인 로그를 취했다 할지라도 이는 상수항일 뿐이다. 시작할 때 말했듯이 big-O 에서 상수항은 무시할 수 있다.

  • 재귀함수의 수행 시간

    • 다음과 같은 재귀함수의 수행 시간은 어떻게 될까?

      1
      2
      3
      4
      5
      6
      int f(int n) {
      if (n<=1) {
      return 1;
      }
      return f(n-1) + f(n-1);
      }
    • 함수 f가 두번 호출되는것을 보고 O(N^2)이라고 생각할 수 있지만 틀렸다.

    • f(4) 일때 위와 같이 f(3)을 두번 호출하고 f(3)은 f(2)를 거쳐 f(1)까지 호출한다.

    • 위와 같이 두 개의 자식 노트를 가진 경우 총 호출 횟수는 얼마인가? 호출 횟수를 표로 나타내보자.

깊이 노드의 개수 2^N 표현
0 1 20
1 2 21
2 4 22
3 8 23
4 16 24
    • 따라서, 전체 노드의 개수는 20 + 21 + 22 + 23 + … + 2N = 2N+1 - 1 이다.

    • 즉, 위와 같은 재귀 함수의 수행 시간은 O(2N)이 된다.

    • 보통 다수의 호출로 이루어진 재귀 함수의 수행 시간은 O(분기깊이) 로 표현할 수 있다. 여기서 분기란 재귀 함수가 자신을 재호출 하는 횟수를 뜻한다.

균형잡힌_세상_4949번

[Python, Go] 백준 4949번 풀이

균형잡힌 세상

  • 괄호문제 의 연장이다.

  • 소괄호뿐만 아니라 대괄호까지 포함해 문장에서 괄호가 올바르게 되어져있는지 확인해야한다.

  • 괄호안에 있는 괄호의 짝도 맞아야 yes를 출력할 수 있다. 예를들어 ( [ ) ] 와 같은 경우 하나의 괄호 안에 올바른 짝의 괄호가 들어가지 못했으므로 no 를 출력해야 한다.

  • 정규표현식을 사용해 따라가야될 괄호들을 뺀 문자들은 pass 시켜주는 방법을 사용했다.

  • 이외에는 괄호문제와같이 스텍에 ( 와 [ 를 담아서 사용했다.

    • 단 ) 와 ] 를 만났을 때, 스텍의 마지막 요소가 짝이되는 괄호인지를 판별해줘야 한다.
  • Python 풀이
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def vps(line):
stack = []
if line[0] == ")" or line[0] == "]":
# print("1")
return "no"
else: pass
for s in line:
if bool(com.match(s)) == True:
pass
elif s == " " or s == ".":
pass
elif s == "(" or s == "[":
stack.append(s)
# print(stack)
elif s == ")" and stack != []:
if stack[-1] == "(":
stack.pop()
else:
# print("2")
return "no"
elif s == "]" and stack != []:
if stack[-1] == "[":
stack.pop()
else:
# print("3")
return "no"
else:
# print("4")
return "no"
if stack == []:
return "yes"
else:
# print("5")
return "no"
  • Go 풀이
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
func vps(x string) string {
var stack []string

// fmt.Println(string(x[0]))
// return x
if string(x[0]) == ")" || string(x[0]) == "]" {
return "no"
}
for _, ch := range x {
s := string(ch)
match, _ := regexp.MatchString("[a-zA-Z]", s)
if match == true {
} else if s == " " || s == "." {
} else if s == "(" || s == "[" {
stack = append(stack, s)
} else if s == ")" && stack != nil {
if stack[len(stack)-1] == "(" {
if len(stack) == 1 {
stack = nil
} else {
stack = stack[:len(stack)-1]
}
} else {
return "no"
}
} else if s == "]" && stack != nil {
if stack[len(stack)-1] == "[" {
if len(stack) == 1 {
stack = nil
} else {
stack = stack[:len(stack)-1]
}
} else {
return "no"
}
} else {
return "no"
}
}
if stack == nil {
return "yes"
} else {
return "no"
}
}
  • Go로 풀이할때, 조건이 많을때는 switch가 더 좋기때문에 switch를 사용했다면 더 좋았을것같다.

Full Code

Full Code - Python

Full Code - Go

괄호_9012번

[Python, Go] 백준 9012번 풀이

괄호

  • 괄호의 쌍이 맞게 이루어져있는지 찾아내는 문제이다.

  • “(“괄호와 “)” 괄호의 개수를 세는것에서 끝나면 안된다.

  • 스택에 “(“ 가 들어왔을때 저장하고 “)” 와 만나면 스택에서 하나를 제거하는 방법으로 쌍을 맞춰주었다.

  • 가장 먼저 들어오는 문자열이 “)” 이라면 쌍이 맞을 수 없으므로 NO 를 리턴하며, 문자열 모두를 파악한 후 stack이 비어있다면 YES 그렇지 않다면 NO 이다

  • Python 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import sys

n = int(sys.stdin.readline())


def vps(li):
stack = []

if li[0] == ")":
return "NO"
else:
for s in li:
if s == "(":
stack.append(s)
elif s == ")" and stack != []:
stack.pop()
else:
return "NO"

if stack == []:
return "YES"
else: return "NO"

for i in range(n):
order = list(sys.stdin.readline().rstrip())
print(vps(order))
  • Go 풀이

    • Go 를 사용할때는 파이썬의 pop과같은 내장함수가 없으므로 “)”를 만났을때 슬라이스의 길이가 1인 경우와 그렇지 않은 경우를 나눠서 판단했다.
func vps(x string) string {
    var stack []string

    for idx, ch := range x {
        s := string(ch)
        if idx == 0 && s == ")" {
            return "NO"
        } else {
            if s == "(" {
                stack = append(stack, s)
            } else if s == ")" && stack != nil {
                length := len(stack)
                if length == 1 {
                    stack = nil
                } else {
                    stack = stack[:length-1]
                }
            } else {
                return "NO"
            }
        }
    }
    if stack == nil {
        return "YES"
    } else {
        return "NO"
    }
}

Full Code

Full Code - Python

Full Code - Go

영화감독_숌_1436번

[Python, Go] 백준 1436번 풀이

영화감독 숌

  • 숫자 6이 연속해서 3번 나타나는 수를 구하는 문제이다.

  • 666, 1666, … , 5666, 의 다음은 6660, 6661, … 이다

  • 666 부터 시작해서 수를 1씩 늘려가면서 모두 확인한다.

  • 해당 수를 string으로 바꾸고 for문을 통해 6이 나왔을때 그 다음의 수도 6인지 그리고 그 다음 숫자도 6인지 확인하는 check 변수를 사용했다.

  • 만약 check가 3이되면 해당 숫자는 6이 연속해서 3번 들어갔으므로 count를 1 증가시키고 주어진 목표만큼 count가 증가하면 종료, 출력했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
n = int(input())

name = 666
count = 0

while True:
if count == n:
print(name-1)
break
else:
check = 0
for i in str(name):
if i == "6":
check += 1
if check == 3:
count += 1
continue
else: pass
else:
check = 0
name += 1
  • Go도 같은 방식의 풀이지만, string을 for문에 돌릴때 반환되는 값은 포인터 값이므로 string(x) 로 바꿔주는것만 주의 참조

  • string을 int로 바꿀때 strconv.ParseInt 를 사용했으나 strconv.Atoi를 사용해도됨

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main

import (
"fmt"
"strconv"
)

func main() {
var n int
count := 0
name := 666
fmt.Scanf("%d", &n)

for {
if count == n {
fmt.Printf("%d", name-1)
break
} else {
check := 0
for _, k := range strconv.Itoa(name) {
v, _ := strconv.ParseInt(string(k), 10, 8)
if v == 6 {
check += 1
switch check {
case 3:
count += 1
}
} else {
check = 0
}
}
}
name += 1
}
}
  • check 값이 3인지 확인할때 if문을 사용해도 괜찮지만 switch문을 사용해보았다.

Full Code

Full Code - Python

Full Code - Go

for문에서_string_사용하기

[Go] string(문자열)을 for문으로 출력, 이용하기

  • Go로 문제를 풀 때, 문자열을 for문으로 돌려야 하는 경우가 자주 발생했다.

  • 파이썬같은 경우, 문자열을 다음과 같이 입력하면 문자열 그대로 출력된다.

1
2
for i in "CAT":
print(i) #print : C A T
  • Go도 문자열을 for문에 사용할 수는 있지만, 파이썬과 달리 Go는 인덱스와 포인터 값을 반환한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

func main() {
str := "CAT"
for _, r := range str {
c := string(r)
fmt.Println(c)
}
fmt.Println()
for i, r := range str {
fmt.Println(i, r, string(r))
}
}
  • 위의 코드를 실행시켜보면, 다음과 같이 출력된다.
    C
    A
    T

0 67 C
1 65 A
2 84 T

  • 위와같이, Go에서는 for문에서 문자열이 아닌 포인터값(int)을 반환한다.

  • 따라서 문자열을 이용하고 싶을 경우, 새로운 변수를 만들고 이에 string()함수를 통해 초기화 시켜주어야 한다.

    • 위의 예처럼, 반환받은 r값을 새로운 변수 c := string(r) 로 초기화 시켜서 사용.

스택_10828번

[Python, Go] 백준 10828번 풀이

스택

  • 주어지는 명령에 따라 스택을 처리하는 문제이다. 파이썬은 큐나 스택을 지원하는 라이브러리가 있지만 사용하지 않고 리스트를 통해 구현했으며, Go는 슬라이스를 통해 구현했다.
  • 스택을 초기화할 필요가 있는 문제가 아니었으므로 하나의 파이썬의 경우 하나의 for문안에서 처리하고 Go는 각각의 명령에 따른 함수를 만들어 사용했다.

  • Python 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import sys

n = int(sys.stdin.readline())

stack = []

# n = int(input())

for i in range(n):

order = sys.stdin.readline().rstrip()
# print(order)
if len(order.split()) == 2:
stack.insert(0,int(order.split()[1]))

else:
if order == "pop":
if stack == []:
print(-1)
else:
print(stack[0])
stack.pop(0)
elif order == "size":
print(len(stack))
elif order == "empty":
if stack == []:
print(1)
else:
print(0)
# top
else:
if not stack == []:
print(stack[0])
else:
print(-1)
  • Go를 통해 슬라이스를 다룰때 파이썬의 pop과 같은 내장함수가 없다.

    • 따라서, 슬라이스에서 하나를 제거할 때 슬라이스의 길이가 1인경우와 1이 아닌경우를 나눠서 생각했다.

    • 슬라이스의 길이가 1인경우, 남아있는 하나를 제거하고 empty slice를 만들기 위해 nil 처리

    • 슬라이스의 길이가 1이 아닌 경우, 슬라이스의 가장 끝의 하나를 제거하면 되므로 슬라이스의 길이 L 을 구하고 L-1 까지의 슬라이스만을 가져간다.

  • Go 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package main

import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)

var s []int

func s_push(x int) {
s = append(s, x)
}

func s_pop() {

if s == nil {
fmt.Printf("%d\n", -1)
} else if len(s) == 1 {
top := s[0]
fmt.Printf("%d\n", top)
s = nil
} else {
l := len(s)
top := s[l-1]
fmt.Printf("%d\n", top)
s = s[:l-1]
}
}

func s_size() {
l := len(s)
fmt.Printf("%d\n", l)
}

func s_empty() {
if s == nil {
fmt.Printf("%d\n", 1)
} else {
fmt.Printf("%d\n", 0)
}
}

func s_top() {
if s == nil {
fmt.Printf("%d\n", -1)
} else {
l := len(s)
top := s[l-1]
fmt.Printf("%d\n", top)
}
}

func main() {
var n int
inputReader := bufio.NewReader(os.Stdin)
fmt.Scanf("%d", &n)

for i := 0; i < n+1; i++ {
input, _ := inputReader.ReadString('\n')

order := strings.Split(input, " ")

action := strings.TrimSpace(order[0])

if len(order) == 2 {
n := strings.TrimSpace(order[1])
num, _ := strconv.Atoi(n)
s_push(num)
} else {
switch action {
case "pop":
s_pop()
case "size":
s_size()
case "empty":
s_empty()
case "top":
s_top()
}
}
}
}

Full Code

Full Code - Python

Full Code - Go

Golang_정리하기_4

[Go tutorial] Go 정리하기 - 4

Go-tour 참조

구름edu 참조

  • 스위치 (switch)

    • case의 라벨과 일치하는경우를 찾아 실행

    • 어느것에도 맞지않다면 default문으로 실행 가능

    • break를 따로 입력하지 않아도 해당되는 case문만 실행된다.

    • 스위치의 각 조건은 위에서 아래로 평가한다. 참인 case를 찾으면 평가를 마침.

    • switch 전달 인자

      • 태그

      • 표현식

      • 전달되는 인자 없이 case에 표현식 사용 가능

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        func main() {
        var a, b int

        fmt.Print("정수 a와 b를 입력하시오:")
        fmt.Scanln(&a, &b)

        switch {
        case a > b:
        fmt.Println("a가 b보다 큽니다.")
        case a < b:
        fmt.Println("a가 b보다 작습니다.")
        case a == b:
        fmt.Println("a와 b가 같습니다.")
        default:
        fmt.Println("모르겠어요.")
        }
        }
  • 메소드와 인터페이스

    • 메소드란 특정 속성들(구조체)을 이용해 기능을 수행하기 위해 만들어진 함수이다.

    • 선언

      • “func (매개변수이름 구조체이름) 메소드이름() 반환형 {}” 형식으로 선언
    • 매개변수 이름은 메소드 내에서 매개변수처럼 사용

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      type Vertex struct {
      X, Y float64
      }

      func (v *Vertex) Abs() float64 {
      return math.Sqrt(v.X*v.X + v.Y*v.Y)
      }

      func main() {
      v := &Vertex{3, 4}
      fmt.Println(v.Abs()) ### print : 5
      }
    • 위의 예에서는 메소드에 구조체를 붙였다.

    • 뿐만 아니라 메소드에는 아무 타입이나 붙일 수 있다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      type MyFloats float64

      func (f MyFloats) Abs() float64 {
      if f < 0 {
      return float64(-f)
      }
      return float64(f)
      }

      func main() {
      k := MyFloats(-math.Sqrt2)
      fmt.Println(k.Abs()) ### print : 1.4142135623730951
      }
    • 위의 예에서는 float타입을 메소드에 붙였다.

  • 인터페이스

    • 구조체가 변수를 묶어놓은 것이라면, 인터페이스는 메소드를 모아놓은 것이다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      package main

      import (
      "fmt"
      "math"
      )

      type geometry interface {
      area() float64
      perimeter() float64
      }

      type Rect struct {
      width, height float64
      }

      type Circle struct {
      radius float64
      }

      func (r Rect) area() float64 {
      return r.width * r.height
      }

      func (c Circle) area() float64 {
      return math.Pi * c.radius * c.radius
      }

      func (r Rect) perimeter() float64 {
      return 2 * (r.width + r.height)
      }

      func (c Circle) perimeter() float64 { .Pi * c.radius
      }

      func main() {
      r1 := Rect{10, 20}
      c1 := Circle{10}
      r2 := Rect{12, 14}
      c2 := Circle{5}

      printMeasure(r1, c1, r2, c2)
      }

      func printMeasure(m ...geometry) {
      for _, val := range m {
      fmt.Println(val)
      fmt.Println(val.area())
      fmt.Println(val.perimeter())
      }
      }
    • 위의 예를 보면 인터페이스 안에 메소드가 들어가있다. 또한, 같은 이름의 메소드가 두개씩 있다.

    • 이름이 동일하게 선언되어도 메소드가 전달받는 구조체가 다르기 때문에 괜찮은것이다.

    • 메인함수에서 구조체를 초기화하고 for문을 통해 각 구조체를 전달받은 메소드에 대해 결과값을 출력하고 있다.

    • 빈 인터페이스

      • 인터페이스는 어떠한 타입도 담을 수 있는 dynamic type 이다.

      • 인터페이스는 매개변수로 사용할 수 있다.

      • 인터페이스는 내용을 따로 선언하지 않아도 형으로 사용할 수 있다.

      • 하나의 변수를 형이 다른 형태로 저장해 출력한다고 생각한다면, 매개변수형에 따른 2개 이상의 함수를 만들어야한다.

      • 하지만 빈 인터페이스를 사용한다면, 어떤 형도 담을 수 있기 때문에 편하게 사용이 가능하게된다.

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        package main

        import "fmt"

        func printVal(i interface{}) {
        fmt.Println(i)
        }

        func main() {
        var x interface{} //빈 인터페이스 선언

        x = 1
        printVal(x)

        x = "test"
        printVal(x)
        }
      • 위의 예에서 x의 값에따라 다르게 형을 선언하지 않고 출력하는것을 확인할 수 있다.

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×