clean.tpz
// List organizer. Paste many lines. It trims whitespace, removes duplicates, and sorts them. Written in Topaz.
// Key identifiers: 글자정리=escapeChar, 글=ch, 줄정리=escapeLine, 줄=line, 정리하기=organize,
// 텍스트=text, 줄목록=lines, 원시=raw, 다듬은=trimmed, 정렬됨=sorted, 결과=result,
// 이전=prev, 처음=first, 고유=unique
// 목록 정리기. 여러 줄을 붙여넣으면 공백 제거, 중복 제거, 정렬을 거칩니다. Topaz로 작성했습니다.
// 순수하고 결정적입니다. 같은 입력은 인터프리터와 네이티브/wasm 빌드에서 같은 HTML을 냅니다.
// Pure and deterministic. The same input yields the same HTML in the interpreter and the native/wasm builds.
// arr.sorted()(줄 정렬)와 str.byteLength()(빈 줄 제거), 그리고 문자열 기본 연산인
// split/trim을 직접 사용합니다. 줄은 사용자 텍스트이므로 출력 전에 모두 HTML 이스케이프합니다.
// Uses arr.sorted() (sort lines), str.byteLength() (drop empty lines), and the string builtins split/trim directly.
// Lines are user text, so everything is HTML-escaped before output.
function 글자정리(글: string) -> string {
if 글 == "&" { "&" }
else if 글 == "<" { "<" }
else if 글 == ">" { ">" }
else { 글 }
}
function 줄정리(줄: string) -> string {
let mut 출력 = ""
for 글 in 줄.scalars() {
출력 = 출력 + 글자정리(글)
}
출력
}
function 정리하기(텍스트: string) -> string {
// 줄바꿈 기준으로 분리한 뒤 각 줄 공백을 제거하고 빈 줄(byteLength 0)을 버립니다
// Split on newlines, trim each line, and discard empty lines (byteLength 0).
let mut 줄목록: Array<string> = []
for 원시 in 텍스트.split("\n") {
let 다듬은 = 원시.trim()
if 다듬은.byteLength() > 0 {
줄목록.push(다듬은)
}
}
// 오름차순으로 정렬한 뒤 인접 중복을 버립니다(같은 줄은 이제 이웃이 됩니다)
// Sort ascending, then drop adjacent duplicates (identical lines are now neighbors).
let 정렬됨 = 줄목록.sorted()
let mut 결과 = "<ol class=\"list\">"
let mut 이전 = ""
let mut 처음 = true
let mut 고유 = 0
for 줄 in 정렬됨 {
if 처음 || 줄 != 이전 {
결과 = 결과 + "<li>" + 줄정리(줄) + "</li>"
고유 = 고유 + 1
}
이전 = 줄
처음 = false
}
결과 = 결과 + "</ol>"
"<p class=\"meta\">원본 {줄목록.length}줄 → 고유 {고유}줄 (정렬·중복제거)</p>" + 결과
}
print(정리하기(input()))