Help us understand the problem. What is going on with this article?

プログラミングたのしー!って思った出来事(Paizaの問題を解いた時に遭遇した体験のメモ書き)

More than 3 years have passed since last update.

はじめに

Paizaの「もし次の常駐先が女子エンジニアばかりだったら」(もし女)を解いた時に
「同じ内容でもソースコードってこんなに変わるのか……」っていうのを実体験したので、その時の事をメモ代わりにおいて置きます。

問題文

緑川つばめを窮地から救え (Bランク問題)
https://paiza.jp/moshijo/challenge/moshijo_character_9

最初に書いた時のソースコード

shisya2.rb
n = gets.to_i
l = n.to_s.length
def ary(a)
  a = []
end

ans = []
(l - 1).times do |h|
  ans << ary(h)
end

ansl = ans.length
if l == 1
  if n < 5
  ans << n
  else
  ans << n.round(-1)
  end
elsif l == 2
  ans << n.round(-0)
  ans << n.round(-1)
else
  ansl.times do |m|
    break if m + 1 == ansl
    l.times do |i|
      ans[m] << n #これを入れておかないと、100みたいな値を入れたときに表示が出ない
      ans[m] << n.round(-i) if n.round(-i) > n# ifで改行するとendの数がずれて動かなくなる
      ans[m].each do |j|
        if j.round(-i) > n.round(-i) && j.round(-i) != n.round(-i)
          ans[m + 1] << j.round(-i)
          ans[m + 1].uniq!
        end
      end
    end
  end
end
m = ans.flatten.max
#以下のif文は、445を入れた時に500で止めずに1000まで行かせるため,何も考えずにroundさせると123とかが0になるのでifで場合分け
if m > m.round(-l)
  puts m
else
  puts m.round(-l)
end

もはや自分でも何がしたかったか良く分からないコードに(むしろこれでよくテストケース通ったな・・・・・・)
配列の中に配列を作って、その中に四捨五入した値を入れて、最終的にその中の最大値を取り出す的な事をしたかったらしい。

このソースコードを提出した次の日
ある配列操作のメソッドを知り、それを利用することで大幅に改善する事ができた。

改善後のソースコード

shisya4.rb
n =gets.to_i
l = n.to_s.length
ans = []
ans << n

(0..l).each do |i|
  if ans[0] < ans[0].round(-i)
    ans << ans[0].round(-i)
    ans.shift
  else
    #何もしない
  end
end

puts ans[0]

一体何があったのか分からないぐらいシンプルになる。
重要なメソッドは.shift
配列の最初の要素を消してくれるメソッドである。
これにより、配列の中身が常に最大の数になったため、場合分けが1回で済むようになった
動きも単純になり、
値を比較して、もし大きければ配列に格納、その後に先端の値を削除する。違ったら何もしない
という誰が見ても分かるようになった。

で、何が言いたいか

プログラミングってたのしー!

オマケ

他の問題のソースコードも置いておきます
御影百合絵からのお願い  (Dランク問題)

abc.rb
a = gets.to_i
b = gets.to_i
c = gets.to_i

sum = a + b + c
puts sum

春日みちるからのSOS (Dランク問題)

help.rb
a = gets.to_s
re =Regexp.new("help")
if re =~ a
 puts "SOS"
else
 puts a
end

園田冴絵からの応援要請 (Dランク問題)

abp.rb
a,b,c= gets.split

d = a.to_i+b.to_i
e = a.to_i-b.to_i

if c == '+' then
puts d
elsif
puts e
end

芦屋川雛乃からのヘルプ依頼 (Cランク問題)

angou.rb
a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = gets.split.map(&:to_i)
s = gets.chop.to_s #chopで改行コードを消さないとifの時にマッチしないので注意
t = gets.chop.split('').map(&:to_i) # chopは改行コードを落すため、この状態で配列を作成すると最後に\nが入って、to_iで数値化した時に最終的に0になる
ary = [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9]

# encode時の処理
if s == "encode"
  x = []
  t.each do |i|
    x << ary[i]
  end
  puts x.join
else
  # decode時の処理
  y = []
  t.each do |i|
    y << ary.index(i)
  end
  puts y.join
end

桂乃梨子とピンチを乗り越えろ (Cランク問題)

nmath.rb
n = gets.to_i
ary1 = gets.split.map(&:to_i)
ary2 = gets.split.map(&:to_i)

aryc = ary1.slice(0,n)
aryr = ary2.slice(0,n)

aryf = []
aryr.product(aryc) do |i,j|
  aryf << i + j
end

arys = aryf.each_slice(n).to_a

arys.each do |n|
  puts n.join(" ")
end

水無瀬朋の一大事 (Cランク問題)

ncp.rb
n = gets.to_i
h = {}
n.times do |i|
  h[i+1] = gets.split.map(&:to_i)
end

m = gets.to_i
ary = []
m.times do |j|
  ary[j] = gets.split.map(&:to_i)
end

m.times do |k|
  item = h[ary[k][0]]
  op= item[0] * ary[k][1] #opはoriginal_priceから
  dc = (ary[k][1] / item[1]) * item[2] #dcはdiscountから
  price = op - dc
  puts price
end

六村リオの緊急事態 (Bランク問題)
まだ解けてないです
(絶対パスは分かるけど、相対パスの位置関係が・・・・・・)

参考にしていただければ幸いです。

wing-x
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away