csvから任意のフォーマットに変換するツールを作成した話

タイトルの通りcsvを変換するツールを作った話です。

github.com

概要とか使い方はGitHubのREADMEに書くとして、ブログには作ったきっかけとかを書こうと思います。

作ったきっかけ

「DBにこの初期値を登録してねー」っていうcsvファイルがあってそれをDBに投入するんですが、そのcsvファイルがちょくちょく変更になったりするので、面倒になって「初期値投入用のコマンドを自動生成すればええやん」となり作りました。

使ったライブラリとか

言語はPythonを使いました。

コマンドライン引数のパースにdocoptを使用しました。
これは初めて使ったんですが、ヘルプを書くことでそれをパースロジックとして使用するという発想が面白いなと思いました。
ヘルプを書くだけでよくて、コードを書く必要がないのつよい。

また、csvファイルのパースにcsvモジュールを、exeファイル化にpyinstallerを使用しました。

フォーマットファイルへの指定方法からわかる人にはわかると思うんですが、フォーマットファイルへのcsv要素の投入はprintf 形式の文字列書式を利用しています。
若干古い仕様なんですが、正規表現えいえいとかをしなくて済んだのでいいかなって。

気になったこと

pyinstallerで--noconsoleオプションを指定をするとコマンドから実行してもprintで書いた文字列が表示されないのでやめた。

exeファイルをダウンロードしようとするとブラウザが怒ってくる。
ネットから取ってきたexeファイルを実行するのは実際危ないので、使う場合はこのツールのことを信用する場合のみ使ってね。

まとめ

しょうもないツールばっか作ってないである程度の大きさのコードを書きたいと思いながらも、こういうことするのは楽しい。

大きいコードは完成までいける気がしないので結局やらないがち。

Pythonで僕だけのキーボードショートカットを生み出す

前説

最近キーボードショートカットを覚えることにハマっています。 案外なんでもキーボードだけで出来ることに気づいた僕はこんなことを考え始めました。

「ブラウザの起動をキーボードに割り当てられないかな?」

INF回やる操作なのに毎回カーソルをタスクバーまでもっていくのが面倒になってしまいました。 ちょうど某で使っていたwxPythonが使えそうだということで僕だけのキーボードショートカットを生み出すことにしました。

コード解説

まずは作成したPythonコードから

import wx
import webbrowser
import subprocess


class MyFrame(wx.Frame):
    def __init__(self):
        super(MyFrame, self).__init__(None)

        # virtualKeyCode https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes

        # Alt + ↑にブラウザの起動
        id = wx.NewIdRef()
        self.RegisterHotKey(id, wx.MOD_ALT, virtualKeyCode=38)
        self.Bind(wx.EVT_HOTKEY, self.openBrowser, id=id)

        # Win + F4にVPN設定画面の起動
        id = wx.NewIdRef()
        self.RegisterHotKey(id, wx.MOD_WIN, 115)
        self.Bind(wx.EVT_HOTKEY, self.openVpnClient, id=id)

    def openBrowser(self, event):
        webbrowser.open("https://google.com")

    def openVpnClient(self, event):
        subprocess.Popen(r"C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client\vpnui.exe")


if __name__ == "__main__":
    myFrame = wx.App()
    MyFrame()
    myFrame.MainLoop()

wxPythonのFrameクラスを継承してMyFrameクラスを作成しています。
MyFrameのコンストラクタではRegisterHotKeyからキーボードショートカットの登録、Bindから登録したキーボードショートカットへのイベントハンドラの設定を行っています。
KeyCodeは確認したくなったときにすぐ見られるようにコメントでペタリしてあります。
38は↑、115はF4です。
イベントハンドラ内では受け取っている引数のwx.Eventであれやこれやができますが、今回作成したopenBrowserではwebbrowser.open()を叩いているのみになっています。
登録するショートカットが1つではつまらないので、ついでにこれまた在宅勤務になってINF回起動するVPNのアプリにキーボードショートカットを設定しておきます。
あとはmainからこれを呼び出してあげるだけです。
wx.App()を使っているのはwxPythonのお決まりの書き方なので、よくわからなければおまじないだと思ってもらえれば。

このwxPythonのホットキーを用いる方法は実行中のプロンプトがフォアグラウンドになくても使えるので、キーボードショートカットを作成するのに向いています。 逆にほかのアプリを使用中にはこのキー入力がwxPythonに吸われてしまうため、Ctrl + CでコピーといったFrameに対する操作を実装するのには向いていないように思います。

キーボードショートカットを常駐させる

キーボードショートカットを作ったからには常にこのキーボードショートカットを使える状態にしておきたいです。
しかし、その目的を考えるとPythonコードは不向きです。
そこでPyinstallerを用いてPythonのコードをexe化します。
こうしてできたexeファイルをスタートアップに登録してあげることで、このキーボードショートカットを常駐させることができます。
ここでスタートアップに登録する際にexeファイルそのものではなく、そのショートカットを登録することで新しくキーボードショートカットを追加したいときもexe化まで行えばいいためお勧めです。

まとめ

今回はwxPythonを用いてキーボードショートカットを作成しました。 もとはといえば、Ctrl + Cでコピーを実装するべくググっていたら見つけた代物だったのですが、これはこれで必要としていたものだったので棚からぼたもちといったところです。 割と実用的なのでQiitaに書こうかとも思ったのですが、書いてるうちにポエムが長くなってしまったのでこっちに。

ぼくのPCに入っているアプリたち

新しくPCを購入したので、そのセットアップを進めつつ忘備録的に書いていきます。

今回買ったPCのステータス

本題に入る前に今回購入したPCのスペックを載せておきます。 僕の使用用途を考えると少しオーバースペックな気がしなくもないけど、とても快適なので満足

基本ツール系

Google Chrome

Adobe Acrobat Reader

Tablacus Explorer

VMware Horizon Client

  • お仕事用

ゲーム系

Steam

Minecraft

SNS

Discord

Slack

LINE

  • https://line.me/ja/
  • キーボード入力に慣れていると、スマホで文字を入力するのが億劫になりがちで入れてる
  • MSストアから入れるほうがめんどくさくない

プログラミング系

WSL2

VS Code

動画編集系

YMM4

  • ゆっくり実況を作るときに使うやつ
  • https://manjubox.net/ymm4/
  • VOICEROID実況を作るときも立ち絵の口パクとかに対応してるので便利

VOICEROID2

  • AMAZONでダウンロード版を買った
  • 大体そこで完結してるからいいけど、VOIEROID+からの移行ツールだけはAHS公式から拾ってこないといけない

余談

この記事を書いている頃にwingetの先行リリースとかがありました
ここに挙げたアプリもそこそこあったので、使うと便利かもしれない
この記事を書いてるときにはまだ未実装だったけど、wingetにアンインストールの機能が出来ればいいのなと思っている
Windowsに入れたアプリのアンインストール方法が非自明になりがちなので

テストケース自動生成のプログラムをどうやって管理しようかなって考えた話

今日はテストケースの自動生成とそれを用いたジャッジを自動で行ってくれるツールの作成を行っていました。

そこで考えてたこととかを書いておきます。

まず普段競プロをしている環境

OS:Windows10
IDEVisual studio 2019

以前まではテストケースを生成するプログラムを別のプロジェクトとしてVisual studioで作っていたんですが、そのテストしようと思ったらそこに毎回コピペしないといけないのが面倒だったんですよね

以前までのコードはこんな感じ

void make_testcase(){
    ifstream ifs("in.txt");
    //あれこれ
}

#define cin ifs
#define cout ofs
void solve(){
    ifstream ifs("in.txt");
    ofstream ofs("out.txt");
    //書いてたコードをコピペする
}
#undef cin
#undef cout

void solve_naive(){
    ofstream ofs("out_naive.txt")
    //愚直解を必要に応じて書く。WAになるケースを探したいときとかに使う。
}

void judge(){
    //out.txtとout_naive.txtの中身が等しいか判定する。
}

int main(){
    make_testcase();
    solve();
    solve_naive();
    judge();
}

毎回コードをコピペしないといけなのもそうですが、cinやcoutをdefineでファイル入出力に書き換えてる辺りとかかすごく気に入らなかったんですよね。
まぁ、あるコンテストの時間中に必要に駆られて急いで書いたものだったので…
それもあって今回新しく作ってみました。

一番の目的はコピペする作業をなくして、元ファイルを更新すればテストの方のプログラムも書き換わる状態にすることです。

まず考えたのはテストを書いてるファイルで元ファイルをincludeすることです。
Pythonとかだったらこの方法で出来そうだなという気持ちになります。

提出用プログラム.py

def solve():
    #提出用コードを書く

if __name__ == "__main__":
    solve()

テスト用プログラム.py

from 提出用プログラム import solve
#さっきのc++で書いたやつっぽいのを書く

ただ同じような感じではC++だと出来なさそうな気持ちになりました。(できるのかもしれないけど私には思いつかなかった…)
includeしちゃうと提出用プログラムに書いてあるmain関数が実行対象になってしまうので出来なさそうなんですよね
提出用のソースコードとしての要件を満たしつつ、テスト用にも使えるように提出用プログラムを書くのは大変そうなので今回は諦めました。

そこで今回はbashを使うことでこの問題を解決することを考えました。
Windows環境なのでバッチファイルを作ってもよかったんですが、いかんせんとっつきにくいところがあるので…
そういうちょっとしたことをやりたいとき、なにかと便利なWSL(Windows Subsystem for Linux)にお世話になろうと思います。

ここでちょっとWSLについて軽く説明。
といっても原理とかではなく今回採用するに至った理由などが中心。
使ってるディストリビューションによって細かい所は違う可能性がありますがその時はごめんなさい。私はUbuntuを使ってます。
まず1つ目の利点はWindows上のファイルに簡単にアクセスできることです。/mnt/c配下にCドライブがマウントされてるっぽいイメージでアクセスできます。(細かい仕組みはまだ理解できてません)
2つ目の利点はWindowsにインストールされたVScodeからWSL上のファイルを編集できる所です。Linuxを使うならVimなりEmacsなりを使えよという指摘ももっともなのですが、慣れ親しんだエディタを使えることは素晴らしいので…
ちなみにこの機能は比較的最近のものです。(私がWSLを入れた頃はまだなかった)
詳しくは「Remote WSL」とかでググってみてください。

では本題に戻って。
まずは実際に書いたbashファイルを見てもらうことにします。

#!/usr/bin/bash
g++ -O2 -o  submit.out "Windows上の提出用プログラムのディレクトリ"
g++ -o naive.out naive.cpp
g++ -o testcase.out testcase.cpp
./testcase.out > in.txt
time cat in.txt | ./submit.out > out.txt
cat in.txt | ./naive.out > out_naive.txt
./judge.out

パイプとかリダイレクトとかの存在は知っていましたが、使うのは初めてだったので面白かったです。
リダイレクトを使用することで標準出力をファイルに書き込むことが出来るので、それを使ってさっきまでの問題を解決することができました。
あとおまけで実行時間も測っています。(環境が全然違うので参考程度ですが)
こういう小技に凝るのが趣味なので、本当にやるべきことが一向に進まないのが最近の悩みです。
では今日はこの辺で

ABC162 D

問題文

RGB のみからなる、長さ N の文字列 S があります。

以下の 2 つの条件をともに満たす組 (i, j, k) (1i<j<kN) の数を求めてください。

  • SiSj かつ SiSk かつ SjSk である
  • jikj である

制約

  • 1N4000
  • S は RGB のみからなる、長さ N の文字列である

 

まず一つ目の条件を満たす組の数を考える。

これはSから順番を気にせずR,G,Bを一つずつ選び、左から(i,j,k)とした場合の数と等しいので(Rの数)×(Gの数)×(Bの数)と等しい。

次にj-i=k-jの点を全て調べ、一つ目の条件を満たしている組の数を引くと求めたい答えとなる。

 

ステップ1がO(N)、ステップ2がO(n^2)となり十分高速。

chunithm-location

こんにちは,ciderです
今日はchunithmのあるゲーセン一覧をgoogle mapから簡単にみられるものを作ったので紹介します

使い方

  1. まず下のリンクをクリックしますdrive.google.com
  2. するとgoogle mapなりgoogle driveなりが開き,chunithm-locationというマイマップがスマホに登録されます
    f:id:cider68760155:20200312183532p:plain
    クリック後の画面例
  3. 次回以降はgoogle mapの「保存済み→地図」から見ることが出来ます
    f:id:cider68760155:20200312183514p:plain
    マイマップの保存先

中身

申し訳程度の技術ブログ要素ww
ゲーセンの場所一覧はchunithmの公式サイトスクレイピングして持ってきます
あとはcsv形式にして,google mapに投げるだけの簡単なお仕事
google mapって便利だねぇww github.com

お問い合わせ

この内容に関するお問い合わせはこのブログにコメントしていただくか,TwitterGitHubからお願いします
質問,バグ報告,機能追加要望など,どんな些細なことでもいいのでコメントいただけるととても嬉しいです!

AGC033反省会

はい.

久々の0完太陽.

二時間半椅子を温める作業をしていました.

これじゃだめなので反省会を開催したいと思います.

 

まず,

問題を見た瞬間の「これはダメだ」感が強かった.

グリッド問題が苦手of苦手なので,NoSub撤退も最初から視野に入っていました.

じゃあなぜ,TLE解を提出してしまったのか.

それはグリッド問題がなぜ苦手なのかに関係してると思うんです.

それは「グリッド問題の計算量の見積もり方が分からない」ってことだったんです.

結局僕は「ソートはO(n log n)」みたいな計算量しか見積もれないってことだったんです.

だってdfsとかbfsの計算量ってよく分からなくないですか

そう思って蟻本を読みなおしてみると,どうやら同じ場所を二度探索しないように工夫することでO(HW)を達成しているようです.

で,今回の問題はどうすればO(HW)を達成できたのか.

僕にはdfsでもbfsでも解けるように見えました(実際どっちも書きました)

しかし訪れた場所は見ないような実装をしていたつもりなのになぜかTLEが出るし,それを頑張ろうとすると再帰での更新がバグってWAが出たりしました.

結局dfsやbfsの問題を避けてきたのが結果として表れたってだけなんですよね

じゃあこれを変えるためにはどうすればいいか

結局の所,精進をするしかないんですよね

問題を解いてbfsさんやdfsさんのお気持ちを理解してあげるしかないんです

ということでグリッド問題を解きまくりたいと思います.

とりあえずこの問題は絶対ACさせる.

ほかにもグリッド問題を探して解く.

なかなか気持ちがもたない気がするのでバチャしたいなぁ

おすすめのグリッド問題があれば教えて頂きたいです

 

これで水色になろうなんて本当に甘かったです.

僕は変わります

グリッド問題を得意問題にしてみせます