0%

해시뱅?

얼마 전 신기한 URL을 봤다.

1
2
3
www.test.com/#/
www.test.com/#/settings
www.test.com/#/register

이런 식으로 URL에 #이 붙는 것이다. 처음에는 뭔지 몰라 그냥 지나갔는데 오늘 이것의 정체가 해시뱅이라는 것을 알게 되었다. 샵 다음에 느낌표(#!)를 붙이기도 하나 보다. 이름부터가 해시뱅(#!)인 걸 보면… 아무튼 해시뱅은 이 블로그에 엄청나게 자세히 설명이 되어 있다.

블로그 글을 요약하자면, 해시뱅을 사용하는 이유는 단일 페이지 애플리케이션(SPA) 구현을 위해서다. 해시뱅을 사용하면 페이지 갱신 없이 URL을 변경할 수 있다. 정확히는 변경되는 것처럼 보이는 거지만. 해시뱅에서 # 다음 부분을 fragment identifier라고 하는데, 위 예제에서는 settings, register이 fragment identifier가 된다. 해시뱅의 원리는 html의 네임 앵커를 이용한 것이다.

꽤 오래 전에 사용했던 기술이고 지금은 deprecated 되었다. (하지만 내가 사용하게 되는데…)

React에 해시뱅 적용하기

적용 방법은 단순하다. HashRouter를 사용하면 된다.

BrowserRouter 에서

1
2
3
4
5
6
7
8
9
10
11
12
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import App from './components/App';


const Routes = () => (
<BrowserRouter>
<App />
</BrowserRouter>
);

export default Routes;

HashRouter로 바꿔주었다.

1
2
3
4
5
6
7
8
9
10
11
12
import React from 'react';
import { HashRouter } from 'react-router-dom';
import App from './components/App';


const Routes = () => (
<HashRouter>
<App />
</HashRouter>
);

export default Routes;

HashRouter를 굳이 사용해야 할 이유를 하나 꼽자면 레거시 브라우저(IE9 이하) 지원 정도…? 그 이외에는 사용해야 할 이유를 잘 모르겠다.

References

  • 해시뱅(#!)에 대해서…
  • What’s the shebang/hashbang (#!) in Facebook and new Twitter URLs for?

Leetcode - 832

풀이과정

  • 각 배열의 값을 좌우 대칭으로 변경하고 값을 반전시켜주면 되는 문제.
  • front, back 변수 두 개 만든 다음, 중간을 기점으로 루프 돌 때마다 front를 증가시키고 back을 감소시켜 변경할 값들의 인덱스를 구한 다음에 값을 swap했다.
  • 그렇게 좌우 대칭한 배열의 값들을 반전시켜주면 끝.

Code (Javascript)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var flipAndInvertImage = function (A) {
for (let array of A) {
let front = 0;
let back = array.length - 1;

// flip horizontally
while (array.length / 2 > front) {
// swap
let temp;
temp = array[front];
array[front] = array[back];
array[back] = temp;

front += 1;
back -= 1;
}

// invert
for (let i = 0; i < A.length; i++) {
array[i] = array[i] === 0 ? 1 : 0;
}
}
return A;
};

요새 리트코드로 많이 풀길래 한번 풀어봄.. 간만에 자바스크립트로 풀었다..

리트코드는 다른 사람 코드 어떻게 보는 건지 모르겠다.. 구글링인가..?

Baekjoon Online Judge - 2606

  • 방문한 노드의 갯수를 새면 되는 문제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import collections

def bfs(start):
queue = collections.deque()
visited = [start]
queue += graph[start]
count = 0

while queue:
node = queue.popleft()
if node not in visited:
queue += graph[node]
visited.append(node)
# visited 리스트에 노드를 넣을 때마다 count 1씩 증가
count += 1
return count

V = int(input())
E = int(input())

graph = [[] for _ in range(V+1)]

for _ in range(E):
a, b = map(int, input().split())
graph[a].append(b)
graph[b].append(a)

print(bfs(1))

Baekjoon Online Judge - 1260

  • BFS는 쉽게 했는데 DFS에서 삽질을 많이 했다. 자꾸 1>4>3>2가 출력되길래…
  • 작은 노드부터 탐색을 해야하기 때문에, dfs 함수 내에서 작은 노드부터 탐색할 수 있게끔 자식 노드를 정렬해 스택에 넣어줘야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import collections

def dfs(v):
stack = []

# 스택과 visited 리스트에 루트 노드 추가
visited = [v]
# 작은 노드부터 탐색해야하기 때문에 정렬
stack.extend(reversed(adj[v]))

while stack:
# 제일 위에 있는 노드 꺼내기
node = stack.pop()
# 해당 노드가 방문하지 않은 노드일 경우
if node not in visited:
# 해당 노드를 visited 리스트에 추가
visited.append(node)
# 해당 노드의 자식노드를 스택에 추가
# 작은 노드부터 탐색해야하기 때문에 정렬
stack.extend(reversed(adj[node]))
return visited

def bfs(v):
queue = collections.deque()

# 큐와 visited 리스트에 루트 노드 추가
visited = [v]
queue += adj[v]

while queue:
# 먼저 큐에 들어가있던 노드 꺼내기
node = queue.popleft()
# 해당 노드가 방문하지 않은 노드일 경우
if node not in visited:
# 해당 노드의 자식노드를 큐에 추가
queue += adj[node]
# 해당 노드를 visited 리스트에 추가
visited.append(node)

return visited

N, M, V = (map(int, input().split()))

adj = [[] for _ in range(N+1)]

for _ in range(M):
a, b = (map(int, input().split()))
adj[a].append(b)
adj[b].append(a)

# 정점 번호가 작은 순대로 정렬
adj[a].sort()
adj[b].sort()

# 배열을 문자열로 변환
answer1 = " ".join(str(x) for x in dfs(V))
answer2 = " ".join(str(x) for x in bfs(V))

print(answer1)
print(answer2)

프로그래머스 - 스택/큐

Code (Python)

  • 스택/큐 문제. 아마 스택으로 풀면 되지 않을까 싶은데 정작 스택으로 안 푼 문제.
  • 끝에서부터 처음까지 비교해, 만약 앞의 수가 클 경우 인덱스를 정답 배열에 넣고, 그게 아닐 경우 0을 정답 배열에 넣는다.
  • 역순으로 저장했으니 reverse() 메소드로 정렬한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def solution(heights):
length = len(heights)
answer = []
while length > 0:
length = length - 1
for i in range(length, -1, -1):
if heights[length] < heights[i]:
answer.append(i + 1)
break
if i == 0 and heights[length] >= heights[i]:
answer.append(0)

answer.reverse()
return answer

다른 사람의 코드 1

  • 정답 배열에 길이만큼 0을 먼저 집어넣고, 조건(h[i] < h[j])에 맞을 경우에만 값을 바꿔줬다.
1
2
3
4
5
6
7
8
def solution(h):
ans = [0] * len(h)
for i in range(len(h)-1, 0, -1):
for j in range(i-1, -1, -1):
if h[i] < h[j]:
ans[i] = j+1
break
return ans

프로그래머스 - 완전 탐색

Code (Python)

  • 123~987까지의 리스트를 미리 만듦 (baseball_list)
  • baseball_list의 길이만큼 정답 배열(answer)을 만들고 True로 값 초기화
  • 스트라이크와 볼의 갯수가 같지 않을 경우 정답 배열의 값을 False로 변경
  • 배열 내에서 True인 것만 필터링해 출력
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from itertools import permutations

def solution(baseball):
baseball_list = list(permutations([1,2,3,4,5,6,7,8,9], 3))
answer = []

for i in range(len(baseball_list)):
answer.append(True)

for i in baseball:
number = tuple(map(int, list(str(i[0]))))

for index, baseball in enumerate(baseball_list):
ball = 0
strike = 0

if number[0] == baseball[0]:
strike += 1
elif number[0] == baseball[1] or number[0] == baseball[2]:
ball += 1
if number[1] == baseball[1]:
strike += 1
elif number[1] == baseball[0] or number[1] == baseball[2]:
ball += 1
if number[2] == baseball[2]:
strike += 1
elif number[2] == baseball[0] or number[2] == baseball[1]:
ball += 1

if strike != i[1] or ball != i[2]:
answer[index] = False

return len(list(filter(lambda x: x, answer)))

프로그래머스 - 완전 탐색

Code (Python)

  • 가로가 x, 세로가 y일 때 red는 x*y, 전체 크기(brown+red)는 (x+2) * (y+2)
  • x*y > red인 경우는 문제의 조건에 안 맞는 것이니 break
  • 참고로 brown은 2(X+Y)+4로 구할 수 있다.
1
2
3
4
5
6
7
def solution(brown, red):
for y in range(1, red + 1):
for x in range(y, red + 1):
if x * y == red and (x + 2) * (y + 2) == brown + red:
return [x + 2, y + 2]
elif x * y > red:
break

다른 사람의 코드 1

  • 이중 for문 쓸 필요 없이, red가 i로 나누어 떨어지는 경우 brown값을 구해보면 된다.
  • for문의 범위는 int(red**(1/2))+1
1
2
3
4
5
def solution(brown, red):
for i in range(1, int(red**(1/2))+1):
if red % i == 0:
if 2*(i + red//i) == brown-4:
return [red//i+2, i+2]

다른 사람의 코드 2

  • 전체 크기만큼 반복문을 돌린다.
  • brown 값이 아닌 red 값으로 정답을 찾는 방식
1
2
3
4
5
6
7
8
def solution(brown, red):
nm = brown + red
for n in range(1, nm+1):
if nm%n != 0:
continue
m = nm//n
if (n-2)*(m-2) == red:
return sorted([n, m], reverse = True)

자바스크립트 관련 자료를 원문으로 보다 보면 함수 호출을 call a function 대신 invoke a function 이라고 하는 경우가 있다. call이나 invoke 둘 다 함수 호출을 뜻하지만, 둘은 미묘한 차이가 있다.

보통 함수 호출은 call이라는 단어를 사용하는데 invoke를 사용하는 이유는, 자바스크립트는 직접적으로 호출이 될 수도 있지만 call()apply() 메소드를 사용해 간접적으로 호출이 될 수도 있기 때문이다.

1
2
3
fn();
fn.call();
fn.apply();

셋 다 함수를 호출하기는 하는데, fn()처럼 직접적으로 호출할 때는 call이 어울리고, fn.call()fn.apply()로 호출할 때는 invoke가 어울린다. (그래봤자 미묘한 어감의 차이일 뿐이지만…)

아래의 그림을 보자.

Call and Invoke

  • call: 실제로 함수를 호출하는 명령문을 참조
  • invoke: 함수를 호출/실행하기 위해 호출문을 간접적으로 참조

reference

  • Calling vs invoking a function

프로그래머스 - 연습 문제

Code (Python)

  • 완전탐색(Brute-Force)
  • itertools 없었으면 절대 못 풀었을 문제다. 그저 갓이썬…
  • itertools.permutation로 모든 숫자의 조합을 구해 리스트에 저장.
  • 숫자 조합 리스트의 최대값까지의 소수를 찾는다. 소수는 에라토스테네스의 체를 활용해서 찾으면 된다.
  • 소수 리스트와 숫자 조합 리스트의 합집합을 구하고 길이를 리턴한다.
  • 다음에는 itertools 없이 풀어봐야겠다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import itertools

def sieve(n):
num=set(range(2,n+1))

for i in range(2,n+1):
if i in num:
num-=set(range(2*i,n+1,i))
return num

def solution(numbers):
numbers_list = []
for i in range(1, len(numbers) + 1):
numbers_list += list(map(''.join, itertools.permutations(numbers,i)))

numbers_list = set(map(int, numbers_list))
prime_list = sieve(max(numbers_list))

return len(numbers_list & prime_list)

References

  • 순열과 조합 - combinations, permutations

Baekjoon Online Judge - 2231

Code (Python)

  • 예외처리를 잘못해서 두 번이나 틀린 문제..~ 분해합이 없을 경우의 처리를 해줘야 한다.
  • 어차피 분해합의 생성자는 분해합보다 작다. 고로 입력값(N)까지만 비교하면 됨.
  • 입력값(N)까지 비교했음에도 분해합을 찾지 못하고, i == N이 되면 그냥 0을 출력하면 된다.
  • 문제 이해 잘못해서 슬랙방에 이상한 질문이나 남기고… 아진짜닉변하고싶다…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
N = int(input())

for i in range(1, N + 1):
hap = 0
number = i
while number != 0:
rest = int(number % 10)
hap += rest
number = int(number/10)
hap += i
if hap == N:
print(i)
break
if i == N:
print(0)

References 1 (출처)

  • 자릿수 하나하나 배열에 넣어서 더함
1
2
3
4
5
6
7
8
9
10
11
12
13
num = int(input())
answer = 0

for i in range(1, num+1):
coef_num_list = list(map(int, str(i)))
answer = i + sum(coef_num_list)

if answer == num:
print(i)
break

if i == num:
print(0)