🔢

SadServers解説 Easy No.6 「簡単な数学」

に公開

https://ja.wikipedia.org/wiki/ラサ市

問題概要

問題URL

https://sadservers.com/scenario/lhasa

シナリオ

簡単な数学

問題詳細

/home/admin/scores.txt というファイルに、2列の数字が書かれています。
1列目の数字は番号で、2列目の数字はテストの得点のようなものです。2列目の数字の平均を求めてください。

$ head /home/admin/scores.txt 
1 7.4
2 0.4
3 1.6
4 6.2
5 7.6
...

なお、今回の仮想マシンには、bc、Python3、Go言語(Golang)、sqlite3がインストールされています。

解決判定

解答をファイル/home/admin/solutionに書いて、Check My Solutionボタンをクリックしてください。例えば、解答が"123.45"であれば、次のようなコマンドを実行し、Check My Solutionボタンをクリックしてください。

$ echo "123.45" > ~/solution

解答は、小数点3桁以下を切り捨てて、ぴったり小数点2桁まで記入してください。たとえば、計算結果が21.349なら答えは21.34、計算結果が33.1なら答えは33.10です。

解答が正解かどうか、コマンドプロンプト上で確認することも可能です。ハッシュ値を求める次のコマンドを実行して、以下と同じ出力が得られた場合は正解です。

$ md5sum /home/admin/solution 
6d4832eb963012f6d8a71a60fac77168  /home/admin/solution

 

問題解決の方針

【表示する】

今回の問題では、ファイル内容を編集・集計するコマンドを適切に使えるかが問われています。
どのようなコマンドをどういった手順で実行すれば、特定の列の平均値を計算することができるでしょうか。

具体的な解決の段取りを表示する
  1. ファイルの2列目だけを抽出する
  2. 数字の合計と個数を求め、平均を計算する
  3. 小数第2位以下を切り捨てる

 

ヒント

オリジナルヒント

ヒント1

2列目の得点だけを取り出したいので、cut を使います。

実行コマンド

区切り文字は" "(半角スペース)のため、-d ' 'オプションで、半角スペースを区切り文字に指定します。
また、-f 2オプションで、2列目を抽出する列に指定します。

$ cut -d ' ' -f 2 /home/admin/scores.txt
7.4
0.4
1.6
6.2
7.6
...
別解

awkコマンドを使用することでも、2列目を取り出すことができます。

$ awk '{print $2}' /home/admin/scores.txt
7.4
0.4
1.6
6.2
7.6
...
ヒント2

awkコマンドを使用して、各行の数字を足し合わせるとともに、足し合わせた回数を記録しておきます。そして、最後に数字の合計を回数で割ることで、平均を計算します。

実行コマンド
$ cut -d ' ' -f 2 /home/admin/scores.txt |
   awk '{ sum += $1; n++ } END {  print sum / n }'
5.204
ヒント3

小数第3位以下を切り捨てます。手動で書き込んでも良いですし、出力の際に有効数字を指定してもよいです。

実行コマンド

出力の際に有効数字を指定することで、小数第2位以下を切り捨てる場合の処理です。

$ cut -d ' ' -f 2 /home/admin/scores.txt | awk '{ sum += $1; n++ } END { printf "%.2f\n", sum / n }'
5.20
$ echo "5.20" > ~/solution
$ md5sum /home/admin/solution 
6d4832eb963012f6d8a71a60fac77168  /home/admin/solution

ハッシュ値が 6d4832eb963012f6d8a71a60fac77168 と一致しました!

SadServers公式ヒント(翻訳)

ヒント1

解き方はさまざまあります(コードを書く、データベースに読み込むなど)。シンプルな方法は、コマンドラインの計算機 bc を使って2列目の数字(得点)の合計を求めることです。2列目の得点は awkcut で簡単に抽出できます:awk '{ print $2 }' scores.txt

ヒント2

paste コマンドを使うと数字の間に + を挿入でき、そのまま bc に渡せます:sumexpr=$(awk '{ print $2 }' scores.txt | paste -sd+)

ヒント3

2列目の数字の合計は次のコマンドで求まります:sum=$(echo $sumexpr | bc)。これは 520.4 を返します(bcscale 設定に関わらず)。

ヒント4(最終解答)

要素数(行数)は elements=$(wc -l scores.txt|awk '{ print $1 }') などで求まります(最終行に改行があるかどうかに注意)。bcscale を 2 に指定して割り算し、解答ファイルに書き出します:echo "scale=2; $sum/$elements"|bc > ~/solution(答えは 5.20)。

 

参考

今回の仮想マシンにはPython3がインストールされているとのことなので、Pythonコードを実行して解いてみます。
以下のPythonコードを書いてみました。

calculate_average.py
sum = 0
count = 0

with open("/home/admin/scores.txt", 'r') as input_file:
    for line in input_file:
        sum += float(line.split()[1])
        count += 1

average = sum / count

with open("/home/admin/solution", 'w') as output_file:
    output_file.write(f"{average:.2f}\n")

print("計算結果は {:.2f} です。".format(average))

実行してみます。

実行コマンド(答えが含まれるので注意)
$ python3 calculate_average.py
計算結果は 5.20 です。

コマンドで実行した場合と同じ計算結果が得られました!
 
「いきなり問題を解き始めても調べるばかりになってしまう…」 「やりたいことが分かっても、コマンドが分からない…」 という方は、下記の記事でLinuxのコマンドを復習してから、SadServersの問題に取り掛かってみてはいかがでしょうか。
https://zenn.dev/comf_nakamura/articles/linux_command
 

問題一覧はこちら

https://zenn.dev/comf_nakamura/articles/sadservers_sitemap

Discussion