728x90

https://www.acmicpc.net/problem/1002

Code

최종 제출 코드

😢 여러가지 고려해야할 경우를 찾아내는 것이 힘들었다.

😊
1. 원이 두 점에서 만나는 경우 (2)( r2 - r1 < d < r1 + r2)
2. 두 원이 외접하는 경우 (1)( d === r1 + r2 )
3. 두 원이 내접하는 경우 (1)( d === r2 - r1 && d !== 0 )
4. 한 원이 다른 원을 포함하는 경우 (0)( d < r2 - r1 )
5. 두 원이 떨어져 만나지 않는 경우 (0)( d > r1 + r2 )
6. 두 원이 일치하는 경우 (-1)( d === 0, r1 === r2 )

중점 사이의 거리를 구하고, 위 6가지 경우만 조건문으로 분류해주면 된다.

참고 자료 https://mathbang.net/101

 

두 원의 위치관계, 내접, 외접

위치관계 또 나오네요. 이번에는 두 원의 위치관계에요. 위치관계 마지막이니까 정신 바짝 차리고 따라오세요. 원과 직선의 위치관계, 원의 할선과 접선, 접점에서 했던 것처럼 두 원이 어떤 관계가 있는지 그때..

mathbang.net

Full Code (https://github.com/DasolPark/Dasol_JS_Algorithm/tree/master/Baekjoon)

// Turret
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
 
// For local test
const input = ['3', '0 0 13 40 0 37', '0 0 3 0 7 4', '1 1 1 1 1 5'];
const T = parseInt(input.shift());
 
for (let i = 0; i < T; i++) {
const xyrxyr = input[i].split(' ').map(num => parseInt(num));
const x1 = xyrxyr.shift();
const y1 = xyrxyr.shift();
let r1 = xyrxyr.shift();
const x2 = xyrxyr.shift();
const y2 = xyrxyr.shift();
let r2 = xyrxyr.shift();
 
const dx = x1 - x2;
const dy = y1 - y2;
if (r1 > r2) {
// r1 <= r2로 정의
const temp = r1;
r1 = r2;
r2 = temp;
}
const rSum = (r1 + r2) * (r1 + r2);
const rSub = (r2 - r1) * (r2 - r1);
const d = dx * dx + dy * dy; // 중점 사이의 거리
 
// 1. 원이 두 점에서 만나는 경우 (두 점)(r2 - r1 < d < r1 + r2)
if (d < rSum && d > rSub) {
console.log(2);
// 2. 두 원이 외접하는 경우 (한 점)( d = r1 + r2)
// 3. 두 원이 내접하는 경우 (한 점)( d = r2 - r1 && d != 0)
} else if (d === rSum || (d === rSub && d !== 0)) {
console.log(1);
// 4. 하나의 원이 다른 원을 포함하는 경우 (못 만남)( d < r2 - r1 )
// 5. 두 원이 멀리 떨어져 만나지 않는 경우 (못 만남)( d > r1 + r2 )
} else if (d < rSub || d > rSum) {
console.log(0);
// 6. 두 원이 일치하는 경우 (무수히)( d = 0, r1 = r2 )
} else if (d === 0) {
if (r1 === r2) {
console.log(-1);
} else {
console.log(0);
}
}
}
728x90

https://www.acmicpc.net/problem/3053

Code

최종 제출 코드

😢 택시 기하학과 유클리드 기하학을 검색한 후, 이해하고 풀면 되는 문제

😊 유클리드 기하학에서 반지름이 R인 원이 넓이'반지름*반지름*PI'이므로 Math.powMath.PI를 이용하여 풀었고,
택시 기하학에서 반지름이 R인 원의 넓이마름모와 같으므로, '밑변*높이*2'(직사각형 넓이*2라고 생각)로 풀어주면 된다.

Full Code (https://github.com/DasolPark/Dasol_JS_Algorithm/tree/master/Baekjoon)

// Taxi geometry(Euclid geometry)
 
// For submit
 
// const fs = require('fs');
// const input = parseInt(fs.readFileSync('/dev/stdin').toString().trim());
 
// For local test
const input = 1;
 
function Euclid(radius) {
return Math.pow(radius, 2) * Math.PI;
}
 
function taxi(radius) {
return Math.pow(radius, 2) * 2;
}
 
console.log(Euclid(input).toFixed(6));
console.log(taxi(input).toFixed(6));
728x90

https://www.acmicpc.net/problem/3009

Code

최종 제출 코드

😢 이쁘게 풀어주려다가 그냥 조건문으로 끝낸 문제

😊 가끔은 단순한게 좋은 방법인듯 하다.

일단 x좌표가 같은 것이 있다면, 이미 평행한 좌표가 있는 것이고
y좌표가 같은 것이 있다면, 역시 평행한 좌표가 있는 것이다.
따라서, x 또는 y가 한 번만 존재하는 좌표를 찾아내고 그 값을 넣어주면 된다.

Full Code (https://github.com/DasolPark/Dasol_JS_Algorithm/tree/master/Baekjoon)

// Fourth coordinate(in a rectangle)
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
 
// For local test
const input = ['30 20', '10 10', '10 20'];
const strToInt = input.map(coords =>
coords.split(' ').map(num => parseInt(num))
);
 
let x = 0;
let y = 0;
if (strToInt[0][0] !== strToInt[1][0]) {
if (strToInt[0][0] !== strToInt[2][0]) {
x = strToInt[0][0];
} else {
x = strToInt[1][0];
}
} else {
x = strToInt[2][0];
}
 
if (strToInt[0][1] !== strToInt[1][1]) {
if (strToInt[0][1] !== strToInt[2][1]) {
y = strToInt[0][1];
} else {
y = strToInt[1][1];
}
} else {
y = strToInt[2][1];
}
 
console.log(`${x} ${y}`);
728x90

https://www.acmicpc.net/problem/4153

Code

최종 제출 코드

😢 변의 길이 순서가 랜덤으로 들어오는 듯 하다.

😊 ||(or)으로 모든 경우를 넣어주든지
sort순서를 처리해주면 된다.

Full Code (https://github.com/DasolPark/Dasol_JS_Algorithm/tree/master/Baekjoon)

// A right-angled triangle(Pythagorean theorem)
 
// 2nd Soludion(sort)
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
 
// For local test
const input = ['6 8 10', '25 52 60', '5 12 13', '5 4 3', '0 0 0'];
 
for (let sides of input) {
const strToInt = sides
.split(' ')
.map(num => Math.pow(parseInt(num), 2))
.sort((a, b) => a - b);
const firstSidePow = strToInt.shift();
const secondSidePow = strToInt.shift();
const thirdSidePow = strToInt.shift();
if (firstSidePow === 0 && secondSidePow === 0 && thirdSidePow === 0) {
break;
}
 
if (firstSidePow + secondSidePow === thirdSidePow) {
console.log('right');
} else {
console.log('wrong');
}
}
 
// 1st Solution(or)
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
 
// For local test
// const input = ['6 8 10', '25 52 60', '5 12 13', '0 0 0'];
 
// for (let sides of input) {
// const strToInt = sides.split(' ').map(num => Math.pow(parseInt(num), 2));
// const firstSidePow = strToInt.shift();
// const secondSidePow = strToInt.shift();
// const thirdSidePow = strToInt.shift();
// if (firstSidePow === 0 && secondSidePow === 0 && thirdSidePow === 0) {
// break;
// }
 
// if (
// firstSidePow + secondSidePow === thirdSidePow ||
// firstSidePow + thirdSidePow === secondSidePow ||
// secondSidePow + thirdSidePow === firstSidePow
// ) {
// console.log('right');
// } else {
// console.log('wrong');
// }
// }
728x90

https://www.acmicpc.net/problem/1085

Code

최종 제출 코드

😢 이렇게 쉬울 거라고 생각하지 못 했던 문제

😊 x, y는 현재 나의 위치이며 w, h는 직사각형의 오른쪽 위 꼭짓점, 0,0은 왼쪽 아래 꼭짓점이다.

                  10,3
(w, h)
          6,2
(x, y)
       
0,0

                 

위 표을 좌표계라고 생각해보자. 그리고 벗어날 수 있는 모든 경우의 수를 배열에 저장해보자.
좌표 0,0 기준으로 직사각형을 벗어나려면 x, y값 그 자체로 움직여야 벗어날 수 있으므로 [x, y]를 배열에 우선 넣는다.(x-0, y-0)
좌표 w, h 기준으로 직사각형을 벗어나려면 w-x, h-y만큼 움직여야 벗어날 수 있다. 따라서, [w-x, h-y]를 추가적으로 배열에 넣는다.

결과적으로 [ x, y, w-x, h-y ] 총 4개의 경우의 수를 구할 수 있다(직사각형을 벗어날 수 있는 이동 값)
최종적으로 Math.min.apply(null, 배열)넣어서 최소값을 구하고 출력해주면 된다.

Full Code (https://github.com/DasolPark/Dasol_JS_Algorithm/tree/master/Baekjoon)

// Escape from Rectangle
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split(' ').map(num => parseInt(num));
 
// For local test
const input = [6, 2, 10, 3]; // x y w h
const x = input[0];
const y = input[1];
const w = input[2];
const h = input[3];
const counters = [x, y, w - x, h - y];
 
console.log(Math.min.apply(null, counters));
728x90

https://www.acmicpc.net/problem/9020

Code

최종 제출 코드

😢 역시 에라토스테네스의 체를 이용하면 되고, 골드바흐의 파티션을 어떻게 구할지 생각을 해줘야 한다.

😊 31번째 줄 코드는 이전 문제에서 사용한 것과 같고, 33-37번째 줄 코드에서 2부터 n까지 소수를 저장해준다.

중첩 for loop을 열고, 입력 받은 n을 0으로 만들 수 있는 소수의 짝checkPrimePair 배열에 2차원 형식으로 저장해준다.
(checkPrimePair가 저장된 모습은 [ [2, 3], [3, 5] ] 같은 형식이라고 생각해주면 된다)

그리고 또 다시 for loop을 열고 checkPrimePair중 가장 작은 차이가 나는 소수 짝의 index를 구해준다.

마지막으로, 해당 index의 짝을 join(' ')형식으로 출력해주면 된다.

지금까지 풀었던 알고리즘 중에 가장 길지 않나 싶다. 다시 풀어보며 조금 더 개선할 수 있는 곳을 찾아봐야겠다.

Full Code (https://github.com/DasolPark/Dasol_JS_Algorithm/tree/master/Baekjoon)

// Goldbach's conjecture
 
// 1st Solution
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n').map(num => parseInt(num));
 
// For local test
const input = [3, 8, 10, 16];
const T = input.shift();
 
for (let i = 0; i < T; i++) {
const n = input.shift();
const isPrimeNumArr = new Array(n + 1);
const primeNumArr = [];
const checkPrimePair = [];
 
isPrimeNumArr.fill(true);
isPrimeNumArr[0] = isPrimeNumArr[1] = false;
 
for (let j = 2; j <= n; j++) {
if (Math.pow(j, 2) > 1000000) {
break;
} else {
for (let square = Math.pow(j, 2); square <= n; square += j) {
isPrimeNumArr[square] = false;
}
}
}
 
for (let i = 2; i <= n; i++) {
if (isPrimeNumArr[i]) {
primeNumArr.push(i);
}
}
 
for (let i = 0; i < primeNumArr.length; i++) {
for (let j = i; j < primeNumArr.length; j++) {
if (n - primeNumArr[i] - primeNumArr[j] === 0) {
checkPrimePair.push([primeNumArr[i]]);
checkPrimePair[checkPrimePair.length - 1].push(primeNumArr[j]);
}
}
}
 
let min = checkPrimePair[0][1] - checkPrimePair[0][0];
let indexOfMin = 0;
for (let i = 0; i < checkPrimePair.length; i++) {
if (checkPrimePair[i][1] - checkPrimePair[i][0] < min) {
min = checkPrimePair[i][1] - checkPrimePair[i][0];
indexOfMin = i;
}
}
console.log(checkPrimePair[indexOfMin].join(' '));
}
728x90

https://www.acmicpc.net/problem/4948

Code

Solution 1
Solution 2 개선된 코드

😢 '에라토스테네스의 체'를 이용해서(1929번 문제) 구간만 잘 정해주면 된다.

😊 Solution 1)
마지막에 0을 받으면 끝나도록 while loop을 돌려줬다.
1929번 문제에서 M, N을 여기서는 n = 입력 받은 값, m = n * 2로 구간을 설정해줬다.
또한, 값을 판단하기 위해 선언하는 Array에서, 구간을 벗어나는 index에 false를 세팅해주고 시작하면 된다.
(0보다 크고 n보다 작거나 같을 때까지)

추가 Solution 2) 코드 개선
전체 입력을 반복하는 반복문은 for ... of로 대체하였으며, 첫 째 줄에 0을 받으면 break하도록 설정하였다.
n보다 크고 2n보다 작거나 같아야 하므로, 구간은 n+1부터 2n까지라고 보면 된다. 
따라서 n=num+1, m=2*num으로 구간을 선언해주었다.
마찬가지로, m+1만큼 Array를 선언해준 후 fill(true)로 채워줬다. (index 0과 1은 false로 채워줬다)
이제 에라토스테네스의 체 방법으로 소수를 구해주고, n부터 m까지 소수가 있다면 count 후 counter를 출력해줬다.

이렇게 3396ms에서 520ms로 속도를 개선할 수 있었다.

Full Code (https://github.com/DasolPark/Dasol_JS_Algorithm/tree/master/Baekjoon)

// 베르트랑 공준(Bertrand Gongjoon)
 
// 2nd Solution
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n').map(num => parseInt(num));
 
// For local test
const input = [1, 10, 13, 100, 1000, 10000, 100000, 0];
for (let num of input) {
if (num === 0) {
break;
}
 
const n = num + 1;
const m = 2 * num;
const isPrimeNumArr = new Array(m + 1);
let counter = 0;
 
isPrimeNumArr.fill(true);
isPrimeNumArr[0] = isPrimeNumArr[1] = false;
 
for (let i = 2; i <= m; i++) {
if (Math.pow(i, 2) > 1000000) {
break;
} else {
for (let square = Math.pow(i, 2); square <= m; square += i) {
isPrimeNumArr[square] = false;
}
}
}
 
for (let i = n; i <= m; i++) {
if (isPrimeNumArr[i]) {
counter++;
}
}
console.log(counter);
}
 
// 1st Solution
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n').map(num => parseInt(num));
 
// For local test
// const input = [1, 10, 13, 100, 1000, 10000, 100000, 0];
 
// while (true) {
// const n = input.shift();
// if (n === 0) {
// break;
// }
// let counter = 0;
// const m = 2 * n;
// const isPrimeArr = new Array(m + 1);
 
// isPrimeArr.fill(true);
// for (let i = 0; i <= n; i++) {
// isPrimeArr[i] = false;
// }
 
// for (let i = 2; i < m + 1; i++) {
// if (parseInt(Math.pow(i, 2) > m)) {
// break;
// } else {
// for (let square = parseInt(Math.pow(i, 2)); square < m + 1; square += i) {
// isPrimeArr[square] = false;
// }
// }
// }
 
// for (let i = 2; i < m + 1; i++) {
// if (isPrimeArr[i]) {
// counter++;
// }
// }
// console.log(counter);
// }
728x90

https://www.acmicpc.net/problem/1929

Code

최종 제출 코드

😢 원리를 이해하고 코드를 구현하는 데, 시간이 조금 걸렸다. 여러 자료도 참고했다.

😊 에라토스테네스의 체 방법으로 소수를 구하는 문제다.
소수를 구하면, 그 소수의 배수는 소수가 될 수 없다. 그래서 그 배수들을 사전에 제거하고 남은 수를 이용해 소수를 구하는 방법이다.

먼저, (1 ≤ M ≤ N ≤ 1,000,000)이므로 MAX를 선언해준다.
그리고 소수를 판단할 isPrimeArr(Array)를 N+1만큼 선언해준다(인덱스를 N까지 사용할 것이므로)
isPrimeArr는 .fill()을 이용해 모두 true값으로 세팅해줬다. 그리고 0과 1은 소수가 아니므로 false를 세팅해줬다.

for loop을 돌리면서 해당 소수의 배수는 false로 값을 바꿔준다. 그리고 조건문을 이용해 우리가 구할 숫자를 넘어가면 break;
내부 for loop에서 for조건문의 마지막을 넣지 않았는데, 그 안에 square += i를 넣어줘도 된다. 같은 의미다(배수를 계속 더해줌)

마지막에 입력 받은 구간만큼 for loop을 이용해 출력해주면 된다(isPrimeArr이 true면 소수)

아래 링크를 참고하면 이론과 함께 시각적으로 어떻게 진행되는지 볼 수 있어 좋다. 좋은 참고자료!

https://ko.wikipedia.org/wiki/%EC%97%90%EB%9D%BC%ED%86%A0%EC%8A%A4%ED%85%8C%EB%84%A4%EC%8A%A4%EC%9D%98_%EC%B2%B4

 

에라토스테네스의 체 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 둘러보기로 가기 검색하러 가기 수학에서 에라토스테네스의 체는 소수(소쑤)를 찾는 방법이다. 고대 그리스 수학자 에라토스테네스가 발견하였다. 알고리즘[편집] 2부터 소수를 구하고자 하는 구간의 모든 수를 나열한다. 그림에서 회색 사각형으로 두른 수들이 여기에 해당한다. 2는 소수이므로 오른쪽에 2를 쓴다. (빨간색) 자기 자신을 제외한 2의 배수를 모두 지운다. 남아있는 수 가운데 3은 소수이므로 오른쪽에 3을 쓴다. (초

ko.wikipedia.org

Full Code (https://github.com/DasolPark/Dasol_JS_Algorithm/tree/master/Baekjoon)

// Find Prime Number(에라토스테네스의 체)
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split(' ').map(num => parseInt(num));
 
// For local test
const input = [3, 16];
const MAX = 1000000;
let M = input.shift();
let N = input.shift();
let isPrimeArr = new Array(N + 1);
let square = 0;
 
isPrimeArr.fill(true);
isPrimeArr[0] = isPrimeArr[1] = false;
 
for (let i = 2; i < N + 1; i++) {
if (isPrimeArr[i]) {
if (parseInt(Math.pow(i, 2)) > MAX) {
break;
} else {
for (square = parseInt(Math.pow(i, 2)); square < N + 1; ) {
isPrimeArr[square] = false;
square += i;
}
}
}
}
 
for (let i = M; i < N + 1; i++) {
if (isPrimeArr[i]) {
console.log(i);
}
}
728x90

https://www.acmicpc.net/problem/2581

Code

최종 제출 코드

😢 기본 '소수 찾기'문제에서 조건을 조금 추가해주면 쉽게 해결되는 문제

😊 최솟값을 구해주기 위해 Array를, 소수값의 합을 구해주기 위해 sum 변수를 추가했다.
소수를 구하는 부분은 function으로 따로 빼주었으며,
function내에서 소수를 찾으면 arr에 push함과 동시에 소수들을 sum에 누적해 줬다.
그리고 마지막에 만약 Array.length가 없다면 소수는 없는 것이므로 -1을 출력하도록 했다.

Full Code (https://github.com/DasolPark/Dasol_JS_Algorithm/tree/master/Baekjoon)

// Prime Number(Sum and Min or -1)
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
 
// For local test
const input = ['64', '65'];
const primeNumArr = [];
let primeNumSum = 0;
 
function primeNumber(n) {
if (n < 2) {
return;
}
 
for (let i = 2; i < n; i++) {
if (n % i === 0) {
return;
}
}
primeNumArr.push(n);
primeNumSum += n;
}
 
const begin = parseInt(input.shift());
const end = parseInt(input.shift());
 
for (let i = begin; i <= end; i++) {
primeNumber(i);
}
 
if (!primeNumArr.length) {
console.log(-1);
} else {
console.log(primeNumSum);
console.log(Math.min.apply(null, primeNumArr));
}
728x90

https://www.acmicpc.net/problem/1978

Code

최종 제출 코드

😢 소수란? 1과 자기 자신만으로 나누어 떨어지는 1보다 큰 양의 정수.

😊 따로 function을 만들어서 풀었다.
0 또는 1은 소수가 아니므로 if(n < 2) 조건문을 걸어 return;했고,
2부터 자기 자신-1까지 나눠주면서 나머지가 0된다면 소수가 아니므로 return;
위의 조건에 모두 해당되지 않는다면, 해당 숫자는 소수이므로 counter++;

Full Code (https://github.com/DasolPark/Dasol_JS_Algorithm/tree/master/Baekjoon)

// Find Prime Number
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
 
// For local test
const input = ['4', '1 3 5 7'];
const T = parseInt(input.shift());
const numbers = input
.shift()
.split(' ')
.map(num => parseInt(num));
let counter = 0;
 
function primeNumber(n) {
if (n < 2) {
return;
}
 
for (let i = 2; i < n; i++) {
if (n % i === 0) {
return;
}
}
counter++;
}
 
for (let i = 0; i < T; i++) {
primeNumber(numbers[i]);
}
 
console.log(counter);

+ Recent posts