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

C# でソート練習

プログラミング学び直しシリーズ。食わせる数列は以下。1 〜 100の100個の整数をランダムに並べたもの。

60 32 85 24 57 31 98 50 49 81 52 80 96 41 55 91 54 70 77 36 94 74 89 29 38 1 34 73 4 2 6 18 16 65 51 3 22 56 9 28 13 46 17 33 45 72 99 26 76 14 42 82 44 35 53 19 92 87 90 8 12 95 97 69 20 37 48 15 66 64 78 83 40 79 75 86 68 62 61 10 84 100 93 27 21 43 25 67 71 88 63 23 11 39 30 59 5 58 7 47

バブルソート

using System;
using System.Linq;

public class Program
{

    public static void Main(string[] args)
    {
        var steps = 0;
        var list = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();

        bool swapped = false;
        do
        {
            swapped = false;
            for (var i = 0; i < list.Length - 1; i++)
            {
                steps++;
                var a = list[i];
                var b = list[i + 1];

                if (a > b)
                {
                    list[i] = b;
                    list[i + 1] = a;
                    swapped = true;
                }
            }
        } while (swapped);

        foreach (var x in list)
        {
            Console.WriteLine(x);
        }

        Console.WriteLine("steps: " + steps);
    }

}
steps: 9207

シェイカーソート

using System;
using System.Linq;

public class Program
{

    public static void Main(string[] args)
    {
        var steps = 0;
        var list = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();

        bool swapped = false;
        do
        {
            swapped = false;

            for (var i = 0; i < list.Length - 1; i++)
            {
                steps++;
                var a = list[i];
                var b = list[i + 1];

                if (a > b)
                {
                    list[i] = b;
                    list[i + 1] = a;
                    swapped = true;
                }
            }

            for (var i = list.Length - 1; i > 0; i--)
            {
                steps++;
                var a = list[i];
                var b = list[i - 1];

                if (a < b)
                {
                    list[i] = b;
                    list[i - 1] = a;
                    swapped = true;
                }
            }

        } while (swapped);

        foreach (var x in list)
        {
            Console.WriteLine(x);
        }

        Console.WriteLine("steps: " + steps);
    }

}
steps: 5346

ノームソート

using System;
using System.Linq;

public class Program
{

    public static void Main(string[] args)
    {
        var steps = 0;
        var list = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();

        for (int i = 0; i < list.Length - 1; i++)
        {
            do
            {
                steps++;
                var a = list[i];
                var b = list[i + 1];

                if (a > b)
                {
                    list[i] = b;
                    list[i + 1] = a;
                    i--;
                }
                else
                {
                    break;
                }
            } while (i != -1);
        }

        foreach (var x in list)
        {
            Console.WriteLine(x);
        }

        Console.WriteLine("steps: " + steps);
    }

}
steps: 5158

選択ソート

using System;
using System.Linq;

public class Program
{

    public static void Main(string[] args)
    {
        var steps = 0;
        var list = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();

        for (var i = 0; i < list.Length; i++)
        {
            var min = i;

            for (var j = i + 1; j < list.Length; j++)
            {
                steps++;
                if (list[min] > list[j])
                {
                    min = j;
                }
            }

            steps++;
            if (i != min)
            {
                var a = list[i];
                var b = list[min];

                list[i] = b;
                list[min] = a;
            }
        }

        foreach (var x in list)
        {
            Console.WriteLine(x);
        }

        Console.WriteLine("steps: " + steps);
    }

}
steps: 5050

C# で愚直にN-Queens問題

プログラミング学び直しシリーズ。Nクイーン問題 (8クイーン問題) をC# で愚直に解く。

using System.Collections.Generic;
using System.Linq;
using System;

class MainClass
{
    public static void Main(string[] args)
    {
        nQueen(
            int.Parse(Console.ReadLine())
        );
    }

    static void nQueen(int n)
    {
        var queens = new List<Queen>();
        for (int y = 0; y < n; y++)
        {
            for (int x = 0; x < n; x++)
            {
                if (check(queens, x, y))
                {
                    queens.Add(new Queen(x, y));
                    break;
                }
                else
                {
                    while (x == (n - 1) || y == (n - 1))
                    {
                        var q = queens.Last();
                        y = q.y;
                        x = q.x;
                        queens.Remove(q);
                    }
                }
            }
        }

        foreach (var q in queens)
        {
            Console.WriteLine(q);
        }
    }

    static bool check(List<Queen> queens, int x, int y)
    {
        foreach (var q in queens)
        {
            if (q.x == x || q.y == y || Math.Abs(x - q.x) == Math.Abs(y - q.y))
                return false;
        }
        return true;
    }

    class Queen
    {
        public int x { get; set; }
        public int y { get; set; }

        public Queen(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public override string ToString()
        {
            return string.Format("x={0}, y={1}", x, y);
        }

    }

}

出力例。例えば8の場合:

x=2, y=0
x=4, y=1
x=1, y=2
x=7, y=3
x=5, y=4
x=3, y=5
x=6, y=6
x=0, y=7

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)

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