hello.This is the second time, a serial project to learn Ruby while making Ruby.In the first time, I learned what Ruby interpreta is, preparing for an environment for programming with Ruby, and writing the first Ruby program to calculate simple calculations.
This time, as a minimal knowledge of Ruby to make Ruby, you will learn the concept of "variables", "branches", and "loops".
The last thing I wrote in the previous article was the following programs, which output simple calculations.
p((1 + 2) / 3 * 4 * (56 / 7 + 8 + 9))
このプログラムをRubyインタプリタで実行すると、計算結果である「100
」がすぐに出力されます。 Windowsで実行した例はこんな具合になるはずです(C:¥Ruby
フォルダのcalc0.rb
というファイルにこのプログラムを保存した場合の例です)。
C:¥Ruby > ruby calc0.rb ⏎100C:¥Ruby >
念のため補足しますが、上記の内容を適当な名前をつけたファイルに保存し、そのファイルの名前をターミナルやコマンドラインでruby
コマンドの後ろに指定して、エンターキーを押す、というのが、「このプログラムをRubyインタプリタで実行する」ということの意味です。これについては第一回で詳しく説明したので、「具体的には何をすればいいんだ?」と思って手が止まってしまった方は第一回をもう一度読み直してみてください。
ここからは、実行結果について説明する場合をのぞき、ターミナルやコマンドラインでプログラムを実行する方法をいちいち説明しないことにします。なにか新しいプログラムが出てきたら、それを新しいファイルに書いて名前を付けて保存し、ruby
コマンドで実行してください。
If you just calculate the formula, the results will be output immediately, so there is no problem.However, in actual programs, you often want to put the calculation results once and output them later.
そんなときに使えるのが変数です。変数とは、いうなれば「値を覚えてくれるもの」です。たとえば、上記の計算結果をすぐに出力するのではなく、変数に覚えさせておくプログラムは、次のように書けます。 このプログラムでは、まずイコール記号=
より右側に書いてある数式の計算をして、その結果を「answer
」という名前の変数に覚えさせています。
answer = (1 + 2) / 3 * 4 * (56 / 7 + 8 + 9)
このプログラムは変数に値を覚えさせるだけで、いっさい出力をさせていないため、実行しても何も表示されません。 実際に上記の1行だけを書いたRubyプログラムを保存して、それを実行してみてください。 (しつこいようですが、プログラムを実行するときは、新しいファイルに適当な名前でプログラムの内容を保存し、そのファイルをターミナルやコマンドラインでruby
コマンドに指定して、エンターキーを押す、ですよ。)
C:¥Ruby > ruby calc1.rb ⏎←何も表示されない!C:¥Ruby
answer
に覚えさせた計算結果を、実行時にターミナルやコマンドラインに表示されるようにするには、プログラムを次のように改良します。
answer = (1 + 2) / 3 * 4 * (56 / 7 + 8 + 9)p(answer)
このプログラムを実行してみましょう。今度は画面に100
が表示されましたね。
C:¥Ruby > ruby calc2.rb ⏎100C:¥Ruby >
覚えておいた値をすぐに出力するだけでは、変数のありがたみが感じられないかもしれません。 そこで、変数に値を覚えさせてから、その覚えさせた値を出力するまでの間に、何か別の計算をしてみましょう。 次のプログラムを見てください。(「#
」から行末まではRubyインタプリタによってプログラムの一部とみなされないので、補足説明を書くのに使っています。)
answer = (1 + 2) / 3 * 4 * (56 / 7 + 8 + 9)p(1 + 1)# 別の計算結果をその場で出力p(answer)
画面には2
と100
が表示されるはずです。
C:¥Ruby > ruby calc3.rb ⏎2100C:¥Ruby >
変数を使えるのはp
で出力するときだけではありません。変数を使った計算式を書くこともできます。 つまり、こんなふうに計算式に変数を書けば、前に変数に覚えさせておいた値が計算で使われます。
answer = (1 + 2) / 3 * 4 * (56 / 7 + 8 + 9)p(answer + 1) # 101 が出力される
In addition, multiple variables can be made, and they can be calculated.
one = 1two = one + 1p(one + two * two) # 5 が出力される
It is called "assign" to make variables remember the value.In addition, taking out the value you have remembered is "reference" or "read the value".
変数の名前に使える文字は、アルファベットの小文字とアンダースコア(_
)です。 ただし、Rubyが特別な意味をもたせている語(後述する「if」や「while」など)を変数の名前にすることはできません。 なお、出力命令の「p」と同名の変数は定義できます(混乱するのでしないほうがよいですが)。このことは別の回で少し触れます。
You can read the variables twice or more.That is, even if you read a value from a variable, the variable will not forget the value without permission.
foo = 1 # foo に 1 を代入するp(foo)# 1 が出力されるp(foo)# もう一回 1 が出力される
You can forget the old value by learning new values.
foo = 1 # foo に 1 を代入するp(foo)# 1 が出力されるfoo = 2 # foo に 2 を代入(上書き)するp(foo)# 2 が出力される
3行めのfoo = 2
の代入によって、変数foo
は以前覚えていた1
を忘れました。 代わりにfoo
はいま2
を覚えています。
Let's look at a slightly complicated example.
foo = 1p(foo)# 1 が出力されるfoo = foo + 1p(foo)# 2 が出力される
3行めのfoo = foo + 1
では、まずイコール記号より右側のfoo + 1
が計算されます。この時点では変数foo
には1が入っているので、foo + 1
の計算結果は2になります。 そして、この2という値をfoo
に代入(上書き)しているわけです。つまり、このプログラムの3行めは、実質的にfoo = 2
と同じ意味になります。
「変数 = 式
」というのは、数学だったら「変数と式が等しい」という意味ですが、Rubyプログラムの中ではあくまで「変数に式の計算結果を覚えさせる(代入する)」という意味であることに注意しましょう。
ダメ押しです。次のプログラムで最後に5
が出力されることを確認してください。
foo = 1p(foo)# 1 が出力されるfoo = foo + 1p(foo)# 2 が出力されるfoo = foo + foo + 1p(foo)# 5 が出力される
By the way, next is the branch.In the examples that have appeared so far, we have only considered programs that execute the contents written in the file in order in order.However, for example, if you want to create a game program, you need a way to change the content executed under various conditions.
ためしに簡単な計算ゲームを考えてみましょう。プレイヤーが1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
の答えを推察するゲームを作ることにします。 ゲームなので、プレイヤーに数字を入力してもらう方法が必要ですね。これにはRubyのgets.to_i
という命令が使えます。
値の出力に使っているp
に比べると、gets.to_i
はごちゃごちゃしていて命令っぽく見えないかもしれませんが、実は「入力を受け取る」という仕事と、受け取ったものを「数値に変える」という仕事を続けて行う命令で、そのため見た目が少しいかつくなっています。
まずはとっかかりとして、1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
の計算結果とプレイヤーが入力した数の値を、それぞれ変数answer
と変数guess
に代入して結果を出力してみましょう。 こんなプログラムになります。
answer = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10guess = gets.to_ip(answer)p(guess)
このプログラムを実行してみてください(ファイルに保存してruby
コマンドで実行ですよ)。 いままでのプログラムの実行結果とは違い、特に何も出力されないままになると思います。 これは、プログラムがプレイヤーからの入力を待っている状態です。そこで、適当な数字(たとえば10
)をキーボードで入力し、エンターキーを押してください。
C:¥Ruby > ruby calc4.rb ⏎← 何も出力されない(入力を待っている状態)
↓
C:¥Ruby > ruby calc4.rb ⏎10 ⏎← 10と入れてエンターキーを押す
↓
C:¥Ruby > ruby calc4.rb ⏎10 ⏎55← 正解10← プレイヤーが入力した値
正解の55
と、入力した10
が出力されましたね。プレイヤーの推察は間違っていたようです。
さきほどのプログラムでは、単にanswer
とguess
の値をそれぞれ出力しただけでした。 もっとゲームっぽく、プレイヤーが入力した数字の値が正解に一致したときは「あたり!」、一致しないときは「はずれ!」などのメッセージを出してあげたいものです。 変数の値に応じてやることを変えるには、どうすればいいでしょうか。
そこで使うのが分岐です。Rubyではif
文という分岐命令が使えます。if
文は、ある条件が成り立つときと成り立たないときでやることが変わります。 さきほどのゲームのプログラムでif
文を使い、プレイヤーの推察した数値が正解かどうかに応じて「あたり!」か「はずれ!」を出力するようにしてみましょう。 変数guess
とanswer
が等しい(「guess == answer
」)ときはp("あたり!")
を、そうでないときはp("はずれ!")
を実行するようになります。
answer = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10guess = gets.to_iif guess == answer# 変数guessと変数answerは等しい? p("あたり!") # 等しい場合else p("はずれ!")# 等しくない場合end
このプログラムでは、「等しい」を表すのに=
を二つ並べた「==
」を使っていることにも注目してください。「=
」単体は代入のときに使うのでした(Rubyに限らず、わりと多くのプログラミング言語でも同じです)。ちなみに、「等しくない」を表すには「!=
」と書きます。
このプログラムを実行してみてください。プレイヤーとして55
を入力した場合には「"あたり!"
」、それ以外の数字を入力した場合には「"はずれ!"
」と表示されてプログラムが終了するはずです。
C:¥Ruby > ruby calc5.rb ⏎← 何も出力されない(入力を待っている状態)
↓
C:¥Ruby > ruby calc5.rb ⏎10 ⏎← 10と入れてエンターキーを押す
↓
C:¥Ruby > ruby calc5.rb ⏎10 ⏎"はずれ!"← 入力が間違っている場合の表示
プログラムの中では「"はずれ!"
」とか「"あたり!"
」のように文字の並びを「"
」(ダブルクォーテーション)で括っています。 これは、Rubyインタプリタに文字列として扱ってもらいたい値は「"
」で括るという約束になっているからです。
この約束は、いかにも文字列のように見える「あたり!
」などだけでなく、数字の場合も同じです。 つまり、裸の「1
」はRubyプログラムでは数(正確には整数値)として扱われますが、ダブルクォーテーションで括った「"1"
」は文字列として扱われます。 数ではないので、足し算や掛け算はできません。
逆に、Rubyプログラム中で「"あたり!"
」を裸の「あたり!
」としてしまうと、Rubyインタプリタに文字列だと思ってもらえません。 未定義の変数か何かの名前として扱われるのでエラーになります。
このプログラムのように、if
文ではif
とelse
とend
をセットにして書けます。Rubyインタプリタは、if
の直後に書かれた条件が成り立つときはelse
の前までにある命令(複数の命令が並んでいることもあります)を実行し、成り立たないときはelse
の後とからend
までの命令を実行します。
条件が成り立つときだけ何かしたい(つまり条件が成り立たない場合には何もしない)なら、else
とその後の命令を省略することもできます。
answer = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10guess = gets.to_iif guess == answer p("あたりです!") p("おめでとうございます!")end
if
文の中に別のif
文を入れることもできます。たとえば、はずれのとき「"はずれ!"
」と出力するだけではそっけないので、ヒントを出してあげましょう。
answer = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10guess = gets.to_iif guess == answer p("あたりです!") p("おめでとうございます!")else p("はずれ!") if guess > answer# 変数guessは変数answerよりも大きい? p("それはちょっと大きすぎるよ!") else p("それはちょっと小さすぎるよ!") endendp("また遊んでね!")
これではずれのとき、入力した値が大きすぎたか小さすぎたかを教えてくれるようになります。 また、プログラムの一番最後で「"また遊んでね!"
」というメッセージを出すようにしました。これはif
文のどちらを実行した場合でも出力されます。このように、if
文のどちらかが実行された後は、end
の直後に実行が移ります。
if
文の中身の行は空白で始めるという慣習があります。この空白をインデントと言います。インデントを綺麗にそろえることで、どこからどこまでがif
文の中身なのかを視覚的にわかりやすくできます。
In addition to the branch, I will touch on the "loop".
さきほどの数当てゲームのプログラムは、はずれたらメッセージを出して終わってしまいます。しかし、はずれたプレイヤーは当てるまで何度も挑戦したいでしょう。そっちのほうがゲームとしてもふつうです。 当たるまで繰り返しプレイヤーからの入力を待ちたいといった場合に使えるのが「ループ」です。 Rubyにはwhile
文というループ命令があります。while
文は、「ある条件が成り立つ限り、同じことを繰り返し実行する」という命令です。
いまの場合は、変数answerと変数guessの値が同じにならない場合には「はずれ!」と出力して再びプレイヤーの入力を待つようにしたいので、「値が同じでない」という条件を判定できる「!=
」を使って、こんなプログラムを書けます。(先ほどまでとは違うプログラムになるので、新しいまっさらなファイルに保存してから実行してくださいね。)
answer = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10guess = gets.to_iwhile answer != guess p("はずれ!") guess = gets.to_iendp("あたり!")
while
文は、while
とend
をセットで書きます。Rubyインタプリタは、while
の直後に書かれた条件が成り立つときはend
の前までの命令を実行し、そうでないときはend
の後ろに飛びます。条件が成り立つときに命令が実行されるという点ではif
文に似ていますが、異なるのは、中身を実行し終えたときにwhile
文の先頭に戻ってきて、条件が成り立つかどうかのチェックから繰り返されるという点です(if
文では対応するend
の後ろに進んでしまいます)。
たとえば、プレイヤーが50
を入力したとします。これははずれなので、while
文(プログラムでいうと3行め)の条件にあたるanswer != guess
が成り立ちます。よって、while
の中身のうち、まずプログラムの4行めにある「p("はずれ!")
」が実行されます。それからプログラムの5行めで、再び変数guess
に読み込むべくプレイヤーの入力を待ちます。これでwhile
文の中身の実行は終わりなので、while
文の最初に戻ります。
もしプレイヤーが今度は51
を入力したとすると、もう一度answer != guess
の判定を行い、51もまたはずれなので、while
文の中身が実行されます。先ほどと同じように4行め、5行めが実行され、三たびプレイヤーの入力を待つことになります。
今度はプレイヤーが55
を入力したとしましょう。今度は変数guess
に55
が代入された状態でwhile
文のanswer != guess
が判定されます。55はあたりなので、今度はwhile
文の条件が成り立ちません。よってend
の後ろ(プログラムの最終行)に進み、「あたり!」と出力して終わります。
This is the end of the newly learned content.You may think, "This is all?"So, let's practice again with a different example.
題材は、1
から1000
までの足し算です。ここまでのプログラムでは、1
から10
までの足し算をこんなふうに書いていました。
answer = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
これくらいなら大したことないですが、1
から1000
までとなると、同じように書き下すのは大変です。こういう処理こそコンピュータに計算させましょう。
とっかかりとして、1
から1000
まで代入を繰り返すwhile
文を書いてみます。
i = 1while i <= 1000 i = i + 1end
このプログラムでは、まず変数i
に1
を代入しておき、その状態でwhile
文がきます。 このwhile
文ではi
が1000以下(この条件はRubyではi <= 1000
と書きます)だったら中身が実行されます。
while
文の中身はi = i + 1
です。 これは前述の「Overwrite the variable」で見たfoo = foo + 1
と同じパターンで、変数の値に1を足し、その結果を同じ変数に代入し直します。 結果としてi
は2になります。
この状態で再びwhile
文の条件判定に戻ります。2
は1000
以下なので今回も条件を満たし、中身が実行されます。 同じようにi = i + 1
を実行して、今度はi
が3になります。 つまり、while
文の中身が実行されるたびにi
の値が1ずつ増えていきます。
そしてi
が1001になったとき、初めてi <= 1000
という条件が成り立たなくなり、while
文が終了します。
こういうwhile
文は非常によくあるパターンで、繰り返し計算をしたい場合に出現します。ぜひパターンとして覚えてしまいましょう。
さて、いましたいのは1 + 2 + ... + 1000
という計算でした。先ほどのwhile
文では1ずつ増える数値が変数に上書きされていくだけで、足し算はされません。 1ずつ増える数値を足しこんでいくには、次のようにします。
answer = 0# 追加i = 1while i <= 1000 answer = answer + i# 追加 i = i + 1endp(answer)# 追加
I added three lines to the previous program.Let's think about what will happen with this.
最初に追加したanswer = 0
は、変数answer
に0
を代入しているだけです。i
には先ほどと同じく、まず1
が代入されます。while
文の条件も先ほどと同じなので、まずはi <= 1000
が成り立って中身が実行されます。
中身の最初はanswer = answer + i
という文です。 この時点でanswer
には0
が、i
には1
が入っているので、answer + i
は0 + 1
になり、その結果である1
がanswer
に代入されます。
続いてi = i + 1
が実行され、再びwhile
文の条件判定に戻り、やはり条件を満たすのでanswer = answer + i
が再度実行されます。 いまはanswer
には1
が、i
には2
が入っているので、answer + i
は1 + 2
で3
になります。
同様にi
を1
増やし、while
文を一周してきて、次のanswer = answer + i
では、3 + 3
でanswer
が6
になります。これを繰り返していきます。
ここで、変数answer
に足されていく値i
に注目すると、最初は1
、次は2
、その次は3
、……というふうになっています。 つまり、answer
には、1 + 2 + 3 + ...
の計算結果が入れられていくということです。 したがって、i
が1000
になるまで繰り返してwhile
文が終わったら、その時点でanswer
には1
から1000
までを足した計算結果が入っていることになります。
その計算結果を最後にp(answer)
で出力して終了です。
すでにRubyを知っている人は、ここまで読んで、「Rubyにはもっと良い書き方があるのに、なぜこんなふうに書くのか」と思っていることでしょう (たとえば1.upto(1000) {|i| answer += i }
やanswer = (1..1000).inject(0, &:+)
のような)。 ここで説明しているMinRuby(最小のRuby)は、メソッド呼び出しのような「高級な」言語機能を持たないことにします(ただの関数はあります。次回説明します)。 よって、ここでもメソッド呼び出しは説明しません。
The opinion that it is not Ruby is legitimate.Method calls are not indispensable to programming languages, but programming languages are so important that humans are easy to read and write, as humans give their computer instructions.However, the purpose of this series is to create a Minruby interpreter, so the language function to be explained first is minimized.It's a little complicated, but please come with me for a while.Luxury language functions such as method calls may be explained in the latter half of the series.
第2回では、「変数」というものと、if
文(分岐)とwhile
文(ループ)を説明しました。 第1回に比べて、ちょっとはプログラミングをしている感じが出てきたと思います。 今回の例題をいろいろいじったり、以下に用意したExercisesをやってみたりして、今回覚えた機能に慣れておいてください。
Next time, I will explain how to handle data called "wood structure" as a preparation for creating an interpreter.Using that, I will explain the "data structure" and "function" of MinRuby.looking forward to.
It is a practice problem to further deepen your understanding.
In programming, it is important to actually move your hands and let blood to pass through knowledge.If you actually try to write a program, it takes unexpectedly time to understand.But that's normal.You can take it slowly, so let's think carefully.If you can solve this smoothly, it can be the next pace.
The next program is almost the same as the program described above, but the calculation results are wrong.Think about what this program is calculating.
answer = 0i = 1while i <= 1000 i = i + 1 answer = answer + iendp(answer)
ヒント:answer = answer + i
の文の直前にp(i)
という命令を追加して、answer
に実際に足されている値を見てみるといいでしょう。 (1000は大きすぎるので、5くらいに置き換えて考えてみてください)
Of the 1 to 1000, a value in which only the even numbers are added (that is, 2 + 4 + 6 +...Please write a program that calculates + 998 + 1000).
ヒント: 現状のプログラムでは無条件にanswer = answer + i
としているところを、i
が偶数の場合にだけ実行するようにすればいいでしょう。特定の条件のときだけ実行するにはif文を使えばいいのでしたね。偶数かどうかを判定するのは、i
を2で割った余りが0であるかどうか、つまりi % 2 == 0
でできます。
There is a program called Fizzbuzz.The number from 1 to 100 is output in order, but if the number is divisible by 3, output "Fizz" instead of the number, and in the case of the number that can be divisible by 5, output "BUZZ" instead of the number.If the number of 3 or 5 is divisible, it is a program that outputs "Fizzbuzz".
Please write Fizzbuzz.If you do the following output when executed, the answer is correct.
12"Fizz"4"Buzz""Fizz"78"Fizz""Buzz11"Fizz"1314"FizzBuzz"...
ヒント1: まず、while
文を使って1から100まで繰り返すプログラムを書きましょう(開発中は100ではなく20くらいまでにしておくとデバッグしやすいかもしれません)。while
文の中でやる処理は、(1)その数字を出力する、(2)"Fizz"
を出力する、(3)"Buzz"
を出力する、(4)"FizzBuzz"
を出力する、のいずれかになります。うまく分岐を組んでください。FizzBuzzを口に出してやってみると、条件が頭の中で整理できると思います。
Hint 2: There are many ways to assemble branches, but for example, the following assembly is considered.
if i % 3 == 0 if i % 5 == 0 ... else ... endelse if i % 5 == 0 ... else ... endend
Try to put the processing from (1) to (4) in four open places.
Tweet
To the category top
■ Saturday, July 6, 2019 13: 00-19: 00
3-1 Goban-cho, Chiyoda-ku, Tokyo
The seminar held on March 23 this year, "Introduction to quantum programming on quantum computers," was held repeatedly.Unlike the previous "Introduction to quantum computers learned with paper and pencils", the goal is to learn the basics of "quantum programming" necessary to calculate with quantum computers.With the cooperation of IBM, you will learn how to use a quantum circuit by combining basic gates and how to use many simulators in IBM QISKIT.
Kadokawa ASCII Research Institute Inquiry Form
Programming + Editorial Department has received a wide range of requests and consultations related to programming and education, such as planning and implementation for corporate seminars and corporate training, creating reviews of products and publications, and requesting event coverage.If you are interested in individuals, corporations, or organizations, please feel free to contact us from the above form.
Display format: PC ⁄ Smartphone