「趣味」カテゴリーアーカイブ

btrfs では fsck が何もしないし、定期的に実行しなくてもよいという話。

この記事この記事で最近触っているbtrfsでは、fsckが必要ないらしい。

実際、fsck.btrfs をしてみると、btrfs checkを使えと助言してくれるようだ。(man fsck.btrfs にもそのように書いてある)

実際、何もしなくてもごくごくたまーに、syslogの中でbtrfsのchecksumエラーの修正とかそういうのが出てくるので、少なくともCentOS7では割といろいろよきに計らってくれているのだろうと想像している。

本当に何もしなくていいのかなぁ、といろいろ見ていると、
http://marc.merlins.org/perso/btrfs/post_2014-03-19_Btrfs-Tips_-Btrfs-Scrub-and-Btrfs-Filesystem-Repair.html
というのにあたり、まぁとりあえず btrfs scrub はやっておいた方がいいらしいというのはあるが、これってRAID向けの機能のような気がするので、とりあえず使わない。(試しにやってみたら、チェックサムエラーの修正が起こってしまったのだけれども、、、このコマンド自体はデータを読むだけで何もしないはずだが、データを読んだときに何か起こったのかなぁ。定期的に全データさらうっていうのもありか、、? うーん。 今は、USBメモリな起動ドライブにあまり負荷をかけたくない。)

なので、
https://btrfs.wiki.kernel.org/index.php/FAQ#When_will_Btrfs_have_a_fsck_like_tool.3F
にも書いてある ”Note that in many cases, you don’t want to run fsck. Btrfs is fairly self healing, …” という文言を信じて、何もしないことにした。

なお、btrfs では、defrag をするコマンドも用意されているが、まぁ、これも負荷があるだろうから、定期的にはやらないことにした。

ついに!うちの!Lumia640にも!Windows10が!きたぞー!

https://blogs.windows.com/windowsexperience/2016/03/17/upgrading-existing-windows-phone-8-1-devices-to-windows-10-mobile/
というわけで、さっそく、Lumia640に upgrade advisor を入れてチェック、とっととアップグレードを始めた。

本体メモリが足らなかったので、適当にSDカードにデータを逃がして、アップグレード開始。
ちょっと時間がかかるが、今アップグレードが走っているところ。どうなるかな~。

で、30分くらいかかってアップグレード終了。

Microsoftアカウントのパスワードを入れ直す必要はなく、wifi設定も完全に引き継いだ状態で起動。

ちょっと試した感じだと、

  1. フォントがきれいになった
  2. タイルの見た目がかわった?
  3. 設定の階層が1段増えて、以前のようにフラットではなくなった
  4. タッチキーボードが変わった。矢印キーはなくなって、トラックポイントみたいなのを使うように変わったようだ。デフォルトだと日本語キーボードから英語キーボードへの変更にひと手間増えた感じがあるけど、ここは設定で変えられる。
  5. IEがEdgeに変わったけど、フォントが変わったくらいしか今のところ気になるところはないかな。
  6. 画面上からスワイプした時の通知バーの通知アイコン。以前は4つを厳選しないといけなかったけど、今はデフォルト表示の4つを選べるほか、「展開」すると、選ばなかったものもすぐに使える。特に、アプリがないとできなかった「懐中電灯」機能がついていること、これはでかい。

印象としては見た目が変わった感じは大きいけど、通知アイコンまわりの操作感が変わったのは地味に便利。たぶんこれはいいものだ。

あ、そういえば、Lumiaカメラをはじめ、いくつかのアプリは無くなってしまいましたな。まぁいいけど。

======

その後、しばらく使っていると、以前より電池の持ちが悪くなった感じがある。 以前 Android を使っていたときと同じような感触。
不要なアプリのバックグラウンド動作を片っ端から切ってみたら、まぁちょっとは持つようになったと思うが、ちょっとがっかり感があるかなぁ。

CentOS7 (1511) でbtrfsのスナップショットを定期的に保存するようにした。

前の記事で省いた、btrfsのスナップショットまわりについて。

btrfsのスナップショット便利だから、みんな使った方がいいよという話。

概要

前に記事に書いたように、システムのバックアップについては、別の外付けドライブを用意してある。このバックアップは、バックアップスクリプトの中で細工をして、grub設定ファイルやfstabなどは調整ずみであり、すぐに起動できるようになっている。

当然これは、起動ドライブが壊れるたらどうしよう、という意味でのバックアップにはなっているのだが、これとは別に、ファイルを誤って削除したらどうしよう、という意味でのバックアップも用意する必要がある。

幸い、btrfsにはスナップショット機能がついており、重複ファイル分の容量を気にせずスナップショットを作りまくれるので、今回はこれを利用することにした。

続きを読む CentOS7 (1511) でbtrfsのスナップショットを定期的に保存するようにした。

CentOS7 (1511) で、すぐに起動できるシステムバックアップの作成

NUC(DN2820FYKH)で、起動用のドライブとは別のドライブを用意して、すぐに起動できるシステムバックアップを作成した。USBドライブなどの外付けデバイスでシステムバックアップを作成するときにでもご参考に。

やりたいこと

NUC(DN2820FYKH)で、現在USB3.0なUSBメモリ(32GB)を起動ドライブとしている。USBメモリがいつ壊れるかと気にしながら使い続けるというのもさすがに心もとないので、すぐに起動できるバックアップを用意しておきたい。

続きを読む CentOS7 (1511) で、すぐに起動できるシステムバックアップの作成

pspgoのスライド部分が壊れたのでばらして直した。

pspgoを何度も落としたりしていた結果、ある時気づいたら画面と本体をつなぐスライド部分(右側)のねじが外れて浮いてしまっていた。

あ~あとしょげながらも、とりあえずは参考URLを参考にして、PSPgoをばらしてみた。細かい部品が多かったりしたけど、ばらすのはドライバ一本でなんとかなる。

スライド部分の本体側ねじは、まだ本体内部のねじ穴のところに残っていたので、それをつけてしめなおしておしまい。

接続部分が小さいフレキケーブルが硬くてなかなか抜けなかったのが、今回一番難しかったところ。これは、たまたまあったでかいクリップ(目玉クリップ?)を使って引っ張ったらなんとか抜けたが、これでなんとかなることに気付かなかったら詰んでた。

今回は完全に画面と本体をばらす必要はなかったので、バッテリ部分の封印シールについては、一応触らずに済ませることができたが、たぶん折り目がついてしまっているので、微妙なところではある。(本当は新しいバッテリとか、大容量互換バッテリに付け替えてしまいたいところだけども、、、。)

まぁ、治ったからよかった。

参考URL
http://imaginglabo.web.fc2.com/PSPgo-barabara.htm
http://mrepairshop.jp/blog-entry-59.html

パスワード管理ソフトの KeePass を導入した

KeePassを導入して、いろいろなパスワードを難しくして覚えさせ、自動入力でハッピーな暮らしになったかもしれない話。

今までは、一つのパスワード付きファイルを用意して、パスワードが必要なサイトごとに、

  1. ユーザID
  2. パスワードのヒント(当然、パスワードの使いまわしはないようになっている)

を、書いて保存していた。

これはこれでうまくいっていると思っていたが、以前から気になってはいたがなかなか手が出なかったパスワード管理ソフトを今回導入してみた。

続きを読む パスワード管理ソフトの KeePass を導入した

codeiq @riverplus さんの「ロング・ロング・ストリング問題」を解いた

https://codeiq.jp/q/2683

作者による解説は
https://codeiq.jp/magazine/2016/03/38398/ (Wayback Machine 経由)

回答は
http://togetter.com/li/947393
でまとめられている。

問題はだいたいこんな感じ

自然数 n に対して、関数 F(n) を、n**n(n の n 乗)を 10 進数で表したときの桁数と定義します。
さらに、2 以上の自然数 m に対して、F(n) = m となる n の値を G(m) と定義します。
もしそのような n が存在しない場合は、G(m) = -1 と定義します。

標準入力から、自然数 m(2 ≦ m ≦ 1010)が与えられます。
標準出力に G(m) の値を出力するプログラムを書いてください。

rubyで書いたニュートン法の提出コードはこちら。
四捨五入しているところはちょっと怪しいと思ったけど、
テストケースが全部通ったので、とりあえずは深く考えずにそのままにしている。
自然対数じゃない対数の微分とか、高校以来かもしれない。

 m=gets.chomp.to_i
# 入力mに対して、10**m=n**n、すなわち n*log10(n)-m = 0 を満たす 
# 実数nを、ニュートン法で求める。
i = m
tmp = (i*Math.log10(i) - m )/(Math.log10(i) + 1/ Math.log(10))
while tmp.abs > 0.01
  i-=tmp
  tmp = (i*Math.log10(i) - m )/(Math.log10(i) + 1/ Math.log(10))
end
i=i.round # ここは大丈夫かな? # -1 になる条件をチェックしつつ出力。
puts (i*Math.log10(i)).ceil == m ? i : -1 

codeiq @riverplus さんの「プラス・マイナス・ゼロ問題」を解いた。

問題&解法はこちら。
https://codeiq.jp/magazine/2016/02/37963/

問題は、大体下記のような感じ。

自然数 n に対して、次の等式を考えます。

    □1□2□3□4…□n = 0

四角の部分には、プラス(+)またはマイナス(-)の記号が入ります。

自然数 n に対し、等式を成立させる記号の入れ方の数を F(n) と定義します。

標準入力から、自然数 n(1 ≦ n ≦ 50)が与えられます。
標準出力に F(n) の値を出力するプログラムを書いてください。

提出コードはruby。(コメントだけ追加しました。)
基本的には、ひとつひとつ+-していったときの値を、まとめて勘定しているだけ。
一番最初に全通り数え上げてみるのを書いてみた後、それではとてもとても無理ということで書き直した感じ。

def solve(n)
  # 1..j の数字について処理した結果の値をキーに、そのキーの値になる
  # +-の組み合わせの数を値として持つ連想配列を考える。
  # (Arrayだとインデックスが負にならないような小細工が必要で面倒)
  ret = {1 => 1} # -1から始まるものは、対称性から最後に2倍してすます
  (2..n).each{|j|
    tmp = Hash.new{|h,k| h[k] = 0}
    # j番目のHashは、j-1 番目のHashの各要素{k=>v}について、
    # k+j, k-j の値にvを足していくことで得られる。
    ret.each{|k,v|
      tmp[k+j] += v
      tmp[k-j] += v
    }
    ret = tmp
  }
  ret[0] * 2
end
while str = STDIN.gets
  n = str.chomp.to_i
  puts solve(n)
end

最近のゲーム

フランスに来て時間ができそうなので、しばらくやっていなかったPSPのゲームでもやろうと、PSPgoを持ってきた。
普通にこちらでもストアにつなげることはわかっていたので、あとでいろいろと購入もしている。
(つうか、3DSを持ってこなかったのは、後から考えれば失敗だった、、、。)
続きを読む 最近のゲーム

codeiq @riverplusさんの 「スロット・マシン問題」を解いた。

解きました。フィードバックは大変なんでしょうね~。
最初に書いたコードでは、F(12)までとてもとてもまともな時間で計算できなかった。
想定時間30分で12のときまで解くのは結構ハードだと思う。

恥ずかしながら半日~1日くらい??

【問題】

n 個のリール(数字が描かれている部分です)を持つスロットマシンを回します。

各リールには、0 から 9 のいずれかの数字がランダムに出ます。

このとき、「最も多く出現した数字の出現回数」に等しいドルが賞金として得られます。

例えば n = 6 のスロットマシンを考えましょう。

各リールに、左から順に 7 7 5 1 0 7 という数字が出たとします。

このとき、7 の数字が最も多く 3 回出現していますので、賞金は 3 ドルです。

リールの数字が 0 2 0 9 2 6 のとき、賞金は 2 ドルです。

リールの数字が 1 2 3 4 5 6 のとき、賞金は 1 ドルです。

リールの数字が 8 8 8 8 8 8 のとき、賞金は 6 ドルです。

このスロットマシンを 1 回まわしたときの賞金の期待値を F(n) とします。

例えば F(1) = 1,F(2) = 1.1,F(3) = 1.29 となることが確かめられます。

■ 第1問 (Normal)

F(6) の値を求めて下さい(四捨五入は不要です)。

■ 第2問 (Hard)

F(12) の値を求めて下さい(四捨五入は不要です)。

【方針】
○ nをn以下で10個までの自然数の和に分割する方法が何通りあるかを計算する。
(このとき、同時に賞金ごとに分類しておく)
○ 上で計算した分割方法ごとに、リールの数字が何通りあるかを計算し、期待値を求める。
○ たとえば、n=6で4点のときは、[4, 1, 1], [4, 2] の2通りの分割があり、
それぞれ、 (10*9*8)*(6!/4!)/2!, (10*9)*(6!/4!/2!)/1!通りの組み合わせになる。
配列の長さmについて、(10からmとる順列)*(並べ方の数)/(配列中に同じ数字があれば割引く)通り。(うーん、我ながらわかりにくいか。)

【rubyの提出コード】

#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
BASE=10 # スロットが10進数で回る。
def solve(n)
  score_sum=0 # スコアの総和
  count_sum=0 # (デバッグ用)スロットの並び方の総和
  make_array(n).each{|score, arrays|
    arrays.each{|arr| # nと賞金で決まる配列ごとにループ
      # 対称性を考慮して、並べ方の数を数える。
      # 配列の中の同じ数字があるかどうか。
      sym=(1..n).map{|i| arr.count(i)>1 ? arr.count(i) : nil }
        .compact.map{|i| facto(i)}.reduce(&:*) || 1
      # 上の対称性も考慮した、並べ方の数。
      part = facto(n)/arr.map{|i| facto(i)}.reduce(&:*) / sym
      # 配列の中の数字にそれぞれ0-9の数字を当てはめる
      count = permu(arr.length) * part
      count_sum += count
      score_sum += score*count
    }
  }
  #  print "count(#{n}) = #{count_sum}\n"
  score_sum.to_f / BASE**n
end
# 普通の階乗計算
def facto(n)
  $facto||=[1]
  $facto[n]||=n*facto(n-1)
end
# BASE個の中からn個とる順列
def permu(n)
  ((BASE + 1 -n)..BASE).reduce(&:*)
end
# nをBASE個までの整数の和に分割し、賞金ごとに分けたHashに配列の配列として格納。
# たとえば n=3 のとき、{1=>[[1, 1, 1]], 2=>[[2, 1]], 3=>[[3]]}を返す。
def make_array(n)
  ret = Hash.new{|h,k| h[k]=[] }
  min = 1 + (n-1)/BASE
  (min..n).map{|sc|
    tmp = rec(sc,n).reject{|arr| arr.length > BASE }
    ret[sc].push(*tmp)
  }
  ret
end
# nと賞金が決まった時の、可能な自然数への分割を配列の配列で返す。
def rec(sc,n,ret=[],all=[])
  sum = ret.reduce(&:+) || 0
  num = n-sum
  if n == sum
    all << ret
  elsif num == sc
    ret << sc
    all << ret
  elsif sc == 1
    num.times{ ret << 1 }
    all << ret
  elsif num > 0 && num >= sc
    ret << sc
    (1..[sc,n-sc].min).each{|_sc|
      rec(_sc,n,ret.dup,all) # 次の数は直前に格納した数字と同じか少ない。
    }
  else
    nil
  end
  all
end

(1..20).each{|i|
  print "F(#{i}) = #{solve(i)}\n"
}

sheevaplug をついに手放した。

手放した、といっても、手元に置かなくなった、くらいの意味だったりする。
2009年8月くらいからずっと家において、NASの頭やバックアップとかのちょっとしたcronを仕込んで使っていたsheevaplugをついに実家においてきた。

実家側でIPアドレスをダイナミックDNSサーバに通知しておいて、必要に応じてバックアップ等のために遠隔で入っていろいろ手当てする予定。
とりあえずログインはできている。

core2duo P8700 のノートPCにwindows10を入れた話

実家においてある、少し古いノートPCにウインドウズ10を入れたら、Edgeとかinternetexplorerとかを立ち上げている時に、しょっちゅう画面が暗転してしまっていた。(そしてたまに戻らなくなって、再起動が必要になってしまう、、、。)

これはどうも、Core2Duoのグラフィックドライバが古いせいらしいが、すでにそれは更新されていないので、どうしようもない。
とりあえずは、「インターネットオプション」の詳細設定タブで「GPUレンダリングではなくてソフトウェアレンダリングを使用する」をチェックして再起動したら、問題なく動くようになったので、これでOK。

windows10 にしたらいろいろとドライバまわりで苦労する。。。そのためのアップグレード予約だったのかも。。。

venue8pro で、 3Gネットワークを誤ってプライベートネットワークにしたら戻せなくなってしまった話。

windows10 にしたvenue8proで、VPN接続したつもりでファイル共有等いろいろあれこれしたら、間違えて3Gネットワークの接続をプライベートネットワークにしてしまい、どうにも戻せなくなってしまった。VPN接続とかWiFi接続とかだと、設定→詳細オプション→デバイスとコンテンツの検索 で切替えできるはずが、携帯電話ネットワークでは選べるスイッチが出てこなかった。

というわけで、http://answers.microsoft.com/en-us/insider/forum/insider_wintp-insider_security/how-do-you-change-from-public-to-private-network/106c320f-7d40-40a8-b428-11976b82fcaeこのあたりを参照して、レジストリを直にいじって解決。やれやれやれやれ、、、。

codeiq 「カット・アンド・スクエア問題」

問題はこちら
http://riverplus.net/codeiq/CutAndSquare.pdf

かいつまんで言うと、
[偶数 n に対して、先頭にゼロを持たない n 桁の整数で上 n/2 桁と下 n/2 桁とに分け、それぞれを 2 乗して和をとると、元の数に戻るような数で、n=6, n=10の場合を求めよ。]という感じ。
色々と回答があるようで、参考になったな~。

で、Rubyで書いた提出コードが下記。
sqrtの結果を整数に丸めるあたりが怪しい気がするが、まぁ、当たりでないときは外れるはずだからOKのはず。

ideone.comにも置きました。便利だね。
http://ideone.com/eMPnrv

【方針】
求めるN桁の数をnとし、 n = a * 10**(N/2) + b とする。
n = a**2 + b**2 (b>0, a>10**(N/2 – 1)) の条件を満たす整数a,bを見つける方針でとく。
1. n = a**2 + b**2 の1桁目に注目すると、aの1桁目の数字は0,2,8のみとなる。
   (Excelで100通りをすべてチェックしましたが、a,bの下1桁の値の組み合わせは8通りしかありません。)
2. 条件の式からbについて解くことができるので、各aについて、bが条件を満たす整数かどうかをチェックする。
   (bについてはループしなくて済む。)

N=10
Base2=10**(N/2)

result = []
((Base2/10)...Base2).select{|a| # aの下1桁を0, 2, 8に絞る。
  tmp = a%10
  tmp == 0 or tmp == 2 or tmp ==8
}.each{|a| # aについてのループ。
  # bは、aについて解いておく。(b>0なので、一意にさだまる。)
  b=(1 + Math.sqrt(1+4*Base2*a -4*a*a)).round/2
  n = a*Base2 + b
  result << n if a*a + b*b == n # 条件を満たすかどうかをチェック。
}
p result
p result.reduce(&:+)

windows10 を dell venue8 pro に入れた

こないな~と、待っていたら、タブレットの方に windows10 へのアップグレードが来ていたので入れてみた。

見た目や設定の場所などは今までと変わったものの、アクションセンターの表示がandroidタブレットのように一覧性よく見やすくなったし、右からのスワイプだけで出せるから感じ。
新しいブラウザはまだあんまり使っていないけれど、トップページにニュースがつらつら並ぶのは、結構便利かも。
windows8.1 のチャームの共有メニューみたいなのが、ブラウザの中から選べるのがよさげ。

なんだか、タブレットを横にして持つと、下が少し詰まって画面がほんの少し小さく感じるかも。

タブレットモードだと、本当にwindowsのデスクトップにアクセスできないようで、タスクバーにピン止めしてるだけだったやつは使えない感じ。どうだろか。

あとは、アクティブスタイラスがちゃんと認識するようになってた。今まではなんかよく使えなくなってた。
なんか、スタイラスがなくても、指で結構ちゃんと選べるようになっている気がする。
スタート画面は一覧性がいいように全画面にするのかなぁ。 設定→パーソナル設定→スタートで設定できる。

仮想デスクトップはまだ試していない。どんなもんじゃろか。

=======
通信関係がちょくちょく切れてイラついたけど、ドライバを更新したらこれは解決した。
あとは、なんだかスリープからの復帰で画面が戻ってこない時があるのが気になるが、、、。

続codeiq

前の記事

スカウトメールがすぐに来た。まぁ、今のところ予定はないんで辞退申し上げるのですが、、、。

pythonやocamlでも解いてみたりしたが、ocamlやばい。intが31bitしかなくて?オーバーフローしても警告もなく実行が続いて気付かない、、、。
手元のocaml4では動くけど、ideoneに突っ込むと、バージョンが古いためか対応できない!やれやれ、、、。

いつもとちょっと違う言語を触ってみる気になるのはいいなぁ。別な関数型言語に手を出してみるべか。

codeiq

しばらく前から気になる広告がいくつか出ていたので、連休の暇つぶしにやってみた。

サクサクっと解けるものは解けるのだけれども、なかなか早く解くアルゴリズムを、想定時間(30分とか)で考えてコードしてテストするのは、結構厳しい感じ。

まぁ、暇つぶしとしてはそれなりによさそうかな。
企業からのスカウトというのが来てしまっても、今のところは困ってしまうのだけれども、暇つぶしとして、ということで、、、。

set_trace_func を使うことで Ruby on Rails のデバッグが超はかどったという話。

最近、 rails で開発しているときに、set_trace_funcでエラー行を表示させるのが便利だったので、メモ。 gem で使っているライブラリも疑っていろいろ見ないといけないので、結構便利だ。

rails側では controllerか何かで適当に
require_relative "hogehoge" if Rails.env.development?
しておいて、hogehoge.rbには下に書いた感じで書くと、はかどった。

実際には、if文の条件をもっといろいろ追加して、余計な出力を出さないようにするが、大筋ではこんな感じ。
eventでc-callやらc-returnを指定すれば、cで書いたメソッドの呼び出しと戻りも表示できる、ということで、いろいろできそうだ。

require 'pp'
set_trace_func lambda{|event, file, line, id, binding, klass|
  if event == "raise"
    # raise 例外が発生したファイル名と行番号を表示。
    print "#{event} at #{klass}:#{id} #{file}:#{line}"

    # 例外が発生した場所でのローカル変数一覧を表示。
    # railsではインスタンス変数やselfを表示させようとすると
    # 表示結果が多すぎて煩雑になる。
    binding.eval(local_variables.map{|v|[v.to_s, eval(v)]})
      .each{|name, val| print "#{name} = #{val.pretty_inspect}" }
  end
}

sinatra で、サーバ側で作成した画像を直接表示

バイナリで送って、javascriptでbase64でencode、、、とか最初は考えたけど、探したらhttp://qiita.com/haruboh/items/b90fcf763295b56b0915を見つけられたので、そのままやった。

まぁ、よくよく考えてみれば当たり前。転送量だってそんなにたいした画像を書くわけでもないので、気にするほどでもなかった。
なお、元記事にある改行コードの削除は、strict_encode64メソッドでエンコードすればOK。

だいたいこんな感じ。
画像作成はgnuplot(と、ruby_gnuplot)を利用。 set output を指定しなければ、ruby変数に処理結果を格納できる。

require 'base64'
require 'gnuplot'
get '/plot' do
  img = Gnuplot.open do |gp|
    # 適当なpng作成処理
  end
  base64 = Base64.strict_encode64(img)
  "<img src='data:image/png;base64,#{base64}'>"
end

で、よくよく確かめたら、今どきのgnuplotは set ternminal svg でsvgをそのまま吐けるので、エンコードとかややこしいことを考えずとも、そのままHTMLにはればよかった。
これだと、gnuplotの日本語fontなど色々ケアしなくてもよいので楽だった。(IE8,9対策に、pngでも描画できないとだめだけども、、、。)

require 'base64'
require 'gnuplot'
get '/plot' do
  img = Gnuplot.open do |gp|
    # 適当なsvg作成処理
  end
  img # svgは普通のXML文字列なので、そのままでOK
end

Microsoft sculpt comfort mouse の関係でbluetoothドライバの設定変更

買った時の記事

sculpt comfort mouse がカクついてイラつく。カクつき始めたら新しい電池を入れればしばらくは快適だが、何が原因かよくわからん。(この電池を入れ替えるとき、eneloopだと電池の出し入れがきついのがまたイラつく。もうむかついたので、電池を入れるとき、引っ張るためのリボンを仕込んだ。)

とりあえず、http://answers.microsoft.com/en-us/windows/forum/windows_8-hardware/why-bluetooth-mouse-keeps-on-disconnecting-in/4d6587f2-a1e9-4486-8a1d-07299cc78d7c を参考にして、
デバイスマネージャー > ヒューマンインターフェース デバイス > Microsoft ハードウェア Bluetooth デバイス > 電源の管理 タブ > 「電力の節約のために、コンピューターでこのデバイスの電源をオフにできるようにする。」 のチェックを外した。

意味があるかはわからないが、とりあえずはこれでしばらく様子見。