ベスパリブ

プログラミングを主とした日記・備忘録です。ベスパ持ってないです。

リモートデスクトップの上のバーの消し方と切断方法

上のバー、ハイパー邪魔。

消し方

  1. リモートデスクトップの接続画面
  2. オプションの表示
  3. 「画面」メニュー
  4. 「全画面表示の使用時に接続バーを表示する」のチェックを外す

f:id:takeg:20191204090438p:plain

切断方法

  1. スタートボタンを右クリック
  2. 「シャットダウンまたはサインアウト」
  3. 「切断」を選択

f:id:takeg:20191204090445p:plain

小数点以下の不要な0を除去したい(Python)

何がやりたいかと端的に言うと、

  • 30.100 => 30.1
  • 30.000 => 30

のようにしたい。

Decimalモジュールを使う

小数点といえばDecimalなので、Decimalモジュールを探したらそれっぽいDecimal.normalizeがありました。

数値を正規化 (normalize) して、右端に連続しているゼロを除去し、 Decimal('0') と同じ結果はすべて Decimal('0e0') に変換します。等価クラスの属性から基準表現を生成する際に用います。たとえば、 Decimal('32.100') と Decimal('0.321000e+2') の正規化は、いずれも同じ値 Decimal('32.1') になります。

これは良さそう。早速使ってみます。

from decimal import Decimal
s = "30.0"
a = Decimal.normalize(Decimal(s))
print(a)
# 3E+1

うーん。指数表現になってしまった。

他に使えそうなものを探すと、Context.normalizeがありました。こっちを使ってみましょう。

from decimal import Decimal, Context

s = "30.0"

context = Context()
a = context.normalize(Decimal(s))
print(a)
#3E+1

変わらないですね。指数表現じゃなくしてほしいんですが。

色々漁ってると、Decimal FAQにドンピシャなQAがありました。

Q. ある種の十進数値はいつも指数表記で表示されます。指数表記以外の表示にする方法はありますか?

A. 値によっては、指数表記だけが有効桁数を表せる表記法なのです。たとえば、 5.0E+3 を 5000 と表してしまうと、値は変わりませんが元々の2桁という有効数字が反映されません。

もしアプリケーションが有効数字の追跡を等閑視するならば、指数部や末尾のゼロを取り除き、有効数字を忘れ、しかし値を変えずにおくことは容易です:

>>> def remove_exponent(d):
...     return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
>>> remove_exponent(Decimal('5E+3'))
Decimal('5000')

なるほど。

結論

というわけで、数値(float or int)から正規化した文字列(str)を返す関数は以下のようになります。

from decimal import Decimal, Context


def decimal_normalize(f):
    """数値fの小数点以下を正規化し、文字列で返す"""
    def _remove_exponent(d):
        return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
    a = Decimal.normalize(Decimal(str(f)))
    b = _remove_exponent(a)
    return str(b)

print(decimal_normalize(30.0))
# 30
print(decimal_normalize(30))
# 30
print(decimal_normalize(30.0001000))
# 30.0001
print(decimal_normalize(0.0))
# 0
print(decimal_normalize(0))
# 0
print(decimal_normalize(-5.0))
# -5

Decimal(x)するときに、xはstr型にする必要はなくてfloat型のままでもいけますが、私はstr型に変換するようにしています。なんか挙動の差があって、str型に変換したほうが安定していたイメージがあるので(うろおぼえ)。

Decimalモジュールを使わない

Decimalモジュールを探す前に書いていたコード。Decimalを使いたくないときはこっちでもまあ。

def decimal_normalize(f):
    text = str(f)
    while True:
        if ("." in text and text[-1] == "0") or (text[-1] == "."):
            text = text[:-1]
            continue
        break
    return text

print(decimal_normalize(30.0))
# 30
print(decimal_normalize(30))
# 30
print(decimal_normalize(30.0001000))
# 30.0001
print(decimal_normalize(0.0))
# 0
print(decimal_normalize(0))
# 0
print(decimal_normalize(-5.0))
# -5

ABC 143: D問題の解説 (Python3)

問題:AtCoder Beginner Contest 143: D - Triangles

公式解説PDF:https://img.atcoder.jp/abc143/editorial.pdf

公式解説動画:https://youtu.be/3U_N7zelnMM?t=2983

解説

解説動画まんまです。

二分探索問題です。


問題の条件の、

  • a < b + c
  • b < c + a
  • c < a + b

というのは三角形の成立条件ですね

3つの棒を選んで、それでいくつ三角形を作れるかという問題ですが、便宜上、選んだ3辺のうち最も長い辺をcとします。

単純な方法で求めるならば全探索で、a,b,cそれぞれでループ(3重ループ)回せばよいですが、それだと O(N^3)でTLEします。


しょうがないので、aとbを固定して考えてみます(aとbについてforループで回します)。

与えられた棒が 2 3 4 6 6 7 10 とします。これをリストに入れて予めソートしておきます。

今、a=3, b=6 とすると、

2 3 4 6 6 7 10
a b

a + b = 9なので、a + b > c より、cは9未満になります。

2 3 4 6 6 7 10
a b

上記の○の数を数えていけば、答えは求まります。

ここで問題となるのが、上でいう「7以下」という境界をどう高速に求めればよいのかということですが、これは二分探索で高速に求まります。

f:id:takeg:20191122214936j:plain

コーナーケース

  • 特になし

実装

# -*- coding:utf-8 -*-
import bisect

def solve():
    N = int(input())
    Ls = list(map(int, input().split()))
    Ls.sort()

    # O(N^2 * logN)の全探索で解く
    ans = 0
    for a_i in range(N):
        for b_i in range(a_i+1, N):
            c_i = bisect.bisect_left(Ls, Ls[a_i]+Ls[b_i])
            if c_i > b_i:
                ans += c_i - b_i - 1
            else:
                pass

    print(ans)

if __name__ == "__main__":
    solve()

計算量は O(N^2 logN)です 。

HHKB Professional JPを 1ヶ月使った感想

2019/09/08(日)、HHKBのキーボードを買いました。

www.pfu.fujitsu.com

買ったのはHHKB Professional JPの墨(PD-KB420B)です。

買った理由

  • 長くなりそうなITエンジニア人生、HHKBを一度くらい使ってみたいと思った
  • 人生の仕事に割り振る時間は多く、この仕事の時間はできるだけ楽しく快適にしたいというモチベーションは常々あった。少しでも快適なものになる可能性があるならそうしたい
  • 仕事が行き詰まってる感あったので、新しいキーボードで気分を変えたい
  • 「使用キーボードはHHKBです」とか言ってみたい
    • ブランドもの欲しがるやつみたい
  • 本当は赤ポチキーボードが欲しくてYODA IIが欲しかったけど、再販に時間がかかりそうで待てなかった
  • 他の赤ポチキーボードで良さそうなのがなかった

などです。

BT(Bluetooth)版を買わなかった理由

キーボードは基本Bluetoothのものしか買わないのですが、以下の理由でBT版は見送りました。

USB接続はやっぱ面倒くさいですが、会社の広めできれいな机ならばまぁ許容できます。

ただHHKBのUSB接続の非常に良い点として、USB接続のHHKB本体側はmini USB Bタイプになっているので、本体とケーブルを完全に取り外しが可能です。ちょっと横に置くときとかに便利ですし、ケーブルが断線した場合はケーブルのみ買い換えればOKです。

Type-Sを買わなかった理由

現在(2019/09/08)の最新モデルはHHKB Professional Type-Sと呼ばれるもので、こちらはSpeed(早打ち)とSilent(静音性)の性能が高くなってるとのこと。基本的に最新のものを欲しいと思う性分なので本当はこっちが欲しかったけど以下の理由で見送りました。

  • 白キーボードしかなく、白キーボードが嫌だった
  • かつてのPayPay特需で貯まっていたビックカメラのポイントで買いに行ったが、そもそも在庫にType-Sがなかった
  • HHKB Professionalより1万円くらい高い。まあ許容範囲だと思ったけど、上記のビックカメラのポイントを使いたかったのと、在庫がなかったのでもういいやと思った。

日本語配列にした理由

キーボードの右下がHHKBと刻印されてるやつがカッコいいのですが、それは英語配列版なのです。英語配列は以下の理由で見送りました。

  • 日本語配列しか使ったことない
  • 英語配列を覚える気はさらさらない
  • やっぱり「i」の上には「(」「)」があって欲しい
    • キーボードを試打するときは頭の中で「int main(void){ (FizzBuzzのコード) }」とか「class Hoge(): def __init__(self):」とか「kodomoootokage」とか打つのだが、やはり「()」は「i」キーの上だよなぁ
  • 日本語配列版は十字キー(↑←↓→キー)が存在します。なんだかんだで使い慣れてるのであったほうが便利。

使用感

  • 話に聞いていたが、やっぱりスコスコして気持ちいい。
    • 第一印象としては「スコスコして気持ちいい」
    • 3週間くらい経つと、打キー感が最高なのと独特の配列に慣れて、もうずっとこれでいいんじゃないかと思えてくる
  • 打キー感はかなり良い。普段は2千円くらいのワイヤレスキーボードを好んで使っていて、それはそれで大好きなんだけど、打キー感に関しては段違いに良いと言っていいかも。
  • HHKBは特殊なキー配列になっているが、やはり慣れは必要。
    • 特に「Ctrl」キーの位置の違い、「半角/全角」キーの位置の違いは最大の慣れポイント
  • キーの数を減らしてる分、F5キーとかはFnキーと組み合わせて使うように設計されているのだが、慣れてきたらまぁ違和感なく使えるのだけれど、F5キーとかスクリーンショットキーとかを結構頻繁に使うフロントエンドやWiki業務のときはちょっと結構めんどくさい
    • 他の人のレビューで見てなるほどと思ったが、HHKBは省スペース性とプログラミングに特化しているが、文章を書くときやファンクションキーやPrtScキーなど特殊キーをよく使う場合はフルキーボードのほうが使い勝手がいいかもしれない
  • 少し後悔としては、RealForce + HHKBのキーボードにすれば良かったかもしれないと思っている。やはり会社でHHKB配列に慣れて、家でコード書くときにHHKB配列じゃないのはかなり煩わしい。普通の配列のRealForce型にしとけばよかったかも。それとも家用のHHKBを買うしかない...?
    • マジで会社と家で配列が違うのはストレスなので、家用を買おうか悩んでいる

通常のキーとHHKB JPキーの配置の違い

通常のキーボードとHHKB JP(日本語配列)はキー配置が違います(英語配列はまた違う)。詳しくはこちら

一番下の段のキーのマークと配置が独特なので、それらについて少し解説します。

  • 一番左のキーが「Fn」キー
    • 通常は一番左下は「Ctrl」だが、HHKB JPは「Fn」キー
  • 左から2番目の「HH」キー
    • 「HH」みたいなマークのキーは、「半角/全角」キーに該当する。
    • 半角全角切り替えを左手小指ですることになるので、ここは慣れポイント。
  • 左から3番目の「◇」キー
    • Windowsでは、「Win」キーに該当する。Macでは知らない。これは通常とマークが違うだけで同じ配置
  • 左から4番目の「Alt」キー
    • Altキーは通常とまんま
  • 左から5番目の「↑\↓」キー
    • 「↑\↓」みたいなマークのキーは、「無変換」キーに該当する。これは通常とマークが違うだけで同じ配置
  • 左から6番目の「スペース」キー
    • 言わずもがなスペースキー。通常と同じ配置(真ん中に大きく配置)。
  • 左から7番目の「↺」キー
    • 「↺」みたいなマークのキーは、「変換」キーに該当する。これは通常とマークが違うだけで同じ配置

みたいに、配置はともかく謎マークのキーが存在します。この謎マークは背面のDIPスイッチでPC(Windows)モードやMacモードを切り替えたときにマークの意味に矛盾を生じさせないためでしょう。それが逆にわかりにくくなってる感はありますが。

おまけ1

カラーキートップを購入し、少しカスタマイズしました。

f:id:takeg:20190914184326j:plain
その1。いいね

f:id:takeg:20190914184228j:plain
その2。うーん

f:id:takeg:20190914184139j:plain
その3。オッ

今はその3で運用しています。

  • 「なんでESCキーは黒のままなの?」
    • ESCを目立たせるメリットがないと思った。端っこのキーだし。
  • 「なんで0(F10)キーを青くしてるの?」
    • 0キーを青くすることでここから左のキーが数字で、右側が記号と判別しやすい
    • F10キーをよく使う。日本語入力してるとたまにある「design」って入力しようとして「でしgn」って入力しちゃったときにF10で即「design」にできる。ということを良くするので。
    • その2と見比べたら、ESCを青くしたらなんか変。なのでESCは黒のままで。

おまけ2

NEW GAME! 涼風青葉のねんどろいどを買いました。購入した理由は以下の理由です。

  • 長くなりそうなITエンジニア人生、相談できる相手はすぐそばに置いておきたい
  • 人生の仕事に割り振る時間は多く、この仕事の時間はできるだけ楽しく快適にしたいというモチベーションは常々あった。少しでも快適なものになる可能性があるならそうしたい
  • 仕事が行き詰まってる感あったので、フィギュアでも置いて気分を変えたい
  • 女性社員が机の上にちっちゃい動物の置物をたくさん置いてて、いいなと思った

しかし以下の理由で、まだ会社に持っていけていません。

  • キモいと思われたくない

シット!なんてこったブッダ!俺は涼風青葉と一緒に仕事をしたいっていうのに、他人の目を気にして行動できないままでいやがる。お前はいつもそうだ。何をするにも中途半端で、誰もお前を愛さない。

ABC 112: D問題の解説 (Python3)

問題:AtCoder Beginner Contest 112: D - Partition

公式解説PDF:https://img.atcoder.jp/abc112/editorial.pdf

公式解説動画:AtCoder Beginner Contest 112 解説放送 - YouTube

解説

解説動画まんまです。


 a_1 + a_2 + ... + a_N = M のとき、最大公約数 gcd(a_1, a_2, ..., a_N)の最大値は?という問題です。

ここで gcd(a_1, a_2, ..., a_N) = Kとおくと、

 a_1, a_2, ... , a_N はそれぞれKの倍数なので、MもKの倍数です。

MがKの倍数ということは、KはMの約数ということです。


KはMの約数ということは、 M \geq K N と書けます。

たとえば、N=10, M=168のときの、約数Kの最大値を求めたいとします。

Mの約数は1, 2, 3, 4, 6, 7, 8, 12, 14, 21, 24, 28, 42, 56, 84, 168です。

  • K = 1のとき

 M = 9K + 159K となるのでOKです。

  • K = 7のとき

 M = 9K + 15KとなるのでOKです。

  • K = 8のとき

 M = 9K + 12KとなるのでOKです。

  • K = 12のとき

 M = 9K + 5K となるのでOKです。

  • K = 14のとき

 M = 9K + 3K となるのでOKです。

  • K = 21のとき

 M = 9K - 21 で、9KはM=168の値を超えてしまうのでだめです。

K=24以降も、同様に9KがMを超えてしまうのでだめです。


以上の考察から、Mの約数Kのうち、 M \geq K N を満たす最大のKを探索すれば良いです。

制約より、Mのとりうる最大値は 10^9と大きいですが、 M=ABとしたときの約数のペア(A, B)は高々 \sqrt{M}を境に対称なので、探索は \sqrt{M}以下までで十分です。

対称というのはたとえば、M=100のとき、約数のペア(A, B)は、

  • M = 1 * 100
  • M = 2 * 50
  • M = 4 * 25
  • M = 5 * 20
  • M = 10 * 10 (ここから対称)
  • M = 20 * 5
  • M = 25 * 4
  • M = 50 * 2
  • M = 100 * 1

となるので、約数のペアを探すのに1~100まで探索しなくても、1~10までの探索でOKです。

コーナーケース

  • 特になし

実装

def solve():
    N, M = list(map(int, input().split()))

    # Mの約数をすべて調べる
    divs = set()  # Mの約数を格納する
    n = 1
    while n <= M**(1/2):
        if M%n == 0:
            # nがMの約数ならば
            divs.add(n)
            divs.add(M//n)
        n += 1

    # Mの約数dの中で、M >= d*Nを満たす最大のものが答え
    ans = 0
    for d in divs:
        if M >= d*N:
            ans = max(ans, d)
    print(ans)


if __name__ == "__main__":
    solve()

計算量は O(\sqrt{M})です 。

boogie board Model:WT13150の電池交換

2019/1/1にキングジム ブギーボード 電子メモパッド BB-1GXクロ クロをAmazonで購入しました。個人的にコードやアイデアの殴り書きに使っていてかなり気に入っていたのですが、2019/9/後半くらいに消去ボタンを押しても文字が消えなくなりました。寿命かな?と思ったけど、購入してから1年経ってないし、消去回数約5万回に達しているとは思えないので、初期不良品か故障か電池切れのどれかだろうなと思いました。まあそんなに高価なものでもないしおもちゃとしては面白かったので捨てようかなと思ったのですが、ダメ元ついでに分解してみることにしました。

f:id:takeg:20191002143559j:plain
ペンを止めるやつと、ネジを外すと、上部分が外れる

唯一ネジ止めしてある裏側の4つのネジを外すと、ボタン電池を発見。ボタン電池を一旦外し、再度取り付けて消去ボタンを押すと文字が消えました。どうやら電池(電池のズレか、電池切れ)が原因だったっぽい。うちわのように仰いでたりしてたので、何かの拍子でズレたのかも。しらんけど。

ボタン電池はCR2025の3ボルト。電池交換したらまた使えるようになりました。

この型式のものは公式的には電池交換不可能なものなので、交換の際は自己責任でお願いします。

ABC 142: D問題の解説 (Python3)

問題:AtCoder Beginner Contest 142: D - Disjoint Set of Common Divisors

公式解説PDF:https://img.atcoder.jp/abc142/editorial.pdf

公式解説動画:AtCoder Beginner Contest 142 - YouTube

解説

要約すると、(gcd(A, B)を素因数分解したときの素因数の個数)+1が答え。


入力例2を考えます。

「420と660の正の公約数の中からいくつか約数を選んで、選んだやつのどの異なる2つの整数も互いに素となる最大の約数の個数は何か?」という問題になります。

420と660の正の公約数は、必ず最大公約数以下の値になります。よって約数のとりうる範囲は1 ~ 最大公約数になります。420と660 の最大公約数gcd(420, 660)は60です。

60の約数を列挙してみます。

1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60

このうち、どの2つの整数も互いに素となる約数の個数が最大となる選び方は、

1, 2, 3, 5 の4つです。

見やすく表にして整理すると、

60の約数 1 2 3 4 5 6 10 12 15 20 30 60
答え 1 2 3 5

たとえば15はなぜいけないのでしょうか?それは15を素因数分解すると 15 = 3^1 * 5^1 なので、15を選ぶと3と5が選べなくなってしまいます。 よって15を選ぶより3と5を選んだほうが多くを選べるということになります。

12や20なんかも同様の理由で選べません。

4はどうでしょうか?これは素因数分解すると 4 = 2^2になります。つまり4を選ぶと2を選べなくなります。この2を選ばないパターンの1 3 4 5は、どの2つの整数も互いに素となっているのでOKです。よって2の代わりに4を選ぶのはありですが、選ぶメリットは特にないですよね。素数しか選ばないというルールのほうが問題を簡単化できます。

ということで入力例2の場合では、gcd(420, 660)で最大公約数を求めて、その最大公約数を素因数分解したときの素因数を選べば、どの2つの整数も互いに素となります。あとついでに1も約数なのでこれも加えます。これが答えになります。


制約 A, B \leqq 10^{12}を考えます。Nがでかすぎるので、 O(N)の解法はTLEします。

この問題におけるNとは、AとBの最大公約数gcd(A, B)の値です。1~gcd(A, B)の範囲で素因数を数えることになります。gcd(A, B)の最大値は 10^{12}なので、 O(N)は無理です。

ですが実は、最大公約数Nが何かの整数pで割り切れるときは、 N = p * q と書けますので、 p \leqq \sqrt{N}となります(例: N=10^{12} のとき、 p=10^6 q=10^6 )。なのでNまで調べる必要はなく、 O(\sqrt{N})で解くことができます。

このあたりの考え方はエラトステネスの篩とかで素数を数える問題を知っていて慣れていれば、 O(\sqrt{N})で解けそうだなと当たりがつきます。

コーナーケース

  • 最大公約数が1のとき、1を出力して終了

実装

# -*- coding:utf-8 -*-
import sys
from fractions import gcd
from collections import Counter


def prime_factorization(n):
    """nを素因数分解する

    Return d(dict):
        素因数をキー、素因数の指数部を値とするディクショナリを返す

    Example:
        n=140 -> d = {2: 2, 5: 1, 7: 1}
    """
    d = Counter()
    m = 2
    while m*m <= n:
        while n%m == 0:
            n //= m
            d[m] += 1
        m = m + 1 if m == 2 else m + 2  # m=3からは、m+=2する(偶数は明らかに素数ではないので)

    if n > 1:
        d[n] += 1
    return d


def solve():
    A, B = list(map(int, sys.stdin.readline().split()))
    cd = gcd(A, B)

    if cd == 1:  # コーナーケース
        print(1)
        return

    # (素因数分解の素因数の個数)+1が答え
    prime_d = prime_factorization(cd)
    print(len(prime_d)+1)


if __name__ == "__main__":
    solve()

計算量は O(\sqrt{N})です 。

蛇足

なんか偉そうに「この問題に慣れていれば~」とか書きましたが、本番でTLEしてるんですよね。精進します。