復活のCHRISTMA

この記事はクリスマスワンナイトハッカソン2021の作品紹介記事です

やったこと

二年前のワンナイトハッカソンフレキシブル基板達が作っていた素晴らしい言語『CHRISTMA』のソースコードLLVM IRに変換するやつを作った

qiita.com

IRというのは中間表現で、他の言語からLLVM IRに変換するプログラムを「LLVMのフロントエンド」って言うらしい(あってる?)

やりかた

  1. BrainfuckWikipediaを読む
  2. 各命令をC言語に脳内変換して書く
  3. ↑のプログラムをLLVM IRにコンパイルする(clangを使った。最適化オプションに注意)
  4. 気合と集合知の力でBrainfuckLLVM IRのコンパイラを書く

既存のコンパイラに小さな入力を食わせて出てきたものを見てコンパイラを書く、みたいなのはCコンパイラを作ったときにもやった気がする
調べると全く同じことをやっている記事がQiitaにあったけど見なかったことにした
見たら負けな気がする

最終的には世界に挨拶できるくらいにはなった(他のことを試していない)
挨拶って大事だと思う

できたもの

これを

mainファイルの中のCHRISTMAプログラム(ヒアドキュメント)

こうして

出力される.llファイル

こう

実行結果

ソースコードはここ

github.com

おわりに

これで私もフロントエンドエンジニア。

懐も寒い冬はチタタプしろ【茨城高専アドカレ2021】

この記事は茨城高専アドベントカレンダー2021の4日の記事です

茨城高専アドベントカレンダー2021 Advent Calendar 2021 - Adventar

 

一晩で食い切れる鍋を作ろうと思う

買い出し

f:id:kantarow:20211203174840j:image

f:id:kantarow:20211203174846j:image

これだけ

財布に優しいメニューです

やる

白菜とネギを切り、ネギは簡単みじん切りマシーンに突っ込む

f:id:kantarow:20211203184508j:image

こうなる

f:id:kantarow:20211203184610j:image

余計なものも買ってきたので切る

f:id:kantarow:20211203184625j:image

盛る

f:id:kantarow:20211203184721j:image

鶏肉は皮を外して細かく刻む

f:id:kantarow:20211203184753j:image

包丁で叩く。杉本、チタタプって言え。

f:id:kantarow:20211203184801j:image

チタタプした胸肉とネギと生姜と醤油と塩をボウルに入れて混ぜる

f:id:kantarow:20211203184917j:image

f:id:kantarow:20211203184921j:image

こいつをこねて丸くして、白菜の硬い方を敷き詰めた鍋に乗せる

f:id:kantarow:20211203184958j:image

この上に白菜の葉をふわっと乗せて料理酒を少し入れて蓋して蒸す。

白菜からは結構水分が出てくる。

味付けは丸鶏がらスープと塩。

外した鶏の皮は焼いて食う

f:id:kantarow:20211203185003j:image

うまい。

カツオも減ってきた

ネギが足りないのでわさびを投入

f:id:kantarow:20211203185130j:image

うまい。

夏になると生のカツオが並ぶので、柵で買って漬けにするのがすき。

臭みとりのために湯にくぐらせたりもするけど、見た目がたたきっぽくなる。たたきってフライパンでもできるんだろうか

 

そうこう言ってる間に鍋ができてた

f:id:kantarow:20211203190722j:image

胡椒を振って食べる

f:id:kantarow:20211203190748j:image

白菜の味が前面に出ててうまい。

味付けはそんなにしっかりやらなくていいと思う。

おわり。

 

【授業メモ】閲覧専用のエディタに挿入機能をつける

情報工学実験という科目で、kilovという意図的に機能が削られたエディタに機能を追加する演習をやっている。
kilovはkiloというC言語で書かれたエディタをいじったものなので、完全なソースコードGitHubで見ることもできる。
このブログに載せているコードが正しいかどうかはわからない。

github.com

やる

kilovは、editorConfigという構造体にerowという行を表す構造体の配列を持たせているため、こいつを編集して画面を更新してやるという流れになる。
この演習でメインループをいじる必要は無い。

ざっとコードを眺めると、キー入力を受け取って各種処理につなげているeditorProcessKeypressという関数が見つかる。
こいつの中にあるswitch文が、特殊な制御の入力以外はdefault節からそのままの値を返していることがわかる。
このままでは何も起こらずメインループが次に進むので、このdefault節から文字を挿入する関数を呼んであげればいい。
命名は既存の関数に倣って、editorInsertCharacterとかにしておく。

まずは現在のカーソル位置から行のデータを取る。

erow row = E.row[E.rowoff + E.cy];

rowoffは行のオフセット、cyはカーソルが何行にあるかを表している。
最初はrowoffを足し忘れて、普通に動いているように見えるがカーソルが下に行って画面が動くと挙動がおかしくなる不具合が出た。そいういうことに気付けるので、デバッグ時は大きめのファイルを開いてみることをおすすめする。僕はいつもkilov.cを開いてる。

行が取れたので、こいつが持っているcharsをいじっていく。
方針としては、charsreallocで拡張し、必要に応じて文字列を配列の後方に1文字ぶん移動させ、入力文字を格納してやる。
文字列の移動は、挿入箇所が行の末尾である場合のみ不要になる。

適当に書くとこんな感じ。

int filecol = E.coloff + E.cx;
int filerow = E.rowoff + E.cy;

row.chars = realloc(row.chars, sizeof(char)*(row.size+2));

if (filecol == row.size) {
  row.chars[row.size+1] = '\0';
} else {
  memmove(row.chars+filecol+1, row.chars+filecol, row.size-filecol+1);
}

row.chars[filecol] = c;
editorUpdateRow(&row);
E.dirty++;

元のサイズ+2でreallocしているのはヌル終端を入れるため。
行を変更したあとはeditorUpdateRowを呼び出している。こいつがcharsを元にrenderという表示用の文字列を更新してくれる。
また、E.dirty++とすることで未保存の変更があることを教えている。

これでだいたい動くはず。

Enterキーで改行する機能は実装したので、適当に削除も実装してレポート書きます。

おわり

椅子を買った

タンスのゲンのやつ

www.amazon.co.jp

この一年間で腰に感じた負担を思うと一万円は安すぎる。
探せば中華製の安いやつはありそうだが、自分が選ぶと失敗しそうだったのでやめた。

組み立ててから少しだけ作業をしたが、今の所不満はない。というか今まで座っていた椅子がひどすぎて、腰が痛くならないことに感動している。
気に入っている点として、ヘッドレスト、ロッキング、跳ね上げ式アームレストがある。
ふとした時に首を預けたり、体勢を変えたりできるので、休憩のために椅子から離れて一生布団の上から動けなくなることを防ぐことができる。
アームレストについては跳ね上がったところで何が嬉しいんだと思ったが、角度を調整するとキーボードを叩く手が安定する。
しかし肩の開きに対してキーボードが小さすぎるため、分割式のものが欲しくなってきた。いいものがあったら紹介してほしい。

AP対策日記 2/15

留年がほぼ確なので資格を取ろうと思い、同級生に便乗してAP申し込みました。
なるべく楽しくやっていこうと思います。

今日やったとこ

命題と論理

学校で一万回やった

情報量

ある事象Jが起きた時の情報量は、底を2とするJの生起確率の逆数の対数です。変形すると確率の対数に-1をかけた形になります。
確率は1以下になるので正の値を得るためにマイナスをかけてるんですね、多分。
式からわかるように確率が小さいほど情報量はでかいです。
情報量が多い写真を見ると直感的にわかる。

kogusoku.com

事象Aと事象Bが独立な場合、それらが同時に起こる時の情報量は、それぞれの情報量の和で表せます。
情報量は確率の対数なので、その和は確率同士の積の対数に変形できますね。
加法性を利用するのは、事象A, Bが同時に起きる確率を求めてから情報量を計算するのと同じことっぽい。

すべての事象の平均的な情報量を平均情報量(エントロピー)といい、各事象の生起確率と情報量の積の総和で求められます。
式の形からわかるように情報量の期待値です。

符号化

ハフマン符号化とランレングス符号化が参考書には出てくる。

ハフマン符号化は以下の記事がわかりやすかった。

www.mnc.toho-u.ac.jp

これは実装したことがある。一年前だが。

ランレングス符号化は、元の符号列を、符号と、符号が連続する数から1を引いた数の組で表現するというもの。

2値画像の圧縮にも利用されるらしい。

コンピューターシステムの理論と実装 3章 Bit回路設計あれこれ

コンピューターシステムの理論と実装(オライリージャパン)の3章のBit回路の実装課題で躓いたのでメモです

Bit回路とは

入力はinloadのふたつ、出力はout

書籍ではこのように書かれている

If load(t-1) then out(t)=in(t-1)
else out(t)=out(t-1)

loadが1ならinを保持し出力、loadが0ならinを無視して保持されている値を出力する。

Dフリップフロップ

このように記憶(状態)を必要とする回路を順序回路と言う。
逆に入力だけで出力が決まるものは組み合わせ回路と呼ばれ、ANDとかORとかの組み合わせで表現できる。

ではどのように状態を保持するかというと、書籍ではDフリップフロップを使うことになっている。
Dフリップフロップは、一つ前の入力を出力する回路で、DはDelay(遅延)を表す。

順序回路の設計

順序回路の構成

順序回路は

  • 状態決定回路
  • 記憶回路
  • 出力決定回路

から構成される。

f:id:kantarow:20201005153322j:plain
順序回路の構成

状態決定回路の出力をw、記憶回路の出力をy、出力決定回路の出力をzとする。

状態割当

yの値によって状態を割り当てる。0か1しかないので、それぞれS0S1とする。

状態決定回路

状態決定回路は論理関数で表現できる。
上の図から入力と状態で決定されることがわかる。
inx1, loadx2とする。
簡単な回路なので状態遷移表を書かずに整理すると、w=1となるのは

  • y・x1・x2
  • ~y・x1・x2
  • y・x1・~x2
  • y・~x1・~x2

(中点は論理積チルダ(~)は論理否定を表す。)

状態遷移表から求める場合は、w=1の行を探して、値が1ならそのまま、値が0なら否定して論理積をとればよい。加法標準形とかで検索すると良い記事がヒットするかも。

簡単化

ベイチ図を用いる。

f:id:kantarow:20201005155521j:plain
ベイチ図

この図から、w = y・~x2 + x1・x2が求められる。
論理回路で表すとこう。

f:id:kantarow:20201005160121j:plain
回路図

ちなみにこの回路はyzが等しいです。
つまりあとはHDLで書くだけ

**
 * This file is part of www.nand2tetris.org
 * and the book "The Elements of Computing Systems"
 * by Nisan and Schocken, MIT Press.
 * File name: projects/03/a/Bit.hdl
 */

/**
 * 1-bit register:
 * If load[t] == 1 then out[t+1] = in[t]
 *                 else out does not change (out[t+1] = out[t])
 */

CHIP Bit {
    IN in, load;
    OUT out;

    PARTS:
    And(a=in, b=load, out=s);
    Not(in=load, out=t);
    And(a=t, b=w, out=u);
    Or(a=s, b=u, out=v);
    DFF(in=v, out=w);
    Or(a=w, b=false, out=out);
}

これをシミュレーターに渡して付属のテストを動かすと通るはずです。
最後のOrDFFの出力をoutにつなげるために追加したのですが、もっとスマートな方法はないでしょうか。あったら教えてもらえると嬉しいです。