(備忘録)AtCoderをやって 5 (Otoshidama)
問題
日本でよく使われる紙幣は、10000 円札、5000 円札、1000 円札です。以下、「お札」とはこれらのみを指します。
青橋くんが言うには、彼が祖父から受け取ったお年玉袋にはお札が N 枚入っていて、合計で Y 円だったそうですが、嘘かもしれません。このような状況がありうるか判定し、ありうる場合はお年玉袋の中身の候補を一つ見つけてください。なお、彼の祖父は十分裕福であり、お年玉袋は十分大きかったものとします。
制約
1≤N≤2000
1000≤Y≤2×10 7
N は整数である。
Y は 1000 の倍数である。
自分の回答(他の方回答参考)
0..nを用いてeachを使うのかなというのは思いついていましたが、 入れ子させたeachの方でn-aのようにする発想は思いつきませんでした。 あと一万円、五千円、千円の枚数をeach文の中でputsさせるような実装を考えていましたが、 それぞれの初期値を-1(該当しなかった場合の返り値)に設定しておき、each文が終わった後でputsさせる方が 分かりやすかったですね。
n, y = gets.split.map(&:to_i) ten_thousand_yen = -1 five_thousand_yen = -1 thousands_of_yen = -1 (0..n).each{ |a| (0..n - a).each{ |b| if y == (10000*a + 5000*b + 1000*(n-a-b)) ten_thousand_yen = a five_thousand_yen = b thousands_of_yen = (n-a-b) end } } puts "#{ten_thousand_yen} #{five_thousand_yen} #{thousands_of_yen}"
その他回答
putsをeachの中で使っているパターン。foundを初期値falseにして置いてマッチするパターンが見つかった時にfoundをtrueにしてcatch throwを使って全てのループを脱出するわけですね。(最初breakで良くね?と思ったけどbreakだと一番内側の繰り返ししか脱出できないからだとわかった)
N,Y = gets.split.map(&:to_i) found = false catch(:break_loop) do (0..N).each do |a| (0..(N-a)).each do |b| c = N-a-b if a*10000 + b*5000 + c*1000 == Y puts "#{a} #{b} #{c}" found = true throw :break_loop end end end end puts "-1 -1 -1" unless found