【AtCoder:12回目】AtCoder Beginner Contest 135の振り返り(Ruby)

【目次】

【本題】

振り返り

今回は 7/28(土)に開催されたAtCoder Beginner Contest 135の振り返りを行います。

AtCoder Beginner Contest 135 - AtCoder

今回1問しか回答できませんでした・・・まるで成長していない・・・

レーティング微減

A - Harmony

問題文 相違なる整数 A , B があります。

| A − K |

= | B − K | となるような整数 K を出力してください。

そのような整数が存在しなければ、代わりに IMPOSSIBLE を出力してください。

制約 入力は全て整数である。 0 ≤ A ,

B ≤ 10 9 A と B は相違なる。

AとBをそれぞれ1づつ引いていくと、互いが偶数同士(奇数同士)であれば、必ず|A−K|=|B−K|になるのですが、偶数と奇数(奇数と偶数)になると、交わる事はありません。

なので、両方とも偶数(奇数)か?という条件で、出力を制御しました。

その結果が、以下のコードです。

a,b = gets.split.map(&:to_i)

if (a.even? && b.even?) || (a.odd? && b.odd?)
  puts (a + b) / 2
else
  puts 'IMPOSSIBLE'
end

三項演算子にした方が、スマートかもしれません。

A,B = gets.split.map(&:to_i)
c = A + B
puts c.odd? ? 'IMPOSSIBLE' : c / 2

B - 0 or 1 Swap

問題文 { 1 ,

2 ,

. . . ,

N } を並び替えた数列 p = { p 1 ,

p 2 ,

. . . ,

p N } があります。

あなたは一度だけ、整数

i ,

j

( 1 ≤ i < j ≤ N ) を選んで

p i

p j

を入れ替える操作を行うことができます。操作を行わないことも可能です。

p を昇順にすることができるなら YES を、できないならば NO を出力してください。

制約 入力は全て整数である。 2 ≤ N ≤ 50 p は { 1 ,

2 ,

. . . ,

N } を並び替えた数列である。

一回目は、以下の様なロジックでコードを実装しました。

1:昇順でソートした配列と、そのままの配列を比較して、相違する箇所を抽出します。

2:相違する箇所が2箇所以上なら、NOを返す(並べ換えは1回のみの為)

3:相違する箇所を、ソートした箇所と置換する

4:3とソートした配列が一致すればYESを返し、一致しなければNOを返す

n=gets.to_i

while p1 = $stdin.gets do
  p = p1.chomp.split(" ")
end

cange = []
p.zip(p.sort) do |p, p_sort|
  cange << p if p != p_sort
end

return puts 'NO' if cange.size > 2

canged = p.map do |p|
  case p
  when cange[0]
    cange[1]
  when cange[1]
    cange[0]
  else
    p
  end
end

if canged == p.sort
  puts 'YES'
else
  puts 'NO'
end

しかし、これでは一部のサンプルで実行時エラーになってしまいました。

次に思い付いたのは、わざわざ置換せずとも、相違する箇所が2箇所以内であれば、どの様な数値の並びであっても昇順になるだろうという仮説の基、以下の様にコードを実装しました。

n=gets.to_i

while p1 = $stdin.gets do
  p = p1.chomp.split(" ")
end

cange = []
p.zip(p.sort) do |p, p_sort|
  cange << p if p != p_sort
end

if cange.size > 2
  puts 'NO'
else
  puts 'YES'
end

しかし、これは一部のサンプルが通りませんでした。

もうこうなると、取っ掛かりが無くて、回答できる気がしなくなってしまう・・・

そして、最後に以下の様にzipメソッドを使わない方法を試したりなどしましたけど、テストケースが通らず、終了となりました。

n=gets.to_i

while p1 = $stdin.gets do
  p = p1.chomp.split(" ")
end

p_sort = p.sort
cange = p.map.with_index { |p, index| p if p != p_sort[index] }
cange.compact!

if cange.size != 2 ||  p != p_sort
  puts 'NO'
else
  puts 'YES'
end

相違が二つ以内ならYESで出力する以下のコードで最終的に通りました。

N = gets.to_i
p = gets.split(' ').map(&:to_i)
p_sorted = p.sort
count = 0
 
N.times do |i|
  count += 1 if p[i] != p_sorted[i]
end
 
puts count <= 2 ? 'YES' : 'NO'

煮詰まるとおかしな方法に走ってしまう・・・