728x90

💪

Click! 👉 https://github.com/DasolPark/Dasol_JS_WorkoutTimer

JavaScript와 반응형 CSS를 사용하여 데스크톱 또는 모바일에서 사용할 수 있는 운동 도우미 타이머 어플리케이션입니다.

📌운동 종목과 종목의 세트를 상세히 작성할 수 있으며, 각 세트별로 완료한 시간을 체크해줍니다.
💡운동 종목과 세트는 추가 또는 삭제가 가능하며, 운동을 완료하면 완료된 시간을 수정할 수 없습니다.

Date Object를 이용하여 현재 시간을 표시하도록 만들었으며, 브라우저 Local Storage에 닉네임을 저장할 수 있도록 했습니다.
스탑워치는 setTimeout()을 이용하여 시간이 계속 증가될 수 있도록 하였습니다.
또한, DOM을 이용하여 종목이나 세트 element가 추가되거나 삭제될 수 있도록 제작하였습니다.

시작 화면과 운동이 입력된 화면
운동 시간을 체크하며 진행되는 화면
데스크톱 전체 화면

 

728x90

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

Code

 

최종 제출 답안
벌집 문제 힌트

😢 보자마자 위에서 표시해 놓은 부분들이 눈에 띄었다.
각 범위를 한 바퀴 돌고 다음 범위로 넘어가는 부분인데, 각 수를 계산해보니 6, 12, 18, 24로 등차수열을 이루고 있었다.
그래서 등차수열을 이용해서 푸는 문제인가? 하고 계산식을 넣으려고 하다가 시간을 좀 낭비했다.

😊 패턴을 찾았다면 프로그래밍적으로 단순하게 작성해 나가면 된다.
최소 거리는 1부터 시작할 것이고, 범위도 1부터 시작한다. 
증가하는 범위는 1,(2~)7, (8~)19, (20~)37...이므로 '기존 범위+(count된)최소 거리*6' 이다.
while loop을 이용해 범위가 입력 받은 N보다 작을 때까지 반복해주면 된다.

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

// Honey Comb
 
// 1st Solution - Good
 
// For submit
 
// const fs = require('fs');
// const N = Number(fs.readFileSync('/dev/stdin').toString().trim());
 
// For local test
const N = 58;
let counter = 1;
let range = 1;
 
while (range < N) {
range += counter++ * 6;
}
console.log(counter);
728x90

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

Code

최종 제출 답안

😢 이런저런 조건들을 떠올리다보니 산으로 갔던 문제
역시 조건 그대로 코드를 작성하기 보다는, 다른 시각으로 바라보는 조건이 핵심

😊 가장 최고의 조건을 걸어두고 하나씩 물러나며 최선의 조건을 찾아야한다.

최종 제출 답안)

bigMax 변수에 가장 큰 봉지인 BIG(5)으로 설탕 무게를 나눴을 때, 나오는 숫자를 저장한다.
그리고 bigMax가 음수로 떨어지지 않을 때까지 while loop을 열어준다.

임시로 만든 tempSugar 변수에는 앞에서 계산한 bigMax 무게만큼 SUGAR를 빼준다.
만약 tempSugar가 작은 봉지인 SMALL(3)으로 나눴을 때 나머지가 없다면 최선의 조건이기 때문에 출력하고 계산을 끝내준다.
하지만, 만약 조건에 맞지 않는다면 bigMax를 1만큼 빼준다.
그런 후 tempSugar의 크기를 5만큼 높여주고 다시 3으로 나눠본다.

이런식으로 계속 반복하며 다시 5씩 늘려보고 다시 3으로 나눠봤을 때 나머지가 0이라면 계산이 가능한 설탕 무게이고,
그렇지 않고 bigMax가 음수로 떨어진다면 그건 계산할 수 없는 설탕 무게이므로 -1을 출력한다.

다른 정답자들 중에 배울 수 있었던 답안)

다른 정답자의 답안

😊 먼저, SMALL(3)의 개수를 담아두기 위한 bags 변수를 선언해준다. while loop을 무한으로 돌리면서,
설탕을 BIG(5)으로 나눴을 때 나머지가 0이라면 BIG으로 나눈 값과 bags를 합쳐 출력한다.
그리고 만약 SUGAR가 0이하로 떨어지면 -1을 출력해준다.
둘 다 해당되지 않으면 설탕을 SMALL(3)만큼 빼주고, bags를 1 증가시켜준다. (설탕을 3으로 나눈 것과 같은 의미)

즉, 이것도 역시 최고의 방법인 5를 우선으로 나눠주고, 그게 되지 않는다면 3을 하나씩 늘려가는 방법으로 해결했다.
이것도 굉장히 훌륭한 방법이라고 생각한다.

 

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

// Sugar Delivery
 
// 3rd Solution - Good
 
// For submit
 
// const fs = require('fs');
// let SUGAR = Number(fs.readFileSync('/dev/stdin'));
 
let SUGAR = 11; // 18 4 6 9 11
const BIG = 5;
const SMALL = 3;
 
let bigMax = Math.floor(SUGAR / BIG);
while (bigMax >= 0) {
let tempSugar = SUGAR - bigMax * BIG;
if (tempSugar % SMALL === 0) {
console.log(bigMax + tempSugar / SMALL);
return;
} else {
bigMax--;
}
}
console.log(-1);
 
// 1st Solution
 
// For submit
 
// const fs = require('fs');
// const SUGAR = parseInt(fs.readFileSync('/dev/stdin').toString().trim());
 
// For local test
// const SUGAR = 18; // 18 4 6 9 11
// const BIG = 5;
// const SMALL = 3;
 
// if (SUGAR >= SMALL) {
// let bigMax = Math.floor(SUGAR / BIG);
// if (bigMax <= 0) {
// if (SUGAR % SMALL === 0) {
// console.log(SUGAR / SMALL);
// return;
// } else {
// console.log(-1);
// return;
// }
// } else {
// while (bigMax >= 0) {
// let tempSugar = SUGAR - bigMax * BIG;
// if (tempSugar % SMALL === 0) {
// console.log(bigMax + tempSugar / SMALL);
// return;
// } else {
// bigMax--;
// }
// }
// console.log(-1);
// }
// } else {
// console.log(-1);
// }
 
// 2nd(other solution) - Good
 
// For submit
 
// const fs = require('fs');
// let SUGAR = parseInt(fs.readFileSync('/dev/stdin').toString().trim());
 
// For local test
// let SUGAR = 9; // 18 4 6 9 11
// let bags = 0;
 
// while (true) {
// if (SUGAR % 5 === 0) {
// console.log(SUGAR / 5 + bags);
// break;
// } else if (SUGAR <= 0) {
// console.log(-1);
// break;
// }
// SUGAR = SUGAR - 3;
// bags++;
// }
728x90

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

Code

https://github.com/DasolPark/Algorithm_JavaScript/blob/37d399b654275b31f94815eb86c2853ec8cc5b1b/Baekjoon/1712.js

😢 21억 조건을 못 보고 반복문을 돌려 counter를 하나씩 증가시키려고 했다.. 잘못된 방법!

😊 역시나 수학 카테고리답게 다항식을 이용해서 풀면 쉽게 풀 수 있다.
A는 고정 비용, B는 가변 비용, C는 판매 가격이다.
판매 누적 금액고정비용+가변 누적 비용을 넘어서면 손익분기점을 넘어간다.
식을 만들어 본다면, A + Bx < Cx로 만들 수 있다. 
식을 정리해보자. A < Cx - Bx로 Bx를 넘겨주고, A < (C-B)x 로 정리해주면 조금 더 보기 쉽다.
즉, C-B가 0이하(즉, 0 또는 음수)로 떨어지면 손익분기점은 없다. 계속 적자다..ㅎㅎ

손익분기점이 없어서 '-1'을 출력하는 조건문은 2가지 정도로 표현할 수 있다.
1. if(C-B <= 0) { console.log(-1); }
A < (C-B)x 식을 생각해서 C-B가 0이하면 손익분기점은 없다고 표현할 수 있다.
2. if(C <= B) { console.log(-1); }
C-B > 0이 돼야하므로, C <= B으로 정리해주면 손익분기점이 없다고 표현할 수 있다.

Full Code

// Break-Even Point
 
// 1st Solution(other)
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split(' ');
 
// For local test
const input = ['1000', '70', '170'];
const A = parseInt(input.shift());
const B = parseInt(input.shift());
const C = parseInt(input.shift());
const netProfit = C - B;
 
if (netProfit <= 0) {
console.log(-1);
} else {
console.log(Math.floor(A / netProfit) + 1);
}
 
// 2nd Solution(ohter)
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split(' ').map(num => parseInt(num));
 
// For local test
// const input = ['1000', '70', '170'].map(num => parseInt(num));
// const A = input.shift();
// const B = input.shift();
// const C = input.shift();
 
// if (C <= B) {
// console.log(-1);
// } else {
// console.log(Math.floor(A / (C - B)) + 1);
// }
728x90

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

Code

https://github.com/DasolPark/Algorithm_JavaScript/blob/a283e8643975b13a658de279d66a7d2f989d9cab/Baekjoon/1316.js

😢 간단한 문제지만, 어떻게 하면 효율적으로 풀 수 있을까 고민했던 문제. 결과적으로 그다지 효과적이지 않은..

😊 결국 중첩 for loop을 이용해서 각 word의 문자를 체크하는 방법으로 풀었다.
Object를 하나 만들어주고, 해당 문자가 이미 사용되었다면 charMap에 '문자': true로 넣어주었다.
만약 charMap에 이미 해당 문자가 있다면 해당 word의 index-1과 같은지 비교해주었다.
같다면 그룹단어, 그렇지 않다면 더 이상 검사할 필요가 없기 때문에 counter를 감소시켜주고, break으로 내부 for loop을 끝냈다.

다른 정답자들의 풀이도 좋은 소스가 되었다.

Full Code

// Group Word Checker
 
// 3rd Solution
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
 
// For local test
// const input = ['3', 'happy', 'new', 'year'];
const input = ['4', 'aba', 'abab', 'abcabc', 'a'];
const N = parseInt(input.shift());
let counter = N;
 
for (let i = 0; i < N; i++) {
const charMap = {};
for (let j = 0; j < input[i].length; j++) {
if (!charMap[input[i][j]]) {
charMap[input[i][j]] = true;
} else if (input[i][j] !== input[i][j - 1]) {
counter--;
break;
}
}
}
 
console.log(counter);
 
// 1st Solution
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
 
// For local test
// const input = ['3', 'happy', 'new', 'year'];
// const input = ['4', 'aba', 'abab', 'abcabc', 'a'];
// const N = parseInt(input[0]);
// let counter = N;
 
// for (let i = 1; i <= N; i++) {
// const charMap = {};
// for (let j = 0; j < input[i].length; j++) {
// if (!charMap[input[i][j]]) {
// charMap[input[i][j]] = true;
// } else if (charMap[input[i][j]] && input[i][j - 1] === input[i][j]) {
// continue;
// } else {
// counter--;
// break;
// }
// }
// }
// console.log(counter);
 
// 2nd solution(other)
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
 
// For local test
// const input = ['3', 'happy', 'new', 'year'];
// const input = ['4', 'aba', 'abab', 'abcabc', 'a'];
// const N = parseInt(input.shift());
// let counter = 0;
 
// function checkGroupWord(str) {
// const checker = [];
 
// for (let i = 0; i < str.length; i++) {
// if (checker.indexOf(str[i]) === -1) {
// checker.push(str[i]);
// } else {
// if (checker[checker.length - 1] !== str[i]) {
// return;
// }
// }
// }
// counter++;
// }
 
// for (let i = 0; i < N; i++) {
// checkGroupWord(input[i]);
// }
 
// console.log(counter);
728x90

Linked List의 정의(Definition of Linked List)

Linked Lists Data Structure Image

🎈 위 그림에서 볼 수 있듯, Linked List는 기본적으로 NodeHead(or Tail까지)로 구성되어 있다.
NodeDataNext로 구성되어 있는데, Data는 해당 노드의 데이터 Next는 다음 Node를 가리키는 Reference를 가지고 있다.
그리고 Linked List의 맨 앞 Node는 Head가 가리키며, 맨 끝 Node는 Tail이 가리키고 있다.

Linked Lists의 method는 만들기 나름이지만, 이 글에서는 insertFirst(data), size(), getFirst(), getLast(), clear(), removeFirst(), removeLast(), insertLast(data), getAt(index), removeAt(index), insertAt(data, index) 를 다뤄볼 것이다.

https://github.com/DasolPark/Algorithm_DataStructure_JavaScript-Stephen-/blob/master/completed_exercises/linkedlist/directions.html
(자세한 Node class API, LinkedList class API 내용은 위 링크를 확인해주세요)

JavaScriptclass를 이용하여 NodeLinked List를 만들어보겠다.

Node class

😐 Node class는 위처럼 data, next로 구성했다. next는 값이 언제 들어올지 모르므로 default 설정해준다.
(default가 궁금하다면 JavaScript - ES2015를 참고해주세요)

Linked List class 1

😐 Linked List의 constructor()는 head만 선언해주었다. this.head의 시작은 항상 null.

insertFirst() method가장 첫 번째 list에 Node를 생성해 준다.
가장 첫 번째 List에 넣어줘야하므로, this.head에 Node를 생성해준다. 기존에 첫 번째 값이 존재할 수 있으므로, next에는 this.head를 넣어줘서, 이전에 this.head가 가리키고 있던 (과거)첫 번째 노드를
새로 만든 첫 번째 Node가 가리킬 수 있도록 reference를 재설정해준다.

size() methodlist의 크기를 알려준다.
while loop을 이용해 node를 끝까지 탐색하게 해주고, node를 이동할 때마다 counter를 1개씩 증가시켜주면 된다.

getFirst() methodlist의 첫 번째 node를 반환한다.
간단하게, this.head를 반환해주면 된다. 만약 list가 비어있다면 null이 반환될 것이다.

getLast() methodlist의 마지막 node를 반환한다.
if 조건문을 이용해, list가 비어있다면 null을 반환해준다.
비어있지 않다면, while loop을 이용해 node를 끝까지 탐색하여 마지막 node를 반환해준다.
여기서 중요한 것은 while loop안에 if 조건문으로, 탐색중인 node의 다음 node가 없다면,
해당 node가 마지막이므로 바로 반환
할 수 있도록 작성해주는 것이다.

clear() methodlist를 초기화한다.
this.head = null;을 작성해주면 간단하게 해결할 수 있다.

Linked List class 2

removeFirst() method가장 첫 번째 node를 제거해준다.
this.head첫 번째 node를 가리키고 있고, this.head.next두 번째 node를 가리키고 있다.
따라서, this.head에 두 번째 노드인 this.head.next를 넣어주면, 첫 번째 노드는 제거된다.
(list 그림을 상상해야한다. head가 첫 번째 노드를 가리키다가, 두 번째 노드를 가리킨다고 생각하면 된다)

removeLast() method가장 마지막 node를 제거해준다.
list가 비어있을 경우, list에 node가 하나일 경우를 먼저 조건문으로 처리해줘야 한다.
(previous와 node를 사용할 것이므로 적어도 node가 2개 이상 돼야 한다.)
탐색을 하기 전에, 제거할 node의 이전 node를 가리키는 previous, 제거할 node인 node를 선언해준다.
while loop안에서 지금까지 해왔던 탐색과 마찬가지로 node를 이용해 마지막 node를 찾은 후,
previous.next에 null을 넣어줘서 마지막 node를 제거해준다.

insertLast(data) methodlist의 가장 마지막에 node를 생성해 준다.
직접 작성해줄 수도 있겠지만, 여기서 이전에 작성한 method를 재사용해줄 수 있다. 바로 getLast() method다.
마지막 node를 찾아줄 getLast()를 사용하고, 만약 last가 있다면 last의 다음에 node를 생성해주고,
만약 last가 없다면 list가 비었다는 것이므로, this.head에 node를 생성해주면 된다.

Linked List class 3

getAt(index) method원하는 index의 node를 찾아준다.
size() method를 작성할 때와 비슷하게, counter를 선언해주고 while loop을 이용해 탐색한다.
while loop 안에서 if 조건문을 이용해 만약 index와 counter가 같다면 해당 node를 반환해준다.
while loop 안에서 못 찾았다면, index값이 list의 개수를 벗어나거나, list가 비어있는 것이므로 null을 return해준다.

removeAt(index) method해당 index의 node를 제거해준다.
해당 node를 제거하려면 이전 node도 알아야하기 때문에 적어도 node가 2개 이상이어야 한다.
따라서 list가 비어있을 경우list에 node가 1개만 있을 경우를 조건문으로 처리해준다.
그리고 여기서도 기존 method를 재사용할 수 있다. 바로 this.getAt(index)이다.
this.getAt(index-1)을 이용해 previous를 찾아내고, previous가 탐색 범위가 넘어갔을 경우를 조건문으로 처리해준다.
!previous는 아예 범위가 벗어난 경우, !previous.next는 previous는 찾아냈지만, previous가 마지막 node인 경우다.
만약 위의 조건문에 걸리지 않는다면,
정상적으로 해당 node 제거가 가능하다는 것이므로, previous.next에 previous.next.next를 넣어준다.
이렇게 처리해주면, previous와 previous.next.next 사이에 있던 node를 제거할 수 있다.

insertAt(data, index) method해당 index에 node를 생성해준다.
여기서도 해당 index의 이전 node를 가리키는 previous를 사용해줘야 하기 때문에,
list가 비어있을 경우, list에 node가 1개만 있을 경우를 조건문으로 처리해준다.
이전과 다르게, 위의 조건문에 걸렸을 경우에는 바로 node를 생성해주고 return한다.
여기서는 2개의 기존 method를 재사용해줄 수 있다. 바로 getAt()getLast()이다.
getLast()를 사용하면 insertAt에 list의 범위를 넘어간 index를 넣었을 때, list의 가장 마지막에 node를 생성해줄 수 있다.
previous.next를 가리키는 node를 생성해주고, previous.next에 새로운 node를 넣어주면 된다.
(머릿속으로 Linked List이미지를 상상하자)

🎉 위의 방법으로 JavaScript를 이용해 Linked List를 작성해줄 수 있다.
다음 글에서는 Linked List를 이용한 Algorithm들을 살펴보겠다.

Full Code

class Node {
constructor(data, next = null) {
this.data = data;
this.next = next;
}
}
 
class LinkedList {
constructor() {
this.head = null;
}
 
insertFirst(data) {
this.head = new Node(data, this.head);
}
 
size() {
let counter = 0;
let node = this.head;
 
while (node) {
counter++;
node = node.next;
}
 
return counter;
}
 
getFirst() {
return this.head;
}
 
getLast() {
if (!this.head) {
return null;
}
 
let node = this.head;
while (node) {
if (!node.next) {
return node;
}
node = node.next;
}
}
 
clear() {
this.head = null;
}
 
removeFirst() {
if (!this.head) {
return;
}
 
this.head = this.head.next;
}
 
removeLast() {
if (!this.head) {
return;
}
 
if (!this.head.next) {
this.head = null;
return;
}
 
let previous = this.head;
let node = this.head.next;
while (node.next) {
previous = node;
node = node.next;
}
previous.next = null;
}
 
insertLast(data) {
const last = this.getLast();
 
if (last) {
// There are some existing nodes in our chain
last.next = new Node(data);
} else {
// The chain is empty!
this.head = new Node(data);
}
}
 
getAt(index) {
let counter = 0;
let node = this.head;
while (node) {
if (counter === index) {
return node;
}
 
counter++;
node = node.next;
}
return null;
}
 
removeAt(index) {
if (!this.head) {
return;
}
 
if (index === 0) {
this.head = this.head.next;
return;
}
 
const previous = this.getAt(index - 1);
if (!previous || !previous.next) {
return;
}
previous.next = previous.next.next;
}
 
insertAt(data, index) {
if (!this.head) {
this.head = new Node(data);
return;
}
 
if (index === 0) {
this.head = new Node(data, this.head);
return;
}
 
const previous = this.getAt(index - 1) || this.getLast();
const node = new Node(data, previous.next);
previous.next = node;
}
 
forEach(fn) {
let node = this.head;
let counter = 0;
while (node) {
fn(node, counter);
node = node.next;
counter++;
}
}
 
*[Symbol.iterator]() {
let node = this.head;
while (node) {
yield node;
node = node.next;
}
}
}
728x90

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

Code

https://github.com/DasolPark/Algorithm_JavaScript/blob/89a6bd743bd70a7b83988da93eca0436672e31e4/Baekjoon/2941.js

😢 단순 조건문 처리로는 풀기 싫어서, 어렵게 풀려다가 생각하는 시간이 조금 걸렸다.
그리고 문제를 보자마자 Regular Expression이 떠올라서, RegExp로 풀려고 공부를 조금 했다.

😊 조건문으로만 풀기에는 뭔가 문제가 아까웠다. 그래서 이런 방법 저런 방법을 시도해봤다. (물론 단순 조건으로도 풀어봤다)

regex변수크로아티아 알파벳 조건들을 입력해주고 replace() 에 주입하여, 만약 일치하는 것이 있다면 공백(' ')으로 만들어줬다.
RegExp 구성을 살펴보겠다. 아주 간단하다.
=, -와 같은 문자들은 특수문자이기 때문에 특별하다는 뜻으로 \(backslash, escape라고도 부른다)를 앞에 붙여줘야 하고,
그 외 조건들은 |(or)문자를 사용해서 구분해주었고, g를 붙여 Global search를 해줬다.

결과적으로 2개 이상 문자를 갖는 크로아티아 알파벳은 공백으로 변경되어 1개의 문자를 갖게 된다.
따라서 결과의 length를 출력해주면 크로아티아 알파벳의 개수를 알 수 있다.
(조건 외의 알파벳은 1개로 치니까 따로 처리하지 않는다)

Full Code단순 조건문 처리로 푼 예제도 있으니 참고하길 바란다.

✔ String.prototype.replce()

크로아티아 알파벳만의 조건을 넣어서, 공백(' ')으로 변경해주기 위해 사용했다.

✔ Regular Expressions

문자열을 다루기 위한 정규표현식이다. 크로아티아 알파벳 조건을 표현하기 위해 사용하였다.

위의 Skill들은 JavaScript - helper methods 카테고리에서 간단한 사용방법을 확인할 수 있다.

Full Code

// Croatia Alphabet
 
// 1st Solution(Regular Expressions)
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim();
 
// For local test
const input = 'ljes=njak';
 
var regex = /c\=|c\-|dz\=|d\-|lj|nj|s\=|z\=/g;
const result = input.replace(regex, ' ');
 
console.log(result.length);
 
// 2nd Solution(while, idx, if else)
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim();
 
// For local test
// const input = 'ljes=njak';
// let idx = 0;
// let counter = 0;
 
// while (idx < input.length) {
// if (
// input[idx] === 'c' &&
// (input[idx + 1] === '=' || input[idx + 1] === '-')
// ) {
// idx += 2;
// counter++;
// } else if (
// input[idx] === 'd' &&
// input[idx + 1] === 'z' &&
// input[idx + 2] === '='
// ) {
// idx += 3;
// counter++;
// } else if (input[idx] === 'd' && input[idx + 1] === '-') {
// idx += 2;
// counter++;
// } else if (
// input[idx + 1] === 'j' &&
// (input[idx] === 'l' || input[idx] === 'n')
// ) {
// idx += 2;
// counter++;
// } else if (input[idx] === 's' && input[idx + 1] === '=') {
// idx += 2;
// counter++;
// } else if (input[idx] === 'z' && input[idx + 1] === '=') {
// idx += 2;
// counter++;
// } else {
// idx++;
// counter++;
// }
// }
 
// console.log(counter);
 
// 3rd Solution(shift, while, if else)
 
// For submit
 
// const fs = require('fs');
// const str = fs.readFileSync('/dev/stdin').toString().trim().split('');
 
// For local test
// const str = 'ljes=njak'.split('');
// let counter = 0;
 
// while (str.length) {
// if (str[0] === 'c' && (str[1] === '=' || str[1] === '-')) {
// counter++;
// str.shift();
// str.shift();
// } else if (str[0] === 'd' && str[1] === 'z' && str[2] === '=') {
// counter++;
// str.shift();
// str.shift();
// str.shift();
// } else if (str[0] === 'd' && str[1] === '-') {
// counter++;
// str.shift();
// str.shift();
// } else if (str[1] === 'j' && (str[0] === 'l' || str[0] === 'n')) {
// counter++;
// str.shift();
// str.shift();
// } else if (str[0] === 's' && str[1] === '=') {
// counter++;
// str.shift();
// str.shift();
// } else if (str[0] === 'z' && str[1] === '=') {
// counter++;
// str.shift();
// str.shift();
// } else {
// counter++;
// str.shift();
// }
// }
 
// console.log(counter);
728x90

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

Code

https://github.com/DasolPark/Algorithm_JavaScript/blob/9c69b97d5fdc20167e9804bf0d73d8245c73732e/Baekjoon/5622.js

😢 알파벳을 직접 손으로 입력하고 싶지 않았고, Object로 value(각 지연 시간)까지 넣어서 진행하고 싶었다.
큰 어려움은 없었고, 중심을 Object로 만들고 푸는 과정에서 어떻게 진행할지 조금 고민했다.

😊 'A'부터 'Z'까지 진행하는 for loop을 열고, 'PQRS', 'WXYZ'는 예외로 들어가도록 조건문을 걸어주었다.
( i !== 'R'charCodeAt(0) && i !== 'Y'.charCodeAt(0) )으로 조건을 넣어준 이유는,
'PQRS', 'WXYZ' 이 2가지만 제외하면 모두 길이가 3이다. 그래서 길이 3으로 저장되기 전인 R or Y에서 저장을 차단하고,
앞의 두 문자가 각각 합쳐져 길이가 4가 되었을 때 key로 저장되도록 했다.

Object를 만들어준 후에, 입력 받고 split('')한 값에 reduce달았고, 안에 Object를 반복하는 for ... in loop을 열어주었다.
그렇게 입력받은 값 중각 key에 해당하는 문자가 있다면, acc에 해당 key의 value를 중복 저장해주고 return 해주었다.
결과적으로 result값에 전화를 걸기 위해 필요한 시간이 저장된다.

다른 풀이도 확인해보았지만, 대부분 직접 알파벳을 입력해서 사용하였고, 특별히 다른 점을 찾지 못 했다.

✔ Object {}

{ 'ABC' : 3, 'DEF': 4 ... } 이런 식으로 전체 알파벳을 저장하기 위해 작성하였다.

✔ charCodeAt()

해당 알파벳의 ASCII Code(숫자)를 알아내서 for loop을 이용하기 위해 사용하였다.

✔ String.fromCharCode()

()안에 ASCII코드를 넣어서 문자를 가져오기 위해 사용하였다.

✔ reduce

전화를 걸기 위해 필요한 시간을 중복 저장하기 위해 사용하였다.

✔ for ... in

Object의 key을 가져오는 for loop을 이용하기 위해 사용하였다.

위의 Skill들은 JavaScript - Helper methods or Grammar 카테고리에서 간단한 사용방법을 확인할 수 있다.

Full Code

// 2nd Solution
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim();
 
// For local test
const input = 'UNUCIC';
const splitInput = input.split('');
const charMap = {};
let charStack = '';
let counter = 3;
 
for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) {
charStack += String.fromCharCode(i);
 
if (
charStack.length === 3 &&
i !== 'R'.charCodeAt(0) &&
i !== 'Y'.charCodeAt(0)
) {
charMap[charStack] = counter;
counter++;
charStack = '';
} else if (charStack.length === 4) {
charMap[charStack] = counter;
counter++;
charStack = '';
}
}
 
const result = splitInput.reduce((acc, char) => {
for (let stage in charMap) {
if (stage.includes(char)) {
acc += charMap[stage];
}
}
return acc;
}, 0);
 
console.log(result);
 
// 1st Solution
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim();
 
// For local test
// const input = 'UNUCIC';
// const splitInput = input.split('');
// const charMap = {};
// let charStack = '';
// let counter = 3;
 
// for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) {
// charStack += String.fromCharCode(i);
 
// if (
// charStack.length === 3 &&
// i !== 'R'.charCodeAt(0) &&
// i !== 'Y'.charCodeAt(0)
// ) {
// charMap[charStack] = counter;
// counter++;
// charStack = '';
// } else if (charStack.length === 4) {
// charMap[charStack] = counter;
// counter++;
// charStack = '';
// }
// }
 
// let eachTime = 0;
// const result = splitInput.map(char => {
// for (let stage in charMap) {
// if (stage.includes(char)) {
// eachTime += charMap[stage];
// }
// }
// return eachTime;
// });
 
// console.log(result[result.length - 1]);
728x90

스택의 정의(Definition of Stack)

Stack Data Structure Image

🎈 위 그림에서 볼 수 있듯, Stack의 실행순서는 LIFO로 진행된다.
LIFO란 Last In First Out의 약자로서, 마지막으로 들어간 값이 가장 먼저 나올 수 있다. 프링글스 과자를 생각하면 쉽다.

Stack은 기본적으로 추가( push() ), 삭제( pop() ) 기능을 사용하여 다루며,
마지막 값 보기( peek() ) 기능처럼 본인이 필요한 기능을 만들어 사용하면 된다.

JavaScriptclass를 이용하여 Stack을 만들어 보겠다.

https://github.com/DasolPark/Algorithm_DataStructure_JavaScript-Stephen-/blob/master/completed_exercises/stack/index.js

😐 위에서 볼 수 있듯, Stack의 전체 뼈대는 생성자(constructor)를 이용하여 array를 선언해준다.

Array의 helper methods

add()에서는 Array.prototype.push()를 그대로 이용하여, 값이 항상 Stack의 뒤쪽으로 들어가게 구성해준다.

pop()에서도 Array.prototype.pop()를 그대로 이용하여, 항상 (나중에 들어간)마지막 값이 나올 수 있게 구성한다.

peek()에서는 index에 [this.data.length-1]을 넣어줘서 값이 있다면 마지막 값을, 없다면 undefined를 return하게 해준다.

🎉이렇게 class를 작성해주면, LIFO(Last In First Out)기능을 하는 기본 Stack을 만들어낼 수 있다.

다음 글에서는 2개의 스택(Stack)을 사용하여 하나의 큐(Queue)처럼 사용하는 큐(Queue)를 만들어보겠다.

Full Code

class Stack {
constructor() {
this.data = [];
}
 
push(record) {
this.data.push(record);
}
 
pop() {
return this.data.pop();
}
 
peek() {
return this.data[this.data.length - 1];
}
}
728x90

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

Code

https://github.com/DasolPark/Algorithm_JavaScript/blob/ebb4130f5a91e299f73bbe1e4e6d7986538d6e2b/Baekjoon/2908.js

😢 순서를 뒤바꾸는 방법으로 간단하게 푼 문제(Reverse Int or String Algorithm 참고)

😊 입력값으로 받은 숫자 StringArray로 나누고(split('')) reduce를 이용하여 순서를 뒤바꿔 줬다.
그런 후 각 세자리 숫자만큼 나눠서(split(' ')) 배열에 저장하고 Math.max.apply()를 이용해 더 큰 값을 구해줬다.
(아래 Full Code를 참고하면, reduce를 쓰지않고 다른 방법을 사용하여 푼 예제를 볼 수 있다)

✔ String.prototype.split('')

element 하나하나씩 나눠서 배열로 return해줬다. ( [ '7', '3', '4', ' ', '8', '9', '3' ] )

✔ Array.prototype.reduce()

안에 순서를 뒤바꾸는 reduce function을 주입하여 return해줬다. ( '398 437' )

✔ String.prototype.Split(' ')

가운데 공백(space)을 이용해 세자리 숫자씩 각각 나눠줬다. ( [ '734', '839' ] )

✔ Math.max.apply()

apply()에 숫자를 넣어서 max(더 큰)값을 구해줬다

위의 Skill들은 JavaScript - helper methods 카테고리에서 간단한 사용방법을 확인할 수 있다.

Full Code

// 2nd Solution(reduce(), Math.max.apply())
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim();
 
// For local test
const input = '734 893';
const revEntire = input.split('').reduce((rev, numChar) => numChar + rev, '');
const eachNumArr = revEntire.split(' ');
const max = Math.max.apply(null, eachNumArr);
 
console.log(max);
 
// 1st Solution(reduce, Math.max.apply())
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim();
 
// For local test
// const input = '734 893';
// const reverseInt = input
// .split('')
// .reduce((rev, num) => {
// return num + rev;
// }, '')
// .split(' ');
// const max = Math.max.apply(null, reverseInt);
 
// console.log(max);
 
// 3rd Solution(for...of, No Math.max())
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim();
 
// For local test
// const input = '734 893';
// let rev = '';
 
// for (let numChar of input) {
// rev = numChar + rev;
// }
 
// const eachNumArr = rev.split(' ').map(num => parseInt(num));
// let max = 0;
 
// for (let i = 0; i < eachNumArr.length; i++) {
// if (eachNumArr[i] > max) {
// max = eachNumArr[i];
// }
// }
 
// console.log(max);
 
// 4th Solution(reverse())
 
// For submit
 
// const fs = require('fs');
// const input = fs.readFileSync('/dev/stdin').toString().trim();
 
// For local test
// const input = '734 893';
// let rev = input
// .split('')
// .reverse()
// .join('');
 
// const eachNumArr = rev.split(' ').map(num => parseInt(num));
// let max = 0;
 
// for (let i = 0; i < eachNumArr.length; i++) {
// if (eachNumArr[i] > max) {
// max = eachNumArr[i];
// }
// }
 
// console.log(max);

+ Recent posts