bouzuya.hatenablog.com

ぼうずやのにっき

genuuid 0.4.2 をつくった

genuuid 0.4.2 をつくった。 bouzuya/rust-sandbox の genuuid に置いてある。

  • Docker イメージに scratch を使用するよう変更した
  • crate のバージョンアップや置き換え
    • structopt 0.3.25 → clap 4.0.32 + clap_complete 4.0.7
    • axum 0.3.0 → 0.6.1
    • etc.
  • GitHub Actions の workflow をアップデート

外からの使用感は変わらない。 Docker イメージのサイズ削減 (86MB→7MB) の件は明日書くので割愛。

crates:structopt から crates:clap (--features derive) に置き換えた。 derive の名前を直していくくらいかなと思ったのだけど、シェルの補完スクリプトを表示するための clap::Shell が v2 → v3 で crates:clap_complete に分離されていたことの影響があった。

https://github.com/clap-rs/clap/blob/v3-master/CHANGELOG.md#breaking-changes

Completion generation has been split out into clap_complete.

↓のコミットで雑に直している。たぶん直せている。

https://github.com/bouzuya/rust-sandbox/commit/fe7bbdc1291fb33f45d88a06f770869b70096fbe

crates:structoptCLI の作成でわりと使っており、上記のシェルの補完スクリプトの表示機能も何度かつくっている。今後も同様に置き換えをする場合に似たような修正が発生するはずなので、ここにメモしておく。


『詳解 Rust プログラミング』 (『 Rust in Action 』の翻訳版) の 1 章を読んだ。


今日のコミット。

2023-W01 ふりかえり

2023-W01 をふりかえる。

2023-W01 の目標 とその記事

目標。

記事。

つくったもの

よんだもの

みたもの

(なし)

その他

勉強会。

(なし)

おでかけ。

(なし)

ゲーム。

  • フィットボクシング 2 31 + 1 + 111 + 42 日目 (2 + 2 + 2 日抜け)
  • Stacklands 3 周目の途中

買い物。

(なし)

体調。

育児。

  • 上の子はココアがお気に入りだ
  • 上の子はときどき「だれもあそんでくれなかった」と教えてくれる
  • 下の子はフィットボクシング中にあしにしがみついてくる

2023-W01 はどうだったか。

保育所の送迎の関係で勤務時間を変更している。せわしい。

ふりかえりをしている。自身の成果物 (GitHub リポジトリやアプリケーションなど) を見て、「パッとしないな、ダメだな……」ってなっている。趣味なので楽しくやりたい。同時にできれば第三者が見たとき何かしら良い評価をされるものにしたい。

date-to-week-date 0.1.1 をつくった (2023-01-07) 。 calendar date を week date に変換する。例えば https://bouzuya.net/lab/date-to-week-date/?date=2023-01-03 。小さいものでも出していきたい。

AtCoder は ABC284 に参加した (2023-01-07) 。 1238 → 1201 (-37) (https://atcoder.jp/users/bouzuya/history/share/abc284) 。茶パフォで緑に落ちかけた。また ABC の過去問題を解いている。

ラジオ体操・懸垂・フィットボクシング 2 を続けている。のどが痛い。不安だ。

Steam Deck の L1 が壊れている (2022-12-29) 件が一向に進んでいない。心配だ。話が進んだとしても、再送などにすごい時間がかかりそうだ。『 Stacklands 』をまたプレイしている。あとすこしでクリアだと思う。

2023-W02 の目標

  • Yew を使った Web アプリケーションを何か公開する
  • bouzuya.net に genuuid / date-to-week-date を追記する
  • 『詳解 Rust プログラミング』を読みはじめる

date-to-week-date 0.1.1 をつくった

2023-01-022023-01-03 で date-to-week-date 0.1.0 と 0.1.1 をつくった。

date-to-week-date は (calendar) date を入力すると week-date を返す Web アプリケーション。

$ curl -s 'https://bouzuya.net/lab/date-to-week-date/?date=2023-01-03'
2023-W01-2

以前から似たような CLI をいくつかつくっている気がするけど、小さい Web アプリケーションをつくり慣れるために Web アプリケーション化した。こういうのインストール不要で意外と便利な気がしてきている。 Docker あるならインストール不要じゃ……と言われればそうだろうし、インストール困難な環境ってあんまりないよねと言われればそうだろうけど……。


ABC284 に参加した。茶パフォ。 1200 でなんとか水色維持したけど DFS するだけの問題が解けなくて死。


crates:strum に Pull Request した。 https://github.com/Peternator7/strum/pull/250


今日のコミット。

Impulse Blocker という Firefox アドオンをインストールした

Impulse Blocker という Firefox アドオンをインストールした。バージョンは 1.2.0 。

配布ページ: https://addons.mozilla.org/ja/firefox/addon/impulse-blocker/ ソースコード: https://github.com/raicem/impulse-blocker 使い方: https://blog.cemunalan.com.tr/2017/05/17/impulse-blocker-guide/

これは指定のドメインをブロックしてアクセスできなくするアドオン。ブロックされているドメインのページにアクセスしようとすると Impulse Blocker のメッセージが表示されアクセスできなくなる。例えば www.youtube.com なら Your impulse to visit www.youtube.com is successfully blocked! と表示される。

ツールバーにアイコンが表示され、 ON/OFF の切り替えや 5 分だけ OFF にしたりできる。

ぼくはこれを YouTubeTwitter へのアクセスのブロックするために使ってみている。入れてみて気づいたことには手癖のように Twitter へアクセスしていること。 Android 側では Digital Wellbeing で時間制限できているのだけど PC 側はしていなかった。これで結構な時間の節約になりそうだ。


ABC079 : AtCoder Beginner Contest 079 の A, B, C, D を解いた。

use proconio::{input, marker::Usize1};

fn dijkstra(n: usize, inf: usize, e: &[Vec<(usize, usize)>], s: usize) -> Vec<usize> {
    use std::{cmp::Reverse, collections::BinaryHeap};
    let mut d = vec![inf; n];
    let mut pq = BinaryHeap::new();
    d[s] = 0;
    pq.push(Reverse((0, s)));
    while let Some(Reverse((w_u, u))) = pq.pop() {
        if w_u > d[u] {
            continue;
        }
        for (v, w_v) in e[u].iter().copied() {
            let w = w_u + w_v;
            if w < d[v] {
                d[v] = w;
                pq.push(Reverse((w, v)));
            }
        }
    }
    d
}

fn main() {
    input! {
        h: usize,
        w: usize,
        c: [[usize; 10]; 10],
        a: [[i64; w]; h],
    };

    let mut edges = vec![vec![]; 10];
    for i in 0..10 {
        for j in 0..10 {
            edges[i].push((j, c[i][j]));
        }
    }

    let mut dists = vec![];
    for i in 0..10 {
        let d = dijkstra(10, 1 << 60, &edges, i);
        dists.push(d[1]);
    }

    let mut ans = 0_usize;
    for i in 0..h {
        for j in 0..w {
            if a[i][j] == -1 {
                continue;
            }
            ans += dists[a[i][j] as usize];
        }
    }

    println!("{}", ans);
}

今日のコミット。

ABC107 の A, B, C を解いた

ABC107 : AtCoder Beginner Contest 107 の A, B, C を解いた。

use proconio::input;

fn main() {
    input! {
        n: usize,
        k: usize,
        x: [i64; n],
    };

    let mut minus = vec![];
    let mut zero = vec![];
    let mut plus = vec![];
    for x_i in x.iter().copied() {
        match x_i.cmp(&0) {
            std::cmp::Ordering::Less => minus.push(x_i),
            std::cmp::Ordering::Equal => zero.push(x_i),
            std::cmp::Ordering::Greater => plus.push(x_i),
        }
    }
    minus.reverse();

    let k = if zero.is_empty() { k } else { k - 1 };

    if k == 0 {
        println!("0");
        return;
    }

    let mut ans = 1 << 60;
    for cm in 0..=k {
        if cm > minus.len() {
            continue;
        }
        let cp = k - cm;
        if cp > plus.len() {
            continue;
        }
        let d_minus = if cm == 0 { 0 } else { minus[cm - 1].abs() };
        let d_plus = if cp == 0 { 0 } else { plus[cp - 1] };
        ans = ans.min(d_minus * 2 + d_plus).min(d_minus + d_plus * 2);
    }

    println!("{}", ans);
}

今日のコミット。

AGC024 の A, B を解いた

AGC024 : AtCoder Grand Contest 024 の A, B を解いた。

use proconio::{input, marker::Usize1};

fn main() {
    input! {
        n: usize,
        p: [Usize1; n],
    };

    let mut q = vec![n; n];
    for (i, p_i) in p.iter().copied().enumerate() {
        q[p_i] = i;
    }

    let mut max = 1_usize;
    let mut count = 1_usize;
    let mut prev = q[0];
    for q_i in q.into_iter().skip(1) {
        if prev < q_i {
            count += 1;
        } else {
            count = 1;
        }
        prev = q_i;
        max = max.max(count);
    }

    let ans = n - max;
    println!("{}", ans);
}

bouzuya/rust-sandbox の twiq-light で user id を https://api.twitter.com/2/users/me で得るようにした。ハードコーディングされていた id がなくなり、認証済みのトークンだけで得られるようになったのは良い。無駄なやりとりなので、認証時に一度取得してあとは保持しておけば良いだけなんだけど……。

認証ユーザーが途中で変わった場合などに取得済みのツイートなどをどうすべきか。そんな状況はぼくひとりで使う限りは起きそうにないのだけど……。


子どもの送迎中にけがをした。つい先日もやけどした。けががおおい。

子どもの送迎に合わせて勤務時間を調整した。


今日のコミット。

twiq-light 0.2.0 をつくった / ABC137 の A, B, C, D を解いた

2023-01-01 に twiq-light 0.2.0 をつくった。 bouzuya/rust-sandbox の twiq-light/ にある。

  • twiq-light queue 関連のコマンドを追加した
    • ツイートの予約ができるようになった
  • 認証情報などを毎回渡さなくて済むように設定ファイルを追加
    • ${XDG_CONFIG_HOME}/net.bouzuya.rust-sandbox.twiq-light/config.json
  • ツイートのデータファイルの位置を変更
    • ${HOME}/twiq-light.json${XDG_STATE_HOME}/net.bouzuya.rust-sandbox.twiq-light/tweet.json
  • TWIQ_LIGHT_TWITTER_BEARER_TOKEN 環境変数を削除し、 Firestore 上に保存された OAuth2 の token に統合

思った以上にいろいろ変えている。もっと早くバージョンを区切っても良かったように思う。

設定ファイルなどの配置は crates:xdg を使って XDG Base Directory specification (https://wiki.archlinux.jp/index.php/XDG_Base_Directory) に寄せている。TWIQ_LIGHT_CONFIG_HOMETWIQ_LIGHT_STATE_HOME 環境変数で保存場所は別途指定できる。

他の人が使うことをまったく想定していない。そのうち直すかもしれない。


ABC137 : AtCoder Beginner Contest 137 の A, B, C, D を解いた。

use std::collections::BinaryHeap;

use proconio::input;

fn main() {
    input! {
        n: usize,
        m: usize,
        mut ab: [(usize, usize); n],
    };

    ab.sort_by_key(|&(a, _)| a);

    let mut sum = 0_usize;
    let mut pq = BinaryHeap::new();
    let mut index = 0_usize;
    for d in 1..=m {
        while index < n {
            let (a, b) = ab[index];
            if a <= d {
                pq.push(b);
            } else {
                break;
            }
            index += 1;
        }

        if let Some(x) = pq.pop() {
            sum += x;
        }
    }

    let ans = sum;
    println!("{}", ans);
}

今日のコミット。