통계학
수를 처리하는 것은 통계학에서 상당히 중요한 일이다. 통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다. 단, N은 홀수라고 가정하자.
1.산술평균 : N개의 수들의 합을 N으로 나눈 값
2.중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
3.최빈값 : N개의 수들 중 가장 많이 나타나는 값
4.범위 : N개의 수들 중 최댓값과 최솟값의 차이
N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.
첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.
첫째 줄에는 산술평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.
둘째 줄에는 중앙값을 출력한다.
셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다.
넷째 줄에는 범위를 출력한다.
5
1
3
8
-2
2
2
2
1
10
4000
4000
4000
0
4000
4000
4000
0
5
-1
-2
-3
-1
-2
-2
-2
-1
2
3
0
0
-1
0
0
0
1
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
// 주어진 숫자 배열의 산술평균을 계산하는 함수
function calculateMean(numbers) {
const sum = numbers.reduce((acc, cur) => acc + cur, 0); // 배열의 모든 요소를 더하여 합을 계산
return sum / numbers.length; // 합을 배열의 길이로 나누어 평균을 구함
}
// 주어진 숫자 배열의 중앙값을 계산하는 함수
function calculateMedian(numbers) {
const sorted = numbers.sort((a, b) => a - b); // 배열을 오름차순으로 정렬
const mid = Math.floor(numbers.length / 2); // 배열의 중앙 인덱스 계산
return numbers.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid]; // 배열의 길이가 짝수인 경우 중앙 두 값의 평균 반환, 홀수인 경우 중앙값 반환
}
// 주어진 숫자 배열의 최빈값을 계산하는 함수
function calculateMode(numbers) {
const countMap = new Map(); // 숫자를 키로, 등장 횟수를 값으로 저장하기 위한 Map 객체 생성
numbers.forEach((num) => {
if (countMap.has(num)) {
countMap.set(num, countMap.get(num) + 1); // 이미 등장한 숫자라면 등장 횟수 증가
} else {
countMap.set(num, 1); // 처음 등장한 숫자라면 등장 횟수를 1로 설정
}
});
let maxCount = 0; // 가장 많이 등장한 횟수
let modes = []; // 최빈값들을 저장할 배열
countMap.forEach((count, num) => {
if (count > maxCount) {
maxCount = count; // 더 큰 등장 횟수를 갱신
modes = [num]; // 최빈값을 modes 배열에 넣어줌
} else if (count === maxCount) {
modes.push(num); // 동일한 등장 횟수인 경우 modes 배열에 추가
}
});
return modes.length > 1 ? modes.sort((a, b) => a - b)[1] : modes[0]; // 최빈값이 여러 개인 경우 두 번째로 작은 값을 반환, 아니면 최빈값 반환
}
// 주어진 숫자 배열의 범위를 계산하는 함수
function calculateRange(numbers) {
const min = Math.min(...numbers); // 배열의 최소값 계산
const max = Math.max(...numbers); // 배열의 최대값 계산
return max - min; // 최대값과 최소값의 차이를 범위로 반환
}
rl.on('line', (input) => {
const numbers = input.split(' ').map(Number); // 입력값을 공백으로 구분하여 숫자 배열로 변환
const mean = calculateMean(numbers); // 평균 계산
const readline = require("readline"); // readline 모듈을 import 합니다.
const rl = readline.createInterface({
// readline 인터페이스를 생성합니다.
input: process.stdin,
output: process.stdout,
});
const input = []; // 입력값을 저장할 배열을 선언합니다.
rl.on("line", (line) => {
input.push(Number(line)); // 각 줄마다 입력값을 숫자로 변환해 배열에 저장합니다.
}).on("close", () => {
// 입력이 종료되면 실행할 로직을 정의합니다.
const n = input.shift(); // 첫 번째 입력값 (숫자의 개수)을 n으로 설정합니다.
const numbers = input; // 나머지 입력값 (숫자들)을 numbers에 저장합니다.
numbers.sort((a, b) => a - b); // 숫자들을 오름차순으로 정렬합니다.
// 산술평균 구하기: 숫자들의 합을 숫자의 개수로 나누고 반올림합니다.
const average = Math.round(numbers.reduce((a, b) => a + b, 0) / n);
// 중앙값 구하기: 숫자들 중 중앙에 위치한 값을 찾습니다.
const median = numbers[Math.floor(n / 2)];
// 최빈값 구하기
const counts = {}; // 각 숫자의 등장 횟수를 저장할 객체를 생성합니다.
numbers.forEach((number) => {
counts[number] = (counts[number] || 0) + 1; // 각 숫자의 등장 횟수를 카운트합니다.
});
const modes = [];
const max = Math.max(...Object.values(counts)); // 등장 횟수의 최댓값을 찾습니다.
for (let [key, value] of Object.entries(counts)) {
// 객체를 순회하며
if (value === max) modes.push(Number(key)); // 등장 횟수가 최댓값과 같은 숫자를 모두 찾습니다.
}
modes.sort((a, b) => a - b); // 최빈값 후보들을 오름차순으로 정렬합니다.
const mode = modes.length > 1 ? modes[1] : modes[0]; // 최빈값이 하나면 그대로, 두 개 이상이면 두 번째로 작은 값을 최빈값으로 선택합니다.
// 범위 구하기: 가장 큰 값에서 가장 작은 값을 뺍니다.
const range = numbers[numbers.length - 1] - numbers[0];
// 출력: -0이 출력되는 경우를 방지하기 위해 0으로 변경해 출력합니다.
console.log(average === -0 ? 0 : average);
console.log(median);
console.log(mode);
console.log(range);
});