🗒 문제



📝 나의 문제풀이
class Solution {
fun solution(n: Int, w: Int, num: Int): Int {
// n개를 w만큼 끊어서 배열을 만든다 (입출력 예 1로 예시)
// (1,2,3,4,5,6)
// (12,11,10,9,8,7)
// (13,14,15,16,17,18)
// (22,21,20,19)
val tempResult = (1..n)
.chunked(w)
.mapIndexed { index, value ->
if (index % 2 == 1) value.reversed() else value
}
// 마지막 줄이 덜 찼으면 0으로 채워 길이 맞추기
val result = tempResult.toMutableList()
val lastIndex = result.lastIndex
val lastChunk = result.last().toMutableList()
val missing = w - lastChunk.size
if (missing > 0) {
if (lastIndex % 2 == 1) {
// 홀수층 → 앞쪽(왼쪽)에 0 채우기
repeat(missing) { lastChunk.add(0, 0) }
} else {
// 짝수층 → 뒤쪽(오른쪽)에 0 채우기
repeat(missing) { lastChunk.add(0) }
}
result[result.lastIndex] = lastChunk
}
// 몇번째 index에 포함되어있는지
val foundIndex = result.indexOfFirst { num in it }
// (12,11,10,9,8,7)
val foundChunk = result[foundIndex]
val isReverse = foundIndex % 2 == 1
val isLastReverse = result.lastIndex % 2 == 1
// num이 속한 위치
val idx = foundChunk.indexOf(num)
// 같은 방향이면 동일 인덱스, 다르면 반대 인덱스
val checkIndex =
if (isReverse == isLastReverse) idx - (foundChunk.size - lastChunk.size)
else idx
val isExist = lastChunk.getOrNull(checkIndex) != null
return if (isExist && result.last()[idx] != 0) {
result.size - foundIndex
} else {
result.size - 1 - foundIndex
}
}
}
📝 다른 사람의 문제 풀이
다른 사람 문제 풀이에서 가독성이 좋은 코드를 발견하지 못하여 GPT 풀이로 대체하였습니다
class Solution {
fun solution(n: Int, w: Int, num: Int): Int {
// 층 구성: 한 층에 w개씩 쌓되, 홀수층은 역방향(오른→왼)
val rows = (1..n)
.chunked(w)
.mapIndexed { i, list -> if (i % 2 == 1) list.reversed() else list }
// 마지막 층이 덜 찼으면 0으로 채워서 모양 맞추기
val paddedRows = padLastRow(rows, w)
// num이 들어 있는 층과 위치 찾기
val rowIndex = paddedRows.indexOfFirst { num in it }
val columnIndex = paddedRows[rowIndex].indexOf(num)
// 마지막 층 방향 확인 (짝수층이면 정방향)
val lastRow = paddedRows.last()
val sameDirection = (rowIndex % 2 == paddedRows.lastIndex % 2)
// 마지막 층에도 같은 위치(또는 대칭 위치)에 상자가 있는지 확인
val checkIndex =
if (sameDirection) columnIndex - (paddedRows[rowIndex].size - lastRow.size)
else columnIndex
val hasBoxAbove = lastRow.getOrNull(checkIndex)?.takeIf { it != 0 } != null
// 꺼내야 하는 상자 개수 계산
return if (hasBoxAbove) paddedRows.size - rowIndex else paddedRows.size - 1 - rowIndex
}
// 마지막 층이 덜 찼으면 빈 공간(0)으로 채워줌
private fun padLastRow(rows: List<List<Int>>, width: Int): List<List<Int>> {
val result = rows.toMutableList()
val last = result.last().toMutableList()
val missing = width - last.size
if (missing > 0) {
if (result.lastIndex % 2 == 1) repeat(missing) { last.add(0, 0) } // ← 홀수층: 앞에 0 채우기
else repeat(missing) { last.add(0) } // → 짝수층: 뒤에 0 채우기
result[result.lastIndex] = last
}
return result
}
}
🖊 문제 풀이 시 알면 좋을 것
chunked()
리스트를 일정한 크기로 나누는 함수.
택배 상자를 층 단위로 자를 때 사용.
val result = (1..22).chunked(6)
// [[1,2,3,4,5,6], [7,8,9,10,11,12], [13,14,15,16,17,18], [19,20,21,22]]
mapIndexed()
리스트의 인덱스와 값을 함께 사용해 변환할 때 사용.
층 번호(index)에 따라 방향(정방향/역방향) 을 다르게 지정 가능.
val rows = (1..22).chunked(6).mapIndexed { i, row ->
if (i % 2 == 1) row.reversed() else row
}
- 짝수층(→): [1,2,3,4,5,6]
- 홀수층(←): [12,11,10,9,8,7]
toMutableList()
불변 리스트를 가변 리스트로 변경.
리스트의 마지막 층을 수정(0으로 채우기 등)할 때 필요.
val lastRow = result.last().toMutableList()
lastRow.add(0) // 가능
repeat()
특정 횟수만큼 코드를 반복 실행.
빈 칸을 0으로 채울 때 자주 사용.
val missing = w - lastRow.size
repeat(missing) { lastRow.add(0) }
getOrNull()
리스트 인덱스를 안전하게 접근할 때 사용.
인덱스가 범위를 벗어나면 null 반환 → 예외 방지.
val value = lastRow.getOrNull(index)
if (value != null) println(value)
takeIf()
조건이 true일 때만 해당 객체를 반환, 아니면 null.
null-safe하게 조건 검사를 간결하게 쓸 수 있음.
val hasBox = lastRow.getOrNull(checkIndex)?.takeIf { it != 0 } != null
→ checkIndex 위치에 실제 상자(0이 아님)가 있으면 true
% (mod 연산자)
홀수/짝수층 구분에 사용.
층 번호(index)가 홀수면 역방향, 짝수면 정방향.
val isReverse = index % 2 == 1
indexOfFirst() / indexOf()
리스트에서 특정 값의 위치를 찾는 함수.
상자가 어느 층, 어느 열에 있는지 찾을 때 사용.
val rowIndex = rows.indexOfFirst { num in it } // 층 번호
val colIndex = rows[rowIndex].indexOf(num) // 열 번호
조건식 기반 인덱스 보정
층 방향이 다를 경우, 인덱스 계산을 대칭시켜 맞춰줌.
val checkIndex =
if (sameDirection) idx - (foundRow.size - lastRow.size)
else idx
조건에 따라 결과 반환
꺼내야 하는 상자의 개수를 상황에 맞게 계산.
return if (hasBoxAbove) rows.size - rowIndex
else rows.size - 1 - rowIndex
패딩(padding) 처리 로직
마지막 층이 w보다 작을 때 모양을 맞추기 위해 0으로 채움.
짝수층(→)은 뒤에, 홀수층(←)은 앞에 채움.
if (missing > 0) {
if (rows.lastIndex % 2 == 1) repeat(missing) { lastRow.add(0, 0) }
else repeat(missing) { lastRow.add(0) }
}
함수 분리
유지보수를 쉽게 하려면 역할별로 함수 분리.
예: padLastRow() 처럼 “마지막 층 정렬” 기능만 따로 관리.
private fun padLastRow(rows: List<List<Int>>, width: Int): List<List<Int>> { ... }
| 개념 | 키워드 | 역할 |
| 층 나누기 | chunked() | n개의 상자를 w개씩 나눔 |
| 층 방향 설정 | mapIndexed() | 홀/짝 방향 제어 |
| 안전한 접근 | getOrNull(), takeIf() | null-safe 처리 |
| 보정 | repeat(), % | 부족한 칸 채우기 / 홀짝 판단 |
| 탐색 | indexOfFirst(), indexOf() | 상자의 위치 찾기 |
| 유지보수 | 함수 분리 | 구조 명확하게 관리 |
이 문제의 포인트는 2차원 행렬을 시뮬레이션하되, 방향 전환과 마지막 층 보정을 안전하게 처리하는 것입니다.
chunked(), mapIndexed(), getOrNull(), takeIf()
네 가지 함수만 정확히 이해하면 어떤 형태의 창고 문제도 풀 수 있을 것입니다.
'코딩테스트' 카테고리의 다른 글
| 코딩테스트 대비 기본기 — 반드시 알아야 할 Kotlin 문법 (0) | 2025.12.10 |
|---|---|
| [프로그래머스] 가장 큰 수 찾기 (0) | 2025.11.13 |
| [프로그래머스] [PCCP 기출문제] 1번 / 동영상 재생기 (0) | 2025.11.10 |
| [프로그래머스] 특별한 이차원 배열 2 (0) | 2025.09.10 |
| [프로그래머스] 그림 확대 (0) | 2025.02.18 |