【Ruby基礎】AtCoder Beginner Contest 074 A - Bichrome Cells

■はじめに

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

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

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

■問題

●出典

AtCoder Beginner Contest 074のAB問題 https://atcoder.jp/contests/abc074/tasks/abc074_a

●問題文

N×N のマス目があります。 このマス目の各マスを白色または黒色に塗ることにしました (すべてのマスをどちらか片方の色に塗ります)。 ちょうど A マスを白色に塗るとき、黒色に塗ることになるマスはいくつあるでしょうか。

●制約

  • 1≦N≦100
  • 0≦A≦N^2

●入力

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

N
A

●出力

黒色に塗ることになるマスの個数を出力せよ。

■回答

●愚直に書く

Nを2乗してAを引けばOKかな?

n = gets.to_i
a = gets.to_i
puts n * n - a

通った!

●メソッド化して書く

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

今回は割愛するか…。

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

リファクタリングもあまり思いつかない。

調べてみたところ、a ** bでaのb乗とのことなので、 それを使うと共に変数に入れるのも省略して書いてみる。

puts gets.to_i ** 2 - gets.to_i

通った!

●他の方の回答例

考え方としては皆さん同様だった。

●出てきたメソッド等

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

■振り返りなど

ちょっと久しぶりになってしまったけど、スムーズに解けて良かった。

【Ruby基礎】AtCoder Beginner Contest 073 A - September 9

■はじめに

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

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

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

■問題

●出典

AtCoder Beginner Contest 073のAB問題 https://atcoder.jp/contests/abc073/tasks/abc073_a

●問題文

今、日本は 9 月 9 日です。 二桁の整数 N が与えられるので、十進法で N に 9 が含まれるか答えてください。

●制約

  • 10≦N≦99

●入力

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

N

●出力

9 が含まれるとき Yes 、含まれないとき No を出力せよ。

■回答

●愚直に書く

2桁の数字の十の位もしくは一の位(あるいはその両方)に9が使われているかどうかの判定、ということか。

a, b = gets.chomp.split("").map(&:to_i)
puts a == 9 || b == 9 ? 'Yes' : 'No'

通った!

●メソッド化して書く

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

メインメソッド、9が含まれているかの判定メソッド、標準入力を取得するメソッドの3つを作成。

def main
  a, b = read_nums
  puts include_9?(a, b)
end

def include_9?(a, b)
  a == 9 || b == 9 ? 'Yes' : 'No'
end

def read_nums
  gets.chomp.split("").map(&:to_i)
end

main

通った!!

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

正規表現が使えそうな気がする。

n = gets.chomp
puts n.match('9') ? 'Yes' : 'No'

通った!

●他の方の回答例

あ〜そうか正規表現じゃなくてもinclude?でできるのか。 あと、9があるかどうかを調べるだけだからchompも無くて大丈夫。

n = gets
puts n.include?('9') ? 'Yes' : 'No'

●出てきたメソッド等

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

■振り返りなど

久しぶりにやったので標準入力の取り方とかがちょっとうろ覚えだったが、割とスムーズに解けて良かった。

2022年の振り返り

2022年を雑に振り返っていく。

法人化して3年が経った

  • 弊社は10月末決算なので、こないだの10月に三期目が終わった。
    • 継続してお仕事をいただけるのは本当にありがたいというのがまず第一。
    • 一方、今年は仕事を詰め込みすぎてしまい、精神的にかなり厳しいタイミングが数回あった。後述するプログラミング学習との兼ね合いが本当に難しい。

仕事について

  • 今年もウェブまわりが多かった。
    • 過去に制作したサイトの改修や機能追加が増えている。
  • Ruby界隈でのプロジェクトやお仕事に関わり始めることができてとても嬉しい。



  • 2020年2021年と連続入賞できていたタイポグラフィ年鑑、今年はダメだった、悔しい。
    • あれもこれもというのは欲張りだけど、ロゴデザインは好きなのでロゴ案件沢山したいし来年も年鑑には挑戦したい。

フィヨルドブートキャンプ(FBC

  • 2021年秋から入会したプログラミングスクール、フィヨルドブートキャンプ

  • FBCでは日報を提出する仕組みがあって、その記録によると今年は450時間くらい勉強していたっぽい。

    • 目標は1日2時間で700時間だったので遠く及ばないけど、仕事もある中では奮闘した方かな…。
  • 夏〜秋にかけて挫折の危機があったが、持ち直すことができてよかった。

    • 仕事が大変な時期の学習は本当に辛かった。辛かったというか、何もできてない笑。自分はまだ志半ばなので、卒業した人達を本当に尊敬する。
  • ようやくRailsのプラクティスに到達して感慨深い。でもまだまだ先は長いなぁ。

  • 朝活仲間ができて嬉しい。1月から早朝輪読会が始まる予定で楽しみ。

  • 果たして来年卒業できるのか!?早く自作サービス作りたい。

  • 関連話題1。FBC仲間のはるぐちさんの影響で競プロのAtCoderを始めた。来年はB問題をサクサク解けるようになりたいな〜。

  • 関連話題2。FBC仲間で現在は休会中のNishimeさんが主宰しているコミュニティ「RESTUDY Cafe」のロゴを作らせてもらった。 https://tsuyochannel.hateblo.jp/entry/2022/07/18/101325

生活

  • 相変わらずの早朝生活。フィヨルドブートキャンプ内でも早朝仲間と呼べる人が何人かできて、嬉しい。
  • 今年はパーソナルトレーニングをやっていた。3月から12月まで。体重は4kgほど落ちて、今現在の体重をキープしておきたい。ついでに言うと脂肪をもうちょっと落として筋肉をつけたい。
    • 来年はちょこざっぷをやろうと思っている。奇跡的に自宅から徒歩5分くらいのところに店舗ができたので通いたい。
  • 2020年頃に一度挫折したscrapbox日記。その時は非公開でやっていたけど、秋頃から新アカウントで公開で始めた。公開のが良いかもなと思っている。 よろしければ覗いてみてください。→ 🌲 sugie box 📦 (と言いつつ年末頃はあまりちゃんと書けてない)
  • 娘が小学校に入学した。どんどん大きくなる。
  • 保護猫を2匹、迎えた!かわいくて仕方ない。

総括と2023年

  • 2022年も充実し、ドタバタとあっという間に過ぎた1年だった。昨年同様、新しくプログラミング学習にチャレンジしているので、何か大きく前進したというよりは自身の力を蓄えるためにもがいていた1年でもあった。
  • 2023年は何と言ってもフィヨルドブートキャンプ卒業を目指したい!卒業即ち自作サービスのリリースでもある。最近、自作サービスを自社サービスとしてリリースしている例を知り、FBC的にもなんら問題ないとのことがわかったので、頑張りたい。すぐに収益化が難しくとも、ちゃんとリリースして育てていけるようなサービスを作りたいなぁ。
  • 仕事の進め方や領域については引き続き手探りながらも模索していきたい。
  • 来年、本厄なので自分の健康にも気をつけたい。
  • 雑談っぽいPodcastを誰かとやりたい。
  • 年明け、2023年の抱負もちゃんとまとめたい。

【Ruby基礎】AtCoder Beginner Contest 072 A - Sandglass2

■はじめに

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

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

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

■問題

●出典

AtCoder Beginner Contest 072のA問題 https://atcoder.jp/contests/abc072/tasks/abc072_a

●問題文

X 秒を測れる砂時計があります。はじめ上のパーツに砂が X [g] あり、1 秒間に 1 [g] 砂が落ちます。なお、上のパーツにもう砂が残っていない場合は砂は落ちません。

t 秒後に上のパーツに残っている砂は何gでしょう。

●制約

  • 1≤X≤10^9
  • 1≤t≤10^9
  • X,t は整数

●入力

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

X t

●出力

t 秒後に上のパーツに残っている砂は何gかを出力せよ。

■回答

●愚直に書く

Xからtを引いて、0以上ならその数値、0より小さければ0、という感じか。

x, t = gets.split.map(&:to_i)
puts x - t >= 0 ? x - t : 0

通った!

●メソッド化して書く

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

メインメソッド、砂の残りの重さを計算するメソッド、標準入力を取るメソッドの3つ。

def main
  x, t = read_nums
  puts sand_weight(x, t)
end

def sand_weight(x, t)
  x - t >= 0 ? x - t : 0
end

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

main

通った!

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

minメソッドとか使えそうな気がする

x, t = gets.split.map(&:to_i)
puts [x - t, 0].max

勘違いしてた、maxメソッドの方だった汗。 x-t0の大きい方を表示、とすれば求める回答になる。

●他の方の回答例

みなさんほとんどmaxメソッドを使っていた。 あと上位の方はevalを使って標準入力を取る時点でx-tを済ませている感じだった。

●出てきたメソッド等

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

■振り返りなど

maxメソッドに気づくことができて良かった。

Ruby初心者がAtCoderの過去問から多くの学びを得るために工夫していること

こんにちは、sugieこと@hiromisugieです。

■はじめに

この記事は、フィヨルドブートキャンプのアドベントカレンダー2022、11日目の記事です。 フィヨルドブートキャンプのアドベントカレンダー2022は、Part1とPart2があります。 ☞ フィヨルドブートキャンプ Part 1 Advent Calendar 2022 ☞ フィヨルドブートキャンプ Part 2 Advent Calendar 2022

Part1の10日目は、まいむさんによる「【名前重要】と向き合っている話」でした。

Part2の10日目は、nicole 2525さんによる「仕事をしながらパートナーと学習する日々について」でした。


●この記事は何か?

AtCoderの過去問を自分でコツコツ解くようになったsugieが、少しでも色々なことを学びとするために工夫していることを紹介していく記事です。

AtCoderをやってみようかな?」と思っている方の参考になれば嬉しいですし、諸先輩方の「もっとこうしてみたら」というアドバイスがあれば嬉しいです🙏


●用語説明

この記事で頻繁に出てくる用語についてご説明します。

  • フィヨルドブートキャンプ
    • sugieが入会しているNiceなプログラミングスクール。以下、略称のFBCと表記します。
  • AtCoder
    • 競技プログラミング」と呼ばれるコンピュータプログラムのコンテストを行うサービス。オンラインで毎週コンテストを開催していますが、sugieはRubyの練習のために過去問を解いています。
  • 勝手にモブプロ会
    • FBCの先輩で卒業生のはるぐちさんが定期的(現在は不定期)にFBC内のDiscordで開催している会。何人かでDiscordのボイスチャットをつないで、AtCoder過去問のA問題とB問題をワイワイ解いています。この会のおかげでsugieはAtCoderを知り、後述するように自分でも解くようになりました。

AtCoder過去問を解く際の流れ

上述のように、「勝手にモブプロ会」でAtCoderを知ったsugieは競プロの面白さの一端を知り、また、もっとRubyに慣れ親しむために、AtCoderの過去問を解くようになりました。そして、自分の回答やそこで得られた気づき等をブログに上げています。

ここからは、自分がAtCoder過去問をどのように進めているのか、また、どんなことに気を付けているのかを、実際に最近解いた問題と共にご紹介していきます。(意図が伝わりやすくするために、実際のブログ記事から少しだけ加筆修正しています)

ここで例に出している問題→AtCoder Beginner Contest 070のA問題


①問題を読む

まず最初に問題を読みます。問題文とともに制約条件、入力例も載っているので、それらを見ながら問題の意味するところを理解していきます。

この時の問題文は以下の内容でした。

●問題文 3 桁の正の整数 N が与えられます。 N が 回文数であるかを判定してください。 回文数とは、10 進法において数字を逆から並べても元の数と同じになる数のことを表します。   ●制約 100 ≦ N ≦ 999 N は整数   ●入力 入力は以下の形式で標準入力から与えられる。

N

●出力 N が回文数である場合は Yes、そうでない場合は No を出力せよ。   (A - Palindromic Number より引用)


②愚直に書く

まずはコードの綺麗さなどのことは置いておいて、答えを出すことを優先して書いていきます。できるだけ思考の流れも書いたり、途中うまくいかなかったことも書き留めておくようにしています。

この時は、下記のような流れで考えていきました。

ひっくり返しても等しければ Yesという感じかな?

n = gets.chomp
if n == n.reverse
  puts 'Yes'
else
  puts 'No'
end

そしてif式を三項演算子にして、

n = gets.chomp
puts n == n.reverse ? 'Yes' : 'No'

通った!


③メソッド化する

これは途中から始めた施策です。当時FBCの課題を進めている際に、メソッド化に苦手意識を持っていたので、シンプルな内容でもメソッドを定義してみる、という練習をしています。

この時は、下記のようにメソッドを定義しました。

メインメソッド、回文かどうかを判定するメソッド、標準入力を受け取るメソッドの3つを作成。

def main
  n = read_str
  puts is_palindromic?(n)
end

def is_palindromic?(n)
  n == n.reverse ? 'Yes' : 'No'
end

def read_str
  gets.chomp
end

main

リファクタリングする

はじめに作った愚直な解答を元にもっとシンプルに書けないか探ったり、あるいは別のアプローチや別メソッドで解けないかを探ります。

この時は、下記のように書いていきました。

3桁であることが保証されているから、1文字目と3文字目が等しければ回文になるか。

n = gets.chomp
puts n[0] == n[2] ? 'Yes' : 'No'

通った!


⑤他の方の回答を見る

ここまで来たら他の方の回答を見ていきます。

僕はコード長の短い順にソートして確認していますが、最上位の方々は魔法のような記述をしていて理解が追いつかなかったりするので、最上位から順番に見ていきつつ自分の回答を良くするヒントになるような解答や、自分の思いつかなかったアプローチをしている解答をメインに探していきます。

この時は、下記をメモしていました。

考え方はほぼ一緒だったけど、いくつかメモ。   ・ n[0] == n[2]でジャッジするのでchompは不要。なるほど。 ・ n / 100 == n % 10でもジャッジできる。面白い。


⑥るりまで、メソッドを確認する

自分のコードや他の方のコードに登場したメソッドについて、Ruby リファレンスマニュアル(通称るりま)で確認します。

この時は、下記のようなメソッドを確認しました。

String#reverse https://docs.ruby-lang.org/ja/latest/method/String/i/reverse.html   String#[] https://docs.ruby-lang.org/ja/latest/method/String/i/=5b=5d.html


⑦振り返り

気づいたことや思ったことを書きます。ガッツリ書こうとすると時間がかかるので、思いついたことをメモする程度です。 (この時は、他の方の回答の部分で書いていたこともあり、振り返り部分の記載は無しでした)


⑧おまけ:学習内容をGitHubで管理

これも途中から始めたのですが、ターミナルの操作やGitHubの操作に慣れるということも兼ねて、上記で書いたコードを自分のリポジトリにアップしています。GitHubの草も生えるし、一石二鳥!


AtCoder過去問を解くことで得られるもの

上述のように解いていくことで、以下のような学びを得られているかなと思います。


①まず「愚直に書く」こと

頭の中でウンウン考えるのではなく、まず手を動かしていくことで、解答に近づくことができます。 「勝手にモブプロ会」でも「ひとまず愚直に書いてみますか!」というように進めていくことが多く、その精神を学べただけでも大きな収穫だったと思います。


リファクタリングの練習

あまりに時間をかけすぎても良くないとは思いますが、「前にも似たような問題があったな」とか「これってもしかしてこっちのメソッドでできる?」といったことを考えて実行してみることは、コードをシンプルにしたり別アプローチをする練習になり、Ruby脳を鍛える練習になっていると思います。


③他の回答からの学び

これも時間が許す範囲での実施にはなりますが、上位解答者の皆さんのコードにはたくさんの学びが詰まっています。AtCoderは競プロという性質上、「いかに短く書くか」という力学が働いています。その結果、最上位の方の解答はまるで魔法のように短いものもあり、自分の実力では解読すらできないことも多いですが、それでも色々な解答を見られることは勉強になることが多く、ありがたいです。


④ターミナルやGit操作への慣れ

自分はまだまだターミナル操作やGitHubでのコード管理に慣れていないので、「AtCoderで解いたコードをGitHubにあげる」というだけて単純に「毎日ターミナルを触っている」ことになり、それだけでも今の自分にとっては大きな経験となっています。


このように、Ruby初心者な自分にとってはひとつの問題からたくさんの学びを得ることができています。


■おわりに

「一粒で二度・三度もおいしい」AtCoderでの練習ですが、最近はA問題だけでなくB問題にもチャレンジしており、先日A問題70問、B問題30問で合計100問を突破しました!

ただし、B問題は今の自分では手こずることも多く、まだまだ修行していきたい所存です。 また、現在はFBCの課題に注力するためにかなりペースダウンしていますが、これからもAtCoderは続けていきたいと思っており、「勝手にモブプロ会」も引き続き参加していきたいです!


ここまで読んでいただき、ありがとうございました!

思えば、昨年のアドベントカレンダーで「【フィヨルドブートキャンプ】働きながらプログラミングの学習をして2ヶ月が経ちました」と書いて、はや一年。あわよくば今年卒業できるかななんて淡い期待をしていましたが、全然ダメでした涙。 来年のアドカレでは自作サービスについて書けるように、引き続き頑張っていきます!


明日のフィヨルドブートキャンプ アドベントカレンダーは以下の予定です。

Part1の12日目:Hikaruさん Part2の12日目:cafedomancerさん


■おまけの猫

気がつくと全く画像の無い記事でしたので、うちの猫を貼っておきます。

今年の7月から飼い始めている保護猫2匹です。本日のアドベントカレンダーPart2を書かれているhirano-vm4(けだま)さんの記事で知りましたが、偶然にも今日のアドカレを書いた2人は2匹の保護猫を飼っていました🐈🐈‍⬛

【Ruby基礎】AtCoder Beginner Contest 071 A - Meal Delivery

■はじめに

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

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

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

■問題

●出典

AtCoder Beginner Contest 071のA問題 https://atcoder.jp/contests/abc071/tasks/abc071_a

●問題文

すぬけ君は,数直線上の位置 x に住んでいます. また,位置 a,b にはそれぞれ出前を行っている店 A,B が存在します.

すぬけ君は,店 A,B のうち,より近いほうから出前をとることにしました. どちらの店がすぬけ君の住んでいる位置により近いかを求めてください.

ただし,数直線上の 2 点 s,t の間の距離は ∣s−t∣ で表されます.

●制約

  • 1≤x≤1000
  • 1≤a≤1000
  • 1≤b≤1000
  • x,a,b は互いに異なる
  • すぬけ君の位置から店 A,B までの距離は異なる

●入力

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

x a b

●出力

店 A のほうが近いなら A を,店 B のほうが近いなら B を出力せよ.

■回答

●愚直に書く

x-ax-bの絶対値の小さい方、という感じかな? えーと、小さい方の数値をただ出すだけならminメソッドで一発だけど、小さい数値になるのはaかbのどちらか、となると、条件分岐でputsすることになるのかな…?

x, a, b = gets.split.map(&:to_i)
p [(x - a).abs, (x - b).abs].min

上記だとaまでの距離とbまでの距離のうち小さい方の数値を出力することになるので、求める解答では無い。

x, a, b = gets.split.map(&:to_i)
puts (x - a).abs < (x - b).abs ? "A" : "B"

これで通った!

●メソッド化して書く

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

今日は割愛。

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

リファクタリングもちょっと思いつかないので割愛。

●他の方の回答例

基本的には皆さん同じ考え方だった。

ひとつ、宇宙船演算子を使っている解答があったのでメモ。

x, a, b = gets.split.map(&:to_i)
puts " BA"[(x - a).abs <=> (x - b).abs]

宇宙船演算子<=>)は、以下のように返す演算子

10 <=> 20   #  -1←左辺が小さい場合は-1
20 <=> 10   #   1←右辺が小さい場合は1
20 <=> 20   #   0←両辺が等しい場合は0
20 <=> '20' # nil←数値と文字列は比較できないのでnil

上記のコードを噛み砕くと、 " BA"[x]というのは BA(1文字目に半角スペースが入ってる)という文字列からx番目を表示する、と言う意味で、xの部分を宇宙船演算子によって以下3パターンに分けている。

  • -1→これは後ろから1番目の意味なので、Aを返す
  • 1→これは先頭から2番目の意味なので、Bを返す
  • 0→これは先頭から1番目の意味なので、 (半角スペース)を返す
    • ただし今回はaとbが異なる数値であることが保証されているので、0になることはない

なるほどな〜、面白い。

●出てきたメソッド等

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

■振り返りなど

宇宙船演算子。サラッと使ってみたい。

【Ruby基礎】AtCoder Beginner Contest 030 B - 時計盤

■はじめに

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

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

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

■問題

●出典

AtCoder Beginner Contest 030のB問題 https://atcoder.jp/contests/abc030/tasks/abc030_b

●問題文

n 時 m 分のアナログ時計があります。短針と長針のなす角度のうち小さい方を度数法で求めてください。

●入力

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

n m
  • 1 行目には、アナログ時計の時刻を表す整数 n,m(0≦n≦23,0≦m≦59) が空白区切りで書かれている。

●出力

短針と長針のなす角度を 1 行目に出力せよ。絶対誤差または相対誤差が 10^−4 以下であれば許容される。 末尾の改行を忘れないこと。

■回答

●愚直に書く

まず短針は24時間表記になってるから12時間表記に直す。 その上で、短針と長針をそれぞれ角度に変換して、差の絶対値を取る感じか…?

n, m = gets.split.map(&:to_i)
n = n % 12

hour = n * 30
minute = m * 6

puts (hour - minute).abs

これだと駄目。 プリントデバッグしてみたら、短針が分数に合わせて少しずつ動く分を考慮できていなかった。そりゃそうだ。

分数分を短針も動かすという処理さえできればうまくいくかな?

1時間で短針は5度、つまり1分あたり5/60 = 1/12度が動くということか。

n, m = gets.split.map(&:to_i)
n = n % 12

minute = m * 6
hour = n * 30.0 + minute / 12.0

puts (hour - minute).abs

むむむ、これだと一部のケースでWAになる。なぜだ…。

あ〜そうか、一部の場合で大きい方の角度を出してしまっているのか。 minutehourは正しいはずなので、最後に条件分岐すればいけるかな?

n, m = gets.split.map(&:to_i)
n = n % 12

minute = m * 6
hour = n * 30.0 + minute / 12.0

angle = (hour - minute).abs
puts angle > 180 ? 360 - angle : angle

通った!手こずったけど、一歩ずつ正解に進んでいった感があり嬉しい。

●メソッド化して書く

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

色々頭が混乱したけど、以下のメソッドを作成。

  • メインメソッド
  • 標準入力1つ目を長針の角度に変換
  • 標準入力2つ目を短針の角度に変換
  • 長針と短針の角度を計算
  • 標準入力を取得
def main
  n, m = read_nums
  n = n % 12

  minute = convert_minute_to_angle(m)
  hour = convert_hour_to_angle(n, minute)

  angle = calc_angle(hour, minute)
  puts angle > 180 ? 360 - angle : angle
end

def convert_minute_to_angle(m)
  m * 6
end

def convert_hour_to_angle(n, minute)
  n * 30.0 + minute / 12.0
end

def calc_angle(hour, minute)
  (hour - minute).abs
end

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

main

通った! もう少し見通しを良くできるかもしれないけど、ここで時間切れ。

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

思いつかないので割愛。

●他の方の回答例

上位回答は、変数を使わなかったりしてかなりコード長を圧縮しているけど考え方としては大体同じような感じ、かな?

一点、minメソッドの活用が参考になったのでメモ。 最後のangle > 180 ? 360 - angle : angleは、角度が180度より大きかったら小さい方の角度を計算する、という流れだけど、[angle, 360 - angle].minとすれば、2つの角度の小さい方を出力することになり、スマート。

●出てきたメソッド等

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

■振り返りなど

minメソッドのこういう使い方をサラッとできるようになりたいけど今回は気づけなかったな〜。