728x90
반응형

문제 1 - 자동차 대여 기록에서 장기/단기 대여 구분하기

1. 문제 

https://school.programmers.co.kr/learn/courses/30/lessons/151138

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

  • DATEDIFF () : 두개의 날짜값의 차이를 int로 반환하는 내장함수이다.
  • 마자막 날짜에서 시작 날짜의 차이를 구하면 하루를 포함하지 않는 값이 나오므로 +1 해줘야 한다.
SELECT HISTORY_ID
        , CAR_ID
        , DATE_FORMAT(START_DATE, "%Y-%m-%d") AS START_DATE
        , DATE_FORMAT(END_DATE, "%Y-%m-%d") AS END_DATE
        , (CASE 
            WHEN (DATEDIFF(END_DATE, START_DATE) + 1) >= 30 THEN "장기 대여"
            ELSE "단기 대여"
            END) as RENT_TYPE
from CAR_RENTAL_COMPANY_RENTAL_HISTORY
where START_DATE like '2022-09%'
order by HISTORY_ID desc

 

문제 2 - 특정 옵션이 포함된 자동차 리스트 구하기

1. 문제 

https://school.programmers.co.kr/learn/courses/30/lessons/157343

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT CAR_ID, CAR_TYPE, DAILY_FEE, OPTIONS
from CAR_RENTAL_COMPANY_CAR
where OPTIONS LIKE '%네비게이션%'
order by CAR_ID DESC

 

문제 3 - 과일로 만든 아이스크림 고르기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/133025

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT A.FLAVOR
FROM FIRST_HALF A, ICECREAM_INFO B
WHERE (A.FLAVOR = B.FLAVOR 
       AND B.INGREDIENT_TYPE = "fruit_based"
 AND A.TOTAL_ORDER > 3000)
ORDER BY A.TOTAL_ORDER DESC

 

문제 4 - 인기있는 아이스크림

1. 문제 

https://school.programmers.co.kr/learn/courses/30/lessons/133024

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT FLAVOR
FROM FIRST_HALF
ORDER BY TOTAL_ORDER DESC, SHIPMENT_ID

 

문제 5 - 흉부외과 또는 일반외과 의사 목록 출력하기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/132203

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT DR_NAME
        , DR_ID
        , MCDP_CD
        , DATE_FORMAT(HIRE_YMD, '%Y-%m-%d') AS HIRE_YMD
FROM DOCTOR
where MCDP_CD IN ("CS", "GS")
order by HIRE_YMD desc, DR_NAME

 

문제 6 - 12세 이하인 여자 환자 목록 출력하기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/132201

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT PT_NAME,	PT_NO, GEND_CD,	AGE, IFNULL(TLNO, "NONE") AS TLNO
FROM PATIENT
WHERE GEND_CD = "W"
    AND AGE <= 12
ORDER BY AGE DESC, PT_NAME

 

문제 7 - 가장 비싼 상품 구하기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/131697

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT MAX(PRICE) AS MAX_PRICE
FROM PRODUCT

 

문제 8 - 조건에 맞는 회원수 구하기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/131697

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT COUNT(USER_ID) AS USERS
FROM USER_INFO
WHERE JOINED LIKE "2021%"
    AND AGE BETWEEN 20 AND 29

 

문제 9 - 나이 정보가 없는 회원 수 구하기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/131528

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT COUNT(USER_ID) AS USERS
FROM USER_INFO
WHERE AGE IS NULL

 

문제 10 - 경기도에 위치한 식품창고 목록 출력하기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/131114

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT WAREHOUSE_ID, WAREHOUSE_NAME, ADDRESS, IFNULL(FREEZER_YN, "N")
FROM FOOD_WAREHOUSE
WHERE ADDRESS LIKE "경기도%"
ORDER BY  WAREHOUSE_ID

 

문제 11 - 강원도에 위치한 생산공장 목록 출력하기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/131112

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT FACTORY_ID, FACTORY_NAME, ADDRESS
FROM FOOD_FACTORY
WHERE ADDRESS LIKE "강원도%"
ORDER BY FACTORY_ID

 

문제 12 - 경기도에 위치한 식품창고 목록 출력하기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/59415

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT MAX(DATETIME) AS 시간
FROM ANIMAL_INS

 

문제 13 - 이름이 있는 동물의 아이디

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/59407

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT ANIMAL_ID
FROM ANIMAL_INS
WHERE NAME IS NOT NULL
ORDER BY ANIMAL_ID

 

문제 14 - 상위 n개 레코드

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/59405

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

  • MySQL에서 상위 N개의 데이터를 출력하기 위해선 LIMIT N 함수를 사용한다.
  • ORACLE : ROWNUM < N
  • MS - SQL : TOP N, TOP N WITH TIES 
SELECT NAME
FROM ANIMAL_INS
ORDER BY DATETIME
LIMIT 1

 

문제 15 - 여러 기준으로 정렬하기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/59404

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT ANIMAL_ID, NAME, DATETIME
FROM ANIMAL_INS
ORDER BY NAME, DATETIME DESC

 

문제 16 - 동물의 아이디와 이름

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/59403

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
ORDER BY ANIMAL_ID

 

문제 17- 이름이 없는 동물의 아이디

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/59039

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT ANIMAL_ID
FROM ANIMAL_INS
WHERE NAME IS NULL
ORDER BY ANIMAL_ID

 

문제 18 - 어린 동물 찾기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/59037#fn1

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
WHERE INTAKE_CONDITION != "Aged"
ORDER BY ANIMAL_ID

 

문제 19 - 아픈 동물 찾기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/59036

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT ANIMAL_ID, NAME
from ANIMAL_INS
where INTAKE_CONDITION = "Sick"
order by ANIMAL_ID

 

문제 20 - 역순 정렬하기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/59035

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT NAME, DATETIME
FROM ANIMAL_INS
ORDER BY ANIMAL_ID DESC

 

문제 21 - 모든 레코드 조회하기

1. 문제

https://school.programmers.co.kr/learn/courses/30/lessons/59034

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

2. 작성한 코드

SELECT ANIMAL_ID
        , ANIMAL_TYPE
        , DATETIME
        , INTAKE_CONDITION
        , NAME
        , SEX_UPON_INTAKE
FROM ANIMAL_INS
ORDER BY ANIMAL_ID
728x90
반응형
728x90
반응형

📝 문제

더보기

1. 문제 설명

 코니는 영어 단어가 적힌 카드 뭉치 두 개를 선물로 받았습니다. 코니는 다음과 같은 규칙으로 카드에 적힌 단어들을 사용해 원하는 순서의 단어 배열을 만들 수 있는지 알고 싶습니다.

  • 원하는 카드 뭉치에서 카드를 순서대로 한 장씩 사용합니다.
  • 한 번 사용한 카드는 다시 사용할 수 없습니다.
  • 카드를 사용하지 않고 다음 카드로 넘어갈 수 없습니다.
  • 기존에 주어진 카드 뭉치의 단어 순서는 바꿀 수 없습니다.

예를 들어 첫 번째 카드 뭉치에 순서대로 ["i", "drink", "water"], 두 번째 카드 뭉치에 순서대로 ["want", "to"]가 적혀있을 때 ["i", "want", "to", "drink", "water"] 순서의 단어 배열을 만들려고 한다면 첫 번째 카드 뭉치에서 "i"를 사용한 후 두 번째 카드 뭉치에서 "want"와 "to"를 사용하고 첫 번째 카드뭉치에 "drink"와 "water"를 차례대로 사용하면 원하는 순서의 단어 배열을 만들 수 있습니다.

문자열로 이루어진 배열 cards1, cards2와 원하는 단어 배열 goal이 매개변수로 주어질 때, cards1과 cards2에 적힌 단어들로 goal를 만들 있다면 "Yes"를, 만들 수 없다면 "No"를 return하는 solution 함수를 완성해주세요.


2. 제한사항

  • 1 ≤ cards1의 길이, cards2의 길이 ≤ 10
    • 1 ≤ cards1[i]의 길이, cards2[i]의 길이 ≤ 10
    • cards1과 cards2에는 서로 다른 단어만 존재합니다.
  • 2 ≤ goal의 길이 ≤ cards1의 길이 + cards2의 길이
    • 1 ≤ goal[i]의 길이 ≤ 10
    • goal의 원소는 cards1과 cards2의 원소들로만 이루어져 있습니다.
  • cards1cards2goal의 문자열들은 모두 알파벳 소문자로만 이루어져 있습니다.

3. 입출력 예

cards1 cards2 goal result
["i", "drink", "water"] ["want", "to"] ["i", "want", "to", "drink", "water"] "Yes"
["i", "water", "drink"] ["want", "to"] ["i", "want", "to", "drink", "water"] "No"

 


4. 입출력 예 설명

  • 입출력 예 #1
     본문과 같습니다.
  • 입출력 예 #2
     cards1에서 "i"를 사용하고 cards2에서 "want"와 "to"를 사용하여 "i want to"까지는 만들 수 있지만 "water"가 "drink"보다 먼저 사용되어야 하기 때문에 해당 문장을 완성시킬 수 없습니다. 따라서 "No"를 반환합니다.

📝 작성한 코드

 처음엔 HaspMap을 써보려다 실패하고 작성한 코드인데, 다른 분들이 작성한 걸 보니 HashMap을 써서 푸신 분이 꽤나 있었다. 이 외에도 Queue(큐)라는 클래스를 사용하신 분들이 많았다. 큐는 선입선출법의 성격을 지닌 자료구조라고 한다. 문제의 조건에서 카드 뭉치를 순서대로 한장 씩 사용한다고 했으므로, 큐의 성격을 이용하여 문제를 풀어보면 좋을 것 같다.
 
 내가 작성한 코드는 간단히 for문을 돌려 진행되는 코드이다. 처음에는 goal[i]와 cards[i]를 비교해보면 된다고 생각했는데, 인덱스범위 오류가 나는 걸 보고 cards의 길이는 goal의 길이보다 작다는 것을 깨달았다. 그래서 cards의 인덱스 값을 따로 변수 (card1Index)로 주고 cards1[card1Index]이 goal에 들어있는 값과 일치하면 그 인덱스에 해당하는 cards의 값은 다시 사용할 수 없도록 +1을 해주었다. 그리고 answer의 초기값을 Yes로 설정해두고 if문의 조건1과 2가 제대로 실행되않으면 No를 반환하도록 하였다.
 

class Solution {
    public String solution(String[] cards1, String[] cards2, String[] goal) {
        String answer = "Yes";
        int card1Index = 0;
        int card2Index = 0;
 
        for (int i = 0; i < goal.length; i++) {
            if (card1Index < cards1.length && cards1[card1Index].equals(goal[i])){
                card1Index++;
            }
            else if(card2Index < cards2.length && cards2[card2Index].equals(goal[i])){
                card2Index++;
            }
            else {
                answer = "No";
            }
        }    
                 
        return answer;
    }
}

 

📝 공부해 볼 코드

Queue(큐)를 사용한 코드.
큐는 데이터를 일시적으로 쌓아두기 위한 자료구조로 스택과는 다르게 FIFO(First In First Out)의 형태를 가진다. FIFO 형태는 뜻 그대로 먼저 들어온 데이터가 가장 먼저 나가는 선입선출을 의미한다.
 
<코드 설명>

  1. Queue<String> queue1 및 Queue<String> queue2를 생성하고, 각각 cards1 및 cards2 배열을 큐로 변환하여 초기화
  2. for (String g : goal) 루프를 통해 목표 배열을 순회한다. 루프 내에서는 peek()라는 메서드를 통해 현재 목표 g가 queue1 또는 queue2의 맨 앞에 있는 카드와 일치하는지 확인한다.
  3. * queue.peek(); // queue의 첫번째 값 참조
  4. 만약 g가 queue1의 맨 앞에 있는 카드와 일치한다면, queue1.poll()를 사용하여 큐에서 해당 카드를 제거한다. 이어서 continue 키워드를 사용하여 다음 목표로 이동한다.
  5. * queue.poll(); // queue에 첫번째 값을 반환하고 제거 비어있다면 null
  6. 만약 g가 queue2의 맨 앞에 있는 카드와 일치한다면, queue2.poll()를 사용하여 큐에서 해당 카드를 제거한다. 이어서 continue 키워드를 사용하여 다음 목표로 이동한다.
  7. 만약 g가 어느 큐에도 일치하지 않는다면, "No"를 반환하며 프로그램을 종료시킨다
  8. 모든 목표를 순회한다면, "Yes"를 반환한다.
import java.util.*;

class Solution {
    public String solution(String[] cards1, String[] cards2, String[] goal) {
        String answer = "";

        Queue<String> queue1 = new LinkedList<>(Arrays.asList(cards1));
        Queue<String> queue2 = new LinkedList<>(Arrays.asList(cards2));

        for (String g : goal) {
            if (g.equals(queue1.peek())) {
                queue1.poll();
                continue;
            } else if (g.equals(queue2.peek())) {
                queue2.poll();
                continue;
            }
            return "No";
        }

        return "Yes";
    }
}

 

Queue(큐) 참고 주소
https://coding-factory.tistory.com/602

728x90
반응형
728x90
반응형

📝문제

더보기

1. 문제 설명

과일 장수가 사과 상자를 포장하고 있습니다. 사과는 상태에 따라 1점부터 k점까지의 점수로 분류하며, k점이 최상품의 사과이고 1점이 최하품의 사과입니다. 사과 한 상자의 가격은 다음과 같이 결정됩니다.

  • 한 상자에 사과를 m개씩 담아 포장합니다.
  • 상자에 담긴 사과 중 가장 낮은 점수가 p (1 ≤ p ≤ k)점인 경우, 사과 한 상자의 가격은 p * m 입니다.

과일 장수가 가능한 많은 사과를 팔았을 때, 얻을 수 있는 최대 이익을 계산하고자 합니다.(사과는 상자 단위로만 판매하며, 남는 사과는 버립니다)

예를 들어, k = 3, m = 4, 사과 7개의 점수가 [1, 2, 3, 1, 2, 3, 1]이라면, 다음과 같이 [2, 3, 2, 3]으로 구성된 사과 상자 1개를 만들어 판매하여 최대 이익을 얻을 수 있습니다.

  • (최저 사과 점수) x (한 상자에 담긴 사과 개수) x (상자의 개수) = 2 x 4 x 1 = 8

사과의 최대 점수 k, 한 상자에 들어가는 사과의 수 m, 사과들의 점수 score가 주어졌을 때, 과일 장수가 얻을 수 있는 최대 이익을 return하는 solution 함수를 완성해주세요.

제한사항

  • 3 ≤ k ≤ 9
  • 3 ≤ m ≤ 10
  • 7 ≤ score의 길이 ≤ 1,000,000
    • 1 ≤ score[i] ≤ k
  • 이익이 발생하지 않는 경우에는 0을 return 해주세요.

2. 입출력 예

k m score result
3 4 [1, 2, 3, 1, 2, 3, 1] 8
4 3 [4, 1, 2, 2, 4, 4, 4, 4, 1, 2, 4, 2] 33

3. 입출력 예 설명

  • 입출력 예 #1
    문제의 예시와 같습니다.

  • 입출력 예 #2
    다음과 같이 사과 상자를 포장하여 모두 팔면 최대 이익을 낼 수 있습니다.
사과 상자가격
[1, 1, 2] 1 x 3 = 3
[2, 2, 2] 2 x 3 = 6
[4, 4, 4] 4 x 3 = 12
[4, 4, 4] 4 x 3 = 12

따라서 (1 x 3 x 1) + (2 x 3 x 1) + (4 x 3 x 2) = 33을 return합니다.

📝작성한 코드

1. 처음 작성한 코드

 과일장수가 최대의 이익을 얻기 위해선 m만큼 과일을 담을 때 담아지는 과일의 수가 딱 떨어지지 않아 1상자를 완성하지 못하고 남아버릴 경우 남아진 과일은 점수가 낮은 과일이여야 하므로 가장 점수가 높은 과일부터  담아져야 한다. 가격을 계산 할 때는 한 상자에 같은 점수의 과일이 담아져 있지 않은 경우 그 상자에서 가장 점수가 낮은 과일을 기준으로 가격을 계산해야 한다. 그렇기 때문에 점수를 오름차순으로 정렬하여 가장 첫번째 과일의 점수로 1상자의 가격을 계산해야 한다.

  • Arrays.sort(score) : score에서 큰 수 부터 차례대로 뽑아오기 위해 오름차순으로 정렬하였다.
  • for문 : score의 값들을 차례대로 뽑아오면서 계산을 하기 위해 for문을 작성했다. k = 4, m = 3, score = [4, 1, 2, 2, 4, 4, 4, 4, 1, 2, 4, 2] 라고 생각해보면 i의 처음 값은 -3이며 이 값은  -score.length보다 크거나 같으므로 -12보다 작아 질 수 없다. for문이 돌아가면 score[-3]인 4가 m인 3과 곱해지고 12라는 값이 answer에 들어간다. for문이 실행됐으니까 i -= m 이 실행 되면서 i는 -6이 된다.

하지만 실행하면 ArrayIndexOutOfBoundsException 오류가 떴다. 이 오류는 배열 인덱스가 배열 길이를 벗어나는 경우에 발생한다. 오류 메시지에서 "Index -3 out of bounds for length 12"가 나오는데, 이는 배열의 길이가 12이고 인덱스 -3에 접근하려고 하고 있다는 것을 의미한다. 

 즉, 자바에서 배열의 인덱스에 접근할 때 음수 사용이 불가능 하다는 것이다. 배열 인덱스는 음이 아닌 정수여야 한다. 그러나 나는  for문에서 i를 -m으로 주면서 score[-3]라는 코드가 나왔기 때문에 오류가 났던 것이다.

import java.util.*;

class Solution {
    public int solution(int k, int m, int[] score) {
        int answer = 0;
        Arrays.sort(score); 
        // System.out.println(Arrays.toString(score));   
        	// [1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4]
       
        for (int i = -m; i >= -score.length; i -= m){           
             answer += score[i] * m ;
        }
        
        return answer;
    }
}

 

2. 수정한 코드

 수정한 코드에서는 i를  score.length로 주었다. k = 4, m = 3, score =[4, 1, 2, 2, 4, 4, 4, 4, 1, 2, 4, 2]라고 생각해보면 i의 초기값은 12이고 i >= m만큼 반복 하므로 i는 3보다 크거나 같을 때까지 반복한다. for문이 실행되면 score[9] 인 4에 m인 3이 곱해져  12라는 값이 answer에 들어간다. for문이 실행됐으니까 i -= m 이 실행 되면서 i는 9가 된다.

 이렇게 조건을 주면 배열의 인덱스에 음수를 넣지 않고도 원하는 값을 가져올 수 있다.

import java.util.*;

class Solution {
    public int solution(int k, int m, int[] score) {
        int answer = 0;
        Arrays.sort(score); 
        // System.out.println(Arrays.toString(score));   
        	// [1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4]

        for(int i = score.length; i >= m; i -= m){
             answer += score[i - m] * m;
        }
 
        return answer;
    }
}

728x90
반응형
728x90
반응형

데이터 전처리 시각화

🐳 데이터 불러오기

### 라이브러리 정의하기
import pandas as pd

### 사용할 데이터 읽어오기
# 데이터프레임 변수명 : df_bus_card_tot
file_path = "./01_data/all/df_bus_card_tot.csv"
df_bus_card_tot = pd.read_csv(file_path)

print("갯수 : ", len(df_bus_card_tot))
df_bus_card_tot.head(1)

 

 

데이터 시각화

시각화의 목적?
직관적인 데이터 확인

 

🐳 시각화에 필요한 라이브러리

### 시각화 라이브러리
import matplotlib # 시각화 라이브러리를 쓰겠다!
import matplotlib.pyplot as plt # 차트나 그림이 들어있다
import seaborn as sns # 파스텔 색감

### 그래프 내에 한글이 포함된 경우 폰트 처리가 필요하다
# - 한글 꺠짐 방지를 위한 라이브러리
### 폰트 환결설정 라이브러리
from matplotlib import font_manager, rc

### 운영체제 확인을 위한 라이브러리
# import platform

plt.rc("font", family = "Malgun Gothic")

### 그래프 내에 마이너스(-) 표시 기호 적용하기
plt.rcParams["axes.unicode_minus"] = False

 

🐳 기준월 및 기준일자별 버스 이용량 시각화 분석

  • 사용할 컬럼 : 기준월, 기준일, 승객연령
  • 사용할 집계함수 : count
  • 이용량 집계를 위한 함수 : pivot_table()
    - 히트맵 시각화시 데이터 생성
  • 사용할 그래프 : 히트맵(hitmap)
    - 히트맵을 그리기 위한 데이터를 만들어야 하는데, 그 데이터를 만들어내는게 피벗테이블
df_pivot = df_bus_card_tot.pivot_table(index = "기준월",
                                       columns = "기준일",
                                       values = "승객연령",
                                       aggfunc = "count")

 

<데이터 count 집계하기>
- y축 : index
- x축 : columns
- 집계 : count(승객연령)

- 결측값 존재 : NaN

 

 

 

🐳 결측치(NaN) 처리하기

  • 결측치를 처리한 이유가 명확해야 한다.
    - 2월 결측치의 경우 2월이 28일 밖에 없어서 나머지 일에는 결측치가 나왔고 타당한 이유이기에 처리가 가능하다.
    - 3월 결측치의 경우 타당한 이유가 없이 결측치를 처리 할 수 없다. 이럴땐 데이터 제공자 측에 왜 데이터가 없는지 확인하고 타당한 이유 생성해야한다. 만약 버스시스템 오류로 인한 확인 불가라는 답변이 온다면 이유가 생성 됐다면 결측치를 0으로 처리하고 타당한 이유 작성하면 된다.
    - 0 으로 처리하지 않고 3월의 전체 평균을 삽입하거나 비어있는 값 전의 값과 후의 값의 평균을 넣거나 데이터를 아예 삭제하는 방법이 있다.
  • 모든 결측치(NaN)는 0으로 대체하기
df_pivot = df_pivot.fillna(0)
df_pivot

 

 

히트맵(heatmap) 시각화

🐳 기준일 및 기준일자별 버스 이용량 시각화 분석

### 그래프 전체 너비, 높이 설정
plt.figure(figsize=(20, 10))

### 그래프 제목 넣기
plt.title("기준월 및 기준일자별 버스 이용량 분석")

### 히트맵 그리기 : 히트맵은 seaborn 라이브러리에 존재한다
# - annot : False는 집계값 숨기기, True는 집계값 보이기
# - fmt : ".0f"는 소숫점 0자리까지 보이기
# - cmap : colormap, 컬러 색상그룹
sns.heatmap(df_pivot, annot=True, fmt=".0f", cmap="rocket_r")

### 그래프 출력
plt.show()

 

  • 그래프 해석
     - 1월 ~ 3월까지의 이용량을 분석한 결과 1월에 가장 많은 이용량을 나타내고 있으며, 2월에서 3월로 가면서 이용량이 점진적으로 줄어들고 있는 것으로 확인된다.
     - 1월 이용량이 가장 많은 이유는 포항시의 특성상 외부에서 관광객의 유입에 따라, 버스를 이용하는 사람들이 많을 것으로 예상된다.
     - 이에 따라, 포항시 관광객에 대한 데이터를 수집하여 해당 년월에 대한 데이터를 비교 분석해볼 필요성이 있다.

🐳 기준일 및 기준시간별 버스 이용량 시각화 분석

df_pivot = df_bus_card_tot.pivot_table(index = "기준일",
                                       columns = "기준시간",
                                       values = "승객연령",
                                       aggfunc = "count")
# 결측치 처리
df_pivot = df_pivot.fillna(0)

# 히트맵 그리기
plt.figure(figsize=(20, 10))

plt.title("기준일 및 기준시간별 버스 이용량 분석")

sns.heatmap(df_pivot, annot=True, fmt=".0f", cmap="YlGnBu")

plt.show()

  • 그래프 해석
    - 버스 이용량에 대한 분석결과, 일반적으로 출/퇴근 시간에 많아야 할 버스 이용량이 포항시의 경우 오후 시간대에 이용량이 밀집되어있다.
    - 특히, 오후1시와 3시에 높은 이용량을 나타내고 있다.
    - 이는 출/퇴근 시간에 자가 차량을 이용하는 사람이 많을 수도 있다는 예상을 할 수 있으며,
    인구 분포가 노령인구가 많기에 오후에 이용자가 많을 수도 있을 수 있다.
    - 따라서, 포항시 인구현황 데이터, 경제활동인구 분석을 통해 비교 분석이 가능할 것으로 예상된다.
    - 또한, 해당 이용량이 높은 시간대의 노선을 확인하여 특성 확인도 필요할 것으로 예상된다.

🐳 기준시간 및 분별 버스 이용량 시각화 분석

df_pivot = df_bus_card_tot.pivot_table(index = "기준시간",
                                       columns = "기준시간(분)",
                                       values = "승객연령",
                                       aggfunc = "count")
# 결측치 처리
df_pivot = df_pivot.fillna(0)

# 히트맵 그리기
plt.figure(figsize=(20, 10))

plt.title("기준시간 및 기준시간(분)별 버스 이용량 분석")

sns.heatmap(df_pivot, annot=True, fmt=".0f", cmap="coolwarm")

plt.show()

  • 그래프 해석
    - 출근 시간대의 버스이용량을  볼 때 오전 7시 55분 ~ 8시 10분 사이에 이용량이 많은 것으로 보인다.
    - 퇴근 시간대의 버스 이용량을 볼 때 오후 6시 ~ 6시 20분까지 이용량이 많은 것으로 보인다.
    - 특히 오후 3시 20분까지 버스 이용량이 매우 크게 나타나고 있다.
    - 오후 시간대 이용자에 대한 추가 확인이 필요할 것으로 보인다. 

🐳 기준일 및 시간별 버스내체류시간(분) 시각화 분석

df_pivot = df_bus_card_tot.pivot_table(index = "기준일",
                                       columns = "기준시간",
                                       values = "버스내체류시간(분)",
                                       aggfunc = "mean")
# 결측치 처리
df_pivot = df_pivot.fillna(0)

# 히트맵 그리기
plt.figure(figsize=(20, 10))

plt.title("기준일 및 시간별 버스내체류시간(분) 시각화 분석")

sns.heatmap(df_pivot, annot=True, fmt=".3f", cmap="BuPu")

plt.show()

  • 그래프 해석
     - 매월 1일에 장거리 이용자가 다소 분포하고 있으며 오전 5시부터 8시를 전후로 장거리 이용자가 증가하고 있다.
     - 오후 5시에 장거리 이용자가 매우 많게 나타난다. 이는 포항시 주변 상권(경제활동인구)의 출/퇴근 시간의 영향을 받을 수도 있을 것으로 예상된다.
     - 오후 7시 이후로는 장거리 이용자가 보편적으로 나타나고 있으며, 위에서 분석한 기준일 및 시간별 이용량 분석에서 확인한 바와 같이 7시 이후의 버스 이용량도 급격하게 줄어드는 것을 보아 저녁시간 버스 이용이 현저히 낮은것으로 보인다.
     - 장거리 이용자가 많은 시간대에 급행버스의 도입에 대한 추가 확인은 필요할 것으로 여겨진다.


막대그래프 시각화

🐳시간대 및 승객구별 버스내체류시간(분) 시각화

  • 필요한 데이터 추출
    - 기준시간, 승객연령, 버스내체류시간(분)
df_temp = pd.DataFrame()
df_temp["기준시간"] = df_bus_card_tot["기준시간"]
df_temp["승객구분"] = df_bus_card_tot["승객연령"]
df_temp["버스내체류시간"] = df_bus_card_tot["버스내체류시간(분)"]
df_temp


  • 승객 빈도 확인하기
df_temp["승객구분"].value_counts()


  • 그룹화 하기
  • 그룹화 후 head()
    - df_temp2.head(1)
    - groupby 이후의 head()의 역할 : 행단위로 조회하는게 아니라 그룹 단위로 조회한다.
    - groupby하고 head(1) 하면 각 그룹의 첫번째 값이 조회 된다.
# sum()
df_temp2 = df_temp.groupby(["기준시간", "승객구분"], as_index=False).sum()

# 내림차순 정렬
df_temp2 = df_temp2.sort_values(by=["버스내체류시간"], ascending=False)
df_temp2


  • 데이터의 행과 열을 교환하기
df_temp2.transpose()


  • 막대그래프 시각화 하기
fig = plt.figure(figsize=(25, 10))

plt.title("시간 및 승객구분별 버스내체류시간(분) 분석")

### hue : x축 및 y축을 기준으로 비교할 대상 컬럼 지정(범주형 데이터를 보통 사용)
sns.barplot(x="기준시간", y="버스내체류시간", hue="승객구분", data=df_temp2)

plt.show()

 

 

밀도그래프 시각화( histplot )

  • 2개의 그래프 조합

🐳시간대 및 승객구별 버스내체류시간(분) 시각화

plt.figure(figsize=(12, 4))
plt.title("시간 및 승객구분별 버스내체류시간(분) 분석")

sns.histplot(data = df_temp2,
            x = "기준시간",
             
            ### 사용할 막대의 최대 갯수
            bins = 30,
             
            ### 막대그래프에 밀도 선그리기            
            kde = True,
             
            ### 범주 데이터
            hue = "승객구분",
             
            ### 여러 범주를 하나의 막대에 표현하기
            multiple = "stack",
            
            ### 비율로 표시
            stat = "density",
             
            ### 막대 너비 : 0.6은 60% 축소한 너비 사이즈
            shrink = 0.6)

plt.show()

 

 

선그래프 시각화

🐳승차하정류장별 버스내체류시간(분) 상위 30건 시각화 분석

  • 구간(승차정류장 ~ 하차정류장) 까지의 버스내 체류시간을 이용하여 체류시간이 많은 구간을 확인하기
df_temp3 = pd.DataFrame()
df_temp3["버스내체류시간"] = df_bus_card_tot["버스내체류시간(분)"]
df_temp3["승하차정류장"] = df_bus_card_tot["승차정류장"] + "-->" + \
                         df_bus_card_tot["하차정류장"]
df_temp3


  • 구간별 그룹화 하기
### 구간(승차정류장 ~ 하차정류장)별 버스내체류시간(분) sum() 그룹화 하기
df_temp_gp = df_temp3.groupby(["승하차정류장"], as_index=False).sum()

### 내림차순 정렬
df_temp_gp = df_temp_gp.sort_values(by=["버스내체류시간"], ascending=False)

### 상위 30건 추출하기
df_temp_gp.head(30)


  • 선 그래프 그리기
plt.figure(figsize=(12, 4))
plt.title("승하차정류장별 버스내 체류시간 분석")

### 선그래프
plt.plot(df_temp3["승하차정류장"], df_temp3["버스내체류시간"])

### x축 및 y축 제목 넣기
plt.xlabel("승하창정류장")
plt.ylabel("버스내체류시간(분)")

### x축의 값의 기울기를 이용하여 조정하기
# - xticks() : x축을 컨트롤하는 함수
plt.xticks(rotation=90)

### 격자선 표시하기
plt.grid(True)

plt.show()

728x90
반응형
728x90
반응형

데이터 처리 시각화 (2)

https://mzero.tistory.com/89

 

[Data Wrangling] 데이터 처리 시각화

데이터 처리 시각화 🍀 포항시 버스데이터 수집 가공 시각화 URL : 국가교통 데이터 오픈마켓 데이터 명 : 포항시 BIS 교통카드 사용내역 🍀 메타 정의서 샘플링 🍀 1 건 샘플링하기 여러개의 파

mzero.tistory.com

[Data Wrangling] 데이터 처리 시각화 (1) 글에 이어서 진행

 

전체 파일 통합하기

  • 1건 샘플링 프로세스를 이용하여 전체 파일 통합하기
  • 최종 통합 데이더프레임 이름 :  df_bus_card_tot
from datetime import datetime

## 통합 시작 시간
start_date = datetime.today().strftime("%Y-%m-%d %H:%M:%S")

### 최종 통합 데이터프레임 이름 : df_bus_card_tot
df_bus_card_tot = pd.DataFrame()

### 0~79까지 폴더에 접근하기 위한 반복 수행
for i in range(0, 80, 1) :
    file_path = f"./01_data/org/trfcard({i})/trfcard.csv"
    df_bus_card_org = pd.read_csv(file_path)
    # 갯수 잘 반복했는지 확인용
    # print(i, " / ", len(df_bus_card_org))
    
    ### 메타정의서의 영문명, 한글명 컬럼 읽어들이기
    # - 데이터프레임 이름 : df_bus_cart_col_org
    file_path = f'./01_data/org/trfcard({i})/trfcard_columns.xlsx'
    df_bus_card_col_org = pd.read_excel(file_path,
                                        header=2,
                                        usecols="B:C")
    # print(i, " / ", len(df_bus_card_col_org))

    #방법 3
    df_bus_card_col_new_dict = {}
    
    for k, v in zip(df_bus_card_col_org.iloc[:, 0], df_bus_card_col_org.iloc[:, 1]):
        df_bus_card_col_new_dict[k] = v

    ### 컬럼명 변경하기
    # - inplace=True : 변경사항을 메모리에 반영하기
    df_bus_card_org.rename(columns=df_bus_card_col_new_dict, inplace = True)


    ### 데이터프레임 복제하기
    df_bus_card_kor = df_bus_card_org.copy()
    
    ### 1. 승차시각과 하차지각 데이터 타입을 문자열로 변환하기
    # - astype() : 데이터 형변환 함수
    df_bus_card_kor = df_bus_card_kor.astype({'승차시각':'str', '하차시각':'str'})

        df_bus_card = df_bus_card_kor[["승차시각","하차시각","승객연령","환승여부",
                                   "추가운임여부","승차정류장","하차정류장"]].copy()

    ### 3. 승차시각과 하차시각의 데이터타입을 날짜타입으로 변경하기(문자 타입만 datetime으로 변환가능하다.)
    df_bus_card["승차시각"] = pd.to_datetime(df_bus_card_kor.loc[:,"승차시각"])
    df_bus_card["하차시각"] = pd.to_datetime(df_bus_card_kor.loc[:,"하차시각"])

    ### 체류시간(분) 계산 및 컬럼 생성
    df_bus_card["버스내체류시간(분)"] = round((df_bus_card["하차시각"] - \
                                   df_bus_card["승차시각"]).dt.total_seconds()/60, 2)
    ### 5. 기준년도, 기준월, 기준일, 기준시간, 기준시간(분), 컬럼 생성하기
    # - 기준년도
    df_bus_card["기준년도"] = df_bus_card["승차시각"].dt.year
    # - 기준월
    df_bus_card["기준월"] = df_bus_card["승차시각"].dt.month
    # - 기준일
    df_bus_card["기준일"] = df_bus_card["승차시각"].dt.day
    # - 기준시간
    df_bus_card["기준시간"] = df_bus_card["승차시각"].dt.hour
    # - 기준시간(분)
    df_bus_card["기준시간(분)"] = df_bus_card["승차시각"].dt.minute

    #print(f"{i} / {len(df_bus_card)}")

    df_bus_card_tot = pd.concat([df_bus_card_tot, df_bus_card], axis=0, ignore_index=True)

## 통합 종료 시간
end_date = datetime.today().strftime("%Y-%m-%d %H:%M:%S")

print(f"전체 실행 시간 ==> {start_date} ~ {end_date}")
print(f" df_bus_card_tot ==> {len(df_bus_card_tot)}")
df_bus_card_tot

 

통합 데이터프레임 저장시키기

  • 저장 파일 위치 : all 폴더
  • 저장 파일 명 : 데이터프레임 변수명과 동일
  • 확장자 : csv
save_path = "./01_data/all/df_bus_card_tot.csv"
df_bus_card_tot.to_csv(save_path, index = False)

728x90
반응형
728x90
반응형

MVC

Model-View-Controller

  • 어플리케이션을 구성하는 다양한 방법론 중 하나로 구성요소를 3가지로 나눈 대표적인 패턴
  • JAVA기반의 Spring Framework에서 사용
  • Model : 데이터를 처리하며 DB와 상호 작용하는 인터페이스 역할을 하며, 기본적으로 DB의 복잡성에 얽매이지 않고 데이터와 상호작용할 수 있다. (백엔드)
  • View : 웹 응용 프로그램인 브라우저에서 실제 사용자에게 표시되는 프레젠테이션 로직을 처리하여 UI로 나타낸다. (프론트엔드)
  • Controller : View에서 핸들러의 흐름을 처리하거나 Model의 데이터를 처리하는 로직을 제공한다. (백엔드)
Model을 통해 데이터베이스에서 가져온 데이터를 파악하고 처리해 View로 전달된 내용을 파악한 후에 View를 통해 사용자로부터 데이터를 얻는다. 또한 Model을 통해 View를 변경하거나, 데이터를 업데이트 하여 지정된 로직을 구현한다.
 
프리젠테이션 로직? 비즈니스 로직?

프리젠테이션 로직 :  보여주기 위한 로직. 화면상의 디자인 구성을 위한 로직을 일컫는 말로써, 게시판에서의 표시하기 위한 for(or while)문 등의 사용이 여기에 해당한다.

 

비즈니스 로직 : 어떠한 특정한 값을 얻기 위해 데이터의 처리를 수행하는 응용프로그램의 일부를 말한다. 즉, 원하는 값을 얻기 위해서 백엔드에서 일어나는 각종 처리를 일컫는 말이다.

 

 

 

MVT

Model-Template-View

  • MVC를 기반으로 한 디자인 패턴
  • Python기반의 Django에서 사용
  • Model : MVC패턴의 Model과 마찬가지로 데이터 간의 인터페이스를 담당한다. (백엔드)
  • Templates : 프레임워크에서 실제 브라우저에 보이는 프레젠테이션 로직을 처리하고 사용자에게 인터페이스를 제공하는 방법을 제어하는 곳이다. (프론트엔드)
  • View : MVC의 Controller와 비슷한 역할을 한다. 따라서 View에서 모든 비지니스 로직을 처리하고, Model과 Templates간의 다리 역할을 하기도 한다.  (백엔드)

 

👍출처

https://yangtaeyoung.github.io/docs/web/mvc/

https://nitro04.blogspot.com/2020/01/django-mvc-mvt.html

728x90
반응형

+ Recent posts