Easy_8
2つの数字の10進法表記を結合した数が平方数かどうか。
文字列を結合するjoin
joinはいくつかの文字列を結合するメソッド。通常は文字列の配列がオブジェクトだがそれに限らない模様。
join(", ")などとセパレータを指定することができる。
ary = ["a", "bc", "def"]
p! ary.join # => "abcdef"
p! ary.join(',') # => "a,bc,def"
p! ary.join(", ") # => "a, bc, def"
Mathモジュール
数学的な関数はMathモジュール1の中にある。libm?
定数はMath::Cの形。πならMath::PI。
関数はMath.fの形。平方根ならMath.sqrt(x)。引数は整数でも小数でもよいが、結果は小数になるので.to_iをつければ丸め値になる。丸め値の自乗が元の数値になれば平方数。
x = read_line.split.join.to_i
y = Math.sqrt(x).to_i
puts x == y * y ? "Yes" : "No"
Easy_9
$x_i$それぞれについて、$0$と$K$のうち近いほうからの距離の2倍の和をとる。
Enumerable#min, Enumerable#sum
min(x, y)のような引数から最小値を得る関数はMathモジュールにあった。
Array#map{|x| Math.min(x, k-x)}で数列$\{x_i\}$を数列$\{min(x_i,k-x_i)\}$に変換して、Enumerable#sumで和をとる。
n = read_line.to_i
k = read_line.to_i
ans = read_line.split.map(&.to_i).map{|x| 2 * Math.min(x, k-x)}.sum
puts ans
sum(&)
実はEnumerableの各要素にメソッドを適用してから和をとる構文もある。
n = read_line.to_i
k = read_line.to_i
ans = read_line.split.map(&.to_i).sum{|x| 2 * Math.min(x, k-x)}
puts ans
Easy_10
貪欲法。カードを降順に並べ替えたら、$a_1-a_2+a_3-a_4+...+(-1)^{N-1}a_N$が解になる。
sort, sort!, reverse, reverse!
sortは配列を昇順に並べ変える。$O(NlogN)$であろう。
reverseは配列を逆順に並べ変える。$O(N)$であろう。
どちらも!なしと!ありがある。!なしは配列を新たに生成して返す、関数的なメソッド。!ありは元の配列を書き換える、手続き的なメソッド。
a.sort.reverse↩︎とか書くとaをソートして逆順にしたものを生成して捨てておきながらaは変わらないので計算機が報われない。
new_a = a.sort.reverse↩︎ならよいけど。
Iterator#cycle
Iterator#cycleはオブジェクトを無限回繰り返すイテレータ(Iterable)を返す。{1, -1}.cycleだと$1,-1,1,-1,...$。
無限回繰り返すのだが、イテレータなのであらかじめ無限個の数列を生成するのでなく、lazyに必要な分だけ生成する。a.zip({1, -1}.cycle)だと、aと等しい長さだけ生成する。
n = read_line
a = read_line.split.map(&.to_i).sort!.reverse!
ans = a.zip({1,-1}.cycle).sum{|x, y| x*y}
puts ans