ようへいの日々精進XP

よかろうもん

アルゴリズムとプログラミング 「第 1 章 プログラミング」の予習とまとめ

これは

放送大学教養学部の「アルゴリズムとプログラミング」という授業で使われる「アルゴリズムとプログラミング」という教材書籍を自分なりにまとめたものです.

第 1 章では, プログラミングとはなんぞや的な簡単な座学から, プログラミングについて C 言語の初歩的なデータの入出力, 変数や関数の取扱について触れられています.

尚, 本まとめについては, 以下の Github リポジトリで管理しており, 加筆修正はリポジトリのみ行います.

github.com

1. アルゴリズムプログラミング言語

抜粋

  • プログラム (program) とは, コンピュータに対する処理を記述したもの
  • プログラムによって問題を解く為の処理手順はアルゴリズム (algorithm) と呼ばれる
  • コンパイラ (compiler) は, プログラムをコンピュータが実行可能な機械語に変換するソフトウェア
  • インタプリタ (interpreter) は, ソースコードを逐次変換しながら実行しているくソフトウェア

メモ

2. コンパイラ

抜粋

  • コンパイラ (compiler) は, プログラムをコンピュータが実行可能な機械語に変換するソフトウェア
  • ソースプログラムは最終的に実行形式であるターゲットプログラムに変換される

以下はターゲットプログラムへの変換過程.

ソースプログラム (source program)
↓
文法解析器 (syntax analyzer)
↓
意味解析器 (semantic analyzer)
↓
中間コード生成器 (intermediate code generator)
↓
最適化コード生成器 (code optimizer)
↓
コード生成器 (code generator)
↓
ターゲットプログラム (target program)

メモ

  • コンパイルの過程で実は色んな仕事をしているんだな...
  • gcc = GNU Compiler Collection

MacOS X に導入されていいる gcc は以下のようなもの.

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.13.6
BuildVersion:   17G65
$ gcc -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

尚, 以後は上記の gcc を利用してコードをコンパイルしていく.

3. 入出力と演算

3.1 出力と入力

  • ヘッダファイル stdio.h には printf 関数をはじめ, 様々な入出力に関連したライブラリ関数が含まれている
  • C 言語では必ず 1 つの main 関数を持つ

以下のコードは標準出力に文字データを出力するプログラム.

/* code: ex1-1.c */
#include <stdio.h>

int main()
{
  printf ("The Open University of Japan\n");
  
  return 0;
}

コンパイルして実行してみる.

$ gcc ex1-1.c -o ex1-1
$ ./ex1-1; echo $?
The Open University of Japan
0

main 関数は整数値を返し, プログラムを呼び出したプロセスに値 0 を返す.

以下のコードは scanf 関数を利用した入力の例, 整数型のデータ入力を要求し, 入力されたデータを表示する.

/* code: ex1-2.c */
#include <stdio.h>

int main()
{
  int a;
  printf ("Enter an integer: ");
  scanf ("%d", &a);
  printf ("The integer you entered was %d.\n", a);
  
  return 0;
}

コンパイルして実行してみる.

$ gcc ex1-2.c -o ex1-2
$ ./ex1-2
Enter an integer: 1000
The integer you entered was 1000.

scanf 関数はキーボード等の標準入力からのデータ入力を行うが, リダイレクションによるデータ入力も可能である.

$ echo 100 | ./ex1-2
Enter an integer: The integer you entered was 100.

$ echo 200 > ex1-2.txt
$ ./ex1-2 < ex1-2.txt
Enter an integer: The integer you entered was 200.

3.2 変数

  • C 言語では変数を使用する前に, 変数の宣言を行う必要がある
  • 変数の宣言では, 使用する変数の型を指定する
  • データ型によって値を保存する為に使われるメモリサイズは異なる, また, OS によってもメモリサイズは異なる

以下, データ型の一覧.

データ型 キーワード キーワードの英語
文字列 char character
整数 int integer
浮動小数点数 float floting-point
倍精度浮動小数点数 double double precision floating-point
値無し void void

以下のコードは sizeof 演算子を使ってデータ型のメモリサイズを表示するプログラムである.

/* code: ex1-3.c */
#include <stdio.h>

int main()
{
  char a;
  short b;
  int c;
  long d;
  float e;
  double f;
  
  printf ("char:   %zd byte (s)\n", sizeof (a));
  printf ("short:  %zd byte (s)\n", sizeof (b));
  printf ("int:    %zd byte (s)\n", sizeof (c));
  printf ("long:   %zd byte (s)\n", sizeof (d));
  printf ("float:  %zd byte (s)\n", sizeof (e));
  printf ("double: %zd byte (s)\n", sizeof (f));
  
  return 0;
}

コンパイルして実行してみる.

$ gcc ex1-3.c -o ex1-3
$ ./ex1-3
char:   1 byte (s)
short:  2 byte (s)
int:    4 byte (s)
long:   8 byte (s)
float:  4 byte (s)
double: 8 byte (s)

3.3 算術演算 (arithmetic operator)

  • 演算子には優先順位があり, 乗算, 除算, 剰余は加算, 減算の演算子よりも優先度が高い
演算 演算子
加算 +
減算 -
乗算 *
除算 /
剰余 %

以下のコードは整数型の変数に対して, 算術演算を行うプログラムである.

/* code: ex1-4.c */
#include <stdio.h>

int main()
{
  int a, b, c;
  a = 10;
  b = 3;
  c = 0;
  printf ("a=%d\n", a);
  printf ("b=%d\n\n", b);
  c = a + b;
  printf ("a + b = %d\n", c);
  c = a - b;
  printf ("a - b = %d\n", c);
  c = a * b;
  printf ("a * b = %d\n", c);
  c = a / b;
  printf ("a / b = %d\n", c);
  c = a % b;
  printf ("a %% b = %d\n", c);
  
  return 0;
}

コンパイルして実行する.

$ gcc ex1-4.c -o ex1-4
$ ./ex1-4
a=10
b=3

a + b = 13
a - b = 7
a * b = 30
a / b = 3
a % b = 1
  • 算術関数は math.h をインクルードして利用する
  • gcc や clang 等のコンパイラコンパイルする場合には -lm オプションを付与する必要がある

以下は math.h 定義されている関数の一例.

計算 double 型 float 型 long double 型
sin の計算 sin sinf sinl
cos の計算 cos cosf cosl
tan の計算 tan tanf tanl
べき乗の計算 pow powf powl
平方根の計算 sqrt sqrtf sqrtl
天井関数の計算 sqrt sqrtf sqrtl

以下, べき乗を求める pow 関数を利用したプログラムの例.

/* code: ex1-5.c */
#include <stdio.h>
#include <math.h>

int main()
{
  double x, y, z;
  x = 30.0;
  y = 3.0;
  z = 0.0;
  printf ("x=%f\n", x);
  printf ("y=%f\n\n", y);
  z = pow (x, y);
  printf ("pow (x, y) = %f\n", z);
  
  return 0;
}

コンパイルして実行してみる.

$ gcc ex1-5.c -o ex1-5
$ ./ex1-5
x=30.000000
y=3.000000

pow (x, y) = 27000.000000

3.4 変数と式

以下, 摂氏から華氏への換算を行うプログラムの例. 変数を利用することで複雑な計算式を解くことが出来る.

/* code: ex1-6.c */
#include <stdio.h>
#include <math.h>

int main()
{
  float celsius, fahrenheit;
  
  celsius = 36.5;
  fahrenheit = (9.0 / 5.0) * celcius + 32.0;
  printf ("%f (Celsius) = %f (Fahrenheit)\n", celsius, fahrenheit);
  
  return 0;
}

コンパイルして実行してみる.

$ gcc ex1-6.c -o ex1-6
$ ./ex1-6
36.500000 (Celsius) = 97.699997 (Fahrenheit)

3.5 プログラム中のコメント

  • /* */
  • // の 1 行コメントも利用可能

以下, サンプルコード.

/* code: ex1-7.c */
#include <stdio.h>

int main()
{
  printf ("The Open University of Japan\n");
  /* Web address
     https://www.ouj.ac.jp/ */
  
  // C++ Style comments
  // C99 allows single-line comments
}

一応, コンパイルして実行してみる.

$ gcc ex1-7.c -o ex1-7
$ ./ex1-7
The Open University of Japan

演習問題

問 1.1

天井関数 (ceil) と床関数 (floor) を利用したプログラムを作成しなさい.

/* code: q1-1.c */
#include <stdio.h>
#include <math.h>

int main ()
{
  double x, y;
  
  x = 3.14159;
  y = 0.0;
  printf ("x = %f\n\n", x);
  y = ceil (x);
  printf ("ceil (x) = %f\n", y);
  y = floor (x);
  printf ("floor (x) = %f\n", y);
  
  return 0;
}

そもそも, 天井, 床関数とは.

床関数(ゆかかんすう、英: floor function)と天井関数(てんじょうかんすう、英: ceiling function)は、実数に対しそれぞれそれ以下の最大あるいはそれ以上の最小の整数を対応付ける関数である。

wikpedia より.

コードをコンパイルして実行する.

$ gcc q1-1.c -o q1-1
$ ./q1-1
x = 3.141590

ceil (x) = 4.000000
floor (x) = 3.000000

問 1.2

平方根を計算するプログラムを作成しなさい. sqrt, sqrtf, sqrtl の異なるデータ型の平方根を求める関数を利用すること.

/* code: q1-2.c */
#include <stdio.h>
#include <math.h>

int main ()
{
  float fx, fz;
  double dx, dz;
  long double lx, lz;
  
  fx = 100.00F;
  fz = sqrtf (fx);
  printf ("fx = %f\n", fx);
  printf ("sqrtf (fx) = %f\n\n", fz);

  dx = 100.00;
  dz = sqrt (dx);
  printf ("dx = %f\n", dx);
  printf ("sqrt (dx) = %f\n\n", dz);

  lx = 100.00L;
  lz = sqrt (lx);
  printf ("lx = %Lf\n", lx);
  printf ("sqrt (lx) = %Lf\n\n", lz);
  
  return 0;
}
  • printf 関数では float 型や double 型を出力する場合, %f を用いる
  • scanf 関数で double 型変数への入力を行う場合には %lf が使われる (処理系によって異なる場合がある)

コードをコンパイルして実行する.

$ gcc q1-2.c -o q1-2
$ ./q1-2
fx = 100.000000
sqrtf (fx) = 10.000000

dx = 100.000000
sqrt (dx) = 10.000000

lx = 100.000000
sqrt (lx) = 10.000000

問 1.3

華氏から摂氏への換算を行うプログラムを作成しなさい.

/* code: q1-3.c */
#include <stdio.h>
#include <math.h>

int main()
{
  float celsius, fahrenheit;
  
  fahrenheit = 36.5;
  celsius = (5.0 / 9.0) * fahrenheit - 32.0;
  printf ("%f (Fahrenheit) = %f (Celsius)\n", fahrenheit, celsius);
  
  return 0;
}

コードをコンパイルして実行する.

$ gcc q1-3.c -o q1-3
$ ./q1-3
36.500000 (Fahrenheit) = -11.722222 (Celsius)

これだけだとつまらないので, ちょっと進化させてみる.

/* code: q1-4.c */
#include <stdio.h>
#include <math.h>

int main()
{
  float celsius, fahrenheit;

  printf ("Enter fahrenheit: ");
  scanf ("%f", &fahrenheit);

  celsius = (5.0 / 9.0) * fahrenheit - 32.0;
  printf ("%f (Fahrenheit) = %f (Celsius)\n", fahrenheit, celsius);
  
  return 0;
}

scanf 関数を利用して, 華氏温度にキーボードから入力した値を代入してみる.

$ gcc q1-4.c -o q1-4
$ ./q1-4
Enter fahrenheit: 100.0
100.000000 (Fahrenheit) = 23.555555 (Celsius)

こんな感じ.

以上

感じたことを少々.

  • C 言語は Go 言語っぽい雰囲気を感じた
  • printf するにも, 変数を利用するにも常に型を意識する必要があるのは新鮮だった
  • コード行末の ; の入力を忘れることが度々...
  • C 言語のテストの書き方ってどうするんだろう

2018 年 10 月 03 日 (水)

ジョギング

  • 山王公園往復
  • 懸垂 3 回, おじいさんっぽい人も懸垂やっていて負けられない思いがあった
  • 引き続き, 右足に違和感
  • 体がとにかく硬い

日課

  • (腕立て x 50 + 腹筋 x 50) x 3

今夜はお好み焼

  • お好み焼き専用の粉はよく出来ているなと思った
  • まあまあ美味しかった

今日のトゥウィート

これ, 試したい.

サニーとは, ダイレックスみたいに激安ではないが, そこそこのものがそこそこ安いお値段で手に入る. 複数の若いカップルがキャッキャしながら楽しそうに買い物しているので, この界隈はそういう層も結構住んでいるんだなと思った. また, 学校もあるし, 幼稚園, 保育園も多いので博多駅からほどほど近いにも関わらずベッドタウンと言っても良いのかな.

2018 年 10 月 02 日 (火)

ジョギング

  • 山王公園往復
  • 懸垂 3 回出来た!! (背筋をうまく使いたい)
  • 引き続き右足

日課

  • (腕立て x 50 + 腹筋 x 50) x 3

今夜も鍋

  • 奥さんはあまり好きではないらしいが...
  • 簡単に多くの食材を取れるという点, 体が温まるという点, 準備や片付けの手間が少ないという点がメリットだと考えているので, 今後もじゃんじゃん鍋っていこうと思う

放送大学二学期が始まった

  • ラジオの放送時間が業務中なので事前に本を読んでおいて, 放送を流しながら仕事をするというスタイル
  • 解らないところは録音や radiko.jp のタイムフリーで聞き直すという感じで
  • アルゴリズムとプログラミング第一回目ということで, プログラミング, アルゴリズムとはという簡単な座学から C 言語の超基礎的なことを話していた

ちなみに, C 言語について調べていたら C 言語にも認定資格試験があることを知った. 資格ビジネスに踊らされてしまうのはちょっと嫌だけど, こちらも勉強してみたいと思う.

C言語プログラミング能力認定試験│資格検定のサーティファイ│あなたのスキルアップを応援します|

今日のトゥウィート

11 時半をすぎると色んなニオイがしてくる.

自分よりも若い人が現役引退を決意した会見を深夜のスポーツニュースで見て.

2018 年 10 月 01 日 (月)

ジョギング

  • 山王公園往復
  • 走りはじめは良いけど, やっぱり終盤になると右足が張りまくっている感じ
  • 懸垂 2 回出来た

日課

  • (腕立て x 50 + 腹筋 x 50) x 3

今季初鍋

  • ちょっと寒くなってきたので, 今季, 初めての鍋を執り行った
  • シンプルに適当な野菜と鶏肉と豚, カイワレと大根の細切りを添えてポン酢で食べる
  • じゃんじゃん鍋していこうと思う

今日のトゥウィート

昨日の surface pro 3 ツイートのくだり. よく考えたら micro SD と書きたかったので勢い余って micro SSD と書いていた自分が恥ずかしい.

2018 年 09 月 30 日 (日)

ジョギング

  • 台風の為, おやすみ
  • 右足が張りまくっている感じ, なんとかせねばな...

日課

  • おやすみ

今日のトゥウィート

引っ越し後の片付けしていたら surface pro3 が出てきたので, Micro SSDUbuntu をインストールしてみたら意外にも元気に動き始めたのが嬉しかった.

冷凍のブリの切り身をいい感じで解凍して臭みを取ってからアヒージョ的なものを作ったら美味しかった.

俺のツールズ

俺が

俺の為に AWS の EC2 インスタンスや AMI, タグ等を操作する作ったツールをいくつかリリースしている.

start.oreno.tools

ほとんどを

見よう見まねの Go 言語で作っているので, なかなか Go 言語の雰囲気 (ディレクトリ構成やパッケージ管理とかも) に慣れないし, ちゃんとテストも書けていないのでずーっと修行が必要である.

直近で作ったやつは

SSM パラメータストアを操作するやつ

github.com

業務でパラメータストアを操作する必要があったので, これまでのノウハウを最大限に活かすことで二時間位でリリース出来た. この手をツールを作ると必ず公式のドキュメントを斜め読みし, AWS CLI のドキュメントのパラメータに寄せようとするので, 地味にそのサービスの勉強にもなることに気付いた. さらに, 単純な API のラッパーでしかないので, わざわざ Go 言語で書く必要は無いのかなーと思うことがあるが, MacOSLinux, Windows 環境で動かすことが出来たり, インストールの手順も簡素化出来るという点では Go 言語で書くメリットは十分にあると考えている.

今回作った pStore については, まだまだ改修の余地はあるが, 以下のようにパラメータストアに登録しているパラメータの一覧, パラメータの追加, 削除がいい感じで行えるはず.

# パラメータの一覧取得
$ pStore
+-------------------------------------+--------------------------+--------------+---------------------+
|                NAME                 |          VALUE           |     TYPE     |  LASTMODIFIEDDATE   |
+-------------------------------------+--------------------------+--------------+---------------------+
| /123456/88888                       | kawahara-test            | StringList   | 2018-09-29 08:09:43 |
| test.test1                          | ******************       | SecureString | 2018-09-28 22:42:23 |
+-------------------------------------+--------------------------+--------------+---------------------+

# パラメータの追加
$ pStore -put -name="foooooon" -value="baaaaaaarn"

$ pStore
+-------------------------------------+--------------------------+--------------+---------------------+
|                NAME                 |          VALUE           |     TYPE     |  LASTMODIFIEDDATE   |
+-------------------------------------+--------------------------+--------------+---------------------+
| /123456/88888                       | kawahara-test            | StringList   | 2018-09-29 08:09:43 |
| foooooon                            | baaaaaaarn               | String       | 2018-09-29 08:37:53 |
| test.test1                          | ******************       | SecureString | 2018-09-28 22:42:23 |
+-------------------------------------+--------------------------+--------------+---------------------+

# パラメータの削除
$ pStore -del -name="foooooon"
$ pStore
+-------------------------------------+--------------------------+--------------+---------------------+
|                NAME                 |          VALUE           |     TYPE     |  LASTMODIFIEDDATE   |
+-------------------------------------+--------------------------+--------------+---------------------+
| /123456/88888                       | kawahara-test            | StringList   | 2018-09-29 08:09:43 |
| test.test1                          | ******************       | SecureString | 2018-09-28 22:42:23 |
+-------------------------------------+--------------------------+--------------+---------------------+

詳しくは README を見てねとなる.

コマンドラインツールのテストをどうするか

AWS のリソースをどうやって用意するか

AWS のリソースに対してどのようにテストするか. いくつか参考になる記事を既に書かれている方がいらっしゃってとても参考になった.

medium.com

aws.amazon.com

有難うございます.

特に冒頭の記事に紹介されていた dockertest というモジュールは次のタイミングで利用してみたい. (今回は docker-compose を利用している)

github.com

ということで, 今回のテストについては AWS 環境は moto を利用することにした.

github.com

moto には moto_server というサーバーモードが用意されているので, このサーバーモードを利用して擬似的に API レスポンスを返す環境を用意した. また, moto_server は docker-compose を利用して起動するようにしてみた.

コマンドの出力結果をテストする

コマンドラインツールの出力をテストする場合, どのような方法が良いのかは以下の記事やスライドがとても参考になった.

出力結果をテストするということは, I/O に依存するテストということになるらしい.

I/O に依存するテストの例として, Ruby の場合だと StringIO クラスを利用してテストを書くと良いようだ.

require "rspec"

describe "stdout をテストする." do
  it "hello が出力されること." do
    $stdout = StringIO.new
    puts "hello"
    output = $stdout.string
    expect(output).to eq("hello\n")
    $stdout = STDOUT
  end
end

これを実行すると, 以下のように出力される.

$ rspec test_spec.rb --format documentation

stdout をテストする.
  hello が出力されること.

Finished in 0.00374 seconds (files took 0.18315 seconds to load)
1 example, 0 failures

Go 言語だと bytes.Buffer を利用すると良いとのこと.

package main

import (
    "bytes"
    "os/exec"
    "testing"
)

func TestCommand(t *testing.T) {
    cmd := exec.Command("echo", "hoge")
    stdout := new(bytes.Buffer)
    cmd.Stdout = stdout

    _ = cmd.Run()

    if stdout.String() != "hoge\n" {
        t.Fatal("Not matched")
    }
}

これを実行すると, 以下のように出力される.

$ go test -v
=== RUN   TestCommand
--- PASS: TestCommand (0.01s)
PASS
ok      go-test 0.016s

ということで, pStore のテストは

実行してみると, 以下のような出力になる.

$ make test
Creating network "tests_default" with the default driver
Creating moto-server ... done
=== RUN   TestVersionFlag
--- PASS: TestVersionFlag (1.54s)
=== RUN   TestStdoutList
--- PASS: TestStdoutList (1.60s)
=== RUN   TestStdoutPut
--- PASS: TestStdoutPut (3.33s)
=== RUN   TestStdoutDel
--- PASS: TestStdoutDel (3.33s)
=== RUN   TestStdoutPutSecure
--- PASS: TestStdoutPutSecure (4.43s)
=== RUN   TestStdoutPutList
--- PASS: TestStdoutPutList (4.93s)
=== RUN   TestConvertDate
--- PASS: TestConvertDate (0.00s)
PASS
ok      pStore  19.186s
Stopping moto-server ... done
Removing moto-server ... done
Removing network tests_default

ただ, これだけなんだけど.

以上

永遠の初心者が「俺のツールス」を通して, 少しでもプログラミングのスキルが上がると嬉しいなと思っている.

2018 年 09 月 29 日 (土)

ジョギング

  • おやすみ
  • 右足が張りまくっている感じは引き続きなので, 強めにストレッチをしておいた

日課

  • (腕立て x 50 + 腹筋 x 50) x 3

買い出し

  • 久しぶりにダイレックスに買い出し
  • 東比恵あたりがめっちゃ混むので夕方の時間帯は止めておこうと思った

SSM パラメータストア

Golang の勉強の為, SSM パラメータストアをちょこっと操作するツールを作った.

github.com

ツールを作るからにはテストも書くべきということで, テストも少しだけ書いてみた. Go 製の CLI ツールのテストについて言及されている以下のブログ記事が勉強になった.

Go言語でテストしやすいコマンドラインツールをつくる | SOTA

また, 以下のスライドも勉強になった.

Unit-testing programs depend on I/O in Go

2018 年 09 月 28 日 (金)

ジョギング

  • 自宅〜山王公園〜自宅
  • 右足が張りまくっている感じ

日課

  • (腕立て x 50 + 腹筋 x 50) x 3

マッサージ

  • お昼休みに近所のマッサージ屋さんに
  • 45 分コース
  • やっぱり右半身に強い張り

今日のトゥウィート

そんな気持ち.

2018 年 09 月 27 日 (木)

ジョギング

  • 自宅から博多駅を経由して呉服町まで
  • 信号が多すぎて走りづらかった

日課

  • おやすみ

JAWS-UG 福岡もくもく会

10 回目ということで. 焼き鳥屋さんでもくもく. 楽しかった.

今日のトゥウィート

もくもく会, 盛り上がりました.

2018 年 09 月 26 日 (水)

ジョギング

  • 山王公園まで往復 35 分程
  • 改めて懸垂してみたら 1 回だけ上げれた, 明日は 2 回上げれると嬉しい

日課

  • おやすみ

とんとん

  • 刺盛り 1 人前, すごく鮮度が良くて美味しんだけど, 意外に高価ということが判ったので, 刺盛り頼む時はお祝いごとの時だけにしたい
  • 色々とこれからの事を考えながら, キープしている焼酎をチビチビ

放送大学

印刷教材が届いたのでやっていく. 今回は「アルゴリズムとプログラミング」.

今日のトゥウィート

輸入物で良いので分厚いやつ食べたい. ミディアムレアで.