← 제니앱

글자수 세기

글자, 공백 제외, 단어, 줄, UTF-8 바이트 수를 세며, 한글 1글자는 3바이트입니다.

count.tpz
// Character counter. A chars / words / lines / bytes counter written purely in Topaz.
// Key identifiers: 세기=count, 공백인가=isWhitespace, 카드=card, 글=char, 이름=label,
//   값=value, 텍스트=text, 글자들=chars, 전체글자=totalChars, 공백제외=nonSpaceChars,
//   줄수=lineCount, 바이트수=byteCount, 단어수=wordCount, 단어중=inWord, 결과=result
// 글자수 세기. Topaz로만 작성한 글자 / 단어 / 줄 / 바이트 카운터입니다.
// 호스트의 텍스트(편집기 textarea)를 읽어 HTML 통계 카드 조각을 출력합니다.
// Reads the host's text (the editor textarea) and emits HTML stat-card fragments.
// 순수하고 결정적입니다. 같은 텍스트면 인터프리터와 네이티브/wasm 빌드에서 같은 HTML이 나옵니다.
// Pure and deterministic: same text yields the same HTML across interpreter and native/wasm builds.
// 바이트 수는 `str.byteLength()`(UTF-8)를 씁니다. 한글 스칼라는 3바이트이므로 바이트 제한
// Byte count uses `str.byteLength()` (UTF-8). Each Hangul scalar is 3 bytes, so byte-limited
// 서식(바이트 제한이 있는 서식 등)에는 스칼라 수가 아니라 이 값이 필요합니다.
// formats (e.g. forms with byte limits) need this value rather than the scalar count.

// 이 스칼라가 단어를 나누는 기준인 ASCII 공백(스페이스/탭/줄바꿈/CR)인가?
// Is this scalar an ASCII whitespace (space/tab/newline/CR) that delimits words?
function 공백인가(글: string) -> bool {
  글 == " " || 글 == "\t" || 글 == "\n" || 글 == "\r"
}

// 통계 카드 하나. 라벨 위에 큰 숫자 하나입니다(숫자와 고정 라벨만 쓰고 사용자 텍스트는 출력하지 않습니다).
// One stat card: a big number above a label (only numbers and fixed labels, never user text).
function 카드(이름: string, 값: int) -> string {
  "<div class=\"stat\"><b>{값}</b><span>{이름}</span></div>"
}

function 세기(텍스트: string) -> string {
  let 글자들 = 텍스트.scalars()
  let 전체글자 = 글자들.length
  let 공백제외 = filter(글자들, 글 => !공백인가(글)).length
  let 줄수 = 텍스트.split("\n").length
  let 바이트수 = 텍스트.byteLength()

  // 단어는 공백이 아닌 글자들의 연속입니다(공백에서 비공백으로 넘어가는 전환마다 셉니다)
  // A word is a run of non-whitespace chars (count each space-to-non-space transition).
  let mut 단어수 = 0
  let mut 단어중 = false
  for 글 in 글자들 {
    let 공백 = 공백인가(글)
    if !공백 && !단어중 { 단어수 = 단어수 + 1 }
    단어중 = !공백
  }

  let mut 결과 = "<div class=\"stats\">"
  결과 = 결과 + 카드("글자 수", 전체글자)
  결과 = 결과 + 카드("공백 제외", 공백제외)
  결과 = 결과 + 카드("단어 수", 단어수)
  결과 = 결과 + 카드("줄 수", 줄수)
  결과 = 결과 + 카드("바이트 (UTF-8)", 바이트수)
  결과 + "</div>"
}

print(세기(input()))
66글자 수
54공백 제외
13단어 수
2줄 수
165바이트 (UTF-8)