真面目なブログはこっち 👉 blog.s64.jp

C# で雑にFizzBuzz

プログラミング学び直しシリーズ。FizzBuzzをC#で愚直に書く。

class MainClass
{

    public static void Main(string[] args)
    {
        foreach (int i in Enumerable.Range(1, 100))
        {
            Console.WriteLine(fizzBuzz(i));
        }
    }

    static string fizzBuzz(int x)
    {
        StringBuilder b = new StringBuilder();

        if (fizz(x)) b.Append("Fizz");
        if (buzz(x)) b.Append("Buzz");
        if (b.Length == 0) b.Append(x);

        return b.ToString();
    }

    static bool fizz(int x)
    {
        return x % 3 == 0;
    }

    static bool buzz(int x)
    {
        return x % 5 == 0;
    }

}

ひと目見ただけで何が起きてるのか理解するのはこれくらいが良さそうだけど、もっとスマートな書き方をあとで考えてみよう。

「マスタリングTCP/IP 入門編 第5版」の読書感想文

プログラミング学び直し活動の一環として、「マスタリングTCP/IP 入門編 第5版」を読みました。

マスタリングTCP/IP 入門編 第5版

マスタリングTCP/IP 入門編 第5版

以下は読書感想文です

読むとよさそうな人

  • アプリケーションばかりでOSやインフラ等の層へ関与しない人
  • 雰囲気でプログラミングをしている人
  • プログラミングに興味のある人、学生

向いてる用途

  • コンピュータとネットワークの歴史を知る
  • プログラミングの考え方を鍛える (OSI参照モデルなど)
  • 中学 〜 高校講師が生徒向けのテキストとして採用する
  • ネットワークについて雰囲気を知る
  • 現代のアプリケーションについて大雑把にイメージする

向いてない / できないこと

  • Internet Protocolを書けるようになる
  • TCP/IPより上の層でプロトコルを書く

感想

広く浅くネットワークやそれに付随する概念を学ぶことができた。

コンピュータの歴史上にネットワーク、特にインターネットが必要不可欠であることが理解できる解説から始まり、アプリケーションばかり開発している自分は関与し得ない歴史的背景を知ることができた。
他者からインターネットの仕組みについて訊ねられた際に返答する分には十分な知識を得ることができる。が、これを読むことで実際にIPやその上位層のプロトコルを書けるようにはならない。あくまで大まかな雰囲気を知る、まさに "入門" にふさわしい本であろう。

また、いわゆる "パソコンの授業" を担当している講師はこれを元にカリキュラムを作ることができると感じた。自分も実際に担当している授業で取り入れようと思う。
挿絵や例えも多く、前提知識が少なく平易な言葉で書かれているため、初学者への教え方に困った際にも参考になるだろう。

TCP/IP全体像として各層のプロトコルが複雑に絡み合っているため致し方ないことではあるが、各章の内容を順々に読むだけでは少々理解しづらく、2週するなどして前後の内容を把握した状態で読み直すとより理解が深められるのではと感じた。

f:id:S64:20180405224506j:plain

昭島市長である臼井 伸介さまより献本いただきました。ありがとうございます。

PLEXチューナ + Chinachu gamma + CentOS 7で録画サーバを作るAnsible Playbook

約3年ぶりに眠ってる録画サーバを復活させようとした時のメモ。
今回利用したのは、

  • x86_64系サーバ (ベアメタル前提)
  • PLEX社製USBデータ供給チューナ
  • ICカードリーダ
    • SCR3310-NTTComを使いましたが、SCR3310/v2.0でも平気かもしれません

など。
注意点として、今回 PX-W3PE, PX-Q3PE などの接尾辞が4でないチューナは扱えません。これはCentOS 6向けドライバしか提供されておらずCentOS 7で利用できないこと、またCentOS 6は既にDockerのサポートが切れておりdocker-composeなどの導入が困難なためです。

ちなみに、多分pt3とかでもいけます。

1. CentOS 7入れる

サーバなのでMinimalがよいです。以降はOS導入直後のクリーンな環境を前提に進めます。
そういったalternativeなメディアはこちらから取ってくるとよいと思います。
インストーラ時点でインターネットに接続しておくと、次の手順が楽です。

2. gitとansible入れる

OSを入れたら以下コマンドを実行すればインストールできると思います。インターネット接続済みであることが前提です。
gitは標準リポジトリから取得できますが、ansibleはepelからの取得になります。そのためepel-releaseを追加していることに注意してください。

yum update -y # 各種パッケージの更新
# ...
# Complete!
yum install -y git epel-release
# ...
# Complete!
yum install -y ansible
# ...
# Complete!

なお、ansibleは後述のplaybookを実行するため、gitはそのplaybookを取得するために使います。そのため録画サーバに直接関係はありません。
終わったらカーネルなども更新されてるかもしれないので、再起動しておきます。

3. 作っておいたPlaybookをcloneする

セットアップを全て自動化できるようにAnsibleのPlaybookにまとめておきました。サーバ構築の肝は全部勝手にやれると思います。

cd ~ # 念の為
git clone 'https://github.com/S64/ansible-chinachu-gamma-playbook.git'
cd ansible-chinachu-gamma-playbook # 入る

4. READMEやplaybookのソースをよく読む

S64/ansible-chinachu-gamma-playbookを読み、playbookを実行することで具体的に何が行われるのか確認しておいてください。少し変わったことをしています。例えば、Chinachu/docker-mirakurun-chinachuをベースにカスタマイズしている、PLEXチューナ向けrecpt1をrecpx4としてインストールしているなどです。

気に入ったらGitHub上でStarを付けてください。

Star

5. playbookを実行する

rootでやりました。記事執筆時点では冪等性を担保してないので注意してください。

ansible-playbook 10_setup.yml

ドライバインストールなどの様々な面倒がここで全て完了します。気に入ったらStarを付けてください。

6. チューナの設定ファイルを記述する

Mirakurunではtuners.ymlに設定を記述します。このplaybookを利用した場合、設定ファイルの位置は /opt/chinachu/docker-mirakurun-chinachu/mirakurun/conf/tuners.yml になります。

具体的な設定内容はこちらをそのまま利用しても問題ありません。

cd /opt/chinachu/docker-mirakurun-chinachu/mirakurun/conf
vi tuners.yml # `vi`が難しければ`nano`をインストールするとよいかも

7. 再起動して使い始める

再起動すると、自動的にChinachu / Mirakurunがビルドされ、起動します。
ビルドがそれなりに長いので、初回は起動に時間が掛かります。もし手元でビルドが成功することを確認しておきたい場合は、再起動する前に以下を実行するとよいです。

cd /opt/chinachu/docker-mirakurun-chinachu
docker-compose build

おしまい

もしわからないことがあったり、特に壊れている場合はGitHubのIssueまたはTwitterで教えてください。Playbook側管轄の内容なら対応したいです。

蟻本第2版34ページの問題をHaskellで書く

蟻本第2版23ページの問題 (POJ 1852) をHaskellで書く - 🍥shuma_yoshiokaに引き続き、プログラミング学び直し日記。「プログラミングコンテストチャレンジブック 第2版」の34ページより、「部分和問題」。類似問題はこちら。

プログラミングコンテストチャレンジブック [第2版] ?問題解決のアルゴリズム活用力とコーディングテクニックを鍛える?

プログラミングコンテストチャレンジブック [第2版] ?問題解決のアルゴリズム活用力とコーディングテクニックを鍛える?

f0 :: [Int] -> Int -> Bool
f0 (a:as) k = a == k || f0 as k || f1 a as k
f0 [] _ = False

f1 :: Int -> [Int] -> Int -> Bool
f1 x (y:ys) k = x + y == k || f1 (x+y) ys k
f1 _ [] _ = False

main :: IO ()
main = do
    _ <- readLn :: IO Int -- n
    as <- (map read . words) <$> getLine :: IO [Int]
    k <- readLn :: IO Int

    putStrLn $ if (f0 as k) then "Yes" else "No"

コレで合ってるか大変不安である。しかし参考ナシで例を一発正当できたので嬉しい。

蟻本第2版23ページの問題 (POJ 1852) をHaskellで書く

蟻本第2版21ページの問題をHaskellで書く - 🍥shuma_yoshiokaに引き続き、プログラミング学び直し日記。「プログラミングコンテストチャレンジブック 第2版」の23ページより、「Ants」の問題。類似問題はこちら。

プログラミングコンテストチャレンジブック [第2版] ?問題解決のアルゴリズム活用力とコーディングテクニックを鍛える?

プログラミングコンテストチャレンジブック [第2版] ?問題解決のアルゴリズム活用力とコーディングテクニックを鍛える?

fMin :: [Int] -> Int -> Int
fMin (x:xs) l = maximum [ minimum [x, l-x], (fMin xs l) ]
fMin [] _ = minBound

fMax :: [Int] -> Int -> Int
fMax (x:xs) l = maximum [(l-x), (fMax xs l)]
fMax [] _ = minBound

main :: IO ()
main = do
    l <- (readLn :: IO Int)
    _ <- (readLn :: IO Int) -- n
    xs <- (map read . words) <$> getLine :: IO [Int]

    let r = ( fMin xs l , fMax xs l )

    putStrLn $ "min = " ++ show (fst r) ++ "\nmax = " ++ show (snd r)

この回答自体はとてもアッサリで、問題文から導き出す過程が大変。解説文ナシで解く技量はまだ無い。

蟻本第2版21ページの問題をHaskellで書く

FPについて学び直しメモ - 🍥shuma_yoshiokaに引き続き、プログラミング学び直し日記。「蟻本」こと「プログラミングコンテストチャレンジブック 第2版」を読みながら、問題をHaskellで解いてゆく試み。

プログラミングコンテストチャレンジブック [第2版] ?問題解決のアルゴリズム活用力とコーディングテクニックを鍛える?

プログラミングコンテストチャレンジブック [第2版] ?問題解決のアルゴリズム活用力とコーディングテクニックを鍛える?

21ページより「三角形」の問題。類似問題はこちら。

f1 (x:xs) = maximum [(f2 x xs), (f1 xs)]
f1 [] = 0

f2 x (y:ys) = maximum [(f3 x y ys), (f2 x ys)]
f2 _ [] = 0

f3 x y (z:zs) = maximum [(f4 (maximum [x, y, z]) (x + y + z)), (f3 x y zs)]
f3 _ _ [] = 0

f4 max len = if (len - max) > max then len else 0

main :: IO ()
main = do
    _ <- (readLn :: IO Int) -- n
    as <- (map read . words) <$> getLine :: IO [Int]
    print $ f1 as

ほぼ初めてということもあり、ループを使わず再帰脳づくりするのにかなり時間掛かった

FPについて学び直しメモ

OOPについて学び直しメモ - 🍥shuma_yoshioka に引き続き、雰囲気でプログラミングしているのでFP (Functional Programming, 関数型プログラミング) について雑に学び直した。
学び直しとは言うけど、そもそも関数型プログラミングは勉強したことないし、もっと言うとちゃんとHaskell書いたのも初めてになる。

手続型言語と関数型言語の違い

明確な定義は無いらしいが、言語自体に 関数の再帰呼出しによるプログラムの数式化 を助ける機構があるか否か、がポイントとなるもよう。

Javaはオブジェクトを手続型のように扱えるのがコンセプトとなる言語なので、このような言語は オブジェクト指向型言語 などのように分類されやすい (手続き型言語として分類されにくい) 。よって、手続き型言語には例えば PHP, Python などが挙げられやすい。
対し関数型として挙げられやすい言語は、Lisp, Haskell, OCaml, Erlang, Scala など。(Scalaはハイブリッドと言われがちだが)

Javaが「全てがオブジェクトである」のと同じように、関数型言語は「全てが数式である」と言える。
オブジェクト指向言語は、たとえ同じメソッドであってもそのオブジェクトが持つ状態により暗黙的に値が変わる場合が多々ある。
あまり良い例とは言い難いが、パッと出せるとこで言うと例えば、

class MyCls {
  
  private final int state1;
  private final int state2;

  public MyCls(int state1, int state2) {
    this.state1 = state1;
    this.state2 = state2;
  }

  public int calcState(int x) {
    return x * (state1 + state2);
  }
}

// App.java
public class App {

  public static void main(String[] args) {
    MyCls obj = new MyCls(2, 3);
    System.out.println(obj.calcState(5)) // 上の行を知らないと、ここの式で何が出力されるかわからない
  }
}

というのが発生する。これは決して常に悪く作用するわけではないが、参照透過性が無いと言える。
参照透過性は、入力が同じなら同じ作用と同じ値を返す状態で成立する。つまり手計算した値を直接埋め込んでも大丈夫な状態でなければいけない。

対し関数型言語とし例えばHaskellの場合、以下のようにするだろう。

data MyState = MyState { state1 :: Int, state2 :: Int }

calcState x y = x * (state1 y + state2 y)

main = do
  let my = MyState { state1 = 2, state2 = 3 }
  print $ calcState 5 my

このような参照透過性を実現する強い制約が関数型言語をそれたらしめていると言える。
そしてこのような制約のおかげで、再帰呼出しによる数式化が助けられている。

fibSeq x y = [x] ++ fibSeq y (x + y)
-- または `fibSeq x y = x : fibSeq y (x + y)`

main = do
  print $ take 10 $ fibSeq 0 1

{-
  フィボナッチ数列を求める簡単な例。
  読み方:
    1. 第一引数のみを持った配列をつくる
    2. xとyを足し合わせたものを求める
    3. 再帰呼び出しで配列を取る。第一引数はy、第二引数はさきほど足し合わせたもの
    4. それらの配列を連結する。第一引数の次に第二引数という風に結合され、さらにそれを足し合わせたもの、という形に無限に求め続ける
    5. `take 10`を使い、先頭から10番目の要素までを取り出す (現れた時点で辞める)
    6. それを標準出力へ
-}

なおパターンマッチなども特徴的だが、これらはあくまでも言語機能、糖衣構文のようなものでしかないので深くは言及しない。

関数型言語のエッセンス

関数型言語の特徴として、前述のとおり数式化可能なこと、参照透明性が高いことが挙げられる。
そうした特徴は様々な非関数型言語へも取り入れられている。たとえば、JavaのStream, Reactive Extensionsなども関数型言語の影響を受けている。

関数を引数とした関数を高階関数 (ハイオーダー ファンクション) という。Reactive ExtensionsなどのRxと呼ばれるライブラリは、FRP (Functional Reactive Programming) を実現するもの。Reactive、Observableは非同期プログラミングにおける概念なので、ここでは深く言及しない。
またKotlinなどはCollectionsとして同様の高階関数を提供している。

おしまい

他にも触っておくべきことが多そうだが、恥ずかしながら関数型言語の利用経験が少ないためすぐに思いつかなかった。そのため一旦ここで区切ることにする。
参考にした記事は、

など。