Open12

アルゴリズム学習

3210mo3210mo

重複した文字を一つに squeeze

squeeze('-')・・・()中の重複している箇所を1つにしてくれる

input = '---PA--I-ZA--'
puts input.squeeze('-')
#=> '-PA-I-ZA-'
3210mo3210mo

文字列の置換 sub, gsub

sub("A","B")・・・ 1つ目の"A"という文字列を"B"に置き換える
gsub("A","B")・・・ 全ての"A"という文字列を"B"に置き換える

S = "phpを私は学習する!php大好き!"

puts S.sub("php","ruby")
#=> rubyを私は学習する!php大好き!

puts S.gsub("php","ruby")
#=> rubyを私は学習する!ruby大好き!
3210mo3210mo

複数行の入力を配列にする times, map

# 入力
3     # n=入力が与えられる数
111
222
333

# よく書くコード
n = gets.chomp.to_i
W = []
n.times do
    W << gets.chomp.to_s
end
p W
#=> ['111', '222', '333']

# かっこいいコード
n = gets.chomp.to_i
W = n.times.map { gets.chomp }
p W
#=> ['111', '222', '333']
3210mo3210mo

配列の中身を並び替え sort, sort_by

sortの基本

昇順、降順に並び替え

array = [300, 200, 150, 400, 100]
p array.sort
#=> [100, 150, 200, 300, 400]
p array.sort.reverse
#=> [400, 300, 200, 150, 100]

文字列も並び替え

array = ["C", "Z", "A", "E"]
p array.sort
#=> ["A", "C", "E", "Z"]

新たな配列を返り値とするので、破壊的メソッドsort!を定義すると自分自身の配列をソートする

array = [300, 200, 150, 400, 100]
# "--- sort (非破壊メソッド) ---"
array.sort
p array
#=> [300, 200, 150, 400, 100]

# "--- sort! (破壊的メソッド) ---"
array.sort!
p array
#=> [100, 150, 200, 300, 400]

構造化データの並び替え

array = [
{"name" => "うどん", "price" => "300"},
{"name" => "パスタ", "price" => "700"},
{"name" => "ラーメン", "price" => "500"},
]
p array.sort {|x, y| x["price"] <=> y["price"] }
#=> [{"name"=>"うどん", "price"=>"300"}, {"name"=>"ラーメン", "price"=>"500"}, {"name"=>"パスタ", "price"=>"700"}]
Ruby特有の比較メソッド <=> について

self <=> otherのような条件であった場合、selfが大きい時に正、等しい時は0、小さい時に負の整数を返す。
Rubyではこの<=>メソッドを使うことにより、大小比較の条件を非常にシンプルに記述できる。

基本的にはsort_byを使用する(処理速度が速いため)

each文のように回してあげるイメージ

array = [300, 200, 150, 400, 100]
p array.sort_by {|value| value}
#=> [100, 150, 200, 300, 400]

回しているもののkeyを取得するイメージ

array = [
{"name" => "うどん", "price" => "300"},
{"name" => "パスタ", "price" => "700"},
{"name" => "ラーメン", "price" => "500"},
]
p array.sort_by {|x| x["price"] }
#=> [{"name"=>"うどん", "price"=>"300"}, {"name"=>"ラーメン", "price"=>"500"}, {"name"=>"パスタ", "price"=>"700"}]

3つの要素を順に多い順に並べる

array = [
  {:kin=>28, :gin=>33, :dou=>59},
  {:kin=>14, :gin=>18, :dou=>28},
  {:kin=>28, :gin=>36, :dou=>38},
  {:kin=>2, :gin=>42, :dou=>73},
  {:kin=>22, :gin=>52, :dou=>81},
  {:kin=>21, :gin=>58, :dou=>71},
  {:kin=>23, :gin=>57, :dou=>82},
  {:kin=>28, :gin=>33, :dou=>59},
  {:kin=>16, :gin=>16, :dou=>19},
  {:kin=>16, :gin=>47, :dou=>92}
]

# ソート処理
sorted_array = array.sort_by { |hash| [-hash[:kin], -hash[:gin], -hash[:dou]] }
3210mo3210mo

入力 gets.chomp.split.map(&:to_i)

1 2 3をひとつずつ変数に代入

HWM = gets.chomp.split(' ')
H = HWM[0].to_i
W = HWM[1].to_i
M = HWM[2].to_i

1行で記述できる

H, W, M = gets.chomp.split.map(&:to_i)
3210mo3210mo

0がN個ある配列を作る

seki = []
N.times do
  seki << 0
end

1行で記述できる

seki = Array.new(N, 0)
3210mo3210mo

each_slice

(1..10).each_slice(3) {|a| p a}
    # => [1, 2, 3]
    #    [4, 5, 6]
    #    [7, 8, 9]
    #    [10]
3210mo3210mo

配列の指定したインデックスの要素を先頭にするrotate

先頭に来るものを指定して、後ろの並びは変わらないイメージ

a = [ "a", "b", "c", "d" ]
a.rotate         # => ["b", "c", "d", "a"]
# 指定しない場合rotate(1)とする
a                # => ["a", "b", "c", "d"]
a.rotate(2)      # => ["c", "d", "a", "b"]
a.rotate(-1)     # => ["d", "a", "b", "c"]
a.rotate(-3)     # => ["b", "c", "d", "a"]

3210mo3210mo

各要素に対してブロックを評価し、その値を抜いた要素を集めて配列にreject

# 偶数を除外する (奇数を集める)
(1..6).reject {|i| i % 2 == 0 } # => [1, 3, 5]
3210mo3210mo

二次元配列の行と列を入れ替えるtranspose

p [[1,2],
   [3,4],
   [5,6]].transpose
# => [[1, 3, 5], [2, 4, 6]]

p [].transpose
# => []

p [1,2,3].transpose

# => -:1:in `transpose': cannot convert Fixnum into Array (TypeError)
#       from -:1

p [[1,2],
   [3,4,5],
   [6,7]].transpose
# => -:3:in `transpose': element size differ (3 should be 2) (IndexError)

3210mo3210mo

各要素の条件を満たすか判定 any?, all?, one?, none?

Array#any?

配列に1つ以上、条件を満たす要素があるか調べるにはArray#any?を使う。

p [1, 2, 3].any?{|i| i % 2 == 0} #=> true
p [1, 3, 5].any?{|i| i % 2 == 0} #=> false

Array#all?

配列のすべての要素が、条件を満たしているか調べるにはArray#all?を使う。

p [1, 2, 3].all?{|i| i % 2 == 0} #=> false
p [2, 4, 6].all?{|i| i % 2 == 0} #=> true

Array#one?

配列に1つだけ、条件を満たす要素があるか調べるにはArray#one?を使う。

p [1, 2, 3].one?{|i| i % 2 == 0} #=> true
p [2, 4, 6].one?{|i| i % 2 == 0} #=> false

Array#none?

配列のすべての要素が、条件を満たしていないことを調べるにはArray#none?を使う。

p [1, 2, 3].none?{|i| i % 2 == 0} #=> false
p [1, 3, 5].none?{|i| i % 2 == 0} #=> true