10日目 | Nim100日ドリル
~配列とseq~

今日の目標

今日は、複数の値をまとめて扱うための arrayseq を学ぶ。
まず、長さが固定されている array と、あとから要素を追加できる seq の違いを理解する。
次に、要素を取り出す方法、要素を追加する方法、長さを取得する方法を覚える。
最後に、テストの点数一覧を使って合計点を計算し、平均点を求めるプログラムを書けるようにする。

今日の内容

10ー1 ~arrayは「長さが決まっている箱」~

プログラムでは、1つの点数だけでなく、複数の点数をまとめて扱いたい場面がよくある。
たとえば、国語、数学、英語の3教科の点数を扱う場合、変数を3つ作って kokugosuugakueigo と分けてもよい。
しかし、教科数が増えると変数名が増え、合計点や平均点を求める処理も書きにくくなる。

そこで使うのが array である。array は、同じ型の値を決まった個数だけ並べて持つための仕組みである。
Nimでは、array[3, int] のように書く。これは「int 型の値を3個持つ array」という意味である。

                    
let scores: array[3, int] = [80, 90, 70]

echo "1番目の点数: ", scores[0]
echo "2番目の点数: ", scores[1]
echo "3番目の点数: ", scores[2]
echo "点数の個数: ", scores.len
                    
                

上のコードでは、scores という array を宣言している。array[3, int] は「int 型の値を3個持つ array」という意味である。
[80, 90, 70] は、3つの点数を並べたリストである。これを array に代入することで、scores という変数に3つの点数がまとめて入る。
scores[0] は1番目の点数(80)を取り出す方法である。scores[1] は2番目の点数(90)、scores[2] は3番目の点数(70)を取り出す方法である。
scores.len は、点数の個数(3)を取得する方法である。
array は長さが固定されているため、あとから要素を追加することはできない。

要素を取り出すときは、scores[0] のように番号を使う。この番号をインデックスという。
Nimのインデックスは 0 から始まる。
つまり、1番目の要素は scores[0]、2番目の要素は scores[1]、3番目の要素は scores[2] である。
初心者はここで scores[3] と書いてしまいやすいが、長さ3のarrayで使えるインデックスは 0、1、2 だけである。

10ー2 ~seqは「あとから増やせる一覧」~

array は長さが固定されているため、最初から要素数が決まっている場合には使いやすい。
しかし、実際のプログラムでは、あとからデータを追加したい場面が多い。
たとえば、テストの点数を1人ずつ登録していく場合、最初から何人分の点数が入るか決まっていないことがある。

このようなときに使うのが seq である。
seq は「sequence」の略で、Nimでは可変長の一覧を表す。
seq[int] と書くと、「int 型の値を並べて持つ、長さを変えられる一覧」という意味になる。

                    
var scores: seq[int] = @[]

scores.add(80)
scores.add(90)
scores.add(70)

echo "点数一覧"
echo scores[0]
echo scores[1]
echo scores[2]
echo "点数の個数: ", scores.len
                    
                

上のコードでは、scores という seq を宣言している。seq[int] は「int 型の値を並べて持つ、長さを変えられる一覧」という意味である。
@[] は、空の seq を作る方法である。
scores.add(80) は、点数80を scores に追加する方法である。同様に、90と70も追加している。
scores[0] は1番目の点数(80)を取り出す方法である。scores[1] は2番目の点数(90)、scores[2] は3番目の点数(70)を取り出す方法である。
scores.len は、点数の個数(3)を取得する方法である。

10ー3 ~平均点を求めるには合計と長さが必要である~

点数一覧から平均点を求めるには、まずすべての点数を合計し、その合計を点数の個数で割る必要がある。
たとえば、80、90、70 の平均点は、合計 240 を個数 3 で割るため、80 になる。

Nimで一覧の中身を順番に処理するときは、for 文を使う。
for score in scores: と書くと、scores の中の値が1つずつ score に入る。
その scoretotal に足していけば、合計点を求められる。

                    
var total = 0
for score in scores:
  total += score
                    
                

上のコードでは、total という変数を0で初期化している。
for score in scores: と書くと、scores の中の値が1つずつ score に入る。
その scoretotal に足していけば、合計点を求められる。
最後に、平均点は total / scores.len で求められる。

                    
let average = total.float / scores.len.float
                    
                

total.float は、整数の total を小数として扱うための書き方である。
scores.len.float も同じである。
初心者がよくやるミスは、let average = total / scores.len と書いてしまうことだ。
Nimでは整数同士を / で割る書き方は基本的に期待通りに動かない。
小数の平均点を出したいなら、float に変換してから割ると覚えておくとよい。

課題1

この問題では、空のseqに点数を追加し、点数の個数と2番目の点数を表示する。____ に入るコードを考えて、プログラムを完成させる。

                    
var scores: ____ = @[]

scores.____(80)
scores.____(90)
scores.____(70)

echo "点数の個数: ", scores.len
echo "2番目の点数: ", scores[____]
                    
                

期待する出力は次のとおりである。

                    
点数の個数: 3
2番目の点数: 90
                    
                

ヒントとして、整数を入れるseqの型は seq[int] である。
seqに要素を追加するときは add を使う。
また、2番目の要素を取り出すときのインデックスは 2 ではない。
Nimのインデックスは 0 から始まるため、1番目が 0、2番目が 1 である。

課題2

このコードは、3人分の点数を表示するプログラムである。このコードを改造して、さらに 90 と 100 を追加し、最後に平均点も表示するようにする。

                    
var scores: seq[int] = @[60, 70, 80]

echo "点数一覧"

for score in scores:
  echo score
                    
                

期待する出力は次のとおりである。

                    
点数一覧
60
70
80
90
100
平均点: 80.0
                    
                

ヒントとして、追加する処理は for 文より前に書くとよい。
点数を追加したあとに for score in scores: を実行すれば、追加した点数も一緒に表示される。
平均点を求めるには、var total = 0 を用意し、for 文の中で total += score と書いて合計する。
そのあとで let average = total.float / scores.len.float とすれば、小数として平均点を求められる。

課題3

この課題では、入力として 72、85、91、64、78 の5つの点数を持つseqを使う。
処理では、点数を1つずつ表示しながら合計点を求める。出力では、人数、合計点、平均点を表示する。

出発コードは次のとおり。

                    
var scores: seq[int] = @[72, 85, 91, 64, 78]

var total = 0

echo "点数一覧"

for score in scores:
  echo score
  total += score

let average = ____

echo "人数: ", scores.len
echo "合計点: ", total
echo "平均点: ", average
                    
                

期待する出力は次のとおりである。

                    
点数一覧
72
85
91
64
78
人数: 5
合計点: 390
平均点: 78.0
                    
                

よくあるエラーの1つは、次のように書いてしまうことである。

                    
let average = total / scores.len
                    
                

この書き方では、整数同士を / で割ろうとして型の問題が起きる。
平均点は小数になる可能性があるため、整数のままではなく、float に変換してから割る必要がある。直す場合は次のように書く。

                    
let average = total.float / scores.len.float
                    
                

もう1つのよくあるミスは、scores.add("90") のように文字列を追加しようとすることである。
scoresseq[int] なので、中に入れられるのは整数である。
"90" は文字列であり、90 は整数である。見た目は似ているが、Nimでは別の型として扱われる。

今日のまとめ

今日は、複数の値をまとめて扱うための arrayseq を学んだ。
array は長さが固定されている一覧であり、最初から要素数が決まっているときに使いやすい。
一方、seq はあとから要素を追加できる一覧であり、データの数が変わる場面で使いやすい。
どちらも scores[0] のようにインデックスで要素を取り出せるが、インデックスは 0 から始まる点に注意が必要である。

また、scores.len を使えば要素数を取得できる。
平均点を求めるときは、for 文で点数を1つずつ取り出して合計し、その合計を scores.len で割る。
ただし、小数の平均点を出したい場合は、total.float / scores.len.float のように float へ変換してから割る必要がある。

次回は、Nimでの文字列処理について学ぶ予定である。





9日目へ

11日目へ

トップへ戻る


お問い合わせ