何か投稿してみようということで、少し前に解いた練習問題を貼っていきたいと思います
高度なテクニックは全く使っていないので、初心者の方も安心してご覧ください
コード、本文ともに見づらいと思いますがご勘弁を…
素晴らしき元サイト様
アウトプットのネタに困ったらこれ!?Ruby初心者向けのプログラミング問題を集めてみた(全10問)
カレンダー作成問題
問題文
問題文(折りたたみ)
コード
require "date"
today = Date.today
first_date = Date.parse(today.strftime("%Y.%m.1"))
last_date = (first_date >> 1) - 1
puts today.strftime("%B %Y").center(21)
puts " Su Mo Tu We Th Fr Sa"
print " " * first_day.wday
(1..last_day.day).each do |day|
print day.to_s.rjust(3)
print "\n" if (first_date.wday + day) % 7 == 0 || day == last_day.day
end
要点解説
today = Date.today
first_date = Date.parse(today.strftime("%Y.%m.1"))
last_date = (first_date >> 1) - 1
今日、月初、月末のDateオブジェクトを定義します
月初は、today
をフォーマットし、その月の一日の文字列を作ってparse
しています
月末は来月のfirst_date
の1日前として今月の最終日を求めています
print " " * first_day.wday
wday
で得られる値は、0から始まる曜日を表す数字です (日曜→0, 月曜→1・・・という感じ)
その回数空白を出力すれば、1日までの空白を再現できます
print "\n" if (first_date.wday + day) % 7 == 0 || day == last_day.day
1日の位置+現在の日付が7の倍数になったら改行します
カラオケマシン問題
問題文
問題文(折りたたみ)
コード
class KaraokeMachine
SCALE = %w(C C# D D# E F F# G G# A A# B).freeze
def initialize(melody)
@melody = melody
end
def transpose(amount)
@melody.gsub(/[A-G]#?/) { |sub| SCALE[(SCALE.index(sub) + amount) % 12] }
end
end
要点解説
@melody.gsub(/[A-G]#?/) { |sub| SCALE[(SCALE.index(sub) + amount) % 12] }
正規表現での置換を使います
まず「A-Gのいずれかと#が0か1個ある」文字列をブロックに渡します
ブロック内部ではSCALE
の(SCALE.index(sub) + amount) % 12
の音階を返します
ビンゴカード作成問題
問題文
問題文(折りたたみ)
出力例は以下のとおりです。
B | I | N | G | O
13 | 22 | 32 | 48 | 61
3 | 23 | 43 | 53 | 63
4 | 19 | | 60 | 65
12 | 16 | 44 | 50 | 75
2 | 28 | 33 | 56 | 68
ビンゴカードを文字列として出力する、Bingo.generate_card メソッドを作成してください。
(中略)
Bingo.generate_card メソッドの出力結果は上で述べた数字のルールのほかに、以下の仕様を満たす必要があります。毎回異なるカードを生成します。
各列はパイプ(|)で区切ります。
数字や"BINGO"の文字は右寄せで出力します。
真ん中(FREEになる場所)はスペースを出力します。
コード
*ウンコードです
class Bingo
def self.generate_card
%w(B I N G O).each_with_index do |chr, i|
column = ["#{chr}"]
iex = (i + 1) * 15
5.times do |c|
column << rand((iex + 1 - 15)..iex).to_s
redo if column.uniq!
if chr == "N" && c == 2
column.pop
column << " "
end
end
instance_variable_set("@#{chr}", column)
end
@B.zip(@I, @N, @G, @O) do |row|
puts row.map { |x| x.rjust(2) }.join(" | ")
end
end
end
要点解説
5.times do |c|
column << rand((iex + 1 - 15)..iex).to_s
redo if column.uniq!
if chr == "N" && c == 2
column.pop
column << " "
end
end
B,I,N,G,Oの文字列の入ったそれぞれの配列にランダムな数字を入れていきます
(iex + 1 - 15)..iex
はごちゃごちゃしてますが、一応期待通りの範囲オブジェクトを作れます
uniq!
は重複する値が無いとnil
を返します
なので、if文の条件式にするとuniq!
が適用されcolumn
から重複した値が除かれた場合にredo
します
instance_variable_set("@#{chr}", column)
第1引数を変数名、第2引数を中身としてインスタンス変数を定義できるメソッドです
苦肉の策です…
ボーナスドリンク問題
問題文
問題文(折りたたみ)
*新しい飲み物が3本揃えばまた一本貰えるというひっかけ問題(?)
コード
def bounus_drink(amount)
all_ju = [amount]
dividend = amount
loop do
result = dividend.divmod(3)
all_ju << result[0]
dividend = result.sum
break if dividend < 3
end
all_ju.sum
end
要点解説
loop do
result = dividend.divmod(3)
all_ju << result[0]
dividend = result.sum
break if dividend < 3
end
交換できた本数(dividend / 3
の商)と、交換で手に入れた新しい飲み物も含めた交換できてない本数(dividend /3
の余り)の合計が3以下になるまで3で割り続けます
再帰処理?ナニソレオイシイノ?
電話帳作成問題
問題文
問題文(折りたたみ)
コード
class NameIndex
KATAKANAS =[
('ア'..'オ').to_a << 'ヴ',
('カ'..'ゴ').to_a,
('サ'..'ゾ').to_a,
('タ'..'ド').to_a,
('ナ'..'ノ').to_a,
('ハ'..'ボ').to_a,
('マ'..'モ').to_a,
('ヤ'..'ヨ').to_a,
('ラ'..'ロ').to_a,
('ワ'..'ン').to_a
].freeze
def self.create_index(names)
name_index = []
KATAKANAS.each do |katakana|
matched = names.select { |name| katakana.include?(name.chr) }
name_index << [katakana[0], matched.sort] unless matched == []
end
name_index
end
end
要点解説
matched = names.select { |name| katakana.include?(name.chr) }
names
から1文字目がkatakana
に含まれいるものを抜き出します
問題文の例でいうと、katakana
が('ア'..'オ').to_a << 'ヴ'
だった場合、matched
は["イトウ"]
になります
つづく
以上、前半の5問でした
Ruby初心者向けプログラミング問題10選を解いてみた(下)に続く