【Ruby基礎】AtCoder Beginner Contest 031 B - 運動管理

■はじめに

Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。 基本的にはAtCoderというプログラミングコンテスト競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、難易度の低いA問題かB問題を解いていく)

(5/23時点の方針) メソッドの切り分け方や値の受け渡しを練習するために、コード長の短さについては気にせずに書くことにする。

(2022/10/17時点の方針) しばらくはB問題を小さい番号の方からやっていく。たまにA問題もやるかも。

■問題

●出典

AtCoder Beginner Contest 031のB問題 https://atcoder.jp/contests/abc031/tasks/abc031_b

●問題文

高橋君は AtCoder 社のマスコットキャラクターである。

マスコットキャラクターとしての魅力を維持するために、高橋君は適度な運動をすることになっている。高橋君は週の運動時間が L 分以上 H 分以下でなければならない。

しかしながら、青木君は最近、高橋君が運動しているところを見ていない。高橋君の運動状況が気になった青木君は、高橋君の過去 N 週間の運動時間が制限にあっているのか、そして足りないなら少なくともあと何分運動する必要があったのかを計算するプログラムを作成することにした。

●制約

  • ああああ

●入力

入力は以下の形式で標準入力から与えられる。

L H
N
A1
A2
:
AN
  • 1 行目には、2 個の整数 L, H(1≦L≦H≦10^4 ) が空白区切りで与えられる。これは、高橋君が週に L 分以上 H 分以下の運動をしなければならないことを表す。
  • 2 行目には、整数 N(1≦N≦50) が与えられる。これは青木君が N 週分の運動時間について調べていることを表す。
  • 3 行目からの N 行には、高橋君の運動状況を表す整数が与えられる。N 行の内 i(1≦i≦N) 行目には、整数 Ai (0≦Ai ≦10^4 ) が与えられる。これは i 個前の週において高橋君が Ai 分運動したことを表す。

●出力

出力は N 行からなる。i(1≦i≦N) 行目には、i 個前の週において高橋君が必要な分よりも多く運動している場合は −1 を、そうでない場合は追加で必要な運動時間の最小値を分単位で 1 行に出力せよ。 出力の末尾にも改行を入れること。

■回答

●愚直に書く

久しぶりのB問題。 まずは標準入力をちゃんと取るところから。

l, h = gets.split.map(&:to_i)
n = gets.to_i
a = n.times.map do |line|
  line = gets.to_i
end

# 以下は確認用
p l, h
p n
p a

これで標準入力は取れた。

次に、配列aの各要素がl以上h以下かどうかを判定していく感じか。

l, h = gets.split.map(&:to_i)
n = gets.to_i
a = n.times.map do |line|
  line = gets.to_i
end

a.each do |elm|
  if elm < l
    puts l - elm
  elsif elm > h
    puts -1
  else
    puts 0
  end
end

通った!

●メソッド化して書く

メソッドを作る練習のために、あえてそういう書き方をする。

メインメソッド、判定用メソッド、標準入力を取るメソッド2つの計4つ。 メインメソッド内のeachを回す部分をさらに別メソッドに分けても良いかな?

def main
  l, h = read_target
  a = read_record
  a.each do |elm|
    puts judge(l, h, elm)
  end
end

def judge(l, h, elm)
  if elm < l
    l - elm
  elsif elm > h
    -1
  else
    0
  end
end

def read_target
  gets.split.map(&:to_i)
end

def read_record
  n = gets.to_i
  n.times.map do |line|
    line = gets.to_i
  end
end

main

通った!

リファクタリング/別アプローチ

色々試したけど上手く整理できなかったので割愛…!

●他の方の回答例

maxを使った解答があり、なるほどと思った。

自分の回答に取り入れると以下のような感じ。

l, h = gets.split.map(&:to_i)
n = gets.to_i
a = n.times.map do |line|
  line = gets.to_i
end

a.each do |elm|
  if elm <= h
    puts [l - elm, 0].max
  else
    puts -1
  end
end

これだとif内がシンプルになるしそれによって三項演算子にもしやすい。なるほど。

●出てきたメソッド等

公式リファレンスを見る訓練。

■振り返りなど

計算するのにちょっと混乱してしまった。 とはいえB問題を愚直にでも解けたので良かった。

【Ruby基礎】AtCoder Beginner Contest 079 A - Good Integer

■はじめに

Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。 基本的にはAtCoderというプログラミングコンテスト競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、難易度の低いA問題かB問題を解いていく)

(5/23時点の方針) メソッドの切り分け方や値の受け渡しを練習するために、コード長の短さについては気にせずに書くことにする。

(2022/10/17時点の方針) しばらくはB問題を小さい番号の方からやっていく。たまにA問題もやるかも。

■問題

●出典

AtCoder Beginner Contest 079のA問題 https://atcoder.jp/contests/abc079/tasks/abc079_a

●問題文

1118 のような、3 つ以上の同じ数字が連続して並んだ 4 桁の整数を 良い整数 とします。 4 桁の整数 N が与えられるので、N が 良い整数 かどうかを答えてください。

●制約

  • 1000≦N≦9999
  • 入力は整数からなる

●入力

入力は以下の形式で標準入力から与えられる。

N

●出力

N が 良い整数 ならば Yes を、そうでなければ No を出力せよ。

■回答

●愚直に書く

えーと、1つずつ配列に入れて、要素が重複してたらまとめるようなメソッドがあった気がするのでそれをやって、まとめた後の要素数が1か2であれば大丈夫か? いや、それだと1122みたいな時もまとめた後の要素数が2になるからダメだな。。。

うーん、愚直に考えて、まず配列の要素をsortして、1番目と2番目と3番目が等しければYesってことで良いか…?

やってみよう。

n = gets.chomp.split("").map(&:to_i).sort
if n[0] == n[1] && n[0] == n[2]
  puts "Yes"
else
  puts "No"
end

通った! もうちょっとスマートな方法はありそう…!

●メソッド化して書く

メソッドを作る練習のために、あえてそういう書き方をする。

今日は割愛。

リファクタリング/別アプローチ

絶対もっとシンプルにできそう、、、

やたら試行錯誤してしまったが、sortしているので、「1番目と2番目と3番目が等しければ」ではなく1番目と3番目が等しければ」だけで今回の条件は満たせそう。

n = gets.chomp.split("").map(&:to_i).sort
if n[0] == n[2]
  puts "Yes"
else
  puts"No"
end

通った!

三項演算子にして、

n = gets.chomp.split("").map(&:to_i).sort
puts n[0] == n[2] ? "Yes" : "No"

通った!

●他の方の回答例

アッ、正規表現…! そうか正規表現でできたのか〜。 ただ、回答例を見てもどういう書き方になっているかよく掴めていない…。

puts gets[/(.)\1\1/]?:Yes: :No

/(.)\1\1/、特に\1がわからなかったのでChatGPTさんに聞いた。

なるほど、/(.)\1\1/は同じ文字が3回連続ということか。

あと以下の回答もあって、これは力技だけどわかりやすい…!

puts gets=~/111|222|333|444|555|666|777|888|999|000/ ? "Yes" : "No"

●出てきたメソッド等

公式リファレンスを見る訓練。

■振り返りなど

正規表現を思いつけず悔しかった。 あと正規表現の理解が浅く、もうちょっと勉強せねばと思った。

【Ruby基礎】AtCoder Beginner Contest 078 A - HEX

■はじめに

Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。 基本的にはAtCoderというプログラミングコンテスト競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、難易度の低いA問題かB問題を解いていく)

(5/23時点の方針) メソッドの切り分け方や値の受け渡しを練習するために、コード長の短さについては気にせずに書くことにする。

(2022/10/17時点の方針) しばらくはB問題を小さい番号の方からやっていく。たまにA問題もやるかも。

■問題

●出典

AtCoder Beginner Contest 078のA問題 https://atcoder.jp/contests/abc078/tasks/abc078_a

●問題文

プログラミングでは 16 進数がよく使われます。 16 進数では 0,1,...,9 の数字の他に A, B, C, D, E, F の 6 つのアルファベットを使い,それぞれ 10,11,12,13,14,15 を表します。 この問題では 2 つのアルファベット X,Y が与えられます。 X と Y はどちらも A, B, C, D, E, F のうちどれかです。 X と Y を 16 進数として見たとき,どちらのほうが大きいかを判定してください。

●制約

  • X,Y は A, B, C, D, E, F のうちどれかである。

●入力

入力は以下の形式で標準入力から与えられる。

X 
Y

●出力

X のほうが小さいならば <, Y のほうが小さいならば >, 等しいならば = と出力してください。

■回答

●愚直に書く

問題がややこしいけど、要はABCDEFの中から2文字がチョイスされてそれを比較すれば良さそう。

a, b = gets.split
if a > b
  puts ">"
elsif a < b
  puts "<"
else
  puts "="
end

通った!

●メソッド化して書く

メソッドを作る練習のために、あえてそういう書き方をする。 久しぶりなのでやってみるか…!

メインメソッド、大小記号を判定するメソッド、標準入力を取得するメソッドの3つを作成。 久しぶりすぎて忘れていたので過去投稿も参考にしつつ作成した。

def main
  a, b = read_str
  puts judge(a, b)
end

def judge(a, b)
  if a > b
    ">"
  elsif a < b
    "<"
  else
    "="
  end
end

def read_str
  gets.split
end

main

通った!

リファクタリング/別アプローチ

if文のところもうちょっとスッキリできそうな気がするけど思いつかないなぁ。 なんとなく宇宙船演算子<=>)が活かせそうな気がするんだけどうまく落とし込めない。

と思いながら過去の自分の投稿で宇宙船演算子が出てきたものを見返していたら思いついた!

a, b = gets.split
puts "=><"[a <=> b]

通った〜〜〜うれしい!!

ちなみに参照した過去記事はこちら https://sugie.co/2022/11/22/ruby-abc071a/

今回でいうと、a <=> bを評価した時に-101が返って来るので、=><という文字列のインデックス部分に[a <=> b]を入れることで下記のようになる。

  • aがbより手前の文字→宇宙船演算子-1が返る→puts "=><"[-1]なので<が出力
  • aがbと同じ文字→宇宙船演算子0が返る→puts "=><"[0]なので=が出力
  • aがbより後の文字→宇宙船演算子1が返る→puts "=><"[1]なので>が出力

●他の方の回答例

上位層はほとんど宇宙船演算子を使っていた。 三項演算子入れ子を使っている人もチラホラ。

●出てきたメソッド等

公式リファレンスを見る訓練。

■振り返りなど

久しぶりにAtCoderできて楽しかった。 宇宙船演算子を使えて嬉しかった。

【GitHub】リモートmainブランチの最新状態をローカルの作業用ブランチに取り込む

自分用のメモ。

  1. git switch mainで一旦mainブランチに移動
  2. git pullでリモートのmainを取り込む
  3. git switch branch1で作業用ブランチに移動
  4. git merge mainでmainの最新状態作業用ブランチに取り込む

【Ruby基礎】AtCoder Beginner Contest 077 A - Rotation

■はじめに

Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。 基本的にはAtCoderというプログラミングコンテスト競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、難易度の低いA問題かB問題を解いていく)

(5/23時点の方針) メソッドの切り分け方や値の受け渡しを練習するために、コード長の短さについては気にせずに書くことにする。

(2022/10/17時点の方針) しばらくはB問題を小さい番号の方からやっていく。たまにA問題もやるかも。

■問題

●出典

AtCoder Beginner Contest 077のA問題 https://atcoder.jp/contests/abc077/tasks/abc077_a

●問題文

縦 2 マス、横 3 マスのマス目が与えられます。上から i 行目、左から j 行目のマスの色は、Cij で表されます。 このマス目を180度回転させたとき、元のマス目と一致するなら YES を、そうでないなら NO を出力するプログラムを作成してください。

●制約

  • Cij (1≤i≤2,1≤j≤3) は英小文字である。

●入力

入力は以下の形式で標準入力から与えられる。

C11 C12 C13
C21 C22 C23

●出力

マス目を180度回転させたとき、元のマス目と一致するなら YES を、そうでないなら NO を出力せよ。

■回答

●愚直に書く

2行目をreverse して1行目と一致すればYESってことかな。

a = gets.chomp
b = gets.chomp
puts a.reverse == b ? 'YES' : 'NO'

通った!

●メソッド化して書く

メソッドを作る練習のために、あえてそういう書き方をする。

久しぶりに書くか。 2行の標準入力取得をメソッド内で書くのはどうやるんだっけ、、、

def main
  a, b = read_lines
  puts rorate?(a, b)
end

def rorate?(a, b)
  a.reverse == b ? 'YES' : 'NO'
end

def read_lines
  2.times.map do |line|
    line = gets.chomp
  end
end

main

通った!

リファクタリング/別アプローチ

リファクタリングは今日は無し。

●他の方の回答例

基本的に皆さん同じアプローチのようだった。

●出てきたメソッド等

公式リファレンスを見る訓練。

■振り返りなど

メソッド化をサボっていたのでかなり忘れていたが、久しぶりに書けてよかった。

【Ruby基礎】AtCoder Beginner Contest 076 A - Rating Goal

■はじめに

Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。 基本的にはAtCoderというプログラミングコンテスト競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、難易度の低いA問題かB問題を解いていく)

(5/23時点の方針) メソッドの切り分け方や値の受け渡しを練習するために、コード長の短さについては気にせずに書くことにする。

(2022/10/17時点の方針) しばらくはB問題を小さい番号の方からやっていく。たまにA問題もやるかも。

■問題

●出典

AtCoder Beginner Contest 076のA問題 https://atcoder.jp/contests/abc076/tasks/abc076_a

●問題文

高橋君はあるプログラミングコンテストが行われているサイトに参加しています。 ここでは, コンテストに出場した時にこの順位に応じて「パフォーマンス」というものがつき、それによってレーティング (整数とは限らない) が次のように変化します。

  • 現在のレーティングを a とする。
  • 次のコンテストで, パフォーマンス b を取ったとする。
  • そのとき, レーティングは a と b の平均まで変化する。

例えば, レーティングが 1 の人が次のコンテストでパフォーマンス 1000 を取ったら, レーティングは 1 と 1000 の平均である 500.5 になります。

高橋君は, 現在のレーティングが R で, 次のコンテストでレーティングをちょうど G にしたいと思っています。 そのとき, 高橋君が取るべきパフォーマンスを求めなさい。

●制約

  • 0 ≤ R,G ≤ 4500
  • 入力はすべて整数

●入力

入力は以下の形式で標準入力から与えられる。

R
G

●出力

高橋君が取るべきパフォーマンスを出力しなさい。

■回答

●愚直に書く

Gを2倍してRを引けば良さそう。

r = gets.to_i
g = gets.to_i

puts g * 2 - r

通った!

●メソッド化して書く

メソッドを作る練習のために、あえてそういう書き方をする。

今回はメソッド化する余地もあまりないかな…。

リファクタリング/別アプローチ

リファクタリングも特に思いつかない…。標準入力を1行で取るとかはできるのかな。

●他の方の回答例

方針としては皆さん一緒だった。

コンパクトにまとめるなら以下のような感じ。

puts -gets.to_i+2*gets.to_i

なるほど。

●出てきたメソッド等

公式リファレンスを見る訓練。

今回特に無し!

■振り返りなど

  • 久しぶりだったので取っ付きやすい難易度で良かった。

以下テスト リンク

【Ruby基礎】AtCoder Beginner Contest 075 A - One out of Three

■はじめに

Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。 基本的にはAtCoderというプログラミングコンテスト競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、難易度の低いA問題かB問題を解いていく)

(5/23時点の方針) メソッドの切り分け方や値の受け渡しを練習するために、コード長の短さについては気にせずに書くことにする。

(2022/10/17時点の方針) しばらくはB問題を小さい番号の方からやっていく。たまにA問題もやるかも。

■問題

●出典

AtCoder Beginner Contest 075のAB問題 https://atcoder.jp/contests/abc075/tasks/abc075_a

●問題文

3 つの整数 A,B,C が与えられます。 A,B,C のうち 2 つは 同じ整数であり、残りの 1 つだけ異なる整数です。 例えば、A=5,B=7,C=5 の場合、A,C の 2 つは同じ整数であり、B は 1 つだけ異なる整数です。 3 つの整数のうち、1 つだけ異なる整数を求めてください。

●制約

  • −100≦A,B,C≦100
  • A,B,C は整数
  • 入力は問題文の条件を満たす

●入力

入力は以下の形式で標準入力から与えられる。

A B C

●出力

A,B,C のうち、1 つだけ異なる整数を出力せよ。

■回答

●愚直に書く

なんかunique みたいなメソッドがあったような気がする…。 →uniqだった。そしてこれは重複した要素を取り除くというメソッドなので、今回使えるわけではないか…!?

めちゃくちゃ愚直に考えると、以下の条件分岐で解答にはなるかな?

  • A=BだったらC
  • A≠Bだったら下記
    • A=CだったらB
    • A≠CだったらA
a, b, c = gets.split.map(&:to_i)
if a == b
  puts c
else
  if a == c
    puts b
  else
    puts a
  end
end

通った! これはもうちょっと上手く書きたい気がするが…。

●メソッド化して書く

メソッドを作る練習のために、あえてそういう書き方をする。

今回の問題は割愛しようかな…。

リファクタリング/別アプローチ

先に並べ替えをしておくと条件分岐がシンプルになるのではないかと思ったのでやってみる。 並べ替えをするには、3つの数字を1つの配列に入れないといけないか。

array = gets.split.map(&:to_i).sort

if array[0] == array[1]
  puts array[2]
else
  puts array[0]
end

通った! なんかもうちょっとうまい方法ありそうだけど、今日はここまでにしておくか…。

●他の方の回答例

コード長一番短い方の回答↓

p eval`tr ' ' ^`

なんだこれは笑。

最上位の方々に限らず^を使っている方が多いなぁ、なんだこれは。ビット演算子か。

●出てきたメソッド等

公式リファレンスを見る訓練。

今日は無し。

■振り返りなど

今日はちょっと不完全燃焼になってしまった。 ビット演算子、ちゃんと確認しておきたい。