クソコードの起源を追う

背景

年末頃のことです。X(旧Twitter)にてクソコードに関する呟きと、そこから色々な考えが連なってきて「商売ができるクソコード vs 商売ができないキレイなコード」と思われる構図が見受けられました。

よくよく考えると、「クソコード」という言葉を自分なりに理解なく使っていることを感じ、以下のような書き込みをX(旧Twitter)に残して色々と調べてみることにしました。

そして以下のようなポストを残していろいろな合間に調べていました。

https://twitter.com/hima0398/status/1740164322981208195

 

古くに語られていたクソコードというワード

例えば「技術的負債」という言葉は、Ward Cunningham
1992年にオブジェクト指向プログラミングのカンファレンスで
コードの初回リリースを「負債」と喩えたことが起源と言われています。

その喩えで表現しようとしていたことはt_wadaさんのブログにまとめられており、起源を辿ることができます。

t-wada.hatenablog.jp

では「クソコード」はどうなのか?月並ですが現在インターネット上から
検索できる情報を探してみます。

 

2011年クソースという記録

当時日本工学院八王子専門学校の講師 大圖衛玄さんが(おそらくCEDEC 2011で発表された)「ソースコードの品質向上のための効果的で効率的なコードレビュー」のスライド中(p.74以降)に下記のような解説が確認できました。

https://www.slideshare.net/MoriharuOhzu/ss-9224836

クソース [kusource]

理解不能で変更困難なプログラムコード。
巨大かつ複雑で、重複しているケースも多い。
変更するたびにバグが発生し、バグが収束することはない。
地方によっては、uncodeと呼ばれる。

 

2012年ウンコード・マニア

酷いコードに苦労したプログラマーに溜まった何かを吐き出し、

反面教師から学べる(?)サイトです。

unkode-mania.net

上記クソースのスライドはこちらのサイトからのリンクでした。

2023年の投稿もあり、10年以上酷いコードが蓄積され続けているサイトになっていました。

 

2012年ハッシュタグ「#俺が見たクソコード選手権」

当時Twitter界隈では、2012年頃にすでに#俺が見たクソコード選手権というハッシュタグが観測でき、合わせてNAVERまとめへのリンクがありました。

しかしながら、NAVERまとめは2020年に終了しており、現在リンク先の参照はできませんでした。

 

まとめ

「クソコード」という言葉をなるべく正しく認識して使うために起源に近づいてみました。今調べられた時点では2010年代前半にいくつか目立った話題が観測でき、さらに以前にも使われていた話はあるものの、それより前の具体的な話は見つけられずでした。

 

その他

年末年始に何やっているのだろう。。

2023年ふりかえり

年末ですので、ふりかえりつつ記事を書いておこうと思います。

生活

5月に5類感染症に移行されたこともあり、数年前に戻りつつあるのを感じました。

働き方は顔を合わせる働き方が増え、長らく行われなかった飲み会等も開催できるようになってきました。反面のことも色々とあり、これは2023年において2024年新しい気持ちで変化していきたいと思います。

プライベートでは久しぶりに遠方へ旅行することができました。しかしながら、昔ほど街に出る機会は激減しています。数年前にやっていたことで、まだ日常に戻ってきていないと思えますが、楽しみ方が変わったと考えることもできます。

競技プログラミング

ここ数年時間をかけて取り組んでいる趣味です。

今年早々に以下のような宣言をしていました。

実績を見ますと、達成できたこととできていないこととがありますね。
来年の目標はまた来年つぶやこうと思います。

アルゴリズム

Perf:1593

Rate:1148 → 1123

ヒューリスティック

Perf:1719

Rate:1052 → 1333

来年に向けて

今年はあっという間に過ぎた気がします。そして、何をしていたかが数え切れるくらいしか思い浮かばないということもあります。

少し日常化していることを見直して、新しいことを初めて見ることと、何か残るものを残していけたら良いと思います。

ゴールデンウィーク まよコン参加記

ゴールデンウィーク中、毎日まよコンに参加しました。

まよ🌽さんが主催してくれていますAtCoder Problemsで開催されるバーチャルコンテストです。
毎日AtCoder Beginer Contest(ABC)と同じ時間帯、同じレベルの過去問を解きます。

詳しくはまよ🌽さんの記事に書かれています。

qiita.com

最近コンテストでの成績が下がり気味でしたのと、連休ということで毎日参加してみました。

 

AtCoder Problemsにはいくつもバーチャルコンテストが開催されていますが、
こうして毎日実際のコンテストと同じ時間帯に参加し続けるのは初めての試みでした。

  • 自分が精進すべき難易度の問題に毎日触れ合えた
  • 過去に解いた問題でも考えて解法にたどり着くような感触があった

そういった気づきもあり、良い精進ができたかなと思います。

Atcoder Problemsのヒートマップも、ゴールデンウィーク前と比べてカラフルになり
モチベーションにもつながったと思います。カレンダー通り5/3からが連休でしたので、水曜日以降毎日水〜青色の問題に向き合っていたことが残っています。

※ヒートマップの右側の部分が該当箇所で、カレンダー通り5/3(水)〜5/7(日)と、5/7のコンテストの残り問題を日付が変わって5/8に青Diffの問題をACした名残です。

 

開催時間的に、ゴールデンウィークが終わった後の平日は会社からの帰ってこれる時間や翌日に備えて寝る時間との相談となり毎日は難しいかもしれません。

ただ、せっかく続いた良い習慣ですので、途切れないくらいには続けてみようと思います。

 

Mo’s アルゴリズムについて勉強しました

3/11(土)のAtCoder Beginner Contest 293で、Mo'sアルゴリズムを使って解く問題が出題されました。

コンテスト中手も足も出ませんでしたので、該当の問題と過去問をいくつか解きました。

解いた問題

atcoder.jp

atcoder.jp

atcoder.jp

感想

AtCoder Beginner Contest 242に出題されてTwitterでも話題になっていたのを見かけましたが、その時に少し見たくらいで理解が全然できていませんでした。今回改めて座学とコード化とやって、次回出題されたときには使えるよう対策できたと思います。個人的には、クエリ平方分割を学んでおくと理解が早まりました。

解答コードはGoで書いたのですが、一部制限時間ギリギリのケースがありました。もしかしたら効率の悪い探索をしているかもしれませんので、この辺りは改めて調べておこうと思います。

AtCoder Beginner Contest 293参加記

A - Swap Odd and Even

問題

https://atcoder.jp/contests/abc293/tasks/abc293_a

 

文字列をこのように入れ替えます。問題文に加えて

入力例、出力例で何をするかはっきりしました。

 

B - Call the ID Number

問題

https://atcoder.jp/contests/abc293/tasks/abc293_b

 

仕様に従ってコード化するような印象でした。

I番目の人が呼ばれたかどうかをboolで管理して

問題通りのコードを書きました。

 

C - Make Takahashi Happy

問題

https://atcoder.jp/contests/abc293/tasks/abc293_c

 

H行W列のマス目が最大でも10x10程度、入力例2を見ると

最大でも48620個と書かれていましたので、全通り試して数え上げようと思いました。

数え方はこのようなイメージで、深さ優先探索で解きました。

 

D - Tying Rope

問題

https://atcoder.jp/contests/abc293/tasks/abc293_d

 

コンテスト後、この考えは余分だった気もしますがi番目のロープを

このようにグラフ化しました。

 

問題の制約(同じ色の端が複数回結ばれることはありません)というところから、

このような結び方は無いと読み取りました。

 

それをもとにUnionFindでロープを連結し、すでに連結成分になっているものに

ロープを結ぶ処理が行われたら環状になっているものとして計上します。

 

E - Geometric Progression

問題

https://atcoder.jp/contests/abc293/tasks/abc293_e

入力例1を眺めてひらめきがあり、試しに X = 9くらいで以下のように式変形をしました。

 \displaystyle (A^{0}+A^{1}+A^{2}+A^{3}) + (A^{0}+A^{1}+A^{2}+A^{3})A^{4} + A^{8}

もう少し式を一般化して、

 \displaystyle F(A, X, M) = \left\{ \begin{array}{} 1 \;\;\; (X=1)\\ F(A, \lfloor \frac{X}{2}\rfloor, M) + F(A, \lfloor \frac{X}{2}\rfloor, M) A^{\lfloor \frac{X}{2}\rfloor} + Y \;\;\; (X \gt 1) \end{array} \right.
 \displaystyle Y = \left\{ \begin{array}{} 0 \;\;\; ( X \equiv 0 \pmod 2 )\\ A^{X-1} \;\;\; ( X \equiv 1 \pmod 2 ) \end{array} \right.

と、式を立てられましたので繰り返し二乗法のように再帰することで解けました。

 

コンテスト後、kyopro_friendsさんの解説に驚かされました。

もしMが素数でしたら、私はこの式がコンテスト中思いつかず、

もっと順位が下がっていたかもしれません。

 

結果

A〜Eの5完でした。個人的に最高のパフォーマンスが出せて、

再度水色に戻ることができました。



今年の目標にしていたパフォーマンス1600にはわずかに届かず

残念でしたが、取れそうな手応えが得られたのは嬉しかったです。

 

multisetを辿る問題をGoで解く(ABC241 D - Sequence Query)

昔Qiitaに投稿した記事に関して、追加の気づきがありましたので書き残しておきます。

qiita.com

ABC241 D - Sequence Queryの問題をGo言語でmultisetに関わるデータ構造をemirpasic/godsの赤黒木を利用して解くアプローチをしました。

手元とジャッジとでライブラリのバージョンが異なって、イテレータ辺りでコンパイルエラー(CE)になったというお話です。

記事執筆時点のジャッジ環境は下記が参考になるかと思います。Goは1.14.1、ライブラリのバージョン表記はありませんが2020年初旬頃の最新版と思われます。

atcoder.jp

気づきとしては、AVL木のデータ構造には、*Node.Prev()、*Node.Next()の実装がありましたのでそれを使ってイテレータ部分を辿ることができました。以下がACになりました提出です。

atcoder.jp

その時ライブラリに実装されていたものの違いかと思います。

RECRUIT 日本橋ハーフマラソン 2023冬(AtCoder Heuristic Contest 018)参加記

30代後半から競技プログラミングを始めましたhimaと言います。

RECRUIT 日本橋ハーフマラソン 2023冬(AtCoder Heuristic Contest 018)に参加しました。02/18〜26までの9日間の長期コンテストです。

ヒューリスティックコンテストにはこれまで何度か参加していましたが、今回長い時間じっくりと取り組み、自分のレートより大幅に良いパフォーマンスが出せました。その記録を残しておこうと思います。

綺麗な解法というよりは、参加の日記のレベルです。ヒューリスティックコンテストの参考になれば幸いです。

 

問題

atcoder.jp

 

1日目

目標は正の点数を取得することと、ビジュアライザ等の開発環境を整備することにしました。

ヒューリスティックコンテストでは問題の理解と確認のため、はじめに問題の理解とその通りの解答がかけているかとりあえずAC(Accepted)されるコードを書いています。今回はインタラクティブな問題(解答コードが出力したものに対して、ジャッジプログラムからの入力を受け取る対話形式の問題)のため、ジャッジとの対話を確認も兼ねています。

各家から一番近い水源まで、L字のルートを描きながら適当なパワーで掘っていくコードを提出して、初日の夕方にひとまず正のスコアを得ました。

コンテストのテストケースで、絶対スコアが18835039でした。

あとは、手元でインタラクティブなジャッジ含めた動作確認ができるよう提出コードでは標準入出力、テストコードではテスト用のジャッジに値を渡す形にコードを書いてgo testコマンドで動作確認ができるように整備しました。

 

2日目

硬い岩盤を掘り進めるとコスパが悪いのが掴めてきて、なるべく柔らかい岩盤を掘り進めるように修正しました。優先度付きキューを使って試行錯誤していました。

無駄な掘削をしており、絶対スコアは25319332。初回提出の方が良かったです(今回のコンテストは絶対スコアが低い方が良いので)。

この辺りから、最短経路や経路探索のアルゴリズムについて調べ始めました。アルゴリズムのコンテストでは、ダイクストラ法、ワーシャルフロイド法、まれにベルマンフォード法を使っています。A*アルゴリズムというものを勉強する機会になりました。

コンテスト後に拝見した解放の中にはA*アルゴリズムを使用している方もおり、今回の復習など、合うところに実装を試してみたいと思いました。

 

3、4日目

3日目は仕事後に少しコードを改善して提出、20698072まで微改善しました。

4日目はお休みをもらってAHCに注力していました。

方針を変えて、予め岩盤調査を行った後に経路を考える方法に切り替えました。20*20の領域に区切って特定のパワーで掘り、岩盤が壊せた付近は比較的柔らかいだろうと推測して最短経路を繋いでいきました。

まだ実装に甘いところがあり、余計な掘削も取りきれず最終スコアは26745703。まだまだ進捗が出ませんでした。順位も、400位前後をうろうろしていました。

 

5、6日目

5日目は仕事のため手付かず。

6日目は祝日のため、再びAHCに注力していました。

余計な採掘を取り除き、絶対スコア9261310、200位台まで上がれました。

7日目

お仕事のため、進捗ありませんでした。

 

8、9日目

手元でパワーをいくつか変えながらテストケースを回して良いスコアが出ているパワーを選んだりしながら細かく順位を上げていました。

入力用のファイルには岩盤の固さがわかっていますので、それで答えに近い水の通し方やそのスコアを見ながら、解答コードが硬い岩盤を選んでいる経路の改善をしていました。

あらかじめ岩盤調査をしていたところが、01BFSで解くような道と壁になっていましたが、実際はもっとなだらかなギャップを埋める方法を探していました。

いろんな解説記事には、それに合う手法があるようですが、この時思いつきましたのは単純な画像のぼかしの方法で、それを適用してみました。

あとは、グリッド状に岩盤調査していたのをダイヤ型(サイコロの5の目とも言われますかな?)にポイントをあてて掘削も試しました。


後者(5の目状の岩盤調査)の方で、絶対スコアは6721084まで達成できました。が、相対スコアは前者(グリッド状の岩盤調査)の方が良く、最終的にこちらを提出しました。

9日目は何か改善したいと思いつつ、閃きがなく8日目の提出が最終提出となりました。

 

結果

最終提出の暫定順位が213位、システムテストの結果210位に入ることができました。

パフォーマンスは1719で、ヒューリスティックで最大のパフォーマンスを出すことができ、ヒューリスティックで入水することができました。

atcoder.jp

今年掲げていた目標も1つ達成することができました(あとはアルゴの方でも達成したいと思います)。

 

いくらか考察が不十分な点もあり、方針ガチャがたまたま当たったという説もあります。

今後も安定したパフォーマンスが出せるように、ヒューリスティックの勉強、コンテスト参加を続けていきたいと思います。