Skip to content

Instantly share code, notes, and snippets.

@wagurano
Last active December 4, 2020 09:16
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save wagurano/9cd4f5527e22bd253aad to your computer and use it in GitHub Desktop.
Save wagurano/9cd4f5527e22bd253aad to your computer and use it in GitHub Desktop.

vita3k

저자

@wagurano 줄여서 와그, 루비니언, 평화를 사랑하며 코딩하는 프로그래머

시작하며

서울 펄 몽거스의 펄 크리스마스 달력을 참고하여 루비 크리스마스 달력(Advent Calendar)에 참여하는 글입니다.

무엇보다 한글처리에 도움을 주신 neocoin 님에게 감사드립니다.

지난 11월 레일스럼블에 비타3천(vita3k) 프로젝트로 참여하였습니다. 누구나 한번쯤 친구들과 재미삼아 이름에 있는 글자를 획수로 하나둘씩 세면서 궁합점수를 계산해봤을텐데요. 봉봉ㅍㅍㅅㅅ에서도 해볼 수 있습니다. 배우 '장동건'씨와, '고소영'씨의 이름 궁합은 '1'으로 계산결과가 의미없다는 것을 잘 보여줍니다. 그러면 한글을 자모로 나누고 각 획수를 계산하는 과정을 보여드리겠습니다.

준비물

이름 궁합

이름 궁합은 두사람의 이름을 한 글자씩 섞어서 나열한 다음 한글 자모의 획수를 그 아래에 적습니다. 획수를 순서대로 둘씩 짝지어 덧셈합니다. 다만, 그 아래에 적을 때는 한자리수만 적습니다. 예를 들면 '동'은 6, '소'는 4 이고 덧셈은 '10'이라서 '0'을 적습니다. 둘씩 짝지어 덧셈하는 과정을 두개가 남을때까지 반복합니다. '성유리'와 '이효리'를 예를 들어 계산해보겠습니다.

성 이 유 효 리 리
 5 2 4 6 6 6
  7 6 0 2 2
   3 6 2 4
    9 8 6
     7 4

한글 자모 처리

한글 자모를 처리하는 참고자료는 아래와 같습니다.

참고자료를 토대로 neocoin님의 만들어둔 루비코드를 사용하였습니다.

한글 자모 중에서 'ㄱ'은 한획으로 쓰지만 이름 궁합으로 계산할 때는 가로 한번, 세로 한번으로 'ㄱ'을 2획으로 계산합니다.

따라서 아래와 같이

자음 획수
2
4
2
3
6
5
4
4
8
2
4
1
3
6
4
3
4
4
3
모음 획수
2
3
3
4
2
3
3
4
2
4
5
3
3
2
4
5
3
3
1
2
1
이중자모 획수
4
5
5
7
9
9
7
9
9
8
6

미리 정해두었습니다.

여기서는 String 클래스를 오픈하여 코드를 추가할 수 있으나 모듈로 구분하여 만들었습니다.

  # '한'을 초성, 중성, 종성인 'ㅎ,ㅏ,ㄴ'으로 나눕니다.
  def split_hangul char
    point = char.codepoints.first
    case point
    when HANGUL_SYLLABLES_RANGE
      uni_value = point - 0xAC00
      jong = uni_value % 28
      cho  = ( ( uni_value - jong ) / 28 ) / 21
      jung = ( ( uni_value - jong ) / 28 ) % 21
      [TABLE_FOR_CHO[cho], TABLE_FOR_JUNG[jung], TABLE_FOR_JONG[jong]]
    else
      char
    end
  end

  # 미리 정해둔 한글의 자모에 대한 획수를 계산합니다.
  def count_strokes string
      string.chars.map{ |char|
        (split_hangul char).map{ |c| STROKES[c] }.inject(:+)
      }
  end

이름 궁합 계산

획수에 따라 두 사람의 이름 궁합을 계산하는 코드는 아래와 같습니다.

  def to_strokes foo, bar
    f = foo.chars
    b = bar.chars
    baz = Array.new(foo.size){ "#{f.shift}#{b.shift}" }.join ''
    ((count_strokes baz).join '').to_i
    z = count_strokes baz
    loop {
      break if z.size <= 2
      (z.size - 1).times { z << (z.shift + z[0]) % 10 }
      z.shift
    }
    z.join('').to_i
  end
  1. String#chars 메소드는 문자열을 낱글자 배열로 만듭니다.
  2. 두사람의 이름을 한글자씩 섞어서 문자열 하나로 만듭니다. 예를 들어 '장동건' + '고소영'은 '장고동소건영'으로 만듭니다.
  3. 합친 문자열의 획수를 배열로 먼저 만들고
  4. 둘씩 짝지어 덧셈하는 과정을 두자리가 남을 때까지 반복합니다.
  5. 최종 결과는 '00'~'99' 까지입니다.

기타

세사람이상 하고 싶거나 알파벳으로 되어있는 이름도 궁합을 계산할 수 있도록

  # 세사람 이상 이름 궁합 계산합니다.
  def to_strokes_from list
    c_list = list.map{ |x| x.chars }
    baz = Array.new(c_list.first.size){ c_list.map{ |x| x.shift }.join '' }.join ''
    ((count_strokes baz).join '').to_i
    z = count_strokes baz
    loop {
      break if z.size <= 2
      (z.size - 1).times { z << (z.shift + z[0]) % 10 }
      z.shift
    }
    z.join('').to_i
  end

  # 네이버 사전을 사용해서 알파벳으로 된 이름을 '한국어'로 읽을 때 '한글'로 표기합니다.
  def to_korean word
    a = Net::HTTP.get("translate.naver.com",
      "/koreaPron.dic?query=#{word}&srcLang=en&tarLang=ko")
    a.force_encoding('UTF-8').strip
  end

  # 한글, 알파벳 구분없이 두사람 이름 궁합을 계산합니다.
  def to_strokes_global foo, bar
    foo = foo.split.map{ |x| to_korean x }.join '' unless hangul? foo
    bar = bar.split.map{ |x| to_korean x }.join '' unless hangul? bar
    [foo, bar, to_strokes(foo, bar)]
  end

정리하며

이름 궁합은 즉흥적으로 만들어서 좀 더 다듬고 있습니다. 루비 1.9 에서도 하려면 shift 메소드에 대한 대안이 필요하고 라이브러리로 활용할 수 있도록 메소드 이름을 정리하고 있습니다. 이름 궁합이나 한글처리에 관심있으신분은 위의 코드를 참고하여 '젬'으로 만들어서 배포하면 좋겠습니다.

감사합니다.

EOT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment