[코딩 공부] 2일차(2/14)

성철민·2023년 2월 13일
0

배움

목록 보기
2/42

Schedule1. 스파르타코딩클럽

내일배움캠프 5기 합류 전 기본적인 강의를 들어야 한다고 한다.

강의: [왕초보] 비개발자를 위한, 웹개발 종합반

웹개발을 위한 기본적인 강의 (HTML, CSS, JavaScript)

진도

  • 간단한 CSS 태그들을 이용해서 로그인 페이지 만들기
    - h1~h6(글씨 크기, h1은 구글 검색에 이용), div(구역 나눔), p(문단 구분), button(버튼)
    - class: 태그 명찰 ( style에서 .태그 이름 {}로 스타일 지정 가능 )
    • style: color, font-size, background, width, height, border-radius
    • style: padding ( 안쪽 위치 조정 ), margin ( 바깥쪽 위치 조정 )
  • Shift + Alt + F로 코드 탭 위치 재조정
  • 구글폰트를 이용해 페이지 폰트 바꾸기
  • 주석: Ctrl + /( HTML은 위치에 따라 주석 방법이 다르므로 단축키 기억하기 )
  • .css파일로 다른 파일을 링크해 스타일을 가져올 수 있다

감상
모호했던 css에 대해 좀 더 구체적으로 알 수 있었다


강의: [왕초보] 엑셀보다 쉬운, SQL

웹개발을 위한 기본적인 강의 (SQL)

진도

  • 어제 배운 기본 구문(SELECT, WHERE, LIKE)를 이용해서 특정 조건을 만족하는 로우 구하기
  • GROUP BY ( 동일한 범주를 갖는 데이터를 묶어서, 범주별 통계를 내줌 )
  • 통계: MIN, MAX, AVG, ROUND( , ), SUM
  • ORDER BY ( 오름차순 ASC(ascending), 내림차순 DESC(descending) )
  • 배운 절들을 전부 사용해서 쿼리문 만들기

감상
어떤 걸 보고 싶을 땐 쿼리문을 어떻게 조합해야 되는 지 봐야하므로 구문에 익숙해져야겠다


Schedule2. BAEKJOON

파이썬 문제 풀어보기

단계별로 풀어보기('7단계. 기본수학 1' 도전중)


2775번. 부녀회장이 될테야

정답

def apartment_memo(k, n, cache):
    #base case
    if k == 0:
        cache[k][n] = n + 1
        return n + 1
    elif n == 0 and k > 0:
        cache[k][n] = 1
        return 1

        
    if cache[k][n] != 0:
        return cache[k][n]
    else:
        cache[k][n] = apartment_memo(k - 1, n, cache) + apartment_memo(k, n - 1, cache)
        return cache[k][n]
    

def apartment(k, n):
    apt_cache = [[0] * (n + 1) for _ in range(k + 1)]
    apt_cache[0][0] = 1

    apartment_memo(k, n, apt_cache)

    print(apt_cache[k][n])
    

T = int(input())

for i in range(T):
    k = int(input())
    n = int(input())

    apartment(k, n - 1)
  • 기존 재귀함수 풀이에 한번 계산한 값을 저장할 수 있는 apt_cache라는 2차원 배열을 만들어 주었다. 이 Memoization을 이용하기 위해 apartment_memo라는 새로운 함수를 만들어 주었고 apartment함수를 호출하면 입력받은 k, n값에 따라 그 크기만큼의 2차원 배열을 만들어 주고 apartment_memo라는 함수를 다시 호출해 Recursion으로 정답을 도출하는 코드이다.
  • Memoization을 이용해 확실히 값을 도출하는 시간은 비약적으로 빨라졌으나 시행착오 끝에 완성한 코드라 주석도 없고 시각적으로 난해하다. 그리고 더 획기적인 코드가 있을 것이라 생각한다.
  • 예를 들어 문제에서 n은 1호 이상의 값인데 내가 만든 apt_cache는 0부터 시작하므로 이걸 어떻게 적용해야 할 지 조금 난감했다. 그래서 n을 입력받고 apartment함수에 n-1을 매개변수로 집어넣는 방식으로 해결했다.

ChatGPT 코드

def people_num(k, n):
    # 0층부터 n호까지의 사람 수를 먼저 계산한다
    people = [i for i in range(n+1)]
    # k층까지 각 호수별 사람 수를 누적해서 더한다
    for i in range(1, k+1):
        for j in range(1, n+1):
            people[j] += people[j-1]
    return people[n]

# 입력 예시에 대한 출력
print(people_num(1, 3)) # 6
print(people_num(2, 3)) # 10

챗GPT는 위 문제를 짧은 코드로 풀었다

  • 0층의 사람 수 people 리스트를 1, 2, 3, 4, 5, ..., n로 먼저 초기화 해준 뒤에, 다음 층 people[j]는 아래층 people[j]와 전 호수 people[j-1]의 합과 같다는 점을 이용했다.
  • 예를 들어 k = 1, n = 3이라면 people = [1, 2, 3]으로 시작해 people = [1, 3(1+2), 6(3+3)], people = [1, 4(1+3), 10(4+6)]이 된다.
  • 컴퓨터가 이해할 수 있는 규칙으로 단순화시키는 방법을 좀 더 고민해 봐야겠다.

2839번. 설탕 배달

개요: 3kg, 5kg 설탕봉지로 조합해 주어진 Nkg을 가장 적은 수의 봉지로 배달하는 방법을 구하는 문제

초기 구상: 5kg 설탕봉지로 딱 나누어 떨어질 때가 가장 이상적이므로 먼저 5로 나누어 떨어지는지 확인 후에 나누어 떨어지지 않으면 5kg 봉지 개수를 하나씩 줄이고 3kg봉지를 늘려 최적의 수를 찾도록 구상

정답

N = int(input())

a = N

if N % 5 == 0:
    print(N // 5)
else:
    for five in range(N // 5, -1, -1):
        for three in range(1, N // 3 + 1):
            if N == 5 * five + 3 * three:
                a = min(a, five + three)
    if a != N:
        print(a)
    else:
        print(-1)

정답은 도출했지만 min() 등을 쓰지 않고 중첩 for을 쓰지 않는 더 최적화된 방법이 있을 것 같다.

ChatGPT 코드

n = int(input())

# 5킬로그램 봉지를 최대한 많이 사용하기 위해, 5로 나누어 떨어질 때까지 5킬로그램 봉지 사용
quotient, remainder = divmod(n, 5)
if remainder == 0:
    print(quotient)
else:
    # 5킬로그램 봉지로 나누어 떨어지지 않는 경우, 3킬로그램 봉지로 나누어줌
    for i in range(quotient, -1, -1):
        j = (n - 5*i) // 3
        if 5*i + 3*j == n:
            print(i+j)
            break
    else:
        print(-1)

챗GPT 코드는 for문을 하나로 구성하여 O(n)의 시간복잡도로 최적화되어있다.

  • 챗GPT도 마찬가지로 divmod()함수(n을 5로 나누어 나머지튜플로 리턴)를 이용해 5로 나누어 나머지가 0이면 몫을 바로 정답으로 하는 코드를 구성했다.
  • 5kg 봉지를 하나씩 줄여갈 때 for문을 사용하고 5kg 봉지로 최대한 봉지 수를 구성하고 남은 값을 3으로 나눈 몫을 j에 저장했다. 그리고 5 * i + 3 * jn이 되었을 때 i+j를 출력하고 반복문을 중단시키는 코드로 최적화시켰다.
  • 중첩 for문을 줄일 수 있는 방안을 항상 생각해야겠다.

10757번. 큰수 A+B

개요: 주로 사용되는 낮은 정수가 아니라 91283041284121 등 아주 큰 수를 더하는 문제

초기 구상: 파이썬에서는 변수 자료형에 따른 메모리의 제한이 없기 때문에 크게 문제가 없을 거라고 생각했다.

정답

import sys

A, B= map(int, input().split())
print(A + B)

역시나 파이썬에서는 자료형에 크게 구애 받지 않아 간단한 코드로 작성이 가능했다.
만약 C나 perl같은 언어에서는 저렇게 큰 자료형이 없기 때문에 문자열로 받아 따로따로 처리해야 할 것으로 보인다.

ChapGPT 코드

#include <iostream>
#include <string>

using namespace std;

int main() {
    string a, b;
    cin >> a >> b;

    string result = ""; // 결과를 저장할 문자열 변수
    int carry = 0; // 자리 올림 수
    int sum = 0; // 각 자리별 합

    // 덧셈 연산
    for (int i = 1; i <= max(a.length(), b.length()); i++) {
        sum = carry; // 이전 자리에서의 자리올림을 더함
        if (i <= a.length()) sum += a[a.length()-i] - '0'; // a의 해당 자리수 값 더함
        if (i <= b.length()) sum += b[b.length()-i] - '0'; // b의 해당 자리수 값 더함

        carry = sum / 10; // 자리 올림 계산
        result = to_string(sum % 10) + result; // 해당 자리의 결과 값 저장
    }

    if (carry) result = to_string(carry) + result; // 마지막 자리 올림이 있으면 결과 문자열의 가장 앞에 추가

    cout << result << endl; // 결과 출력

    return 0;
}

챗GPT에게 C언어로 코딩을 부탁했다.

  • 예상대로 a, b을 문자열로 받은 뒤에 max(a.length(), b.length())로 둘 중 더 큰 수 자리수 만큼 반복문을 돌며 각 자리수의 합을 구한다.
  • 합이 10이 넘는다면 자리올림을 다음을 위해 저장해 두고 나머지를 이용해 해당 자리에 결과값을 저장한다.
  • 파이썬이 아니라 다른 언어였다면 위와 같은 사항들을 고려했을 것이다.

1978번. 소수 찾기

개요: 주어진 수 N개 중에서 소수가 몇 개인지 찾아서 출력하는 문제

초기 구상: 리스트로 받은 값을 반복문으로 하나씩 가져오고 그 수를 또 다시 반복문으로 나눠가면서 나머지가 0이 되면 리스트에서 제거하는 방식을 구상했으나 더 복잡해졌다

정답

N = int(input())

number_list = list(map(int, input().split()))

count = 0

for i in number_list:
    check = 0
    if i == 1:
        check = 1    
    for j in range(2, i // 2 + 1):
        if i % j == 0:
            check = 1
    
    if check == 0:
        count += 1

print(count)
  • number_list를 넘겨 받은 뒤에 for문으로 하나씩 호출하고 또 다시 2 ~ i // 2 + 1까지의 수로 나눠서 나머지가 0이 되면 check에 1을 넣었다.
  • 전체를 빠져나온 뒤에 check가 여전히 0일 경우 count에 1을 더해줘서 소수를 구하는 방식이다.
  • N 리스트의 element가 무지 클 경우 위 방식은 너무 시간이 오래 걸린다.

ChatGPT 코드

# 소수 판별 함수
def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

# 입력 받기
n = int(input())
numbers = list(map(int, input().split()))

# 소수 개수 구하기
count = 0
for num in numbers:
    if is_prime(num):
        count += 1

# 결과 출력
print(count)
  • 챗GPT 역시 거의 비슷한 방식으로 답을 구했으나 최적화를 위해 i // 2 + 1이 아닌 int(i ** 0.5)로 시간을 더 줄였다.
  • 제곱근을 쓴 이유는 어떤 요소 na, b의 곱 a * b로 나타낼 수 있는데 a, b 중 적어도 하나는 n의 제곱근보다 작거나 같아야 하기 때문이다
  • 둘 다 n의 제곱근보다 크면 a * bn보다 큰 값이 되어버린다.
  • 따라서 2부터 int(i ** 0.5)까지만 나누어 줘도 소수 판별이 가능하다.

Schedule3. Codeit(컴퓨터 과학 전공 과정)

코드잇 코딩 공부 과정

[Python] 객체 지향 프로그래밍의 4개의 기둥

Chapter3. 상속

4. 상속Ⅰ(부모로부터 물려받기)

  • class와 class사이에 부모-자식 관계 설정 가능 (상속)
class 자식클래스(부모클래스):
	내용
  • 상속을 하면 자식 클래스가 부모 클래스의 변수메소드를 그대로 물려 받음
  • help(클래스) 함수로 상속 관계나 메소드 등을 알 수 있음
  • 특히 Method resolution order:로부터 해당 인스턴스의 클래스가 어떤 부모 클래스를 가지는지 보여줌
  • 모든 클래스는 builtins.object를 부모 클래스로 가짐

5. 상속과 관련된 메소드와 함수들

  • print(클래스.mro())mro() 메소드를 호출하면 해당 클래스가 상속하는 부모 클래스를 볼 수 있음
  • print(isinstance(검사할 인스턴스, 기준 클래스))isinstance()함수를 사용하면 검사할 인스턴스가 기준 클래스의 인스턴스인지 불린 값으로 리턴함
  • print(issubclass(검사할 클래스, 기준이 되는 부모 클래스))issubclass()를 사용하면 검사할 클래스가 부모 클래스의 자식 클래스인지 불린 값으로 리턴함

6. 상속Ⅱ(오버라이딩)

  • 오버라이딩(overridding) : 부모로부터 물려받은 내용을 자식 클래스에 맞게 덮어 씌우는 것
  • 오버라이딩 방법
    1. 자식 클래스에 같은 이름의 부모 클래스 내용 붙여넣고 밑에 다른 내용 적기
    2. 부모 클래스.해당 메서드(파라미터)로 부모 클래스 내용 붙여넣고 밑에 다른 내용 적기
    3. 부모 클래스를 super()함수로 대체, super().해당 메서드(파라미터)로 사용 (이 경우 파라미터에 self 파라미터를 넘겨줄 필요가 없음)
  • 변수 오버라이딩 방법 : 자식 클래스에서 같은 이름의 변수를 수정해주면 된다.

7. 상속Ⅲ(mro)

  • mro(method resolution order, 메소드 탐색 순서)
  • 메소드 검색 방향: 자식 -> 부모
  • 자식과 부모 클래스가 각각 같은 이름의 메소드가 있더라도 자식부터 검색되기 때문에 오버라이딩이 가능하다.

8. 상속Ⅳ(기능 추가하기)

  • 이제 자식 클래스에 기능 추가는 기존대로 하면 된다.

9. 상속 정리

  • 위의 내용 정리

12. 다중 상속

  • 상속할 때 부모 클래스를 2개 이상 설정하면 다중 상속이 가능하다.
class 자식클래스(부모클래스1, 부모클래스2, ...):
	내용
  • 다만 __init__ 메소드 등을 설정할 때 super() 함수로는 어떤 부모 클래스의 __init__메소드를 가져와야 할 지 알 수 없으므로 직접 부모 메소드의 이름으로 메소드를 가져와야 한다.

13. 다중 상속의 위험성

  • 다중 상속으로 2개 이상의 부모 클래스를 상속받았을 때 두 부모 클래스에 함께 있는 메소드를 호출하게 되면 어떤 부모 클래스의 메소드를 호출할 지 알 수 없다.
  • mro()변수로 호출하면 그 순서를 알 수 있으며, 상속 시의 순서에 따라 순서가 바뀌기도 한다.
  • python에서는 다중 상속이 가능하지만 java에서는 무조건 한 개의 상속만 가능하다.
  • 해결방법 :
    1. 부모 클래스끼리 같은 이름의 메소드를 갖지 않도록 하기
    2. 같은 이름의 메소드는 자식클래스에서 오버라이딩 해버리기

감상
python의 Class 상속에 관해서 배울 수 있었다. 큰 단위의 프로젝트를 할 때 Class단위 사용을 많이 할텐데 사용법에 익숙해지고 눈에 익을 수 있도록 자주 봐야겠다.

profile
developer

0개의 댓글