41일차

Suhyeon Lee·2024년 11월 27일

CodeKata

SQL

124. Group Sold Products By The Date

  • 작성한 쿼리
SELECT
  sell_date
  , COUNT(DISTINCT product) AS num_sold
  , GROUP_CONCAT(DISTINCT product ORDER BY product) AS products
FROM
  Activities
GROUP BY
  sell_date
ORDER BY
  sell_date
;

→ runtime, beats가 너무 낮길래 다른 방식으로도 풀어봄

WITH cte AS (
  SELECT
    DISTINCT sell_date
    , product
  FROM
    Activities
)
SELECT
  sell_date
  , COUNT(*) AS num_sold
  , GROUP_CONCAT(product ORDER BY product) AS products
FROM
  cte
GROUP BY
  sell_date
ORDER BY
  sell_date
;

참고할 만한 다른 풀이

SELECT sell_date,
       count(DISTINCT product) AS num_sold,
       group_concat(DISTINCT product ORDER BY product ASC SEPARATOR ',') products
  FROM activities
 GROUP BY sell_date
 ORDER BY sell_date;

125. List the Products Ordered in a Period

  • 작성한 쿼리
WITH cte AS (
  SELECT
    product_id
    , SUM(unit) AS unit
  FROM
    Orders
  WHERE
    DATE_FORMAT(order_date, '%Y%m') = '202002'
  GROUP BY
    product_id
  HAVING
    SUM(unit) >= 100
)
SELECT
  product_name
  , unit
FROM
  Products
  JOIN cte
  USING(product_id)
;

참고할 만한 다른 풀이

select 
  product_name
  , sum(unit) as unit
from 
  Products P 
  left join Orders O
  on P.product_id = O.product_id
where
  order_date between '2020-02-01' and '2020-02-29'
group by
  product_name
having unit >= 100
SELECT
  p.product_name
  , sum(o.unit) as unit
FROM 
  Products as p
  inner join Orders as o 
  ON p.product_id = o.product_id
WHERE 
  MONTH(o.order_date)=2 AND YEAR(o.order_date)=2020
GROUP BY 
  o.product_id 
HAVING 
  unit>=100
with sel as (select product_id, order_date, sum(unit) as total
from Orders
where DATE_FORMAT(order_date, '%Y-%m') = '2020-02'
group by product_id)
select p.product_name, s.total as unit
from sel s left join Products p on s.product_id = p.product_id
where s.total >= 100

Python

52. 콜라 문제

  • 작성한 코드
def solution(a, b, n):
    answer = 0
    while n >= a:
        get_coke = n//a*b
        left_coke = n%a
        
        answer += get_coke
        n = left_coke + get_coke
    return answer

참고할 만한 다른 풀이

def solution(a, b, n):
    answer = 0
    # 1. 빈 병의 개수 n이 교환 가능한 최소 숫자 a 이상일 때까지 반복
    while n >= a:
        # 2. b개의 병 추가
        answer += b
        # 3. 남은 병 계산하기
        n = n - a + b
    return answer
import math
def solution(give, take, init):
    return math.ceil((init - give + 1) / (give - take)) * take
  • (init - give + 1) / (give - take)

    • 처음 병 수에서 몇 번을 반복해야 하는지 횟수를 구하기 위함
      • 처음 병 수가 9이고 3병을 주고 1병을 받는다면 결국 2병을 주는 것이고 0병이 남을 때까지 반복하려면 5번을 반복해야 함: init / (give - take)

        9-(3-1)=7
        7-(3-1)=5
        5-(3-1)=3
        3-(3-1)=1
        1-(3-1)=-1
        # 총 5번을 한 번에 계산하려면
        init / (give - take)
        9/(3-1)=4.5
      • 그러나 프로그래머스의 조건은 주는 병 수보다 적게 남는 건 인정하지 않으므로 처음 병 수에서 주는 개수를 빼고 다시 1을 더함(남은 개수가 주는 개수와 같은 경우도 포함해야 하므로 1을 더해야 한다)

        9-(3-1)=7
        7-(3-1)=5
        5-(3-1)=3
        3-(3-1)=1
        # 1-(3-1)=-1은 제외됨 
        
        # 총 4번을 한 번에 계산하려면
        (init - give + 1) / (give - take)
        (9-3+1)/(3-1)=3.5
      • 여기서 3.5는 4로 인정해야 함: 마지막의 3을 인정하기 위해 1을 더한 것이며, 그 1을 나눈 결과가 0.5이기 때문

  • math.ceil((init - give + 1) / (give - take))

    • 나머지를 횟수로 인정하기 위해 무조건 올림
  • 총 몇 병을 받는지 출력해야 하므로 위에서 구한 횟수에 받는 개수 take를 곱함

여기서 횟수를 한꺼번에 계산하고 최종적으로 받는 개수를 곱한다는 사고방식으로 전환하는 게 어려움.(남은 병을 다시 합치는 조건 때문.)
그렇지만 주고 받는 차이를 생각하면 줄어드는 양은 일정하기 때문에 나누기가 가능.
어디까지 나누라는 조건은 그만큼 미리 빼면 되므로 여전히 나누기 가능.

solution = lambda a, b, n: max(n - b, 0) // (a - b) * b

→ 한꺼번에 계산하지 않고 a개만 팔고 b개를 받는 과정은 결국 a-b 개씩 병을 소비하는 것으로 생각, 첫번째 진행할 때는 a개만 소비되기 때문에, b만큼 못받음(-b), 그 조건을 먼저 계산 n-b 반복횟수는 n-b // (a-b) 여기에 받는 병수 b 곱한 것

  • 이해하기 쉽게 변경해보자

solution = lambda a, b, n: max(n - b, 0) // (a - b) * b

🡇

def solution(give, take, init):
    # max 불필요
    return max(init - take, 0) // (give - take) * take
  • 프로그래머스 문제 조건에 init은 항상 take보다 크므로 init - take가 0보다 작을 수 없음.
    • // 연산자는 몫만 구하는 기능
      → math.floor 함수로 변경 가능

🡇

import math
def solution(give, take, init):
    return math.floor((init - take) / (give - take)) * take

🡇

import math
def solution(give, take, init):
    return math.floor((init - give + (give - take)) / (give - take)) * take
  • 처음 병수에서 주는 병수를 뺀 것이 기준 병수
  • 거기서 차이(give - take)만큼 꽉 차게 더했기 때문에 더 많은 값이 나올 때를 대비해 버림

아티클 스터디

비개발자를 위한 엑셀로 이해하는 SQL

머신 러닝 특강

회귀 분석
실습

회고

  • 서울에는 눈이 왔다고 한다.
    (여긴 비랑 우박이 왔음)
  • 머신 러닝 알고리즘을 쓰는 법은 이제 조금 알 것 같은데 이걸 해석하고 검증하는 법은 아직도 잘 모르겠고 막막하다…
    • 검정 방법 위주로 다시 복습해봐야지
profile
2 B R 0 2 B

0개의 댓글