covid-19:第4波を予想してみた2

covid-19:第4波を予想してみた - a-sanの日記
の続きです。

2021/05/02までのデータで計算すると以下のようになりました。
f:id:a-san:20210503214006p:plain

今までの計算結果をまとめると以下のようになりました。

yyyy/mm/ddまでのデータ ピーク予想 ピーク時の感染者数 第4波の全感染者数
2021/04/24 2022/11/04 146192612 45387305413
2021/04/25 2021/08/25 36835 5733218
2021/04/26 2021/05/20 6276 560070
2021/04/27 2021/05/19 6120 537854
2021/04/28 2021/05/27 7070 676965
2021/04/29 計算忘れ
2021/04/30 2021/05/22 6533 595528
2021/05/01 2021/05/28 7147 688479
2021/05/02 2021/05/30 7415 729602

さて、先頭の2021/04/24のデータはピークが2022/11になっていますし、感染者数が1億4000万人なので日本の人口より多いです。
つまり、精度が悪すぎて信用できません。
しかし、2日後ぐらいから妥当っぽい値になり、振れ幅も少なくなってきています。

さて、どの程度当たるでしょうか?
ハズれたらごめんなさい。

covid-19:第4波を予想してみた

第4波を最小二乗法で近似してピークを予想してみました。

f:id:a-san:20210501093813p:plain


波形は正規分布に従うと仮定。
データは以下のサイトの「国内の感染者数」を使用。https://www3.nhk.or.jp/news/special/coronavirus/
第4波の開始位置は、第3波と第4波の間の最小の日(2021/03/08)からとする。


ここ一週間ほど計算してみましたが、まだ波形は安定しません。
毎日計算していますが、計算のたびに数日ぐらいピークがずれます。

 

C言語でカレンダー表示

昔似たモノを作ったはずなのに見つかりません。

なので作りなおしました。

f:id:a-san:20210320204225p:plain

引数なしで今月のカレンダー、年月を指定すればその月のカレンダーを表示します。


まずは、Zellerの公式が必要。年月日から曜日を求めるやつ。

それと、閏年かどうかを判定する関数。

当時は2000年より前だったから、2000年に正しく動くかどうか何度もテストしました。

今は各種ライブラリが用意されているけれど、昔はみんな手作りしていました。

VisualStudioで開発したのだけれど、localtimeで警告されるので、#pragmaで無効にしてます。

 

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#pragma warning(disable: 4996)    // 'localtime': This function or variable may be unsafe. Consider using localtime_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

// ツェラーの公式
// 1:月 2:火 3:水 4:木 5:金 6:土 7:日
int getZeller(int yyyy, int mm, int dd)
{
    int c, y, gamma, d;
    if (mm <= 2) {
        yyyy -= 1;
        mm += 12;
    }
    c = yyyy / 100;
    y = yyyy % 100;
    gamma = 5 * c + (c / 4);
    d = (dd + (26 * (mm + 1) / 10) + y + y / 4 + gamma + 5) % 7 + 1;
    return d;
}

// 閏年か?
// 1:閏年     0:閏年ではない
int isLeapYear(int yyyy)
{
    return yyyy % 4 == 0 && yyyy % 100 != 0 || yyyy % 400 == 0;
}

// 指定した年月の日数を返す
// ex. (2000, 2) => 29
int getDays(int yyyy, int mm)
{
    switch (mm) {
        case 2:
            return isLeapYear(yyyy) ? 29 : 28;
        case 4: 
        case 6:
        case 9:
        case 11:
            return 30;
        default:
            return 31;
    }
}

void dispCalendar(int yyyy, int mm)
{
    int dd, days, youbi, i;

    printf(" *** %4d%2d月 ***\n", yyyy, mm);
    printf("日 月 火 水 木 金 土\n");
    days = getDays(yyyy, mm);
    youbi = getZeller(yyyy, mm, 1);
    if (youbi != 7) {
        for (i = 0; i < youbi; i++) {
            printf("   ");
        }
    }
    for (dd = 1; dd <= days; dd++) {
        printf("%2d ", dd);
        if ((dd + youbi) % 7 == 0) printf("\n");
    }
}

int main(int argc, char* argv[])
{
    int yyyy, mm;

    fprintf(stderr, "calen version 0.0\n");
    fprintf(stderr, "Copyright (C) Yoshinori Watanabe 2021. All Rights Reserved.\n");
    fprintf(stderr, "\n");
    
    if (argc == 3) {
        // 引数より年月を取得
        yyyy = atoi(argv[1]);
        mm = atoi(argv[2]);
    }
    else if (argc == 1) {
        // 現在日時より年月を取得
        time_t timer;
        struct tm* local;

        timer = time(NULL);
        local = localtime(&timer);
        yyyy = local->tm_year + 1900;
        mm = local->tm_mon + 1;
    }
    else {
        // 使い方を説明
        printf("usage: calen <yyyy> <mm>\n");
        return 1;
    }

    dispCalendar(yyyy, mm);

    return 0;
}

Javaでタプル

お仕事でJavaの開発をしているのだけれど、どうしても複数の値を返す必要がいくつかありました。
それ専用のクラスをその都度作るのもイマイチだし、
Object[]で返すのもダサい。
Scalaならタプルが使えるのに・・・。


なので、Javaでタプルを作ってみました。

/** 2つの要素を持つImmutableなタプル */
public class Tuple2<T1, T2> {
    public final T1 _1;
    public final T2 _2;
    public Tuple2(T1 _1, T2 _2) {
        this._1 = _1;
        this._2 = _2;
    }
}


使い方です。

    /** intとStringを返すメソッド. */
    Tuple2<Integer, String> getIntStr() {
        // ...
        return new Tuple2<Integer, String>(5, "ほげ");
    }


    void foo() {
        Tuple2<Integer, String> ret = getIntStr();
        int n = ret._1;
        String s = ret._2;
    }

フィボナッチ数列の拡張

スゴイことを発見してしまった!
フィボナッチ数列を負の方に拡張したら、
符号が交互に変わるフィボナッチ数列だった!

..., -21, 13, -8, 5, -3, 2, -1, 1, 0, 1, 1, 2, 3, 5, 8...

隣り合う2項を引き算して求めてます。




まぁ、絶対誰かが先にやってるだろうなぁ〜。

面白そうな問題を見つけたのでScalaで解いてみました。
問題はコチラ
http://nabetani.sakura.ne.jp/hena/ord13updowndouble/

/**
 * 増やす減らす二倍する 〜 横へな 2013.9.6 参考問題
 * @see     http://nabetani.sakura.ne.jp/hena/ord13updowndouble/
 */
import scala.collection.mutable.ListBuffer

object Ord13updowndouble {
    type 手 = Char  // '+'/'-'/'*'
    case class 状態(val 数:Int = 0, val 手順:List[手] = Nil) {
        override def toString = 数 + " 手数=" + 手順.length + " 手順=" + {
            手順.reverse.map{ _ match {
                case '+' => "+1"
                case '-' => "-1"
                case '*' => "*2"
                }
            }.mkString("[", " ", "]")
        }
    }

    /** 引数のそれぞれの状態に対して、次の状態を作成する。 */
    def createNextStatus(stats: List[状態]): List[状態] = {
        val result = new ListBuffer[状態]
        for (s <- stats) {
            if (s.数 != 0) {
                result += new 状態(s.数 - 1, '-' :: s.手順)
            }
            result += new 状態(s.数 + 1, '+' :: s.手順)
            result += new 状態(s.数 * 2, '*' :: s.手順)
        }
        result.toList
    }

    /** 解く。同じ手数で複数の解があれば、すべて返す。 */
    def solv(数:Int):List[状態] = {
        var list = List(new 状態())
        while (true) {
            // 解けた状態を探す。
            val solved = list.filter{s => s.数 == 数}
            if (solved.length != 0) return solved
            list = createNextStatus(list)
        }
        Nil
    }

    def main(args:Array[String]) {
        val solved = solv(59)
        solved foreach println
    }
}

結果

59 手数=9 手順=[+1 +1 *2 *2 *2 -1 *2 *2 -1]
59 手数=9 手順=[+1 *2 *2 *2 *2 -1 *2 *2 -1]

[scala]scala.swing.SplitPaneのバグ

コンストラクタで分割の方向を指定できるのだけれど、VerticalとHorizontalが逆になります。

import scala.swing._

object SplitTest extends SimpleSwingApplication {
  def top = new MainFrame {
    title = "Scala SplitTest"
    contents = new SplitPane(Orientation.Horizontal,
      new Label("Left"),
      new Label("Right"))
  }
}
/*
fsc SplitTest.scala
scala SplitTest
*/

理由は、javax.swing.JSplitPane.HORIZONTAL_SPLIT(値は1) 、またはjavax.swing.JSplitPane.VERTICAL_SPLIT(値は0)を渡してやらなければいけないのだけれど、javax.swing.SwingConstants.HORIZONTAL(値は0)、またはjavax.swing.SwingConstants.VERTICAL(値は1)を渡しています。
ちょうど値が逆になっているのです。

scala/SplitPane.scala at v2.10.3 · scala/scala · GitHub
JSplitPane (Java Platform SE 6)
実は2010年10月ぐらい前から気がついているのだけれど、いまだに直らない。ScalaのSwingって使われてないのかな?