해당 글은 Jekyll 기반 GitHub Blog 중심으로 작성한 내용입니다.
블로그를 운영한 지 이제 24일이 지났을 쯤에, 내 GitHub Blog에 수정할 부분이 뭐가 있는지 자세히 확인해봤다.
기존에 댓글 기능을 Disqus을 사용했는데, 몇 가지 단점들이 보이기 시작했다.
무료 라이센스로 사용하는 경우 광고가 붙어서 다른 사용자가 보기 불편하다는 생각이 들었다.
Disqus 자체가 무겁다는 얘기가 주변 개발자들로부터 전해들었다.
댓글을 입력하려면 Disqus 자체 회원가입을 해야 하거나, 깃허브 계정이 아닌 페이스북, 트위터, 구글 계정으로 로그인 해야하는 불편함이 있었다.
내 GitHub Blog 에만 존재할 수도 있는데, 스크롤을 맨마지막까지 내리면 해당 댓글 창이 사라지는 것을 확인했다.
utterances
라는 것을 발견하게 되었다.GitHub issues를 기반으로 하는 가벼운 댓글 위젯이다.
블로그 댓글, 위키(wiki) 페이지 등에 해당 위젯을 사용할 수 있다.
(해당 앱에 대한 자세한 설명은 여기에 가보시면 확인할 수 있습니다)
이미 설치된 경우 Configure
버튼으로 보이는데, 설치되지 않았다면 Install
버튼이 보일 것이다.
해당 Install
버튼을 클릭하면 repository(저장소)를 선택하는 화면이 나오는데, GitHub Blog repository(저장소)를 선택하면 된다.
그리고 아래의 Install
버튼을 클릭하여 설치를 완료한다.
repo:
아래 입력 칸에는 본인의 “Github-ID/GitBlog-repository name”을 입력하면 된다.
예) devfancy/devfancy.github.io
Blog Post ↔️ Issue Mapping
밑에는 블로그 Posts와 깃허브 Issues를 연동하기 위해 선택하는 항목들이다.
누군가가 나의 Post에 댓글을 입력하면 해당 Post의 제목과 경로(URL)를 Issues에 표기하기 위해 첫 번째 부분을 선택했다.
Issue Label
에는 밑에 나와있는 설명대로 Issue 부분에 Label 이름을 정하는 건데, 선택 사항이므로 안해도 상관 없다.Theme
에는 댓글에 대한 배경 색상을 정하는 부분이다. 어두운 색상 / 밝은 색상 / 그외 다양한 색상 이 있기 때문에, 본인이 원하는 색상을 선택하면 된다.
나는 밝은 색상을 선택했다.
Enable Utterances
의 의미는 나의 블로그 탬플릿에 해당 utterances
를 적용하는 부분이다.
구글링을 한 결과, 대부분 본인의 GitHub Blog 폴더의 _layout/post.html
혹은 _includes/comments.html
에 해당 스크립트를 추가하였다.
나는 내 GitHub Blog 구조상 더 적절한 _includes/comments.html
에 추가하였다.
(본인의 GitHub Blog 구조에 맞게 추가하는 것이 중요하다)
기존에 나는 disqus 를 적용하였기 때문에 해당 부분을 주석처리하고 그 밑에 utterances
부분을 추가하였다.
<!-- -->
<!-- utterances comment -->
<script src="https://utteranc.es/client.js"
repo="devfancy/devfancy.github.io"
issue-term="pathname"
label="comments"
theme="github-light"
crossorigin="anonymous"
async>
</script>
이제 GitHub repository에 utterances
을 반영(적용) 하면 끝이다.
Git Desktop이 설치가 이미 되었다면, 커밋 내용을 입력하고 push 하면 된다.
Git Desktop이 설치 되지 않았다면, IntelliJ - 본인의 GitHub Blog 폴더 열기 - 터미널 열기
하고 다음 명령어를 입력하면 된다. (Git 명령어 직접 입력)
메모리: 메모리: 52 MB, 시간: 1.57 ms - Answer Code1
코딩테스트 연습 > 연습문제
import java.util.Arrays;
class Solution
{
public int solution(int []A, int []B)
{
int answer = 0;
// 기본 정렬 조건 : 오름차순
Arrays.sort(A);
Arrays.sort(B);
for(int i = 0; i < A.length; i++) {
answer += A[i] * B[B.length - 1 - i];
}
return answer;
}
}
양쪽에서 각각 한개의 숫자를 뽑아 곱한 값을 누적하였을 때 한 쪽의 최댓값과 다른 쪽의 최솟값을 곱하는 경우 누적값을 최소로 구할 수 있다
정렬을 하기 위해서는 import java.util.Arrays;
선언해야 한다.
Arrays.sort()
: 기본 정렬 조건이 오름차순 이다.
따라서 A와 B 배열을 정렬하여 한 쪽의 최댓값과 다른 쪽의 최솟값을 곱해 누적하면 최소값을 구할 수 있다
최솟값을 구하는 조건을 바로 떠올리지 않아서 시간이 좀 걸렸지만, 조건만 알 수 있으면 바로 풀 수 있는 문제였다.
최솟값을 구하는 조건에 대해서 잘 기억해두자.
메모리: 52.8 MB, 시간: 19.78 ms - Answer Code1
메모리: 53.1 MB, 시간: 7.90 ms - Answer Code2
코딩테스트 연습 > 스택/큐
import java.util.*;
class Solution {
boolean solution(String s) {
// [1] 정답을 저장할 변수로 answer와 stack을 선언
boolean answer = true;
Stack <Character> stack = new Stack<>();
// 반복문을 이용하여 문자열을 앞에서부터 비교
for(int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// [2] 문자를 비교할 때 `(` 일 경우 스택에 push
if(c == '(') {
stack.push(c);
}
// [3] `)`일 경우
if( c == ')') {
// stack의 크기가 0이면 false 반환
if(stack.size() == 0) {
answer = false;
}
// stack의 크기가 0이 아니라면 `(`가 있다는 의미이므로 스택에 pop
else {
stack.pop();
}
}
}
// [4] 문자열을 끝까지 확인한 이후에 스택의 크기가 0이면 true 반환
if(stack.size() != 0) {
answer = false;
}
return answer;
}
}
스택을 이용하여 괄호가 짝을 이룬다면 스택을 제거한다.
문자열을 끝까지 검사했을 때 스택의 크기가 0이면 올바른 괄호이므로 true를 반환하고, 그렇지 않으면 false를 반환한다.
[1] 정답을 저장할 변수로 answer와 stack을 선언하고, 반복문을 이용하여 문자열을 앞에서부터 비교한다.
[2] 문자를 비교할 때 (
일 경우 스택에 push 한다.
[3] )
일 경우 이때, stack의 크기가 0이 아니라면 스택에 pop 한다.
(
가 있다는 의미이고, 스택의 크기가 0이라면 (
가 없으므로 짝을 이룰 수 없다.[4] 문자열을 끝까지 확인한 이후에 스택의 크기가 0이면 true, 아니면 false를 return 한다.
class Solution {
boolean solution(String s) {
boolean answer = false;
int count = 0;
for(int i = 0; i<s.length();i++){
if(s.charAt(i) == '('){
count++;
}
if(s.charAt(i) == ')'){
count--;
}
if(count < 0){
break;
}
}
if(count == 0){
answer = true;
}
return answer;
}
}
(2번째 풀이) 다른 사람의 풀이를 가져와봤는데, 스택을 사용안하면서 count 변수를 사용하여 깔끔하게 풀이했다.
그 결과 1번째 풀이보다 시간적인 측면에서 3배 가까이 시간을 절약하는 것을 볼 수 있었다.
스택을 사용한다고 해서 좋은 정답은 아니라는 것을 알 수 있었다.
메모리: 86.2 MB, 시간: 4.88 ms - Answer Code1
코딩테스트 연습 > 연습문제
import java.util.*;
class Solution {
public String solution(String str) {
String answer = "";
// 1. 공백을 기준으로 문자열을 잘라서 String 배열에 저장
String [] strArr = str.split(" ");
// 2. 잘린 String 배열을 순서대로 처리
for(int i = 0; i < strArr.length; i++) {
String now = strArr[i];
// 문자열의 길이가 0이면 " " 추가
if(strArr[i].length() == 0) {
answer += " ";
}
// 문자열의 길이가 있다면
else {
// 첫번째 문자는 소문자 -> 대문자로 변환
answer += now.substring(0, 1).toUpperCase();
// 나머지 문자는 대문자 -> 소문자로 변환
answer += now.substring(1, now.length()).toLowerCase();
// 단어 사이에 공백을 위해 마지막에 `" "`을 추가
answer += " ";
}
}
// 3. 입력 받은 문자열의 맨 마지막이 " "이라면(기존에 있었던 공백이면), 바로 answer 반환
if(str.substring(str.length()-1, str.length()).equals(" ")) {
return answer;
}
// 4. 입력 받은 문자열의 맨 마지막이 `" "`이 아니라면 해당 부분을 제거하고 반환
return answer.substring(0, answer.length()-1);
}
}
기존 문자열 이름인 str 을 split(" ")
을 사용하여 공백을 기준으로 잘라서 String 배열에 저장한다.
잘린 String 배열을 순서대로 처리한다.
첫 번째 문자와 나머지 문자를 나눈다 -> substring()
첫 번째만 대문자로, 나머지는 소문자로 변환한다.
toUpperCase() : 소문자 -> 대문자
toLowerCase() : 대문자 -> 소문자
단어 사이에 공백을 위해 마지막에 " "
을 추가한다.
입력 받은 문자열의 맨 마지막이 " "
이라면(기존에 있었던 공백이면), 바로 answer을 반환한다.(마지막 공백을 지우지 않는다)
입력 받은 문자열의 맨 마지막이 " "
이 아니라면 해당 부분을 제거하고 반환한다.
첫 번째 부분과 나머지 부분을 구분하는 경우에는 substring()
을 사용하자.
소문자와 대문자간 변환할 때 쓰이는 toUpperCase()
, toLowerCase()
에 대해 다시 공부하게 되었고,
(중요) 문제풀이 - 3번째 조건 부분이 없으면 테스트케이스 부분이 실패로 되버렸다.
메모리: 83.7 MB, 시간: 28.33 ms - Answer Code1
메모리: 87.1 MB, 시간: 9.33 ms - Answer Code2
코딩테스트 연습 > 연습문제
import java.util.*;
class Solution {
public String solution(String s) {
String answer = "";
ArrayList<Integer> arr = new ArrayList<Integer>();
String [] str = s.split(" ");
for(int i = 0; i < str.length; i++) {
arr.add(Integer.parseInt(str[i]));
}
answer = "" + Collections.min(arr) + " " + Collections.max(arr);
return answer;
}
}
import java.util.*;
class Solution {
public String solution(String s) {
int max, min, n;
String [] str = s.split(" ");
max = min = Integer.parseInt(str[0]);
for(int i = 0; i < str.length; i++) {
n = Integer.parseInt(str[i]);
if(max < n) max = n;
if(min > n) min = n;
}
return min + " " + max;
}
}