WEB+DB PRESS Vol.118

読んだ感想。

特集1 実践リモートワーク

リモートワークになったら、今まで通りの成果を上げるのが難しそうだし、評価したりされたりするのも難しそうだ。まぁ、自分は緊急事態宣言中も出勤した社畜ですが。GMO ペパボのような、既にリモートワークの土壌があるような会社は東京を中心に結構あると思うが、どこもまだ試行錯誤の段階っぽく、こうした事例が出てくるのはありがたい。

リモートワークをやるとなると、高速なインターネット回線は必須。うちのマンションが提供する回線は遅いので、フルリモートになったら仕事にならないだろうな。リモートワークだとインターネット回線費や光熱費がかかるわけで、今まで通勤手当だったものが、インターネットや光熱費の手当てに変わるんだろうか。

特集2 Pythonデータ可視化入門

収集したデータを可視化するために必要なツールが Python には揃っていて、本特集の通りやればデータを分析する環境を整えることができそう。残るは可視化したデータから何を読み取るかの術を身に付けることだけど、それはデータサイエンスの領域か。ただ、本特集で得た知識を本業で生かそうにも、携わっているクラウドサービスはデータを収集するところからの段階で、可視化以前の問題だった。

特集3 はじめての脆弱性調査

徳丸本を読んでから現在まで、自分が直接携わる Web アプリケーションの脆弱性対策は心がけてきたつもり。主に Azure App Service でホストし、ミドルウェアも Azure SQL Database なんかを使ってきたので、ミドルウェアやネットワークの脆弱性診断はやったことがない。それに、一朝一夕で身につくものでもなさそう。

本業で脆弱性診断をやるとしたら、専門の業者に依頼するか、セキュリティエンジニアを採用したいところだけど、自分には裁量が無いのでどちらも不可能に近い。クラウドベンダーが提供する PaaS や SaaS を使って、クラウドベンダーに任せてしまう路線を続けるしかなさそうだ。

WEB+DB PRESS Vol.118

WEB+DB PRESS Vol.118

  • 発売日: 2020/08/24
  • メディア: Kindle

ABC046B - AtCoDeerくんとボール色塗り

atcoder.jp

1 番目のボールを塗る色は K 通り。2番目のボールには 1 番目と同じ色が使えないので K - 1 通り。3 番目のボールには 2 番目と同じ色が使えないので、これまた K - 1 通り。後はその繰り返しで、N 番目のボールを塗る色は K - 1 通り。

using System;

namespace ABC046B
{
    class Program
    {
        static void Main(string[] args)
        {
            var input = Console.ReadLine().Split(' ');
            var N = int.Parse(input[0]);
            var K = int.Parse(input[1]);

            var A = K * Math.Pow(K - 1, N - 1);
            Console.WriteLine(A);
        }
    }
}

ABC055B - Training Camp

atcoder.jp

System.Numerics.BigInteger を使えば N が最大値 100000 でも計算できるけど、時間がかかりすぎて、とても2秒以内には終わらない。 最後に剰余を計算せずとも、毎回計算しても大丈夫だった。

using System;

namespace ABC055B
{
    class Program
    {
        static void Main(string[] args)
        {
            var n = int.Parse(Console.ReadLine());
            var m = 1000000007L;
            var a = 1L;

            for(var i = 1; i <= n; i++)
            {
                a = (a * i) % m;
            }

            Console.WriteLine(a);
        }
    }
}

ABC070B - Two Switches

atcoder.jp

スイッチを離した時間の早い方と、スイッチを押し始めた時間の遅い方の差を求めればいい。差がマイナスなら、同時に押している時間はない。

using System;

namespace ABC070B
{
    class Program
    {
        static void Main(string[] args)
        {
            var input = Console.ReadLine().Split(' ');
            var a = int.Parse(input[0]);
            var b = int.Parse(input[1]);
            var c = int.Parse(input[2]);
            var d = int.Parse(input[3]);

            var begin = Math.Max(a, c);
            var end = Math.Min(b, d);
            var answer = begin < end ? end - begin : 0;
            Console.WriteLine(answer);
        }
    }
}

ABC096C - Grid Repainting 2

atcoder.jp

左上から順番に探索していって、# のマスのとき「上下左右に隣接するマスのうちどれか1つでも # があるか」をチェックする。# があれば探索を続け、無ければ目標を達成できないので探索終了。

using System;
using System.Collections.Generic;

namespace ABC096C
{
    class Program
    {
        static void Main(string[] args)
        {
            var input=Console.ReadLine().Split(' ');
            var H = int.Parse(input[0]);
            var W = int.Parse(input[1]);
            var s = new List<string>();
            for(var i = 0; i < H; i++)
            {
                s.Add(Console.ReadLine());
            }

            var answer = "Yes";
            for (var x = 0; x < W; x++)
            {
                for (var y = 0; y < H; y++)
                {
                    if (s[y][x] == '#')
                    {
                        if (!CanPaint(s, H, W, x, y))
                        {
                            answer = "No";
                            break;
                        }
                    }
                }
            }
            Console.WriteLine(answer);
        }

        static bool CanPaint(List<string> s, int H, int W,int x, int y)
        {
            if (x > 0 && s[y][x - 1] == '#') return true;
            if (y > 0 && s[y - 1][x] == '#') return true;
            if (x + 1 < W && s[y][x + 1] == '#') return true;
            if (y + 1 < H && s[y + 1][x] == '#') return true;
            return false;
        }
    }
}

ABC075B - Minesweeper

AtCoder Beginners Selection は全部解いたので、次は AtCoder Beginner Contest の過去問を解くことにした。

atcoder.jp

左上から順に全探索しつつ、現在のマスが . だったら、接しているマスに # が何個あるかを数えて出力していく。

using System;
using System.Collections.Generic;

namespace ABC075B
{
    class Program
    {
        static void Main(string[] args)
        {
            var input = Console.ReadLine().Split(' ');
            var H = int.Parse(input[0]);
            var W = int.Parse(input[1]);
            var S = new List<string>();
            for (var i = 0; i < H; i++)
            {
                S.Add(Console.ReadLine());
            }

            for (var i = 0; i < H; i++)
            {
                for (var j = 0; j < W; j++)
                {
                    if (S[i][j] == '#')
                    {
                        Console.Write('#');
                    }
                    else
                    {
                        var count = CountBomb(S, j, i);
                        Console.Write(count);
                    }
                }
                Console.WriteLine();
            }
        }

        static int CountBomb(List<string> S, int x, int y)
        {
            var count = 0;
            for (var i = y - 1; i <= y + 1; i++)
            {
                if (i < 0 || S.Count <= i)
                {
                    continue;
                }
                for (var j = x - 1; j <= x + 1; j++)
                {
                    if (j < 0 || S[i].Length <= j || (i == y && j == x))
                    {
                        continue;
                    }
                    if (S[i][j] == '#')
                    {
                        count++;
                    }
                }
            }
            return count;
        }
    }
}

ABC086C - Traveling

atcoder.jp

次の目的地に向かって進んでいって、早く着きそうだったら周辺で時間を潰し、最終的に時間ぴったりに着けば OK。

using System;

namespace ABC086C
{
    class Program
    {
        static void Main(string[] args)
        {
            var n = int.Parse(Console.ReadLine());
            var lines = new int[n][];
            for (var i = 0; i < n; i++)
            {
                var line = Console.ReadLine().Split(' ');
                lines[i] = new int[3]
                {
                    int.Parse(line[0]),
                    int.Parse(line[1]),
                    int.Parse(line[2]),
                };
            } 

            var t = 0;
            var x = 0;
            var y = 0;
            for (var i = 0; i < lines.Length; i++)
            {
                var tNext = lines[i][0];
                var xNext = lines[i][1];
                var yNext = lines[i][2];

                var tDiff = tNext - t;
                for(var j = 0; j < tDiff; j++)
                {
                    if (x != xNext)
                    {
                        if (x < xNext)
                        {
                            x++;
                        }
                        else
                        {
                            x--;
                        }
                    }
                    else if (y != yNext)
                    {
                        if (y < yNext)
                        {
                            y++;
                        }
                        else
                        {
                            y--;
                        }
                    }
                    else
                    {
                        // 目的地に早く着いてしまったら周囲で時間を潰す
                        y++;
                    }
                }

                // 時間ピッタリに着けなかったら No
                if (x != xNext || y != yNext)
                {
                    Console.WriteLine("No");
                    return;
                }
                t = tNext;
            }
            Console.WriteLine("Yes");
        }
    }
}