conビルドまとめ

sudo apt update
sudo apt install -y cmake python3-pip zlib1g-dev gcc-avr avr-libc
git clone https://github.com/abcminiuser/lufa

C:\Users[ユーザー名]\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu18.04onWindows_79rhkp1fndgsc\LocalState\rootfs\home

ubuntuのhomeディレクトリがある。

arduinoをインストールして、

C:\Program Files (x86)\Arduino\hardware\tools\avr\bin

をPATHに追加

これでavrdudeが使えるようになる。

C:\Program Files (x86)\Arduino\hardware\arduino\avr\bootloaders\gemma

にあるavrdude.conf をコピー

ubuntuホームから作業用ディレクトリに移動して

avrdude -c avrdude.conf -v -patmega32u4 -cavr109 -PCOM? -Uflash:w:Joystick.hex:i

で書きこむ

書き込み先ポートは環境によって違うので、調べ方を描く

技術書典7参加記録まとめました

収支

  • 支出
    • サークル参加費 7,000円
    • 印刷費 83,610円 
      • 日光企画様 オンデマ平閉じフルカラーA5 120Pの300冊
    • 移動費 2,000円くらい
    • 戦利品購入 31,000円
  • 収入
    • 1000円x157冊=157,000円
      • (かんたん後払いの手数料は計算に含んでいない)

収支合計+33,390円

サークルチェック数と印刷部数と頒布価格

techbookfest.org

サークルカットパワポで10分くらいで作りました。

f:id:yuji-dis:20190923112412p:plain

サークルチェック数の推移はこんな感じ。 最終値が175で、前回が160だったので少し上回りました。

入稿したのが9/17でその時点では74となっています。 大体前回と同じ推移であったため、150前後は出るという予想で200部にしようとしたのですが、300部と大して値段が変わらなかった(1.7万円位の差)だったので300部にしました。 余る見込みでBoothに投げ込めばいいや理論です。いっぱい刷ったほうがお得感強い。

印刷費で赤字になりたくないので、損益分岐点を100部として、頒布価格を1,000円にしました。 1500円だと貰いすぎで500円だと辛みがあったのでちょうどよかったと思います。 1000円もらって本を渡すだけでよかった今回はだいぶ楽だったかなと。

当日の様子

10時ごろ売り子兼ファンネルをお願いしていた会社のCTOと東池袋のセブンで合流

現地にいったらサークル入場待機列があってビビった

結局入場できたのが10時半ごろでそこから設営を開始

11時になりファンネルを飛ばして店番。 11時~13時が一番売れるスピード速かったです。 12時ごろに約3万円分の本をもったファンネルが帰ってきたので交代しつつ。 業務委託で常駐している会社のCTOを顎で使う技術書典7

11時~16時までずっと混んでたなという印象です。 (うちに来たとかそういう意味ではなく通路の人口密度的な)

17時ちょっと前にはさすがに人が減っていましたが、それでもかなりの数の人が残っていて、17時にほんとに終わるの?って感じでした。

反省点

  • 原稿
    • 7月ややニートだったのに全く原稿しなかったのは懲罰ものですよ…
    • 計測用コードの差し替えとかを行ったおかげでコード全体の差し替えと計測結果差し替えが必要になり、無駄に大変だった
    • 表紙やサークルカットはデザイナーに外注したいなと思う所さん
      • 写真にタイトル貼るだけって手抜きすぎない?
    • サークル名入れ忘れ(2回目
    • なんかぶち抜いてた 気を付けたはずなのに…

  • 入稿
    • gimpの編集形式(xcf)のまま表紙入稿した
    • psdに変換して再入校したらレイヤー統合してなかった
    • レイヤー統合して入稿した
    • 計3回も再入稿してやがる…
  • 設営
    • 通路から見ると何のサークルなのか全く分からなかった
      • ポスターで何のスペースか表示するのが重要
    • 自分で作ってきたpopのかんたん後払いQRコードが前回のものだった
    • 見本を7冊用意したので見本待ちが発生しなかったのはよかった
    • 立ち読みコーナーの本を回収するのを忘れていた
    • 黒字になってよかった

前回からの変更点

  • 本の大きさ
    • B5からA5に変えました(サイズダウン
      • 印刷費が半額程度になるので、サイズにこだわりなければA5一択です
  • ダウンロードカードの追加
    • ラクスル様で名刺サイズのダウンロードカードを発注しました
    • 600枚で3000円くらいでした安い。即日来ました早い。
    • 本に挟み込んで頒布しました。たまにDLCだけ買ってく人もいました。
  • 値段
    • 1500円から1000円に変えました。
    • 印刷費、頒布数の観点から狙い通りだったかなと思います。

技術書典7の雑感

  • 大なり小なり波はありますが、ずっと人がいる感じは前回と変わらないかなという感想です。
  • 2フロア制が良かったのかどうかは私の視点からは分かりません。
    • 散歩したときに2Fを見ただけで体力切れになって3Fに行けなかったので、そういう人がほかにもいるかもなあと思いました。
    • がっつり見れる人にとってはサークル数が増え、読みたい本が増える良い施策だったと思います。
      • ファンネルして貰った分は2Fと3Fに分かれていて、見たい本自体は前回より多い!ってなってました。
  • 立ち読みしてそのまま買っていってくださる方がたくさんいました。
    • 内容はつたないものになっていますが、興味を持って下さりとても励みになります。
  • あと払いアプリがやたらとログアウトしているように感じました。(売り子視点
  • 運営と参加者の皆様、ありがとうございました。

戦利品

文章、Vtuber機械学習数学、興味のあるプログラミング言語って感じの分布です。

最後に

300刷って150くらいしか出ていないので150くらい在庫がBoothに追加される予定です。 1週間くらいで在庫が生えてくるんじゃないかと思います。

電子版はすでに3部ほど購入いただいています。ありがとうございます。

↓この辺↓

parallel algorithmが使えるようになったと聞いてubuntu18.04(WSL)にgcc9.2.0とIntelTBBを導入

parallel algorithmが実装された!

GCC 9 Release Series — Changes, New Features, and Fixes - GNU Project - Free Software Foundation (FSF)

より

Runtime Library (libstdc++)
Improved support for C++17, including:
The C++17 implementation is no longer experimental.
Parallel algorithms and <execution> (requires Thread Building Blocks 2018 or newer).
<memory_resource>.
Using the types and functions in <filesystem> does not require linking with -lstdc++fs now.

並列アルゴリズムはこれまでintelコンパイラでしか使えなかったが、gccで使えるようになった!

結論

f:id:yuji-dis:20190826012938p:plain

ソートは、vectorが程度大きければ3倍程度に速くなる。(PCのコアは4つ)

gcc9.2.0のビルド

makeにすごく時間かかるので、時間があるときに行うこと。

$ wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-9.2.0/gcc-9.2.0.tar.gz
$ tar xvzf gcc-9.2.0.tar.gz
$ cd gcc-9.2.0
$ ./contrib/download_prerequisites
$ ./configure --enable-languages=c,c++ --prefix=/usr/local/lib/gcc-9.2.0 --disable-bootstrap --disable-multilib
$ make
$ make install

make installされたものを確認する。

$ /usr/local/lib/gcc-9.2.0/bin/gcc -v
Using built-in specs.
COLLECT_GCC=/usr/local/lib/gcc-9.2.0/bin/gcc
COLLECT_LTO_WRAPPER=/usr/local/lib/gcc-9.2.0/libexec/gcc/x86_64-pc-linux-gnu/9.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ./configure --enable-languages=c,c++ --prefix=/usr/local/lib/gcc-9.2.0 --disable-bootstrap --disable-multilib
Thread model: posix
gcc version 9.2.0 (GCC)


$ /usr/local/lib/gcc-9.2.0/bin/g++ -v

Using built-in specs.
COLLECT_GCC=/usr/local/lib/gcc-9.2.0/bin/g++
COLLECT_LTO_WRAPPER=/usr/local/lib/gcc-9.2.0/libexec/gcc/x86_64-pc-linux-gnu/9.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ./configure --enable-languages=c,c++ --prefix=/usr/local/lib/gcc-9.2.0 --disable-bootstrap --disable-multilib
Thread model: posix
gcc version 9.2.0 (GCC)

自分の場合は~/bin/を作って後入れのものはそこにシンボリックリンクを張るようにしている。 .bashrcで

export PATH=~/bin:$PATH

とかしてあればおk

$ ln -s /usr/local/lib/gcc-9.2.0/bin/g++ ~/bin/g++   
$ ln -s /usr/local/lib/gcc-9.2.0/bin/gcc ~/bin/gcc

リンクが生きているか確認。

~$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/local/lib/gcc-9.2.0/libexec/gcc/x86_64-pc-linux-gnu/9.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ./configure --enable-languages=c,c++ --prefix=/usr/local/lib/gcc-9.2.0 --disable-bootstrap --disable-multilib
Thread model: posix
gcc version 9.2.0 (GCC)
~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/lib/gcc-9.2.0/libexec/gcc/x86_64-pc-linux-gnu/9.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ./configure --enable-languages=c,c++ --prefix=/usr/local/lib/gcc-9.2.0 --disable-bootstrap --disable-multilib
Thread model: posix
gcc version 9.2.0 (GCC)

libの入れかえ。

$ ls -l /usr/local/lib/gcc-9.2.0/lib64/libstd*
-rw-r--r-- 1 root root 58776946 Aug 25 22:53 /usr/local/lib/gcc-9.2.0/lib64/libstdc++.a
-rwxr-xr-x 1 root root      979 Aug 25 22:53 /usr/local/lib/gcc-9.2.0/lib64/libstdc++.la
lrwxrwxrwx 1 root root       19 Aug 25 22:53 /usr/local/lib/gcc-9.2.0/lib64/libstdc++.so -> libstdc++.so.6.0.27
lrwxrwxrwx 1 root root       19 Aug 25 22:53 /usr/local/lib/gcc-9.2.0/lib64/libstdc++.so.6 -> libstdc++.so.6.0.27
-rwxr-xr-x 1 root root 22553280 Aug 25 22:53 /usr/local/lib/gcc-9.2.0/lib64/libstdc++.so.6.0.27
-rw-r--r-- 1 root root     2425 Aug 25 22:53 /usr/local/lib/gcc-9.2.0/lib64/libstdc++.so.6.0.27-gdb.py
-rw-r--r-- 1 root root 18290658 Aug 25 22:53 /usr/local/lib/gcc-9.2.0/lib64/libstdc++fs.a
-rwxr-xr-x 1 root root      919 Aug 25 22:53 /usr/local/lib/gcc-9.2.0/lib64/libstdc++fs.la

$ cd /usr/lib32/
## ここlib32なのはWSL上のUbuntuだからだと思うので、実環境に合わせて調整が必要
## 以下必要に応じてsudo
/usr/lib32$ sudo mv libstdc++.so.6 libstdc++.so.6.bak


/usr/lib32$ sudo ln -s libstdc++.so.6.0.27 libstdc++.so.6
/usr/lib32$ sudo cp /usr/local/lib/gcc-9.2.0/lib64/libstdc++.so.6.0.27 ./
/usr/lib32$ sudo ln -s libstdc++.so.6.0.27 libstdc++.so.6
/usr/lib32$ ls -l
total 24064
drwxr-xr-x 1 root root      512 Jun  2  2018 gconv
-rw-r--r-- 1 root root   116256 Apr 17  2018 libgcc_s.so.1
lrwxrwxrwx 1 root root       19 Aug 25 23:24 libstdc++.so.6 -> libstdc++.so.6.0.27
-rw-r--r-- 1 root root  1582060 Apr 17  2018 libstdc++.so.6.0.25
-rwxr-xr-x 1 root root 22553280 Aug 25 23:24 libstdc++.so.6.0.27
lrwxrwxrwx 1 root root       19 Apr 17  2018 libstdc++.so.6.bak -> libstdc++.so.6.0.25

intel TBBの導入

tbbのビルド

$ cd temp
$ git clone https://github.com/intel/tbb
$ cd tbb
$ make
$ cd build/linux_intel64_gcc_cc7.4.0_libc2.27_kernel4.4.0_release/
$ ls
arena.d                    frontend.d               proxy.d               task_v2.d
arena.o                    frontend.o               proxy.o               task_v2.o
backend.d                  governor.d               queuing_mutex.d       tbb.def
backend.o                  governor.o               queuing_mutex.o       tbb_function_replacement.d
backref.d                  itt_notify.d             queuing_rw_mutex.d    tbb_function_replacement.o
backref.o                  itt_notify.o             queuing_rw_mutex.o    tbb_main.d
cache_aligned_allocator.d  itt_notify_malloc.d      reader_writer_lock.d  tbb_main.o
cache_aligned_allocator.o  itt_notify_malloc.o      reader_writer_lock.o  tbb_misc.d
concurrent_hash_map.d      large_objects.d          recursive_mutex.d     tbb_misc.o
concurrent_hash_map.o      large_objects.o          recursive_mutex.o     tbb_misc_ex.d
concurrent_monitor.d       libtbb.so                rml_tbb.d             tbb_misc_ex.o
concurrent_monitor.o       libtbb.so.2              rml_tbb.o             tbb_statistics.d
concurrent_queue.d         libtbbmalloc.so          scheduler.d           tbb_statistics.o
concurrent_queue.o         libtbbmalloc.so.2        scheduler.o           tbb_thread.d
concurrent_queue_v2.d      libtbbmalloc_proxy.so    semaphore.d           tbb_thread.o
concurrent_queue_v2.o      libtbbmalloc_proxy.so.2  semaphore.o           tbbmalloc.d
concurrent_vector.d        market.d                 spin_mutex.d          tbbmalloc.def
concurrent_vector.o        market.o                 spin_mutex.o          tbbmalloc.o
concurrent_vector_v2.d     mutex.d                  spin_rw_mutex.d       tbbmallocproxy.def
concurrent_vector_v2.o     mutex.o                  spin_rw_mutex.o       tbbvars.csh
condition_variable.d       observer_proxy.d         spin_rw_mutex_v2.d    tbbvars.sh
condition_variable.o       observer_proxy.o         spin_rw_mutex_v2.o    version_string.ver
critical_section.d         pipeline.d               task.d                x86_rtm_rw_mutex.d
critical_section.o         pipeline.o               task.o                x86_rtm_rw_mutex.o
dynamic_link.d             private_server.d         task_group_context.d
dynamic_link.o             private_server.o         task_group_context.o

tbbのインスト―ル

$ cd /usr/lib/x86_64-linux-gnu
$ ls -l |grep tbb
lrwxrwxrwx 1 root root       11 Oct  4  2017 libtbb.so -> libtbb.so.2
-rw-r--r-- 1 root root   235056 Oct  4  2017 libtbb.so.2
lrwxrwxrwx 1 root root       17 Oct  4  2017 libtbbmalloc.so -> libtbbmalloc.so.2
-rw-r--r-- 1 root root   112120 Oct  4  2017 libtbbmalloc.so.2
lrwxrwxrwx 1 root root       23 Oct  4  2017 libtbbmalloc_proxy.so -> libtbbmalloc_proxy.so.2
-rw-r--r-- 1 root root    10368 Oct  4  2017 libtbbmalloc_proxy.so.2

$ sudo mv libtbb.so.2 libtbb.so.2.bak
$ sudo mv libtbbmalloc.so.2 libtbbmalloc.so.2.bak
$ sudo mv libtbbmalloc_proxy.so.2 libtbbmalloc_proxy.so.2.bak

$ sudo cp ~/temp/tbb/build/linux_intel64_gcc_cc7.4.0_libc2.27_kernel4.4.0_release/libtbb.so.2 ./
$ sudo cp ~/temp/tbb/build/linux_intel64_gcc_cc7.4.0_libc2.27_kernel4.4.0_release/libtbbmalloc.so.2 ./
$ sudo cp ~/temp/tbb/build/linux_intel64_gcc_cc7.4.0_libc2.27_kernel4.4.0_release/libtbbmalloc_proxy.so.2 ./

$ ls -l |grep tbb
lrwxrwxrwx 1 root root       11 Oct  4  2017 libtbb.so -> libtbb.so.2
-rwxr-xr-x 1 root root  2765432 Aug 26 00:43 libtbb.so.2
-rw-r--r-- 1 root root   235056 Oct  4  2017 libtbb.so.2.bak
lrwxrwxrwx 1 root root       17 Oct  4  2017 libtbbmalloc.so -> libtbbmalloc.so.2
-rwxr-xr-x 1 root root   856888 Aug 26 00:43 libtbbmalloc.so.2
-rw-r--r-- 1 root root   112120 Oct  4  2017 libtbbmalloc.so.2.bak
lrwxrwxrwx 1 root root       23 Oct  4  2017 libtbbmalloc_proxy.so -> libtbbmalloc_proxy.so.2
-rwxr-xr-x 1 root root    56768 Aug 26 00:43 libtbbmalloc_proxy.so.2
-rw-r--r-- 1 root root    10368 Oct  4  2017 libtbbmalloc_proxy.so.2.bak

$ cd /usr/include/tbb
$ sudo mv tbb tbb_bak
$ sudo cp -r ~/temp/tbb/include/tbb ./

parallel algorithm入りプログラムのコンパイル&run

とりあえずsortで見てみる。 ノーマル、seq, par, par_unseqの5つで確認

#include <algorithm>
#include <deque>
#include <execution>
#include <iostream>
#include <list>
#include <map>
#include <random>
#include <unordered_map>
#include <vector>

#include "../timer/timer_class.hpp"

// 10^7
const uint64_t vector_num = 1000 * 1000 * 10;

std::random_device seed_gen;
auto engine = std::mt19937_64(seed_gen());
auto int_rand = std::uniform_int_distribution<>(0, vector_num);

int main() {
  timer t;
  for (uint64_t size = 100; size <= vector_num; size *= 10) {
    std::cout << "===" << size << "=== " << std::endl;
    std::vector<int> vec;
    std::vector<int> vec_for_seq;
    std::vector<int> vec_for_par;
    std::vector<int> vec_for_par_unseq;

    // 中身が同じ4つのvectorを作る
    // memcpyとかでもおk
    for (size_t s = 0; s < size; ++s) {
      int r = int_rand(engine);
      vec.push_back(r);
      vec_for_seq.push_back(r);
      vec_for_par.push_back(r);
      vec_for_par_unseq.push_back(r);
    }

    t.restart();
    std::sort(vec.begin(), vec.end());

    t.print("vector_sort");
    t.restart();

    std::sort(std::execution::seq, vec_for_seq.begin(), vec_for_seq.end());

    t.print("vector_seq_sort");
    t.restart();

    std::sort(std::execution::par, vec_for_par.begin(), vec_for_par.end());

    t.print("vector_par_sort");
    t.restart();

    std::sort(std::execution::par_unseq, vec_for_par_unseq.begin(),
              vec_for_par_unseq.end());

    t.print("vector_par_unseq_sort");
  }
  return 0;
}

コンパイルのコマンド

$ g++ -std=c++17 -ltbb -O3 parallel_sort.cpp  

スペック

f:id:yuji-dis:20190826013403p:plain

ソートの計測時間 単位はns

vectorのsize 100 1000 10000 100000 1000000 10000000
vector_sort 3800 37600 472000 5823300 64813800 758304100
vector_seq_sort 3900 37200 463000 6000900 63663000 743859300
vector_par_sort 1398300 262200 252400 1904600 20200300 245639800
vector_par_unseq_sort 12700 30800 222400 1701900 19388900 239521300

f:id:yuji-dis:20190826012933p:plain

f:id:yuji-dis:20190826012938p:plain

サイズが小さいときのparがクソでかなので無視するとして…。 ある程度vectorのサイズが大きければ3分の1程度になる。

par_unseqの効果がほぼ無いので、sortでは意味ないかも。別アルゴリズムで確認したい。

という内容を技術書典で出す本に書きたい。

ほしいマンガ

魔法少女プリティ☆ベル

https://www.amazon.co.jp/kindle-dbs/product/B07FMK5Y28?redirect=true

マージナルオペレーション

https://www.amazon.co.jp/gp/product/B074C8KNPT?ref_=dbs_r_series&storeType=ebooks

嘘喰い

https://www.amazon.co.jp/gp/product/B074C4FVPB?ref_=dbs_r_series&storeType=ebooks

Pumpkin Scissors

https://www.amazon.co.jp/gp/product/B074C7Z618?ref_=dbs_r_series&storeType=ebooks

2度目の転職をします

まとめ

  • お気持ち整理用です。
  • 1度目の転職理由は給与でした。
  • 2度目の転職理由は体調と会社への不満からでした。
  • 8月からはフリーランスになります。
  • 最後に乞食リストがあります。

はじめに

退職エントリーみたいなものです。 2回目の転職になり、1回目書いてないのでまとめて書きました。

※ 会社名などの固有名詞は一切出てきません。

1社目

1社目は安い給料で大手企業で馬車馬する人身売買業者で働いていました。 残業代込で手取り20万円程度の給与でした。

大手企業さんは半導体関連の会社です。 そこでやれる仕事内容自体は結構おもしろく、得意なことを活かしたり、知らないことをたくさん学ぶことが出来ました。

得意なことでは、画像処理プログラムの作成・検証・実験・報告のプロセスを回したり。 知らないことでは、CCDカメラCMOSカメラの作成・光学系含めた性能評価系の構築、駆動系のハード・ソフトの両方を作成したりしました。

産業用カメラをあれこれ触ったり光学定盤で遊んだりは、今後の人生で体験できないのではないかと思います。 センサ、光学系という方向から画像処理を改めて考えることができた貴重な体験でした。

辞めたのは、仕事の内容と量に対して給与が安すぎるというだけです。 昇給額が3000円の世界にいるのはしんどいです。

仕事の内容は上でも触れたので割愛します。 仕事の量という観点では、一緒に仕事をしていたプロパーの社員と私がいろいろなものに首を突っ込みすぎて関わった人から仕事が大量に降ってくる状態になった というのがあります。 塗装材料と環境汚染について調べたりもしていて、何で我々こんな作業までやってるん・・・?っていう状態にまでなっていました。 朝メールソフトを立ち上げたら問い合わせの未読メールが20件とか溜まってるのはほんとにクソです。お前らいつまで働いてんだよ。

派遣元の人身売買業者への帰属意識?そんなの欠片も存在しません。

そんなこんなで転職しました。

2社目

受託開発屋さんに転職しました。 そこで会社に引きこもって受託開発していました。 家も引っ越していたので会社が近く通勤がすごく楽でした。 通勤時間は0秒まで削るべきそうすべき。

給与は源泉徴収を見る限り400万程度だったようです。 月の手取りは25万くらいだったかな。 年間の合計残業時間たぶん10時間程度なので、残業代はほぼ0ですね。

受託開発ですが、ほぼ一人で2並列に受けて仕事をこなしていました。 ざっくり書くと、

  • 装置との通信制御プログラムの作成/保守
  • ROS用プログラムの改造

みたいなこと年間通してやってました。

ほぼ1人プロジェクト故にかなりの裁量権があり、見積から開発、納品物の作成まで行っていました。 開発で使用する要素技術、プログラミング言語まで選ぶことが出来た状態です。 裁量権の大きさと1人プロジェクトのおかげで、スケジュール管理やタスク管理などを細かく行う必要がなく、 大きめの線表だけ作っておけばあとは自分の作業速度依存にできたのは大きなメリットでした。 短時間集中でざっくざっくと進めたので残業ほぼ0を達成という感じです。

私の手元に来た段階では、通信制御のプログラムがC#で書かれていたのですが、 マルチプラットフォーム化への要望が出てきた時にkotlinを選択して、 Windows,ubuntuandroid両方で使えるプログラムを組んだりしました。 検討段階ではJavaScript+chromiumの何かなども候補にあげて検討してって感じですね。 始めた段階ではkotlinってなんだよラブライブの新キャラか何かかよっと思っていましたが、 ある程度分かると書き心地のいい言語でした。 coroutineは未だに理解できてないですが。 非同期制御にしてしまうとそこがボトルネックになってしまうことがあったので最終的に使うのやめたという話も合ったり。

ROS用プログラムはそもそもROSってなんだよから始まったので、勉強から始まりました。 人の書いたプログラムを分析して問題点の分析と改造していくのは結構楽しい作業でした。 改造する際には発注元の人と議論したり、そも議論用の資料を作ったり、出来ること出来ないことを元に交渉したり…。 出力見る限りどっかどう見てもバグってるプログラムを「仕様どうり」って言い切っていたのでバグ取りしたり…。

退職理由は、体調面と会社への不満からです。

体調面では慢性的な偏頭痛になってしまいました。 それだけなら良かったのですが、職場がエアコンや冷蔵庫の音がすごく耳に響いてしまい、職場にいると頭痛が増長されてしまう状況でした。 仕事への集中もへったくれもない状態だったので、ノイズキャンセリングヘッドホンをつけて作業させてくれとお願いしましたが、 コミュニケーションの阻害になるからという理由から却下されました。 ただ、前述の通り私は1人プロジェクト状態だったので、そもそも誰かとコミュニケーションをとる必要性がありません。 実際に「おはようございます」と「おつかれさまでーす」って言って帰るくらいしか発声した記憶がないレベルです(打ち合わせ時はめっちゃ喋る)。 あ、slackはめっちゃ書いてました、イキリオタクかよ。そうだよ。 必要ならばヘッドホン外せば良いしそも喋らないしslackあるしコミュニケーションの阻害になるとは考えられないというメールを出したりしましたが、返信が返ってくることはありませんでした。

ちなみに偏頭痛には特効薬があったりします。 詳しくは脳神経外科とかにいってみてください。 私はカロナールマクサルトの併用でだいぶ抑えられるようになりました。

音に関連して、外線電話の存在が非常にストレスでした。 電話が鳴る、電話に出るだけで作業内容と集中力が消え飛びます。 電話も業務に関連することではなく営業の電話ばかりだったので、電話の存在意義が感じられませんでした。 証券会社と不動産会社と人材紹介会社の電話は須らくクソだし、必要ならこっちからアクションするからわざわざ電話してくんな。 また、電話にだれも出んわ状態はダメですね。偉い人が電話に出てはいけないって決まりはないと思うけど。 やめたら?電話置くの。どうせ出ないんだからいらないでしょ?

前述のとおり、受託案件を2つ並列でやっており、見積も自分でやっていたので金額も分かっていました。 私の給与は400万/年でした。 私が担当したプロジェクトの2018年の総売り上げは、その年俸の大体5~8倍の間ほどです。 厳密には計算してないのでブレ幅大きいですがたぶんそれくらいです。 遊ぶ金欲しさに仕事しているので、給与は会社に対する重要な評価指標になります。 稼いだ額に対して相応の報酬がもらえていないというのが正直な感想です。 言葉で評価しているとか言われても金額に表れてこないんだったらその会社にいる意味はないです。 現場からは以上です。

他にも退職理由はありますが、ただの個人攻撃になってしまうので割愛します。

これから

8月以降はフリーランスで業務委託で働きます。 最初は普通にどこかの企業に転職しようと考えていたのですが、 ~口車にうまく乗せられて~ 業務委託で働いてみないかとお誘い頂いたので、いっちょやってみるかとなりました。

実際のところ働き始めて5年くらいになりますが、派遣/請負開発ばかりで自社製品というものを提供する立場になかったりすることもあり、 所属企業への帰属意識っていうものが1ミリも生まれてきませんでした。 面接の時の言葉を借りると、自社製品(サービス)への愛というものを持つことができていません。 今回サービスのための開発をするという認識でいるため、この辺りに自覚ができるようになったらいいなという思いです。

ダメだったらスキルツリー適当にいじって汎用性を上げていきます。

宣伝?

次の次の仕事

ただのリスクヘッジです。 もし上の地雷臭漂う文章を読んでも「youうちで働きなyo」って会社様がいらっしゃいましたらお声がけいただければと思います。 次の節にtwitterリンク置いとくのでDMとかください。前に作った業務経歴書などお渡しします。

8-10月は業務委託でお仕事いただいています。

11月以降は空白です。 8-10月の会社様から継続でお仕事頂けるかもしれないし、頂けないかもしれません。 継続してお仕事頂けるなら継続したいという気持ちがあります。

技術書典

技術書典出るんですがボッチなので一緒に出展する人を今でも募集しています。。。 あそこに1人でいるのは体力的に辛い。

おわりに

乞食リスト

本と雑貨

https://www.amazon.jp/hz/wishlist/ls/5PCUZH7Q1556?ref_=wl_share

たべもの

https://www.amazon.jp/hz/wishlist/ls/25CUR3XQ9OEYT?ref_=wl_share

フリーランスになるメモ

  • 開業

税務署に改行届を出す。

事業の開始等の事実があった日から1月以内に提出してください。
なお、提出期限が土・日曜日・祝日等に当たる場合は、これらの日の翌日が期限となります。

だから、フリーランスになった月の頭に行うようにする。 廃業も同様に。

www.nta.go.jp

  • 保険

協会けんぽの手続きは、協会けんぽ支部へ行って手続きする。 郵送でもいいらしい。

ハンコは不要だった。扶養者がいる場合は、扶養者のマイナンバーが必要。 本人だけの場合はマイナンバー不要だった。

www.kyoukaikenpo.or.jp

スケジュール感は以下のように。

7/31退職→8/1資格喪失、会社が手続き→年金事務所(?)で手続き1週間→協会けんぽで手続き+発行で1週間

就職時は資格喪失届を出す。(郵送でおk)

毎月支払いの場合は月末に支払い所が郵送されてくる→翌月の10日までに支払いを行う

支払いしなかった場合は自動的に資格喪失となる。

*国民年金の手続き

第二種被保険者(会社員)から第一種被保険者(フリーランス、学生など)に変わったので、年金手続きが必要。

市役所に行って手続きをする。 離職票などの厚生年金の資格喪失を証明できる書類が必要。

第二種被保険者(会社員)から第一種被保険者(フリーランス、学生など)に変わったので、変更手続きが必要。 SBI証券から手続き用の書類を送ってもらって、記入して返送する。

拠出金額も変更できる。 第二種被保険者の場合は最大23,000円だが、第一種被保険者の場合は(月6.8万-国民年金の支払い額)が最大拠出金額になる。

大体5.1万円くらいだったので5.1万円で記入して返送した。

Atcorder ABC132 F-Small Products

リンク

まとめ

  • dpで解ける問題
  • 単純なdpだとテーブルが爆発する
  • 数が少ない時は良いが、大きい数に対応するためにも工夫が必要

問題

K個の整数をならべて、隣り合う整数同士を書けた結果がNを下回るような整数列の数を数える。

例えば K=2,N=3のとき

{1,1},{2,1},{3,1},{1,2},{1,3}で5個

方針

dp[i][j]で"i+2"が"並べた整数の個数"、"j"が"今注目している整数に対して何個の整数列ができるか+それまでの合計値"として組む。

#include <iostream>
#include <vector>

int main() {
  int n, k;
  std::cin >> n >> k;

  --k;
  int size = n + 1;
  std::vector<int64_t> dp(size * k);

  for (int64_t i = 0; i < k; ++i) {
    dp[i * size + 0] = 0;
    for (int64_t j = 1; j < size; ++j) {
      int64_t &now = dp[i * size + j];
      const int64_t &left = dp[i * size + j - 1];
      if (i == 0) {
        now = n / j + left;
      } else {
        now = dp[(i - 1) * size + n / j] + left;
      }
    }
  }

  std::cout << *(dp.end() - 1) << std::endl;

  printf("     |");
  for (int j = 0; j < size; ++j) {
    printf("%5d", j);
  }
  std::cout << "\n----------------------\n";
  for (int i = 0; i < k; ++i) {
    printf("%5d|", i + 2);
    for (int j = 0; j < size; ++j) {
      printf("%5d", dp[i * size + j]);
    }
    std::cout << std::endl;
  }

  return 0;
}

実行結果

input 3 2 output 5 => OK

$ ./a.out 
3 2
5
     |    0    1    2    3
----------------------
    2|    0    3    4    5

input 10 3 output 147 => OK

10 3
147
     |    0    1    2    3    4    5    6    7    8    9   10
----------------------
    2|    0   10   15   18   20   22   23   24   25   26   27
    3|    0   27   49   67   82   97  107  117  127  137  147

分析

input 10 3の時を分析する。 dpがどのように変化しているかはテーブル参照。

整数を2つ並べた時に注目する。

     |    0    1    2    3    4    5    6    7    8    9   10
----------------------
    2|    0   10   15   18   20   22   23   24   25   26   27

今回の値が0だった場合は、何をかけても0にしかならないため、整数列は1つも存在しない。

今回の値が1だった場合は、1,2,3,4,5,6,7,8,9,10のどれをかけても良いため、10個の候補が存在する。

今回の値が2だった場合は、1,2,3,4,5のどれをかけても良いため、5個の候補が存在する。 1だった場合のところに加算して、合計15個の候補が存在する。

これを10まで繰り返すことで2つの整数に関して何個の候補があるかを調べることができる。

ここに3つ目の整数を追加しよう

     |    0    1    2    3    4    5    6    7    8    9   10
----------------------
    2|    0   10   15   18   20   22   23   24   25   26   27
    3|    0   27   49   67   82   97  107  117  127  137  147

今回の値が0だった場合は、何をかけても0にしかならないため、整数列は1つも存在しない。

今回の値が1だった場合は、[x y 1]という整数列になる。 yの値は1\~10だったらなんでもいい。 yが1だった場合はxが1\~10まで。 yが2だった場合はxが1\~5まで。 …

そのため[x y 1]のときに作れる整数列はyを1\~10まで試した時の合計値になる。 今回は合算しているので列の長さ2、値10の時の27を見ればいいことになる。

今回の値が2だった場合も同様に考える。 [x y 2] と並んでいて、yに1\~5の値が入る。 そのため列の長さ2、値5の時の22になる。 1の時に合算して49だ。

問題点と改善

一番の問題点は、nの値が大きいとメモリ確保でコケることだ。

  int n, k;
  std::cin >> n >> k;

  --k;
  int size = n + 1;
  std::vector<int64_t> dp(size * k);

入力例3を入れると一発でわかる。

$ ./a.out 
314159265 35
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
中止 (コアダンプ)

Kは100までになっているのでN方向のdpをなんとかしたい。

テーブルから増加幅を確認してみる。

// input 10 3
----------------------
    2|   10    5    3    2    2    1    1    1    1    1
    3|   27   22   18   15   15   10   10   10   10   10

列の長さ2の場合、6\~10が常に1になっている。 列の長さ3の場合、6\~10が常に10になっている。 int(10/6) == int(10/10)は同じになるため、目標値に対する商が同じときは合体させることができそうだ。 この関係はint(10/4) == int(10/5)でも同じことがいえる。

圧縮の方針は、

  • int(N/a) == int(N/b)となるa,bをまとめ上げる
  • そのときの個数を数えておく
  • 数え上げのタイミングで"今回の値で作れる整数列”×"今回の値に圧縮されている数"を積み上げていくようにする。
#include <iostream>
#include <vector>

const int64_t MOD = 1000 * 1000 * 1000 + 7;

int main() {
  int64_t n, k;
  std::cin >> n >> k;

  std::vector<int64_t> cand;
  std::vector<int64_t> num;
  cand.push_back(0);
  num.push_back(0);

  for (int64_t i = 1;;) {
    auto div = n / i;
    cand.push_back(div);
    auto next = n / div + 1;
    num.push_back(next - i);
    i = next;
    if (div == 1) {
      break;
    }
  }

  --k;
  auto size = cand.size();
  std::vector<int64_t> dp(size * k);

  dp[0] = 0;
  for (int64_t j = 1; j < size; ++j) {
    int64_t &now = dp[j];
    const int64_t &left = dp[j - 1];
    now = ((cand[j] * num[j]) % MOD + left) % MOD;
  }

  for (int64_t i = 1; i < k; ++i) {
    dp[i * size + 0] = 0;
    for (int64_t j = 1; j < size; ++j) {
      int64_t &now = dp[i * size + j];
      const int64_t &val = dp[i * size - j];
      const int64_t &left = dp[i * size + j - 1];

      now = ((val * num[j]) % MOD + left) % MOD;
    }
  }

  std::cout << *(dp.end() - 1) << std::endl;

  printf("     |");
  for (int j = 0; j < size; ++j) {
    printf("%5d", j);
  }
  std::cout << "\n----------------------\n";
  for (int i = 0; i < k; ++i) {
    printf("%5d|", i + 2);
    for (int j = 0; j < size; ++j) {
      printf("%5d", dp[i * size + j]);
    }
    std::cout << std::endl;
  }

  return 0;
}

というわけでこのプログラム(の最後のテーブル出力部分を消して)を提出してAC。

10 3の場合で確認しておく。 input 10 3 output 147 => ok

10 3
147
     |    0    1    2    3    4    5
----------------------
    2|    0   10   15   18   22   27
    3|    0   27   49   67   97  147

初期化回りは大きく変更している。

ここで同じ商になる値を探りつつ、その時作れる整数列と重ねることができる値の数を求めている。 こんな変な計算しなくても出せる気がしている。

  for (int64_t i = 1;;) {
    auto div = n / i;
    cand.push_back(div);
    auto next = n / div + 1;
    num.push_back(next - i);
    i = next;
    if (div == 1) {
      break;
    }
  }

ここは1列目(つまり整数が2個の時)の初期化になる。 上の計算のついでに行ってしまえばいいという話もある。

  dp[0] = 0;
  for (int64_t j = 1; j < size; ++j) {
    int64_t &now = dp[j];
    const int64_t &left = dp[j - 1];
    now = ((cand[j] * num[j]) % MOD + left) % MOD;
  }

2列目(3個の整数の列)以降はひたすら合算していく。 valで参照しているのがひとつ前の列の、"今の値に対して何個の整数列が作れるか"になる。 それを条件が重なっている数分掛け算してどんどこ足していく。

  for (int64_t i = 1; i < k; ++i) {
    dp[i * size + 0] = 0;
    for (int64_t j = 1; j < size; ++j) {
      int64_t &now = dp[i * size + j];
      const int64_t &val = dp[i * size - j];
      const int64_t &left = dp[i * size + j - 1];

      now = ((val * num[j]) % MOD + left) % MOD;
    }
  }

もし例3を実行するなら最後のテーブル出力のところは消してから実行したほうがいい。(一敗

numの列とdpが2列あれば計算できるのでメモリはもっと節約できる。