< Back

[ paiza.IOを使った ] 標準入力入門とアルゴリズム入門(Ruby)

はじめに

自分が1年くらい独学で勉強して、2017年1月にエンジニアに転職したので、当時苦労した点などを思い出しつつ、このタイミングでまとめられたらいいと思っています。
何か間違いとか異論ありましたらコメント欄でお願いします。

記事について

やりたいこと

一緒にpaiza.IOを使いRubyで頭の体操をしましょう!!

paiza.IO: 言語ごとに環境構築しなくていいオンラインサービスなので、今回はこれを使います。
Ruby: 今回はプログラミング言語のRubyを使います。
頭の体操: 数独とかクイズとか好きな人は、アルゴリズムの問題サイトを解くのすごく達成感あると思います!!

記事の対象者

  • プログラミングを習い初めたけど、何から始めよう。
  • ドットインストールくらいはみたよ
  • アルゴリズムの問題解きたい !!
  • 標準入力ってなに ??
  • どんな言語選べば良いのかな。環境構築大変そう。
  • Paiza, CodeIQ, yukicoderなどのサイトを使ってみたい。

記事での勉強法おすすめ

アルゴリズムの問題を解きまくろう

記事を読み終えると

[ 標準入力 ]が使えるようになる!

アルゴリズムの問題サイトで、簡単な問題を解くことができるようになります!!
最後までお付き合いください。

paiza.IO

paiza.IOはこちら

コードを書いたらそのまま実行できるオンラインサービスで、かなり便利です。
helpによると対応言語はこちら。
[ C, C++, C#, Java, Python2, Python3, Ruby, Perl, PHP, JavaScript, Objective-C, Scala, Swift, Go, Haskell, CoffeeScript, Bash, Erlang, R, COBOL, VB, F#, Clojure, D, Elixir, MySQL ]
使い方はこちらpaiza.IO の使い方にまとまってましたので参考にされるといいかと思います。私が扱うのは標準入力の機能付近です。

簡単な文字の入力と出力はpaiza.IOが便利

上記のhelpから対応言語をコピーしてきたらこちら

help.txt
C   clang 3.8 / LLVM 3.8 (C99)  2   512
C++ clang 3.8 / LLVM 3.8 / libc++ (C++14)   2   512
C#  mono-4.2.1 (C#6, CLI4.5)    2   512
Java    java 1.8.0  2   512
Python2 python 2.7.12   2   512
Python3 python 3.5.2    2   512
(以下省略)

こういう簡単なテキストの処理がpaiza.IOでは便利だと思ってます。

スクリーンショット 2017-02-24 12.14.45.png
helpの対応言語一覧からのコピーを上の画像の「入力」という部分に貼り付け、rubyコードを書き実行すると「出力」に結果がでます。

ruby.rb
arr = [] # 配列の初期化
while (gets) # 標準入力があるかぎり実行
    arr << $_.split(" ")[0] 
    # $_に標準入力が入る
    # split(" ")で半角スペースで区切り、配列にする
    # 配列の一番目をarrに入れている
end
p arr
# p arr の出力結果がこちら
["C", "C++", "C#", "Java", "Python2", "Python3", "Ruby", "Perl", "PHP", 
"JavaScript", "Objective-C", "Scala", "Swift", "Go", "Haskell", "CoffeeScript", 
"Bash", "Erlang", "R", "COBOL", "VB", "F#", "Clojure", "D", "Elixir", "MySQL"]

こんな感じで、簡単なテキスト処理をしたいというときにはかなり使ってます。
コードは非公開設定もできます。

このpaiza.IOを使ってアルゴリズムの問題とか、初心者の時自分がつまずいた点を以下に書いていきたいと思います。

標準入力を使ってみよう

今後の書き方のまとめ

スクリーンショット 2017-02-24 13.35.10.png

言語は左上の[Ruby]と選んでください。

Main.rb
# Main.rbのここにコード書いていきます。
# 隣にファイル追加できたりしますが一旦は使わない方向で!
  • 実行 => ファイル実行。アカウントログインしてる人だと成功するとデータ保存される!
  • 出力 => pとかputsとかprintとかの出力結果
入力.txt
# こんな形で入力は[ 入力.txt ]と書く場合があると思いますので、入力欄に入れてください!
  • 入力 => ここが噂の標準入力
  • 実行時エラー => エラーが出た場合は画面がオレンジっぽいの出るので、ここを見ましょう!

さて本題、標準入力を使ったデータ操作を見ていきましょう!

Q. こんな感じで問題だしていくのでその操作のサンプルを書いていきます!

rubyの[p]というのは出力ですが、文字列ならの5なら[ "5" ]と数値の5なら[ 5 ]と出力してくれるので、判断に使ってください!

数字の扱い

Q. 数字が与えられるのでそれを5倍して出力しなさい

入力.txt
4
Main.rb
i = gets
p i # => "4" 文字列の4が出力されます。
p i * 5 # => "44444" 文字列が5回繰り返して出力されます
p i.to_i # => 4 数値の4が出力されました。
p i.to_i * 5 # => 20 数値の20が出力
  • p 文字列か数値かをわかりやすく出力してくれる
  • gets 標準入力から一列取得してくる
  • iという変数にgetsを代入
  • .to_i というメソッドで数値への変換を行っている
  • [ * ]これはかけるという意味で、文字列数値どちらでも使えます。

どんどんいきますよ〜〜〜〜


Q. 数字が3行で与えられるのですべてを足して出力せよ

入力.txt
7
13
5
Main.rb
sum = 0
sum += gets.to_i # sumには7が足されます
sum += gets.to_i # sumには13が足されます
sum += gets.to_i # sumには5が足されます
puts sum # => 25が出力されました!
  • puts 文字列でも数値でも""なしで出力されます
  • 3回同じ操作をするのはコードが冗長なので、同じ結果が得られる別の書き方にかえます
Main.rb
sum = 0
3.times do
    sum += gets.to_i
end
puts sum # => 25が出力されました!
  • 3.times do end => 3回実行せよって命令です。
  • さきほどと同じように7,13,5がどんどん足されていきます。

n個の数値をかけ合わせなさい
一行目にnを、残りのn行に数値を入れるとする

入力.txt
4 # ここに書いてある数値の分だけ、掛け算するよ! 
1
2
3
4

1 * 2 * 3 * 4の出力がみたいってこと!

Main.rb
num = gets.to_i # 最初の4が入る
sum = 1 # 掛け算するので最初は0にしちゃだめ
num.times do # numの数(4)回実行されるよ
    sum *= gets.to_i # 1~4がどんどん掛け算されていく
end
puts sum # => 24が出力されました!
  • num.times do のnumは変数でもOKです!今回は4回実行されました。

次いくよ〜〜


配列の操作

[n m]と入力があるので、n*mを出力しなさい!

入力.txt
4 6
Main.rb

input = gets
p input # => ["4 6"]
p input.split(" ") # => ["4", "6"]
=begin
["4", "6"]は配列になっていて
0番目の要素に"4"が
1番目の要素に"6"が入っています。
=end
p input.split(" ")[0] # => "4"
p input.split(" ")[1] # => "6"
p input.split(" ")[0].to_i # => 4
p input.split(" ")[1].to_i # => 6
puts input.split(" ")[0].to_i * input.split(" ")[1].to_i # => 24

  • rubyのコメントは#(一行コメント)
  • =beginから=endまで(複数行コメント)
  • splitは分割して配列にしてくれるメソッド
  • 今回はsplit("半角スペース")で[4 6]を分割
  • もうちょっときれいに書くと
Main.rb
input = gets.split(" ") # 入力をすぐに配列に分割
num1 = input[0].to_i # 配列の0番目を数値に
num2 = input[1].to_i # 配列の1番目を数値に
puts num1 * num2 # 数値の掛け算

みたいな感じでしょうか。次行きます〜〜〜


半角スペース区切りであたえられる5つの数字[n m l s t]を足しなさい。

入力.txt
2 3 6 14 6
Main.rb
input = gets.split(" ") # 半角スペース区切りで配列にする
p input # => ["2", "3", "6", "14", "6"] 
input.map!{|item| item.to_i} # 配列の中をすべて数字に変えるメソッド
p input # => [2, 3, 6, 14, 6]

sum = 0
input.each do |item| # inputの中身を一個一個取り出すメソッド
    sum += item
end

puts sum # 31
  • mapメソッドの解説
  • (mapは難しいので私はなんとなく使ってた。使いたい度にGoogleで調べてたから覚えなくてもいいかも)
  • まずは破壊的メソッド(!!!!!)と非破壊の違い
map.rb
arr = ["2", "3"]
p arr.map!{|item| item.to_i} # [2, 3] !つけるとarrの配列を置き換えるよ
p arr # [2, 3]
p arr.map{|item| item.to_s} # to_sで文字列に変換 ["2", "3"]
p arr # [2, 3] 上で!つけてないので、あれ文字列から数値に戻りました。

arr2 = ["4", "5"]
arr2.map!{|item| item.to_i} # こうやって!つけるか
p arr2 # [4, 5]
arr3 = arr2.map{|item| item.to_i} # 別の配列に入れてあげないと駄目
p arr3 # [4, 5]
  • |item|とはなんぞや
map.rb
arr = ["2", "3"]
arr.map!{|item| item.to_i}
=begin
|item|の文字はiでもnumでもstrでもtmpでもなんでもいい
配列arrにはいってる文字を全てitemにいれて処理してる感じ。
=end

# イメージこんな感じ
arr = ["2", "3"]
item = arr[0] # itemに最初の文字"2"を代入
arr[0] = item.to_i # arrの0番目に数値2を代入
p arr # [2, "3"]
item = arr[1] # itemに次の文字"3"を代入
arr[1] = item.to_i # arrの1番目に数値3を代入
p arr # [2, 3]
# 無事すべて数字になりました〜〜!!

  • 次はeach doメソッド
Main.rb
arr = [2, 3, 6]
sum = 0
arr.each do |item| # arrの中身を一個itemに入れてる感じ
    sum += item
end

# イメージ
sum = 0
item = arr[0] # 2
sum += item # 0 + 2
item = arr[1] # 3
sum += item # 2 + 3 = 5
item = arr[2] # 6
sum += item # 5 + 6 == 11
puts sum # => 11
# こんな感じです!
  • each doは配列の一つひとつにアクセスするのに便利!

半角スペース区切りであたえられる5つの数字[n m l s t]を足しなさい。

入力.txt
2 3 6 14 6
Main.rb
input = gets.split(" ")
input.map!{|item| item.to_i}

sum = 0
input.each do |item|
    sum += item
end

puts sum # 31
  • です!
  • これをメソッドにしときます
入力.txt
2 3 6 14 6
Main.rb
def my_gets
    input = gets.split(" ")
    input.map!{|item| item.to_i}
    return input
end
p my_gets # [2, 3, 6, 14, 6] 数字にしてくれました!
  • こんな感じでよく使う操作とかはメソッドにして、一番上に書いて、その後呼び出してあげると便利です。
  • returnは書かなくてもいいです。(最後に評価された値が返り値になります)
Returnの他の書き方(最初はreturn書くのがわかりやすいよ).rb
def my_gets
    input = gets.split(" ")
    input.map!{|item| item.to_i}
    input # 明示的に書いてあげるとわかりやすい
end

def my_gets2
    input = gets.split(" ")
    input.map{|item| item.to_i} # なんならこれでも同じ値になる
end

  • ついでに配列を渡すと合計値が返ってくるメソッド
Main.rb
def sum_arr(arr)
    sum = 0
    arr.each do |item|
        sum += item
    end
    return sum
end

arr = [1, 3, 5]
p sum_arr(arr) # 9


半角スペース区切りであたえられる5つの数字[n m l s t]を足しなさい。
入力は3行あるよ!

入力.txt
2 3 6 14 6
4 1 14 4 4
8 4 61 11 2
Main.rb
3.times do
    input = gets.split(" ")
    input.map!{|item| item.to_i}
    sum = 0
    input.each do |item|
        sum += item
    end
    puts sum
end
出力.rb
31
27
86
  • さっきのやつを三回繰り返したらできあがる簡単なもの。
  • でもこれをメソッドを使って整理しとくのがおすすめ
  • 中の処理がなにやってるのかわかりにくくなって
  • 2週間後思い出せなくなったり
  • 「コードの再利用がしやすくなるよ」
Main.rb
def sum_arr(arr)
    sum = 0
    arr.each do |item|
        sum += item
    end
    return sum
end

def my_gets
    input = gets.split(" ")
    input.map{|item| item.to_i}
end

# メインの処理はここから
3.times do # 
    arr = my_gets # 数値型の配列を標準入力から持ってきて
    puts sum_arr(arr) # それを全て足し合わせるメソッドに入れて出力するだけ
end
# ここまで
  • こんな感じでコードの見通しがよくなります!

とりあえず、、いっぱい行渡すから全部たせよ…!

入力.txt
4
2
3
5
6
13
52
Main.rb
sum = 0
while(gets) # 標準入力がある間実行しなさい
    sum += $_.to_i # getsで入力された値は実は$_に入ってます。
end
puts sum # 85
  • while(gets)ってすばらしい!

その他

入力.txt
あいうえお
あいうえお
Main.rb
p gets # "あいうえお\n"
p gets.chomp # "あいうえお"
  • chompは一番うしろの「改行(\n)」を取り除いてくれたりします
Main.rb
while(gets.chomp)
    p $_
end
# こんなことやろうとすると、nil(文字が入ってない時)にはつかえねーよ!ってエラーでるので注意!undefined method `chomp' for nil:NilClass (NoMethodError)

もうこのコードもわかるようになりましたか?

入力.txt
C   clang 3.8 / LLVM 3.8 (C99)  2   512
C++ clang 3.8 / LLVM 3.8 / libc++ (C++14)   2   512
ruby.rb
arr = [] # 配列の初期化
while (gets) # 標準入力があるかぎり実行
    arr << $_.split(" ")[0] 
    # 配列arrの一番最後に<<を使って、に目をarrに入れている
end
p arr # ["C", "C++"]
  • $_.split(" ")[0]には [C]とか[C++]とか一番左の文字列が入ります
  • その文字列を<<メソッドを使って配列arrに挿入していって
  • 最後に出力してます

こんなところでしょうか。
各言語による標準入力一覧 by paizaで自分の使いたい言語調べてみると面白いですよ!rubyとかpython書くコードすくねえ。。みたいな感想いだきました。

いろんなサイト

プログラミング言語の選び方

人気言語のまとめは、こちらの記事 これからの時代はプログラミングって聞くけどどの言語がいいの?が参考になると思います。いろんな集計媒体ごとに人気の言語は違うのがよくわかるかと思います。

また、How To Become A Hackerの日本語訳も参考になると思います。

初心者の方は、取得の敷居が低い言語(PythonとかRuby?)から初めてみたらいいんじゃないかなとか思ったらい。

アルゴリズムサイトのまとめ

プログラミングコンテストの解説

どのプログラミングコンテストに挑戦しよう??と思ったら強くなるためのプログラミング -様々なプログラミングコンテストとそのはじめ方-こちらが参考になります。プログラミングコンテストには、サーバーサイド系、セキュリティ系、データマイニング、AI、アルゴリズムとたくさんあって、各コンテストをマトリックスにまとめられてすごく参考になりました。

オンラインジャッジ系のサイト一覧

こちらが言語の習得やアルゴリズムの学習に最適 オンラインジャッジサイト一覧でまとめられてます。とりあえずストックとかブックマークしておくと、便利です。

ワタシ的なアルゴリズムサイトのおすすめ

個人的には断然Paizaをおすすめします。理由は問題のレベルにバラツキがすくないこと、それと数学苦手でも解けるということ、です。問題を解く快感にはまってBランクの問題まで全部解いてます。Aとかは半分くらい。

アルゴリズムの可視化

海外のサイトですが、アルゴリズムの可視化されてるのでかなりおもしろいずっと眺めてられます。
visualgo
適当に触るとソートとかのアルゴリズムが動き出しますが、英語でわからないという方はこちらアルゴリズムとプログラミングをビジュアルで一挙に理解できる「VisuAlgo」を参考にされるといいかと思います。

font awesome


こんな感じの絵文字みたいなのをQiitaで使えるのでぜひ!

最後に

切に願うことは[標準入力ってなに…]みたいな本当ささいなことでことでつまづく人を減らしていきたい。そんな思いがあります。

コーディングが上達するきっかけは人それぞれだとは思いますが、私はアルゴリズムの問題解きながら、言語の文法を覚えていきました。数独とか、問題解くことが好きな方ってはまると思うんですよ、アルゴリズム。電車で、数独解いてる方みると、ほらアルゴリズムの世界に足を踏み入れてよ、みたいな感情がわいたりします(ちょっと誇張)

この世界に一歩踏み出した方、いっぱいエラーだしてください。google検索してみてください。少しでもこのページが参考になると嬉しいです。

.