確率モデル(サイコロ)問題4

説明

確率モデル(サイコロ)問題3のプログラムを使って、サイコロそれぞれの出目が何回あったのかを棒グラフにして確認します。

棒グラフにするには、下のプロシージャを使ってください。

ヒント

* プロシージャの使い方をリファレンスやプログラマーズガイドで確認しよう

procedure bar_graph a@, min_soeji,max_soeji
  cls 2
  rem 棒グラフの太さ
  w = 10

  rem 左の空白
  left_space = 50

  rem 上の空白
  ytop = 50

  rem x軸の長さ
  xlen = 550

  rem y軸の長さ
  ylen = 300

  rem y軸の下端
  ybottom = ytop + ylen

  rem スケール
  y_max=0
  for i=min_soeji to max_soeji
    if y_max<a@[i] then
      y_max=a@[i]
    end if
  next
  yscale = ylen / y_max

  rem x軸とy軸の線
  line(left_space,ybottom)-(left_space+xlen,ybottom),7
  line(left_space,ybottom)-(left_space,ytop),7

  rem 要素数
  yousosu = max_soeji + 1 - min_soeji

  rem 要素ごとの間隔
  kankaku = (xlen-w*yousosu) / (yousosu+1)

  for i = min_soeji to max_soeji
      x = left_space + (i-min_soeji+1) * kankaku + (i-min_soeji)*w
      x2 = x + w
      box(x,ybottom)-(x2,ybottom-a@[i]*yscale),7,7
  next
end procedure

Studioで試す

以下のリンクから Jasmine Tea でこのサンプルプログラムを Studio 画面で開いて実際に試すことができます。プログラムを実行したいときは、エディターの右下にある青色の「実行」ボタンを押してください。

Studio で開く

プログラム

function count(a@, min_soeji,  max_soeji, x)
  cls 1
  number = 0
  for i = min_soeji to max_soeji
    if a@[i] = x then
      number = number + 1
    end if
  next
  return number
end function

saikoro@=[]
deme@=[]
  
for i = 1 to 100
  saikoro@[i] = random(1,6)
next

for i = 1 to 6
  number = count(saikoro@,1,100,i)
  deme@[i]=number
next

for i = 1 to 6
  print deme@[i]
next

procedure bar_graph  a@, min_soeji,max_soeji
  cls 2
  rem 棒グラフの太さ
  w = 10

  rem 左の空白
  left_space = 50

  rem 上の空白
  ytop = 50

  rem x軸の長さ
  xlen = 550

  rem y軸の長さ
  ylen = 300

  rem y軸の下端
  ybottom = ytop + ylen

  rem スケール
  y_max=0
  for i=min_soeji to max_soeji
    if y_max<a@[i] then
      y_max=a@[i]
    end if
  next
  yscale = ylen / y_max

  rem x軸とy軸の線
  line(left_space,ybottom)-(left_space+xlen,ybottom),7
  line(left_space,ybottom)-(left_space,ytop),7

  rem 要素数
  yousosu = max_soeji + 1 - min_soeji

  rem 要素ごとの間隔
  kankaku = (xlen-w*yousosu) / (yousosu+1)

  for i = min_soeji to max_soeji
      x = left_space + (i-min_soeji+1) * kankaku + (i-min_soeji)*w
      x2 = x + w
      box(x,ybottom)-(x2,ybottom-a@[i]*yscale),7,7
  next
end procedure

call bar_graph deme@,1,6

解説

1行目から25行目までは確率モデル(サイコロ)問題3のプログラムと同じです。詳しくはそちらを参照してください。

28行目から72行目までは棒グラフを生成するプロシージャを定義しています。

28行目でプロシージャの名前と、使用する仮引数を定義しています。bar_graphはプロシージャの名前、aは配列の名前、min_soejiは配列の添え字の最小値、max_soejiは配列の添え字の最大値を意味します。プロシージャの名前以外はすべて仮引数です。

29行目は画面上の図形を消しています。

31行目は棒グラフの太さを定義しています。

33行目から46行目までは、棒グラフを描写する範囲を指定しています。

34行目は左の空白を指定し、x軸の0の位置を決めています。

37行目は上の空白を指定し、y軸の最上部の位置を決めています。

40行目はx軸の長さを指定しています。

43行目はy軸の長さを指定しています。

46行目はy軸の最下部の位置、つまりy軸の0の位置を、上の空白とy軸の長さを足すことで求めています。

48行目から55行目までは、y軸の縮尺を求めています。

49行目ではy軸の最大値をy_maxとして、一旦0を代入しています。y軸の最大値を知ることで、y軸の縮尺を決めることができます。y軸の最大値は、棒グラフで表現する配列の中身の最大値です。

50行目でmin_soejiからmax_soejiまでの数値をforを使って変数iに入れていきます。このi

51行目と52行目で配列aの添え字として使われます。

51行目ではifを使って、配列の中身がy_maxより大きかった場合の分岐処理を定義しています。

52行目では51行目のifが成立した場合の処理として、y_maxにa[i]の数値を代入しています。その時点で最大の数値であるy_maxより大きい値がa[i]として出現した場合、この処理でy_maxが置き換わっていき、最終的に配列の中で一番大きな数値をy_maxとして得ることができます。

55行目はy軸の縮尺y_scaleを求めています。y軸の長さy_lenを、配列の最大値であるy_maxで割った値がy軸の縮尺です。

56行目から59行目までは、y軸とx軸の線を引いています。

58行目はx軸7軸ともに0の位置から、x軸の長さ分line命令を使って線を引いています。これがx軸の線です。

59行目はx軸y軸ともに0の位置から、y軸の最上部の位置までline命令を使って線を引いています。これがy軸の線です。

62行目は棒グラフを書く要素の個数をyousosuとして定義しています。yousosuは、通常の0から始まる配列を棒グラフにする場合には、添え字の最大値に1を足した数になります。ですが今回の配列は1から始まるので、添え字の最大値に1を足す必要はありません。そのため、ここでは0以外で始まる配列にも対応できるように、添え字の最大値に1を足したもの(max_soeji+1)から添え字の最小値(min_soeji)を引く計算をしています。

64行目は棒グラフの間隔を計算しています。棒グラフの間の間隔として使えるスペースは、xの長さ(xlen)から、棒グラフの個数分の太さ(w*yousosu)を引いた分です。これで、全体として間隔に使えるスペースを求められます。間隔に使えるスペース全体を、要素の個数に1を足したもので割ると、棒グラフの間隔が求められます。要素の個数に1を足すのは、一番最後の棒グラフの後ろにも間隔をあけているからです。

67行目から72行目では、配列の中身1つずつに対し、棒グラフを描画しています。

67行目でmin_soejiからはじめてmax_soejiまでの数値をforを使って変数iに入れていきます。

68行目は、現在描画しようとしている要素の左端の位置を計算しています。このプログラムではその位置をxと定義しています。xの位置は、次の要素を足すことで求められます。

* グラフの外の左の空白(left_space)

* その要素までにすでに描画した棒グラフの個数+1(i-min_soeji+1)個分の間隔(kankaku) ここで1個分足しているのは、最初の棒グラフの前にも間隔が必要だからです。

* その要素までにすでに描画した棒グラフ分の太さ((i-min_soeji)*w) 69行目は、現在描画しようとしている要素の右端の位置を計算しています。このプログラムではその位置をx2と定義しています。x2の位置は、67行目で求めたxの位置に棒グラフの太さを足すことで求められます。 70行目はbox命令を使って棒グラフを描写しています。box命令ではその四角の対角線上にある2点の座標を指定します。このプログラムでは、棒グラフの左下の角と、右上の角の座標を指定しています。

* 左下の角を表す座標 : (x,ybottom)

* 右上の角を表す座標 : (x2,ybottom-a[i]*yscale)

xは68行目で求めた値です。x2は69行目で求めた値です。左下の角のyの座標はy軸の0の位置(ybottom)です。右上の角のyの座標は、配列の中身に縮尺をかけた値をybottomから引くことで求められます。配列の中身に縮尺をかけるのは、指定した範囲内でグラフを表現するためです。そのままの値だと、うまくグラフに出力できない場合があります。その値をybottomから引く理由は、グラフィックのめもりがグラフで表現したい向きとは反対に、下に向かって数字が増えていく形になっているからです。ybottomからa[i]*yscaleを引くことで、本来指定したいy軸上の位置を指定することができます。

74行目では、28行目から72行目で定義したプロシージャbar_graphを呼び出しています。定義した仮引数に対応する実引数として、配列名aに配列名demeを、min_soejiに1を、max_soejiに6を渡しています。

問題の引用元:

文部科学省「高等学校情報科「情報Ⅰ」教員研修用教材 第3章 コンピュータとプログラミング」(2020)