본문 바로가기

카테고리 없음

오일러 프로젝트 17 (Julia)

숫자를 영어로 읽기

영어에서 숫자는 110까지가 아닌 119까지가 별개의 이름으로 정해져 있다. 20~99까지는 10의 자리를 표현하는 단어와 1의 자리를 표현하는 단어를 결합하여 표시한다. (twenty one, forty five...)

100의 경우 1의 자리에 대한 단어 + hundred 로 쓰이며, 100 이하의 자리에 값이 있는 경우에는 and를 쓴다. 참고로 hundred는 항상 단수형으로만 쓰인다.

따라서 각 경우는 다음과 같다.

  1. 1000인 경우에는 "one thousand"이다.
  2. 100으로 나눈 몫 + "hundred", 100으로 나눈 몫이 없으면 생략
  3. 100으로 나눈 몫이 0보다 크고 나머지가 있는 경우 "and" 추가
  4. 100으로 나눈 나머지가 20 이상인 경우, 10으로 나눈 몫과 나머지에 해당하는 단어를 붙인다.
  5. 100으로 나눈 나머지가 19이하인 경우 지정된 단어

참고로 줄리아에서 문자열은 * 으로 결합한다.


# 정수를 받아서 이를 읽은 문자열을 리턴한다.
function readnum(n)
  n > 1000 && error("Error")  # 1000보다 큰 수는 에러
  n == 1000 && return "onethousand"  # 1000 일 때
  s = ""
  t = """one two three four five six seven eight nine ten eleven twelve
         thirteen fourteen fifteen sixteen seventeen eighteen nineteen""" |> split
  h = "twenty thirty forty fifty sixty seventy eighty ninety" |> split
  q, r = divrem(n, 100)
  # 100으로 나눈 몫이 있는 경우
  q > 0 && (s *= h[q] * "hundred" * (r > 0 ? "and" : ""))
  # 그 나머지가 20 이상인 경우
  r >= 20 && (s *= t[r ÷ 10 - 1]; r %= 10)
  # 19 이하의 값
  r > 0 && (s *= h[r])
  return s
end


@time 1:1000 .|> readnum .|> length |> sum |> println

사실 문제에서 요구하는 것은 글자의 수 이므로 readnum 함수는 문자열이 아니라 추가되는 단어의 길이만 계산하는 식으로 써도 된다.

function readnum2(n)
  n > 1000 && return 0
  n == 1000 && return 11
  s = 0
  t = [3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8]
  h = [6, 6, 5, 5, 5, 7, 6, 6]
  q, r = divrem(n, 100)
  q > 0 && (s += h[q] + 7 + (r > 0 ? 3 : 0))
  r >= 20 && (s += h[r ÷ 10 - 1]; r %= 10)
  r > 0 && (s += t[r])
  return s
end