3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rubyプログラミング問題にチャレンジ! -改訂版・チェリー本発売記念-Advent Calendar 2021

Day 21

🍒Rubyプログラミング問題にチャレンジ! -改訂版・チェリー本発売記念-🎸

Last updated at Posted at 2021-12-20

PRへのリンク

ロジック

処理の流れ

大まかな流れは

  1. テキストを1文字に分解
  2. 文字を0,1で構成された配列に変換する
  3. 配列で表された文字を出力しやすいように整形して出力する

となります💡

文字を配列に変換する

文字をバイナリを要素とした配列で表現する

1.png

今回のチャレンジに出てくるひらがなは6箇所に●またはーを入れることで表現することができるので、長さ6の配列を使えば表現できそうです。
2.png
3.png
また「カ行」や「サ行」を見るとわかる通り、「ア行」の①、②、④の部分を残して●を加えて変化させているという規則性が見られます。ここで「加える」ということに注目すると、●とーを1,0で表現し加算することで多くのひらがなを表現できそうです💡
なので、要素は1または0であり長さ6の配列を使って点字を表すことにします。
(例:「あ」は[1,0,0,0,0,0]

変換の方法

4.png
5.png

上記のように

  • 母音部分は①②④の点
  • 子音部分は③⑤⑥の点

で規則的に表現することができます。(例外を除く)

そこで母音の配列、子音の配列を定数として定義し、配列をベクトル的に加算することで対象の文字を出すことができます。
例えば「し」を配列に変換したい場合、
母音部分のI[1,1,0,0,0,0]と子音部分のS[0,0,0,0,1,1]をベクトル的に加算して[1,1,0,0,1,1] とすることで変換が可能です。
なお、配列をそのまま加算してもベクトル的な加算はできないので工夫が必要です。

# そのまま加算しても後ろに付け足されるだけ
[1,2,3] + [1,2,3]
=> [1, 2, 3, 1, 2, 3]

# ベクトル的に加算
[[1,2,3], [1,2,3]].transpose.map{|a| a.inject(:+) }
=> [2, 4, 6]

参考:https://qiita.com/Kta-M/items/b54f12d3eb49520925e7#comment-e192ccc9e888a565ce4b

変換部分の実装は以下となります💡

lib/constants.rb
VOWELS = { A: [1, 0, 0, 0, 0, 0],
            I: [1, 1, 0, 0, 0, 0],
            U: [1, 0, 0, 1, 0, 0],
            E: [1, 1, 0, 1, 0, 0],
            O: [0, 1, 0, 1, 0, 0] }.freeze

CONSONANTS = { K: [0, 0, 0, 0, 0, 1],
               S: [0, 0, 0, 0, 1, 1],
               T: [0, 0, 1, 0, 1, 0],
               N: [0, 0, 1, 0, 0, 0],
               H: [0, 0, 1, 0, 0, 1],
               M: [0, 0, 1, 0, 1, 1],
               R: [0, 0, 0, 0, 1, 0] }.freeze

IRREGULARS = { YA: [0, 0, 1, 1, 0, 0],
               YU: [0, 0, 1, 1, 0, 1],
               YO: [0, 0, 1, 1, 1, 0],
               WA: [0, 0, 1, 0, 0, 0],
                N: [0, 0, 1, 0, 1, 1] }.freeze
lib/tenji_maker.rb
# 引数は 'KA'などの文字
def letter_to_tenji_binary(letter)
    return IRREGULARS[letter.to_sym] if letter.match?(/W|Y|N$/)

    consonant = CONSONANTS[letter[0].to_sym] || Array.new(6, 0)
    vowel = VOWELS[letter[-1].to_sym]

    [consonant, vowel].transpose.map { |a| a.inject(&:+) }.to_a
  end

バイナリの配列を点字として出力しやすいように整形する

puts tenji_maker.to_tenji('A HI RU')
#=> o- o- oo
#   -- o- -o
#   -- oo --

チャレンジでは上記のような出力が求められています。

untitled.png

文字ごとに①と④→改行→②と⑤→改行→③と⑥
と出力すれば、求められている結果を出力できます。
よってN文字を変換する場合は、長さ3の配列で、

  • 1番目にはそれぞれの文字の①と④の値の配列がN個
  • 2番目にはそれぞれの文字の②と⑤の値の配列がN個
  • 3番目にはそれぞれの文字の③と⑥の値の配列がN個

入る配列を作ることにしました。

実際のコードは以下となります。

lib/tenji_maker.rb
# 引数にはには①〜⑥の順番で並んだ長さ6の配列が文字数分だけ入る
# 例)"A SA"の場合[[1, 0, 0, 0, 0, 0],[1, 0, 0, 0, 1, 1]]
def tenji_binaries_to_matrix(tenji_binaries)
    tenji_binaries.map { |letter|
      letter.each_slice(3).to_a.transpose
    }.transpose
end

出力部分

ここまできたらあとはそれぞれ1はo、0は-として変換し、出力すれば完成となります💡

lib/tenji_maker.rb
# 点字の出力
def matrix_to_tenji(tenji_binaries_matrix)
  tenji_binaries_matrix.map do |binary_array|
    binary_array_to_tenji_line(binary_array)
  end.join("\n")
end

# 一行分の点字を出力する
# [0,1],[1,1] => '-o oo'
def binary_array_to_tenji_line(binary_array)
  binary_array.map { |bin|
    bin.inject('') { |result, b| result + binary_to_dot(b) }
  }.join(' ')
end

def binary_to_dot(binary)
  binary.zero? ? '-' : 'o'
end

工夫したところ

YA・YU・YOの規則的な変化を不規則として扱った

スクリーンショット 2021-12-20 19.06.06.png
上記の通りYA・YU・YOも規則的な変化をしている部分もありますが、たった3文字の規則性のためにロジックを実装するよりも不規則な文字として扱った方が圧倒的に実装の工数が減りそうだったので不規則文字として扱わせていただきました。(良い方法が思いつかなかったという言い訳でもあります。)

定数を外部ファイルに持たせた📁

オープンクラスの機能を使い、定数を外部ファイルに持たせました

lib/constants.rb
class TenjiMaker
  VOWELS = { A: [1, 0, 0, 0, 0, 0],
              I: [1, 1, 0, 0, 0, 0],
              U: [1, 0, 0, 1, 0, 0],
              E: [1, 1, 0, 1, 0, 0],
              O: [0, 1, 0, 1, 0, 0] }.freeze

  CONSONANTS = { K: [0, 0, 0, 0, 0, 1],
                 S: [0, 0, 0, 0, 1, 1],
                 T: [0, 0, 1, 0, 1, 0],
                 N: [0, 0, 1, 0, 0, 0],
                 H: [0, 0, 1, 0, 0, 1],
                 M: [0, 0, 1, 0, 1, 1],
                 R: [0, 0, 0, 0, 1, 0] }.freeze

  IRREGULARS = { YA: [0, 0, 1, 1, 0, 0],
                 YU: [0, 0, 1, 1, 0, 1],
                 YO: [0, 0, 1, 1, 1, 0],
                 WA: [0, 0, 1, 0, 0, 0],
                 N: [0, 0, 1, 0, 1, 1] }.freeze
end
lib/tenji_maker.rb
require 'constants'

class TenjiMaker
.
.

伊藤さんへのメッセージ

Railsエンジニアとなって約3ヶ月が経ちますが、チェリー本には今でもお世話になっております🎉
block の項目などは初見では難しい上に「これ何に使うんだろ?」といった感じでした。しかし実務に入り色々なコードに触れてから改めて読んでみるとすんなりと理解することができ、gemのソースコードを読む時や難しい本を読む時の基礎として非常に役に立っております。ありがとうございました🍒🎸

参考リンク

全視情協:点字とは - 点字のしくみ

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?