문제 설명 과일 장수가 사과 상자를 포장하고 있습니다. 사과는 상태에 따라 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 해주세요.
function solution(k, m, score) {
var answer = 0;
let arr = score.sort((a, b) => b - a); // 내림차순 정렬
let box = [];
arr.forEach((item,i) =>{
box.push(arr[i])
// 박스에 사과가 m개 담겼다면 점수계산
if(box.length === m){
answer += Math.min(...box) * box.length;
box=[];
}
})
return answer;
}
중간에 발생한 문제점
처음에는 splice로 꺼내는 작업을 했더니 forEach가 멈춰버리는 일이 생겼습니다. 알아보니 forEach는 처음에 시작할때 배열의 길이와 요소를 고정된 상태로 순회한다는걸 몰랐습니다.
혹시 문제가 남은 사과까지 계산한다면..?
문제에서는 남은 사과는 계산하지 않습니다.
혹시라도 남은 사과를 계산을 했었다면
for문이나 while문으로짜고 splice로 잘라서 넣고 남은 arr.length가 m보다 작다면 arr의 요소를 더해서 계산하면 될 듯 싶습니다.
function solution(k, m, score) {
let answer = 0;
let arr = score.sort((a, b) => b - a);
// 상자 단위로 처리 (m개씩 꺼내서 상자 구성)
while (arr.length >= m) {
let box = arr.splice(0, m); // m개씩 꺼내서 상자에 담기
answer += Math.min(...box) * m; // 최소 점수 * m (상자의 가격)
}
// 남은 사과가 있으면 마지막 상자에 대해 처리
if (arr.length > 0) {
let box = arr.splice(0, arr.length); // 남은 사과들
answer += Math.min(...box) * arr.length; // 남은 사과들 가격 계산
}
return answer;
}
count는 컴포넌트 내부에 캡슐화된 상태 정보로 볼 수 있으며, 외부에서는 이를 직접 수정할 수 없습니다. setCount나 setCount 가 포함된 함수를 통해서 상태를 업데이트 할 수 있습니다. 즉 count는 MyComponent 내부에 캡슐화 되어 있으며, 외부에서는 직접 수정할 수 없고 incrament 함수를 통해 조작할 수 있습니다.
2. 합성 (Composition)
정의: 여러 개의 객체를 하나로 묶어 더 큰 복합 객체를 만드는 방식으로, 객체 간 상속보다는 상호 협력을 통해 재사용성을 높이는 디자인 패턴입니다.
장점: 합성을 사용하면 객체 간 결합이 느슨해지고, 유연한 구조를 만들 수 있어 유지보수성과 확장성이 향상된다. 상속의 문제점을 피하고, 더 많은 재사용성을 제공할 수 있습니다.
정의: 여러 클래스가 같은 인터페이스나 메서드 명을 공유하면서 서로 다른 방식으로 동작하는 특성을 의미합니다. 이는 객체 지향의 중요한 원칙으로, 하나의 타입을 여러 방식으로 사용할 수 있게 합니다. 리엑트에서의 다형성은 props를 통해 동일한 컴포넌트가 다른 props를 받으면 다르게 동작하게 만들어서 다형성을 적용할 수 있습니다.
장점: 다형성을 사용하면 코드의 유연성과 확장성이 높아지며, 인터페이스나 추상 클래스 등을 활용해 기능을 확장할 수 있다.
이 두 방식은 웹 애플리케이션에서 데이터를 주고받는 방법을 설명하며, 각각 고유한 장단점이 있어 상황에 따라 적절하게 사용합니다.
1. Sync(동기)
- 요청과 응답이 동시에 이루어지는 방식입니다. 웹 페이지를 새로고침하면서 데이터를 불러오는 경우가 이에 해당합니다. 예를 들어, 온라인 쇼핑몰에서 사용자가 결제 정보를 입력하고 결제 버튼을 누르면, 페이지가 새로고침되면서 결제가 처리되고, 새 페이지에 결제 완료 정보가 표시됩니다.
장점
코드의 간결성 - 동기 통신은 요청과 응답이 순차적으로 이루어지므로, 코드를 작성하고 이해하기 쉽습니다.
순서 보장 - 요청을 보낸 후 응답을 받아야 다음 작음을 수행할 수 있으므로, 요청과 응답의 순서가 보장됩니다.
에러 처리 용이 - 요청과 응답이 연결되어 있어, 에러 발생 시 처리하기 쉽습니다.
단점
성능 저하 - 페이지 전체를 새로고침해야 하므로 서버와의 통신량이 많아지고, 성능이 저하될 수 있습니다.
사용자 경험 저하 - 페이지가 깜빡거리거나 멈추는 형상이 발생하여, 사용자가 불편함을 느낄 수 있습니다.
작업 차단 요청을 보낸 후 응답을 기다려야 하므로, 다른 작업을 동시에 수행할 수 없습니다.
2. Async(비동기)
- 요청과 응답이 동시에 이루어지지 않는 방식입니다. 페이지를 새로고침하지 않고, 필요한 부분만 업데이트하는 경우가 이에 해당합니다. 예를 들어, 실시간 채팅 애플리케이션에서 메세지를 전송하면, 전체 페이지를 새로고침하지 않고 채팅 창에만 새 메시지가 나타납니다.
장점
성능 향상 - 페이지의 일부만 업데이트하므로, 웹페이지의 속도와 성능이 향상됩니다.
사용자 경험 개선 - 화면이 깜박거리거나 멈추지 않고 부드럽게 작동하여, 사용자 경험이 향상됩니다.
병렬 작업 가능 - 요청을 보낸 후에도 다른 작업을 수행할 수 있습니다.
단점
코드 복잡도 증가 - 비동기 통신은 코드 작성과 이해가 어려울 수 있으며, 복잡도가 증가할 수 있습니다.
순서 보장의 불확실성 - 요청과 응답이 동시에 일어나지 않아, 요청의 처리 속도에 따라 응답순서가 뒤바뀔 수 있습니다.
에러 처리 복잡 - 요청과 응답이 분리되어 있어, 에러가 발생했을 때 원인을 파악하고 처리하기가 어렵습니다.
3. 동기 및 비동기 처리의 예시
동기 처리의 예시
상품 상세 페이지 로딩
설명: 사용자가 상품 목록에서 특정 상품을 클릭하면, 상품의 상세 정보 페이지로 이동합니다. 이때 전체 페이지가 새로고침되며, 새로운 URL로 이동하여 서버에서 상품에 대한 전체 HTML 페이지를 받아옵니다.
동작: 전체 페이지가 서버로부터 응답을 받아 로딩되기 전까지 사용자는 다른 작업을 할 수 없습니다. 이는 요청이 완료될 때까지 기다려야 하기 때문입니다.
간결함 : 동일한 URI를 반복적으로 사용하면서, URI를 간소화하고 가독성을 높일 수 있습니다. 이로 인해 URI의 구조가 복잡해지지 않으며, 이해하기 쉬운 API를 설계할 수 있습니다.
의미 전달 : URI와 HTTP 메서드를 조합함으로써, 자원에 대한 조작 의도를 명확하게 전달합니다. 예를 들어, /users/j-plum URI는 특정 사용자를 나타내며, GET, PUT, DELETE 메서드를 통해 조회, 수정, 삭제와 같은 다양한 작업을 수행할 수 있음을 직관적으로 알 수 있습니다.
GET /users/j-plum: j-plum이라는 사용자의 정보를 조회합니다.
PUT /users/j-plum: j-plum이라는 사용자의 정보를 수정합니다.
DELETE /users/j-plum: j-plum이라는 사용자를 삭제합니다.
3) 표현(Representation)
- 표현은 자원의 상태나 데이터를 전달하는 방식을 의미합니다. 서버는 클라이언트의 요청에 따라 자원의 상태를 다양한 형식으로 반환할 수 있습니다. 주로 JSON이나 XML형식으로 표현됩니다.
- 표현이란? : 표현은 자원의 실제 데이터를 포험하며, 이를 통해 클라이언트는 서버로부터 자원의 상태를 확인하거나 필요한 데이터를 받을 수 있습니다. 표현은 자원의 구조와 내용을 설명합니다.
예시 : 만약 사용자가 /users/j-plum URI에 GET 요청을 보내면, 서버는 ID가 123인 사용자의 정보를 반환합니다.