# Ruby 1.8에서테스트
def min(i, j)
  return (i <= j) ? i : j
end

# str_1, str_2에서 공통되는 부분문자열의 길이를 리턴해준다

def comm_len(str_1, str_2)

  len = 0

  (min(str_1.length, str_2.length)).times do |i|
    (str_1[i] == str_2[i]) ? (len += 1) : break
  end

  return len

end

# str에 있는 문자열을 앞에서부터 차례대로 접미사 배열을 만듬
# banana였으면 a[0] = banana, a[1] = anana,이렇게 해서  a[5] = a 가 됨

def get_suffix_arr(str, len)

  suffix_arr = Array.new(len)
  suffix_arr.each_index {|i| suffix_arr[i] = str.slice(i ... len)}

  return suffix_arr

end

# 중복된 문자열중에 가장 긴 부분문자열을 찾는것임
# programming pearls ch 15에 2번째에 나오는 문제이다.

def longest_dup_substr(str)

  longest_idx, max_len = 0, 0

  str_len = str.length

  # 공통된 문자열이 중복되서 나왔으면 두개의 다른 접미사로
  # 들어가 있을것임 같은 접미사들이 모이도록 하기위해 접미사배열을 만들어 정렬을함
  # 그럼 그 놈들 중에 겹치는 놈들을 찾아 그 길이가 제일 긴놈이
  # 제일긴 중복된 문자열이다

  suffix_arr = get_suffix_arr(str, str_len).sort!

  # 접미사 배열이 정렬되갖구있으니, 인접한 문자열끼리 계속 공통부분의 길이를 찾아나감

  (str_len - 1).times do |i|
    ret = comm_len(suffix_arr[i], suffix_arr[i + 1])

    if ret > max_len
      max_len = ret
      longest_idx = i
    end

  end

  # 가장 긴 공통 문자열이 있는 index에서 있는 문자열을 max_len만큼 잘라서 리턴

  return suffix_arr[longest_idx].slice(0 ... max_len).strip

end

require 'test/unit'

class TestLoneestDupSubstr < Test::Unit::TestCase

  def test_method
    ans = ["ana", "can do for you"]
    input = ["banana&grape",
             """Ask not what your country can do for you,
              but what you can do for your country""" ]


    input.each_index {|i| assert_equal(ans[i], longest_dup_substr(input[i]))}
  end

end
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by sloth_chord
# Ruby 1.8에서 테스트
def count_words(cnt_hash, line)

  line.scan(/\w+/) do |word|
    cnt_hash[word] += 1
  end

end

def desc_print(cnt_hash)

  # 빈도수를 큰것부터 내림차순정렬함
  desc_hash = (cnt_hash.sort {|a, b| a[1] <=> b[1]}).reverse!
  desc_hash.each{|word, count| puts "#{word} : #{count}"}

end

# 파일에서 단어의 출현 빈도수를 세는 프로그램
# 많은것부터 차례대로 출력을해줌
# !! 첨부파일 word_frequency_count_input.txt를 다운후 테스트


def word_fre_cnt(input_name)

  ip = File.open(input_name)

  # cnt_hash는 word와 출현의 빈도수를 key, value로 가진다
  # 기본값을 0으로 한다
  # 그러면 나중에 + 1 씩만하면되니까는 편함

  cnt_hash = Hash.new(0)

  while (line = ip.gets)
    count_words(cnt_hash, line)
  end

  desc_print(cnt_hash)
  ip.close

end


word_fre_cnt('word_frequency_count_input.txt')
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by sloth_chord
TAG program, ruby
# Ruby 1.8에서테스트


# !! 첨부파일인 words.txt 다운받아 실행해야함

# programming pearls ch 2에 나온 방법을 쓴것인데
# 출력 형식만 약간 바꿨음

# 원래 word와 그 word의 sign을 가질 클래스이다.


class WordSign

  # word를 알파벳순으로 정렬해서 sign으로 가진다

  def initialize(word)
    @word = word
    @sign = word.split(//).sort!
  end

  attr_reader :word, :sign

  # 정렬을 위해 <=>를 재정의함

  def <=>(obj)
    return (self.sign <=> obj.sign)
  end

end

class Anagram

  private

  def initialize(input_name, output_name)
    @ws_arr = []
    @input_name = input_name
    @output_name = output_name
  end

  def mark_sign

    ip = File.open(@input_name)

    # 각 단어마다 word와, word를 정렬해서 만든 sign을 가진 객체
    # WordSign의 배열 만듬

    ip.each {|line| word_arr = line.split(' ')
      word_arr.each {|word| @ws_arr << WordSign.new(word)}
    }

    ip.close

  end

  # sign이 같으면은 anagram

  def anagram?(sign_1, sign_2)
    return (sign_1 == sign_2)
  end

  def squash

    bar = "\n\n=======================================\n\n"

    op = File.open(@output_name, 'w')

    old_sign = ""
    old_word = ""

    group_num = 0

    is_new_group = true

    # sign으로 정렬되 있다.

    (@ws_arr.length).times do |i|

      if anagram?(old_sign, @ws_arr[i].sign)

        # 같은 사인이면은 아나그램
        # 만약 처음으로 아나그램을 확인을 한거면은
        # old_word를 같이 찍구, group_num증가시킨다

        if is_new_group
          op.print bar
          op.puts old_word

          group_num += 1
          is_new_group = false
        end

        op.puts @ws_arr[i].word

      else

        # 다른 사인이면은 old_word, old_sign의 값을 바꾸구
        # is_new_group는 true를 넣음

        is_new_group = true
        old_word = @ws_arr[i].word
        old_sign = @ws_arr[i].sign

      end

    end

    op.close()

    return group_num

  end

  public

  def anagram_list

    # sign을 만들어서 ws_arr을 만들구서
    # sign 별로 정렬을한 후 아나그램을 모아서 출력해줌

    mark_sign()
    @ws_arr.sort!
    group_num = squash()

    printf("in the %d words find %d groups of anagrams\n", @ws_arr.length, group_num)
    printf("you can check the anagrams in the %s\n", @output_name)

  end

end

obj = Anagram.new('words.txt', 'anagram_list.txt')
obj.anagram_list()
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by sloth_chord