내일배움캠프 4주차 Weekly I Learned

정형빈·2022년 9월 28일
0

WIL

목록 보기
4/15

내일배움캠프 4주차 회고

4주차 시간표

이번 주차는 저번 주차에 시작된 자료구조와 알고리즘 원격강의, 그리고 새롭게 시작된 파이썬 장고 실무 기초 원격강의가 주가 되는 한 주였다. 금요일에는 처음 해보는 새로운 프로그램인 타임어택 구현 테스트라는 것도 있었다. 그리고 시간표상으로는 나타나지 않았지만 파이썬 및 장고 거북이반 스터디도 매일 계속되고 있었다.

자료구조와 알고리즘 원격강의

알고리즘이란?

  • 어떤 문제의 해결을 위하여, 입력된 자료를 토대로 하여 원하는 출력을 유도하여 내는 규칙의 집합. 여러 단계의 유한 집합으로 구성되는데, 각 단계는 하나 또는 그 이상의 연산을 필요로 한다.
  • 어떤 문제가 있을때, 그것을 해결하기 위한 여러 동작들의 모임이다.

알고리즘을 공부해야하는 이유

1. 좋은 개발자가 되기 위해서

  • 개발자는 프로그램을 만드는 직업이기 때문에 좋은 개발자가 되려면 좋은 프로그램을 구현할 줄 알아야 한다.
    • 좋은 프로그램이란? 적은 공간을 이용해서 빠른 속도로 수행되는 프로그램이다.
    • 그런 프로그램을 만들기 위해서는 경우에 따라 특정 자료구조나 접근방법을 사용해야 한다. 즉, 프로그램을 잘하기 위해서는 여러 자료구조와 방법들을 배우고 익혀야 좋은 프로그램을 만들 수 있다.

2. 좋은 회사에 취직하기 위해서

  • 수많은 회사들이 코딩테스트를 통해 개발자를 구인하고 있다. 카카오, 삼성, 구글 등 국내외 유망 IT 기업들 외에도 많은 스타트업까지 코딩테스트를 개발자의 필수 관문으로 만들고 있다. 하지만 엄청나게 어려운 수준의 문제를 출제하진 않는다. 기초적인 지식과 해결책으로 적절한 사고를 할 수 있는지에 대해 검증하기 위해 필수 관문을 만드는 것이다.

최댓값 찾기

  • Q. 다음과 같이 숫자로 이루어진 배열이 있을 때, 이 배열 내에서 가장 큰 수를 반환하시오.

    [3, 5, 6, 1, 2, 4]
  • A1.

    • 각 숫자마다 모든 다른 숫자와 비교해서 최대값인지 확인한다. 만약 다른 모든 값보다 크다면 반복문을 중단한다.

    • python 의 for ~ else 문은 for문에서 break가 발생하지 않았을 경우의 동작을 else문에 적어주는 것이다.

      def find_max_num(array):
          for num in array:
              for compare_num in array:
                  if num < compare_num:
                      break
              else:
                  return num
      
      print("정답 = 6 / 현재 풀이 값 = ", find_max_num([3, 5, 6, 1, 2, 4]))
      print("정답 = 6 / 현재 풀이 값 = ", find_max_num([6, 6, 6]))
      print("정답 = 1888 / 현재 풀이 값 = ", find_max_num([6, 9, 2, 7, 1888]))
  • A2.
    배열 내에서 가장 큰 수를 찾아야 한다. 그러면, 가장 큰 수를 저장할 변수를 만들고, 배열을 돌아가면서 그 변수와 비교한다. 만약 값이 더 크다면, 그 변수에 대입한다.

      def find_max_num(array):
          max_num = array[0]
          for num in array:
              if num > max_num:
                  max_num = num
          return max_num
      
      print("정답 = 6 / 현재 풀이 값 = ", find_max_num([3, 5, 6, 1, 2, 4]))
      print("정답 = 6 / 현재 풀이 값 = ", find_max_num([6, 6, 6]))
      print("정답 = 1888 / 현재 풀이 값 = ", find_max_num([6, 9, 2, 7, 1888]))
      ```

최빈값 찾기

  • Q. 다음과 같은 문자열을 입력받았을 때, 어떤 알파벳이 가장 많이 포함되어 있는지 반환하시오
"hello my name is sparta"
  • A1.
    각 알파벳마다 문자열을 돌면서 몇 글자 나왔는지 확인한다. 만약 그 숫자가 저장한 알파벳 빈도 수보다 크다면, 그 값을 저장하고 제일 큰 알파벳으로 저장한다. 이 과정을 반복하다보면 가장 많이 나왔던 알파벳을 알 수 있다.
        
        def find_max_occurred_alphabet(string):
            alphabet_array = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
                              "t", "u", "v", "x", "y", "z"]
            max_occurrence = 0
            max_alphabet = alphabet_array[0]
        
            for alphabet in alphabet_array:
                occurrence = 0
                for char in string:
                    if char == alphabet:
                        occurrence += 1
        
                if occurrence > max_occurrence:
                    max_alphabet = alphabet
                    max_occurrence = occurrence
        
            return max_alphabet
        
        result = find_max_occurred_alphabet
        print("정답 = a 현재 풀이 값 =", result("Hello my name is sparta"))
        print("정답 = a 현재 풀이 값 =", result("Sparta coding club"))
        print("정답 = s 현재 풀이 값 =", result("best of best sparta"))
  • A2. 각 알파벳의 빈도수를 alphabet_occurrence_list 라는 변수에 저장한다. 그리고 각 문자열을 돌면서 해당 문자가 알파벳인지 확인하고, 알파벳을 인덱스 화 시켜 각 알파벳의 빈도수를 업데이트 한다. 이후, 알파벳의 빈도수가 가장 높은 인덱스를 찾는다.
      
        
        def find_max_occurred_alphabet(string):
            alphabet_occurrence_array = [0] * 26
        
            for char in string:
                if not char.isalpha():
                    continue
                arr_index = ord(char) - ord('a')
                alphabet_occurrence_array[arr_index] += 1
        
            max_occurrence = 0
            max_alphabet_index = 0
            for index in range(len(alphabet_occurrence_array)):
                alphabet_occurrence = alphabet_occurrence_array[index]
                if alphabet_occurrence > max_occurrence:
                    max_occurrence = alphabet_occurrence
                    **max_alphabet_index** = index

여기까지 했으면, 가장 높은 빈도수의 인덱스를 알아낼 수 있다. 이제 chr() 함수를 사용하면 아스키 코드 번호를 실제 문자로 변환할 수 있다.

        chr(97) == 'a'
        chr(0 + ord('a')) == 'a'
        chr(0 + 97) == 'a'
        chr(1 + 97) == 'b'

최종 답안

        def find_max_occurred_alphabet(string):
            alphabet_occurrence_array = [0] * 26
        
            for char in string:
                if not char.isalpha():
                    continue
                arr_index = ord(char) - ord('a')
                alphabet_occurrence_array[arr_index] += 1

            max_occurrence = 0
            max_alphabet_index = 0
            for index in range(len(alphabet_occurrence_array)):
                alphabet_occurrence = alphabet_occurrence_array[index]
                if alphabet_occurrence > max_occurrence:
                    max_occurrence = alphabet_occurrence
                    max_alphabet_index = index
        
            return chr(max_alphabet_index + ord('a'))
        
        result = find_max_occurred_alphabet
        print("정답 = a 현재 풀이 값 =", result("Hello my name is sparta"))
        print("정답 = a 현재 풀이 값 =", result("Sparta coding club"))
        print("정답 = s 현재 풀이 값 =", result("best of best sparta"))

시간 복잡도 판단하기

  • 시간 복잡도란?

    • 입력값과 문제를 해결하는 데 걸리는 시간과의 상관관계
    • 입력값이 2배로 늘어났을 때 문제를 해결하는 데 걸리는 시간은 몇 배로 늘어나는지를 보는 것이다.
  • Q. 최댓값 찾기 알고리즘의 시간 복잡도 판단해보기

    • A1.
        input = [3, 5, 6, 1, 2, 4]
        
        def find_max_num(array):
            for num in array:
                for compare_num in array:
                    if num < compare_num:
                        break
                else:
                    return num
        
        result = find_max_num(input)
        print("정답 = 6 / 현재 풀이 값 = ", find_max_num([3, 5, 6, 1, 2, 4]))
        print("정답 = 6 / 현재 풀이 값 = ", find_max_num([6, 6, 6]))
        print("정답 = 1888 / 현재 풀이 값 = ", find_max_num([6, 9, 2, 7, 1888]))
  • 이 해결 방법은 각 숫자마다 모든 다른 숫자와 비교해서 최대값인지 확인한다. 만약 다른 모든 값보다 크다면 반복문을 중단한다. 이제 이 함수가 시간이 얼마나 걸리는지 분석하려면 각 줄이 실행되는 걸 1번의 연산이 된다고 생각하고 계산한다.
            for num in array:              # array 의 길이만큼 아래 연산이 실행
                for compare_num in array:  # array 의 길이만큼 아래 연산이 실행
                    if num < compare_num:  # 비교 연산 1번 실행
                        break
                else:
                    return num
  • 위에서 연산된 것들을 더해보면,
      1. array의 길이 X array의 길이 X 비교 연산 1번만큼의 시간이 필요하다. 여기서 array(입력값)의 길이는 보통 N이라고 표현한다. 그러면 위의 시간을 다음과 같이 표현할 수 있다.
N×NN \times N

그러면 이제 이 함수는 N2N^2 만큼의 시간이 걸렸다고 표현 할 수 있다.

  • A2.
        def find_max_num(array):
            max_num = array[0]        
            for num in array:      
                if num > max_num:  
                    max_num = num
            return max_num
        
        result = find_max_num(input)
        print("정답 = 6 / 현재 풀이 값 = ", find_max_num([3, 5, 6, 1, 2, 4]))
        print("정답 = 6 / 현재 풀이 값 = ", find_max_num([6, 6, 6]))
        print("정답 = 1888 / 현재 풀이 값 = ", find_max_num([6, 9, 2, 7, 1888]))
  • 이 해결 방법은 리스트를 하나씩 돌면서 num 과 max_num 값을 비교하는 함수이다.
            max_num = array[0] # 연산 1번 실행
        		for num in array:      # array 의 길이만큼 아래 연산이 실행
        		    if num > max_num:  # 비교 연산 1번 실행
        		        max_num = num  # 대입 연산 1번 실행

위에서 연산된 것들을 더해보면,
1. max_num 대입 연산 1번
2. array의 길이 X (비교 연산 1번 + 대입 연산 1번)
만큼의 시간이 필요하다. 첫 번째 방법에서 했던 것처럼 array 의 길이를 N이라고 하면 다음과 같이 표현할 수 있다.

1+2×N1+2\times N

그러면 우리는 이제 이 함수는 2N+12N+1 만큼의 시간이 걸렸음을 알 수 있다.

공간 복잡도 판단하기

  • 공간 복잡도란?

    • 입력값과 문제를 해결하는 데 걸리는 공간과의 상관관계
    • 입력값이 2배로 늘어났을 때 문제를 해결하는 데 걸리는 공간은 몇 배로 늘어나는지를 보는 것이다.
  • Q. 최빈값 찾기 알고리즘의 공간 복잡도 판단해보기

    • A1.
        def find_max_occurred_alphabet(string):
            alphabet_array = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "x", "y", "z"]
            max_occurrence = 0
            max_alphabet = alphabet_array[0]
        
            for alphabet in alphabet_array:
                occurrence = 0
                for char in string:
                    if char == alphabet:
                        occurrence += 1
        
                if occurrence > max_occurrence:
                    max_alphabet = alphabet
                    max_occurrence = occurrence
        
            return max_alphabet
        
        result = find_max_occurred_alphabet
        print("정답 = a 현재 풀이 값 =", result("Hello my name is sparta"))
        print("정답 = a 현재 풀이 값 =", result("Sparta coding club"))
        print("정답 = s 현재 풀이 값 =", result("best of best sparta"))

이 해결 방법은 각 알파벳마다 문자열을 돌면서 몇 글자 나왔는지 확인한다. 만약 그 숫자가 저장한 알파벳 빈도 수보다 크다면, 그 값을 저장하고 제일 큰 알파벳으로 저장한다. 이 함수가 공간을 얼마나 사용하는지 분석하려면 저장하는 데이터의 양이 1개의 공간을 사용한다고 계산하면 된다.

            alphabet_array = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "x", "y", "z"]
        # -> 26 개의 공간을 사용합니다
            max_occurrence = 0 # 1개의 공간을 사용합니다
            max_alphabet = alphabet_array[0]   # 1개의 공간을 사용합니다.
        
            for alphabet in alphabet_array:
                occurrence = 0  # 1개의 공간을 사용합니다

위에서 사용된 공간들을 더해보면,
1. alphabet_array 의 길이 = 26
2. max_occurrence, max_alphabet, occurrence 변수 = 3

2929

만큼의 공간이 필요하다.

  • A2.
        def find_max_occurred_alphabet(string):
            alphabet_occurrence_list = [0] * 26
        
            for char in string:
                if not char.isalpha():
                    continue
                arr_index = ord(char) - ord('a')
                alphabet_occurrence_list[arr_index] += 1
        
            max_occurrence = 0
            max_alphabet_index = 0
            for index in range(len(alphabet_occurrence_list)):
                alphabet_occurrence = alphabet_occurrence_list[index]
                if alphabet_occurrence > max_occurrence:
                    max_occurrence = alphabet_occurrence
                    max_alphabet_index = index
        
            return chr(max_alphabet_index + ord('a'))
        
        result = find_max_occurred_alphabet
        print("정답 = a 현재 풀이 값 =", result("Hello my name is sparta"))
        print("정답 = a 현재 풀이 값 =", result("Sparta coding club"))
        print("정답 = s 현재 풀이 값 =", result("best of best sparta"))

이 해결 방법은 각 알파벳의 빈도수를 저장한 다음에, 빈도 수 중 가장 많은 알파벳의 인덱스 값을 반환한다.

        		alphabet_occurrence_list = [0] * 26 # -> 26 개의 공간을 사용합니다
        
            for char in string:
                if not char.isalpha():
                    continue
                arr_index = ord(char) - ord('a')  # 1개의 공간을 사용합니다
                alphabet_occurrence_list[arr_index] += 1
        
            max_occurrence = 0                   # 1개의 공간을 사용합니다
            max_alphabet_index = 0               # 1개의 공간을 사용합니다
            for index in range(26):
                alphabet_occurrence = alphabet_occurrence_list[index] # 1개의 공간을 사용합니다
                if alphabet_occurrence > max_occurrence:
                    max_occurrence = alphabet_occurrence
                    max_alphabet_index = index

위에서 사용된 공간들을 더해보면,
1. alphabet_array 의 길이 = 26
2. arr_index, max_occurrence, max_alphabet_index, alphabet_occurrence 변수 = 4

3030

만큼의 공간이 필요합니다.

그러면 우리는 이제 이 함수는 3030 만큼의 공간이 사용되었음을 알 수 있다.

점근 표기법

  • 점근 표기법이란?

    • 알고리즘의 성능을 수학적으로 표기하는 방법이다.

    • 알고리즘의 “효율성”을 평가하는 방법이다.

    • 점근 표기법(asymptotic notation)은 어떤 함수의 증가 양상을 다른 함수와의 비교로 표현하는 수론과 해석학의 방법이다.

    • 점근 표기법의 종류에는 빅오(Big-O)표기법, 빅 오메가(Big-Ω) 표기법이 있다.

      • 빅오 표기법은 최악의 성능이 나올 때 어느 정도의 연산량이 걸릴것인지를 표기한다.
      • 빅오메가 표기법은 최선의 성능이 나올 때 어느 정도의 연산량이 걸릴것인지를 표기한다.
  • 배열에서 특정 요소 찾기

    • Q. 다음과 같은 숫자로 이루어진 배열이 있을 때, 이 배열 내에 특정 숫자가 존재한다면 True, 존재하지 않다면 False 를 반환하시오.
    • A.
        def is_number_exist(number, array):
            for element in array:
                if number == element:
                    return True
            return False
        
        result = is_number_exist
        print("정답 = True 현재 풀이 값 =", result(3,[3,5,6,1,2,4]))
        print("정답 = Flase 현재 풀이 값 =", result(7,[6,6,6]))
        print("정답 = True 현재 풀이 값 =", result(2,[6,9,2,7,1888]))

알고리즘 더 풀어보기 (1)

  • 곱하기 or 더하기

    • Q. 다음과 같이 0 혹은 양의 정수로만 이루어진 배열이 있을 때, 왼쪽부터 오른쪽으로 하나씩 모든 숫자를 확인하며 숫자 사이에 '✕' 혹은 '+' 연산자를 넣어 결과적으로 가장 큰 수를 구하는 프로그램을 작성하시오. 단, '+' 보다 '✕' 를 먼저 계산하는 일반적인 방식과는 달리, 모든 연산은 왼쪽에서 순서대로 이루어진다.

               def find_max_plus_or_multiply(array):
                   # 이 부분을 채워보세요!
                   return 1
               
               result = find_max_plus_or_multiply
               print("정답 = 728 현재 풀이 값 =", result([0,3,5,6,1,2,4]))
               print("정답 = 8820 현재 풀이 값 =", result([3,2,1,5,9,7,4]))
               print("정답 = 270 현재 풀이 값 =", result([1,1,1,3,3,2,5]))
      			```
               
    • A.

           def find_max_plus_or_multiply(array):
               multiply_sum = 0
               for number in array:
                   if number <= 1 or multiply_sum <= 1:
                       multiply_sum += number
                   else:
                       multiply_sum *= number
               return multiply_sum
           
           result = find_max_plus_or_multiply
           print("정답 = 728 현재 풀이 값 =", result([0,3,5,6,1,2,4]))
           print("정답 = 8820 현재 풀이 값 =", result([3,2,1,5,9,7,4]))
           print("정답 = 270 현재 풀이 값 =", result([1,1,1,3,3,2,5]))

알고리즘 더 풀어보기 (2)

  • 반복되지 않는 문자

    • Q. 다음과 같이 영어로 되어 있는 문자열이 있을 때, 이 문자열에서 반복되지 않는 첫번째 문자를 반환하시오. 만약 그런 문자가 없다면 _ 를 반환하시오.

              input = "abadabac"
              
              def find_not_repeating_first_character(string):
                  # 이 부분을 채워보세요!
                  return "_"
              
              result = find_not_repeating_first_character
              print("정답 = d 현재 풀이 값 =", result("abadabac"))
              print("정답 = c 현재 풀이 값 =", result("aabbcddd"))
              print("정답 =_ 현재 풀이 값 =", result("aaaaaaaa"))
              ```
              
    • A.

      def find_not_repeating_first_character(string):
          alphabet_occurrence_array = [0] * 26
      
          for char in string:
              if not char.isalpha():
                  continue
              arr_index = ord(char) - ord("a")
              alphabet_occurrence_array[arr_index] += 1
      
          not_repeating_character_array = []
          for index in range(len(alphabet_occurrence_array)):
              alphabet_occurrence = alphabet_occurrence_array[index]
      
              if alphabet_occurrence == 1:
                  not_repeating_character_array.append(chr(index + ord("a")))
      
          for char in string:
              if char in not_repeating_character_array:
                  return char
      
          return "_"
      
      result = find_not_repeating_first_character
      print("정답 = d 현재 풀이 값 =", result("abadabac"))
      print("정답 = c 현재 풀이 값 =", result("aabbcddd"))
      print("정답 =_ 현재 풀이 값 =", result("aaaaaaaa"))

1주차 끝 & 숙제 설명

소수 나열하기

  • Q1. 정수를 입력 했을 때, 그 정수 이하의 소수를 모두 반환하시오. (소수는 자신보다 작은 두 개의 자연수를 곱하여 만들 수 없는 1보다 큰 자연수이다.)

  • A1.

input = 20


def find_prime_list_under_number(number):
    prime_list = []

    for n in range(2, number + 1):
        for i in prime_list:
            if n % i == 0 and i * i <= n:
                break
        else:
            prime_list.append(n)

    return prime_list


result = find_prime_list_under_number(input)
print(result)

풀이

소수는 약수가 자기자신과 1 밖에 없는 수를 뜻하기 때문에 소수를 구하는 함수를 우선 만들어준다. range의 범위를 2부터 number까지로 설정하기 위해 for문을 만들어주고 여기서 나온 n이라는 값을 2부터 n-1까지 나누어보고 이 때 나누어 떨어지지 않으면 소수이기 때문에 prime_list에 append해준다. 주어진 자연수 N이 소수이기 위한 필요충분 조건은 N이 N의 제곱근보다 크지 않은 어떤 소수로도 나눠지지 않는다. 수가 수를 나누면 몫이 발생하게 되는데 몫과 나누는 수, 둘 중 하나는 반드시 N의 제곱근 이하이기 때문이다. 이를 이용해서 i * i ≤ n 일 때까지만 비교하면 된다.

문자열 뒤집기

  • Q2. 0과 1로만 이루어진 문자열이 주어졌을 때, 이 문자를 모두 0, 혹은 모두 1로 같게 만들어야 한다. 할 수 있는 행동은 연속된 하나의 숫자를 잡고 모두 뒤집는 것 이다. 뒤집는 것은 1을 0으로, 0을 1로 바꾸는 것을 의미한다. 주어진 문자열을 모두 0 혹은 모두 1로 같게 만드는 최소 횟수를 반환하시오.
      input = "011110"


      def find_count_to_turn_out_to_all_zero_or_all_one(string):
          # 이 부분을 채워보세요!
          return 1


      result = find_count_to_turn_out_to_all_zero_or_all_one(input)
      print(result)

-A2.

      input = "011110"


      def find_count_to_turn_out_to_all_zero_or_all_one(string):
          count_to_all_zero = 0
          count_to_all_one = 0

          if string[0] == '0':
              count_to_all_one += 1
          elif string[0] == '1':
              count_to_all_zero += 1

          for i in range(len(string) - 1):
              if string[i] != string[i + 1]:
                  if string[i + 1] == '0':
                      count_to_all_one += 1
                  if string[i + 1] == '1':
                      count_to_all_zero += 1

          return min(count_to_all_one, count_to_all_zero)


      result = find_count_to_turn_out_to_all_zero_or_all_one(input)
      print(result)

풀이

"뒤집는 횟수"는 0에서 1로 변하는 순간 혹은 1에서 0으로 변하는 순간이다.

0에서 1로 변한다는 소리는, 0으로 다시 뒤집어야 하니 전체를 0으로 만들기 위한 숫자가 +1 된다.
1에서 0으로 변한다는 소리는, 1로 다시 뒤집어야 하니 전체를 1로 만들기 위한 숫자가 +1 된다.

1) 뒤집어 질 경우
2) 첫 번째 원소가 0인지 1인지
에 대해서 계산하면, 모두 0으로 만드는 횟수와 모두 1로 만드는 횟수를 만들 수 있다. 그리고 0으로 만드는 횟수와 모두 1로 만드는 횟수 둘 중 최솟값을 반환해주면 답을 구할 수 있다.

입력값의 첫번째 숫자가 0일 경우 문자열을 모두 1로 만드는 최소 뒤집는 횟수를 +1 해주고 반대로 첫번째 숫자가 1일 경우 문자열을 모두 0으로 만드는 최소 뒤집는 횟수를 +1 해준다.

for문을 만들어 두번째 세번째 ~ input값의 자릿수 만큼 계산해 0이냐 1이냐에 따라 뒤집는 횟수를 1씩 더하는 함수를 만든다. 그렇게 해서 뒤집는 횟수를 구했을때 모두 0일때와 모두 1일때 중 뒤집는 횟수가 더 적은쪽을 구하도록 min함수를 이용해 값을 return해준다.

마지막으로 해당 결과값을 print해주도록 코드를 작성해준다.

여기까지가 무려 1주차의 자료구조와 알고리즘 강의의 내용이다. 내용도 상당히 많고 내용도 어려운것이 마치 수학문제를 풀던 때가 생각이 났다. 처음부터 튜터님이나 매니저님들이 중요도가 높은 과목이 아니라고 하셨기 때문에 파이썬 문법에 집중하기 위해 1주차 까지만 수강하고 다음에 나머지를 수강하기로 했다.

파이썬 거북이반

import random

option = ["가위", "바위", "보"]
computer = random.randint(0, 2)
computer_value = option[computer]

while True:
    user_value = input("가위 바위 보?")
    if user_value in option:
        break
    else:
        print("값을 정확히 입력해주세요!")

print(f"플레이어는 {user_value}를 선택, 컴퓨터는 {computer_value}를 선택했습니다")


if computer_value == user_value:
    print("비겼습니다")
elif user_value == "가위":
    if computer_value == "바위":
        print("졌습니다")
    else:
        print("이겼습니다")
elif user_value == "바위":
    if computer_value == "보":
        print("졌습니다")
    else:
        print("이겼습니다")

elif user_value == "보":
    if computer_value == "가위":
        print("졌습니다")

    else:
        print("이겼습니다")
else:
    print("예상치 못한 경우입니다")

풀이
랜덤함수를 활용하여 컴퓨터의 가위바위보 값을 랜덤으로 받아오도록 한다. 그리고 input값을 입력했을 때 입력값이 가위바위보에 해당하지 않을 경우 재입력 메세지를 출력하고 올바로 입력했을 경우 나의 입력값과 컴퓨터가 랜덤으로 받아온 값을 비교하여 승패를 결정하는 조건문 함수를 만든다. 그리고 그 결과값을 출력하도록하고 오류발생시 오류메세지를 출력하도록 설정한다.

class란?

  • 클래스를 선언하는것은 과자 틀을 만드는 것이고, 선언된 과자틀(class)로
    과자(instance)를 만든다고 생각하면 된다.
  • 선언 후 바로 사용되는 함수와 다르게 클래스는 인스턴스를 생성하여 사용하게 된다.
  • class 내부에 선언되는 메소드는 기본적으로 self라는 인자를 가지고 있다.
  • self는 클래스 내에서 전역 변수와 같이 사용된다.

용어 정리

- 인스턴스(instance) : class를 사용해 생성된 객체
- 메소드(method) : 메소드란 클래스 내에 선언된 함수이며, 클래스 함수라고도 한다.
- self : 메소드를 선언할 때에는 항상 첫번째 인자로 self를 넣어줘야 한다.
		 클래스 안에 있는 변수나 함수 정보를 담고 있다.
         

저번에도 정리한 내용이지만 클래스를 이보다 깔끔하고 확실하게 설명하는 방법은 없는 것 같아서 다시 한 번 정리내용을 가져왔다.
이 내용들을 머리속에 넣은 채 수업을 들으니 수업에 잘 따라갈 수 있었다. 아직도 클래스를 왜 사용해야 하는지 와닿지는 않지만 클래스를 함수를 통해 클래스 내의 메소드를 통해 인스턴스를 뽑아내는 것이 가능하다는 것 까지는 이해를 할 수있게 되었다.

class Person:
    def talk(self):
        print("안녕하세요 저는" + self.name + "입니다.")
        print("제 나이는" + self.age + "입니다.")
        print("제 취미는" + self.hobby + "입니다.")
        print()

    def __init__(self, name, age, hobby):
        print("이닛 함수 실행중")
        self.name = name
        self.age = age
        self.hobby = hobby


x = Person("권기현", "20", "피아노")
y = Person("오형석", "20", "기타")
z = Person("정형빈", "20", "캐스터넷츠")

x.talk()
y.talk()
z.talk()

# members = []

# members.append(x)
# members.append(y)
# members.append(z)

# for member in members:
#     print(member.name)
#     print(member.age)
#     print(member.hobby)

장고 입문 가이드 특강

- 강민철 튜터님

Framework

  • 웹 프레임워크 또는 웹 어플리케이션 워크라고 불리며 동적인 웹 페이지나, 웹 어플리케이션, 웹 서비스 개발 보조용으로 만들어지는 어플리케이션 프레임워크의 일종
  • 웹 페이지를 개발하는 과정에서 겪는 어려움을 줄이는 것이 주 목적으로 통상 데이터베이스 연동, 템플릿 형태의 표준, 세션 관리, 코드 재사용 등의 기능을 포함

쉽게말해서 웹 서비스를 쉽게 만들어주는 기계라고 튜터님은 표현해주셨고 내부 구조를 들여다보기 보다는 사용법을 익히는 것을 우선시 하라고 말씀해주셨다.

Django

  • Python기반의 웹 프레임워크
    • Flask도 마찬가지로 Python을 기반으로하는 웹 프레임워크지만 Django가 좀 더 기능이 많고 사용법이 복잡하다. 실제로 웹 서비스를 만들때 대부분은 Flask보다는 Django를 많이 사용한다고 한다.
  • MVT(Model->Views->Template)의 흐름으로 구성되어있다.

Django의 핵심 요소

  • 데이터베이스 관리
    • 객체 관리
  • 인증
    • 회원 가입
    • 회원 탈퇴
    • 로그인/로그아웃
    • 회원 정보 수정
  • 요청에 대한 응답을 하기까지
    • Request 가공
    • Response 가공

가상환경

  • 가상환경 == 통
    • 가상환경이란 자신이 원하는 Python 환경을 구축하기 위해 필요한 패키지를 담아 놓는 통 혹은 바구니라고 할 수 있다.
  • 프로그램을 통해서 패키지를 설치하는 방법도 있지만 Git Bash를 통해 명령어로 직접 패키지를 인스톨하는 방법도 있다.
    • 패키지설치 = $ pip install <패키지 이름>
    • 패키지 제거 = $ pip uninstall <패키지 이름>
    • 설치된 패키지 이름 및 버전 조회 = $ pip freeze!
    • 설치된 패키지들의 목록을 requirements.txt로 내보내기 = $ pip freeze > requirements.txt
    • requirements.txt 안에 적힌 파일 설치하기 = $ pip install –r requirements.txt

장고 원격 강의 발제

용어 정리 - 클라이언트 / 서버 / API

  • 클라이언트 : '요청을 보내는 곳'. 주로 '나', '내 컴퓨터' 혹은 '크롬'을 클라이언트라고 한다.
  • 서버 : '요청을 받아서 응답 해 주는 곳' 우리가 인터넷에서 웹페이지, 로그인등의 행동을 하고 난 후에 이루어지는 많은 과정들을 처리 해 준다.
  • API : 데이터를 어떻게 주고 받자! 라고 정한 약속

웹의 동작 구조

  • 페이지를 받는 경우 : HTML, CSS, Javascript가 적절하게 섞여있는 페이지를 받는 경우이다. 우리가 흔히 접속하는 구글, 네이버 등등의 페이지를 보는 경우가 포함되어 있다.
  • 데이터만 받는 경우 : 페이지나 화면은 크게 필요 없고, '데이터' 만을 받고 싶은 경우도 있다. 데이터 베이스에서 자료를 가져오거나, 다른 사람이 만든 데이터를 가져 올 때의 경우가 포함되어있다.

장고 원격 강의

  • 장고에서 사용하는 여러가지 명령어
    • django-admin startapp @ -> 프로젝트의 '앱'을 만드는 명령어
    • python @.py makemigrations -> 데이터베이스 변경을 알려주는 명령어
    • python @.py migrate -> 변경 된 데이터베이스를 적용시켜주는 명령어
  • 장고 admin 화면을 띄우고 그 화면에 생성한 데이터베이스 모델을 추가했다.
  • ORM
    • ORM (Object Relational Mapping) 은 데이터베이스를 하나의 '객체(Object)' 덩어리로 보고, 데이터베이스를 SQL언어가 아닌 클래스로 쉽게 표현 및 사용 할 수 있게 해 준다.
  • admin에 나의 데이터베이스 모델을 추가
  • POST, GET을 분리해서 view.py안에 넣어 기능하도록 작성

타임어택 구현 테스트

1. 전역변수와 지역변수 구분하기

아래 코드에서 a, b 변수가 지역변수인지 / 전역변수인지 구분하고, 코드 실행 없이 결과를 예상해서 적어주세요

a = 10

def test1():
    b = 20

def test2():
    print(a)
    print(b)

test1()
test2()
# 실행이 잘 될까요?
# 실행이 되지 않는다면 어떤 에러가 발생할까요?

A. a는 코드 전체에 적용되는 전역변수이고 b는 test1함수 내에서만 적용되는 지역변수이기 때문에 test2 함수에서 출력할 b의 값이 지정되지 않기 때문에 코드실행에 오류가 발생한다.

2. mutable과 immutable 구분하기

mutable에 해당하는 자료형과 immutable에 해당하는 자료형을 적어주세요

A.

mutable
 - list
 - dictionary

immutable
 - int
 - float
 - str
 - tuple

3. filter/map 혹은 리스트 축약식 활용해서 리스트 다뤄보기

아래 문제를 filter와 map 함수 혹은 리스트 축약식을 활용해 풀어주세요

  1. 1부터 10000까지의 숫자를 numbers 변수에 할당해주세요
  2. 1부터 10000까지 숫자 중, 짝수에 해당하는 숫자만 even_numbers 변수에 할당해주세요
  3. 1부터 10000까지의 숫자 중, 3의 배수이며 15의 배수가 아닌 숫자에 10을 곱하여 some_numbers 에 할당해주세요
def get_even_numbers(numbers):
    result = []
    # some code
    return result

def get_some_numbers(numbers):
    result = []
    # some code
    return result

def main():
    numbers = [] # 1 ~ 10000
    even_numbers = get_even_numbers(numbers)
    some_numbers = get_some_numbers(numbers)
    print(even_numbers) # [2, 4, 6, ...]
    print(some_numbers) # [30, 60, 90, 120, 180, ...]
    
main()

A.

def get_even_numbers(numbers):
    result = list(filter(lambda x: x%2 == 0, numbers))
    return result

def get_some_numbers(numbers):
    result = list(filter(lambda x: x%3 == 0 and x%15 !=0, numbers))
    result = list(map(lambda x: x*10, result))
    return result

def main():
    numbers = list(map(int, range(1, 10001))) # 1 ~ 10000
    even_numbers = get_even_numbers(numbers)
    some_numbers = get_some_numbers(numbers)
    print(even_numbers) # [2, 4, 6, ...]
    print(some_numbers) # [30, 60, 90, 120, 180, ...]
    
main()

4. lambda를 활용해서 정렬해보기

아래 사용자들을 수학, 과학, 영어, 사회 점수의 총 합을 기준으로 총 합이 가장 높은 사람이 첫 번째에 오도록 정렬해주세요

from pprint import pprint

users = [
    {"name": "Ronald", "age": 30, "math_score": 93, "science_score": 65, "english_score": 93, "social_score": 92},
    {"name": "Amelia", "age": 24, "math_score": 88, "science_score": 52, "english_score": 78, "social_score": 91},
    {"name": "Nathaniel", "age": 28, "math_score": 48, "science_score": 40, "english_score": 49, "social_score": 91},
    {"name": "Sally", "age": 29, "math_score": 100, "science_score": 69, "english_score": 67, "social_score": 82},
    {"name": "Alexander", "age": 30, "math_score": 69, "science_score": 52, "english_score": 98, "social_score": 44},
    {"name": "Madge", "age": 22, "math_score": 52, "science_score": 63, "english_score": 54, "social_score": 47},
    {"name": "Trevor", "age": 23, "math_score": 89, "science_score": 88, "english_score": 69, "social_score": 93},
    {"name": "Andre", "age": 23, "math_score": 50, "science_score": 56, "english_score": 99, "social_score": 54},
    {"name": "Rodney", "age": 16, "math_score": 66, "science_score": 55, "english_score": 58, "social_score": 43},
    {"name": "Raymond", "age": 26, "math_score": 49, "science_score": 55, "english_score": 95, "social_score": 82},
    {"name": "Scott", "age": 15, "math_score": 85, "science_score": 92, "english_score": 56, "social_score": 85},
    {"name": "Jeanette", "age": 28, "math_score": 48, "science_score": 65, "english_score": 77, "social_score": 94},
    {"name": "Sallie", "age": 25, "math_score": 42, "science_score": 72, "english_score": 95, "social_score": 44},
    {"name": "Richard", "age": 21, "math_score": 71, "science_score": 95, "english_score": 61, "social_score": 59},
    {"name": "Callie", "age": 15, "math_score": 98, "science_score": 50, "english_score": 100, "social_score": 74},
]

# some code

pprint(users, width=300, sort_dicts=False)
"""
[{'name': 'Ronald', 'age': 30, 'math_score': 93, 'science_score': 65, 'english_score': 93, 'social_score': 92},
 {'name': 'Trevor', 'age': 23, 'math_score': 89, 'science_score': 88, 'english_score': 69, 'social_score': 93},
 {'name': 'Callie', 'age': 15, 'math_score': 98, 'science_score': 50, 'english_score': 100, 'social_score': 74},
 {'name': 'Sally', 'age': 29, 'math_score': 100, 'science_score': 69, 'english_score': 67, 'social_score': 82},
 {'name': 'Scott', 'age': 15, 'math_score': 85, 'science_score': 92, 'english_score': 56, 'social_score': 85},
 {'name': 'Amelia', 'age': 24, 'math_score': 88, 'science_score': 52, 'english_score': 78, 'social_score': 91},
 {'name': 'Richard', 'age': 21, 'math_score': 71, 'science_score': 95, 'english_score': 61, 'social_score': 59},
 {'name': 'Jeanette', 'age': 28, 'math_score': 48, 'science_score': 65, 'english_score': 77, 'social_score': 94},
 {'name': 'Raymond', 'age': 26, 'math_score': 49, 'science_score': 55, 'english_score': 95, 'social_score': 82},
 {'name': 'Alexander', 'age': 30, 'math_score': 69, 'science_score': 52, 'english_score': 98, 'social_score': 44},
 {'name': 'Andre', 'age': 23, 'math_score': 50, 'science_score': 56, 'english_score': 99, 'social_score': 54},
 {'name': 'Sallie', 'age': 25, 'math_score': 42, 'science_score': 72, 'english_score': 95, 'social_score': 44},
 {'name': 'Nathaniel', 'age': 28, 'math_score': 48, 'science_score': 40, 'english_score': 49, 'social_score': 91},
 {'name': 'Rodney', 'age': 16, 'math_score': 66, 'science_score': 55, 'english_score': 58, 'social_score': 43},
 {'name': 'Madge', 'age': 22, 'math_score': 52, 'science_score': 63, 'english_score': 54, 'social_score': 47}]
"""

A.

users.sort(key=lambda x: sum([x["math_score"], x["science_score"], x["english_score"], x["social_score"]]), reverse=True)

이번 주를 마치며

파이썬 기초 문법을 마무리하고 주특기인 장고를 본격적으로 배우기 시작하게된 한 주 였다. 난이도 자체가 많이 높은 것은 아니라서 안심했지만 심화과정으로 들어가면 어떤 난관이 기다리고 있을지 모르기때문에 긴장하고 있어야 한다. 그리고 알고리즘도 파이썬 문법 강화를 위해서 잠깐 뒤로 미뤘을 뿐이지 안해도 되는 것은 아니기 때문에 이것에 대한 학습시간도 따로 필요하게 될 것이다.

profile
스파르타 내일배움캠프 3기 수강생 정형빈

0개의 댓글