ちゃっくのメモ帳

ちゃっくがメモしときたいことをメモしとくよ

2ヶ月間毎週有給を入れた

今年中に使う必要のある有給があったので、11月12月は毎週有給を入れた。
月火木金のどこかを休みにしていき、水曜日は個人的に仕事がしやすい日なので有給を使わないようにした。

11月から始めたので1.5ヶ月くらいやってみたけど、正直幸福度は高くなかった。
中途半端に週の途中に休みを入れても「明日から仕事か...」ってなるなる曜日が月曜日に加えて1日増えるだけだったし、「明日仕事あるしあんまり遠くに行けないな」とか考えてしまい、結局昼くらいまで寝てしまい、日曜日の再生産って感じだった。

金曜日に有給を取ると、「明日は土曜日だし活動するか」という意気込みを持って川越に行ってみたり、筑波山に行ったりすることができたし、土曜日になっても「まだ土曜日!?」となることができてそれなりに幸福度が高かった。
一方で、月曜日の有給はあまり幸福度が高くなかった。なんでだろう。3連休にするといいというわけではないらしい。日曜日に「明日も休みだ」という安心感?は得られるが、金曜有給にした後の土曜日ほどの幸福感は無かった。もしかしたら「この後4日働かないと」みたいな気持ちになるからかもしれない。
木曜日の有給は最悪だった。今後、特に理由がない限り木曜日に1日だけ有給をとるということは二度とないと思う。虚無にしたのは完全に自己責任だけど。
火曜日は来週とっているが、まだ火曜日にとったことがないのでわからない。ただ、木曜日に近い感じになりそうかなと思っている。

結論として有給は金曜日に取るか、もしくはもっと連続してとった方が良さそうだなと思った。

とりあえず、夕方まで睡眠するのをやめたい。

actix-webのRequest HandlerでHTTPリクエストを送りたかった

TL; DR

use actix_web::client::Client
actix_web::client::Client - Rust

何があったか

リクエストハンドラの中でHTTPリクエストを送りたいということは珍しいことではない。例えば、APIを叩いた時に、APIサーバが別のAPIを叩いたりする場合がある。
これをactix-web(v3)でやりたかった。
Rustに詳しくないので、とりあえずググって出てきたreqwestを使えばいいのだろうという判断を下し、ハンドラの中からreqwestを使ってみた。
しかし、実際にこれを実装すると"thread 'actix-rt:worker:0' panicked at 'there is no reactor running, must be called from the context of a Tokio 1.x runtime'"というエラーとともにpanicをした。Tokio 1.x系のランタイムから呼ばれないと行けないらしい。
あれ、actix-webってtokio-coreを使ってるから大丈夫なのでは...とか思ったが、Cargo.lockをみるとactix-rtはtokio 0.2.24に依存している。
試しにtokio 1.xをdependencyに入れてもactix-rtがtokio 1.xを使ってくれるわけでもなさそうなので困った。reqwestのバージョンを下げればいいかもしれない?
後学のために、ここをうまく解消する方法を知っている人がいたらぜひコメントもしくはTwitterで教えてください。

では、とりあえずタイトルのactix-webのRequest HandlerからHTTPリクエストを送る方法がないのかといわれたら、そんなことはなく、そもそもreqwestを使うという発想が間違っており、actix_web::client::Clientを使えば良かった。この使い方はドキュメントをみてください。

未経験からエンジニアになって9ヶ月経ちました。

これは IQ1 Advent Calender 2020の25日目の記事です。
adventar.org

書きたかったもの。
なんかこう、あざとく炎上する記事ってあるじゃないですか。個人的に好きだった炎上エントリは、見つからなかったんですがQiitaにあった「コンパイルはいらない。コンパイルがなくても型検査できる。」みたいな記事で実態は動的に見ているみたいなやつです。(すみません、見たのが結構昔なので結構忘れてしまいました)。あんな感じの記事を書きたかったのです。しかし、思いつきませんでした。完全にIQが1です。


代わりに今年の振り返りでもしておきます。

はじめたもの

4月からエンジニアをはじめました。未経験からエンジニアってやつです。
就職活動をしている時は「リモートワークのない会社の方がいいかな」って思いながら就職活動をしていました。実際にリモートワークをしたらリモートワークはあった方がいいなって思いました。一番大きな理由は通勤がないことです。毎日往復1~1.5時間って結構大きいです。1日の4~6%を通勤に使いたくないなぁと思うようになりました(実際起きている時間に対しては5~8%くらいになりそう)。あと、自分は広い場所で集中するのがかなり苦手です。意識が散ります。そのため、実際に出社して仕事したことは何回かあるのですがちょっと仕事がしにくかったです。まぁ毎日やっていれば慣れる気もしますが。


9月からオンライン英会話をはじめました。
福利厚生にあったので暇つぶしに登録してみました。感想としては英会話を学んでいるというより、英語で人間の会話を学んでいると言った方が適切な気がしています。
大体月に20~25回くらいやっています。多分リモートワークじゃなかったら切り捨てる最初のものです。割と毎日30分というのは負担です。
人間の会話には定番テーマがあるみたいです。自分は天気の話題が定番とは知っていましたが、他にも映画やドラマ、食べ物、服などがあるようです。
特に世界中がパンデミックNetflixAmazon Prime Videoを契約した人が増えたようで知らない講師とも映画やドラマの話題はそれなりに通じます。それなりの講師と会話した感じだとウォーキングデッドはかなり通じます。見ておいてよかったです。


9月には他にもジムに通うようになりました。
こちらも福利厚生を使うと半額くらいになったので週1~2くらいで行っています。
なかなか筋肉がつかないです。最近はジムの後にザバスを買って飲むようになりました。この影響かはわかりませんが、腕には少し筋肉がつきました。
ザバスはバニラ、バナナ、ココア味を試して、バニラが一番美味しい気がしています。バナナ、ココアは3口くらいまでは美味しいんですがなんかそのあとにめちゃくちゃ後味が悪く感じます。その点、バニラは初めから甘すぎて後味とかよくわかりません。


あとは10数年ぶりに登山を3回しました。 ヤマノススメを読んだり@nishino_hirokiに誘われたりして行きました。
小さい頃はそんなに楽しいと思わなかったのですが、今行くとかなり楽しいです。いつも家にこもってるのもあるかもしれません。
登山靴は買ったので、次はザックが欲しいです。(山用品、基本的に高い...)

買ったもの

  • クーラー
    • 壊れました
  • Switchのコントローラー
    • 妹がSwitchを買っていたのでたまに借りています。コントローラーくらい自分で書いました。えらい。
  • 登山靴
    • 山オタクに勧められました。普段そんなに高い九つは買っていないので靴にしては高いな〜って思ったりしていました。
  • Chromebook
    • 2 in 1を試してみたかったのと安かったので買ってみました。性能についてはweb閲覧くらいなら困らないですね。
    • ただ、ちょっと思ったよりも重かったです。
  • mac mini
    • ふとM1がほしい気がしたので書いました。90度回転したディスプレイで解像度がバグるので直して欲しいです。

その他コメント

今年を振り返ると、ほとんど労働していた気がするんですが、働き出したのは4月なんですよね。3月は旅行に行ったりしていた記憶がありますが、ずいぶん懐かしく感じます。記憶が正しければ2月くらいからなんかコロナの雲行きは怪しくなっていましたが、3月中旬くらいまではここまで悲壮感はなかった気がします。

今日はGoのdeferでバグらせた

Goには実行を遅延させるdeferキーワードがある。
これを使ってバグらせた。

例として次のようなコードを書いたとする。
このコードを実行すると、invalid memory address or nil pointer dereferenceでpanicする。
これくらいシンプルなコードだとわかりやすいが、panicのエラーはreturn文のところを指すので、もう少し複雑なコードになるとちょっとエラーを追跡しにくい.....

func f() string {
	var g func()
	defer g()

	g = func() {
		println("Hello")
	}

	return "World"
}

func main() {
	println(f())
}

Tour of Goのdeferの説明には次のように書いてある。

The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.

これを、「引数の評価は即座に行われ、関数の呼び出しはreturn時に行われる」という解釈を誤っていた。
呼び出す関数の決定も実行時に遅延されると間違えていた。

Goのreference manualを見ると次のように書いてある。
The Go Programming Language Specification - The Go Programming Language

Each time a "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.

If a deferred function value evaluates to nil, execution panics when the function is invoked, not when the "defer" statement is executed.

実際はdefer statementが記述された地点で呼び出す関数の決定も行われ、実行だけが遅延されるらしい。

次のようなコードを書くとその挙動を確認できると思う。

func f() string {
	var g func()

	g = func() {
		println("Hello1")
	}

	defer g()

	g = func() {
		println("Hello2")
	}

	return "World"
}

func main() {
	println(f())
}
// Hello1
// World
// と出力される

まぁ、後から振り返ってみると遅延して実行される関数がdefer statementとして記述された時点と違う実装が呼び出されたら、もうその関数を遅延して実行したとは言い難い気がするし、かなり扱いにくいものになっていただろうからこの挙動は納得がいく。

お仕事終わった後の趣味プログラミングくらいバグらせないでスカッと書きたい.....

CpawCTF始めたっぽい

唐突に気が向いてCTFしてみたくなった。
Cpawが初心者にちょうどよいらしいのでやってみることにしたので土日でやってみた。なぜかchakkuが登録されていて登録できなかった。

とりあえずLevel2まで埋めることにした。出来ていないのは[Recon]Who am I?と[Reversing]reversing easy!ってやつ。

Who am IはとりあえずTwitterで「from:porisuteru スペシャルフォース2」を検索してみたけどなにもでなかった。

reversing easyはobjdumpで逆アセンブルした。movlが幾つも並んでる箇所があったので多分それが答えの気がするけど文字に直すのがめんどくさくて放置。もうすこし簡単な方法あるのかな....gdbとかで見たほうが良いのだろうか。strings | grep cpawするとそれっぽい答えが出てるけど、どこが終端かはっきり判断する決め手がなくて気持ち悪いので解けてないことにする。


Level2くらいまでだと何も知らなくても割となんとかなるっぽい。

k-bitのXORを取ると2^k-1になるような2つの非負整数から2^0~2^kの奇数を作れる

k-bitの整数を考える。
 a \oplus b = 2^k-1を満たすような2つのk-bitの整数a,b( a\geq b)の組を考える。
全ての組について考えた時、この2つの整数a,bから、 a-b [2^0,2^k]の範囲の全ての奇数を作ることができる。

具体例

例えば3-bitの場合を考える。
このとき、a,bのペアとして次のものが考えられる。
(b111,b000), (b110, b001), (b101, b010), (b100, b011)
そのため、
 b111-b000 = 7(b111)
 b110-b001 = 5(b101)
 b101-b010 = 3(b011)
 b100-b011 = 1(b001)
と、 [2^0,2^3]の奇数を全て作ることが出来ている。

証明(かなり厳密性がない気がする)

これは多分、帰納的に示すとよい。(構成的に示したかったが上手く構成出来なかった。)

まず、1-bitの時を考える。
このとき、(a,b)の組として考えられるのは(1,0)で、1-0=1より[2^0, 2^1]の範囲の奇数を作ることが出来ている。

次に、k-bitの場合に上の命題が成立するとする。
この時、k+1 bitの場合について考える。
 [2^0, 2^{k+1}]の範囲にある奇数は、 [2^0, 2^{k}]の奇数の先頭に0を付けたものと、1を付けたものから構成される。(たとえば、3-bitの場合は2-bitの\{b00,b01,b10,b11\}の先頭に0を付けたもの\{b000,b001,b010,b011\}と先頭に1をつけたもの \{b100,b101,b110,b111\}で構成される)

先頭に1をつけたものについては、k-bitのときの(a,b)の組のaの先頭に1を,bの先頭に0つけると構成できる。この構成により \
[2^k+1, 2^{k+1}]の範囲の奇数を全て生成することができる。
(例えば、2-bitの場合のa,bの組 (b10,b01)に対して、3-bitの (b110,b001)を作ると2-bitの2-1=1から3-bitでは6-1=5を作ることができる。)
これは筆算を使うとイメージしやすい。


先頭に0をつけたものについては、k-bitのときの(a,b)の組のbの先頭に1を引いたものをk+1bitのときのaとして、k-bitのときの(a,b)の組のaの先頭に0を付けたものをk+1bitのときのbとすれば、 [2^0, 2^k]の範囲の奇数を構成できる。
(例えば、2-bitの場合のa,b,の組み (b10,b01)に対して、3-bitの (b101,b010)を作ると2-1=1から5-2=3を作ることができる。)

イメージとしてはこんな感じ。
f:id:chakku000:20200705030316j:plain

コメント

証明はなんであの構成でいいのかを真面目に示してない。示すのがめんどくさくなってしまった。
間違いがあったら教えてください。
そもそも命題があんまり直感的じゃない気がするんだけど、なにかポイントに気がついたらかなり直感的な気がする。
なんか見逃してそうなので誰か教えてほしい....

そもそも、なんでこれを示そうかと思ったかというと元ネタはこれです。この解説を見ているときに気になりました。
atcoder.jp