Custom Grid - boostcampwm2025/and01-boostcamp GitHub Wiki
๋ฌธ์
Compose ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณตํ๋ Layout์ด UI ์๊ตฌ์ฌํญ์ ๋ง์กฑ์ํฌ ์ ์์.
1. ์๊ณ ๋ฆฌ์ฆ ๊ฐ์
1.1 2D Occupied Grid ๋ฐฉ์
rows ร columnsํฌ๊ธฐ์ 2์ฐจ์ Boolean ๋ฐฐ์ด์ ์ฌ์ฉ- ๊ฐ ์์ดํ ๋ฐฐ์น ์, ํด๋น ์์ดํ ์ด ์ฐจ์งํ ๋ชจ๋ ์ ์ ์ํํ๋ฉฐ ์ถฉ๋ ์ฌ๋ถ ๊ฒ์ฌ
- ๋น์นธ์ด ์กด์ฌํ๋ ์์ ์์น ๋ฐฐ์น ํ์ฉ
์ฃผ์ ์ฝ๋
// ๊ทธ๋ฆฌ๋ ์ ์ ์ํ
val occupied = Array(rows) { BooleanArray(columns) }
// ํน์ ์์น์ ์์ดํ
๋ฐฐ์น ๊ฐ๋ฅ ์ฌ๋ถ ๊ฒ์ฌ
fun canPlace(r: Int, c: Int, rs: Int, cs: Int): Boolean {
if (r + rs > rows || c + cs > columns) return false
for (rr in r until r + rs) {
for (cc in c until c + cs) {
if (occupied[rr][cc]) return false
}
}
return true
}
// ์์ดํ
๋ฐฐ์น ํ ์ ์ ์ํ ๋งํน
fun mark(r: Int, c: Int, rs: Int, cs: Int) {
for (rr in r until r + rs) {
for (cc in c until c + cs) {
occupied[rr][cc] = true
}
}
}
// ์์ดํ
๋ฐฐ์น ๋ก์ง
for (r in 0 until rows) {
for (c in 0 until columns) {
if (canPlace(r, c, item.rowSpan, item.colSpan)) {
mark(r, c, item.rowSpan, item.colSpan)
// placeable ๋ฐฐ์น ์ฒ๋ฆฌ
break
}
}
}
1.2 ์ถ(์ด) ์๊ธฐ ๋ฐฉ์ (Skyline / Column Height)
- ๊ฐ ์ด(column)์ ๋ํด ํ์ฌ๊น์ง ์์ธ ๋์ด๋ง ๊ด๋ฆฌ
- ์์ดํ ์ ํญ์ ์๋์์ ์๋ก๋ง ์์
- ์ค๊ฐ ๋น์นธ(holes)์ด ์กด์ฌํ์ง ์๋ ๊ตฌ์กฐ๋ฅผ ์ ์ ๋ก ํจ
์ฃผ์ ์ฝ๋
// ๊ฐ ์ด์ ํ์ฌ ๋์ด
val columnHeights = IntArray(columns) { 0 }
// ์์ดํ
๋ฐฐ์น ๋ก์ง
for (c in 0..columns - item.colSpan) {
// ํด๋น ์์ดํ
์ด ์ฐจ์งํ ์ด ๋ฒ์ ์ค ๊ฐ์ฅ ๋์ ๋์ด
val baseRow = (c until c + item.colSpan)
.maxOf { columnHeights[it] }
// ๊ทธ๋ฆฌ๋ ๋์ด ์ด๊ณผ ์ ๋ฐฐ์น ๋ถ๊ฐ
if (baseRow + item.rowSpan > rows) continue
// ๋ฐฐ์น ํ์ ํ ์ด ๋์ด ๊ฐฑ์
for (cc in c until c + item.colSpan) {
columnHeights[cc] = baseRow + item.rowSpan
}
// placeable ๋ฐฐ์น ์ฒ๋ฆฌ
break
}
์ถ ์๊ธฐ ๋ฐฉ์ ์๊ณ ๋ฆฌ์ฆ ์์
var bestCol = -1
var bestBaseRow = Int.MAX_VALUE
for (c in 0..columns - item.colSpan) {
val baseRow = (c until c + item.colSpan).maxOf { columnHeights[it] }
if (baseRow + item.rowSpan > rows) continue
if (baseRow < bestBaseRow) {
bestBaseRow = baseRow
bestCol = c
}
}
๊ฐ์ฅ ๋ฎ์ ์ต์ ์ ์ด์ ์ฐพ๋ ๋ฐฉ์์ผ๋ก ์์
2. ๋ฐฐ์น ํ๋จ ๋ก์ง ๋น๊ต
2.1 2D Occupied Grid ๋ฐฉ์
- ๋ชจ๋
(row, column)์์น๋ฅผ ์ํ - ์์ดํ
์ด ์ฐจ์งํ
rowSpan ร colSpan์์ญ ์ ์ฒด ๊ฒ์ฌ - ํ๋๋ผ๋ ์ด๋ฏธ occupied ์ํ๋ฉด ๋ฐฐ์น ๋ถ๊ฐ
- ๋ฐฐ์น ๊ฐ๋ฅ ์ ํด๋น ์์ญ ์ ์ฒด๋ฅผ occupied๋ก ๋งํน
๋ธ๋ก ํ๋ ๋น ์๊ฐ ๋ณต์ก๋: O(rows ร columns ร rowSpan ร colSpan)
์ฅ์
- ์ค๊ฐ ๋น์นธ ํ์ฉ ๊ฐ๋ฅ
- ๋น๊ต์ ์์ดํ ์์ ์์กด์ฑ์ด ๋ฎ์(๋น ๊ณต๊ฐ์ด ์๊ธฐ๋ ์์ดํ ์์๋๋ผ๋ ๋ชจ๋ ์์ดํ ์ด ๋ฐฐ์น ๋จ)
๋จ์
- ๋ก์ง ๋ณต์ก๋ ๋์
- ์๊ฐ ๋ณต์ก๋๊ฐ ๋น๊ต์ ๋์
2.2 ์ถ ์๊ธฐ ๋ฐฉ์
- ๋ฐฐ์น ์์ ์ด
c๋ง ์ํ c .. c + colSpan๋ฒ์์์ ์ต๋ columnHeight ๊ณ์ฐbaseHeight + rowSpan <= rows์ธ์ง๋ง ๊ฒ์ฌ- ๋ฐฐ์น ํ์ ์ ํด๋น ์ด๋ค์ height ๊ฐฑ์
๋ธ๋ก ํ๋ ๋น ์๊ฐ ๋ณต์ก๋: O(columns ร colSpan)
์ฅ์
- ๋น๊ต์ ์๊ฐ ๋ณต์ก๋๊ฐ ๋ฎ์
๋จ์
- ์ค๊ฐ ๋น์นธ ํ์ฉ ๋ถ๊ฐ
- ์์ดํ ์์์ ๋ฐ๋ฅธ ๊ฒฐ๊ณผ ์์กด์ฑ ํผ(๋น ๊ณต๊ฐ์ด ์๊ธฐ๋ ์์์ผ ๊ฒฝ์ฐ ๋ชจ๋ ์์ดํ ์ ๋ฐฐ์นํ์ง ๋ชปํจ)
3. ๊ฒฐ๋ก
- 2D Occupied Grid ๋ฐฉ์์ ๋์ ์์ ๋์ ์ ๋ฐ ์ ์ด๋ฅผ ์ ๊ณตํ๋ค.
- ์ถ ์๊ธฐ ๋ฐฉ์์ ๋จ์ํจ๊ณผ ์ฑ๋ฅ์ ์ ๊ณตํ๋ ๋์ ์ ์ฝ์ ์์ฉํด์ผ ํ๋ค.
- ํ์ฌ๋ ๋ฐฐ์น์ ์์๋ฅผ ๋ณด์ฅํด์ฃผ๊ธฐ ๋๋ฌธ์ ์๊ฐ๋ณต์ก๋๊ฐ ๋ฎ์ ์ถ ์๊ธฐ ๋ฐฉ์์ ์ ํ
4. ์ถ๊ฐ ๊ณ ๋ ค
-
๊ทธ๋ฆฌ๋ ๋ทฐ์ ๋จ์ ์ด๋ฏธ์ง ์ปจํ ์ธ ๋ง์ ๊ณ ์ ์ ์ผ๋ก ์ฌ์ฉ๊ฐ๋ฅ ํ๋ ์ถํ ๋ค๋ฅธ ์ปจํ ์ธ ๋ ์ฝ์ ๊ฐ๋ฅํ๊ฒ ํ์ฅ
-
ํ์ฌ๋ ๊ณ ์ ๋ ๋ฐฐ์น, ์์๋ก ๋ธ๋ญ๋ค์ ๋ฐฐ์นํ๊ณ ์์ผ๋ ์ถํ ์ฌ์ฉ์์ ํธ์์ฑ์ ๊ณ ๋ คํด์ผํจ
- ๊ทธ๋ฆฌ๋์ ํ๊ณผ ์ด์ ์์ ๋กญ๊ฒ ๋ณ๊ฒฝ ๊ฐ๋ฅ
- ๊ทธ๋ฆฌ๋ ๋ด์ ๋ธ๋ก๋ค์ ๋ฐฐ์น๋ฅผ ๋ณ๊ฒฝ
- ๊ทธ๋ฆฌ๋ ๋ด ๋ธ๋ก์ ์ถ๊ฐํ๊ฑฐ๋ ๋ธ๋ก์ ํฌ๊ธฐ๋ฅผ ๋ณ๊ฒฝ
-
์ด๋ฏธ์ง๋ฅผ ๋ธ๋ญ์ ๋ฐฐ์น ํ crop์ผ๋ก ์ฒ๋ฆฌ ์ค์ด๊ธฐ์ ์ด๋ฏธ์ง์ ๋น์จ์ ๊ณ ๋ คํ์ง ๋ชปํ ์ฑ ์๋ ค์ ๋ณด์ผ ๊ฐ๋ฅ์ฑ์ด ์กด์ฌ
- ๋ด๋ถ ์ปจํ ์ธ ํฌ๊ธฐ๋ฅผ ๊ณ ๋ คํด ์ ์ ํ ๋ธ๋ก์ ๋ฐฐ์นํ๋ ์ฒ๋ฆฌ