(2019年エイプリルフール)「違法ソフト対策室」からの発表

2019年4月1日 エイプリルフールネタ。「違法ソフト対策室」「シウマイ警察」「神戸ビーフ警察」「T〇SS」「マックロソフト」「真黒黒男氏」等は実在しません。

・・・ただし、この問題を持つ違法アプリは多いです。

=====================================================================

経済産業省・文部省・総務省が共同で設立した部署「違法ソフト対策室」は 2019年4月1日、OS「マックロソフト ウィドウズ」および表計算ソフト「マックロソフト エグジール」を違法ソフトだから利用しないよう通達を出した。

「違法ソフト対策室」は対象のソフトが違反した法律は「明治五年太政官布告第三百三十七号(改暦ノ布告)」としている。

この法律の別紙の「時刻表」では「午前零時 即午後十二時  子刻」「十二時 午刻」となっており、このことから「午前0時、すなわち午後12時は 真夜中」「午前12時は正午」となっているが、上記のソフトでは「午前12時は真夜中」「午後12時は正午」としている。

「マックロソフト ウィドウズ」の時刻形式の設定画面で確かめたところ、確かに「午前12時 = 24時制の 0時」であることが確認された。

午前1200

また、「マックロソフト エグジール」でも「午前12時 = 24時制の 0時」「午後12時 = 24時制の 12時」となっている。

午前1200_MX

これらの問題は「明治五年太政官布告第三百三十七号(改暦ノ布告)」の法律で定められている 「午前/午後」が欧米で利用される「a.m./p.m.」とは異なるにも関わらず法律を無視して「a.m./p.m.」の定義をそのまま流用したことに起因している。(「『12:30 am』は何時か」について語ってみる」)

違法ソフトとの指摘を受けた日本マックロソフトの社長 真黒黒男(まっくろくろお)氏は「指摘は真摯に受け止め、改修することを検討する。・・・ところで、科学技術庁長官が解散を検討すると述べた EM菌議連(有用微生物利活用推進議員連盟)って解散したでしょうか?」と検討すると言いつつ改修する意思がないことを匂わせた。

一方、サイバー捜査でフットワークが軽いことで評判のシウマイ警察、神戸ビーフ警察がこの件で強制捜査の令状の請求を裁判所に行っているとの情報が入ってきている。

「違法ソフト対策室」では「日本の法律を蔑ろにし、ひいては日本という国家を蔑ろにしている悪質な事例である。他の OS・アプリ等についても引き続き調査して違法ソフトを撲滅していく」としている。

さらに「違法ソフト対策室」は「T○SS(超○算数推進会)と協力し、OS のソースコード提出を求め、閏年が正しく求められているかについても検証する」としている。(「明治三十一年勅令第九十号(閏年ニ関スル件)」「正しい閏年の求め方」)

「T○SS」はこの協力を申し出た経緯として「『算数は国語』に続いて「プログラミングは国語」という教えを定着させるため、協力することにした」としている。

SQL Server 2017 のGraph拡張を試してみた

SQL Server 2017 には 「Graph 拡張」というのができる。

https://blogs.technet.microsoft.com/dataplatforminsider/2017/04/20/graph-data-processing-with-sql-server-2017/

みたところこの記事(2017年4月)の時点では

  • node
  • edge

といった、特定のフィールドを予め持ったテーブルを作成できるだけというレベルだが。
今後の拡張には期待。

でもとりあえず1度は試してみた。 CodeIQ のとある問題で試してみた。
(7/18 追記:なお、これは SQL Server 2017 CTP2.1 で試しています。
この前後に RC1 がリリースされたので。。。。)

が、これは公開できない(まだ公開中の問題だし) ので別に問題を作って試してみることにする。

n × m で区切られた領域があり、それぞれには 0 から9までの「高さ」がある。
上下左右のみ移動可能で、
高さが同じならば 4分、高さが 1増えるならば7分、高さが1 減るならば 3分で移動できる。
左上から右下まで最短何分でいけるか。
ただし、たどり着く少なくとも経路は一つあるものとする。

なんかどっかで見かけた問題に似ていないこともないがこれで試してみよう。

まず、テーブルを作成する。


IF object_id('dbo.SAMPLE_N') IS NOT NULL BEGIN
    DROP TABLE dbo.SAMPLE_N
END

CREATE TABLE dbo.SAMPLE_N(
    X INT
    , Y INT
    , H INT
    , TT INT
    , constraint PK_SAMPLE_N PRIMARY KEY(
        $node_id)
    ) AS NODE

CREATE UNIQUE INDEX IDX_SAMPLE_N__XY ON SAMPLE_N(X,Y);

IF object_id('dbo.SAMPLE_E') IS NOT NULL BEGIN
    DROP TABLE dbo.SAMPLE_E
END

CREATE TABLE SAMPLE_E(
        W INT NOT NULL
            , constraint PK_SAMPLE_E PRIMARY KEY(
                $edge_id
            )
    ) AS EDGE

CREATE INDEX IDX_SAMPLE_E__F ON SAMPLE_E($from_id);

node のテーブルは

CREATE TABLE table_n () as node

の形式で「as node」を付ける。すると自動的には「$node_id」の列名でアクセスできる列ができる。(ただし、実際の列名はローカル一時テーブルのときのように $node_id ではない。が、今後「$node_id列」と呼ぶ。)
この 「$node_id列」、特にキーとかにはなっていないので今回はこの「$node_id列」を主キーとする。
その他、各ノードは座標(X,Y) と高さ H、そして後で設定する所要時間(Travel Time) TT の列を持ち、座標には Unique index を付けた。

edge のテーブルは

CREATE TABLE table_n () as edge

の形式で「as edge」を付ける。すると自動的には「$edge_id」「$from_id」「$to_id」の列名でアクセスできる列ができる。(同じく、実際の列名は違うが「$edge_id列」「$from_id列」「$to_id列」と呼ぶ。)
主キーは 「$edge_id列」とし、「$from_id列」にも index を作成する。
Edge にはその経路を通る場合の重み(Weight) W の列を付けた。

テーブルはできたので次は最短距離を求める問題を作成する。


DECLARE @FIELD_W int = 10;
DECLARE @FIELD_H int = 5;

DECLARE @ix int = 0
DECLARE @iy int = 0
DECLARE @h int = 5
SET @iy = 0

SELECT RAND(5)
TRUNCATE TABLE SAMPLE_E
TRUNCATE TABLE SAMPLE_N

WHILE @iy < @FIELD_H BEGIN
    SET @ix = 0
    WHILE @ix  0.6 AND @h < 9
                            THEN @h + 1
                        ELSE @h
                    END
            FROM
                (VALUES(RAND())) AS R(v);
        INSERT INTO SAMPLE_N(X,Y,h)
            SELECT
                IIF(@iy % 2 = 0,@ix,@FIELD_W - @ix -1),@iy,
                @h;
        SET @ix += 1
    END
    SET @iy += 1
END

UPDATE SAMPLE_N
    SET TT = 0
    WHERE
        X = 0 AND Y = 0;

SELECT
    Y
    , STRING_AGG(CAST(h AS NVARCHAR(1)),'') WITHIN GROUP (ORDER BY X) AS MAP
FROM
    SAMPLE_N
GROUP BY
    Y
ORDER BY Y

高さ @FIELD_H, 幅 @FIELD_W とする。 左上を (0,0) 、右下を (@FIELD_W – 1, @FIELD_H – 1)として 「SELECT RAND(5)」で乱数系列を初期化。(同じ MAP を繰り返し作成するため。シード値を変えれば別のマップを作れ、コメントアウトすれば作るたびに変わる。) 乱数で高さを上げ下げしつつ 1行目は左から右、2行目は右から左、・・・と高さを設定する。 CTE では 100までしか再帰できないので T-SQL の While でループを回した。 出発点の (0.0) には所要時間 0 を設定。 最後に できた MAP を表示する。 STRING_AGG は SQL Server 2017 から追加された関数で、他の Database で言うところの GROUP_CONCAT() である。 (なお、現時点(2017年7月17日) では STRING_AGG の書式ひな形は誤っているので注意が必要。) これでできる MAP は次のようになる。

Y	MAP
0	5567654343
1	6543223444
2	7899988789
3	5456567899
4	5455567787

さて、問題を解くにあたり、まず Edge を設定する。


TRUNCATE TABLE SAMPLE_E;

INSERT INTO SAMPLE_E
    SELECT
        NF.$node_id
        , NT.$node_id
        , CASE
                WHEN NF.H > NT.H THEN 3
                WHEN NF.H < NT.H THEN 7
                ELSE 4
            END AS W
    FROM
        SAMPLE_N NF
        , SAMPLE_N NT
    WHERE
        ABS(NF.H - NT.H) <= 1
        AND (
            (NF.X = NT.X AND ABS(NF.Y - NT.Y) = 1)
            OR (NF.Y = NT.Y AND ABS(NF.X - NT.X) = 1))

テーブルをクリア後、node テーブルを cross join し、

  • 高さの差が 1以下
  • (X が同じで Y の差が 1) または(Y が同じで X の差が 1)

の組み合わせに対して

  • 登りなら 7
  • 下りなら 3
  • それ以外は 4

の重みを設定して edgeテーブルに登録する。

で実際に解く。


DECLARE @UPDATED int =  1

WHILE @UPDATED > 0 BEGIN
    UPDATE NT
            SET NT.TT = NF.TT + E.W
        FROM
            SAMPLE_N NF
            , SAMPLE_E E
            , SAMPLE_N NT
        WHERE
            match (NF-(E)->NT)
            AND (NF.TT IS NOT NULL)
            AND ((NT.TT IS NULL)
                OR (NT.TT > NF.TT + E.W))
    SET @UPDATED = @@ROWCOUNT
    --SELECT @UPDATED
END

パワープレイ(爆)。
「edge の先の所要時間が設定されていないか、より短く成るなら所要時間を更新する」
というのを更新が無くなるまで繰り返す。
この「match」構文が graph database 専用らしい。
(7/18 当初 match構文を使い忘れていたので修正しました。)

で結果表示。


SELECT 
        TT
    FROM
        SAMPLE_N N
        INNER JOIN (
            SELECT MAX(X) X,MAX(Y) Y FROM SAMPLE_N) M
        ON M.X = N.X AND M.Y = N.Y

SELECT
        Y
        , STRING_AGG(CAST(h AS NVARCHAR(1)),'-') WITHIN GROUP (ORDER BY X) AS MAP
        , STRING_AGG(CAST(tt AS NVARCHAR(4)),'-') WITHIN GROUP (ORDER BY X) AS TravelTime
    FROM
        SAMPLE_N
    GROUP BY
        Y
    ORDER BY Y

この問題の場合は所要時間 64分、
MAP の各地点までの所要時間は次のとおり

Y MAP TravelTime
0 5-5-6-7-6-5-4-3-4-3 0-4-11-18-21-24-27-30-37-40
1 6-5-4-3-2-2-3-4-4-4 7-8-11-14-17-21-28-35-39-43
2 7-8-9-9-9-8-8-7-8-9 14-21-28-32-36-39-43-46-53-60
3 5-4-5-6-5-6-7-8-9-9 72-65-62-59-52-49-46-53-60-64
4 5-4-5-5-5-6-7-7-8-7 74-67-64-60-56-53-50-54-61-64

とりあえず、特別な機能はわからないがやってみたと。
方向性がアレなサンプルなのでこれ公開したら他の人がどんなサンプル作っているか見てみます。lt;

各テーブルのレコード数一覧(Microsoft SQL Server用)

なんかのセミナーで「テーブルの行を取得するのに COUNT(*) なんて使いません」と聞いた。
で、必要になったついでにググってみた。
sysindexes を参照する方法があったが、
さすがにそれはやめとこうと、sysindexes でググって sys.dm_db_partition_stats にたどり着いた。

そういうわけで

========================
SELECT S.name + '.' + T.name,row_count
FROM sys.dm_db_partition_stats D
	INNER JOIN sys.TABLES T
	ON D.object_id = T.object_id
	INNER JOIN sys.schemas S
	ON T.schema_id = S.schema_id
WHERE
	(index_id=0 or index_id=1)
ORDER BY
	T.name 
========================

よい子はこんなことしちゃだめだぞ!

.NET Framework でイベントログに書き込むとき、イベントソースの存在確認をしてはいけない

.NET Framework でイベントログに書き込むときは System.Diagnostics名前空間の System.Diagnostics.Eventlog クラスを用いる。

ここでよくあるサンプルは次のような感じになっている。

Sample 1

using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            const string EVENTSOURCE = "EventSource1";
            const string MESSAGE = "EventLogTest";

            if (!EventLog.SourceExists(EVENTSOURCE))
            {
                EventLog.CreateEventSource(EVENTSOURCE, null);
            }
            EventLog.WriteEntry(EVENTSOURCE, MESSAGE);

        }
    }
}

ところが、このサンプルにはよくない。

Sample 1 で登場する EventLog クラスのメソッドの動作の概要は次の通り。

SourceExists イベントソースが登録されているかを返す。管理者権限が無ければ例外エラーになる。
CreateEventSource イベントソースを登録する。既に対象のイベントソースが登録されているならば例外エラーになる。また、管理者権限が無ければ例外エラーになる。
WriteEntry イベントログに指定したイベントソースで書き込む。対象のイベントソースが登録されていない場合、管理者権限があれば新たにイベントソースを登録する。対象のイベントソースが登録されていない場合で管理者権限が無ければ例外エラーになる。

つまり、

Sample 1 は管理者権限が無ければ動作しない

のである。

特に、最新の Visual Studio は動かす際に管理者権限が無くても良くなっているが、一昔前の Visual Studio は動かす時に管理者権限が必要だったため、 Sample 1 のバグ(僕はこれはバグであると断じる)は

単体テストで OK で、結合テストで NG

となる可能性が高いものである。

前にいたプロジェクトで Sample 1のようなイベントソースの存在チェックをおこなっているバグがに遭遇したことがあったし、実際にググったら Sample 1 のようなものしか出てこない。(2016-9-12 現在)

正しくは次のようにする必要がある。

Sample 2

using System.Diagnostics;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            const string EVENTSOURCE = "EventSource1";
            const string MESSAGE = "EventLogTest";

            EventLog.WriteEntry(EVENTSOURCE, MESSAGE);
        }
    }
}

Sample 1 と Sample 2 の動作の違いは次のようになる。

 

管理者権限がある場合 管理者権限がない場合
イベントソースが登録済 イベントソースが未登録 イベントソースが登録済 イベントソースが未登録
Sample 1 イベントログに書き込まれる。 イベントソースを登録してイベントログに書き込まれる (管理者権限が無いことによる)例外エラー (管理者権限が無いことによる)例外エラー
Sample 2 イベントログに書き込まれる。 イベントソースを登録してイベントログに書き込まれる イベントログに書き込まれる。 (管理者権限が無いことによる)例外エラー

したがって、.NET Framework でイベントログに書き込むプログラムを作る場合、次の点に注意する。

  • イベントソースの存在チェックを行ってはいけない。
  • イベントソースは構築時に別プログラムや PowerShell  Script を管理者権限のある状態で動かして登録する、管理者権限がある状態で動かすインストーラに組み込むなどして事前に登録しておくようにする。

逆上がり不能心因主因説

初めに

逆上がりができない人がいる。あるいはできるようになるのに時間がかかる場合がある。

理由は唯一ではないと思われるがここではその原因の中で主たるものは恐怖心によるものだとの理論を展開する。

尚、この文章は所謂ポエムである。
(きちんとした裏付けが無い、個人の思いつきだけで書きなぐった無意味なもの、
場合によっては誤りを含んでいるにもかかわらず、
あたかも意義がある説明のように(作者がそう思って)記述していある文書を揶揄して「ポエム」という。)

逆上がりができない原因

逆上がりができない原因は唯一ではないと思われるし、必ずしも全員ができるとは限らないと言える。例えば手が無いと無理だし足が無い場合もし回ることができてもそれを逆上がりと呼称していいかの議論が必要である。

ただし、以下の条件を満たすなら身体的に逆上がりができない可能性は極めて低いと思われる。

  • 前回りができる。
  • 懸垂が2回以上できる。
  • ジャンプで飛び上がることができる。

そして、上記の条件を満たすにもかかわらず逆上がりができない場合は心理的要因、具体的には恐怖心によるものだと推定する。

恐怖心により逆上がりができない場合の挙動

恐怖心により逆上がりができない人が逆上がりをした場合にどのような動作になるかは次の手法で逆上がりができる人でも再現できる。

  • 確実に頭をぶつける低さの鉄棒で逆上がりをする(ふりをする)

全く動かないのでなければ通常、次のようになるはずである。
逆上がり失敗
つまり、手が伸びて足が前にすすみ蹴り上げないでぶら下がる状態である。
そして、その時の”感じ”、頭を打つことへの恐怖が逆上がりできない人が(消して頭をぶつけることはないにもかかわらず)感じる感覚である。
なお、もしかしたら頭をぶつける低さの鉄棒で本当に逆上がりをしようとして頭をぶつける場合もあるかもしれませんが、その場合はそのまま頭を打って死んでください。
その馬鹿さ加減による危険性は周りの人間にまで巻き込みひいては国を危うくしかねません。

理をもって恐怖心を克服する

では恐怖心により逆上がりができない場合にできるようになる・できるようにするにはどうすればいいか。
それは理をもって恐怖心を克服するするのである。
そのために

  1. 逆上がりを怖がっていることを自覚する・させる。
  2. 安全に逆上がりをする方法をきちんと説明して認識させる。
  3. 安全な方法に基づいていれば絶対に頭を打つことはないことを説明して認識させる。

のである。

逆上がりを怖がっていることを自覚する・させる

まず、逆上がりを怖がっていることをはっきりと自覚する・させることである。
ここ地点に立たないと逆上がり安全性の説明をしてもなぜその説明をしているかが理解できないはずである。
また、後述するが逆上がりが怖いことの自覚が実は逆上がりに意義を持たせることにつながる。

実際には本人がこの解答にたどり着いても周りが否定して潰してしまうケースが多いが
教える側も逆上がりを怖がっていることを理解し解決することを考えないと
言葉の暴力や虐待といえるような指導をすることになる。
逆上がりの怖さを確認する方法はすでに述べた。

安全に逆上がりをする方法

安全に逆上がりをする方法は次のとおりである。

  • 頭をぶつけない高さの鉄棒で試みる
  • 絶対に手を離さない

いろいろ考えるとこれだけでは無いのだが、基本的にはこれである。

頭をぶつけない高さの鉄棒で試みるというのは前回りをさせてみて高さ的には安全であることを改めて認識させることを含む。
そして恐怖心を和らげるためには一段階高い鉄棒で試みることを勧めてもよい。
実際、逆上がりができる人でも安全な高さにもかかわらず低いと怖いからできないという人はいる。

絶対に手を離さないというのもそのための配慮も含む。
配慮としては

  • 順手にする
  • 手に砂を付けない
  • 疲れたらやめる

である。手に砂を付けないは体操選手が滑り止めをつけるのをまねて砂をつける人がいるが小石等が付着して手と鉄棒の間に入って事故になる可能性があるので禁止する。

そして

  • しっかり握る

ようにする。実は本当に力を入れてしっかり握った場合、
逆上がり失敗
のようにはならないはずである。
もしこのように手が伸びるのなら安全性を理由としてもっとしっかり握るように諭すのがいい。しっかり握ろうとすれば自ずと二の腕に力が入り、伸ばせなくなる。

安全な方法に基づいていれば絶対に頭を打つことはないことを説明して認識させる

頭を打たない高さで手を離さないならば絶対に頭を打たないことの説明としては

  • (ルフィーや奇妙な物語のように)人間の手が伸びることはない
  • 手が引きちぎれることはない

後半の説明としてはヨーロッパで国王に対する殺人等に適用される「八つ裂きの刑」について調べてそれが如何に難事であるかを調べればよい。

逆上がりをやってみる

逆上がりで頭を打つことはないことをきちんと理解できていればあとは思い切ってするだけである。
思いっきりできる心理状態にするために

  • 手を離さなければ大丈夫

とつぶやきながらすることを勧める。

改めて、安全性の観点から

  • 疲れるまでしない。10回やってできなかったら心理状態を整えるために翌日にする
  • いわゆる逆上がりの補助具は思いっきりすることを阻害する上に余計な事故の元なので撤去する

この心因主因説では大人になれば自ずとできるようになると考えるので
できないならそれでも良く、焦ってできるようになる必要はないと考える。

周辺の考察

以下では逆上がり不能心因主因説を是としてさらに暴走する。

逆上がり(教育)不要論について

「逆上がりは後の役に立たないから不要である」みたいな話は昔からあり、
最近では逆上がりがやっと出来るようになった後に何の役に立つのか問い質す話が話題になった。

おそらく、逆上がりが具体的にが何かの役に立つということは考えられないが、
先に役に立たないことは他にもあり、
役に立たないだけで不要とするのは短絡的、或いは本当に問題にするべきことに対して言葉が足りないと言える。

また、多くの人は苦無く逆上がりができるらしいことからできないことが個人的にマイナスを抱えてしまうことになりえる。特に周りが明示的・暗黙にかかわらず攻撃した場合。

逆上がりが出来ないことに対する教育の問題は心因主因説を合わせて考察すると以下の点である。

  1. 逆上がりの怖さを理解しない指導・特訓は逆上がりができるようになることに対してほとんど役にたたない。
  2. 心の持ち方でいきなりできるようになりえるため、「努力の末に達成する」ことの教育には向かない。むしろ悪影響を及ぼす。

1. はできない原因を理解しないで逆上がりの練習を強いることは虐待・嫌がらせであるということである。指導相手のためという善意をもってしていてるならばなおさら悪質である。
そして最終的に逆上がりができなかった場合、心に傷をうけることになる。
2. の問題は逆上がりができるようになった場合に大きな問題を残しえる。
本人がそれまでの練習は無意味だったと理解する場合もある。また、
実は簡単にできるゆえに(単純にそれだけでは)価値が無いことだと理解する場合もある。
例の「逆上がりがなんの役に立つのか」という質問はこういったことに気付いた故に投げかけたと考えられる。

逆上がりができるようになることの価値

先にのべたように、絶対的な意味では逆上がりができること・できるようになることの価値はあまりないとも言える。
しかし、心因主因説から見た場合、逆上がりができるようになることは恐怖心を克服したたという心の成長とみなせる。
そして予め逆上がりを怖がっているという自覚を持ったうえで逆上がりができるようになったのなら
恐怖心を克服した、大げさに言うならば勇気を発したということで個人的なものにとどまるものの本人に価値を残すことができると考える。

なお、この心因主因説では、子供のころ逆上がりができなくても
ここに書いてあることが理解でき、前提条件をみたす大人がいま挑戦すればおそらく逆上がりはできるだろうと考える。。
これは絶対的にはどうでもいいことだが個人的にはマイナスになっていることが 0 になることで意義があるとも考える。

腕力不足による逆上がり不能説の否定

逆上がりの指導法を書いたページ等を見ていると

逆上がり失敗

みたいになる場合に「腕力不足で手を伸ばしてしまう」といった記述をみかけることがあるが、
それはまずありえない。
目の前の理解できない事象に対して安易にその記述者が納得しうる理由をむりやりつけたにすぎず、
そういったページの指導法は信用するべきではない。

万が一、本当に腕力不足だった場合、安全性の観点から逆上がりの練習をさせることは危険であり、また前回りも危険である。
そして一般生活で支障が出るレベルでもあるため腕力を付ける訓練を優先してするべきである。

なお、この心因主因説の前提で「懸垂二回」とは書いたが、これはかなり安全側にマージンを取ったもので
実際には懸垂ができなくても逆上がりをできるだけの筋力はある場合がほとんどであるとはおもう。

逆上がり練習用具の不要論

逆上がりの練習用具はいくつかあるが本当に効果があるかきちんと検討するべきである。
例えば説明を読んでいると「逆さになるのに慣れさせる」とか書いてあり
心因主因説で挙げた問題を間接的に体でなれさせることで解決しようとしている道具がある。
そういう道具を用いる指導者程度に知性が低い相手ならば効果が出てくる可能性があるかもしれないが、
きちんと頭があり言葉が通じる相手ならば理をもって諭す方が効率的で効果が高い。
また道具を用いたときの動きは実際の逆上がりの動作、
特に地面を蹴り上げるという点で大きく異なるのでその面でも不適切である。
さらに、鉄棒に関連する事故を調べた場合、鉄棒自体より逆上がりのための補助具にまつわる事故の方が多い資料もあり、
安全面から逆上がり練習用具は排除するべきと考える。

最後に

僕が初めて逆上がりができたとき

僕は小学校では逆上がりはできなかった。
別段それで居残り練習をさせられたとかの記憶はないが。
中高では逆上がりを試した記憶はない。

大学一年生のとき、同級生で車で遠出したとき、
高速道路のサービスエリアにあった自分の身長より高い鉄棒で
なんとなく逆上がりをやってみたらできた。
そのときブレザを着ていて、ポケットからいろんなものを落としながらやった。
そのとき考えていたことは

「手を離さなければ大丈夫」

だった。

参考文献(?)

正確な文言は忘れたが、「恐怖は感じないことはできないが、抑え込むことはできる」といった類の記述が「ロードス島戦記」(水野良) にあった。

エイプリルフールに嘘をつく必要はない

一応 2015年4月1日のエイプリルフールネタ。
嘘というわけではなく、バカなことを本気でやってみたものである。

 

Brainfuck Code Generator改

前のよりはちょっと短いコードを生成するようにはなったが、まだ改良の余地あり。


--DECLARE @STR VARCHAR(100) = 'SELECT ''I''''m cursed!'';'
DECLARE @STR VARCHAR(100) = 'hoge'
SELECT
n
, c
, a
, l
, CASE
WHEN a ' + REPLACE(SPACE(a),' ','+') + '.'
ELSE
REPLACE(SPACE(ABS(l)),' ',IIF(SIGN(l)<0,'+','-')) + '.'
END
FROM
(
SELECT
n
, c
, ASCII(c) a
, LAG(ASCII(c),1,0) OVER (ORDER BY n) - ASCII(c) AS l
FROM
(
SELECT
ROW_NUMBER() OVER(ORDER BY N1.n) AS n
, SUBSTRING(s,ROW_NUMBER() OVER(ORDER BY N1.n),1) AS c
, LEN(s) AS l
FROM
(VALUES(@STR) ) S(s)
, (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) N1(n)
, (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) N2(n)
) C
WHERE
n <= LEN(@STR)) cl

Brainfuck Code Generator

SQL SERVER でASCII 文字列を出力する Brainfuck のコードを生成するSQL
2008以降で動作する見込み。
2014で確認。
=============================================================
DECLARE @STR VARCHAR(100) = 'MOJIRETU SYUTURYOKU'
SELECT
n
, c
, ASCII(c)
, '>' + REPLACE(SPACE(ASCII(c)),' ','+') + '.'
FROM
(
SELECT
ROW_NUMBER() OVER(ORDER BY N1.n) AS n
, SUBSTRING(s,ROW_NUMBER() OVER(ORDER BY N1.n),1) AS c
, LEN(s) AS l
FROM
(VALUES(@STR) ) S(s)
, (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) N1(n)
, (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) N2(n)
) C
WHERE
n <= LEN(@STR)

======================================================================

「SQL Server 2014 CTP2 を試してみる (3)ストアドプロシージャの Native Compile」のサンプルコード

「SQL Server 2014 CTP2 を試してみる (3)ストアドプロシージャの Native Compile」のサンプルコード

CREATE TABLE NumListM(
       num integer NOT NULL PRIMARY KEY NONCLUSTERED
       HASH WITH (BUCKET_COUNT=10))
    WITH ( MEMORY_OPTIMIZED = ON , DURABILITY = SCHEMA_AND_DATA );

INSERT INTO NumListM(num) VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

CREATE TABLE dbo.CharListM(
        c char(1) COLLATE Latin1_General_100_BIN2 NOT NULL
        PRIMARY KEY
        NONCLUSTERED
        HASH WITH ( BUCKET_COUNT = 10))
    WITH ( MEMORY_OPTIMIZED = ON , DURABILITY = SCHEMA_AND_DATA );

INSERT INTO CharListM(c) VALUES('A'),('C'),('D'),('H'),('I'),('L'),('M'),('N'),('O'),('W');

SELECT
    (100 * M.num + 10 * A.num + N.num) AS MAN,
    '+' AS [PLUS],
    (10000 * W.num + 1000 * O.num + 100 * M.num + 10 * A.num + N.num) AS WOMAN,
    '=' AS [EQUAL],
    (10000 * C.num + 1000 * H.num + 100 * I.num + 10 * L.num + D.num) AS CHILD
FROM
    NumList AS A,
    NumList AS C,
    NumList AS D,
    NumList AS H,
    NumList AS I,
    NumList AS L,
    NumList AS M,
    NumList AS N,
    NumList AS O,
    NumList AS W
WHERE
    ((100 * M.num + 10 * A.num + N.num)
    + (10000 * W.num + 1000 * O.num + 100 * M.num + 10 * A.num + N.num)
    = (10000 * C.num + 1000 * H.num + 100 * I.num + 10 * L.num + D.num))
    AND (M.num>=1) AND (W.num >= 1) AND (C.num>=1)
    AND (O.num  W.num)
    AND (M.num  W.num)
    AND (A.num  W.num)
    AND (N.num  W.num)
    AND (C.num  W.num)
    AND (H.num  W.num)
    AND (I.num  W.num)
    AND (L.num  W.num)
    AND (D.num  W.num)
    AND (M.num  O.num)
    AND (A.num  O.num)
    AND (N.num  O.num)
    AND (C.num  O.num)
    AND (H.num  O.num)
    AND (I.num  O.num)
    AND (L.num  O.num)
    AND (D.num  O.num)
    AND (A.num  M.num)
    AND (C.num  M.num)
    AND (H.num  M.num)
    AND (I.num  M.num)
    AND (L.num  M.num)
    AND (D.num  M.num)
    AND (M.num  N.num)
    AND (A.num  N.num)
    AND (C.num  N.num)
    AND (H.num  N.num)
    AND (I.num  N.num)
    AND (L.num  N.num)
    AND (D.num  N.num)
    AND (A.num  C.num)
    AND (A.num  H.num)
    AND (C.num  H.num)
    AND (D.num  H.num)
    AND (A.num  I.num)
    AND (C.num  I.num)
    AND (H.num  I.num)
    AND (D.num  I.num)
    AND (A.num  L.num)
    AND (C.num  L.num)
    AND (H.num  L.num)
    AND (I.num  L.num)
    AND (D.num  L.num)
    AND (A.num  D.num)
    AND (C.num  D.num);

create procedure dbo.SoloveMask
with native_compilation, schemabinding, execute as owner
AS
BEGIN ATOMIC
with (transaction isolation level=snapshot, language=N'us_english')
    SELECT
        (100 * M.num + 10 * A.num + N.num) AS MAN,
        '+' AS [PLUS],
        (10000 * W.num + 1000 * O.num + 100 * M.num + 10 * A.num + N.num) AS WOMAN,
        '=' AS [EQUAL],
        (10000 * C.num + 1000 * H.num + 100 * I.num + 10 * L.num + D.num) AS CHILD
    FROM
        dbo.NumListM AS A,
        dbo.NumListM AS C,
        dbo.NumListM AS D,
        dbo.NumListM AS H,
        dbo.NumListM AS I,
        dbo.NumListM AS L,
        dbo.NumListM AS M,
        dbo.NumListM AS N,
        dbo.NumListM AS O,
        dbo.NumListM AS W
    WHERE
        ((100 * M.num + 10 * A.num + N.num)
        + (10000 * W.num + 1000 * O.num + 100 * M.num + 10 * A.num + N.num)
        = (10000 * C.num + 1000 * H.num + 100 * I.num + 10 * L.num + D.num))
        AND (M.num>=1) AND (W.num >= 1) AND (C.num>=1)
        AND (O.num  W.num)
        AND (M.num  W.num)
        AND (A.num  W.num)
        AND (N.num  W.num)
        AND (C.num  W.num)
        AND (H.num  W.num)
        AND (I.num  W.num)
        AND (L.num  W.num)
        AND (D.num  W.num)
        AND (M.num  O.num)
        AND (A.num  O.num)
        AND (N.num  O.num)
        AND (C.num  O.num)
        AND (H.num  O.num)
        AND (I.num  O.num)
        AND (L.num  O.num)
        AND (D.num  O.num)
        AND (A.num  M.num)
        AND (C.num  M.num)
        AND (H.num  M.num)
        AND (I.num  M.num)
        AND (L.num  M.num)
        AND (D.num  M.num)
        AND (M.num  N.num)
        AND (A.num  N.num)
        AND (C.num  N.num)
        AND (H.num  N.num)
        AND (I.num  N.num)
        AND (L.num  N.num)
        AND (D.num  N.num)
        AND (A.num  C.num)
        AND (A.num  H.num)
        AND (C.num  H.num)
        AND (D.num  H.num)
        AND (A.num  I.num)
        AND (C.num  I.num)
        AND (H.num  I.num)
        AND (D.num  I.num)
        AND (A.num  L.num)
        AND (C.num  L.num)
        AND (H.num  L.num)
        AND (I.num  L.num)
        AND (D.num  L.num)
        AND (A.num  D.num)
        AND (C.num  D.num);
END;

exec SoloveMask;

SQL Server でパスカルの三角形(Pascal’s Triangle)(その4)

いやさぁ、転置するくらいなら初めから横に並べていればいいやん。
・・・って感じで再帰CTE 使った本命の解答。


WITH t(level,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21)
AS(
SELECT
	0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
UNION ALL
SELECT
	level + 1
	, f1
	, f1 + f2
	, f2 + f3
	, f3 + f4
	, f4 + f5
	, f5 + f6
	, f6 + f7
	, f7 + f8
	, f8 + f9
	, f9 + f10
	, f10 + f11
	, f11 + f12
	, f12 + f13
	, f13 + f14
	, f14 + f15
	, f15 + f16
	, f16 + f17
	, f17 + f18
	, f18 + f19
	, f19 + f20
	, f20 + f21
	FROM
		t
	WHERE
		level < 20

)
SELECT
	*
	FROM
		t


いや、最初にこれを思いつけよ。

SQL Server でパスカルの三角形(Pascal’s Triangle)(その3)

全パスの分布を数えてみた。
SQL らしい方法で(そうか?)。
(SQL Server 2012 Express Edition)
Intel Core i3 U380 1.33GHz で2分弱~3分強かかった。


SELECT
	*
	FROM
		(
SELECT
	level,value_sum as position ,COUNT(*) / Power(2,20-level) as Value
FROM
(
SELECT
		a.level
		, (
				CASE WHEN t1.level <= a.level THEN t1.value ELSE 0 END
				+ CASE WHEN t2.level <= a.level THEN t2.value ELSE 0 END
				+ CASE WHEN t3.level <= a.level THEN t3.value ELSE 0 END
				+ CASE WHEN t4.level <= a.level THEN t4.value ELSE 0 END
				+ CASE WHEN t5.level <= a.level THEN t5.value ELSE 0 END
				+ CASE WHEN t6.level <= a.level THEN t6.value ELSE 0 END
				+ CASE WHEN t7.level <= a.level THEN t7.value ELSE 0 END
				+ CASE WHEN t8.level <= a.level THEN t8.value ELSE 0 END
				+ CASE WHEN t9.level <= a.level THEN t9.value ELSE 0 END
				+ CASE WHEN t10.level <= a.level THEN t10.value ELSE 0 END
				+ CASE WHEN t11.level <= a.level THEN t11.value ELSE 0 END
				+ CASE WHEN t12.level <= a.level THEN t12.value ELSE 0 END
				+ CASE WHEN t13.level <= a.level THEN t13.value ELSE 0 END
				+ CASE WHEN t14.level <= a.level THEN t14.value ELSE 0 END
				+ CASE WHEN t15.level <= a.level THEN t15.value ELSE 0 END
				+ CASE WHEN t16.level <= a.level THEN t16.value ELSE 0 END
				+ CASE WHEN t17.level <= a.level THEN t17.value ELSE 0 END
				+ CASE WHEN t18.level <= a.level THEN t18.value ELSE 0 END
				+ CASE WHEN t19.level <= a.level THEN t19.value ELSE 0 END
				+ CASE WHEN t20.level <= a.level THEN t20.value ELSE 0 END
			) AS value_sum
	FROM
		(VALUES(1,0),(1,1)) AS t1(level,value)
		,(VALUES(2,0),(2,1)) AS t2(level,value)
		,(VALUES(3,0),(3,1)) AS t3(level,value)
		,(VALUES(4,0),(4,1)) AS t4(level,value)
		,(VALUES(5,0),(5,1)) AS t5(level,value)
		,(VALUES(6,0),(6,1)) AS t6(level,value)
		,(VALUES(7,0),(7,1)) AS t7(level,value)
		,(VALUES(8,0),(8,1)) AS t8(level,value)
		,(VALUES(9,0),(9,1)) AS t9(level,value)
		,(VALUES(10,0),(10,1)) AS t10(level,value)
		,(VALUES(11,0),(11,1)) AS t11(level,value)
		,(VALUES(12,0),(12,1)) AS t12(level,value)
		,(VALUES(13,0),(13,1)) AS t13(level,value)
		,(VALUES(14,0),(14,1)) AS t14(level,value)
		,(VALUES(15,0),(15,1)) AS t15(level,value)
		,(VALUES(16,0),(16,1)) AS t16(level,value)
		,(VALUES(17,0),(17,1)) AS t17(level,value)
		,(VALUES(18,0),(18,1)) AS t18(level,value)
		,(VALUES(19,0),(19,1)) AS t19(level,value)
		,(VALUES(20,0),(20,1)) AS t20(level,value)
		,(VALUES (1)
				,(2)
				,(3)
				,(4)
				,(5)
				,(6)
				,(7)
				,(8)
				,(9)
				,(10)
				,(11)
				,(12)
				,(13)
				,(14)
				,(15)
				,(16)
				,(17)
				,(18)
				,(19)
				,(20)) AS a(level)
) AS Try_Sum
GROUP BY
	level,value_sum
	) X
	PIVOT(
		MAX(value)
		FOR position IN (
			[0]
			,[1]
			,[2]
			,[3]
			,[4]
			,[5]
			,[6]
			,[7]
			,[8]
			,[9]
			,[10]
			,[11]
			,[12]
			,[13]
			,[14]
			,[15]
			,[16]
			,[17]
			,[18]
			,[19]
			,[20]) ) AS P
ORDER BY
	level