• TOC {:toc}

이 글은 백준 온라인 저지의 17269번 문제를 풀이한 것을 모아놓은 글입니다.

일종의 연습 기록이며 제가 정답을 받은 코드와 참고할만한 다른 코드를 같이 기록합니다. 필요한 경우 코드에 대한 해설을 기록합니다만 코드는 통과했어도 해설은 틀릴 수 있기 때문에 가볍게 참고해주시길 부탁드립니다. 피드백은 편하신 방법으로 자유롭게 주시면 감사하겠습니다.

2021.08.03 (Python)

메모리 시간 코드 길이
29200 KB 92 ms 719 B
단계 시작 시각 끝난 시각 걸린 시간
문제 이해 16:40:20 16:43:14
풀이 생각 21:32:59 21:37:35
코딩 21:37:40 22:11:55
stroke = {
    "A": 3, "B": 2, "C": 1, "D": 2,
    "E": 4, "F": 3, "G": 1, "H": 3,
    "I": 1, "J": 1, "K": 3, "L": 1,
    "M": 3, "N": 2, "O": 1, "P": 2,
    "Q": 2, "R": 2, "S": 1, "T": 2,
    "U": 1, "V": 1, "W": 1, "X": 2,
    "Y": 2, "Z": 1,
}

N, M = map(int, input().split())
x, y = input().split()
x_is_longer = True

if N < M:
    x_is_longer = False
    N, M = M, N

x = list(map(lambda x: stroke[x], x))
y = list(map(lambda x: stroke[x], y))

w = []
for i in range(M): 
    w.append(x[i])
    w.append(y[i])
if x_is_longer:
    w += x[M:]
else:
    w += y[M:]

while len(w) > 2:
    tmp = []
    for i in range(1, len(w)):
        tmp.append((w[i - 1] + w[i]) % 10)
    w = tmp

print(f"{w[0] * 10 + w[1]}%")

아이디어 & 풀이

우선 첫 수열을 만드는 것이 가장 중요하다.

  • 각 문자의 획 수를 나타내는 딕셔너리를 만든 뒤 입력받은 이름의 각 문자를 이를 이용해 매핑한다.
  • 두 이름 중 더 짧은 이름의 길이 만큼 두 이름을 번갈아 받고 긴 이름의 나머지를 뒤에 이어받으면 된다.
    • N, MM을 항상 작은 값으로 유지한다.
      • 이를 위해 NM의 값을 비교해 M이 더 크면 두 값을 swap 한다.
      • 그 과정에서 x, y 중 더 긴 단어를 판별할 수 있는 x_is_longer의 값도 정한다.
    • M까지 x, y 문자를 번갈아 받고
    • x_is_longer의 값에 따라 x[M:]y[M:]를 뒤에 더한다.

수열 w의 길이가 2가 될 때까지 연속된 두 항의 합의 일의 자리로 새 수열을 구성한 뒤 마지막 값을 출력한다.

2022.04.09 (JS)

메모리 시간 코드 길이
10264 KB 184 ms 1021 B
단계 시작 시각 끝난 시각 걸린 시간
문제 이해 01:37:22 01:37:53
풀이 생각 01:37:54 01:39:34
코딩 01:39:35 01:52:15
const fs = require("fs");
const input = fs.readFileSync('/dev/stdin').toString().trim().split("\n");

function test(nums) {
    if (nums.length === 2) return nums;
    const newNums = [];
    for (let i = 0; i < nums.length - 1; i += 1) {
        newNums.push((nums[i] + nums[i + 1]) % 10);
    }

    return test(newNums);
}

function main() {
    const min = Math.min(N, M);
    let str = "";

    for (let i = 0; i < min; i += 1) {
        str += A[i] + B[i];
    }
    str += A.slice(min) + B.slice(min);
    const res = parseInt(test(str.split("").map((c) => stroke[c])).join(""));

    return `${res}%`;
}

const [NM, line] = input;
const [N, M] = NM.split(" ").map((n) => parseInt(n));
const [A, B] = line.split(" ");

stroke = {
    "A": 3, "B": 2, "C": 1, "D": 2,
    "E": 4, "F": 3, "G": 1, "H": 3,
    "I": 1, "J": 1, "K": 3, "L": 1,
    "M": 3, "N": 2, "O": 1, "P": 2,
    "Q": 2, "R": 2, "S": 1, "T": 2,
    "U": 1, "V": 1, "W": 1, "X": 2,
    "Y": 2, "Z": 1,
}

console.log(main());

참고 답안

stroke = [3, 2, 1, 2, 4, 3, 1, 3, 1, 1, 3, 1, 3, 2, 1, 2, 2, 2, 1, 2, 1, 1, 1, 2, 2, 1]
N, M = map(int, input().split())
A, B = input().split()

AB = ""
min_len = min(N, M)
for i in range(min_len):
    AB += A[i] + B[i]
AB += A[min_len:] + B[min_len:]

w = [stroke[ord(i) - ord("A")] for i in AB]

for i in range(N + M - 2):
    for j in range(N + M - 1 - i):
        w[j] += w[j + 1]

print(f"{w[0] % 10 * 10 + w[1] % 10}%")

아이디어 & 풀이

  • 굳이 더 긴 이름을 가릴 필요 없이 둘 다 [min_len:] 으로 slicing 하면 짧은 이름은 range 밖이므로 안 더해진다.
  • 딕셔너리 대신 ASCII 코드를 치환해 인덱스로 이용한다.