<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>TraceofLight (JA)</title><description>게임 개발, 그래픽스 프로그래밍, 데이터베이스 엔지니어링을 기록하는 TraceofLight의 기술 아카이브입니다.</description><link>https://www.traceoflight.dev/</link><language>ja</language><atom:link href="https://www.traceoflight.dev/ja/rss.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Wed, 06 May 2026 01:18:04 GMT</lastBuildDate><item><title>Unity Roadshow 2026 で学んだ内容のまとめ</title><link>https://www.traceoflight.dev/ja/blog/unity-roadshow-2026/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/unity-roadshow-2026/</guid><description>Unity Roadshow に参加して学んだ内容の簡単な記録</description><pubDate>Sun, 19 Apr 2026 13:17:51 GMT</pubDate><content:encoded>&lt;h2&gt;メモリの前提知識&lt;/h2&gt;
&lt;h3&gt;基本内容&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;私たちは仮想メモリ (Virtual Memory、以下 VM) を使用しており、物理メモリを直接コントロールはしない&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;VM はページで構成されており、OS ごとに異なり得る&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Window / Linux 4kb&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;iOS, macOS, Android 16kb&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ページに対応する物理メモリのフレームが存在する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;メモリ圧迫の度合いに応じて、仮想メモリを物理メモリにマージする&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Page Fault&lt;/h3&gt;
&lt;p&gt;物理メモリにロードされていないページが必要になった場合を Page Fault と呼ぶ&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Clean Page: 元データが変わっていないページ。OS がいつでも破棄でき、回収が容易&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dirty Page: アプリケーションが新たに書き込みや変更を加えた情報を持つページ。メモリからすぐに退避できない&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Memory Footprint&lt;/p&gt;
&lt;p&gt;実質的なメモリ圧迫を表す指標で、全 Dirty Page サイズの合計&lt;/p&gt;
&lt;p&gt;Memory Footprint != 物理メモリ使用量、常駐メモリ使用量&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;メモリ管理方法 (Windows vs Linux)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;予約: 物理メモリを使わず仮想メモリのみを確保&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;コミット: 仮想メモリと同量の物理フレームを割り当てる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;デコミット: 予約領域は保ったまま物理フレームを解放する&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Windows: 明示的な API を提供 (virtual alloc, virtual free)&lt;/p&gt;
&lt;p&gt;UNIX Like: 予約とコミットの明示的な分離がない&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;mmap 呼び出しは暗黙的にメモリを予約する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ページに直接アクセスした時点で遅延コミットが発生&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;明示的な API はなく、デコミットはヒントとして動作する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;OS がいつページを回収するかを決定する&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Unity GC における処理&lt;/h2&gt;
&lt;h3&gt;Managed Heap&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;C# のメモリ確保はすべてここで行われる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Garbage Collector が管理する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Unity Profiler では GC.Alloc として表示される&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Garbage Collector&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;有効な参照が存在しない Object を Heap から定期的に回収する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;GC を実行しても仮想メモリの総使用量は減らない&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;回収済みのオブジェクト領域も OS から見れば Dirty&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Segment&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;連続したページの集合を Segment と定義する&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Managed Heap は Raw Page ではなく Segment を使う&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;1 つの Segment に複数の Object が割り当てられ得る&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;割り当てて解放した後、内部的には未使用でも RAM 使用として表示される (Dirty のため)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;大半は何の問題もなく、すぐに再利用される&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;長時間空のままだと常駐メモリの無駄になるため、Unity GC が断続的に処理する&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Unity GC の役割&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;リマッピング戦略を採用している&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GC が複数回実行された後、Old Empty Segment を Drop し、同サイズの New Segment を割り当てる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Windows Remap 戦略: Segment を解放せず Decommit (明示的に扱えるため)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UNIX Like Remap 戦略: munmap &amp;amp; mmap による Remap (Hot Page 効果でキャッシュヒット率が高い)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;これにより常駐メモリを減らせるという利点がある&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;GC.Collect を何度も呼ぶべきでない理由&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Segment のリリースを強制的に実行しないこと&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Collect はコストが高く、アプリがフリーズする恐れがある&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;もともとの意図は長時間空き状態のセグメントをデコミットすることにある&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一時的に空になっただけのセグメントをデコミットするのは意図と異なる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;強制的にデコミットしてもパフォーマンスは改善せず、CPU コストだけが発生する&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;どうせ次フレームで再利用されるセグメントまでデコミットする状況になる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Managed Heap の VM 使用量は増えるばかりで絶対に減らない&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Heap は大きくなるだけで縮小しない&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Boehm GC 本来の特性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;仮想メモリの割り当て量を Trim する理由がない&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;大きな仮想メモリ != 大きな物理メモリ使用量&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;セグメントはどうせ再利用される&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ゲームオブジェクトは毎フレーム頻繁に生成・破棄される&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;オブジェクトが破棄されるたびにセグメントを縮めるのは CPU 性能の浪費にしかならない&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Unity Boehm GC&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Unity の Incremental Boehm GC は保守的な GC (Conservative GC)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;これは Unity が、過去に書かれた C# コードを C++ に変換する処理をサポートする IL2CPP を提供したことで主に使われるようになった&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IL2CPP によって多様な環境への対応が可能になったが、C# と違いメモリ GC は自動化されないため、オープンソースの GC である Boehm GC を採用したと考えられる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;性能よりも安定性を重視し、ポインタ「のように」見える値はすべて参照とみなす&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GC 中にオブジェクトの位置を変えない -&amp;gt; コンパクションがなく、メモリ断片化に弱い&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Compaction について&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;メモリ断片化の解消に有利なメモリ圧縮処理。未使用領域をすべて空けて再配置する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;正確な参照情報が必要なため、保守的な GC では不可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;オブジェクトの位置を移動するにはコストがかかる (Stop The World + 実際の移動)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3&gt;CoreCLR GC&lt;/h3&gt;
&lt;p&gt;CoreCLR GC は Precise GC で、メモリ・スタック・レジスタ上のどの値が参照かを正確に把握する方式の GC&lt;/p&gt;
&lt;p&gt;そして .NET は CoreCLR をコアエンジンとして採用している (CLR: Common Language Runtime)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;CoreCLR がサポートする点&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;CoreCLR GC&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;JIT コンパイラ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Excecption Control&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;misc...&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;この CoreCLR GC (以下 .NET GC) は世代別メモリ管理方式を採用している&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Heap を 3 世代に分けて管理する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gen 0: 生成直後の新しいオブジェクト中心。頻繁かつ高速な GC が走る (大半のオブジェクトはここで消える)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gen 1: Gen 0 を生き延びたオブジェクトが移される Buffer の役割&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gen 2: 長く生き残っている重いオブジェクトが置かれる領域。ここの GC はコストが比較的大きい&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;LOH: 非常に大きいオブジェクトはこの領域に配置される&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;プロモーション過程でメモリ Compaction を行うことで断片化を抑えられる&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;LOH の場合 STW が長くなるため、以前は Compaction しなかったが、現在は明示的にオプション化して扱っているとのこと&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;移行の価値?&lt;/h3&gt;
&lt;p&gt;基本的に Unity が .NET に移行することで生じる副次的な影響として GC が変わるのであって、GC がメインではない、という点が話されていた。それでも価値を挙げるなら...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Compaction が利用できるためメモリ断片化が減る&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GC コストを予測可能にできる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>コンテナ環境についての簡単なメモ</title><link>https://www.traceoflight.dev/ja/blog/difference-btw-container-vm/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/difference-btw-container-vm/</guid><description>コンテナとVMの違い、その他学んだことの記録</description><pubDate>Thu, 02 Apr 2026 06:58:20 GMT</pubDate><content:encoded>&lt;h3&gt;&lt;strong&gt;コンテナ駆動原理&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;ホストOSのカーネルを共有しながらプロセスと同じように隔離する方式&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;それでは、カーネル互換性がない場合は？&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;当然実行されないのが普通、しかし、mac、windowなどで稼働が可能な理由は、vm layerが追加されるから。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Windowsにdocker desktopをインストールする時wsl2をインストールしろと言う理由。MSのLinux VMをインストールしないと、そのレイヤベースのコンテナが動作しにくいからだと思われる。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;カーネルバージョンで問題が発生してもクラッシュが発生する可能性がある(バージョンの違いにより存在しない機能を使おうとするなど)&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;結論&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;カーネルタイプが一致し、機能サポートに問題がなく、cpuアーキテクチャが一致しなければコンテナを稼働することができません。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;VM&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Hypervisorを使った独立実行、カーネルを別に使う。bare-metal / hosted方式があり、私たちが使うのはだいたいホスト型、OSの上にハイパーバイザーが上がるため、パフォーマンスの損失がある。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;ボリュームバインディング&lt;/strong&gt;。&lt;/h3&gt;
&lt;p&gt;データの永続性を保つために使用、ホストマシンの特定のディレクトリをマウントする方法で処理される。Linuxネイティブではvfsに直接記録する方式であり、他のOSの場合は内部仮想ネットワークを燃やす方式で比較的遅い場合がある。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;ウィンドウズでchmodを無視する理由&lt;/strong&gt;。&lt;/h3&gt;
&lt;p&gt;WindowsではACL(Access Control List)を活用した権限管理を行い、chmodの方式を理解していない。&lt;/p&gt;
</content:encoded></item><item><title>クラフトン・ジャングル・ゲームテックラボ修了レポート</title><link>https://www.traceoflight.dev/ja/blog/jungle-gametech-lab-review/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/jungle-gametech-lab-review/</guid><description>クラフトン「ジャングル・ゲームテックラボ」第2期を修了した体験談</description><pubDate>Thu, 26 Mar 2026 18:02:12 GMT</pubDate><content:encoded>&lt;h2&gt;はじめに&lt;/h2&gt;
&lt;p&gt;修了後、世俗での生活を半年ほど先延ばしにしていたため、いつ体験記を書こうか少し悩んでいた気がする。&lt;/p&gt;
&lt;p&gt;それでも、記憶が薄れる前に記録しておいたほうがいいと思い、今こうして書き留めておく。&lt;/p&gt;
&lt;p&gt;おそらくこの記事を読んでいる人は、今まさに悩んでいる最中だろうと思い、上部のメディア欄に説明会動画のアーカイブも添付しておいた。&lt;/p&gt;
&lt;h2&gt;入学前の悩み&lt;/h2&gt;
&lt;p&gt;まず、すぐに入学を決断することはできなかった。2025年下半期に何をしているかについて、いくつかの計画があったからだ。&lt;/p&gt;
&lt;p&gt;それでも入学した理由は、それらの計画が概してうまくいかず、それでも選べる選択肢の中ではかなり良いと思えたからだ。&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;https://traceoflight.dev/media/image/240d3d9a-5133-45d9-a584-df6d6f8dc511-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;何度か面接を受けたものの、良い結果には結びつかなかったため、不足している経験をどう補うべきかという悩みが常にあった。&lt;/p&gt;
&lt;p&gt;商用化されたリアルタイム3Dエンジンを扱った経験が全くなかったため、内部ロジックはおろか、全体的な機能についての説明すらできなかった。&lt;/p&gt;
&lt;p&gt;そのため、AIと格闘しながら捻り出した知識を持って面接官の前に立ったものの、表面的な説明しか並べることができなかった。&lt;/p&gt;
&lt;p&gt;今になって考えてみると、その回答を面接官が聞いてどう思ったかと思うと、非常に恥ずかしい気持ちになる。&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;当時、そのコースを受講することに対するリスクとして、2つほど考慮した。&lt;/p&gt;
&lt;p&gt;先行する期がたった1期だけであり、修了前だったため、どのようなコースなのか、どのような成果が得られるのか全く見当がつかない状況だった。&lt;/p&gt;
&lt;p&gt;また、2期は下半期に実施される予定であり、念頭に置いていたゲーム会社は概ね下半期に新卒採用や採用型インターンの募集を行うため、このような試みを諦めなければならないという点もリスクだと考えた。&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;天秤にかけた末、入科を決めた。今思えば、入科の説明会を聞きに行ったことがかなり影響していたようだ。&lt;/p&gt;
&lt;p&gt;ジャングルコースの中にゲームラボもあったため、受講すべきか、受講するならどのコースを申し込むべきか悩んでいたが、説明会に参加した後、すっきりと決心がついた。&lt;/p&gt;
&lt;h2&gt;コースについて&lt;/h2&gt;
&lt;p&gt;修了して間もないため、どのような結果につながるかは分からないが、これまでのところ非常に満足のいく経験だったと思っている。&lt;/p&gt;
&lt;p&gt;コース内でどのようなことをするのか、どのような状況に置かれるのかについては、コーチの方々の言葉を借りれば「ジャングラーたちの楽しみを半減させてしまう可能性があるため」、ここではあえて書き留めないことにする。&lt;/p&gt;
&lt;p&gt;ただ、TechLabが簡単なコースではないことは断言できる。他の作業との並行はほぼ不可能であり、コース期間中、教室の明かりが消えることはほとんどない。&lt;/p&gt;
&lt;p&gt;このような過程の中で、印象的な経験を通じて知識が定着し、商用リアルタイム3Dエンジンに対する理解度も高まっていくと考えていいだろう。&lt;/p&gt;
&lt;h2&gt;では、どのような人が受講すべきか？&lt;/h2&gt;
&lt;p&gt;説明会の内容を引用するのが最も直感的だろう。&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;https://traceoflight.dev/media/image/2572851e-3357-4318-803f-1cac3e951f91-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;これらについてもっと詳しく知りたいという人なら受講すべきだと思う。これらに対する理解度が大幅に向上する。&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;https://traceoflight.dev/media/image/b21999e7-643c-4d5f-bfbf-f3c801e197f3-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;こちらは扱わないと言ったが、実はここでグラフィックスや開発環境の一部について疑問がある人は、テックラボの受講を検討してみる必要がある。&lt;/p&gt;
&lt;p&gt;受講を終えれば、人によって差はあるものの、少なくともそれらについて知識を語りながら、簡単なやり取りくらいはできる人になれる。&lt;/p&gt;
&lt;h2&gt;締めくくりの所感&lt;/h2&gt;
&lt;p&gt;すべての課程を終えた今、非常にすっきりした気分であるのも事実だが、あまりにも短期間で多くの経験を積んだため、今後整理すべき点も多い。&lt;/p&gt;
&lt;p&gt;しかし、それらをすべて自分のものとして消化し終えた時には、もう少し成長した開発者になっているだろうと思う。&lt;/p&gt;
&lt;p&gt;AIの発展に伴う業界の人員削減の話も絶えないが、私は自分にできることをやっていこうと思う。&lt;/p&gt;
&lt;p&gt;「成長ガスライティング」という話も最近よく出ている状況だが、確かに周囲で成長し続けた人たちに良い結果が現れているのを目の当たりにしているため、おそらくしばらくの間は原動力を維持できるだろう。&lt;/p&gt;
</content:encoded></item><item><title>Windows / macOS 統合ターミナル環境の構築</title><link>https://www.traceoflight.dev/ja/blog/cross-platform-terminal-setting/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/cross-platform-terminal-setting/</guid><description>WindowsとmacOSの両方で動作するクロスプラットフォームのターミナル環境の構築手順</description><pubDate>Thu, 26 Mar 2026 12:18:01 GMT</pubDate><content:encoded>&lt;h2&gt;はじめに&lt;/h2&gt;
&lt;br /&gt;
&lt;p&gt;最近MacBook Airをアップグレードしたため、環境を再設定する必要性を感じた。&lt;/p&gt;
&lt;p&gt;M1からM5への性能面での変化には満足しているが、以前使っていた環境を再び整えようとすると手間がかかることが分かり、この機会に全プロセスを文書化し、手軽に再設定できるよう標準化しようと思った。&lt;/p&gt;
&lt;h3&gt;[2026 Mac ターミナル完全設定 (Ghostty + Starship + AI コーディング環境)](&lt;a href=&quot;https://blog.dnd.ac/settings-mac-terminal-2026/&quot;&gt;https://blog.dnd.ac/settings-mac-terminal-2026/&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;その過程で特に印象に残った資料が、上記のリンク先のものだった。すっきりとしていて見栄えの良い環境がスクリプトとしてまとめられており、大いに参考になった。&lt;/p&gt;
&lt;p&gt;結論から言うと、以下のような形でターミナル環境を構築することができました。&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;https://traceoflight.dev/media/image/f0670bf2-9240-4320-ad5e-6367803485d2-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;内部的には、Wezterm + Nushell + LazyVimを大枠として設定しています。&lt;/p&gt;
&lt;p&gt;[Githubリンク](&lt;a href=&quot;https://www.github.com/TraceofLight/global-terminal-settings&quot;&gt;https://www.github.com/TraceofLight/global-terminal-settings&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;) で設定の全ガイドを確認でき、そのガイドを通じてWindows、MacOSに同一の環境を構築できるようにしています。&lt;/p&gt;
&lt;h2&gt;目標設定&lt;/h2&gt;
&lt;br /&gt;
&lt;p&gt;この作業の目標は明確だった。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Windows / MacOSで同一のターミナル環境を使用すること&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;LazyVimベースのエディタと問題なく動作すること&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;既存の使用環境と大きく変わらないこと&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;tmuxのようなマルチプレクサツールを問題なく使用できること&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;p&gt;このような目標を達成するために作業を進めてみた。&lt;/p&gt;
&lt;h2&gt;進行過程&lt;/h2&gt;
&lt;br /&gt;
&lt;p&gt;まず、使用する技術を選定する必要があった。最近のトレンドとしては、GPUアクセラレーションによるレンダリングが可能なGUIを備えたターミナルエミュレーターが主流であり、実際にこうしたツールが注目されている理由は、高速で装飾が可能であるという点にある。前述のリンクで示したように、ターミナルを構築するにはこうした要素が必要だったため、その中からWeztermを選択することにした。&lt;/p&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;ターミナルエミュレーター&lt;/p&gt;
&lt;p&gt;まず、クロスプラットフォームで同一のUXを提供する必要があったため、エコシステムが構築されたクロスプラットフォームのターミナルエミュレーターとしてはAlacrittyやWezterm程度があると考えた。ミニマリズムを追求するAlacrittyは拡張性に欠けると感じたため、Weztermを選択することになった。マルチプレクサーを搭載している点もメリットの一つだ。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;シェル&lt;/p&gt;
&lt;p&gt;両プラットフォームで同一の操作感を保証する必要があったため、まずはUnixコマンドが使用できる環境に統一しようと試みた。その結果、Windowsではbash、macOSではzshを使用することに初期段階で決定していた。しかし、いくつかの問題があり、最終的にはNushellベースに統一することになった。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;LazyVim&lt;/p&gt;
&lt;p&gt;実はこちらについては、すでに使用していたツールがあり、問題なくほとんどの環境で統合できたため、難しくはなかった。 もともとSpaceVimを使用していたが、こちらはすでに[メンテナンスが終了した状況](&lt;a href=&quot;https://wsdjeg.net/why-spacevim-is-archived/&quot;&gt;https://wsdjeg.net/why-spacevim-is-archived/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;)であったため、LazyVimに移行してからある程度時間が経過していたことに加え、基本的にはIDEを使用しており、補助的なツールとして利用しているため、スムーズにインストールが進んだようだ。&lt;/p&gt;
&lt;h2&gt;問題の発生&lt;/h2&gt;
&lt;p&gt;この過程でいくつかの問題が存在したが、2つの問題はいずれもNushellへの移行に関連している。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Windowsではbashが体感できるほど遅すぎる&lt;/p&gt;
&lt;p&gt;実際、後で確認してみると、これは予見されていた結末だったようだ。Windows環境下では、POSIX式の動作をWindowsで処理するために、互換性のための処理が追加レイヤーとして挿入されることが分かった。そのため、実際にwsl2環境に移行することも検討したが、それは結局Linuxを使用することと変わらないため、除外した。&lt;/p&gt;
&lt;p&gt;-&amp;gt; この問題を解決するためのツールとして、nushellを導入することになった。Unixコマンドと互換性のある部分が多い点、Rustベースで設計されておりある程度のパフォーマンスも保証されている点、MacOSでも同様の環境設定が可能である点を考慮した。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Windowsのnushellでnaviプラグインが動作しない&lt;/p&gt;
&lt;p&gt;naviは、ターミナルコマンドのチートシートとして参照するためのプラグインである。それほど頻繁に活用するわけではないが、当該ツールの機能が全く動作しないのは困るため、いくつかの方法を検討した。結局、naviをフォークして当該問題を解決した後、新たにビルドしたプラグインを使用することで対処した。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;原因：ユーザーのシェルが変更されても、内部ではbashベースの構文が適用されるため、nushell使用時に不具合が発生する状況&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;解決策：該当部分をシェルスクリプトによるコマンドで処理する代わりに、関連する依存関係を排除するため、wgetを使用すべき箇所でRustのHTTPクライアントを使用し、bashを使用すべき箇所でpwshを使用するなど、内部ヘルパーがbashに依存している部分を排除した&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;[詳細な修正履歴](&lt;a href=&quot;https://github.com/TraceofLight/navi/tree/fix/nushell-usability&quot;&gt;https://github.com/TraceofLight/navi/tree/fix/nushell-usability&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;h2&gt;結論&lt;/h2&gt;
&lt;p&gt;開発者はターミナルを使用する機会がかなり多く、環境が一つに統合されれば使い勝手が良くなるのは当然のことだ。だからこそ、クロスプラットフォームかつ同一のユーザビリティをサポートするJetBrainsのIDEにはメリットがあるのではないだろうか。同様に、ターミナルにおいても、自分が追求するものが様々な環境において統一された操作感を維持することであるならば、このような方法を試してみるのも良いと思う。&lt;/p&gt;
</content:encoded></item><item><title>std::variant &amp;amp; std::visit</title><link>https://www.traceoflight.dev/ja/blog/variant-and-visit/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/variant-and-visit/</guid><description>C++17で追加されたvariantとvisitに関する内容のまとめ</description><pubDate>Mon, 28 Jul 2025 14:13:37 GMT</pubDate><content:encoded>&lt;h3&gt;その他の情報&lt;/h3&gt;
&lt;p&gt;[関連ドキュメント](&lt;a href=&quot;https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0088r3.html&quot;&gt;https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0088r3.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;上記のリンクには、C++17から追加されたVariantとその追加理由について記載されています。簡単に言えば、std::optionalとして追加されるべきだった機能が、Boostで長期間使用されていたため、「これ以上引き延ばさずに、早く実装してしまおう」という議論がなされたということです。&lt;/p&gt;
&lt;h3&gt;内部構造&lt;/h3&gt;
&lt;h4&gt;1. Variant&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;データバッファ
テンプレート引数として与えられた型の中で、最もサイズが大きい型を格納できる十分なサイズのメモリ領域であり、概ねUnionとして実装されている&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;識別子
現在、データバッファにどの型のオブジェクトが格納されているかを示すインデックスまたは識別子であり、この識別子を使用することで、std::variantは型安全性を保証できる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;十分なサイズのメモリ領域を持つことにより、variant型は以下のような動作が可能となる。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;
	&lt;span class=&quot;hljs-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Tracer&lt;/span&gt;
	{
		std::string name;

		&lt;span class=&quot;hljs-built_in&quot;&gt;Tracer&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;const&lt;/span&gt; std::string&amp;amp; n) : &lt;span class=&quot;hljs-built_in&quot;&gt;name&lt;/span&gt;(n)
		{
			std::cout &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;  [+] &amp;#x27;&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; name &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;&amp;#x27; Tracer created (Constructor)\n&amp;quot;&lt;/span&gt;;
		}

		&lt;span class=&quot;hljs-comment&quot;&gt;// Copy Constructor&lt;/span&gt;
		&lt;span class=&quot;hljs-built_in&quot;&gt;Tracer&lt;/span&gt;(&lt;span class=&quot;hljs-type&quot;&gt;const&lt;/span&gt; Tracer&amp;amp; other) : &lt;span class=&quot;hljs-built_in&quot;&gt;name&lt;/span&gt;(other.name)
		{
			std::cout &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;  [*] &amp;#x27;&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; name &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;&amp;#x27; Tracer copy-constructed (Copy Constructor)\n&amp;quot;&lt;/span&gt;;
		}

		~&lt;span class=&quot;hljs-built_in&quot;&gt;Tracer&lt;/span&gt;()
		{
			std::cout &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;  [-] &amp;#x27;&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; name &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;&amp;#x27; Tracer destroyed (Destructor)\n&amp;quot;&lt;/span&gt;;
		}
	};

	&lt;span class=&quot;hljs-comment&quot;&gt;// 1. Initialize the variant with a Tracer type.&lt;/span&gt;
	std::cout &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;1. Initializing variant with Tracer(\&amp;quot;Apple\&amp;quot;).\n&amp;quot;&lt;/span&gt;;
	std::variant&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;, Tracer&amp;gt; var = &lt;span class=&quot;hljs-built_in&quot;&gt;Tracer&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;Apple&amp;quot;&lt;/span&gt;);
	std::cout &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;   Variant now holds Tracer(\&amp;quot;Apple\&amp;quot;).\n\n&amp;quot;&lt;/span&gt;;

	&lt;span class=&quot;hljs-comment&quot;&gt;// 2. Assign a value of a different type (int).&lt;/span&gt;
	std::cout &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;2. Assigning integer 100 to the variant.\n&amp;quot;&lt;/span&gt;;
	var = &lt;span class=&quot;hljs-number&quot;&gt;100&lt;/span&gt;;
	std::cout &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;   Variant now holds integer 100.\n\n&amp;quot;&lt;/span&gt;;

	&lt;span class=&quot;hljs-comment&quot;&gt;// 3. Assign another Tracer type value again.&lt;/span&gt;
	std::cout &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;3. Assigning Tracer(\&amp;quot;Banana\&amp;quot;) to the variant.\n&amp;quot;&lt;/span&gt;;
	var = &lt;span class=&quot;hljs-built_in&quot;&gt;Tracer&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;Banana&amp;quot;&lt;/span&gt;);
	std::cout &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;   Variant now holds Tracer(\&amp;quot;Banana\&amp;quot;).\n\n&amp;quot;&lt;/span&gt;;

	std::cout &amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;4. main function is about to end.\n&amp;quot;&lt;/span&gt;;
	&lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このようなコードを実行すると、以下のような結果が得られる。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;1. Initializing variant with Tracer(&amp;quot;Apple&amp;quot;).
  [+] &amp;#x27;Apple&amp;#x27; Tracer created (Constructor)
  [*] &amp;#x27;Apple&amp;#x27; Tracer copy-constructed (Copy Constructor)
  [-] &amp;#x27;Apple&amp;#x27; Tracer destroyed (Destructor)
   Variant now holds Tracer(&amp;quot;Apple&amp;quot;).

2. Assigning integer 100 to the variant.
  [-] &amp;#x27;Apple&amp;#x27; Tracer destroyed (Destructor)
   Variant now holds integer 100.

3. Assigning Tracer(&amp;quot;Banana&amp;quot;) to the variant.
  [+] &amp;#x27;Banana&amp;#x27; Tracer created (Constructor)
  [*] &amp;#x27;Banana&amp;#x27; Tracer copy-constructed (Copy Constructor)
  [-] &amp;#x27;Banana&amp;#x27; Tracer destroyed (Destructor)
   Variant now holds Tracer(&amp;quot;Banana&amp;quot;).

4. main function is about to end.
  [-] &amp;#x27;Banana&amp;#x27; Tracer destroyed (Destructor)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;既存の値に対するデストラクタが先に呼び出され、スタック上に一時オブジェクトを生成した後、コピー生成された値を自身のメモリバッファに取り込む順序を確認できる。&lt;/p&gt;
&lt;p&gt;したがって、最大サイズのクラスを格納するスペースを内部的にユニオンとして保持しておけば、variant型にどのような値が入ってきても問題なく使用できるようにすることができる！&lt;/p&gt;
&lt;h4&gt;2. Visit&lt;/h4&gt;
&lt;p&gt;これはライブラリによって異なるが、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;関数ポインタテーブル&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switch文&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;大きく2つの形態に分類されるという。実際、実装方式やオーバーヘッド、コンパイラの最適化に若干の違いがあるだけで、基本的には識別子を見て、アクティブ化されたTypeに応じて適切な関数を呼び出せるように実装されていると考えてよいだろう。&lt;/p&gt;
</content:encoded></item><item><title>[鐘萬冊] 02.問題解決戦略</title><link>https://www.traceoflight.dev/ja/blog/jongmanbook02/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/jongmanbook02/</guid><description>アルゴリズム問題解決戦略 2章の内容まとめ</description><pubDate>Wed, 18 Dec 2024 04:27:16 GMT</pubDate><content:encoded>&lt;h2&gt;問題解決のプロセス&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;問題を読んで理解する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;問題を身近な用語で再定義する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;どのように解くか計画を立てる。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;計画を検証する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;プログラムで実装する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;どのように解決したかを振り返り、改善する方法があるか探す。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1) 問題を読んで理解する&lt;/h3&gt;
&lt;p&gt;問題を読み間違えないように、問題を積極的に読み、問題が求めていることを完全に理解しようとする努力が必要です。些細な制約条件を見逃してしまうと解けなくなる場合も多く、大会では小さなミスも許されない場合がほとんどだからだ。&lt;/p&gt;
&lt;h3&gt;2) 再定義と抽象化&lt;/h3&gt;
&lt;p&gt;自分が扱いやすい概念を使って、問題を自分の言語で解くこと、問題が要求することを直感的に理解するために必要なプロセスであり、複雑なプロセスであればあるほど重要である。
問題の本質をどのような方法で再構成するかによって、同じことをするプログラムでも全く違うものになる。
難しい問題を簡単に、簡単な問題を難しく解くことができるので、抽象化がプログラムが進むべき方向を決定すると見ることができる。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;抽象化: 現実世界の概念を私たちが扱いやすい数学的/計算学的概念に置き換えて表現する過程。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;3) 計画を立てる&lt;/h3&gt;
&lt;p&gt;問題をどのように解決するかを決定し、使用するアルゴリズムとデータ構造を選択する過程。最も重要な過程であり、問題を見てすぐに解決方法が思い浮かばない場合、この過程で最も多くの悩みを抱えることになる。&lt;/p&gt;
&lt;h3&gt;4) 計画を検証する&lt;/h3&gt;
&lt;p&gt;実装を始める前に計画を検証する段階を経なければならない。この過程で、私たちが設計したアルゴリズムがすべての場合について要求条件を正確に実行することを証明し、実行にかかる時間と使用するメモリが問題の制限内に収まることを確認しなければならない。&lt;/p&gt;
&lt;h3&gt;5) 計画を実行する&lt;/h3&gt;
&lt;p&gt;実装においては、効率性と正確性を常に考慮すること。&lt;/p&gt;
&lt;h3&gt;6) 回顧すること&lt;/h3&gt;
&lt;p&gt;すぐに直接的な影響はないが、長期的に最も大きな影響を与える段階。
一度解いた問題をもう一度解くことで、より効率的なアルゴリズムを見つけたり、簡潔なコードを書くことができるようになったり、同じアルゴリズムを誘導できるより直感的な方法を見つけたりすることができます。
効果的に回顧を行う方法としては、問題を解くたびに自分の経験を記録に残すことが一番有効だと思います。&lt;/p&gt;
&lt;p&gt;アプローチ方法、決定的な気づき、誤答の原因などを記録することで、間違いを減らし、パターン化に役立つこともある。解決した他の人のコードを確認することで、思いもよらない洞察を得ることもある。&lt;/p&gt;
&lt;p&gt;解決できなかった場合でも、一定時間が経過したら他の人のコードや解答を参照するが、必ず復習を伴うこと。&lt;/p&gt;
&lt;h2&gt;問題解決戦略&lt;/h2&gt;
&lt;h3&gt;1) 直感と体系的なアプローチ&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;似たような問題を解いたことがあるか？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;単純に解いた経験ではなく、原理の理解と変形が可能でなければならない。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;単純な方法から始められるか？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;無知で解けるか？から始まる最も単純なアルゴリズムを作り、最適化を通じて実装する方法も存在する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;アルゴリズムの効率のベースラインを決めることができる。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;私が問題を解く過程を数式化できるだろうか？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;問題に与えられた例題などを解きながら定式化する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;問題を単純化できないだろうか？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;与えられた問題のもう少し簡単な変形版を先に解いてみること。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;絵で描いてみることはできないだろうか？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;幾何学的な図形の方が直感的に受け止めやすい。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;数式で表現できるか？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;平文 → 数式が問題を解決するのに役立つ可能性がある。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;問題を分解できるだろうか？&lt;/p&gt;
&lt;p&gt;より扱いやすい形に問題を変形させる方法のうち、制約条件を分解する方法 *制約条件の分解方法&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;後ろから考えて問題を解くことができるか？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;代表的な例：ラダーゲーム&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;前面からすべてのルートを試すよりも、到着地から逆方向に乗ることで回数を減らすことができる。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;順番を強制することができるか？&lt;/p&gt;
&lt;p&gt;順序のない問題に順序を強制する方法 * 順序のない問題に順序を強制する方法&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;例示：1つの変数に対して変形をするか、しないか、2つの場合しか存在しない / 順序が関係ない → 順番に変形するかしないかを決めるケース&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;特定の形の答えだけを考慮できるのか？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;正規化手法&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;様々な答えのうち、形は違うが結果的に同じものをグループ化し、グループの代表的なものだけを考慮する方法。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[効果的なC++] item 02</title><link>https://www.traceoflight.dev/ja/blog/effective-cpp-02/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/effective-cpp-02/</guid><description>#define を使うなら const, enum, inline を思い浮かべましょう。</description><pubDate>Tue, 12 Mar 2024 14:40:14 GMT</pubDate><content:encoded>&lt;h3&gt;#define よりもConst, Enum, Inlineをより好む。&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;前処理よりコンパイラを好むという表現。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;#define FOO 1.024&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;上記のケースは、コンパイル前に該当の文字列を置換する前処理機&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;上記のFOOというシンボリックの存在をコンパイラが知らないうちに削除される可能性があり、エラーにも定数で表記される可能性があるため、関連するバグが発生した場合、追跡するのに時間を浪費することになります。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;const double FOO = 1.024；&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;解決策はマクロを定数に置き換えることです。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;上記の定数はコンパイラで確実に観測でき、シンボルテーブルにも確実に入力されます。また、前処理機を通じて一括して置換された場合、そのオブジェクトのコピーが複数生成される可能性がありますが、定数の場合はコピーが複数生成されません。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[効果的なC++] item 01</title><link>https://www.traceoflight.dev/ja/blog/effective-cpp-01/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/effective-cpp-01/</guid><description>C++を言語の集合体として捉える目線は必須です。</description><pubDate>Tue, 12 Mar 2024 14:01:04 GMT</pubDate><content:encoded>&lt;h3&gt;C++ はマルチパラダイムのプログラミング言語&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;もともとはオブジェクト指向機能を追加した C から始まった&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;現在は手続き型・オブジェクト指向・関数型・ジェネリック・メタプログラミングまでサポートする&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ジェネリックプログラミング: データ型に縛られず、ひとつの値が様々なデータ型を持てるようにすることで再利用性を最大化するプログラミングパラダイム&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;メタプログラミング: 自身または別のプログラムをデータとして扱い、プログラムを記述・修正すること。実行時に行うべき処理の一部をコンパイル時に行う方式を指すこともある&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;C++ を単一の言語ではなく言語の連合体として捉え、それぞれのルールに合わせる必要がある&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;C: 多くのものは C に由来するが、C++ ではより良いアプローチを提供することが多いため、より制限的で安全な範囲で使うとよい&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;オブジェクト指向 C++: クラスが存在する C++ の中心であり、オブジェクト指向設計が最も直接的に作用する領域&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Template C++: 頻繁に触れる領域ではなく、主流の C++ とほぼ相互作用しないが、TMP という強力なパラダイムを生み出した&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;STL: Template ライブラリだが非常に特殊なケースであり、STL を使う際には特有の流儀があって必ずそのルールに従う必要がある&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;上記の下位言語間で切替が起きると、戦略を変える状況に直面することがある&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;単一のルールではなく、それぞれ独自のルールを持つ下位言語の集合だと理解すれば、C++ はより分かりやすくなるはず&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>『Effective C++』はじめに</title><link>https://www.traceoflight.dev/ja/blog/effective-cpp-00/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/effective-cpp-00/</guid><description>『Effective C++』の勉強を始めた話</description><pubDate>Tue, 12 Mar 2024 12:45:19 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-fb3d40db998200c1-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;本当に久しぶりに勉強会に関する記事を書いてみる気がする。&lt;/p&gt;
&lt;p&gt;すべてを記事に書き出したわけではないが、以前合格体験記を書いた会社と比較して、もう少し良いだろうと思った会社で、システム開発を担当している。&lt;/p&gt;
&lt;p&gt;社内でこの本に関する勉強会の話が出たので、勉強するついでに以前から使っていたプラットフォームを活用してみるのも良いと思い、それに伴いコツコツと記事を書いていこうと思う。この本を通じて学習することで、もっと仕事をうまくこなせるようになりたいのだが、まだ先の話のように思えて少し気が重い…。&lt;/p&gt;
&lt;p&gt;記事は、1つの項目ごとに1つずつまとめて残していくつもりだ。ファイト！&lt;/p&gt;
</content:encoded></item><item><title>42Seoul ラピシン 口コミ</title><link>https://www.traceoflight.dev/ja/blog/42seoul-la-piscine/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/42seoul-la-piscine/</guid><description>「42ソウル・ラピシン」第10期第1次コースへの参加レポート</description><pubDate>Sat, 23 Sep 2023 17:19:05 GMT</pubDate><content:encoded>&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;就職活動を進めていた今年の半ば、SSAFYの修了が迫っていた時期、準備期間がさらに長引くのではないかと懸念し、企業への応募書類を作成すると同時に、様々なブートキャンプや教育プログラムについて調べる時間を設けた。&lt;/p&gt;
&lt;p&gt;その結果、自分に最も適した教育プログラムは42Seoulだと考え、応募することにした。&lt;/p&gt;
&lt;p&gt;理由はいくつかあったが、中でも他のブートキャンプ課程に比べて自律的な学習や時間的な柔軟性があり、比較的Low-Levelの言語を扱うという点に魅力を感じた。&lt;/p&gt;
&lt;h3&gt;ラピシン課程の進行&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-1b1c639d3d343b20-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;チェックインとラピシンへの申し込みを無事に終え、ラピシン課程を待っている間に、いくつかの企業から最終合格の通知を受けた。 当初はコースを辞退しようと考えていたが、現場で活躍する42の卒業生たちの話や42の教育課程を考慮した際、十分に両立可能だと判断し、序盤は全力で取り組み、その後は仕事と並行して進めた。&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-7a35603c5af347f5-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;42のコースについて調べた人ならある程度ご存知だろうが、入学・受講前にラピシンと呼ばれるプレコースがある。このコースはかなり過酷な部類に入るのだが…&lt;/p&gt;
&lt;p&gt;おそらく基礎のない非専攻者ならついていくのも大変だろうし、ある程度のプログラミング知識がある非専攻者なら、一生懸命取り組めば一定の成果を上げられると思う。専攻者の場合、他の理由でカリキュラムに集中できなかったり、いじめに遭わなければ、本コースへの入学は難しくはなかっただろうと考えている。&lt;/p&gt;
&lt;p&gt;個人的な考えだが、42で行われる教育は大学の課程と類似性がかなり高いため、むしろ非専攻者にとってより良いものになる可能性があると思う。大学ですでに十分な関連教育を受けていた専攻者の場合、42が提供する奨学金やその他の制度を除けば、他のブートキャンプに比べてメリットが相対的に乏しく見えた。&lt;/p&gt;
&lt;p&gt;私が入学を検討した理由は、奨学金とは別に、専門知識の不足を補える優れた教育課程だと考えたからであり、その大前提は就職したからといって変わらなかったため、ラピシンコースを最後まで完走することができた。&lt;/p&gt;
&lt;p&gt;（当然ながら、就職後は奨学金を受け取ることができない…）&lt;/p&gt;
&lt;h3&gt;結果&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-881466acbebffd64-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;幸いにも良い結果を得ることができ、今回の42Seoul第10期として本コースを受講できるようになった。現在、会社で担当している職務と似た技術スタックを使用するため、双方に良い好循環が生まれるだろうと期待している。&lt;/p&gt;
&lt;h3&gt;Q &amp;amp; A&lt;/h3&gt;
&lt;p&gt;一般的によくあるコースに関する質問に答えてみると、&lt;/p&gt;
&lt;h4&gt;1. 基礎知識なしの非専攻者でも合格可能か？&lt;/h4&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;初期の期はともかく、再挑戦が可能になったとはいえ、情報が広く出回っている現時点ではほぼ不可能だ&lt;/p&gt;
&lt;h4&gt;2. どのような人にこのコースを勧めたいか？&lt;/h4&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;まだ学部在学期間が長く残っている専攻生、就職を考慮せず期間を長く取って基礎知識を築きたい非専攻者。&lt;/p&gt;
&lt;h4&gt;3. 受講前に知っておくと良いこと？&lt;/h4&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;C言語の基礎的な概念や、初めて触れた時にすぐに理解しにくいポインタなど、知っていればいるほど良い。皆がShellの使い方を強調しているが、そこにGitの使い方を習得しておくようアドバイスしたい。&lt;/p&gt;
&lt;h4&gt;4. コースを進めながら、ぜひやってみてほしいことは？&lt;/h4&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;個人的には、最初のRushチームのメンバーが本当に素晴らしい人たちで、最後までその方々と完走した立場から言うと、他の人との交流が必ずしも必要というわけではないが、機会があれば逃さず交流してほしい。開発者にとって、コーディングと同じくらいコミュニケーション能力も重要だ！&lt;/p&gt;
</content:encoded></item><item><title>[簡単な用語整理] File System</title><link>https://www.traceoflight.dev/ja/blog/file-system/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/file-system/</guid><description>File System関連業務で使用する用語まとめ</description><pubDate>Thu, 14 Sep 2023 14:36:39 GMT</pubDate><content:encoded>&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;現在担当している業務でベースとなる用語についての知識が少し不足していると感じたので、ついでに知っていた用語まで追加で調べて、簡単にまとめてみる時間を持つことにした。&lt;/p&gt;
&lt;h3&gt;File Descriptor&lt;/h3&gt;
&lt;p&gt;1.Linux,Unix系システムでは
2.ProcessがFileを扱う時使う値の一種。&lt;/p&gt;
&lt;p&gt;プロセスがファイルを開く時、カーネルがそのプロセッサのファイルディスクリプタ番号のうち、使用していない最小の値を割り当てることで、以後、システムコールを使ってファイルをアクセスする時、ディスクリプタ値を利用してファイルを参照することができます。&lt;/p&gt;
&lt;blockquote&gt;
&lt;h4&gt;基本割り当てディスクリプタ&lt;/h4&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;標準入力 (Standard Input)&lt;/li&gt;
&lt;li&gt;標準出力 (Standard Output)
3.標準エラー (Standard Error)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Inode ### Inode&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Index Nodeの略で、ファイルを素早く探すためのノード。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;inodeはLinuxの全てのファイルにインデックスを付与し、そのファイルに対するメタデータを保有しているノードです。listコマンドで出力するメタデータをinodeが持っています。&lt;/p&gt;
&lt;h3&gt;Symbolic Link&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;元のファイルの inode を指し示す情報を持つファイル。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;内部的にファイルへのアクセスはinode番号でアクセスします。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;元のファイルに関する情報を持たない新しいinodeを持つ * 内部的にファイルアクセスはinode番号でアクセスする&lt;/p&gt;
&lt;h4&gt;cf) Hard Link&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;新しいinodeを持つファイルではなく、inodeだけをそのままコピーしたファイル。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;本当のコピーとの違いは、data記録がコピーと違って追加的に発生しないこと。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Block Device &amp;amp; Character Device&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;データ転送方式の違いでデバイスを分類&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Block: ブロックやセクタなどの定量単位でデータ転送、IO転送速度が速い。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Character: Byte単位でデータ転送、IO転送速度が多少遅くなる可能性がありますが、Application端でBuffering制御を通じた性能差が存在します。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Raw Device&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;ファイルシステムがset upされていないデバイス&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;OSカーネルによってバッファリングされず、DeviceからDataを直接転送、独自のキャッシュシステムを持つ場合に使用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Disk IO性能が良く、CPUオーバーヘッドが少ない。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;OS ファイルシステムのオーバーヘッドを回避でき、OSバッファサイズを減らすことができる。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;shared diskの場合、システムに構成すると同時アクセスができないため、raw deviceとして使用。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;IO Scheduler&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;ディスクI/Oを効率的にするために、リクエストをソート、マージし、処理順序を決定するシステムの一部。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;探索時間が高く、同じ場所へのリクエストをマージすることが効果的なHDDのようなデバイスに特に有効で、SSDでは効果が半減します。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;種類&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;noop: no-operation, 性能の高いディスクに使用します。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;cfq (completely fair queueing)：プロセスごとにIOキューを付与し、できるだけ均等に予約、大量のプロセスが細かなIOを発生させるときに使用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;deadline: 限界点に近いほど優先処理、遅延時間に対する最適化、I/O全てバランスよく処理し、少数のプロセスが多数のI/Oを発生させる環境に適しています。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;anticipacy: 今後発生するI/O要求の位置を予測し、近い位置に存在するI/O要求から処理する方式、伝統的なHDDで使用する構造、入出力を集めて処理する性質があり、遅延時間が長くなる可能性がある。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[BOJ 9519, CPP] 眠い</title><link>https://www.traceoflight.dev/ja/blog/boj9519/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj9519/</guid><description>BOJ 9519、「眠い」問題のC++解法</description><pubDate>Mon, 04 Sep 2023 14:32:38 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;[BOJ 9519](&lt;a href=&quot;https://www.acmicpc.net/problem/9519&quot;&gt;https://www.acmicpc.net/problem/9519&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;h3&gt;分類&lt;/h3&gt;
&lt;p&gt;実装、文字列、シミュレーション&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;この問題については、最初は全探索による解法を試みた。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;まず文字列の長さを測定&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;0 ～ 文字列の長さ分の数値ベクトルを割り当て&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;問題の条件に従って繰り返し反転&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;指定回数だけ反転させた場合、そのハッシュ値を利用して逆順に配置&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;元の姿を確認できる！&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ここで最も重要な点は、問題の条件に従って繰り返し反転させることだが、繰り返し反転させた場合、必ず初期配列と同じ状態に戻る周期が存在するという点が核心である。&lt;/p&gt;
&lt;p&gt;上記の規則を見つけた後、その部分を細分化すると&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;まず文字列の長さを測定&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;0 ～ 文字列の長さ分の数値ベクトルを割り当てる&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;1回目から（文字列の長さ - 1）回目まで周期をチェック&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;全体の反転回数を周期で割った回数だけ繰り返し、ハッシュを導出&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;指定回数だけ反転させた場合、そのハッシュ値を利用して逆順に配置&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;元の状態を確認できる！&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このようになる。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i &amp;lt;= target_length - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i++)
    {
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; j = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; j &amp;lt; target_length / &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;; j++)
        {
            temp = result.&lt;span class=&quot;hljs-built_in&quot;&gt;back&lt;/span&gt;();
            result.&lt;span class=&quot;hljs-built_in&quot;&gt;pop_back&lt;/span&gt;();
            result.&lt;span class=&quot;hljs-built_in&quot;&gt;insert&lt;/span&gt;(result.&lt;span class=&quot;hljs-built_in&quot;&gt;begin&lt;/span&gt;() + &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * j + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, temp);
        }

		&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (start_vector == result)
		{
			cycle = i;
			&lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt; ;
		}
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当初は上記のように配列を直接操作する方式を採用していたが、この場合、insert以降の配列をすべて移動させる必要があり、一種のオーバーヘッドが発生するため、処理時間が若干長くなる傾向が見られた。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i &amp;lt;= target_length - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i++)
    {
		temp_vector.&lt;span class=&quot;hljs-built_in&quot;&gt;clear&lt;/span&gt;();
		temp_vector.&lt;span class=&quot;hljs-built_in&quot;&gt;resize&lt;/span&gt;(target_length);
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; j = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; j &amp;lt; target_length; j++)
        {
			&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (!(j % &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;))
				temp_vector[j] = result[j / &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;];
			&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;
				temp_vector[j] = result[target_length - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; - (j / &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;)];
        }

		&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (start_vector == temp_vector)
		{
			cycle = i;
			&lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt; ;
		}
		&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;
			result = temp_vector;
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;そこで、以降は上記のような方式を用いて配列を事前に作成し、値を一つずつ挿入する方式を採用することで、最大でも配列の長さ分の時間しかかからないようにした。&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// 졸려&lt;/span&gt;

&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;lt;vector&amp;gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;namespace&lt;/span&gt; std;

&lt;span class=&quot;hljs-function&quot;&gt;vector&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;flicker_action&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; target_length, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; count)&lt;/span&gt;&lt;/span&gt;;

&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;void&lt;/span&gt;)&lt;/span&gt;
&lt;/span&gt;{
    ios_base::&lt;span class=&quot;hljs-built_in&quot;&gt;sync_with_stdio&lt;/span&gt;(&lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;);
    cin.&lt;span class=&quot;hljs-built_in&quot;&gt;tie&lt;/span&gt;(&lt;span class=&quot;hljs-literal&quot;&gt;NULL&lt;/span&gt;);
    cout.&lt;span class=&quot;hljs-built_in&quot;&gt;tie&lt;/span&gt;(&lt;span class=&quot;hljs-literal&quot;&gt;NULL&lt;/span&gt;);

    &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; flicker_number;
    string result_string, init_string;
    vector&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;char&lt;/span&gt;&amp;gt; string_vector;
    vector&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;&amp;gt; idx_vector;

    cin &amp;gt;&amp;gt; flicker_number;
    cin.&lt;span class=&quot;hljs-built_in&quot;&gt;ignore&lt;/span&gt;();
    &lt;span class=&quot;hljs-built_in&quot;&gt;getline&lt;/span&gt;(cin, result_string);

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;) result_string.&lt;span class=&quot;hljs-built_in&quot;&gt;length&lt;/span&gt;(); i++)
        string_vector.&lt;span class=&quot;hljs-built_in&quot;&gt;push_back&lt;/span&gt;(result_string[i]);
    

    idx_vector = &lt;span class=&quot;hljs-built_in&quot;&gt;flicker_action&lt;/span&gt;(result_string.&lt;span class=&quot;hljs-built_in&quot;&gt;length&lt;/span&gt;(), flicker_number);
    init_string.&lt;span class=&quot;hljs-built_in&quot;&gt;resize&lt;/span&gt;(result_string.&lt;span class=&quot;hljs-built_in&quot;&gt;length&lt;/span&gt;());

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;) result_string.&lt;span class=&quot;hljs-built_in&quot;&gt;length&lt;/span&gt;(); i++)
        init_string[idx_vector[i]] = result_string[i];

    cout &amp;lt;&amp;lt; init_string &amp;lt;&amp;lt; endl;
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;);
}

&lt;span class=&quot;hljs-function&quot;&gt;vector&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;&amp;gt; &lt;span class=&quot;hljs-title&quot;&gt;flicker_action&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; target_length, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; count)&lt;/span&gt;
&lt;/span&gt;{
    vector&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;&amp;gt; result, temp_vector, start_vector;
	&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; cycle;

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; target_length; i++)
        result.&lt;span class=&quot;hljs-built_in&quot;&gt;push_back&lt;/span&gt;(i);

	start_vector = result;
	cycle = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i &amp;lt;= target_length - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i++)
    {
		temp_vector.&lt;span class=&quot;hljs-built_in&quot;&gt;clear&lt;/span&gt;();
		temp_vector.&lt;span class=&quot;hljs-built_in&quot;&gt;resize&lt;/span&gt;(target_length);
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; j = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; j &amp;lt; target_length; j++)
        {
			&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (!(j % &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;))
				temp_vector[j] = result[j / &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;];
			&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;
				temp_vector[j] = result[target_length - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; - (j / &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;)];
        }

		&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (start_vector == temp_vector)
		{
			cycle = i;
			&lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt; ;
		}
		&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;
			result = temp_vector;
    }

	result = start_vector;

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; (count % cycle); i++)
    {
		temp_vector.&lt;span class=&quot;hljs-built_in&quot;&gt;clear&lt;/span&gt;();
		temp_vector.&lt;span class=&quot;hljs-built_in&quot;&gt;resize&lt;/span&gt;(target_length);
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; j = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; j &amp;lt; target_length; j++)
        {
			&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (!(j % &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;))
				temp_vector[j] = result[j / &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;];
			&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;
				temp_vector[j] = result[target_length - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; - (j / &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;)];
        }

		result = temp_vector;
    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; (result);
}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[BOJ 4821, CPP] ページ数カウント</title><link>https://www.traceoflight.dev/ja/blog/boj4821/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj4821/</guid><description>BOJ 4821, &quot;ページカウント&quot;問題のC++の解法</description><pubDate>Sat, 26 Aug 2023 15:04:16 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/4821&quot;&gt;BOJ 4821&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;分類&lt;/h3&gt;
&lt;p&gt;実装、文字列、パース&lt;/p&gt;
&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;最近入社することになって、かなり忙しい日々が続いている。会社にいること自体に負担を感じる新人なので…しばらくは適応にいっぱいになりそうだ！それでも色々な話を地道に書こうと記録しているので、近いうちに語れるはず。&lt;/p&gt;
&lt;p&gt;最近 C を学べる良い機会を得たし、Python や Java で時間切れの壁にぶつかるたびに残念な思いをしていたので、これを機に C++ で問題演習を進めてみたいと思った。&lt;/p&gt;
&lt;p&gt;短い期間の使用経験ではあるが、実装の多くの場面で手間がかかるとはいえ、それを速さが補ってくれる感覚をかなり受ける。慣れれば速さという長所だけを取り込めるだろうか…？楽しみだ。&lt;/p&gt;
&lt;h3&gt;解説&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;vector: 動的配列構造で、配列に似ているがサイズを動的に変えられ、メモリ確保が自動という大きな利点がある！&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;npos: no position、有効でない位置をチェックするためのインデックス値&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;stringstream: 文字列をストリームとして扱うための仕組みで、入出力と同じ方式で扱えるため、パースによく使われる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;基本ロジックは、ページ数の上限分の範囲をカバーできる bool 配列を作り、入力で来たページ範囲をすべてチェックし、最後にカウントした値を出力するだけだ。&lt;/p&gt;
&lt;p&gt;ただし問題で提示される数値範囲が int を超える値で与えられる可能性があるため、それを制御する変数設定が必要であり、範囲が逆順で与えられた場合はチェックしないという例外も注意する必要がある。&lt;/p&gt;
&lt;p&gt;こういった処理を Python で解くときはとても楽だったが、C++ にしたところコードがかなり長くなってしまった…&lt;/p&gt;
&lt;h3&gt;解法コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// ページ数え&lt;/span&gt;

&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;lt;vector&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;#&lt;span class=&quot;hljs-keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;lt;sstream&amp;gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;namespace&lt;/span&gt; std;

&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;void&lt;/span&gt;)&lt;/span&gt;
&lt;/span&gt;{
	ios_base::&lt;span class=&quot;hljs-built_in&quot;&gt;sync_with_stdio&lt;/span&gt;(&lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;);
	cin.&lt;span class=&quot;hljs-built_in&quot;&gt;tie&lt;/span&gt;(&lt;span class=&quot;hljs-literal&quot;&gt;NULL&lt;/span&gt;);
	cout.&lt;span class=&quot;hljs-built_in&quot;&gt;tie&lt;/span&gt;(&lt;span class=&quot;hljs-literal&quot;&gt;NULL&lt;/span&gt;);

	&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;				total_page, seperator, start, end, result;
	string			temp, each_range;
	vector&amp;lt;string&amp;gt;	line_info;
	vector&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;bool&lt;/span&gt;&amp;gt;	print_info;
	vector&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;&amp;gt;		result_vector;

	&lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;)
	{
		cin &amp;gt;&amp;gt; total_page;

		&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (!total_page)
			&lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt; ;
		&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;
		{
			print_info.&lt;span class=&quot;hljs-built_in&quot;&gt;assign&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;1001&lt;/span&gt;, &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;);
			cin.&lt;span class=&quot;hljs-built_in&quot;&gt;ignore&lt;/span&gt;();
			&lt;span class=&quot;hljs-built_in&quot;&gt;getline&lt;/span&gt;(cin, temp);
			&lt;span class=&quot;hljs-function&quot;&gt;stringstream &lt;span class=&quot;hljs-title&quot;&gt;range_stream&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(temp)&lt;/span&gt;&lt;/span&gt;;

			&lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;hljs-built_in&quot;&gt;getline&lt;/span&gt;(range_stream, each_range, &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;,&amp;#x27;&lt;/span&gt;))
			{
				&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (each_range.&lt;span class=&quot;hljs-built_in&quot;&gt;find&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;-&amp;#x27;&lt;/span&gt;) == string::npos)
				{
					&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (each_range.&lt;span class=&quot;hljs-built_in&quot;&gt;length&lt;/span&gt;() &amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;hljs-built_in&quot;&gt;stoi&lt;/span&gt;(each_range) &amp;lt;= &lt;span class=&quot;hljs-number&quot;&gt;1000&lt;/span&gt;)
						print_info[&lt;span class=&quot;hljs-built_in&quot;&gt;stoi&lt;/span&gt;(each_range)] = &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;;
				}
				&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;
				{
					seperator = each_range.&lt;span class=&quot;hljs-built_in&quot;&gt;find&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;-&amp;#x27;&lt;/span&gt;);
					&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (each_range.&lt;span class=&quot;hljs-built_in&quot;&gt;substr&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, seperator).&lt;span class=&quot;hljs-built_in&quot;&gt;length&lt;/span&gt;() &amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;
						&amp;amp;&amp;amp; &lt;span class=&quot;hljs-built_in&quot;&gt;stoi&lt;/span&gt;(each_range.&lt;span class=&quot;hljs-built_in&quot;&gt;substr&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, seperator)) &amp;lt;= &lt;span class=&quot;hljs-number&quot;&gt;1000&lt;/span&gt;)
						start = &lt;span class=&quot;hljs-built_in&quot;&gt;stoi&lt;/span&gt;(each_range.&lt;span class=&quot;hljs-built_in&quot;&gt;substr&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, seperator));
					&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;
						start = &lt;span class=&quot;hljs-number&quot;&gt;1001&lt;/span&gt;;
					&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (each_range.&lt;span class=&quot;hljs-built_in&quot;&gt;substr&lt;/span&gt;(seperator + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, each_range.&lt;span class=&quot;hljs-built_in&quot;&gt;size&lt;/span&gt;()).&lt;span class=&quot;hljs-built_in&quot;&gt;length&lt;/span&gt;() &amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;
						&amp;amp;&amp;amp; &lt;span class=&quot;hljs-built_in&quot;&gt;stoi&lt;/span&gt;(each_range.&lt;span class=&quot;hljs-built_in&quot;&gt;substr&lt;/span&gt;(seperator + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, each_range.&lt;span class=&quot;hljs-built_in&quot;&gt;size&lt;/span&gt;())) &amp;lt;= &lt;span class=&quot;hljs-number&quot;&gt;1000&lt;/span&gt;)
						end = &lt;span class=&quot;hljs-built_in&quot;&gt;stoi&lt;/span&gt;(each_range.&lt;span class=&quot;hljs-built_in&quot;&gt;substr&lt;/span&gt;(seperator + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, each_range.&lt;span class=&quot;hljs-built_in&quot;&gt;size&lt;/span&gt;()));
					&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;
						end = &lt;span class=&quot;hljs-number&quot;&gt;1001&lt;/span&gt;;
					&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (start &amp;lt;= end)
					{
						&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; i = start; i &amp;lt;= end; i++)
						{
							&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (i &amp;lt;= total_page)
								print_info[i] = &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;;
						}
					}
				}
			}

			result = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
			&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i &amp;lt;= total_page; i++)
			{
				&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (print_info[i])
					result++;
			}
			result_vector.&lt;span class=&quot;hljs-built_in&quot;&gt;push_back&lt;/span&gt;(result);
		}
	}

	&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; i = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;) result_vector.&lt;span class=&quot;hljs-built_in&quot;&gt;size&lt;/span&gt;(); i++)
		cout &amp;lt;&amp;lt; result_vector[i] &amp;lt;&amp;lt; endl;

	&lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;);
}

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>雑多なShellの記録 (3)</title><link>https://www.traceoflight.dev/ja/blog/shell-3/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/shell-3/</guid><description>Shellを学ぶ旅、第3話</description><pubDate>Tue, 25 Jul 2023 18:05:52 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;23-07-26 誤記を修正&lt;/p&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;23-07-27 コマンドを追加&lt;/p&gt;
&lt;h3&gt;BC&lt;/h3&gt;
&lt;p&gt;Basic Calculatorの略称。POSIX標準に基づいて提供され、Unix系システムで使用できる計算機である。&lt;/p&gt;
&lt;p&gt;特徴としては&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;スタックベースの構造を採用&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;逆ポーランド記法（Reverse Polish notation）に対応&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;2 + 3&amp;#x27;&lt;/span&gt; | dc
dc &amp;lt;&amp;lt;&amp;lt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;2 3 + p&amp;#x27;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;TR&lt;/h3&gt;
&lt;p&gt;文字の置換、削除、圧縮などを可能にするコマンド。通常、パイプラインを通じて追加の処理と組み合わせて使用される。&lt;/p&gt;
&lt;p&gt;*&lt;code&gt;tr [문자열1] [문자열2]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;: 長さが同じ文字列を2つ使用し、通常は文字列1の対応する文字を、文字列2の同じインデックスの文字に置き換える。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;``: 長さが同じ2つの文字列を使用し、通常は文字列1の対応する文字を文字列2の同一インデックスの文字に置き換える。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-c&lt;/code&gt;: 2番目のセットの最後の文字が、セットに含まれていない文字をすべて置換する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-s&lt;/code&gt;: 繰り返し発生するシーケンスをすべて削除し、設定された文字に置き換える。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-d&lt;/code&gt;: 該当する文字を削除する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-t&lt;/code&gt;: コマンド実行前に、2つの文字列の長さを揃えるように切り取る処理を行う。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;SED (&lt;/h3&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;様々な編集機能をサポートするコマンド。基本的にバッファに基づいて動作するため、元のファイルは修正されるまで影響を受けない。&lt;/p&gt;
&lt;h4&gt;コマンドオプション&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;/[パターン]/ の形式でパターンを指定する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;g を追加すると、一致するすべてのパターンに対して処理を行う&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;カンマ (,) を使用して範囲を指定する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;p: すべての行を出力し、パターンに一致する場合は1回追加で出力&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-n オプションを追加: 基本出力を除外し、パターンに一致する行のみを出力&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;d: パターンの削除を実行&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;s: パターンの置換&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;e: 複数行編集&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;code&gt;n;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;: 次の行&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;y: 置換&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;i: 挿入&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;c: 変更&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;a: 追加&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 약간의 응용&lt;/span&gt;

sed -n &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;n; p&amp;#x27;&lt;/span&gt;: 짝수 줄 출력
sed -n &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;p; n&amp;#x27;&lt;/span&gt;: 홀수 줄 출력
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;WC&lt;/h3&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;Word Count&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;-l: ファイルの行数を確認&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;-c: ファイルのバイト数を確認&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;-m: ファイル内の文字数を確認&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;-w: ファイル内の単語数を確認&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>雑多なShellの記録 (2)</title><link>https://www.traceoflight.dev/ja/blog/shell-2/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/shell-2/</guid><description>Shellを学ぶ旅、第2話</description><pubDate>Thu, 20 Jul 2023 16:49:40 GMT</pubDate><content:encoded>&lt;h3&gt;リスト&lt;/h3&gt;
&lt;p&gt;通常、``ls`&lt;/p&gt;
&lt;p&gt;` として使用されるコマンドです。このコマンドを使用することで、ディレクトリの内容を確認できます。追加のコマンドを活用すれば、リストを適切な用途に合わせて出力できるため、非常に便利です。&lt;/p&gt;
&lt;p&gt;よく使われるコマンドや特定の用途に必要なコマンドを記載します。さらに詳しい情報が必要な場合は、``man`&lt;/p&gt;
&lt;p&gt;` でマニュアルを表示するか、以下のリンク先のドキュメントを参照してください。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-l&lt;/strong&gt;: ロングデフォルト形式で表示する。
&lt;code&gt;working john 2008-07-25 11:56 csrc 1 alias.c-4.5 27&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-al&lt;/strong&gt;: 全体の内容を表示する。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-t&lt;/strong&gt;: 変更日時順にソートする。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-m&lt;/strong&gt;: 各要素をコンマとスペース (, ) で区切って出力
&lt;code&gt;this, is, example&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-r&lt;/strong&gt;: 現在の順序と逆の順に出力&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-R&lt;/strong&gt;: サブディレクトリの内容まで再帰的に出力する&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-h&lt;/strong&gt;: 単位を人間が読みやすい形式で出力する（m、k、gなどの単位を使用）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;[List Manual](&lt;a href=&quot;https://man7.org/linux/man-pages/man1/ls.1.html&quot;&gt;https://man7.org/linux/man-pages/man1/ls.1.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;h3&gt;Find&lt;/h3&gt;
&lt;p&gt;ファイルを検索するコマンド。指定した場所を基準に、サブディレクトリまで全て検索して結果を出力する。 出力以外にも様々な機能を提供しており、本当に活用したいのであれば正規表現について学んでみよう。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-name&lt;/strong&gt;: 検索対象の名前に関する情報を入力するコマンドであり、正規表現による制約が可能である。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-o&lt;/strong&gt;: or演算子と同じ機能を持つコマンド。Aという条件にaという動作を、Bという条件にbという動作を行わせたい場合は、このコマンドを使用する。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-exec&lt;/strong&gt;: 追加のコマンドを適用できるコマンド&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-delete&lt;/strong&gt;: 見つかったファイルを削除するコマンド&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;-print&lt;/strong&gt;: 見つかったファイルを出力するコマンド&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;同様に、その他のコマンドはここで検索すればよい。&lt;/p&gt;
&lt;p&gt;[Find Manual](&lt;a href=&quot;https://man7.org/linux/man-pages/man1/find.1.html&quot;&gt;https://man7.org/linux/man-pages/man1/find.1.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;h3&gt;Echo &amp;amp; Printf&lt;/h3&gt;
&lt;p&gt;シェルではechoをよく使うが、echo以外にもprintfを使うことができる。正直なところ、改行文字のデフォルト値の有無くらいしか分からなかったので、この部分はChatGPTに助けを求めた！&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-2f0cb8656eb567ac-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;意外にも、よく使われるechoよりもprintfの方が、より精巧な機能をサポートしているそうだ。軽く使う程度では違いを感じられないので、とりあえずこの程度の情報だけ知っておこうと思う。&lt;/p&gt;
</content:encoded></item><item><title>雑多なShellの記録 (1)</title><link>https://www.traceoflight.dev/ja/blog/shell-1/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/shell-1/</guid><description>Shellを学ぶ旅</description><pubDate>Mon, 17 Jul 2023 17:25:08 GMT</pubDate><content:encoded>&lt;h3&gt;ファイルの作成関連&lt;/h3&gt;
&lt;p&gt;*&lt;code&gt;touch&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;: ファイルの作成&lt;/p&gt;
&lt;p&gt;*&lt;code&gt;mkdir&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;: フォルダの作成&lt;/p&gt;
&lt;p&gt;*&lt;code&gt;chmod&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;: ファイルの権限設定&lt;/p&gt;
&lt;p&gt;*&lt;code&gt;chown&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;: ファイルの所有者の設定&lt;/p&gt;
&lt;p&gt;*&lt;code&gt;mv&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;: ファイルの移動および名前の変更&lt;/p&gt;
&lt;h3&gt;ファイル情報の確認&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-f343d0b04676158d-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;*&lt;code&gt;-rwxr-xr-x&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;の部分: ファイルの権限を確認する部分&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先頭の一文字はファイルタイプを表す (-, d, l)&lt;/li&gt;
&lt;li&gt;読み取り・書き込み・実行権限について、ユーザー、グループ、その他に対して3桁の形式で表記される。
2進数形式では、rが4、wが2、xが1の値を持つため、&lt;code&gt;rwx&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;の値は7に、&lt;code&gt;-xr&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;は4に変換できる。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;chmod&lt;/span&gt; 744 Slack.lnk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このような形式のコマンドで権限設定が可能である。
3. リンク数（1と書かれている部分）
4. 所有者（空白の部分）と所有グループに関する情報（197609）
5. ファイルサイズ
6. 最終更新日時に関する情報
7. ファイル名&lt;/p&gt;
&lt;h3&gt;ssh-keygen&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Secure Shellの公開鍵によるGit認証に使用されるケースが多い&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;WindowsおよびLinuxのパッケージに含まれている&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;鍵を生成すると、keyファイルと&lt;code&gt;.pub&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ファイルが生成されるが、.pubファイルの内容をサーバーに提供し、鍵と錠前の形式で使用&lt;/p&gt;
&lt;h3&gt;シェルでファイルの容量を調整する方法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mkfile -n 10k test.sh
fallocate -l 10k test.sh
&lt;span class=&quot;hljs-built_in&quot;&gt;truncate&lt;/span&gt; -s 10k test.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;既存のファイルや新規作成するファイルにおいて、このコマンドを使用してファイルのサイズを調整できる。&lt;/p&gt;
&lt;h3&gt;ファイルの最終更新日時を変更する&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;touch&lt;/span&gt; -t 2301011234 timefile.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;touchの応用として、2023年1月1日12時34分に最終更新が行われたものとして、ファイルの最終更新日時を変更できるコマンド&lt;/p&gt;
&lt;h3&gt;ハードリンク &amp;amp; シンボリックリンク&lt;/h3&gt;
&lt;h4&gt;シンボリックリンク (ソフトリンク)&lt;/h4&gt;
&lt;p&gt;Windowsのショートカットと同様に、特定のフォルダに存在する元のファイルを利用できるようにするリンクであり、元ファイルが削除された場合は機能しない&lt;/p&gt;
&lt;h4&gt;ハードリンク&lt;/h4&gt;
&lt;p&gt;シンボリックリンクとは異なり、原本をコピーして複製を作成するという違いがあり、原本が削除された場合、シンボリックリンクは使用できなくなるが、ハードリンクの場合は結局同じファイルであるため、引き続き使用可能である。リンク数に影響するリンク。&lt;/p&gt;
&lt;h4&gt;コード&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;ln&lt;/span&gt; [대상 폴더] [만들 링크 파일명] &lt;span class=&quot;hljs-comment&quot;&gt;# Hard Link&lt;/span&gt;
&lt;span class=&quot;hljs-built_in&quot;&gt;ln&lt;/span&gt; -s [대상 폴더] [만들 링크 파일명] &lt;span class=&quot;hljs-comment&quot;&gt;# Symbolic Link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;削除コマンドは ``rm`&lt;/p&gt;
&lt;p&gt;` であり、ファイルを削除するのと同じように解除できる&lt;/p&gt;
&lt;h3&gt;Diff &amp;amp; Patch&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;diff a b &amp;gt; difference.patch
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;diff&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;は、2つのファイルを行単位で比較するコマンドであり、&lt;code&gt;patch&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;は、diffなどで確認した比較内容に基づいてファイルを修正できるコマンドである。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;patch -p{패치 경로의 depth} [원본] [patch 파일] &lt;span class=&quot;hljs-comment&quot;&gt;# 패치 파일 적용&lt;/span&gt;
patch -p{패치 경로의 depth} -R [원본] [patch 파일] &lt;span class=&quot;hljs-comment&quot;&gt;# 적용된 패치 파일을 되돌림&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上記のような形式で、既存のファイルに対してdiffで判定された内容をそのまま適用・解除することができる。&lt;/p&gt;
</content:encoded></item><item><title>2023年 アシアナIDT 下半期採用選考の体験談</title><link>https://www.traceoflight.dev/ja/blog/2023-idt/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/2023-idt/</guid><description>アシアナIDTの採用プロセスに参加した体験談</description><pubDate>Sat, 15 Jul 2023 09:23:14 GMT</pubDate><content:encoded>&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;開発職も経済の影響を受けているせいか、採用選考の数や採用人数が昨年より大幅に減少した。結局のところ、チャンスが訪れた時にそれを掴める人が勝者となるため、だからこそ、より一層着実に取り組まなければならないと考えている。&lt;/p&gt;
&lt;h3&gt;書類選考 &amp;amp; 適性検査&lt;/h3&gt;
&lt;p&gt;他社と同様、書類選考で特筆すべき点はなかったが、金融業界の採用と同様に適性検査を実施しなければならない点が特徴的だった。&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-de67b160b1aa0129-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;正常にすべて回答したと思っていたが、（注意）と表示されていて不安ではあったものの、カメラやマイクなどに異常はなかったためそのまま提出し、&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-bfb139a0580b844d-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;問題なく書類選考を通過することができた。余裕があれば、適性検査をもう一度確認していたと思う。&lt;/p&gt;
&lt;h3&gt;コーディングテスト&lt;/h3&gt;
&lt;p&gt;難易度も問題のタイプも、どちらも金融業界のコーディングテストを思い出した。全体的に平易な難易度で、SQLまで似たような形式だったと思う。&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-04f741f5ffa434c7-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;結果は合格、アシアナIDTの面接会場に行く機会を得た！&lt;/p&gt;
&lt;h3&gt;最終面接&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-3d3262bf0a5592a0-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;ビルの入り口で面接者の訪問証を受け取り、向かった。準備中に読んだ他の体験談と同様に、ディスカッション面接と人物面接が行われた。&lt;/p&gt;
&lt;p&gt;ディスカッション面接については、何か大きな役割を果たすことを期待したというよりは、コミュニケーションに問題がある人を選別するプロセスだと考えた。&lt;/p&gt;
&lt;p&gt;人物面接では、書類やコーディングテストの結果などを総合した内容に基づいて質問を受けた。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;入社志願者の中でこのような人はほとんどいないだろうが、会社について十分に調べずに来た人は、質問に難しさを感じるかもしれないと思った。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;面接官が応募者に意見を求めようとする様子から、会社の発展方向について真剣に考えているのだと感じた。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;最終結果&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-1e2142ef3cf56fc9-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;面接では普段よりうまく答えられたと思っていたが、それなりに高い競争率にもかかわらず合格することができた！&lt;/p&gt;
&lt;h3&gt;所感&lt;/h3&gt;
&lt;p&gt;IT業界に入るときに聞く話があまりにも多いため、SI/SMに対して漠然とした恐怖心を抱くケースが多く、実際私もそうだった。&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-94c515233c0d9259-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;s&gt;ハイパーリアリズム&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;それでも、国内IT業界の大部分はITサービスではなくSI/SMが中心であり、これを軽視すれば合理的とは言えない選択をしてしまう可能性もあると思う。&lt;/p&gt;
&lt;p&gt;就職市場が以前とは異なるだけに、あまりにも狭い目標に向かって進むよりも、今できる最善の選択肢は何かを考える感覚が必要な時期だと考えており、これを心に留めておけば良い結果を得られるだろうと思う！&lt;/p&gt;
</content:encoded></item><item><title>[面接質問】オブジェクト指向プログラミングとは？</title><link>https://www.traceoflight.dev/ja/blog/object-oriented-programming/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/object-oriented-programming/</guid><description>オブジェクト指向プログラミングの面接質問まとめ</description><pubDate>Wed, 12 Jul 2023 07:28:03 GMT</pubDate><content:encoded>&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;昨日、某企業の面接を進めながら、オブジェクト指向プログラミングについて答えなければならない場面があったのですが、明らかに知っているつもりで整理していたにもかかわらず、いざ答えようとすると、ぎこちなく話してしまったことがありました。&lt;/p&gt;
&lt;p&gt;おかげで弱い部分を指摘できたと思い、再度整理する時間を取ってみることにしました！&lt;/p&gt;
&lt;h3&gt;オブジェクトとは？&lt;/h3&gt;
&lt;p&gt;一般的な定義から説明すると以下のようになります。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;一般論: 実際に存在するもの
コンピュータサイエンス：クラスに定義された内容でメモリに生成されたもの。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;オブジェクト指向言語で定義されているものは以下の通りです。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Java: クラスのインスタンスまたは配列
Python: 属性値や振る舞いを持つデータ&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Javaのクラスはインスタンスではないが、Pythonのクラスはインスタンスである。&lt;/p&gt;
&lt;h3&gt;オブジェクト指向プログラミング&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;オブジェクトの役割と関係を定義して相互作用を通じてプログラムを構築すること。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;このように定義することができます。&lt;/p&gt;
&lt;h3&gt;オブジェクト指向言語の特徴&lt;/h3&gt;
&lt;h4&gt;抽象化&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;オブジェクト間の共通の特徴を導き出すことができる。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;クラスを定義する部分がこれに該当&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;多形性&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;少し違う方法で動作する関数に対して同じように呼び出すことができます。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;同じコマンドに対して接続されたオブジェクトに解釈を転嫁する方式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Override(内部ソースのオーバーライド), Overload(パラメータによって同じ名前の他の関数を呼び出す)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;カプセル化&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;実装した部分を外部に公開せずに隠すことができます。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;外部とのコミュニケーションが必要な場合、メソッドを通じて情報をやり取りする。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;継承&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;あるクラスが持っている特徴を他のクラスが受け継ぐこと。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;既に作成されたクラスに加え、新しいクラスを生成することができる。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[BOJ 11689, Python] GCD(n, k) = 1</title><link>https://www.traceoflight.dev/ja/blog/boj11689/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj11689/</guid><description>BOJ 11689、「GCD(n, k) = 1」問題のPythonによる解法</description><pubDate>Fri, 07 Jul 2023 06:49:25 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11689&quot;&gt;BOJ 11689&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;分類&lt;/h3&gt;
&lt;p&gt;数学、整数論、オイラー・ピー関数&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;最近、Baekjoonの問題を解く際、真の実力を高めるためには問題の分類を気にせず解くべきだと考え、実践している。しかし、今回取り上げるこの問題のようなものに出くわすと、かなり頭を悩ませることになる。&lt;/p&gt;
&lt;p&gt;この問題の場合、最初に&lt;sup&gt;1&lt;/sup&gt;0¹²までの数字を1秒以内にチェックできなければならないため、少なくともO(N)レベル以下に抑えなければならないとは考えていた。互いに素の判定であれば、通常は素因数分解を行い、重複する数字がなければよいと考えていたため、以下のコードを利用していた。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;factorize&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;target_number: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;:

    result = []
    prime_list = find_prime(target_number)

    now_number = target_number
    &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; now_number &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; each_prime &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; prime_list:
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; each_prime &amp;gt; now_number:
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

            &lt;span class=&quot;hljs-keyword&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; now_number % each_prime:
                &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; now_number % each_prime:
                    now_number //= each_prime
                result.append(each_prime)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;しかし、このコードを基にした場合、時間計算量を満たすことができなかった。結局、悩んだ末にタグを確認することに決め、&lt;code&gt;오일러 피 함수&lt;/code&gt;という新しい友人と出会うことになった。&lt;/p&gt;
&lt;p&gt;調べてみると、これはまさにこの問題そのものの関数であり、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;gt; φ(n) = {n以下の自然数のうち、nと互いに素な自然数の個数}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;このように実装することができた。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;euler_phi&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;number: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;:
    &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&amp;#x27;
    오일러 피 함수를 활용한 자연수 n과 서로소인 수의 갯수를 구하는 함수
    &amp;#x27;&amp;#x27;&amp;#x27;&lt;/span&gt;

    checker = &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;
    result = number

    &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;pow&lt;/span&gt;(checker, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) &amp;lt;= number:
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; number % checker:
            &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; number % checker:
                number //= checker

            result -= result // checker

        checker += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; number &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:
        result -= result // number

    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; result
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;2から順に進めていく。&lt;/li&gt;
&lt;li&gt;割り切れる数があるなら、割り切れる限り割り切る。（素因数分解）&lt;/li&gt;
&lt;li&gt;その数の倍数は互いに素になり得ないため、結果の数から引く。&lt;/li&gt;
&lt;li&gt;最後に残った数があるなら、その数は素数であり、その素数の倍数も互いに素になり得ないため、結果の数から引く。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ここで少し難しかったのがこの部分だった。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;gt; result -= result // checker&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;なぜ&lt;code&gt;number // checker&lt;/code&gt;を削除するのではなく、resultから割り出した値を削除するのか疑問だったが、実は当然のことだった。&lt;code&gt;n&lt;/code&gt;の倍数を削除し、&lt;code&gt;m&lt;/code&gt;の倍数もその数だけ削除すれば、結果的に&lt;code&gt;n * m&lt;/code&gt;の倍数は2回削除されることになる！&lt;/p&gt;
&lt;p&gt;このように重複して処理される数字を処理するために、すでに一度除外された数から、その数字の倍数分だけを引き算することになるのだと言えるだろう。&lt;/p&gt;
&lt;p&gt;いずれにせよ、この解法を理解した瞬間、非常に簡単な問題になる。整数論の問題にはこういう傾向があるようで、学ぶ時は良いが、いざ最初に取り組む時はいつも難しくて少し不便だ…。&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# GCD(n, k) = 1&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;euler_phi&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;target_number: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;):
    result = target_number
    check_number = &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;pow&lt;/span&gt;(check_number, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) &amp;lt;= target_number:
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; target_number % check_number:
            &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; target_number % check_number:
                target_number //= check_number
            result -= result // check_number
        check_number += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; target_number &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:
        result -= result // target_number

    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; result

target = &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;())
&lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(euler_phi(target))
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[面接の質問] 依存性注入</title><link>https://www.traceoflight.dev/ja/blog/dependency-injection/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/dependency-injection/</guid><description>DIに関する面接の質問まとめ</description><pubDate>Thu, 06 Jul 2023 11:46:58 GMT</pubDate><content:encoded>&lt;h3&gt;依存性注入&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;依存性：あるオブジェクトが別のオブジェクトを利用している関係
→ 依存性注入：その関係を設定すること&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;依存性注入が必要な理由？&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Product&lt;/span&gt; {

	&lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; Apple apple;
    
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt; {
    	&lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.apple = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Apple&lt;/span&gt;();
	}

}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このように例を見てみると、ProductというクラスがAppleのコンストラクタを使用している場合、別途注入を受けずにそのまま使用している。
Productを使用する場合、Appleがそのまま付随してくる依存関係として理解できる。 こうなると、オブジェクト同士のつながりではなく、クラス間の関係だと見なすことができる。&lt;/p&gt;
&lt;p&gt;また、もし私が&lt;code&gt;Orange&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;というクラスを追加で使用したい場合、Productクラスのコンストラクタに直接変更を加える必要があり、これは柔軟性が低いと言える。&lt;/p&gt;
&lt;p&gt;結論として、依存性注入が必要な理由を挙げると&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;クラス間の強い結合 + コードの柔軟性の低下&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;このような問題を依存性注入によって解決できるため、必要であると言えるだろう！&lt;/p&gt;
&lt;h3&gt;解決策の適用&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Fruit&lt;/span&gt; {

}

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Apple&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Fruit&lt;/span&gt; {

}

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Product&lt;/span&gt; {

	&lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; Fruit fruit;
    
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(Fruit fruit)&lt;/span&gt; {
    	&lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.fruit = fruit;
    }
    
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;各クラスが独立性を確保していることが確認できる。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;新しいFruitを追加してもProductは変わらない&lt;/li&gt;
&lt;li&gt;クラス間の関係ではなく、オブジェクト間の関係が形成される&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>[面接質問] Java Stack &amp; Heapの構造について</title><link>https://www.traceoflight.dev/ja/blog/java-stack-heap/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/java-stack-heap/</guid><description>JavaのStackとHeapに関する面接の質問まとめ</description><pubDate>Sun, 02 Jul 2023 17:19:40 GMT</pubDate><content:encoded>&lt;h3&gt;Java のメモリ構造&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;/blog/jvm@&quot;&gt;JVMの構造と原理の内容を参考にしてください&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;アプリケーション実行のために構築したJava Runtime Data Areaがメモリに位置することになる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;PC Register, Native Method Stack, Method領域は全てのスレッドが共有します。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;StackとHeap領域だけがスレッド固有の領域として持つことになります。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Heap の構造&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Eden → Survivor → Old&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;上記のような形でオブジェクトが移動するのですが、基本的には生成順で理解すればいいと思います。&lt;/p&gt;
&lt;h3&gt;Garbage Collectorの役割&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Eden: Javaオブジェクトが生成されるとすぐに保存される空間。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Survivor &amp;amp; Old: 参照度によってオブジェクトが移動された空間。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mark and Sweep&lt;/strong&gt; アルゴリズムを使用します。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Minor Garbage Collector&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;EdenとSurvivor領域(Young Generation)のメモリが許容値を超えた場合、オブジェクトの参照に基づいて領域を移動させる役割。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Major Garbage Collector&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;Old領域(Tenured Generation)のメモリが許容値を超えた場合、参照されていないオブジェクトを全て削除してメモリを回収する役割。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;削除の過程でガベージコレクタを実行するスレッドを除いた残りのスレッドを全て停止(&apos;Stop-The-World&apos;)。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Stackの構造&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;基本データ型 + 地域変数 + パラメーター&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ここで、パラメータの場合、オブジェクトのアドレス値を持ってHeap領域のオブジェクトを参照する形で使用されます。&lt;/p&gt;
&lt;p&gt;→ パラメータが他のオブジェクトを参照する場合、アドレス値が変わるだけで、Heapに保存されたオブジェクトがすぐに消えることはありません！ (Major GCが実行されるまでHold)&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://coding-factory.tistory.com/828@&quot;&gt;コーディングファクトリーの記事&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>[BOJ 27231, Python] 2023年が楽しみな理由</title><link>https://www.traceoflight.dev/ja/blog/boj27231/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj27231/</guid><description>BOJ 27231、「2023年が楽しみな理由」の問題のPythonによる解答</description><pubDate>Fri, 30 Jun 2023 10:32:49 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/27231&quot;&gt;BOJ 27231&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;分類&lt;/h3&gt;
&lt;p&gt;ブルートフォースアルゴリズム、バックトラッキング&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-11d42ef72dcdad8a-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;最近、以前解けなかった問題が何とか解けるようになってきたのを見ると、実力が向上したと感じて気分が良い。&lt;/p&gt;
&lt;p&gt;この問題の場合も、最後の挑戦は5ヶ月前に大会で出題された時だが、その間にも解決の兆しが見えない解法を試行錯誤したことが何度かあった。&lt;/p&gt;
&lt;p&gt;最後の挑戦が何度もあった理由は、たった一つの条件が欠けていたからだが、この条件が抜けているだけでなぜタイムリミットオーバーになってしまうのか、その理由はまだよく分からない。 &lt;s&gt;後で補足できる理由ならいいのだが。&lt;/s&gt; → 下の内容を整理しているうちに思い出した。やはりブログの整理は最高だ！&lt;/p&gt;
&lt;p&gt;問題の解法アプローチを紹介すると&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;+ 記号を入れる座標をビットマスクを活用して全数チェック&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;集合、あるいは重複を許さないリストに入れてソート&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;累乗のサイズを徐々に増やしながら、最終的に最初に与えられた数（どんなに細かく分割してもこの数より大きくなることはないため）まで存在する数字の個数をカウント&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そしてここで問題が発生した。&lt;/p&gt;
&lt;p&gt;0、1で構成された数の場合、単一の数字に分割すると、いくら累乗しても値が変わらないため、&lt;code&gt;Hello, BOJ 2023!&lt;/code&gt;を出力する必要があるが、私は単純に1の場合だけを除外していた。&lt;/p&gt;
&lt;p&gt;いくら二乗しても数値が増加しなかったため、whileループに引っかかり、タイムリミットオーバーとなってしまったのだ！その部分を確認するために、単一の数字について2を超えるかどうかをチェックし、2を超える項がない場合は無条件に&lt;code&gt;Hello, BOJ 2023!&lt;/code&gt;を出力するようにすることで、エッジケースを処理し、正解を得ることができた。&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 2023년이 기대되는 이유&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sys

&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt; = sys.stdin.readline

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;pow_target&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;target_num: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, exponent: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;:

    result = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

    now_number = target_num

    &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; now_number:
        result += &lt;span class=&quot;hljs-built_in&quot;&gt;pow&lt;/span&gt;((now_number % &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;), exponent)
        now_number //= &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; result

testcase = &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;())
result_dict = &lt;span class=&quot;hljs-built_in&quot;&gt;dict&lt;/span&gt;()
output = []

&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(testcase):

    target_number = &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().rstrip(&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;\n&amp;#x27;&lt;/span&gt;)

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; result_dict.get(target_number) &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
        output.append(result_dict[target_number])

    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:

        is_under_limit = &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;

        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; each_element &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(target_number):
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(each_element) &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:
                is_under_limit = &lt;span class=&quot;hljs-literal&quot;&gt;False&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; is_under_limit:
            result_dict[target_number] = &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;Hello, BOJ 2023!&amp;#x27;&lt;/span&gt;
            output.append(&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;Hello, BOJ 2023!&amp;#x27;&lt;/span&gt;)
            &lt;span class=&quot;hljs-keyword&quot;&gt;continue&lt;/span&gt;

        length = &lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(target_number)

        check_list = []
        check_list.append(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(target_number))

        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &amp;lt;&amp;lt; length):

            calc_result = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

            now_start = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
            now_end = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; j &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(length):

                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; i &amp;amp; (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &amp;lt;&amp;lt; j):
                    now_end = j
                    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; now_end:
                        calc_result += &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(target_number[now_start : now_end])
                    now_start = now_end
                    
            calc_result += &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(target_number[now_start : length + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;])

            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; calc_result &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; check_list:
                check_list.append(calc_result)

        &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
            result = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

            check_amount = &lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(check_list)
            check_list.sort()

            max_value = check_list[-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]
            pointer = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
            counter = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

            &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; pointer &amp;lt; check_amount:
                now_result = pow_target(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(target_number), counter)

                &lt;span class=&quot;hljs-comment&quot;&gt;# 종료 조건 1&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; now_result &amp;gt; max_value:
                    &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

                &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; pointer &amp;lt; check_amount &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; now_result &amp;gt; check_list[pointer]:
                    pointer += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

                &lt;span class=&quot;hljs-comment&quot;&gt;# 종료 조건 2&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; pointer &amp;gt;= check_amount:
                    &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; now_result == check_list[pointer]:
                    result += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

                counter += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

            result_dict[target_number] = result
            output.append(result)

&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; result &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; output:
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(result)

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[BOJ 13325, Python] 二分木</title><link>https://www.traceoflight.dev/ja/blog/boj13325/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj13325/</guid><description>BOJ 13325、「二分木」問題のPythonによる解法</description><pubDate>Wed, 28 Jun 2023 12:58:52 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;[BOJ 13325](&lt;a href=&quot;https://www.acmicpc.net/problem/13325&quot;&gt;https://www.acmicpc.net/problem/13325&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;動的計画法、木、木における動的計画法&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;私のような場合は、すぐに解けない問題であっても、かなり長い間寝かせてじっくり考えるタイプだ！&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-4b0aee5765d752b7-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;そうしているうちに、このように試してみたが正解しなかった問題や、コンテストの問題と共に大掛かりな試みをしたものの解けなかった問題が溜まっていくことになる。&lt;/p&gt;
&lt;p&gt;これらを片付けるために、たまに問題を読み返しながらじっくり考えるのだが、今日ついにこの記事で問題の解決法を知ることができてとても嬉しい！&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-5ef200830a30afc7-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;なんと最初の試みから8ヶ月もかかった問題で、直前の試みから何度か手を出してみたことはあったが、適切な案が浮かばず解決できなかった。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;pre_order_detail&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;graph_dict: &lt;span class=&quot;hljs-built_in&quot;&gt;dict&lt;/span&gt;, target_node: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;:

    result = [target_node]

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(graph_dict[target_node]) &amp;gt;= &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; each_element &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; pre_order_detail(graph_dict, graph_dict[target_node][&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;]):
            result.append(each_element)
        result.append(target_node)

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(graph_dict[target_node]) &amp;gt;= &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;:
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; each_element &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; pre_order_detail(graph_dict, graph_dict[target_node][&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]):
            result.append(each_element)
        result.append(target_node)

    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; result

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;本来は、上記のような再帰関数の形で前走順回を変形させた形で、訪問するノードを出力した後、スタックのようなデータ構造に入れて各辺をあれこれ処理する方式を考えていた。&lt;/p&gt;
&lt;p&gt;しかし、考えてみると、結果的に比較対象を同じ親ノードから出る辺に限定すれば、2つずつ比較した値のうち大きい方を着実に上位の辺に合算しながら処理する場合、きれいに計算できることが分かった！&lt;/p&gt;
&lt;p&gt;後で解いて分類を見てみると、この種の問題はツリーDPと呼ばれるらしい。確かにDPのそれとは非常に似ていると実感した。&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 이진 트리&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sys

&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt; = sys.stdin.readline

tree_height = &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;())
node_number = &lt;span class=&quot;hljs-built_in&quot;&gt;pow&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;, tree_height + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

edges = [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;] + &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split()))
edge_sum = &lt;span class=&quot;hljs-built_in&quot;&gt;sum&lt;/span&gt;(edges)

now_start = node_number // &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
now_end = node_number - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; now_end:

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;((now_end - now_start) // &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;):

        child_edge = now_start + (&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * i)
        next_node = child_edge // &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;

        edges[next_node] += &lt;span class=&quot;hljs-built_in&quot;&gt;max&lt;/span&gt;(edges[child_edge], edges[child_edge + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;])
        edge_sum += &lt;span class=&quot;hljs-built_in&quot;&gt;abs&lt;/span&gt;(edges[child_edge] - edges[child_edge + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;])

    now_end = now_start
    now_start = now_start // &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;

&lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(edge_sum)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最初に考えていた方式よりも、コードの長さも時間計算量もすっきりした形になった。こうして見ると、確かにボトムアップ（Bottom-Up）の形式をとっている。&lt;/p&gt;
</content:encoded></item><item><title>[余談】IaaS、PaaS、SaaSとは？</title><link>https://www.traceoflight.dev/ja/blog/iaas-paas-saas/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/iaas-paas-saas/</guid><description>よく耳にするけど、深く調べなかった言葉たち</description><pubDate>Mon, 26 Jun 2023 05:21:36 GMT</pubDate><content:encoded>&lt;h3&gt;共通で書かれた&apos;aaS&apos;の意味は？&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&apos;As a Service&apos;の略&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;第3者がクラウドコンピューティングサービスを提供すること！&lt;/p&gt;
&lt;p&gt;###違いは？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;サービスとして提供するものがインフラ、プラットフォーム、ソフトウェアで異なる。
→ 管理レベルの違いが発生&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-7a2b2e1c34c6a3d0-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;1. IaaS&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;オンプレミスインフラストラクチャから発展したタイプ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;インフラサービスをクラウドで提供&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;プロバイダがネットワーク、サーバー、仮想化、ストレージの管理とアクセスを担当。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;AWS、Azure、GCPのような業者がこれに該当します。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2. PaaS&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;IaaSより担当する領域が広くなる。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ユーザーが独自のアプリケーションを開発、実行、管理することができる。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ビルドとデプロイメントのための環境まで提供&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;3. SaaS&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;すべてのアプリケーションをプロバイダーが管理&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;プロバイダーがソフトウェアのメンテナンス、アップグレード、セキュリティを完全に管理します。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;注意事項&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.redhat.com/ko/topics/cloud-computing/iaas-vs-paas-vs-saas&quot;&gt;IaaS vs. PaaS vs. SaaS&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>[面接の質問] コネクションプールとは？ (Feat. ChatGPT)</title><link>https://www.traceoflight.dev/ja/blog/connection-pool/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/connection-pool/</guid><description>DBコネクションプールに関する面接の質問まとめ</description><pubDate>Sun, 25 Jun 2023 17:05:44 GMT</pubDate><content:encoded>&lt;h3&gt;DBコネクションプールとは？&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;gt; DBに事前に接続しておいたオブジェクトをプールに保存
&amp;gt; クライアントからのリクエスト時に接続を貸し出す
&amp;gt; 処理が終了したら接続を返却し、プールに再び保存&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;あらかじめ接続しておき、必要な時に取り出して使う形式の接続オブジェクトだと理解できるだろう。&lt;/p&gt;
&lt;h3&gt;使用する理由？&lt;/h3&gt;
&lt;p&gt;Java Springの場合、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;DBに直接接続して処理する方式を使用する場合&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;毎回JDBCドライバーをロードし、接続オブジェクトを取得する必要がある&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;リクエストのたびにドライバーのロード、オブジェクトの生成、接続が繰り返し行われる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;→ 非常に非効率的であるため、このような問題を解決するためにConnection Poolを使用する。&lt;/p&gt;
&lt;p&gt;+ その他のフレームワークでも使用されているという。&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-bec4f7ed8c564abe-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;特徴&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;WAS実行時にConnectionオブジェクトをプールに事前に生成&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;HTTPリクエストに応じてオブジェクトを取得・使用・返却&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;接続リクエストごとに接続や生成にかかる時間が消費されない
→ 接続負荷を軽減する効果がある&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;gt; - 同時接続者数がプールのオブジェクト数より多い場合は？
&amp;gt;   → 事前に生成された接続オブジェクトが不足すると、返却されるまで順番待ちとなる&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;gt; プールが大きくなるほど、メモリ消費量↑ 待機時間↓&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>[雑記] main関数の位置について</title><link>https://www.traceoflight.dev/ja/blog/main/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/main/</guid><description>main関数は一番上に配置するようにしましょう</description><pubDate>Sun, 18 Jun 2023 11:50:50 GMT</pubDate><content:encoded>&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;学んだことを簡単にまとめるために、「&lt;code&gt;자투리&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;」というカテゴリーを使ってみることにした！&lt;/p&gt;
&lt;h3&gt;main関数を一番上に&lt;/h3&gt;
&lt;p&gt;[CS50](&lt;a href=&quot;https://www.youtube.com/live/ywg7cW0Txs4?feature=share&quot;&gt;https://www.youtube.com/live/ywg7cW0Txs4?feature=share&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)の講義を受けていて気づいたことだが、私のような場合、コードを通常このように書く傾向がある。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;example&lt;/span&gt;():
	&lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;hello&amp;#x27;&lt;/span&gt;)
    
&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;main&lt;/span&gt;():
	example()
    
main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;例を挙げると、必要な関数の詳細な定義をすべて最初に並べておき、その後でmain関数を追加で記述する方式だ。&lt;/p&gt;
&lt;p&gt;しかし、確かに一番最初に main 関数が来ている方が、コードを読む際に他の人にとって分かりやすくなるのではないかと思った。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;main&lt;/span&gt;():
	example()
    this_function()

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;example&lt;/span&gt;():
	&lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;hello&amp;#x27;&lt;/span&gt;)
    
&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;this_function&lt;/span&gt;():
	&lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;function&amp;#x27;&lt;/span&gt;)
    
main()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;コード全体の構成を示す main 関数を上に移動し、詳細な定義をその後に記述することで、コードの機能をより明確に示せるようにしたい。&lt;/p&gt;
</content:encoded></item><item><title>平凡な、SSAFY第8期修了レポート</title><link>https://www.traceoflight.dev/ja/blog/ssafy-8/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/ssafy-8/</guid><description>サムスン青年SWアカデミーを終えて</description><pubDate>Fri, 16 Jun 2023 17:28:37 GMT</pubDate><content:encoded>&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;ついにサムスン青年SWアカデミー、SSAFY第8期の1年間の旅路が終わる瞬間が訪れた。多くの出来事があったが、息つく間もなく駆け抜けてきたため、今になって、今こそ一度書き留めてみようと思う。SSAFYの体験記を見ると、その大半は「優秀」以上の評価で修了し、賞状を1、2枚は受賞していることがわかるが……&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-aee8ee7c7a4b8132-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;この体験記は受賞多数！ 「優秀なSSAFY型人材！」といったような凄腕の人物ではなく、どこかにいそうな、それ以外のSSAFY入学生の物語だと考えていただければと思う。また、今後SSAFYの課程を履修される方々にも役立つ経験談になればと願いながら、書き記してみる。&lt;/p&gt;
&lt;h3&gt;入学&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-442ceb7c6829c573-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-219d272c02689759-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;通常、非専攻者にとっては高いとされているSSAFYの壁を、どうにかして突破した。 自己紹介書は合格、面接では不合格の通知を受けた……が、その稀な「非専攻者追加合格」の通知を受け、ソウルキャンパスに入学することになった。入学直後に行われるスタートキャンプには、経験した者だけが知る苦労があるというが、本当に本当にギリギリの合格者だったため、スタートキャンプを省略することができた。&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-fa0b9011434db360-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;SSAFYに入学すると、自分の名札が渡されるのだが、その名札でさえ、他の初期合格者の名前の上に私の名前がフルネームで貼られていた…後で何度も剥がれそうになったので、テープで固定したのが上の写真だ。&lt;/p&gt;
&lt;p&gt;今思えば、むしろこの名札のおかげで、もう少し頑張ろうという気持ちになったと思う。得られた機会が本当に貴重であることを常に実感し、モチベーションを維持しながら通うことができたようだ！&lt;/p&gt;
&lt;h3&gt;1学期、Pythonトラック&lt;/h3&gt;
&lt;p&gt;1学期にはJavaトラックとPythonトラックがあり、Javaを学ぶのが良いことは知っていたものの、Pythonトラックを受講することになった。1学期に学んだことはいろいろあったが……&lt;/p&gt;
&lt;p&gt;いざ2学期に入ると、実際にしっかり学んで活用できたのは、アルゴリズム、Git、Pythonくらいだったと思う。これさえも、Pythonやアルゴリズムはプロジェクトで使うというより、コーディングテストで活用する方が圧倒的に多いレベルで……&lt;/p&gt;
&lt;p&gt;（フロントエンドは学ぶが、ほとんどがReactの復習なので存在感もない）&lt;/p&gt;
&lt;p&gt;それでもトラックに入れば、SSAFYらしく、ほぼ全員が情熱を持って学んでいく姿が見られる。クラス内で互いに励まし合いながら勉強会を作ったり、カフェで一緒に勉強したりして過ごしたと思う。&lt;/p&gt;
&lt;p&gt;私の場合、プログラミングといえば大学の教養科目で少し触れた程度が全てだったので、ほぼゼロベースであり、全てを完璧にこなすことはできないと考え、選択と集中が必要だと判断した。 そこで、まずは採用プロセスを確認し、着実に突破できるよう努力しようと決めた。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;書類選考 → コーディングテスト → 人物面接 → 技術面接 → 採用&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ほとんどの企業がこの範囲から外れないことを確認した。結果的に**「コーディングテストを突破できなければ未来はない」**と考え、これがアルゴリズムに全力を注ぐ「テックツリー」の始まりとなったのだが…&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-cfc4f764b173e0d0-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;アルゴリズム能力の向上のために勉強会まで作るほど多くの時間を投資したが、結局プラチナ5の達成を最後に事実上燃え尽きてしまった。あの頃からサムスンのソフトウェア能力評価B型を突破するためにJava言語も合間を縫って勉強しながら鍛えたが、残念ながら未取得で終わることになった。 体験記は[こちら](/blog/b&lt;/p&gt;
&lt;p&gt;)にあり、B型を取得できればSSAFYが提供する様々な特典、体験、連携などにおいて優先順位が上がるため、取得できるなら必ず取得するようにしましょう！&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-b2e44c75355b7edc-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;(しかし感覚を失わないために、地道に低レベルの問題でも解き続けることは重要だと考え、コツコツと解き続けた)&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-8836547a6ac0689c-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;あれこれ苦労し、ほぼ毎週行われる理論および実技試験を通過する日々を経て、貫通プロジェクトに到達した。 今思えば、ここでは2学期に挑む7週間のプロジェクトを、&lt;strong&gt;圧倒的に少ない人員と時間で&lt;/strong&gt;やり遂げなければならないレベルが求められていた！どこかで素晴らしいコードをうまく持ってきて応用するレベルを見られたとは思っているが、それでも結局、他人ができなかったことを成し遂げたチームが賞を勝ち取ったようだ。（例えば、デプロイといったこと）&lt;/p&gt;
&lt;h3&gt;2学期、プロジェクトの連続だった日々&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-00a981c35d4a739d-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;2学期の課程では、ずっとプロジェクトに取り組むことになるが、これがSSAFYで最も重要な部分だと考えている。&lt;/p&gt;
&lt;p&gt;今考えてみると、1学期の頃は企業に応募したくても、「何か経験はありますか？」と聞かれても答えることがなく、自己紹介書や面接でアピールできる部分が限られていた。しかし、2学期が進むにつれて、結果に関わらず自分がプロジェクトに誠実に取り組んだのであれば、「こういう部分を担当し、こういう点で困難を感じましたが、こういう方法で改善しました」といった話をできるようになるのだ！&lt;/p&gt;
&lt;p&gt;テーマがこのように決まっているように見えるが、特化プロジェクトでない限り、テーマに縛られることなく、大抵はチームが望むプロジェクトを進めることができた。 私の場合、アプリ開発プロジェクトを2回、モバイル仕様のWeb開発を1回行いました。ポジションに関しては、人によって2学期にやりたいことが異なるかもしれませんが、私はすべてのポジションを経験してみたかったので、バックエンド1回、フロントエンド1回、アプリ1回の経験を持つことになりました。&lt;/p&gt;
&lt;p&gt;Pythonトラックに入学すると、大抵はJavaとは縁が遠くなるが、2学期のプロジェクトの99%がSpring Bootを使用するため、否応なくフロントエンドに向かうことになり、これが自身のポジションを固定することにつながる。したがって、バックエンドを希望するという確固たる意志があるなら、Pythonトラックの受講生は別途Javaを並行して学ぶのが良い。 筆者もJavaの講義を別途受講し、バックエンドのポジションへの道筋を常に残しておこうとした結果、バックエンドのポジションも1回経験することができた。&lt;/p&gt;
&lt;h3&gt;就職活動と様々な面接&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-3bc909615076161a-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;私がこのように1学期から2学期にかけて、何かをアピールできる夢のような時間を過ごしている間、少数の準備万端な人々は着実に企業とのコンタクトを試み、その結果、その過程でいわゆる「サタル」、SSAFYからの脱出を果たす栄光に浴することになった。そんな人々を見て最初に思ったのは、「まだ準備が足りないから… プロジェクトが全部終わってからでも遅くないだろう」だったが、結果的に2学期を並行して進めていると、自然と脱出する多くの先駆者たちを見て、準備を進めることになる。&lt;/p&gt;
&lt;p&gt;誰かが社員証を受け取っている間に、2学期の修了証を受け取って修了する自分の姿が物足りなく感じるかもしれないので、地道に挑戦してみよう。筆者は多くの企業に応募し、結果的に手にしたのは2学期の修了証だったが、それでも後悔のない応募だったと思う。&lt;/p&gt;
&lt;p&gt;SSAFYの様々な特典と積み重ねた技術を持ってコーディングテスト、書類選考を通過すれば、面接が残っている。人物面接と技術面接の両方に実際に臨んでみるまでは、どこが不足しているのか分からない場合が多いため、教育期間中に経験できれば本当に本当に良いと思う。&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-09b59b4e7d50faf7-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;面接は、実際に経験すればするほど確実に実力が伸びる。実際に足りない部分を補っていく能力的な面もそうだが、面接官への対応姿勢などは、その状況や緊張感がなければ経験できないと思うため、自分の能力が許す限り、実際に志望するレベルより低い企業の面接であっても、コツコツと受験し、本当に志望する企業でより良い結果を得られるようにしよう！&lt;/p&gt;
&lt;h3&gt;修了のその先には…&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-0a384db17a2502a8-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;それで、SSAFYが終わったらこれから何をするの？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;この質問について長い間悩んできたし、今も答えを探している最中だ。基本的には、取り組んできたプロジェクトについてじっくり振り返る時間を持ちつつ、学んできた内容の整理もしたいし、やはり就職は早くしたい状況なので…&lt;/p&gt;
&lt;p&gt;結局、すべてを着実に進めていくことになるだろうという気がしている。これまで積み重ねてきた勉強が無駄になるわけではないので、その上にさらに積み上げていくのが最善だと信じている。私のSSAFY第8期の旅はここで幕を閉じるが、開発者としてのキャリアがここで終わるわけではない！もっと良い日が待っていると信じて、地道に努力していきたい。&lt;/p&gt;
</content:encoded></item><item><title>2023 LG CNS上半期採用選考の口コミ</title><link>https://www.traceoflight.dev/ja/blog/2023-lg-cns/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/2023-lg-cns/</guid><description>缶！</description><pubDate>Fri, 16 Jun 2023 08:27:19 GMT</pubDate><content:encoded>&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;今回の上半期にLG CNSの新入社員採用選考に応募し、最終面接まで終了した。結論から言えば、残念ながら良い結果を得ることができなかった。しかし、失敗を覆い隠すのではなく、私がどのような部分が不足していたかを記録して、次回はもっとうまくやればいいという考えがあるので、このように残しておきます。これから採用に参加する人の参考になれば幸いです。&lt;/p&gt;
&lt;h3&gt;書類選考&lt;/h3&gt;
&lt;p&gt;書類選考で特異な部分はあまりなかったようだ。 特異点といえば、他の企業に比べて自己紹介書の分量が少なかったことくらい？ ただ、書類で不合格になったケースが周りにあって、意外に変別要素があったようだ。合格していれば、その後、コーディングテストの手続きを進めることができた。&lt;/p&gt;
&lt;h3&gt;コーディングテスト&lt;/h3&gt;
&lt;p&gt;全体的に難易度はそれほど難しくはなかったと思う。シルバー~ゴールド5レベルの問題をランダムに解くことができれば、十分にオールソーが可能だったと思う。 敢えて方向性を決めるなら、創造的なアルゴリズムを要求するより、現場でどんな問題が出ても対応できる練習が役に立ったと思う。&lt;/p&gt;
&lt;p&gt;@&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-0050c757a54e8dd4-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;@@ さん&lt;/p&gt;
&lt;p&gt;一定レベル以上解決していれば、面接に進むことができ、無事に合格することができた。&lt;/p&gt;
&lt;p&gt;1次面接 ### 1次面接&lt;/p&gt;
&lt;p&gt;コーディングテストに合格し、1次面接の案内を受けることができました。基本的にビデオ面接で行われ、自己紹介書に書いてあった質問の内容や一般的な面接の質問を中心に聞かれたようです。 面接官の方のお話がぼんやりと記憶に残っていますが、新入社員に大きな期待を抱いて能力に対する評価はしないとのことでした。 その後も何か言われましたが...緊張していたので記憶から削除された状態です。どうやら、能力をあまり見ないのであれば、人柄や自己紹介内容の検証、誠実さ、カルチャーフィットなどを中心に見ているのではないかと思います！&lt;/p&gt;
&lt;p&gt;余談ですが、コーディングテストで良い結果を出した場合、面接官からテストについてちょっとした褒め言葉をもらえることもあります。 もしかしたらあるかもしれない反例やエッジケースについて少し気を使ったのですが、結果について確認されたようで、気分が良かったです。&lt;/p&gt;
&lt;p&gt;@&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-95c1802564fc051e-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;@@ さん&lt;/p&gt;
&lt;p&gt;面接が不慣れで、すごくガチガチでぎこちなく見て、落ちてしまった...と思っていたのですが、2次面接まで行く機会を得ることができました...。やっぱり綿棒は科学だ。&lt;/p&gt;
&lt;h3&gt;2次面接&lt;/h3&gt;
&lt;p&gt;他の企業の選考と同様に、実際に入社することになった場合、部署の決定権を持つ方が直接面接に来るようです。最初に自己紹介までしていただいたのですが、緊張しすぎて覚えていないのが残念です。でも、1次面接と同じような感じだと思った瞬間、たまに技術的な部分に突っ込まれ、喋りまくっていたのを覚えています。最後に、もし入社することになったら、どんな姿勢で業務に取り組めば良い結果が得られるか聞いてみたところ、笑顔でいろいろと良いことを言ってくださったのが印象に残っています。 そして......。&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-306ab2ca84c94e03-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;@ さん&lt;/p&gt;
&lt;p&gt;受けた結果は正直、心が痛かった。しかし、面接を終えて考えてみると、残念な部分が多かったので、納得できない結果ではありませんでした。 受けられた技術的な質問や、応募した会社に対する認知度など、あまりに不十分な回答をした面があり、面接官から見て、印象的に採用したいと思うような強みがなかったと思います。&lt;/p&gt;
&lt;h3&gt;感想&lt;/h3&gt;
&lt;p&gt;@&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-ca72109624ea74bc-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;@ さん&lt;/p&gt;
&lt;p&gt;どうやら上半期の採用選考の中で最も合格に近かった企業なので、残念でならないわけにはいきません。しかし、今受け取った成績表が今後の方向性を教えてくれると思い、実際に不足していた部分を補完し続けるために努力しています。&lt;/p&gt;
&lt;p&gt;この経験を足がかりにして、より良い姿になることを願っています。後で私を採用しなかったことを後悔させることができれば、それこそ良い結果ではないでしょうか。 次のCNS採用の時は、**&apos;私が企業を選ぶことができる企業&apos;&lt;strong&gt;の立場より&lt;/strong&gt;&apos;私が企業を選ぶことができる人&apos;**になれるようにもっと努力しなければなりません。&lt;/p&gt;
</content:encoded></item><item><title>[面接の質問】JVMの構造と原則</title><link>https://www.traceoflight.dev/ja/blog/jvm/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/jvm/</guid><description>JVMに関する面接の質問まとめ</description><pubDate>Thu, 15 Jun 2023 16:30:41 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;23-06-27 未記入内容の補充 &amp;gt; 23-06-27
23-07-01 内容の補充及び作成完了&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Java の概要&lt;/h3&gt;
&lt;h4&gt;1. Javaの開発哲学&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;Write Once, Run Anywhere&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;プラットフォームと独立した言語を志向&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;同じ言語で組まれたコードをどのようなオペレーティングシステムでも実行できることに焦点を当てて開発された（一種のクロスプラットフォーム）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2. JDK&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Java Development Kit
Java開発ツールであり、JRE、JVMを全て含む。基本的にJavaで作ったプログラムだけを実行すればいいユーザーと違って、開発者はJDKをインストールしなければならない。JDKにはCompilerが含まれています。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Java Runtime Environment
Java実行環境としてJava Class Library, Java Class Loader, JVMを含んでいます。クラスローダーとライブラリを介して作成されたJavaコードをライブラリと組み合わせてJVMで駆動できるようにする。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Java Virtual Machine&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;JVM とは？&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Java Virtual Machine、Java仮想マシン。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Javaプログラム実行環境を整えてくれるソフトウェア&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Java Code → Compiler → 機械語&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;アプリケーション実行のためのメモリを割り当てられ、Java Runtime Data Areaを構築する。&lt;/p&gt;
&lt;h3&gt;Runtime Data Area&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Heap領域&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Method 領域&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上の2つの領域は全てのThreadが共有&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;PC Register&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Native Method Stack&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stack領域&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上記の3つの領域はThreadごとに開始時に生成され、終了時に消滅します。&lt;/p&gt;
&lt;h3&gt;各領域の詳細&lt;/h3&gt;
&lt;h4&gt;1. Heap&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;クラスのインスタンス、配列が保存される空間。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;動的なメモリ管理システム&apos;Garbage Collection&apos;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2. Method&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;クラス、インターフェースの構造を保存する空間&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;3. Stack&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Cのスタック構造と似ており、地域変数や関数の実行結果を保存する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;関数の呼び出しとリターンを担当し、Stack Frameを持つ。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stack Frameとは？&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;各関数ごとに関数の呼び出し情報が含まれている区分された空間。
FrameはLIFO方式で処理される
余裕空間がない時にフレームが追加される場合 → Stack Overflow発生
プロローグ、エピローグを活用したポインタ方式でスタック復帰位置確認&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;4. Native Method Stack&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;C, CPPで作成されたメソッドの実行スタック&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;コード実行時にNative Method Stackが割り当てられます。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;StackOverflowErrorやOutOfMemoryErrorが発生する可能性がある。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;スタックのサイズを動的に調整することができます。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;5. PC Register&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;各スレッドごとにPC Registerを保有&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;スレッドが現在割り当てられている命令を実行する時、命令のアドレスを記録します。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;命令ごとに値を安定的に変動させて指し示す値を実行するようにする。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.1@&quot;&gt;JVM Document&lt;/a&gt;
&lt;a href=&quot;https://m.blog.naver.com/goreng2/221770110714@&quot;&gt;gorainiさんのブログ&lt;/a&gt;
&lt;a href=&quot;https://velog.io/@sgwon1996/JAVA%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC%EC%99%80-JVM-%EA%B5%AC%EC%A1%B0@&quot;&gt;sgwon1996さんのvelog&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>[面接質問】DB Indexとは？</title><link>https://www.traceoflight.dev/ja/blog/db-index/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/db-index/</guid><description>データベースインデックスに関する面接質問まとめ</description><pubDate>Tue, 13 Jun 2023 15:20:25 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;データベーステーブルの検索速度を向上させるためのデータ構造&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;インデックス使用のメリット&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;テーブル参照速度の向上によるパフォーマンス改善&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;システム負荷を減らせる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;インデックス使用のデメリット&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;DB インデックス用に追加の保存領域が必要になる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DB 管理のための追加作業とオーバーヘッドが発生する&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;インデックスの管理&lt;/h3&gt;
&lt;p&gt;インデックスは常に最新の整列状態を保ってこそ目的の値を素早く探索できるため、データが頻繁に更新される属性にインデックスを張ると、逆にオーバーヘッドによる性能低下を招くことがある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;INSERT: 挿入時に挿入されたデータのインデックスを追加&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DELETE: 削除されたデータのインデックスを「未使用」として処理する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UPDATE: 既存インデックスを未使用化 + 更新後データのインデックスを追加&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;使用するデータ構造&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;B+ Tree&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;B Tree の改良版&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;リーフノードのみにデータを格納&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;リーフノード同士は連結リストの形を持つ&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Hash Table&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Key - Value のペアでデータを格納
非常に短時間でデータを探索できる
不等号比較に不向きなのであまり使わない (整列されないため)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;インデックスの分類&lt;/h3&gt;
&lt;h4&gt;1. Key による分類&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;主インデックス: 主キーを含む (Key の順序 = レコードの順序)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;補助インデックス: 主キーを含まない (Key の順序 != レコードの順序)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2. ファイル組織による分類&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;集中インデックス&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;非集中インデックス&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;3. データ範囲による分類&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;密インデックス&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;疎インデックス&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://brunch.co.kr/@skeks463/25&quot;&gt;brunchstory by Nathan&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>[1Day-1CS]各層を処理するための機器</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-e4320ddf/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-e4320ddf/</guid><description>1日1CS、各層を処理する機器についての簡単なまとめ</description><pubDate>Mon, 05 Jun 2023 15:08:16 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;2023-06-18 内容の統一性のために前の記事の内容を統合する&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;アプリケーションレイヤーを処理する機器&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;L7スイッチ: ロードバランサーとも呼ばれ、サーバーの負荷を分散する機器&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;スイッチ: 複数の機器を接続し、データ通信を仲介し、接続されたポートにのみ電気信号を送り、データを転送する通信ネットワーク機器&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;システム処理可能なトラフィックの増加を目指す。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;URL、サーバー、キャッシュ、Cookieなどに基づいてトラフィックを分散させる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;不必要な外部データを除外するフィルタリング機能も保有。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;トラフィックの監視が可能&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;= Health Checkを通じて障害が発生したサーバーをトラフィック分散対象から除外する。&lt;/p&gt;
&lt;h3&gt;L4 スイッチと L7 スイッチの違い&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;L4 スイッチは伝送層を処理する機器で、ストリーミング関連サービスでは使用できません。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;メッセージベースの認識不可、IP＆Portベースのトラフィックの分散&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;クラウドサービスでL7スイッチのロードバランシングはALB(Application Load Balancer)コンポーネントで、L4スイッチを利用したロードバランシングはNLB(Network Load Balancer)コンポーネントで行います。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Health Check&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;送信周期と再送回数などを設定し、繰り返しサーバーに要求を送ること。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;サーバーに負荷がかからない程度に適切なもの。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;様々な方法でリクエストを送信し、正常に処理された場合、正常なサーバーと判断する。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ロードバランサーを活用したサーバーの冗長化&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;2台以上のサーバーを基盤に仮想IPを提供し、これを基盤に安定的なサービスを提供します。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;特定のサーバーでエラーが発生してもサービスが継続されなければならないため、サーバーの冗長化が必要です。&lt;/p&gt;
&lt;h3&gt;インターネット層を処理する機器&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;ルーター: 複数のネットワークを接続、分割、区分してくれる役割。
L3スイッチ：L2スイッチ+ルーター&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;データリンク層を処理する機器&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;L2スイッチ: デバイスのMacアドレスを管理し、パケットを転送する役割
ブリッジ：2つの近距離接続網を相互接続できるようにする通信網接続装置。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;物理層を処理する機器&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;NIC (Network Interface Card)：LANカード、固有の識別Macアドレスがここに存在する。
リピータ: 受信した信号を増幅して、他の方に転送する装置
AP: パケットをコピーする機器、有線LANを接続して無線ネットワークに接続するための装置。&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>[面接の質問] フレームワークとライブラリ（Feat. ChatGPT）</title><link>https://www.traceoflight.dev/ja/blog/framework-library/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/framework-library/</guid><description>フレームワークとライブラリに関する面接の質問まとめ</description><pubDate>Sat, 03 Jun 2023 13:45:20 GMT</pubDate><content:encoded>&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;今回、面接で初めてこの質問に直面したのだが、正直なところ知っていると思っていた内容だったにもかかわらず、明確に答えられず、もごもごとしてしまい、結局は質問の意図とずれた回答をしてしまった……。そこで、次に同じ質問をされた時にはそうならないようにと、もう少ししっかりと理解しておこうと思い、内容をまとめてみた！&lt;/p&gt;
&lt;h3&gt;ライブラリ&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;開発時に共通して使用できる機能をモジュール化したもので、特定の機能を実行するように作成されたプログラム&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;フレームワーク&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;様々な機能を持つクラスやライブラリが、特定の結果物を実装するために組み合わされた形態&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;ChatGPTの回答&lt;/h3&gt;
&lt;p&gt;上記の定義は、いくつかの記事を読んで、個人的に正解に近いと考えた結果である。 しかし、どこか物足りない感じがして、より詳細に定義された回答が聞きたくなり、ChatGPTを活用してみることにした！&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Libraryの定義
&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-63d37d80c7d7a66e-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Frameworkの定義
&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-f8277c02067f5cf0-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;では、何が違うのか？&lt;/h3&gt;
&lt;p&gt;上記の回答を通じて、改めてFrameworkとLibraryを整理してみると&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Library&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;再利用可能なコードとリソースの集合
関数、クラス、メソッド、データ型などで構成&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Framework&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;ソフトウェア開発のための構造的な枠組み、あるいはプラットフォーム
あらかじめ定義されたコードとライブラリで構成&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;この内容を見ると、疑問が湧いてくるのは当然だ。フレームワークはライブラリを含めることができるが、ライブラリはフレームワークを含めることができないのだろうか？&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-27fca29bce6050ea-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;予想通り、フレームワークはライブラリを含めることができるが、その逆は不可能であるという点が確認できた。 また、この内容を通じて、フレームワークとライブラリの重要な違いを確認できるのだが……&lt;/p&gt;
&lt;p&gt;それはまさに&lt;strong&gt;コードフローの制御権&lt;/strong&gt;である。ライブラリの場合は&lt;strong&gt;開発者がライブラリの機能を呼び出して使用する形態&lt;/strong&gt;だが、フレームワークの場合は&lt;strong&gt;フレームワークによって開発者のメソッドが呼び出される形態&lt;/strong&gt;であるという点に大きな違いがあると言える。&lt;/p&gt;
&lt;p&gt;フレームワークで見られるこの形態をIoC（Inversion of Control）、制御の逆転と呼ぶ。Dependency Injectionに関連する内容なので、別途書く機会があるだろうと考え、ここでは詳しく触れないことにする。&lt;/p&gt;
&lt;h3&gt;結論&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ライブラリは再利用可能なコードとリソースの集合であり、フレームワークは開発のための構造的な枠組み、あるいはプラットフォームである。一般的に機能的な側面では同様に動作するため、あえて違いを挙げるとすれば、その使用方法にある。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;フレームワークはライブラリを含むことができるが、ライブラリはフレームワークを含むことはできない。 コードフローの制御権については、フレームワークの場合はフレームワークが、ライブラリの場合は開発者が持つ。したがって、フレームワークの場合、開発者がフレームワークを修正することは一般的に不可能だが、ライブラリの場合は必要に応じて開発者がカスタマイズすることが可能である。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;p&gt;[カレーユさんのブログ](&lt;a href=&quot;https://curryyou.tistory.com/363&quot;&gt;https://curryyou.tistory.com/363&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)
ChatGPT 3.5&lt;/p&gt;
</content:encoded></item><item><title>[面接の質問】ForkとExecの違い</title><link>https://www.traceoflight.dev/ja/blog/fork-exec/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/fork-exec/</guid><description>Processのforkとexecの面接質問まとめ</description><pubDate>Wed, 31 May 2023 07:48:53 GMT</pubDate><content:encoded>&lt;h3&gt;fork()とexec()の共通点&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;一つのプロセスが他のプロセスを実行させるため使う&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;fork()&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;新しいプロセスのためのメモリを割り当てる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;プロセスが追加される (pidが違うプロセスが一つできる)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;exec()&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;新しいプロセスのための追加的なメモリを割り当てることはありません。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;既存のプロセスをオーバーライドして新しいプロセスをロード (pidは同じ)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;→ 呼び出した後は新しいプロセスが動作するので、既存プログラムのexec時点以降のプログラムは動作しない。&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://woochan-autobiography.tistory.com/207#2.%20fork(),%20exec()%EC%9D%98%20%EC%B0%A8%EC%9D%B4%EC%A0%90&quot;&gt;U-chan Seon&apos;s Blog&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>[BOJ 2887, Python] 惑星トンネル</title><link>https://www.traceoflight.dev/ja/blog/boj2887/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj2887/</guid><description>BOJ 2887、「惑星トンネル」問題のPythonによる解法</description><pubDate>Tue, 30 May 2023 15:33:18 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2887&quot;&gt;BOJ 2887&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;分類&lt;/h3&gt;
&lt;p&gt;グラフ理論、ソート、最小全域木&lt;/p&gt;
&lt;h3&gt;解説&lt;/h3&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-edb2ff1f13cf5892-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;この問題に最初に出会ってから、もう半年以上経っていることに驚かされた…とはいえ最近プラチナ問題を疎かにしていた割には、それでも納得できる解法で解けたという点で意味は十分だったと思い、記録することにした。&lt;/p&gt;
&lt;p&gt;この問題を正攻法で解くには、最大 10 万個の座標から 2 つを選び、その値を最小値から並べた上で最小辺から取り込んでいく Union-Find + Kruskal の組み合わせで解ける。&lt;/p&gt;
&lt;p&gt;しかしそうやって解くと 10&lt;sup&gt;5&lt;/sup&gt; * 10&lt;sup&gt;5&lt;/sup&gt; なので、軽く 100 億通りの場合の数になってしまい、結果として 100 秒程度の実行時間が必要になるため、不可能な解法と言える。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Tip: 1 億回の演算につき約 1 秒と見積もると、計算量を考えやすい！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;したがってこの問題の鍵は、O(N&lt;sup&gt;2&lt;/sup&gt;) の場合の数をどう O(N) 単位まで下げるか、と言える。&lt;/p&gt;
&lt;p&gt;結論から言うと、本問題では任意の点について全域木を構築するとき、隣接する点以外の点は考慮しなくてよい。&lt;/p&gt;
&lt;p&gt;任意の点 A, B が存在し、C という点に接続しなければならない状況を見る。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;x の差分 (|X&lt;sub&gt;A&lt;/sub&gt; - X&lt;sub&gt;B&lt;/sub&gt;|) が y, z より小さい最小値である場合
→ C という点の x 値が A と B の x 値の間に存在すると仮定する&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;|X&lt;sub&gt;A&lt;/sub&gt; - X&lt;sub&gt;C&lt;/sub&gt;| + |X&lt;sub&gt;B&lt;/sub&gt; - X&lt;sub&gt;C&lt;/sub&gt;| となる場合、差は存在しない&lt;/li&gt;
&lt;li&gt;|X&lt;sub&gt;A&lt;/sub&gt; - X&lt;sub&gt;B&lt;/sub&gt;| を維持したまま C を追加でつなぐ任意の |X&lt;sub&gt;A&lt;/sub&gt; - X&lt;sub&gt;C&lt;/sub&gt;| や |X&lt;sub&gt;B&lt;/sub&gt; - X&lt;sub&gt;C&lt;/sub&gt;| が存在するなら&lt;strong&gt;必ず既存の全域木より値が大きくなる&lt;/strong&gt; → &lt;strong&gt;反例の存在により不可&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;したがって任意の 2 点を結ぶ辺が本問題で最小全域木に含まれるなら、その 2 点は必ず隣接していなければならない、という証明になる！&lt;/p&gt;
&lt;p&gt;この証明を理解できれば鍵を押さえたことになり、残りは一般的な Union-Find 問題と大きく変わらないと思う。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;追記) heapq の代わりに PriorityQueue を使ったとき時間切れが発生したが、その問題への回答を見つけることができた。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/36991716/whats-the-difference-between-heapq-and-priorityqueue-in-python&quot;&gt;What&apos;s the difference between heapq and PriorityQueue in python?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;PriorityQueue は Thread Safety を保証するため遅いとのこと。&lt;/p&gt;
&lt;h3&gt;解法コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 惑星トンネル&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sys
&lt;span class=&quot;hljs-keyword&quot;&gt;from&lt;/span&gt; heapq &lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; heappush, heappop

&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt; = sys.stdin.readline

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;check_union&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;union_info: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, now_target: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;:
    &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
    該当ノードの現在の Union を照会する関数
    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; union_info[now_target] == -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:
        union_info[now_target] = now_target

    &lt;span class=&quot;hljs-keyword&quot;&gt;elif&lt;/span&gt; union_info[now_target] != now_target:
        union_info[now_target] = check_union(union_info, union_info[now_target])

    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; union_info[now_target]

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;make_union&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;union_info: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, target_1: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, target_2: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
    &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
    2 点が同じ Union か確認し、違う場合に統合する関数
    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    union_1 = check_union(union_info, target_1)
    union_2 = check_union(union_info, target_2)

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; union_1 == union_2:
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; union_1 &amp;gt; union_2:
            union_info[union_1] = union_2
        &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
            union_info[union_2] = union_1

        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;False&lt;/span&gt;

planet_number = &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;())
coord_list = []

&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(planet_number):
    coord_list.append([i] + &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split())))

cost_queue = []

&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;):
    coord_list.sort(key=&lt;span class=&quot;hljs-keyword&quot;&gt;lambda&lt;/span&gt; x: x[i])
    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; j &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(planet_number - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;):
        heappush(
            cost_queue,
            (
                coord_list[j + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;][i] - coord_list[j][i],
                (coord_list[j][&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;], coord_list[j + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;][&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;]),
            ),
        )

union_info = [-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(planet_number)]

total_length = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
line_number = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; cost_queue:
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; line_number == planet_number - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:
        &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

    now_length, nodes = heappop(cost_queue)
    node_a, node_b = nodes

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; make_union(union_info, node_a, node_b):
        total_length += now_length
        line_number += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(total_length)

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[面接の質問】ProcessとThreadの違い、Multi Thread</title><link>https://www.traceoflight.dev/ja/blog/process-thread/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/process-thread/</guid><description>ProcessとThreadの違いについての面接質問まとめ</description><pubDate>Mon, 29 May 2023 17:44:03 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;s&gt;まだ執筆中の記事です！&lt;/s&gt;
&lt;s&gt;23.05.30. 執筆完了&lt;/s&gt; → 23.06.09. 内容追加&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Program&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;コンピュータが特定の作業を実行するために書かれた、実行可能な一連の命令のまとまり&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;さまざまに定義されているが、全体を読んだ上でこのように理解することにした！プログラムの定義を先に確認した理由は、Process の定義がより範囲の狭いプログラムだからである。&lt;/p&gt;
&lt;h3&gt;Process&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;「実行中の」&lt;strong&gt;プログラムの&lt;/strong&gt;「インスタンス」&lt;/strong&gt; (Task とほぼ同じ意味で使われる)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;メモリ上で実行される、OS から見た作業単位&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;生成に多くの時間と資源を消費する (オーバーヘッドが大きい)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;プログラムそのものではなくプログラムのインスタンスとして、複数が同時に存在し得る点が特徴的だと考える。&lt;/p&gt;
&lt;h3&gt;Thread&lt;/h3&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;プロセス内の作業を実行する、CPU から見た実行単位&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;すべてのプロセスは 1 つ以上のスレッドを持つ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;スレッドはそれぞれ独自のレジスタとスタックを持つ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Heap メモリ領域は共有する&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3&gt;では両者の違いは？&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Process がより大きな範囲の単位だと言える&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ただ単にここまでの説明だと、かなり包括的な答えだと思われそうなので、よく整理された記事を参考に追加でまとめてみた！&lt;/p&gt;
&lt;h3&gt;動作のしかた&lt;/h3&gt;
&lt;h4&gt;1. Process の場合&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;プロセスは実行時に別個のメモリ領域を OS から割り当てられる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;メモリ領域は Code/Data/Stack/Heap の形を持つ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;他プロセスのメモリ領域にはアクセスできない&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2. Thread の場合&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Process の Stack 領域は分割し、固有領域を持つ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;残りの Code, Data, Heap 領域は共有する&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;1 つのプロセスのエラーが他プロセスの領域に波及しない&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;But ひとつのスレッドでエラーが発生するとスレッド全体が終了する&lt;/strong&gt;
→ メモリ領域を共有している部分があるため&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3&gt;まとめ&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Process と Thread の違いとは？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;プロセスは動的に使われているプログラムで、スレッドは作業実行単位の一種であり、概念そのものが異なる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;プロセスは最低 1 つ以上のスレッドを含む&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;プロセス同士は通常メモリ空間を共有しないが、スレッドは共有する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;エラー発生時、プロセスは自分だけがダウンするのに対し、スレッドは同一プロセス内のすべてが落ちる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;+ Multi-Thread について&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;1 つのプロセス内で複数のスレッドが同時に作業を実行すること&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;コンテキストスイッチ (Context Switching)&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;基本的に同時に処理できる最大作業数は Core の数に等しい
Core 数を超えるスレッドが動く場合、各コアが複数の作業を切り替えながら実行する
スレッドが切り替わるとき、現時点までの作業状態や次の作業に必要なデータを保存・復元する処理&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;マルチスレッドとマルチプロセスの長所・短所&lt;/h4&gt;
&lt;h5&gt;1) マルチスレッドの長所&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;プロセス生成や資源割り当てのためのシステムコールが減り、資源の効率的な管理が可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;1 つのプロセス内では Stack を除くメモリ空間を共有するため、スレッド間のデータのやり取りに掛かる処理コストが小さい&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;スレッド間の通信方法が複雑ではないため、プログラムの応答時間を短くできる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;2) マルチスレッドの短所&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;デバッグの難しさと設計難易度の上昇&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;他のプロセスからスレッドを制御できない&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;メモリ共有による同期問題 (同時に同じ資源へアクセス)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;スレッドで問題が起きると、プロセス全体に影響が及ぶ&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;3) マルチプロセスの長所&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;プロセスに問題が起きてもその影響が外部のプロセスに広がらない&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;4) マルチプロセスの短所&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;コンテキストスイッチでのオーバーヘッドが大きい&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;プロセス間通信はスレッド間通信に比べて難しく複雑になりがち&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/&quot;&gt;위키백과의 프로세스와 스레드 항목&lt;/a&gt;
&lt;a href=&quot;https://velog.io/@raejoonee/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EC%8A%A4%EB%A0%88%EB%93%9C%EC%9D%98-%EC%B0%A8%EC%9D%B4&quot;&gt;프로세스와 스레드의 차이 by raejoonee&lt;/a&gt;
&lt;a href=&quot;https://gmlwjd9405.github.io/2018/09/14/process-vs-thread.html&quot;&gt;프로세스와 스레드의 차이 by heejeong Kwon&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>[CI/CD] インスタンスからDooDのデプロイまでの流れ（Nginx、Jenkinsを活用）</title><link>https://www.traceoflight.dev/ja/blog/ci-cd-dood-feat-nginx-jenkins/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/ci-cd-dood-feat-nginx-jenkins/</guid><description>DockerとNginxを活用したデプロイの基礎固め</description><pubDate>Sat, 27 May 2023 14:55:17 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;23-06-16 ボリュームマウントを明確にするためにパスを修正
23-07-05 開発の利便性のために設定を調整&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;/blog/cicd-docker-jenkins-git-webhook&quot;&gt;[CI/CD] Docker + Jenkins + Git Webhook を使った FastAPI サーバの自動デプロイまとめ&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;今回この記事を書く理由は、上の前回記事で 1 次的に学ぼうとしていた内容を扱ったが、修正すべきところを修正し、整えるべきところを整えてきれいな 1 つの記事にまとめたかったからだ。&lt;/p&gt;
&lt;p&gt;前回以降のデプロイ関連タスクや、周りの人のデプロイを手伝う中である程度のノウハウを身につけて定型化できたので、その記録を残し、次回以降のデプロイでも一貫したプロセスとして使えるようにしたい！本記事の手順に沿って進めれば、おそらくデプロイは難しくないはずだ。&lt;/p&gt;
&lt;h3&gt;1 編以降に学んだ追加の内容&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Docker in Docker で実装するより Docker out of Docker で実装する理由は？&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;そもそも Docker は、Docker コンテナ上でコマンドを実行できるようにすることを推奨していない&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Docker in Docker は Docker がインストールされたコンテナに非常に強い権限を付与することになり、セキュリティリスクを招き得る&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;その点 Docker out of Docker はコンテナ外部の Docker とソケットを共有して docker コマンドを実行する方式&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Docker API を使う方式はどう？&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;実は 1 編で問題解決のために試した方式で、実際に効果があった。
ただし Docker out of Docker が無事ビルドできているなら、CI/CD の手順上、いまのところ大きな必要性は感じない…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;別記事に分けるのは中途半端な気がしたので、簡単に記録した API 関連の内容&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Docker は REST API を通じてエンジンとクライアントが通信するが、ほとんど使う機会はないとはいえ、使うことはできる。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;  docker --tlsverify --tlscacert=/.docker/ca.pem \
  --tlscert=/.docker/cert.pem --tlskey=/.docker/key.pem \
  -H={server_ip}:{port_number} &lt;span class=&quot;hljs-built_in&quot;&gt;exec&lt;/span&gt; nginx \
  sed -i &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;4s/.*$/ server {container}:8000;/&amp;#x27;&lt;/span&gt; /etc/nginx/sites-available/default.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このコードは TLS 証明書を持つ Docker Client を通じて、任意のサーバ上にある Nginx 設定ファイルの内容を修正するコードだ。
-H オプションでそのサーバの port を介して Daemon (Docker Engine) と通信し、残りのコードは証明書による接続セキュリティの手続きだ。&lt;/p&gt;
&lt;p&gt;もし証明書を使わずポートを開けっ放しにすると、誰かに開いている port を通してコンテナの「托卵」を喰らう可能性がある！&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-fb3d711504538106-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;コンテナ托卵の実体験。Docker でよく使われる port を認証なしで開けっ放しにした結果…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;証明書によるセキュリティ処理は必ず行うべきで、やむを得ない事情で行えない場合は、その port を介して実行可能なコマンドを制限することが必須不可欠である。&lt;/p&gt;
&lt;p&gt;[Docker API Documents] (&lt;a href=&quot;https://docs.docker.com/engine/api/v1.43/&quot;&gt;https://docs.docker.com/engine/api/v1.43/&lt;/a&gt;) の内容を見ると、より詳しく確認できる！&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;All in One デプロイ基盤構築の手順&lt;/h3&gt;
&lt;h4&gt;1. インスタンス接続とインスタンスのアップデート&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ssh -i {secure shell key のパス} {ユーザー名}@{IP アドレス}

&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; apt-get update
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; apt-get upgrade
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ubuntu のセットアップを進める場合、ユーザー名が ubuntu であることが多い。&lt;/p&gt;
&lt;h4&gt;2. ファイアウォール設定&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; ufw allow ssh    &lt;span class=&quot;hljs-comment&quot;&gt;# ssh は 22 に置き換えても良い&lt;/span&gt;
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; ufw allow http   &lt;span class=&quot;hljs-comment&quot;&gt;# http は 80 に置き換えても良い&lt;/span&gt;
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; ufw allow https  &lt;span class=&quot;hljs-comment&quot;&gt;# https は 443 に置き換えても良い&lt;/span&gt;

&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; ufw &lt;span class=&quot;hljs-built_in&quot;&gt;enable&lt;/span&gt; 	  &lt;span class=&quot;hljs-comment&quot;&gt;# ファイアウォールを起動&lt;/span&gt;
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; ufw status 	  &lt;span class=&quot;hljs-comment&quot;&gt;# ファイアウォールの状態確認&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;おそらくクラウドを使う場合、最初からクラウド独自のポートセキュリティ設定があるので、その設定でも開放しておく必要がある。
ufw は Ubuntu のファイアウォールで、最初に設定する際オフになっている場合は、ポートを許可した上で起動する手順が必要だ。
上の設定で、基本的な http (80)、https (443)、ssh (22) ポートを開放した状態でファイアウォールを起動できる。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;必ず先にポートの allow 設定を行ってから起動することを推奨する。22 番、ssh ポートを閉じたままファイアウォールを起動すると、接続できなくなる…&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;3. Docker および Docker Compose のインストール&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Docker のインストール&lt;/span&gt;

&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; apt-get update
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; apt-get install ca-certificates curl gnupg

&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | &lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; gpg --dearmor -o /etc/apt/keyrings/docker.gpg
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;chmod&lt;/span&gt; a+r /etc/apt/keyrings/docker.gpg

&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;deb [arch=&lt;span class=&quot;hljs-subst&quot;&gt;$(dpkg --print-architecture)&lt;/span&gt; signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
&lt;span class=&quot;hljs-subst&quot;&gt;$(. /etc/os-release &amp;amp;&amp;amp; echo &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;&lt;span class=&quot;hljs-variable&quot;&gt;$VERSION_CODENAME&lt;/span&gt;&amp;quot;&lt;/span&gt;)&lt;/span&gt; stable&amp;quot;&lt;/span&gt; | \
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;tee&lt;/span&gt; /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null

&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; apt-get update
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

&lt;span class=&quot;hljs-comment&quot;&gt;# Docker Compose のインストール&lt;/span&gt;

&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; apt install docker-compose
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/&quot;&gt;Ubuntu Docker インストール Documents&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2023 年 5 月時点の Documents から必要な内容だけをまとめて記載した。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; usermod -aG docker &lt;span class=&quot;hljs-variable&quot;&gt;$USER&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このコマンドで sudo なしに docker コマンドを使えるようになる。
このコマンドを入れない場合 &lt;code&gt;/var/run/docker.sock: connect: permission denied&lt;/code&gt; が発生する。&lt;/p&gt;
&lt;h4&gt;4. docker-compose.yml の作成&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;3.8&amp;#x27;&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;networks:&lt;/span&gt;
  {&lt;span class=&quot;hljs-string&quot;&gt;希望のネットワーク名&lt;/span&gt;}&lt;span class=&quot;hljs-string&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;driver:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;bridge&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;services:&lt;/span&gt;

  &lt;span class=&quot;hljs-comment&quot;&gt;# Jenkins Container 設定&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;jenkins:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;container_name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;jenkins&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;jenkins/jenkins:lts&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;restart:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;unless-stopped&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;{希望のポート番号}:8080&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./mount/jenkins:/var/jenkins_home&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;user:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;root&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;environment:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;TZ=Asia/Seoul&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;networks:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; {&lt;span class=&quot;hljs-string&quot;&gt;希望のネットワーク名&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;デプロイパイプラインのツールとして Jenkins を使う前提で書いた。&lt;/p&gt;
&lt;p&gt;追加のネットワークが不要なら networks 部分は省略でき、Docker out of Docker を使うためにソケットのボリュームバインディングを行う。必要に応じて Time Zone や追加のボリュームバインディングも設定可能だ。&lt;/p&gt;
&lt;h4&gt;5. 使うドメインの DNS 設定&lt;/h4&gt;
&lt;p&gt;ドメイン事業者によって方式が違う。利用しているドメイン事業者の登録方法に従って、自分のサーバ IP を登録してドメインに紐付ける処理が必要だ。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.whatsmydns.net/&quot;&gt;What&apos;s My DNS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;登録してすぐ使えるわけではなく、DNS サーバへの反映時間が存在する。手軽に伝播状況を確認できるサイトを上に貼っておいた。&lt;/p&gt;
&lt;h4&gt;6. Let’s Encrypt を使った証明書発行&lt;/h4&gt;
&lt;h5&gt;1) docker-compose.yml&lt;/h5&gt;
&lt;pre&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Nginx 設定&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;nginx:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;container_name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx:latest&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;restart:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;unless-stopped&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./mount/nginx/nginx.conf:/etc/nginx/nginx.conf&lt;/span&gt; 			&lt;span class=&quot;hljs-comment&quot;&gt;# Nginx 設定のためのバインディング&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./mount/nginx/sites-available:/etc/nginx/sites-available&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./data/certbot/conf:/etc/letsencrypt&lt;/span&gt;				&lt;span class=&quot;hljs-comment&quot;&gt;# 証明書共有のためのバインディング&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./data/certbot/www:/var/www/certbot&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;:80&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;443&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;:443&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;environment:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;TZ=Asia/Seoul&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;networks:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; {&lt;span class=&quot;hljs-string&quot;&gt;希望のネットワーク名&lt;/span&gt;}

  &lt;span class=&quot;hljs-comment&quot;&gt;# Certbot コンテナ設定&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;certbot:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;container_name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;certbot&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;certbot/certbot&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;restart:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;unless-stopped&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./data/certbot/conf:/etc/letsencrypt&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./data/certbot/www:/var/www/certbot&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;environment:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;TZ=Asia/Seoul&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;この内容を docker-compose.yml に追加し、それ以上の処理は行わない。&lt;/p&gt;
&lt;h5&gt;2) mount/sites-available/default.conf&lt;/h5&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;&lt;span class=&quot;hljs-section&quot;&gt;server&lt;/span&gt; {
     &lt;span class=&quot;hljs-attribute&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;80&lt;/span&gt;;
     &lt;span class=&quot;hljs-attribute&quot;&gt;listen&lt;/span&gt; [::]:&lt;span class=&quot;hljs-number&quot;&gt;80&lt;/span&gt;;

     &lt;span class=&quot;hljs-attribute&quot;&gt;server_name&lt;/span&gt; my_domain.org;

     &lt;span class=&quot;hljs-section&quot;&gt;location&lt;/span&gt; /.well-known/acme-challenge/ {
             &lt;span class=&quot;hljs-attribute&quot;&gt;allow&lt;/span&gt; all;
             &lt;span class=&quot;hljs-attribute&quot;&gt;root&lt;/span&gt; /var/www/certbot;
     }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ファイルを作成し、&lt;code&gt;server_name&lt;/code&gt; の後ろに自分のドメインを記載した内容を入れる。&lt;/p&gt;
&lt;h5&gt;3) mount/nginx.conf&lt;/h5&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;&lt;span class=&quot;hljs-attribute&quot;&gt;user&lt;/span&gt; nginx;
&lt;span class=&quot;hljs-attribute&quot;&gt;worker_processes&lt;/span&gt; auto;
&lt;span class=&quot;hljs-attribute&quot;&gt;worker_priority&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;

&lt;span class=&quot;hljs-attribute&quot;&gt;pid&lt;/span&gt; /run/nginx.pid;
&lt;span class=&quot;hljs-attribute&quot;&gt;include&lt;/span&gt; /etc/nginx/modules-enabled/&lt;span class=&quot;hljs-regexp&quot;&gt;*.conf&lt;/span&gt;;

&lt;span class=&quot;hljs-section&quot;&gt;events&lt;/span&gt; {
        &lt;span class=&quot;hljs-attribute&quot;&gt;worker_connections&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1024&lt;/span&gt;;
        &lt;span class=&quot;hljs-attribute&quot;&gt;multi_accept&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;off&lt;/span&gt;;
}

&lt;span class=&quot;hljs-section&quot;&gt;http&lt;/span&gt; {

        &lt;span class=&quot;hljs-attribute&quot;&gt;sendfile&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;on&lt;/span&gt;;
        &lt;span class=&quot;hljs-attribute&quot;&gt;tcp_nopush&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;on&lt;/span&gt;;
        &lt;span class=&quot;hljs-attribute&quot;&gt;tcp_nodelay&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;on&lt;/span&gt;;
        &lt;span class=&quot;hljs-attribute&quot;&gt;keepalive_timeout&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;65&lt;/span&gt;;
        &lt;span class=&quot;hljs-attribute&quot;&gt;types_hash_max_size&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;2048&lt;/span&gt;;
        &lt;span class=&quot;hljs-attribute&quot;&gt;server_tokens&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;off&lt;/span&gt;;

        &lt;span class=&quot;hljs-attribute&quot;&gt;include&lt;/span&gt; /etc/nginx/mime.types;
        &lt;span class=&quot;hljs-attribute&quot;&gt;default_type&lt;/span&gt; application/octet-stream;
        &lt;span class=&quot;hljs-attribute&quot;&gt;log_format&lt;/span&gt;  main  &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&lt;span class=&quot;hljs-variable&quot;&gt;$remote_addr&lt;/span&gt; - &lt;span class=&quot;hljs-variable&quot;&gt;$remote_user&lt;/span&gt; [&lt;span class=&quot;hljs-variable&quot;&gt;$time_local&lt;/span&gt;] &amp;quot;&lt;span class=&quot;hljs-variable&quot;&gt;$request&lt;/span&gt;&amp;quot; &amp;#x27;&lt;/span&gt;
                          &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&lt;span class=&quot;hljs-variable&quot;&gt;$status&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;$body_bytes_sent&lt;/span&gt; &amp;quot;&lt;span class=&quot;hljs-variable&quot;&gt;$http_referer&lt;/span&gt;&amp;quot; &amp;#x27;&lt;/span&gt;
                          &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;quot;&lt;span class=&quot;hljs-variable&quot;&gt;$http_user_agent&lt;/span&gt;&amp;quot; &amp;quot;&lt;span class=&quot;hljs-variable&quot;&gt;$http_x_forwarded_for&lt;/span&gt;&amp;quot;&amp;#x27;&lt;/span&gt;;

        &lt;span class=&quot;hljs-attribute&quot;&gt;ssl_protocols&lt;/span&gt; TLSv1 TLSv1.&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; TLSv1.&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; TLSv1.&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;; &lt;span class=&quot;hljs-comment&quot;&gt;# Dropping SSLv3, ref: POODLE&lt;/span&gt;
        &lt;span class=&quot;hljs-attribute&quot;&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;on&lt;/span&gt;;

        &lt;span class=&quot;hljs-attribute&quot;&gt;access_log&lt;/span&gt; /var/log/nginx/access.log main;
        &lt;span class=&quot;hljs-attribute&quot;&gt;error_log&lt;/span&gt; /var/log/nginx/&lt;span class=&quot;hljs-literal&quot;&gt;error&lt;/span&gt;.log &lt;span class=&quot;hljs-literal&quot;&gt;debug&lt;/span&gt;;

        &lt;span class=&quot;hljs-attribute&quot;&gt;gzip&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;on&lt;/span&gt;;

        &lt;span class=&quot;hljs-attribute&quot;&gt;include&lt;/span&gt; /etc/nginx/sites-available/*;

}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;nginx を初めてインストールするときの内容を基に、適度な初期設定を入れた。&lt;/p&gt;
&lt;h5&gt;4) Let&apos;s Encrypt を通じた手続きでの証明書発行&lt;/h5&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -L https://raw.githubusercontent.com/wmnnd/nginx-certbot/master/init-letsencrypt.sh -o init-letsencrypt.sh
&lt;span class=&quot;hljs-built_in&quot;&gt;chmod&lt;/span&gt; +x init-letsencrypt.sh
vi init-letsencrypt.sh			&lt;span class=&quot;hljs-comment&quot;&gt;# ここでドメインとメールアドレスを入力する必要あり&lt;/span&gt;
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; ./init-letsencrypt.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;証明書発行の手続きを助けてくれるファイルを外部から取得し、権限を設定する。その後、自分のドメインとメールアドレスをファイルに入力し、そのファイルを実行することで証明書発行を進められる。発行に失敗した場合はログを見て原因を見つけ、修正して再試行すれば良い。&lt;/p&gt;
&lt;h4&gt;7. 証明書更新まで考慮した Nginx 設定&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Nginx 設定&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;nginx:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;container_name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx:latest&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;restart:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;unless-stopped&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./mount/nginx.conf:/etc/nginx/nginx.conf&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./mount/sites-available:/etc/nginx/sites-available&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./data/certbot/conf:/etc/letsencrypt&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./data/certbot/www:/var/www/certbot&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;:80&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;443&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;:443&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;environment:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;TZ=Asia/Seoul&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;networks:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; {&lt;span class=&quot;hljs-string&quot;&gt;接続したいネットワーク名&lt;/span&gt;}
    &lt;span class=&quot;hljs-attr&quot;&gt;command:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;/bin/sh -c &amp;#x27;while :; do sleep 6h &amp;amp; wait $${!}; nginx -s reload; done &amp;amp; nginx -g \&amp;quot;daemon off;\&amp;quot;&amp;#x27;&amp;quot;&lt;/span&gt;

  &lt;span class=&quot;hljs-comment&quot;&gt;# Certbot コンテナ設定&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;certbot:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;container_name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;certbot&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;certbot/certbot&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;restart:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;unless-stopped&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./data/certbot/conf:/etc/letsencrypt&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./data/certbot/www:/var/www/certbot&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;environment:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;TZ=Asia/Seoul&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;entrypoint:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;/bin/sh -c &amp;#x27;trap exit TERM; while :; do certbot renew; sleep 12h &amp;amp; wait $${!}; done;&amp;#x27;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&apos;s Encrypt で発行した証明書には使用期限があり、代わりに有効期限が近づくと再発行できる。certbot コンテナと nginx コンテナに再発行関連のコマンドを追加することで、証明書更新が自動で進むよう処理できる。証明書発行が完了している状態なので、nginx がエラーでコンテナビルドに失敗することはなくなる。&lt;/p&gt;
&lt;h4&gt;8. Jenkins コンテナ内に Docker をインストール&lt;/h4&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;追加した内容) もともとはコマンドを直接並べていたが、直感的でないと感じたので修正！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# /jenkins-docker-install.sh&lt;/span&gt;

apt-get update
apt-get install ca-certificates curl gnupg

install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
&lt;span class=&quot;hljs-built_in&quot;&gt;chmod&lt;/span&gt; a+r /etc/apt/keyrings/docker.gpg

&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;deb [arch=&lt;span class=&quot;hljs-subst&quot;&gt;$(dpkg --print-architecture)&lt;/span&gt; signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/debian \
&lt;span class=&quot;hljs-subst&quot;&gt;$(. /etc/os-release &amp;amp;&amp;amp; echo &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;&lt;span class=&quot;hljs-variable&quot;&gt;$VERSION_CODENAME&lt;/span&gt;&amp;quot;&lt;/span&gt;)&lt;/span&gt; stable&amp;quot;&lt;/span&gt; | \
&lt;span class=&quot;hljs-built_in&quot;&gt;tee&lt;/span&gt; /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null

apt-get update
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;既存の docker インストール手順から sudo を抜いたコードを sh ファイルにした。このファイルをマウントで内部に入れて実行すれば、すっきりと一発でインストールできる！&lt;/p&gt;
&lt;hr&gt;
&lt;h4&gt;9. Docker Compose の処理&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;3.8&amp;#x27;&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;networks:&lt;/span&gt;
  {&lt;span class=&quot;hljs-string&quot;&gt;ネットワーク名&lt;/span&gt;}&lt;span class=&quot;hljs-string&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;driver:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;bridge&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;services:&lt;/span&gt;

  &lt;span class=&quot;hljs-comment&quot;&gt;# Jenkins Container 設定&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;jenkins:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;container_name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;jenkins&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;jenkins/jenkins:lts&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;restart:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;unless-stopped&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;{ポート番号}:8080&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./mount/jenkins:/var/jenkins_home&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./mount/jenkins-html:/var/lib/jenkins&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./jenkins-docker-install.sh:/jenkins-docker-install.sh&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;user:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;root&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;environment:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;TZ=Asia/Seoul&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;networks:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; {&lt;span class=&quot;hljs-string&quot;&gt;ネットワーク名&lt;/span&gt;}

&lt;span class=&quot;hljs-comment&quot;&gt;# Nginx 設定&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;nginx:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;container_name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx:latest&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;restart:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;unless-stopped&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./mount/nginx/nginx.conf:/etc/nginx/nginx.conf&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./mount/nginx/sites-available:/etc/nginx/sites-available&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./data/certbot/conf:/etc/letsencrypt&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./data/certbot/www:/var/www/certbot&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;:80&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;443&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;:443&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;environment:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;TZ=Asia/Seoul&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;networks:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; {&lt;span class=&quot;hljs-string&quot;&gt;ネットワーク名&lt;/span&gt;}
    &lt;span class=&quot;hljs-attr&quot;&gt;depends_on:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; {&lt;span class=&quot;hljs-string&quot;&gt;先行コンテナ&lt;/span&gt;}
    &lt;span class=&quot;hljs-attr&quot;&gt;command:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;/bin/sh -c &amp;#x27;while :; do sleep 6h &amp;amp; wait $${!}; nginx -s reload; done &amp;amp; nginx -g \&amp;quot;daemon off;\&amp;quot;&amp;#x27;&amp;quot;&lt;/span&gt;

  &lt;span class=&quot;hljs-comment&quot;&gt;# Certbot コンテナ設定&lt;/span&gt;
  &lt;span class=&quot;hljs-attr&quot;&gt;certbot:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;container_name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;certbot&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;certbot/certbot&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;restart:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;unless-stopped&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./data/certbot/conf:/etc/letsencrypt&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;./data/certbot/www:/var/www/certbot&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;environment:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;TZ=Asia/Seoul&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;entrypoint:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;/bin/sh -c &amp;#x27;trap exit TERM; while :; do certbot renew; sleep 12h &amp;amp; wait $${!}; done;&amp;#x27;&amp;quot;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このように Jenkins 設定まで追加したあと&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;language-xml&quot;&gt;docker-compose -f &lt;/span&gt;&lt;span class=&quot;hljs-template-variable&quot;&gt;{yml ファイルの場所およびファイル名}&lt;/span&gt;&lt;span class=&quot;language-xml&quot;&gt; up -d
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;コマンドでコンテナを全て立ち上げられる。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker &lt;span class=&quot;hljs-built_in&quot;&gt;exec&lt;/span&gt; -it jenkins bin/bash
sh /jenkins-docker-install.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このように Jenkins コンテナ内部に Docker をインストールすることで、Jenkins 内部の Shell コマンドから Docker Engine を制御できるようになる。
既存の Docker Documents を参考にしたが、違いは sudo を使わない点と、Debian 用 Docker をインストールする点だ。&lt;/p&gt;
&lt;h3&gt;オプション&lt;/h3&gt;
&lt;h4&gt;1. Swap Memory 設定&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# swap memory 設定&lt;/span&gt;

&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; fallocate -l {設定容量} /swapfile   &lt;span class=&quot;hljs-comment&quot;&gt;# 設定容量はだいたい G 単位で設定する&lt;/span&gt;
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;chmod&lt;/span&gt; 600 /swapfile
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; mkswap /swapfile
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; swapon /swapfile

&lt;span class=&quot;hljs-comment&quot;&gt;# 再起動後も継続使用したい場合&lt;/span&gt;

&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; vi /etc/fstab 			&lt;span class=&quot;hljs-comment&quot;&gt;# &amp;#x27;/swapfile swap swap defaults 0 0&amp;#x27; をこのファイルに挿入&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# swap を無効化&lt;/span&gt;

&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; vi /etc/fstab 			&lt;span class=&quot;hljs-comment&quot;&gt;# &amp;#x27;/swapfile swap swap defaults 0 0&amp;#x27; を削除&lt;/span&gt;
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; swapoff -v /swapfile
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;rm&lt;/span&gt; /swapfile
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;インスタンス性能や必要に応じてインスタンスが落ちないように、スワップメモリ設定を行うことができる。&lt;/p&gt;
&lt;h4&gt;2. Jenkins プラグインインストールエラー時の対処方法&lt;/h4&gt;
&lt;p&gt;&amp;lt;解決策 1&amp;gt;
Jenkins の管理 &amp;gt; Plugin Manager &amp;gt; Advanced settings &amp;gt; 更新サイトのパートにアクセス
&lt;code&gt;https://updates.jenkins.io/update-center.json&lt;/code&gt; を &lt;code&gt;http://updates.jenkins.io/update-center.json&lt;/code&gt; に変更&lt;/p&gt;
&lt;p&gt;&amp;lt;解決策 2&amp;gt;
&lt;code&gt;skip-certificate-check&lt;/code&gt; という名前のプラグインをインストール&lt;/p&gt;
&lt;p&gt;完璧な解決策ではないが、これらの対策を全て適用することである程度効果が見られた。&lt;/p&gt;
&lt;h3&gt;締めくくりに&lt;/h3&gt;
&lt;p&gt;Docker 関連の内容は、後で扱う一部フレームワークのデプロイを除けば、ここでひと段落させる予定だ。それでも自分が作ったものを実際のネットワーク上で確認できるという達成感があるので、デプロイに関する内容は機会があれば今後ももう少し書いていきたい。&lt;/p&gt;
</content:encoded></item><item><title>[面接の質問] RESTful APIとは何ですか？</title><link>https://www.traceoflight.dev/ja/blog/restful-api/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/restful-api/</guid><description>RESTful APIに関する面接の質問まとめ</description><pubDate>Sun, 21 May 2023 17:27:57 GMT</pubDate><content:encoded>&lt;h3&gt;RESTful API&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;RESTfulなAPIを指す。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-3a8f738579ac35de-image.jpg&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;。極めて当たり前の言葉だが、まさにその通りだ！
それでは、各単語の意味を見ていけば、RESTful APIがどのようなものなのかが分かるだろう。&lt;/p&gt;
&lt;h3&gt;API&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Application Programming Interfaceの略称。
定義およびプロトコルの集合を用いて、2つのソフトウェアコンポーネントが相互に通信できるようにするメカニズム。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;このように定義されている。私なりの理解で言えば、ソフトウェアのコンポーネント同士でもオブジェクトなどを扱う方法がそれぞれ異なるため、この隔たりを処理するために規約を定め、相互に通信・相互作用できるようにしたものを指すと考えてよいだろう。&lt;/p&gt;
&lt;h3&gt;REST&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Representational State Transferの略称。
World Wide Webなどの分散ハイパーメディアシステムのためのソフトウェアアーキテクチャの一つ。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;RESTは当初、インターネットのような複雑なネットワークにおける通信を管理するための指針として作成され、大規模な通信において安定したサポートが可能であると言われ、実装や修正も容易である。&lt;/p&gt;
&lt;h4&gt;RESTアーキテクチャの原則&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一様なインターフェース (Uniform Interface)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;サーバーが標準形式で情報を送信する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;標準形式は、サーバー内のリソースの内部表現とは異なる場合がある&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;同一のリソースに対するすべてのAPIリクエストは、特定の言語やプラットフォームに関係なく同一である&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ステートレス (Stateless)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;各リクエストは、他のすべてのリクエストに対して独立している&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;サーバーは追加情報なしにリクエストを完全に理解し、実行できる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;階層化システム (Layered System)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;クライアントのリクエストを処理するために連携して動作する様々なアプリケーションが存在する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;サーバーは多層構造で構成され、サーバーとクライアントの間にも、承認された仲介者が存在し得る&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;プロキシ、ゲートウェイなどの中間媒体、暗号化、ロードバランシング層などが追加され得る&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;クライアントには見えない状態が維持される&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;キャッシュ可能性 (Cacheable)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;サーバーの応答時間を改善するために、一部の応答を保存するキャッシュをサポート&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;クライアント側またはサーバー側でキャッシュを実装する&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;オンデマンドコード (On Demand Code)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一般的に静的なリソースを送信&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;必要に応じて実行コードをレスポンスに含め、クライアント機能を一時的に拡張またはカスタマイズ可能&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;RESTful APIの利用メリット&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;スケーラビリティ&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;クライアントとサーバー間の相互作用を最適化するため、規模の調整が可能&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;柔軟性&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;完全なクライアント・サーバー分離をサポート&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;各部分が独立して発展できるよう、サーバーコンポーネントを簡素化・分離&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;独立性&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;使用される技術に依存しない&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;APIの設計に関係なく、様々なプログラミング言語を使用してクライアントおよびサーバーアプリケーションを作成し、技術を変更できる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;まとめ&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;RESTful APIとは？
RESTアーキテクチャを使用したアプリケーションプログラミングインターフェースを指し、RESTアーキテクチャの原則に準拠したプログラム間の相互作用を定めた規約である。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;では、どのような利点があるのでしょうか？
当該APIを使用する場合、拡張性、柔軟性、独立性の面でメリットがあると言える！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;p&gt;[[AWS] RESTful APIとは何ですか？](&lt;a href=&quot;https://aws.amazon.com/ko/what-is/restful-api/&quot;&gt;https://aws.amazon.com/ko/what-is/restful-api/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
</content:encoded></item><item><title>[1Day-1CS]ネットワーク機器の処理範囲</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-2e8effb4/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-2e8effb4/</guid><description>1日1CS、ネットワーク機器の処理範囲とアプリケーションレイヤを処理する機器についての簡単まとめ</description><pubDate>Fri, 19 May 2023 17:06:42 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;2023-06-18 内容範囲編集&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;階層別処理範囲 ### 層別処理範囲&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;アプリケーション層：L7スイッチ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;インターネット層: L3スイッチ、ルーター&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;データリンク層: L2スイッチ、ブリッジ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;物理層: NIC、リピータ、AP&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>面接の質問まとめ、スタート！（質問内容）</title><link>https://www.traceoflight.dev/ja/blog/velog-bdb80888/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/velog-bdb80888/</guid><description>面接でよく聞かれる質問のまとめと、この事業を始めた理由</description><pubDate>Tue, 16 May 2023 22:32:46 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-2d4a54a2ae94fc97-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;きっかけ&lt;/h3&gt;
&lt;p&gt;本格的に企業へ履歴書を送り始めてからどれくらい経っただろうか……それでも3ヶ月は経った気がする。コーディングテストはすべて合格しているわけではないが、合格率はかなり高く、最近になって何度か面接を受けてきた成果があった！&lt;/p&gt;
&lt;p&gt;しかし、面接に行っても、それなりにCSの勉強をしたとしても、面接で出される質問と私が勉強したCSの知識には違いがあることに気づいた…… そこで、面接で出題された問題について、ピンポイントで勉強した内容をブログにまとめてみようと思う。&lt;/p&gt;
&lt;h3&gt;質問リスト&lt;/h3&gt;
&lt;h4&gt;全体&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;[RESTful APIとは？](/blog/restful-api&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[プロセスとスレッドの違い](/blog/process-thread&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[ForkとExecの違い](/blog/fork-exec&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[フレームワークとライブラリ](/blog/framework-library&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;トランザクションとは？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;OSI 7層モデルについて&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;サブネットとゲートウェイ、プライベートIPについて&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;バックエンド&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;[DBインデックスとは？](/blog/db-index&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[コネクションプールとは？](/blog/connection-pool&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[JVMの構造と原理](/blog/jvm&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[Javaのヒープとスタックの構造](/blog/java-stack-heap&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[依存性注入](/blog/dependency-injection&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Spring IoCコンテナがどのようにBeanを管理するか
+ プロキシパターン、Spring Beanはプロキシであるにもかかわらず、どのようにマルチスレッド動作を実現しているか&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;シングルトンパターンとSpringの依存性注入&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Frontend&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;アドレスバーにアクセスURLを入力すると何が起こるか&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[1Day-1CS] 層間データ送受信プロセス &amp; PDU</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-pdu/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-pdu/</guid><description>1日1CS、レイヤ間データ送受信およびTDUに関する簡単なまとめ</description><pubDate>Sun, 07 May 2023 17:02:23 GMT</pubDate><content:encoded>&lt;h3&gt;カプセル化・非カプセル化プロセス&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;カプセル化: 上位階層のヘッダとデータを下位階層のデータ部分に含めて、その階層のヘッダを挿入するプロセス。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;アプリケーション → 伝送 → インターネット → リンク層への転送&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;伝送層に転送され、セグメント化またはデータグラム化 + TCP (Layer 4) ヘッダーを追加。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;インターネット層に転送され、IP(Layer 3)ヘッダーを追加 = パケットに追加&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;リンク層に転送され、フレームヘッダー + フレームトレーラーを追加 = フレーム&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;非包装化: 下位層から上位層に進み、各層のヘッダ部分を削除する過程。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;非包装化は逆に進行&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;フレーム → パケット → セグメント、データグラム → メッセージ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;最終的にアプリケーションのTDU(Transmission Data Unit)メッセージに転送します。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Protocol Data Unit&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;層から層から層へデータが伝達されるときの一塊の単位。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;メッセージ、セグメント、データグラム、パケット、フレーム、ビットなど階層ごとに名称が異なる。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ビットで送信するのが最も速く、効率が高い。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;アプリケーション層では、文字列ベースの送受信(拡張が容易であるという理由に由来)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[1Day-1CS]半二重化通信(2), 無線通信とイーサネットフレーム</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-70a48fb3/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-70a48fb3/</guid><description>1日1CS、半二重通信、無線通信、イーサネットフレームに関する簡単なまとめ</description><pubDate>Thu, 04 May 2023 14:01:28 GMT</pubDate><content:encoded>&lt;h3&gt;半二重化通信の種類&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;CSMA/CD: データを送信した後、衝突が発生した場合、一定時間後に再送信する方式。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CSMA/CA: データを送信する前にキャリア検出などで事前に可能な限り衝突を防止する方式。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;データ送信前に無線媒体の確認&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;回線が空いているかどうかを判断（キャリア検出）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使用中の場合、ランダム値を基に間隔を増やしながら使用可能性チェック(IFS)を行います。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;無線通信&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Wifi: 電子機器が無線LAN信号に接続できるようにする技術、無線接続装置が必要。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;BSS(Basic Service Set)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;基本サービスセットを意味する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ルーターを通じた単純接続 + 同じBSS内のAPおよびデバイス同士が通信可能。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ESS(Extended Service Set)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一つ以上の接続されたBSSグループ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;長距離無線通信を提供&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;BSSと比較して、より多くの可用性とモビリティをサポートします。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ある場所から別の場所に移動して、中断することなくネットワークに接続し続けることができます。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;イーサネットフレーム&lt;/h3&gt;
&lt;p&gt;データリンク層で使用される伝送メカニズム&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Preamble: イーサネットフレームの開始を通知します。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SFD (Start Frame Delimiter)：次のバイトからMACアドレスフィールドが始まることを知らせる。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DMAC, SMAC: 送受信MACアドレス&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;EtherType: IPプロトコルを定義&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Payload: 受け取ったデータ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CRC: エラーチェックビット&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[BOJ 2473, Python] 3つの溶液</title><link>https://www.traceoflight.dev/ja/blog/boj2473/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj2473/</guid><description>BOJ 2473、「3つの溶液」問題のPythonによる解法</description><pubDate>Thu, 04 May 2023 13:15:05 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2473&quot;&gt;BOJ 2473&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;二分探索、ソート、ツーポインター&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;典型的なツーポインター問題から少し発展した問題のようだ。&lt;/p&gt;
&lt;p&gt;最初にこの問題を解く際、3つの溶液を混ぜ合わせなければならないことから、何か別の解法があるだろうと考えてしまい、意外にも正攻法を使わなかった。その結果、実際の解法が遅れることになってしまった。&lt;/p&gt;
&lt;p&gt;この問題で注意すべき点は、溶液の総数が5000以下であるという点だ。この条件がなければ、この問題を絶対に制限時間内に解くことはできない……当初、この条件を注意深く見ていなかったために、他の解法を探し続けてしまった点は、今思っても残念な点だった。&lt;/p&gt;
&lt;p&gt;したがって、この問題の解決方法は次のように提示できるだろう。&lt;/p&gt;
&lt;p&gt;順序ソート → 溶液1つを固定 → 残りの溶液について、その溶液と合算して0に最も近くなるように2点法アルゴリズムを使用 → すべて巡回したか、0に達した場合は終了&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 세 용액&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sys

&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt; = sys.stdin.readline

solution_number = &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;())
solution_list = &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split()))

solution_list.sort()
characteristic_value = &lt;span class=&quot;hljs-number&quot;&gt;3000000000&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(solution_number):

    pointer_1 = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
    pointer_2 = solution_number - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; pointer_1 &amp;lt; pointer_2:

        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; pointer_1 == idx:
            pointer_1 += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; pointer_2 == idx:
            pointer_2 -= &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; pointer_1 &amp;gt;= pointer_2:
            &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

        now_value = &lt;span class=&quot;hljs-built_in&quot;&gt;sum&lt;/span&gt;([solution_list[idx], solution_list[pointer_1], solution_list[pointer_2]])

        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;abs&lt;/span&gt;(now_value) &amp;lt; characteristic_value:
            characteristic_value = &lt;span class=&quot;hljs-built_in&quot;&gt;abs&lt;/span&gt;(now_value)
            result = [solution_list[idx], solution_list[pointer_1], solution_list[pointer_2]]

            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; characteristic_value:
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; now_value &amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;:
            pointer_1 += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;elif&lt;/span&gt; now_value &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;:
            pointer_2 -= &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; characteristic_value:
        &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

result.sort()

&lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(*result)

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[1Day-1CS] 全二重化通信と半二重化通信 (1)</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-1/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-1/</guid><description>1日1CS、全二重通信と半二重通信の導入部の簡単なまとめ</description><pubDate>Mon, 01 May 2023 16:24:13 GMT</pubDate><content:encoded>&lt;h3&gt;全二重化通信&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;両方の装置が同時に送受信できる方式&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;送信路と受信路を区分してデータを送受信する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;現代の高速イーサネットが該当方式を使用&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;半二重化通信&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;双方のデバイスは互いに通信できるが、同時に通信することはできません。
一度に一つの経路に基づいて、一度に一つの方向のみ通信します。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;データを送信した後、衝突が発生した場合、一定時間後に再送信を行います。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;有線LAN&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ツイストペアケーブル: ノイズ(CrossTalk)を低減するため、撚り合わせたケーブル。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;光ファイバーケーブル：コアとケーブルの屈折率差を利用した光の伝送ケーブル。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;無線LAN&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;送信と受信に同じチャンネルを使用するため、半二重化通信を使用します。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[1Day-1CS】インターネット層とリンク層</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-e167b4e7/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-e167b4e7/</guid><description>1日1CS、インターネット層とリンク層についての簡単なまとめ</description><pubDate>Thu, 27 Apr 2023 03:32:49 GMT</pubDate><content:encoded>&lt;h3&gt;インターネット層&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;デバイスから受信したネットワークパケットをIPアドレスで指定された宛先に送信するために使用される層です。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;リンク層&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;実質的にデータを転送し、デバイス間で信号を送受信するルールを決める層、ネットワークアクセス層とも呼ばれる。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;物理層: LANを介して0、1で構成されたデータを送る層。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;データリンク層：Ethernet Frameを介してエラー確認、フローおよびアクセス制御を担当する層。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[1Day-1CS] 伝送層</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-f7e9e56d/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-f7e9e56d/</guid><description>1日1CS、伝送層についての簡単なまとめ</description><pubDate>Tue, 25 Apr 2023 17:14:48 GMT</pubDate><content:encoded>&lt;p&gt;伝送レイヤ ### 伝送レイヤ&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;送信者と受信者をつなぐ通信サービスを提供
接続指向のデータストリームのサポート、信頼性、フロー制御を提供します。
アプリケーションとインターネット層間のデータ転送中継の役割 &amp;gt; アプリケーションとインターネット層間のデータ転送中継の役割&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;TCP: 順序保証、接続指向のプロトコル使用、受信可否の確認(仮想回線パケット交換方式)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UDP: 順序保証X、受信可否確認X、単純なデータ転送(データグラムパケット交換方式)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;仮想回線パケット交換方式&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;各パケットに仮想回線識別子を含む。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;すべてのパケットを送信したら仮想回線を解除、パケットは送信順に到着。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;データグラムパケット交換方式&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;パケットが独立して移動し、最適な経路を選択します。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;異なる経路で送信することができ、順序も異なる場合がある。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;TCPの接続成立と解除の過程&lt;/h3&gt;
&lt;h4&gt;接続: 3-way handshake&lt;/h4&gt;
&lt;p&gt;1.クライアントが自分のISNを含む接続要求フラグを送信。
2.サーバーが承認番号でサーバーのISNとクライアントのISN + 1を返送する。
3.クライアントがサーバーのISN + 1を承認番号と一緒に再応答する。&lt;/p&gt;
&lt;h4&gt;接続解除: 4-way handshake&lt;/h4&gt;
&lt;p&gt;1.クライアントがFIN設定されたセグメントを送信してFIN_WAIT突入
2.デーラーを受け取ったサーバーがクライアントにACK承認セグメントを送り、CLOSE_WAITに突入。
3.ACKを送った後、一定時間が経過した後、FINセグメントを送信。
4.ACKを受け取ったクライアントがTIME_WAITに突入し、サーバーにACKを再送信します。
5.受信したサーバーがCLOSE&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;TIME_WAITを使う理由: 遅延パケットの可能性、接続解除を確実に確認する。&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>[BOJ 7490, Python] 0を作る</title><link>https://www.traceoflight.dev/ja/blog/boj7490/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj7490/</guid><description>BOJ 7490、「0を作る」問題のPythonによる解法</description><pubDate>Mon, 24 Apr 2023 16:15:36 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/7490&quot;&gt;BOJ 7490&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;バックトラッキング、ブルートフォースアルゴリズム、実装、文字列&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;典型的なバックトラッキング問題だと思う。しかし、処理の流れが少し分かりにくい点があり、ソート順がASCII順であるという点も少し独特だったようだ。&lt;/p&gt;
&lt;p&gt;PythonのEval関数を使えば簡単に解けると思ったが、その方法を使わず、正攻法で解いた。&lt;/p&gt;
&lt;p&gt;基本的には、数字の合計と未処理の数字2つを持ち、バックトラッキングを進めながら、「加算」、「減算」、「演算しない」という3つのケースについてすべて確認するという考え方で試したところ、正解と判定された。&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 0 만들기&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sys

&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt; = sys.stdin.readline

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;make_sum_zero&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;
    result_arr: &lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt;,
    target_arr: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;,
    last_index: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;,
    now_index: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,
    sum_now: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,
    now_calc: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,
    log=[],
&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
    &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
    백트래킹을 활용하여 숫자들의 합이 0이 되도록 만드는 함수
    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; last_index == now_index:
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; sum_now + now_calc:
            result_arr.add(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;.join(log))

    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; now_index:
            make_sum_zero(
                result_arr,
                target_arr,
                last_index,
                now_index + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,
                &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;,
                target_arr[now_index],
                [&lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;(target_arr[now_index])],
            )

        &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
            new_number = target_arr[now_index]

            make_sum_zero(
                result_arr,
                target_arr,
                last_index,
                now_index + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,
                sum_now + now_calc,
                new_number,
                log + [&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;+&amp;quot;&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;(new_number)],
            )
            make_sum_zero(
                result_arr,
                target_arr,
                last_index,
                now_index + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,
                sum_now + now_calc,
                -new_number,
                log + [&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;-&amp;quot;&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;(new_number)],
            )

            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; now_calc &amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;:
                make_sum_zero(
                    result_arr,
                    target_arr,
                    last_index,
                    now_index + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,
                    sum_now,
                    &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt; * now_calc - new_number,
                    log + [&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;(new_number)],
                )
            &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
                make_sum_zero(
                    result_arr,
                    target_arr,
                    last_index,
                    now_index + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;,
                    sum_now,
                    &lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt; * now_calc + new_number,
                    log + [&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;(new_number)],
                )

testcase = &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;())
output = []

&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(testcase):
    arr_length = &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;())
    result = &lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt;()

    &lt;span class=&quot;hljs-comment&quot;&gt;# 함수를 통해 결과 확인&lt;/span&gt;
    target_arr = [i &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, arr_length + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]
    make_sum_zero(result, target_arr, arr_length)

    &lt;span class=&quot;hljs-comment&quot;&gt;# 혹여라도 겹치는 결과가 있다면 Set을 통해 배제, ASCII 순으로 정렬&lt;/span&gt;
    sort_result = &lt;span class=&quot;hljs-built_in&quot;&gt;sorted&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(result), key=&lt;span class=&quot;hljs-keyword&quot;&gt;lambda&lt;/span&gt; x: &lt;span class=&quot;hljs-built_in&quot;&gt;ascii&lt;/span&gt;(x))
    output.append(sort_result)

&lt;span class=&quot;hljs-comment&quot;&gt;# 문제 조건에 맞춰 출력&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(testcase):
    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; element_idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(output[idx])):
        &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(output[idx][element_idx])

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; idx != testcase - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:
        &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[1Day-1CS] TCP/IP 4層モデルとアプリケーション層</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-tcp-ip-4/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-tcp-ip-4/</guid><description>1日1CS、TCP/IP 4層モデルとアプリケーション層に関する簡単なまとめ</description><pubDate>Mon, 24 Apr 2023 15:18:37 GMT</pubDate><content:encoded>&lt;h3&gt;インターネットプロトコルスイート (Internet Protocol Suite)&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;インターネット上でコンピュータ同士が情報をやり取りするために使用されるプロトコルの集合&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;TCP/IP 4層モデルまたはOSI 7層モデルを用いて説明される&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;TCP/IP 4層&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ネットワークの範囲に応じて、4つの抽象化層で構成される&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;アプリケーション層&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;伝送層&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;インターネット層&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;リンク層&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;OSI層は、アプリケーション層およびリンク層を細分化したことが特徴&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;アプリケーション層&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;FTP、HTTP、SSH、SMTP、DNSなど、アプリケーションが使用されるプロトコル層&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;FTP: デバイス間のファイル転送&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SSH: Secure Shell Protocol、暗号化ネットワークプロトコル&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;HTTP: World Wide Webを通じてウェブサイトを利用するために使用されるプロトコル&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SMTP: 電子メール転送のためのインターネット標準通信プロトコル&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DNS: ドメイン名とIPアドレスを対応付けするサーバー&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;実質的に人々にサービスを提供する層&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[BOJ 25542, Python] 待ち合わせ場所</title><link>https://www.traceoflight.dev/ja/blog/boj25542/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj25542/</guid><description>BOJ 25542、「待ち合わせ場所」問題のPythonによる解法</description><pubDate>Sun, 23 Apr 2023 18:10:04 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;[BOJ 25542](&lt;a href=&quot;https://www.acmicpc.net/problem/25542&quot;&gt;https://www.acmicpc.net/problem/25542&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;ブルートフォースアルゴリズム、実装、文字列&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;初めてこの問題をコンテストで見た時、アイデア自体は難しくないと思っていた。しかし、思った以上に実装に手間がかかる問題であり、7ヶ月前の私はPythonのコードを書くことさえ非常に苦手にしていたため、この問題を解くことができなかった。&lt;/p&gt;
&lt;p&gt;3ヶ月前の私もこの問題を解決しようとしたが、構想したアイデアにさらなるプルーニングが必要だという結論に至り、再び挫折して問題を後回しにするしかなかった。&lt;/p&gt;
&lt;p&gt;最近、余裕もできたし、以前解けなかった問題に再挑戦したいという欲求があったので、改めて試してみたところ、ついに解くことができた！しかし、依然としてこの問題がシルバー問題であるということには疑問がある……&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-90c53486a9b70423-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;当初は、既存の文字列だけで結果を導き出そうとしたが、当然ながら反例が存在するため失敗に終わった。&lt;/p&gt;
&lt;p&gt;次に試したコードも実装を少し工夫したが、やはり既存の文字列のみを使用していたため、それ以外の文字列を使った反例を解決できなかった。以下のコードを添付する。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sys
&lt;span class=&quot;hljs-keyword&quot;&gt;from&lt;/span&gt; itertools &lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; product

&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt; = sys.stdin.readline

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;is_similar&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;checker: &lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;, target: &lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;bool&lt;/span&gt;:
	&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&amp;#x27;
    두 문자열이 비슷한지 확인하는 함수
    &amp;#x27;&amp;#x27;&amp;#x27;&lt;/span&gt;
    
    length = &lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(checker)
    counter = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(length):

        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; checker[idx] != target[idx]:
            counter += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; counter &amp;lt;= &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;
    
    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;False&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 입력&lt;/span&gt;
store_number, name_length = &lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split())

&lt;span class=&quot;hljs-comment&quot;&gt;# 각 문자열의 동일 인덱스를 집합화&lt;/span&gt;
name_list = []
store_chr_arr = [&lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt;() &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(name_length)]

&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(store_number):
    each_name = &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;())
    name_list.append(each_name)

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(name_length):
        store_chr_arr[idx].add(each_name[idx])

result = &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 겹치지 않는 문자열의 Product를 비교&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; each_name_combination &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; product(*store_chr_arr):
    target_name = &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&lt;/span&gt;.join(each_name_combination)
    
    is_answer = &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; check_name &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; name_list:
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; is_similar(target_name, check_name):
            is_answer = &lt;span class=&quot;hljs-literal&quot;&gt;False&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; is_answer:
        result = target_name
        &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; result &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;CALL FRIEND&amp;#x27;&lt;/span&gt;)

&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(result)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当初、未使用の文字を使用しようと試みたことはあったが、実装力が不足していたため実際の実装には移せなかったが、その方法を通じて「正解」を得ることができた。&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 약속 장소&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sys

&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt; = sys.stdin.readline

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;is_similar&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;checker: &lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;, target: &lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;bool&lt;/span&gt;:
    &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&amp;#x27;
    두 문자열이 비슷한지 확인하는 함수
    &amp;#x27;&amp;#x27;&amp;#x27;&lt;/span&gt;

    length = &lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(checker)
    counter = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(length):

        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; checker[idx] != target[idx]:
            counter += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; counter &amp;lt;= &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;False&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 정보 입력&lt;/span&gt;
store_number, name_length = &lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split())

name_list = []
first_checker = &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 첫 문자열만 따로 분류하고 나머지는 이름 리스트에 기록&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(store_number):
    each_name = &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().rstrip(&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;\n&amp;#x27;&lt;/span&gt;))

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; first_checker:
        target_name = each_name
        first_checker = &lt;span class=&quot;hljs-literal&quot;&gt;False&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
        name_list.append(each_name)

&lt;span class=&quot;hljs-comment&quot;&gt;# 첫 문자열을 통해 문자열 변형된 후보를 양산&lt;/span&gt;
result_set = &lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt;()

&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(name_length):
    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; alpha &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;65&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;91&lt;/span&gt;):
        temp = target_name[:]
        temp[idx] = &lt;span class=&quot;hljs-built_in&quot;&gt;chr&lt;/span&gt;(alpha)
        result_set.add(&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&lt;/span&gt;.join(temp))

&lt;span class=&quot;hljs-comment&quot;&gt;# 확인하면서 후보를 소거&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; result_set &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; name_list:

    now_check_name = name_list.pop()
    remove_target = &lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt;()

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; each_result &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; result_set:
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; is_similar(now_check_name, each_result):
            remove_target.add(each_result)

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; each_target &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; remove_target:
        result_set.remove(each_target)

&lt;span class=&quot;hljs-comment&quot;&gt;# 후보가 안 남았다면 문구를 출력, 후보가 남았다면 후보 중 하나를 출력한다.&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; result_set:
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;CALL FRIEND&amp;#x27;&lt;/span&gt;)

&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(result_set.pop())
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[1Day-1CS]ボトルネック、ネットワークの分類と分析</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-26405cdf/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-26405cdf/</guid><description>1日1CS、ボトルネックとネットワークの分類と分析に関する簡単なまとめ</description><pubDate>Sun, 23 Apr 2023 13:06:14 GMT</pubDate><content:encoded>&lt;h3&gt;ボトルネック&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;システム全体の性能や容量が一つのコンポーネントによって制限される現象。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;サーバーでイベントを開いた時、トラフィックが多く発生し、うまく管理しなければ発生する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ネットワークトポロジに関する情報がなければ、ボトルネック現象を正しく解決することができません。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ボトルネック現象の主な原因&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ネットワーク帯域幅&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ネットワークトポロジ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;サーバーCPU、メモリ使用量&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;非効率的なネットワーク構成&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ネットワークの分類&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;ネットワークは規模に基づいて分類&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;LAN (Local Area Network)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;近距離通信網&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;伝送速度が速く、混雑していない。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MAN (Metropolitan Area Network)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;大都市圏ネットワーク&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;伝送速度は平均、LANより混雑しています。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;WAN (Wide Area Network)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;広域ネットワーク&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;伝送速度が遅く、MANより混雑している。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ネットワーク性能分析コマンド&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ping&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;状態を確認したい対象ノードに一定サイズのパケットを送信します。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;パケット受信状態や到達時間などの情報を確認することができます。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;netstat&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;接続されたサービスのネットワーク状態を表示&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ネットワーク接続、ルーティングテーブル、ネットワークプロトコルなどのリストを表示します。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;nslookup&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;DNS関連の内容を確認するために使用します。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;特定のドメインにマッピングされたIPを確認することができます。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;tracert (traceroute)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;目的地ノードまでのネットワーク経路を確認する際に使用します。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;どの区間で応答時間が遅くなるのかなどを確認することができます。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;その他様々なコマンドが存在し、wireshark, netmonなどのプログラムを使用する。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[1Day-1CS] ネットワークトポロジー</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-21436c11/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-21436c11/</guid><description>1日1CS、ネットワークトポロジパターンの簡単なまとめ</description><pubDate>Thu, 20 Apr 2023 12:56:24 GMT</pubDate><content:encoded>&lt;h3&gt;ネットワークトポロジー&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;ノードとリンクがどのように配置されているかについての方式、接続形態&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;ツリートポロジー&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;階層型トポロジー、ツリー状に配置されたネットワーク構成&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ノードの追加、削除が容易&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;特定のノードにトラフィックが集中する場合、サブノードに影響を与える。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;バストポロジ&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;中央通信回線1本に複数のノードを接続する。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;近距離通信網に使用&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設置費用が少なく、信頼性に優れ、中央通信回線にノードの追加、削除が容易。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;スプーフィングの問題が存在&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;スプーフィング：
LAN上で&lt;strong&gt;送信と関係ない他のホスト&lt;/strong&gt;に
&lt;strong&gt;行かないようにするスイッチ機能を麻痺&lt;/strong&gt;させたり、騙したりすること。
&lt;strong&gt;特定のノードにそのパケットが来るように処理&lt;/strong&gt;すること。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;スタートポロジ&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;中央にあるノードに全て接続されているネットワーク構成&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ノードを追加したり、エラーを検出しやすい。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;パケットの衝突が発生する可能性が少ない&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;中央ノード障害発生時、ネットワーク全体を使用できない。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設置費用が大きい&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;リング型トポロジ&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;ノードからノードへデータを移動、リング状の経路でパケットを処理する。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ノード数が増加してもネットワーク上の損失がほとんどない。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;衝突発生可能性が少なく、ノードの故障発見が容易。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ネットワーク構成の変更が難しい&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;障害が発生すると、ネットワーク全体に影響を与える。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;メッシュトポロジ&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;網状トポロジー、網目状接続構造&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一つの端末に障害が発生しても、複数の経路が存在し、ネットワークの継続使用が可能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;トラフィックの分散処理が可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ノードの追加が難しく、構築及び運用費用が大きい。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[1Day-1CS]ネットワーク起動、スループットと遅延時間</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-4b2e3588/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-4b2e3588/</guid><description>1日1CS、スループットと遅延時間についての簡単なまとめ</description><pubDate>Mon, 17 Apr 2023 14:32:41 GMT</pubDate><content:encoded>&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;いよいよ自叙伝の季節が到来し、最近忙しすぎるようですが、それでもコツコツと勉強することが役に立つと思うので、頑張ってみようという決意をもう一度してみます！&lt;/p&gt;
&lt;h3&gt;ネットワーク&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;ノードとリンクが相互に接続されているか、接続やリソースを共有している集合を意味する。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Node: サーバー、ルーター、スイッチなどの装置
Link: ワイヤレス or 有線&lt;/p&gt;
&lt;h3&gt;スループットと遅延時間&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;多くのスループットを処理することができ、遅延時間が短く、障害頻度が少なく、優れたセキュリティを備えたネットワークを意味する。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;スループット：リンク内で正常に転送されたデータの量&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;トラフィック：特定の時点でリンク内に流れるデータの量。
→ トラフィックが多くなった = 流れるデータが多くなった。
→ スループットが多くなった = 処理されるトラフィックが多くなった。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;スループットは、トラフィック、帯域幅、ネットワーク発生エラー、デバイススペックの影響を受ける。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;遅延時間：リクエストが処理される時間、往復で測定。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;遅延時間は、メディアの種類、パケットのサイズ、ルータのパケット処理時間に影響されます。&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>[1Day-1CS】デザインパターン＆パラダイムまとめ</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-5e78c961/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-5e78c961/</guid><description>1日1CS、デザインパターンとプログラミングのパラダイムに関する内容をまとめています。</description><pubDate>Mon, 10 Apr 2023 16:56:14 GMT</pubDate><content:encoded>&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;いままとめている内容はすべて「面接のための CS 専攻知識ノート」を基にしている。本来 1 日 1CS を始めるときに触れておくべき内容だったかもしれないが、ㅋㅋ 今からでも書き残しておく。&lt;/p&gt;
&lt;h3&gt;デザインパターン&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;プログラムを設計するときに発生した問題を、オブジェクト同士の関係などを通じて解決できるようにつくった規約&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Singleton パターン: 1 クラス 1 インスタンス / モジュール結合の問題を解くために依存性注入を活用&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Factory パターン: 上位クラスで大枠を決め、下位クラスが継承で具体化する&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Strategy パターン: カプセル化されたアルゴリズムを Context 内部で差し替えながら使う&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Observer パターン: 状態変化を観察し、変化時にメソッドなどで変更内容を伝える&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Proxy パターン: 対象オブジェクトにアクセスする前に流れを差し挟むインターフェイスの役割&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Iterator パターン: イテレータを使ってコレクションの要素にアクセスし、ひとつのインターフェイスで巡回できる&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;公開モジュール (Revealing Module) パターン: アクセス制御子を作るパターン&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;MVC パターン: Model, View, Controller で構成され、アプリケーションの構成要素を分割して開発できるようにする&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;MVP パターン: Controller を Presenter に置き換える&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MVVM パターン: Controller を View Model に置き換える&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3&gt;プログラミングパラダイム&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;宣言型と命令型の区別
→ 宣言型は「何を」？ 命令型は「どうやって」？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;宣言型&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;関数型プログラミング: 純粋関数を積み上げてロジックを実装&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;命令型&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;オブジェクト指向プログラミング: オブジェクトの相互作用を表現し、オブジェクトのメソッドを活用&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;手続き型プログラミング: 連続した計算で構成され、コードをそのまま記述すれば成立する&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[1Day-1CS] 手続き型プログラミングとパラダイムの混合</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-fbf17eb9/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-fbf17eb9/</guid><description>「1日1CS」、手続き型プログラミング、パラダイムの選択に関する簡単なまとめ</description><pubDate>Sat, 08 Apr 2023 15:32:23 GMT</pubDate><content:encoded>&lt;h3&gt;手続き型プログラミング&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ロジックが実行される連続的な計算プロセスで構成される&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;コードが進行手順通りに実装されるため、可読性が高く、実行速度が速い&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;モジュール化が難しく、保守性が低いという欠点がある&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;パラダイムの選択&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;パラダイムに絶対的な優位性といったものは存在しない&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;サービスの特徴やビジネスロジックを考慮してパラダイムを選択する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ロジックに応じて適宜選択するのも良い&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[1Day-1CS] オブジェクト指向プログラミングの設計原則</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-oop/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-oop/</guid><description>「1日1CS」、オブジェクト指向プログラミングの設計原則に関する簡単なまとめ</description><pubDate>Thu, 06 Apr 2023 12:27:00 GMT</pubDate><content:encoded>&lt;h3&gt;単一責任の原則&lt;/h3&gt;
&lt;p&gt;Single Responsibility Principle&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;すべてのクラスは、それぞれ1つの責任のみを持つべきである。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;開閉原則&lt;/h3&gt;
&lt;p&gt;Open Closed Principle&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;メンテナンスの際、既存のコードへの変更は最小限に抑え、拡張が容易でなければならない。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;リスコフの置換の原則&lt;/h3&gt;
&lt;p&gt;Liskov Substitution Principle&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;オブジェクトは、プログラムの正確性を損なうことなく、サブタイプのインスタンスと置き換え可能でなければならない。つまり、継承が問題なく機能するようにしなければならないという意味である。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;インターフェース分離の原則&lt;/h3&gt;
&lt;p&gt;Interface Segregation Principle&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1つの一般的なインターフェースの代わりに、具体的な複数のインターフェースを作成すること&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;依存性反転の原則&lt;/h3&gt;
&lt;p&gt;Dependency Inversion Principle&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;上位層は下位層の変化から独立していなければならない。自分よりも変化しやすいものに影響を受けないよう、上位クラスや抽象インターフェースを配置すべきである。&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>サムスンソフトウェアコンピテンシー評価B型レビュー</title><link>https://www.traceoflight.dev/ja/blog/samsung-software-competency-evaluation-type-b/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/samsung-software-competency-evaluation-type-b/</guid><description>サムスンのソフトウェア能力評価を3回全て受けて失敗した経験を書いた手記</description><pubDate>Thu, 06 Apr 2023 12:08:47 GMT</pubDate><content:encoded>&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;まず結論から言うと、これまでに与えられた3回のチャンスのうち2回を逃してしまった。そこで、今後どのような勉強をすれば成功できるのかを残しておきたいと思います。&lt;/p&gt;
&lt;p&gt;資格 ### 資格&lt;/p&gt;
&lt;p&gt;サムスン青年ソフトウェアアカデミーの模擬能力評価A型資格を持って受験した。&lt;/p&gt;
&lt;p&gt;回顧 ###回顧&lt;/p&gt;
&lt;p&gt;従来は、どうしても実装することに時間を割きすぎただけでなく、最適化の部分においても多くの不足を感じました。今後、受験できる機会が1回ほど残っていますが、最適化について勉強をたくさんして臨まなければならないと思いました。&lt;/p&gt;
&lt;h4&gt;1.オブジェクトの使用不足&lt;/h4&gt;
&lt;p&gt;どうやらPythonを使ってきたからか、オブジェクトを中心にコーディングすることに慣れていない面があり、たくさん習得しようとしましたが、まだ実力不足を感じています。特にComparatorのようにoverrideして使う部分が難しいと感じます。&lt;/p&gt;
&lt;h4&gt;2.資料構造熟知状態&lt;/h4&gt;
&lt;p&gt;B型合格者たちの話を聞いてみると、全体的にデータ構造についての話をたくさん強調していますが、私がその分、データ構造を十分に熟達しているかと聞かれたら、まだ足りない面があるので、最後のテスト時点まで復習する時間を十分に持つ必要があると思います。&lt;/p&gt;
&lt;h3&gt;+追加&lt;/h3&gt;
&lt;p&gt;4月末を最後に3回のB型の旅が終了した。結果的にB型の資格を取得することができず、最後の問題はほぼ出題されたのですが、最後の一歩を踏み出せなかったのが残念です。&lt;/p&gt;
&lt;p&gt;しかし、挑戦しようとしたからこそ努力したし、努力したからこそ、ある程度のレベルアップができたと思う。&lt;/p&gt;
&lt;p&gt;おかげで、企業入社のコーディングテストを受ける際に、比較的問題が易しそうなのは明らかなメリット。&lt;/p&gt;
&lt;p&gt;たぶん、現在私が持っている資格は仮A型なので、SSAFY修了後にもうB型を見る機会はないだろうが、それでももう一つ終わったという点ではスッキリした！&lt;/p&gt;
</content:encoded></item><item><title>[1Day-1CS] 命令型プログラミング &amp; オブジェクト指向プログラミング</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-cdddda5a/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-cdddda5a/</guid><description>1日1CS, 命令型プログラミング＆オブジェクト指向プログラミングの簡単なまとめ</description><pubDate>Fri, 31 Mar 2023 11:39:05 GMT</pubDate><content:encoded>&lt;h3&gt;コマンド型プログラミングの種類&lt;/h3&gt;
&lt;h4&gt;オブジェクト指向プログラミング（Object-Oriented Programming)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;オブジェクトの集合でプログラムの相互作用を表現し、オブジェクト内部に宣言されたメソッドを活用する方式。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設計に多くの時間がかかり、速度が他のプログラミングパラダイムに比べて遅い。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;オブジェクト指向プログラミングの特徴&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;抽象化: 複雑なシステムから核心的な概念、機能を簡略化すること。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;カプセル化：オブジェクトの属性とメソッドを一つにまとめ、一部を外部から隠蔽すること。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;継承性: 上位クラスの特性を下位クラスが引き継ぎ、再使用、追加、拡張が可能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;多形性：一つのメソッドやクラスが様々な方法で動作可能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Overloading: 同じ名前のメソッドを複数持つこと、&apos;コンパイル&apos;中に発生する&apos;静的&apos;多形性。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Overriding：親クラスから継承したメソッドを子クラスが上書きすること、「実行時」に発生する「動的」多形性。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[1Day-1CS] Declarative Programming</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-dbfa4ad8/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-dbfa4ad8/</guid><description>1日1CS、宣言型プログラミングの簡単なまとめ</description><pubDate>Fri, 31 Mar 2023 11:36:56 GMT</pubDate><content:encoded>&lt;h3&gt;プログラミングパラダイム&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;プログラマーにプログラミングの観点を持たせる役割を果たす開発方法論&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;宣言型 vs 命令型&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;宣言型: 何を解くかに焦点を当てるパラダイム (What)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;命令型: どのように解くかに焦点を当てるパラダイム (How)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;例)
宣言型: 家の住所 (位置を正確に指定)
命令型: 家までの経路 (位置までの行き方を提示)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;宣言型プログラミングの種類&lt;/h3&gt;
&lt;h4&gt;関数型プログラミング&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;小さな純粋関数をブロックのように積み上げてロジックを実装し、高階関数を実装して再利用性を高めるプログラミングパラダイム&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;純粋関数: 出力が入力にのみ依存する関数&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;高階関数: 関数を値のように引数として受け取りロジックを構築する関数&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;言語が 1 級オブジェクト (First Class Object) を扱えるなら高階関数の使用が可能&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;1 級オブジェクトの特徴&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;変数やメソッドに関数を代入できる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;関数の中に関数を引数として渡せる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;関数が関数を返せる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>[1Day-1CS]MVCパターンと類似パターン</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-mvc/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-mvc/</guid><description>1日1CS、MVCパターンについての簡単なまとめ</description><pubDate>Thu, 30 Mar 2023 16:36:43 GMT</pubDate><content:encoded>&lt;h3&gt;MVC パターン&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Model, View, Controller で構成されるデザインパターン&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;アプリケーションの構成要素を 3 分割し、それぞれの要素にのみ集中して開発できるようにする&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;再利用性と拡張性が高い&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;アプリケーションの複雑度が高くなるほど Model と View の関係が複雑になる欠点がある&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Model&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;アプリケーションのデータで、DB・定数・変数などを指す&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h4&gt;View&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ユーザーインターフェイス要素を指し、Model を基にユーザーが見る画面を表す&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;モデルが持つ情報を別途保存せず、画面表示用の情報のみを保持する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;変更点が発生すると Controller に伝える&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Controller&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Model と View をつなぐ Bridge の役割&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Event などのメインロジックを担い、Life Cycle も管理する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Model または View の変更を通知されると、対応する内容を必要な構成要素へ伝える&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h4&gt;類似パターン&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;MVP パターン: Controller を Presenter に置き換える。View と Presenter の関係が 1:1 のため結合度がより強い&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MVVM パターン: Controller を View Model に置き換える。Command と Data Binding を持ち、UI の再利用性と単体テストの容易性を確保できる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[1Day-1CS] プロキシパターン＆イテレータパターン＆露出モジュールパターン</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-c6863ddc/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-c6863ddc/</guid><description>1日1CS、プロキシパターン、イテレータパターン、露出モジュールパターンに関する簡単なまとめ</description><pubDate>Tue, 28 Mar 2023 23:30:10 GMT</pubDate><content:encoded>&lt;h3&gt;プロキシパターン&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ターゲットオブジェクトにアクセスする前に、そのアクセスの流れを傍受し、ターゲットオブジェクトの前段のインターフェースとして機能するデザインパターン。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;セキュリティ、データ検証、キャッシュ、ロギングに使用し、オブジェクトではなくサーバーとしても活用される。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;プロキシサーバー&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;サーバーとクライアントの間で動作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;クライアントが自分を通して他のネットワークサービスに間接的にアクセスできるようにするシステムまたはプログラム。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;代表的な例としてApache、Nginx、CloudFlareなどが存在する。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;プロキシサーバーの使用例&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;プロキシを経由するため、実際に使用するポートを隠すことができます。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nginx を通じて静的リソースを gzip したり、メインサーバーの前段でロギングすることが可能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CloudFlareの場合、HTTPS構築に容易さを提供し、DDOS攻撃防御が可能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;フロントエンドプロキシサーバーを通じてCross Origin Resource Sharing (CORS) エラーを防止することができます。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;イテレータパターン&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;イテレータを使ってコレクションの要素にアクセスするデザインパターン。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;データ型の構造に関係なくイテレータという一つのインターフェースで巡回が可能という利点があります。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通常イテラブルなオブジェクトをイテレータプロトコルを通じて巡回することができる。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;露出モジュールパターン&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;即時実行関数でprivate, publicのようなアクセスコントローラを作るパターン。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;JSの場合は別途アクセス制御者が存在しないので、これを実装して構築することもある。&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[1Day-1CS] ファクトリーパターン・戦略パターン・オブザーバーパターン</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs-f886ff08/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs-f886ff08/</guid><description>「1日1CS」、ファクトリーパターン、戦略パターン、オブザーバーパターンの簡単なまとめ</description><pubDate>Mon, 27 Mar 2023 22:36:03 GMT</pubDate><content:encoded>&lt;h3&gt;ファクトリパターン&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;オブジェクトを使用するコードにおいて、オブジェクト生成部分を抽象化したパターン&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;親クラスが重要な骨格を決定&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;子クラスがオブジェクト生成に関する具体的な内容を決定&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;ファクトリパターンの特徴および利点&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;クラスの分離による疎結合を実現
親クラスの柔軟性を確保し、保守性を向上&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;ストラテジーパターン (ポリシーパターン)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;オブジェクトの振る舞いを変更したくない場合、直接修正しない&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;戦略に相当する&lt;strong&gt;カプセル化されたアルゴリズム&lt;/strong&gt;をコンテキスト内で変更できるように設計し、交換可能にする&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;コンテキスト&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;開発者が特定の作業を完了するために必要な関連情報を意味する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ある動作が発生するために不可欠な必須コンテキストと、動作を効果的に実行するための選択的コンテキストが存在する。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;オブザーバーパターン&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;主体が特定のオブジェクトの状態変化を観察する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;状態変化時にメソッドなどを通じて、オブザーバーに変化の事実を提供する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;主体とオブジェクトを分離せず、可変的なオブジェクトに基づいて構築することもある&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MVCパターンでも活用されている&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[1Day-1CS]シングルトンパターン</title><link>https://www.traceoflight.dev/ja/blog/1day-1cs/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/1day-1cs/</guid><description>1日1CS、シングルトンパターンの簡単まとめ</description><pubDate>Mon, 27 Mar 2023 15:29:32 GMT</pubDate><content:encoded>&lt;h3&gt;デザインパターンとは？&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;プログラム設計時に発生した問題点が存在
→ オブジェクト間の相互関係などを利用して解決できるように一つの規約にする。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;シングルトンパターン&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一つのクラス＝一つのインスタンス&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;クラスごとに複数の個別インスタンスを作ることができますが、そうせずに一つだけ使用します。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通常DBモジュールに多く使用&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;生産性 ↑, 依存性 ↓.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;シングルトンパターンのデメリット&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;TDD(Test Driven Development:テスト主導型開発)時、ユニットテストを進行する時、Issue発生の可能性&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;依存性が高いシングルトンパターンの特性上、各テストごとに独立したインスタンスを作るのが難しい。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;依存性注入&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;シングルトンパターンのモジュール間の結合を強くする短所を解決するための方法&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;メインモジュールが直接他のサブモジュールに依存性を与える代わりに&lt;strong&gt;依存性インジェクタ&lt;/strong&gt;を通じて間接的に依存性を注入(デカップリング)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;長所&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;モジュールを簡単に交換できる構造、Testing &amp;amp; Migrationが容易、依存性の方向性の一貫性、Application推論が簡単になる、関係の明確性など&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;短所&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;モジュールがさらに分離 → クラス数の増加で複雑性増大、ランタイムペナルティ&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;依存性注入の原則&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;上位モジュールは下位モジュールから何も取り込まない。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;両方とも抽象化に依存する必要がある + 抽象化は詳細に依存しない&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>[CI/CD] Docker + Jenkins + Git Webhookを活用したFastAPIサーバーの自動デプロイまとめ</title><link>https://www.traceoflight.dev/ja/blog/cicd-docker-jenkins-git-webhook/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/cicd-docker-jenkins-git-webhook/</guid><description>実戦的な圧縮と自動デプロイの実装</description><pubDate>Fri, 24 Mar 2023 02:08:12 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;内容整理中 &amp;gt; 2023 年 5 月時点で 1 次更新完了
&lt;a href=&quot;/blog/ci-cd-dood-feat-nginx-jenkins&quot;&gt;デプロイ関連の内容は、もう少し整えた 2 編を参照するのがよいです。&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;現在進めているプロジェクトで、AI モデルを活用したアウトプットを提供するサービスを構築していた。&lt;/p&gt;
&lt;p&gt;その機能を Firebase Cloud Function で構築したかったが、モデルをロードする過程などで nodeJS + tensorflow.js を使う関係上モデルの変形が避けられず、もともと重いことによるタイムアウトなど、さまざまな形で苦戦したため、AI モデルを通じた結果を返すシンプルなサーバを構築してみることにした。&lt;/p&gt;
&lt;p&gt;これに伴いサーバの構築とデプロイ作業が自分の役目となり、一次目標として自動デプロイの実現、その後の追加目標として無停止デプロイまで自分の手で進めることにした。&lt;/p&gt;
&lt;p&gt;本記事では AWS などのインスタンスをベースとしたシステム構築および自動デプロイまでだけを扱う。&lt;/p&gt;
&lt;h3&gt;事前知識&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;CI: Continuous Integration (継続的インテグレーション)&lt;/p&gt;
&lt;p&gt;開発者向けの自動化プロセスで、コード変更点がビルド・テストを経て定期的に共有リポジトリへマージされるという過程。これを自動化することで、開発過程のリスクを減らす手段として使われている&lt;/p&gt;
&lt;p&gt;CI Server, Source Control Management, Build Tool, Test Tool などで構成される&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;CD: Continuous Delivery / Deployment (継続的デリバリー / デプロイ)&lt;/p&gt;
&lt;p&gt;デプロイ自動化プロセスを意味し、パイプラインの追加段階を自動化することで、手動の介入なしに変更点が product まで自動的にデプロイされ得る。継続的インテグレーションの裏付けが必要であり、信頼できる環境を作れば 1 日に何度でもリリース可能になる&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;結果として、こうした CI/CD 過程を通じて製品リリースまでの時間を短縮でき、人員の効率を高め、漸進的かつ継続的なプロセスの連続なので、大きな問題が発生する確率を減らしていける。&lt;/p&gt;
&lt;h3&gt;Docker 環境のセットアップ&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;インスタンス情報&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;EC2 のフリーティアの代わりに、相対的に条件のよい Oracle Cloud のフリーティアを採用
arm64 ベースの Ampere A1 Compute 2 Core と 12GB RAM を割り当てて使用&lt;/p&gt;
&lt;p&gt;このほかにもバックアップなどのオプションを無料である程度サポートしているので参考に！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Linux のセットアップ
&lt;a href=&quot;https://bgpark.tistory.com/85&quot;&gt;EC2 を password で接続する方法&lt;/a&gt; - ログイン関連の利便のため、ssh セットアップを扱う記事
&lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/&quot;&gt;Docker のインストール&lt;/a&gt; - Ubuntu 基準の Docker インストール公式 DOCS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;筆者が参考にした資料をまとめた。Docker のインストール手順やインスタンスのセットアップに関する記事は多数存在するので、調べながら Docker をセットアップすれば良い。&lt;/p&gt;
&lt;h3&gt;Docker in Docker のセットアップ (失敗 &amp;gt; API を活用した Docker out of Docker で進行)&lt;/h3&gt;
&lt;h4&gt;使う理由&lt;/h4&gt;
&lt;p&gt;Docker の上でさらに Docker を扱う理由は、コンテナをコンテナで制御するためであり、基本的にそのコンテナの権限が非常に強くなるためセキュリティ上のリスクは指摘されるが、それ自体として魅力的なのは確かだ。&lt;/p&gt;
&lt;h4&gt;試したセットアップ方法&lt;/h4&gt;
&lt;h5&gt;1. Docker 上で Jenkins コンテナを構築&lt;/h5&gt;
&lt;p&gt;まず Jenkins コンテナを Docker で構築する。
Docker Compose を使うとより楽に構築できるので参考に。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker pull jenkins/jenkins:lts

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;まず Jenkins LTS 版のコンテナを取得する。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;vim docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;yml ファイルをこのコマンドで作成 / 開く。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;version:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;2.5.0&amp;quot;&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# compose のバージョンを入力すること&lt;/span&gt;

&lt;span class=&quot;hljs-attr&quot;&gt;services:&lt;/span&gt;

  &lt;span class=&quot;hljs-attr&quot;&gt;jenkins:&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;container_name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;jenkins&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;jenkins/jenkins:lts&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Jenkins LTS 版を使う&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;restart:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;always&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# 自動再起動オプション&lt;/span&gt;

    &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;8181:8080&amp;quot;&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# host の 8181 ポートを Jenkins の 8080 ポートに接続&lt;/span&gt;

    &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# host の volume をこのオプションで共有可能&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/home/opendocs/jenkins:/var/jenkins_home&lt;/span&gt;
      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;

    &lt;span class=&quot;hljs-attr&quot;&gt;user:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;root&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;privileged:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Docker In Docker のための重要オプション&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;yml ファイルに例示コードのように必要な内容を記述する。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker-compose -f {ファイル名} up
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このコマンドで docker-compose.yml をベースにしたセットアップを進められる。ファイル名を変えずに docker-compose.yml そのままなら -f オプションは不要。詳細は Docker Compose Docs を参照すること。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.docker.com/compose/&quot;&gt;Docker Compose Documents&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;+ sudo を使わずに docker を扱う方法 → Docker グループに現在のユーザーを追加する&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# このコマンドで現ユーザーを Docker グループに追加できる&lt;/span&gt;
&lt;span class=&quot;hljs-built_in&quot;&gt;sudo&lt;/span&gt; usermod -aG docker &lt;span class=&quot;hljs-variable&quot;&gt;$USER&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;2. Jenkins Container のセットアップ&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;設定した IP アドレスの Docker から割り当てた Port Number でブラウザにアクセス&lt;/li&gt;
&lt;li&gt;Jenkins インストールログに記載されたキーを画面に入力する&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# このコマンドでコンテナのログを確認できる&lt;/span&gt;
docker logs jenkins
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;推奨プラグインのインストール&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;問題が起きうるが、ひとまずインストールを完了してから対処すれば良い。
完了せずにいると、未インストールのプラグインに起因する依存性エラーが続く…&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://wingsh.tistory.com/261&quot;&gt;プラグインインストールの Time Out 対処法&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;GitHub API Plugin のインストール&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Webhook トリガーで動かすためのプラグイン。インストールしたあと、Secret として Git ID/PW を登録しておくこと。&lt;/p&gt;
&lt;h5&gt;3. GitHub の設定&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Settings の Developer Settings 内で Token を作る。本記事執筆時点では Classic トークンを使い、repo と admin:repo_hook 程度の権限設定で十分。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;自動デプロイ対象 Repo の設定で Webhooks に Webhook を追加する。http://{jenkins_url}/github-webhook/ 程度に設定すればよい。最後の / を外すと問題が起きうるのでおとなしく付けておくこと。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h5&gt;4. Jenkins プロジェクトのセットアップ&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;プロジェクトを追加する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ビルド設定 - ソースコード管理で Git を選び、登録済みの Secret を選べば webhook 信号を受け取れる。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GitHub hook trigger for GITScm polling オプションを選ばないとトリガーが動作しない。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;必要に応じてブランチ選定も行い、セットアップを締めくくってテストする。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>[BOJ 4803, Java] 木</title><link>https://www.traceoflight.dev/ja/blog/boj4803/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj4803/</guid><description>BOJ 4803、「木」の問題のJavaによる解答</description><pubDate>Tue, 28 Feb 2023 00:26:49 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;[BOJ 4803](&lt;a href=&quot;https://www.acmicpc.net/problem/4803&quot;&gt;https://www.acmicpc.net/problem/4803&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;データ構造(data_structures)、深さ優先探索(dfs)、分離集合(disjoint_set)、グラフ理論(graphs)、グラフ探索(graph_traversal)、木(trees)&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;木の性質を利用して、木の数をカウントする問題だった。この問題では、連結要素で構成されたものの中からサイクルを除外することで解決できる。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;すべてのノードについて訪問確認&lt;/li&gt;
&lt;li&gt;未訪問の点について、木に組み込みながら深さ優先探索&lt;/li&gt;
&lt;li&gt;サイクルを形成している場合、構成しているすべての点を訪問済みとして処理&lt;/li&gt;
&lt;li&gt;サイクルを形成していない場合、その集合は木であるため1をカウント&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;上記のようなロジックで実装し、深さ優先探索を行いながらカウント処理をどうするか悩んだ結果、以下のコードを作成した。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;dfs&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; nowNode, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; parent, &lt;span class=&quot;hljs-type&quot;&gt;boolean&lt;/span&gt;[] visitLog, HashMap&amp;lt;Integer, ArrayList&amp;lt;Integer&amp;gt;&amp;gt; graph)&lt;/span&gt; {

        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; nextNode : graph.get(nowNode)) {

            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (nextNode != parent &amp;amp;&amp;amp; !visitLog[nextNode]) {

                visitLog[nextNode] = &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;;

                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; dfs(nextNode, nowNode, visitLog, graph);
                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (result == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) {
                    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
                }

            } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (nextNode != parent &amp;amp;&amp;amp; visitLog[nextNode]) {
                &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
            }

        }

        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;

    }

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最初の点から再帰的に訪問処理を行いながら探索し、サイクルが見つかった場合は基本的にすべての点を巡回した後、0を返す構造で作成した。&lt;/p&gt;
&lt;p&gt;もしサイクルが現れなかった場合は、正常に巡回を終えて1を返すため、その関数の戻り値をカウントし続けることで、木の数を把握できる！&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.io.*;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.util.*;

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Main&lt;/span&gt; {

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;dfs&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; nowNode, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; parent, &lt;span class=&quot;hljs-type&quot;&gt;boolean&lt;/span&gt;[] visitLog, HashMap&amp;lt;Integer, ArrayList&amp;lt;Integer&amp;gt;&amp;gt; graph)&lt;/span&gt; {

        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; nextNode : graph.get(nowNode)) {

            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (nextNode != parent &amp;amp;&amp;amp; !visitLog[nextNode]) {

                visitLog[nextNode] = &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;;

                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; dfs(nextNode, nowNode, visitLog, graph);
                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (result == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) {
                    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
                }

            } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (nextNode != parent &amp;amp;&amp;amp; visitLog[nextNode]) {
                &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
            }

        }

        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;

    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String[] args)&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt; IOException {

        &lt;span class=&quot;hljs-type&quot;&gt;BufferedReader&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedReader&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;InputStreamReader&lt;/span&gt;(System.in));
        &lt;span class=&quot;hljs-type&quot;&gt;BufferedWriter&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedWriter&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;OutputStreamWriter&lt;/span&gt;(System.out));

        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;testCase&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;

        ArrayList&amp;lt;String&amp;gt; outputArr = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;ArrayList&lt;/span&gt;&amp;lt;&amp;gt;();

        &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;) {

            &lt;span class=&quot;hljs-type&quot;&gt;StringTokenizer&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;treeInfo&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;StringTokenizer&lt;/span&gt;(input.readLine(), &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;[ ]&amp;quot;&lt;/span&gt;);
            &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nodeNumber&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(treeInfo.nextToken());
            &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;edgeNumber&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(treeInfo.nextToken());

            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (nodeNumber == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &amp;amp;&amp;amp; edgeNumber == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) {
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }

            testCase += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;

            &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;treeCount&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
            &lt;span class=&quot;hljs-type&quot;&gt;boolean&lt;/span&gt;[] isVisited = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;boolean&lt;/span&gt;[nodeNumber + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;];

            &lt;span class=&quot;hljs-type&quot;&gt;StringBuilder&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;stringBuilder&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;StringBuilder&lt;/span&gt;();
            stringBuilder.append(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;Case &amp;quot;&lt;/span&gt;);
            stringBuilder.append(testCase);
            stringBuilder.append(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;: &amp;quot;&lt;/span&gt;);

            HashMap&amp;lt;Integer, ArrayList&amp;lt;Integer&amp;gt;&amp;gt; treeGraph = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;HashMap&lt;/span&gt;&amp;lt;&amp;gt;();
            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i &amp;lt; nodeNumber + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i++) {
                treeGraph.put(i, &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;ArrayList&lt;/span&gt;&amp;lt;&amp;gt;());
            }

            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; edgeNumber; i++) {

                &lt;span class=&quot;hljs-type&quot;&gt;StringTokenizer&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;edgeInfo&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;StringTokenizer&lt;/span&gt;(input.readLine(), &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;[ ]&amp;quot;&lt;/span&gt;);
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;startNode&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(edgeInfo.nextToken());
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;endNode&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(edgeInfo.nextToken());

                treeGraph.get(startNode).add(endNode);
                treeGraph.get(endNode).add(startNode);

            }

            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i &amp;lt; nodeNumber + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i++) {

                isVisited[i] = &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;;
                treeCount += dfs(i, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, isVisited, treeGraph);
            }

            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (treeCount == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) {
                stringBuilder.append(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;No trees.&amp;quot;&lt;/span&gt;);
            } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (treeCount == &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) {
                stringBuilder.append(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;There is one tree.&amp;quot;&lt;/span&gt;);
            } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (treeCount &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) {
                stringBuilder.append(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;A forest of &amp;quot;&lt;/span&gt;);
                stringBuilder.append(treeCount);
                stringBuilder.append(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot; trees.&amp;quot;&lt;/span&gt;);
            }

            outputArr.add(stringBuilder.toString());

        }

        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; testCase; i++) {

            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (i != testCase - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) {
                output.write(outputArr.get(i) + &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;\n&amp;quot;&lt;/span&gt;);
            } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {
                output.write(outputArr.get(i));
            }

        }

        output.flush();
        output.close();

    }

}

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[BOJ 1485, Python] 正方形</title><link>https://www.traceoflight.dev/ja/blog/boj1485/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj1485/</guid><description>BOJ 1485、「正方形」問題のPythonによる解法</description><pubDate>Sat, 25 Feb 2023 03:05:13 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1485&quot;&gt;BOJ 1485&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;幾何学(geometry)、ソート(sorting)&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;この手順に従って正方形の判定を行えばよい。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;4つの点を結ぶ6本の辺の長さをすべて確認&lt;/li&gt;
&lt;li&gt;ソート&lt;/li&gt;
&lt;li&gt;先頭4つの長さが同じか確認&lt;/li&gt;
&lt;li&gt;後方2つが正方形の対角線の長さとして適切か確認&lt;/li&gt;
&lt;li&gt;すべてを満たす場合のみ、正方形を描画可能として処理&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 정사각형&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sys
&lt;span class=&quot;hljs-keyword&quot;&gt;from&lt;/span&gt; math &lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sqrt, isclose
&lt;span class=&quot;hljs-keyword&quot;&gt;from&lt;/span&gt; itertools &lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; combinations

&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt; = sys.stdin.readline

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;distance&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;coord_1: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, coord_2: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;:
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; sqrt(&lt;span class=&quot;hljs-built_in&quot;&gt;pow&lt;/span&gt;(coord_1[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;] - coord_2[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;], &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) + &lt;span class=&quot;hljs-built_in&quot;&gt;pow&lt;/span&gt;(coord_1[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] - coord_2[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;], &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;))

testcase = &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;())

output = []

&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(testcase):

    is_square = &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;

    coord_info = []

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;):
        coord_info.append(&lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split())))

    edge_info = []

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; edge_distance &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; combinations(coord_info, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;):
        edge_info.append(distance(edge_distance[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;], edge_distance[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]))

    edge_info.sort()

    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;):
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; isclose(edge_info[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;], edge_info[idx]):
            is_square = &lt;span class=&quot;hljs-literal&quot;&gt;False&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; is_square:
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;):
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; isclose(&lt;span class=&quot;hljs-built_in&quot;&gt;pow&lt;/span&gt;(edge_info[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;], &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;) * &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;pow&lt;/span&gt;(edge_info[idx], &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;)):
                is_square = &lt;span class=&quot;hljs-literal&quot;&gt;False&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; is_square:
        output.append(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
        output.append(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;)

&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; result &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; output:
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(result)
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[BOJ 12850, Java] 本台の散歩 2</title><link>https://www.traceoflight.dev/ja/blog/boj12850/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj12850/</guid><description>BOJ 12850、「本隊の散歩 2」の問題のJavaによる解答</description><pubDate>Wed, 22 Feb 2023 14:05:40 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/12850&quot;&gt;BOJ 12850&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;分割統治法を用いた累乗（exponentiation_by_squaring）、グラフ理論（graphs）、数学（math）&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;h4&gt;分割統治法 (Divide and Conquer)&lt;/h4&gt;
&lt;p&gt;そのままでは解決が難しい問題を、小さな問題に分割して解決するアルゴリズム&lt;/p&gt;
&lt;p&gt;この問題の場合、隣接行列を描き、その隣接行列のn乗演算を行った結果の行列の値が目的地に到達する回数が答えであることを知っていれば、難なく解決できる。&lt;/p&gt;
&lt;p&gt;分割統治法と行列演算に関する学習が前提となるが、低難易度の問題をいくつか組み合わせたレベルであり、納得のいく難易度だったと思う。&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.io.*;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.util.*;

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Main&lt;/span&gt; {

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; HashMap&amp;lt;Integer, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][]&amp;gt; matrixRecord = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;HashMap&lt;/span&gt;&amp;lt;&amp;gt;();

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] matrixCalculation(&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] matrix1, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] matrix2) {
        &lt;span class=&quot;hljs-comment&quot;&gt;/* 행렬 연산 함수 */&lt;/span&gt;

        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] resultArr = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;][&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;];

        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;; i++) {
            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; j &amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;; j++) {

                &lt;span class=&quot;hljs-type&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;

                &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; k &amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;; k++) {
                    sum += ((&lt;span class=&quot;hljs-type&quot;&gt;long&lt;/span&gt;) matrix1[i][k] * (&lt;span class=&quot;hljs-type&quot;&gt;long&lt;/span&gt;) matrix2[k][j]) % &lt;span class=&quot;hljs-number&quot;&gt;1000000007&lt;/span&gt;;
                }

                resultArr[i][j] = (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;) (sum % &lt;span class=&quot;hljs-number&quot;&gt;1000000007&lt;/span&gt;);

            }
        }

        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; resultArr;
    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] matrixDivision(HashMap&amp;lt;Integer, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][]&amp;gt; matrixInfo, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; calculationCount) {
        &lt;span class=&quot;hljs-comment&quot;&gt;/* 분할 정복을 통한 행렬 연산 함수 */&lt;/span&gt;

        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;halfCount&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; calculationCount / &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;;

        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] halfMatrix;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] otherHalfMatrix;

        &lt;span class=&quot;hljs-comment&quot;&gt;// 기존 값이 존재할 경우 불러오기&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (matrixInfo.containsKey(halfCount)) {
            halfMatrix = matrixInfo.get(halfCount);
        } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {
            halfMatrix = matrixDivision(matrixInfo, halfCount);
        }

        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (matrixInfo.containsKey(calculationCount - halfCount)) {
            otherHalfMatrix = matrixInfo.get(calculationCount - halfCount);
        } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {
            otherHalfMatrix = matrixDivision(matrixInfo, calculationCount - halfCount);
        }

        &lt;span class=&quot;hljs-comment&quot;&gt;// 연산 후 행렬 반환&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] calculationResult = matrixCalculation(halfMatrix, otherHalfMatrix);
        matrixInfo.putIfAbsent(calculationCount, calculationResult);

        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; calculationResult;
    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String[] args)&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt; IOException {

        &lt;span class=&quot;hljs-type&quot;&gt;BufferedReader&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedReader&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;InputStreamReader&lt;/span&gt;(System.in));
        &lt;span class=&quot;hljs-type&quot;&gt;BufferedWriter&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedWriter&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;OutputStreamWriter&lt;/span&gt;(System.out));

        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;walkTime&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(input.readLine());

        &lt;span class=&quot;hljs-comment&quot;&gt;// 기본 행렬 및 본대 인접 행렬 선언&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] baseMatrix = {
                {&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;},
        };

        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] graph = {
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;},
                {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
        };

        &lt;span class=&quot;hljs-comment&quot;&gt;// 해시맵에 초기값들 등록&lt;/span&gt;
        matrixRecord.put(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, baseMatrix);
        matrixRecord.put(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, graph);

        &lt;span class=&quot;hljs-comment&quot;&gt;// 함수를 통해 분할정복 연산 실행&lt;/span&gt;
        matrixDivision(matrixRecord, walkTime);

        &lt;span class=&quot;hljs-comment&quot;&gt;// 결과 출력&lt;/span&gt;
        output.write(Integer.toString(matrixRecord.get(walkTime)[&lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;][&lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;]));

        output.flush();
        output.close();

    }

}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>リファクタリング 1 - 1. 型「...」は型「...」に代入できません</title><link>https://www.traceoflight.dev/ja/blog/refactoring-1-1/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/refactoring-1-1/</guid><description>「型 &apos;string&apos; は型 &apos;&quot;text&quot; | &quot;outlined&quot; | &quot;contained&quot; | undefined&apos; に代入できません」というエラーの解決手順</description><pubDate>Tue, 21 Feb 2023 16:40:07 GMT</pubDate><content:encoded>&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-title class_&quot;&gt;Button&lt;/span&gt;
onClick={handleLogin}
variant=&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;contained&amp;quot;&lt;/span&gt;
  &amp;gt;
    &lt;span class=&quot;hljs-variable constant_&quot;&gt;LOGIN&lt;/span&gt;
&amp;lt;/&lt;span class=&quot;hljs-title class_&quot;&gt;Button&lt;/span&gt;&amp;gt;
&lt;span class=&quot;language-xml&quot;&gt;&lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-name&quot;&gt;Button&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;onClick&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;{handleGoogleLogin}&lt;/span&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-name&quot;&gt;img&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;src&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;{logoSrc}&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;alt&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;alternative image&amp;quot;&lt;/span&gt;
/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-name&quot;&gt;p&lt;/span&gt;&amp;gt;&lt;/span&gt;Social Login&lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;/&lt;span class=&quot;hljs-name&quot;&gt;p&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;/&lt;span class=&quot;hljs-name&quot;&gt;Button&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;問題の発生&lt;/h3&gt;
&lt;p&gt;このようなコードをTypeScriptでmapを使用して再構築する過程でエラーが発生した。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;gt; Type &apos;string&apos; is not assignable to type &apos;&amp;quot;text&amp;quot; | &amp;quot;outlined&amp;quot; | &amp;quot;contained&amp;quot; | undefined&apos;.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;上記のようなエラーで、MUIを使用しており、MUI Buttonのvariantプロパティの値でエラーが発生していた。これを解決するためにかなり悩んだ末、StackOverflowやChatGPTを徹底的に調べた結果、ようやく解決策を見つけることができた。&lt;/p&gt;
&lt;h3&gt;解決方法&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Variant&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;text&amp;quot;&lt;/span&gt; | &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;outlined&amp;quot;&lt;/span&gt; | &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;contained&amp;quot;&lt;/span&gt; | &lt;span class=&quot;hljs-literal&quot;&gt;undefined&lt;/span&gt;;

&lt;span class=&quot;hljs-keyword&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;SubmitButtonProps&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;ButtonProps&lt;/span&gt; {
  &lt;span class=&quot;hljs-attr&quot;&gt;variant&lt;/span&gt;?: &lt;span class=&quot;hljs-title class_&quot;&gt;Variant&lt;/span&gt;;
  &lt;span class=&quot;hljs-attr&quot;&gt;onClick&lt;/span&gt;?: &lt;span class=&quot;hljs-function&quot;&gt;() =&amp;gt;&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Promise&lt;/span&gt;&amp;lt;&lt;span class=&quot;hljs-built_in&quot;&gt;void&lt;/span&gt;&amp;gt;;
  &lt;span class=&quot;hljs-attr&quot;&gt;contains&lt;/span&gt;?: &lt;span class=&quot;hljs-title class_&quot;&gt;React&lt;/span&gt;.&lt;span class=&quot;hljs-property&quot;&gt;ReactNode&lt;/span&gt;;
}

{loginButtonSettings.&lt;span class=&quot;hljs-title function_&quot;&gt;map&lt;/span&gt;(
  &lt;span class=&quot;hljs-function&quot;&gt;(&lt;span class=&quot;hljs-params&quot;&gt;{ onClick, contains, variant }: &lt;span class=&quot;hljs-title class_&quot;&gt;SubmitButtonProps&lt;/span&gt;, &lt;span class=&quot;hljs-attr&quot;&gt;index&lt;/span&gt;: &lt;span class=&quot;hljs-built_in&quot;&gt;number&lt;/span&gt;&lt;/span&gt;) =&amp;gt;&lt;/span&gt; (
    &lt;span class=&quot;language-xml&quot;&gt;&lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-name&quot;&gt;SubmitButton&lt;/span&gt;
    &lt;span class=&quot;hljs-attr&quot;&gt;key&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;{index}&lt;/span&gt;
  	&lt;span class=&quot;hljs-attr&quot;&gt;onClick&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;{onClick}&lt;/span&gt;
	&lt;span class=&quot;hljs-attr&quot;&gt;contains&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;{contains}&lt;/span&gt;
	&lt;span class=&quot;hljs-attr&quot;&gt;variant&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;{variant}&lt;/span&gt;
	/&amp;gt;&lt;/span&gt;&lt;/span&gt;
  )
)}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上記のような形式で、typeという値を通じてvariantに入る属性値をあらかじめ定義し、interfaceにも記述する必要がある。実はこの部分よりも、以下に書く内容の方が重要だ。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; loginButtonSettings = [
  {
    &lt;span class=&quot;hljs-attr&quot;&gt;onClick&lt;/span&gt;: loginHandler,
    &lt;span class=&quot;hljs-attr&quot;&gt;contains&lt;/span&gt;: &lt;span class=&quot;language-xml&quot;&gt;&lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;&lt;span class=&quot;hljs-name&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;Login&lt;span class=&quot;hljs-tag&quot;&gt;&amp;lt;/&lt;span class=&quot;hljs-name&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;,
    &lt;span class=&quot;hljs-attr&quot;&gt;variant&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;contained&amp;quot;&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Variant&lt;/span&gt;, &lt;span class=&quot;hljs-comment&quot;&gt;// 바로 여기!&lt;/span&gt;
  },
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ここに書かれているように、「contained」は一般的にstringとして認識されるため、Variantという属性値に含まれていたまさにその値であることを認識させる必要がある！&lt;/p&gt;
</content:encoded></item><item><title>リファクタリングに入る</title><link>https://www.traceoflight.dev/ja/blog/refactoring/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/refactoring/</guid><description>Refactoringに入る前に回顧とStackを使う理由</description><pubDate>Tue, 21 Feb 2023 16:26:20 GMT</pubDate><content:encoded>&lt;h3&gt;記録の理由&lt;/h3&gt;
&lt;p&gt;約7週間の短ければ短くて長ければ長いプロジェクトを経験してReactとある程度仲良くなる時間はあったと思います。でも、思ったと違って私はこの友達を綺麗に育てたいのですが、いつの間にか乱雑になるのが勝手に生えたひげを見てるような感じです...。&lt;/p&gt;
&lt;p&gt;それでこのコードを修正してみよう！と思うようになり、簡単に今までのプロジェクトの記録を残しながらこの機会にTypeScriptも使ってみる機会を持とうと思います。&lt;/p&gt;
&lt;h3&gt;なぜReactを使うのか？&lt;/h3&gt;
&lt;p&gt;以前参加したプロジェクトではVueJSも使ってみる機会があってVueをベースにコードを作った経験があったのですが、何か長所と短所を持って比較できる熟練者ではなかったし、Reactを使ったこともなかったので、とりあえず今一番ホットなフレームワークだから使ってみよう！という考えを持って使うことになりました。どうやらVueと比較した時、Vueの短所を体感するよりReactの長所を体感するきっかけになったようです。&lt;/p&gt;
&lt;h4&gt;エコシステムが広い&lt;/h4&gt;
&lt;p&gt;これは数値的にもそうですし、よく知られているメリットだと思いますが、Vueで使ってたほとんどのライブラリはReactでも使えるし、こちらがメインでVueはおまけみたいな感じで提供されてる感じがしました。&lt;/p&gt;
&lt;h4&gt;直感的です。&lt;/h4&gt;
&lt;p&gt;まだ様々なHookを使ってないからか、Propsを処理する方法やコード作成方法など、もっと楽だと感じました。&lt;/p&gt;
&lt;p&gt;ueの場合はまるで頭、胸、腹のようにtemplate、script、styleを作成する形でコード間の区別感を生かした感じでしたが、Reactは基本的にFuction ComponentをJavaScriptコードと区別感を与えない形で作成する方なので、変数アクセスなどにおいてもっと便利だと感じました。&lt;/p&gt;
&lt;p&gt;もちろん、Vueのように分離するとコードを読む時もっと楽かも分かりませんが、作成する基準としては明確な違いがあり、今となってもどっちを使うかと聞かれたらReactを使うでしょう。&lt;/p&gt;
&lt;h4&gt;Event処理が便利でした。&lt;/h4&gt;
&lt;p&gt;上の内容とある程度共有する部分がある内容ですが、EventHandlerを作成する時、Vueを使ってた時よりずっと直観的に書くことができたと思います。Vueの場合はFunctionとVariableを別々に分けて書く部分が多かったようですが、Reactは一般的なプログラミング言語を使うようにその場で変数宣言して処理する形が可能なので、毎日食べてた白飯のような安心感がありました。&lt;/p&gt;
&lt;h3&gt;TypeScriptを使う理由&lt;/h3&gt;
&lt;p&gt;実際の業界で選ぶ長所と短所とは違うかもしれませんが、個人的にはReactの上記のような長所を挙げることができ、Refactoringの過程でもReactを選んだ理由になりました。&lt;/p&gt;
&lt;p&gt;同じようにRefactoringをする時、なぜJSの代わりにTSを使うのかの理由も書いておいた方がいいと思うのでここに書いておきます。&lt;/p&gt;
&lt;h4&gt;エラーキャッチャー&lt;/h4&gt;
&lt;p&gt;TSの長所でJSの短所を解決する部分がすごく大きいと思います。基本的にJSは非常に緩い言語だと思うし、実際そうです。 そのため、エラーが変なところで発生し、解決も難解な時がたまにあるのですが、このような部分をTSがうまく解決してくれると期待しています。&lt;/p&gt;
&lt;h4&gt;慣れてる&lt;/h4&gt;
&lt;p&gt;JSはどうしようもない開発履歴によって個人的にプログラミング言語らしくない部分がすごく多いと思います。しかし、TSは明らかにJSベースであるにもかかわらず、とてもしっくりくる構造を提供することで、JSで残念だった部分を解決してくれました！もちろん、手はもっとたくさん必要ですが、むしろ安定した構造の慣れから来る快適さがTSを使うように誘導しています。&lt;/p&gt;
&lt;h3&gt;おわりに&lt;/h3&gt;
&lt;p&gt;今後、今まで使っていたコードと比較しながら、あるいは学んだ内容を、この投稿の下にどんどん残していく予定です。どれくらい時間がかかるかは分かりませんが、とてもやりがいのある作業になることを期待しています！&lt;/p&gt;
</content:encoded></item><item><title>[BOJ 1922, Java] ネットワーク接続</title><link>https://www.traceoflight.dev/ja/blog/boj1922/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj1922/</guid><description>BOJ 1922、「ネットワーク接続」問題のJavaによる解答</description><pubDate>Mon, 20 Feb 2023 07:55:51 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1922&quot;&gt;BOJ 1922&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;分類&lt;/h3&gt;
&lt;p&gt;グラフ理論、最小スパンニングツリー&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;h4&gt;はじめに&lt;/h4&gt;
&lt;p&gt;最近は問題を解くことばかりに追われて、理論をおろそかにしている気がするため、理論を簡単でも整理しつつ、問題の解法を記録しておこうと思う。&lt;/p&gt;
&lt;h4&gt;MST（minimum spanning tree、最小スパニングツリー）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;スパニングツリーとは？&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;グラフ内のすべての頂点を含む木を意味する。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;最小スパンニングツリー&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;スパンニングツリーの中で、辺の総長が最も短いもの&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;主な特徴&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;n個の頂点を通る(n - 1)本の辺を持つ
長さを最小限に抑えるため、社内ネットワークの構築などに活用可能&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;プリムアルゴリズム&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;初期の頂点を1つ選択&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MSTに含まれる頂点に接続された辺のうち、最も短いものを順次選択&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;すべての頂点が接続された場合、終了&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;クルスカルのアルゴリズム&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;すべての辺を重み順に並べ替える&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;サイクルを形成しない範囲で、辺を順次追加&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;すべての頂点が接続された場合、終了&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;実装コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.io.*;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.util.*;

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Main&lt;/span&gt; {

    &lt;span class=&quot;hljs-comment&quot;&gt;// 간선 정보 클래스 선언&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Connection&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Comparable&lt;/span&gt;&amp;lt;Connection&amp;gt; {

        &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; cost;
        &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; start;
        &lt;span class=&quot;hljs-keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; end;

        &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;Connection&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; cost, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; start, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; end)&lt;/span&gt; {
            &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.cost = cost;
            &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.start = start;
            &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.end = end;
        }

        &lt;span class=&quot;hljs-comment&quot;&gt;// 가중치를 통한 비교&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;compareTo&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(Connection other)&lt;/span&gt; {
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.cost - other.cost;
        }

    }

    &lt;span class=&quot;hljs-comment&quot;&gt;// 정점의 집합을 확인하는 함수&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;checkUnion&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[] unionInfo, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; targetVertex)&lt;/span&gt; {

        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (unionInfo[targetVertex] != targetVertex) {
            unionInfo[targetVertex] = checkUnion(unionInfo, unionInfo[targetVertex]);
        }

        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; unionInfo[targetVertex];
    }

    &lt;span class=&quot;hljs-comment&quot;&gt;// 정점 2개가 집합을 이루는지 확인하는 함수&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;isUnion&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[] unionInfo, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; vertex1, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; vertex2)&lt;/span&gt; {
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; checkUnion(unionInfo, vertex1) == checkUnion(unionInfo, vertex2);
    }

    &lt;span class=&quot;hljs-comment&quot;&gt;// 집합을 합쳐주는 함수&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;makeUnion&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[] unionInfo, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; vertex1, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; vertex2)&lt;/span&gt; {

        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;group1&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; checkUnion(unionInfo, vertex1);
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;group2&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; checkUnion(unionInfo, vertex2);

        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (group2 &amp;gt; group1) {
            unionInfo[group2] = group1;
        } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {
            unionInfo[group1] = group2;
        }

    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String[] args)&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt; IOException {

        &lt;span class=&quot;hljs-type&quot;&gt;BufferedReader&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedReader&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;InputStreamReader&lt;/span&gt;(System.in));
        &lt;span class=&quot;hljs-type&quot;&gt;BufferedWriter&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedWriter&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;OutputStreamWriter&lt;/span&gt;(System.out));

        &lt;span class=&quot;hljs-comment&quot;&gt;// 정점 및 간선의 갯수 입력&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;vertexNumber&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(input.readLine());
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;edgeNumber&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(input.readLine());

        &lt;span class=&quot;hljs-comment&quot;&gt;// 간선 정보를 담을 우선순위 큐 선언&lt;/span&gt;
        PriorityQueue&amp;lt;Connection&amp;gt; costPriorityQueue = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;PriorityQueue&lt;/span&gt;&amp;lt;&amp;gt;();

        &lt;span class=&quot;hljs-comment&quot;&gt;// 간선 정보 입력&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; edgeNumber; i++) {
            &lt;span class=&quot;hljs-type&quot;&gt;StringTokenizer&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;connectionInfo&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;StringTokenizer&lt;/span&gt;(input.readLine(), &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;[ ]&amp;quot;&lt;/span&gt;);

            &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;startNode&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(connectionInfo.nextToken());
            &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;endNode&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(connectionInfo.nextToken());
            &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;cost&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(connectionInfo.nextToken());

            &lt;span class=&quot;hljs-type&quot;&gt;Connection&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;connection&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Connection&lt;/span&gt;(cost, startNode, endNode);
            costPriorityQueue.add(connection);

        }

        &lt;span class=&quot;hljs-comment&quot;&gt;// 집합에 포함된 정점의 갯수와 최소 가중치 정보를 담을 변수 선언&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;totalCost&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;totalEdge&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;

        &lt;span class=&quot;hljs-comment&quot;&gt;// 집합 정보를 담을 배열 선언&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[] groupInfo = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[vertexNumber + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;];
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; vertexNumber + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i++) {
            groupInfo[i] = i;
        }

        &lt;span class=&quot;hljs-comment&quot;&gt;// Kruskal&amp;#x27;s Algorithm&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; (totalEdge &amp;lt; vertexNumber - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt; &amp;amp;&amp;amp; !costPriorityQueue.isEmpty()) {

            &lt;span class=&quot;hljs-comment&quot;&gt;// 가중치 순으로 확인&lt;/span&gt;
            &lt;span class=&quot;hljs-type&quot;&gt;Connection&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nowConnection&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; costPriorityQueue.poll();

            &lt;span class=&quot;hljs-comment&quot;&gt;// 집합 관계를 확인하여 아직 집합이 아닌 경우 집합에 추가하고 가중치 가산&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (!isUnion(groupInfo, nowConnection.start, nowConnection.end)) {
                makeUnion(groupInfo, nowConnection.start, nowConnection.end);
                totalEdge += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;
                totalCost += nowConnection.cost;
            }

        }

        &lt;span class=&quot;hljs-comment&quot;&gt;// 최종 최소 가중치값 출력&lt;/span&gt;
        output.write(Integer.toString(totalCost));

        output.flush();
        output.close();

    }

}

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[BOJ 14503, Java] ロボット掃除機</title><link>https://www.traceoflight.dev/ja/blog/boj14503/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj14503/</guid><description>BOJ 14503、「ロボット掃除機」問題のJavaによる解答</description><pubDate>Sat, 18 Feb 2023 12:31:09 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/14503&quot;&gt;BOJ 14503&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;実装(implementation)、シミュレーション(simulation)&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;典型的な実装問題ですが、問題の説明を理解する段階から少し難解な部分があります。その部分についてだけ、簡単に補足しておこうと思います。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;現在のマスを掃除&lt;/li&gt;
&lt;li&gt;現在のマスを基準に&lt;strong&gt;反時計回りに90度回転した方向からチェック&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;一周して最初に見ていた位置まで確認した後、掃除する場所がなければ後退&lt;/li&gt;
&lt;li&gt;後退する場所もなければ掃除終了&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;この問題において、正面基準で左側を先にチェックするという部分を見落として解いてしまうと、実装云々以前に迷い続けるしかない構造になっている。その点に必ず注意して解くようにしよう！&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.io.*;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.util.*;

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Main&lt;/span&gt; {

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; height;
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; width;

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;isNeedClean&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] table, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; nowYIndex, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; nowXIndex)&lt;/span&gt; {
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; table[nowYIndex][nowXIndex] == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String[] args)&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt; IOException {

        &lt;span class=&quot;hljs-type&quot;&gt;BufferedReader&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedReader&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;InputStreamReader&lt;/span&gt;(System.in));
        &lt;span class=&quot;hljs-type&quot;&gt;BufferedWriter&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedWriter&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;OutputStreamWriter&lt;/span&gt;(System.out));

        &lt;span class=&quot;hljs-type&quot;&gt;StringTokenizer&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;mapSize&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;StringTokenizer&lt;/span&gt;(input.readLine(), &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;[ ]&amp;quot;&lt;/span&gt;);

        &lt;span class=&quot;hljs-comment&quot;&gt;// 뒷 방향 등록 해시맵 선언&lt;/span&gt;
        HashMap&amp;lt;Integer, Integer&amp;gt; backward = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;HashMap&lt;/span&gt;&amp;lt;&amp;gt;();
        backward.put(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;);
        backward.put(&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;);
        backward.put(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;);
        backward.put(&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;);

        height = Integer.parseInt(mapSize.nextToken());
        width = Integer.parseInt(mapSize.nextToken());

        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] mapInfo = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[height][width];

        &lt;span class=&quot;hljs-type&quot;&gt;StringTokenizer&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;startingPoint&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;StringTokenizer&lt;/span&gt;(input.readLine(), &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;[ ]&amp;quot;&lt;/span&gt;);

        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nowY&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(startingPoint.nextToken());
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nowX&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(startingPoint.nextToken());
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nowDirection&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(startingPoint.nextToken());

        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; height; i++) {
            &lt;span class=&quot;hljs-type&quot;&gt;StringTokenizer&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;mapLine&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;StringTokenizer&lt;/span&gt;(input.readLine(), &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;[ ]&amp;quot;&lt;/span&gt;);

            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; j &amp;lt; width; j++) {
                mapInfo[i][j] = Integer.parseInt(mapLine.nextToken());
            }

        }

        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;cleanCounter&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;

        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[] directionY = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;};
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[] directionX = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;};

        Loop:
        &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;) {

            &lt;span class=&quot;hljs-comment&quot;&gt;// 현재 칸이 청소가 필요하다면 청소 실시&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (isNeedClean(mapInfo, nowY, nowX)) {
                mapInfo[nowY][nowX] = &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;;
                cleanCounter += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;
            }

            &lt;span class=&quot;hljs-comment&quot;&gt;// 주변 칸에 대해서 확인&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i &amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;; i++) {

                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;targetDirection&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; (nowDirection + &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt; - i) % &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;;
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;targetY&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowY + directionY[targetDirection];
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;targetX&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowX + directionX[targetDirection];

                &lt;span class=&quot;hljs-comment&quot;&gt;// 청소할 칸이 있는 경우 이동 및 방향 전환&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (isNeedClean(mapInfo, targetY, targetX)) {
                    nowY = targetY;
                    nowX = targetX;
                    nowDirection = targetDirection;
                    &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
                }

                &lt;span class=&quot;hljs-comment&quot;&gt;// 청소할 칸이 없는 경우 뒷칸 확인&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (i == &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;) {
                    targetY = nowY + directionY[backward.get(nowDirection)];
                    targetX = nowX + directionX[backward.get(nowDirection)];

                    &lt;span class=&quot;hljs-comment&quot;&gt;// 뒤로 이동할 수 없는 경우 청소 종료&lt;/span&gt;
                    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (mapInfo[targetY][targetX] == &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) {
                        &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt; Loop;

                        &lt;span class=&quot;hljs-comment&quot;&gt;// 이동할 수 있다면 뒤로 1칸 후진&lt;/span&gt;
                    } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {
                        nowY = targetY;
                        nowX = targetX;
                    }
                }

            }

        }

        &lt;span class=&quot;hljs-comment&quot;&gt;// 이동 결과 출력&lt;/span&gt;
        output.write(Integer.toString(cleanCounter));

        output.flush();
        output.close();

    }

}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>初めての面接体験談</title><link>https://www.traceoflight.dev/ja/blog/first-interview/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/first-interview/</guid><description>簡単な初回面接の感想</description><pubDate>Tue, 07 Feb 2023 11:30:12 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;2023-07-06 サムネイル編集 (&lt;a href=&quot;https://kr.freepik.com/free-vector/interview-concept-illustration_7446777.htm#from_view=detail_alsolike&quot;&gt;作家 storyset&lt;/a&gt; 出典 Freepik)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;はじめに&lt;/h3&gt;
&lt;p&gt;久しぶりに書く記事になった気がする。&lt;/p&gt;
&lt;p&gt;現在 SSAFY 8 期の課程を受けているため、思ったより腰を据えて記事を書く時間がとれなかった。&lt;/p&gt;
&lt;p&gt;ただ、面接のような重要な経験を経たあとにこういったものを整理しておかないと、自分の成長に役立たないと思い、無理にでも記事にしてみる。&lt;/p&gt;
&lt;h3&gt;面接の流れ&lt;/h3&gt;
&lt;p&gt;ビデオ面接で行われ、想定面接時間が長くなかったため、技術面接よりは人物面接寄りだと予想していたが、予想どおり技術面接ではなかった。&lt;/p&gt;
&lt;p&gt;これを「事前に予想して準備していたのは幸いだった」と捉えるべきか、それとも「経験を得る機会を逃して残念」と捉えるべきか悩むレベルだった…&lt;/p&gt;
&lt;p&gt;面接の質問は、覚えているものだけ並べると&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;毎回出てくる自己紹介 1 分&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;専攻ではない現在の分野を選んだ理由は？(筆者は非専攻者)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;空白期間について&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;勤務環境がこういう形だが、思っていたものと違うかもしれない、それでも大丈夫か？&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;少し抽象的に書いたが、思ったよりは準備していた内容で対応できる水準だったので幸いだった。特に非専攻者の場合は、専攻者と比べて CS 知識の不足を念頭に置いて関連質問を狙ってくることが多いため、ある程度の準備は必要だ！&lt;/p&gt;
&lt;h3&gt;個人的な所感&lt;/h3&gt;
&lt;p&gt;ただ、技術面接ではなかったため技術関連の質問があまり交わされなかった点は、次のコーディングテスト通過がいつになるか分からないだけにより一層惜しかった気がする。&lt;/p&gt;
&lt;p&gt;そしていつも念頭に置くべきことだが、会社が面接者を見定める一方で、面接者も会社の値踏みができる時間でもある、と聞いたことがあるが、今回の面接でその点を骨身に沁みて感じた気がする。&lt;/p&gt;
&lt;p&gt;今回面接を受けた会社は、自分が考えていた職務とはあまりに違う仕事をすることになりそうだったため、合格しても多くの悩みを抱えることになりそうだ…！&lt;/p&gt;
</content:encoded></item><item><title>[BOJ 16934, Java] ゲームのニックネーム</title><link>https://www.traceoflight.dev/ja/blog/boj16934/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj16934/</guid><description>BOJ 16934、「ゲームのニックネーム」問題のJavaによる解答</description><pubDate>Wed, 28 Dec 2022 00:35:18 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/16934&quot;&gt;BOJ 16934&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;データ構造(data_structures)、ハッシュを用いた集合とマップ(hash_set)、文字列(string)、木(trees)、トライ(trie)&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;個人的には文字列の問題が苦手で、もう少し勉強しなければならないと思っているが、今回の問題はトライアルゴリズムを使って解くことができた。&lt;/p&gt;
&lt;p&gt;例題が多かったので反例チェックは難しくはなかったが、もしこの問題が例題まで明確でなかったら、もっと頭を悩ませることになっただろう…&lt;/p&gt;
&lt;p&gt;Javaで木構造を実装したことがなかったため、多少時間はかかったが、誰の助けも借りずに実装できたことに意義を見出そう！&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.io.*;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.util.*;

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Main&lt;/span&gt; {

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Node&lt;/span&gt; {

        &lt;span class=&quot;hljs-type&quot;&gt;char&lt;/span&gt; nowChar;
        String value;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
        &lt;span class=&quot;hljs-type&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;isUnique&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;;
        HashSet&amp;lt;Node&amp;gt; childSet;

        &lt;span class=&quot;hljs-comment&quot;&gt;// 헤드에 사용하기 위한 정의 방식&lt;/span&gt;
        Node() {

            &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.childSet = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;HashSet&lt;/span&gt;&amp;lt;&amp;gt;();
            &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.value = &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
            &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.isUnique = &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;;

        }

        &lt;span class=&quot;hljs-comment&quot;&gt;// 일반적인 서브노드들을 위한 정의 방식&lt;/span&gt;
        Node(&lt;span class=&quot;hljs-type&quot;&gt;char&lt;/span&gt; target) {

            &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.nowChar = target;
            &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.childSet = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;HashSet&lt;/span&gt;&amp;lt;&amp;gt;();
            &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.value = &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;;

        }

    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Trie&lt;/span&gt; {

        &lt;span class=&quot;hljs-comment&quot;&gt;// 헤드 노드 1개를 보유하고 시작&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Node&lt;/span&gt;();

        &lt;span class=&quot;hljs-comment&quot;&gt;/**
         * 문자열 1개를 트라이 클래스에 추가하는 메서드
         */&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;addString&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String target)&lt;/span&gt; {

            &lt;span class=&quot;hljs-type&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nowNode&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.head;
            &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;targetLength&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; target.length();

            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt;= targetLength; i++) {

                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (i == targetLength) {

                    nowNode.count += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;
                    nowNode.value = target;

                } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {

                    &lt;span class=&quot;hljs-type&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;hasChild&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;;

                    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (Node subNode : nowNode.childSet) {

                        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (subNode.nowChar == target.charAt(i)) {

                            nowNode = subNode;
                            hasChild = &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;;
                            &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;

                        }

                    }

                    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (!hasChild) {

                        &lt;span class=&quot;hljs-type&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;madeNode&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Node&lt;/span&gt;(target.charAt(i));
                        nowNode.childSet.add(madeNode);
                        nowNode = madeNode;

                    }

                }

            }

        }

        &lt;span class=&quot;hljs-comment&quot;&gt;/**
         * 문자열의 고유 별칭을 찾아내는 메서드
         */&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; String &lt;span class=&quot;hljs-title function_&quot;&gt;findUnique&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String target)&lt;/span&gt; {

            &lt;span class=&quot;hljs-type&quot;&gt;Node&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nowNode&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;this&lt;/span&gt;.head;
            &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;targetLength&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; target.length();
            &lt;span class=&quot;hljs-type&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;isFirstTime&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;;
            &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;
            &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;resultCount&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;

            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; targetLength + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i++) {

                &lt;span class=&quot;hljs-comment&quot;&gt;// 첫 번째로 만나는 고유값이 해당 문자열의 별칭&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (nowNode.isUnique &amp;amp;&amp;amp; isFirstTime) {

                    nowNode.isUnique = &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;;
                    isFirstTime = &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;;
                    result = i;
                    resultCount = nowNode.count;

                    &lt;span class=&quot;hljs-comment&quot;&gt;// 이후로도 만나는 고유값은 고유값이 아니도록 처리&lt;/span&gt;
                } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {

                    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (nowNode.isUnique) {
                        nowNode.isUnique = &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;;
                    }

                }

                &lt;span class=&quot;hljs-comment&quot;&gt;// 마지막 문자까지 확인&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (i == targetLength) {

                    &lt;span class=&quot;hljs-comment&quot;&gt;// 마지막 문자까지 고유값을 체크하지 못한 경우&lt;/span&gt;
                    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (result == -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) {
                        result = targetLength;
                        resultCount = nowNode.count;
                    }

                    &lt;span class=&quot;hljs-comment&quot;&gt;// 카운팅 갯수에 따른 값을 반환&lt;/span&gt;
                    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (nowNode.count == &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) {
                        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; target.substring(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, result);

                    } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {
                        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; target + resultCount;
                    }

                    &lt;span class=&quot;hljs-comment&quot;&gt;// 마지막 문자 이전까지는 트라이 내 탐색 방식으로 진행&lt;/span&gt;
                } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {

                    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (Node subNode : nowNode.childSet) {

                        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (subNode.nowChar == target.charAt(i)) {
                            nowNode = subNode;
                            &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;

                        }

                    }

                }

            }

            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;ERROR!&amp;quot;&lt;/span&gt;;

        }

    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String[] args)&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt; IOException {

        &lt;span class=&quot;hljs-type&quot;&gt;BufferedReader&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedReader&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;InputStreamReader&lt;/span&gt;(System.in));
        &lt;span class=&quot;hljs-type&quot;&gt;BufferedWriter&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedWriter&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;OutputStreamWriter&lt;/span&gt;(System.out));

        &lt;span class=&quot;hljs-comment&quot;&gt;// Trie Algorithm&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;// 트라이 인스턴스 선언&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;Trie&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nickNameTrie&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Trie&lt;/span&gt;();

        &lt;span class=&quot;hljs-comment&quot;&gt;// 유저 수 입력&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;userNumber&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(input.readLine());

        &lt;span class=&quot;hljs-comment&quot;&gt;// 모든 유저에 대해 진행&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; userNumber; i++) {

            &lt;span class=&quot;hljs-comment&quot;&gt;// 닉네임 입력 및 트라이에 추가&lt;/span&gt;
            &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nickName&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; input.readLine();
            nickNameTrie.addString(nickName);

            &lt;span class=&quot;hljs-comment&quot;&gt;// 함수를 호출하여 해당 닉네임에 대한 별칭 출력&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (i == userNumber - &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) {
                output.write(nickNameTrie.findUnique(nickName));

            } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {
                output.write(nickNameTrie.findUnique(nickName) + &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;\n&amp;quot;&lt;/span&gt;);
            }

        }

        output.flush();
        output.close();

    }

}

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[BOJ 17114, Java] ハイパートマト</title><link>https://www.traceoflight.dev/ja/blog/boj17114/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj17114/</guid><description>BOJ 17114、「ハイパー・トマト」問題のJavaによる解答</description><pubDate>Thu, 22 Dec 2022 04:36:35 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;[BOJ 17114] (&amp;lt;&lt;a href=&quot;https://www.acmicpc.net/problem/17114&amp;amp;gt;&quot;&gt;https://www.acmicpc.net/problem/17114&amp;amp;gt;&lt;/a&gt;)&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;実装(implementation)、グラフ理論(graphs)、グラフ探索(graph_traversal)、幅優先探索(bfs)&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;個人的には、BFSがどこまで複雑になり得るかをよく示している問題だと思う。&lt;/p&gt;
&lt;p&gt;問題の存在は以前から知っていたし、解法自体もすでに有名で広く知られているが、自分が解く方法を実装することとはまた別の問題であることを改めて学んだ。&lt;/p&gt;
&lt;p&gt;高速な入出力は基本であり、幅優先探索を行う際に余計な処理を省かないとタイムリミットオーバーになる可能性がある問題。&lt;/p&gt;
&lt;p&gt;Pythonでsys.stdin.readlineを使って解決できるかは分からないが、Javaでは幸いにもBufferedReaderで処理が可能だった。&lt;/p&gt;
&lt;p&gt;この問題を解いた後に調べてみると、スマートな解法が別途あるようだが、ここでは古典的なBFSを力業で拡張することで解決した。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;11次元配列に座標情報を入力&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;未熟なトマトはカウントし、熟したトマトは座標を記録&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;熟したトマトを順巡し、隣接する未熟なトマトを熟したトマトのリストに追加しながらカウント値を減少させ、条件に応じてこの過程を繰り返す&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;カウントが0になったらすべて熟したことになるため、かかった日数を出力&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;カウントが0にならなかったが、既存の未熟なトマトに対して(3)の処理を繰り返しても数が変化しなかった場合、これ以上熟すことは不可能であるため、-1を出力する。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;この問題を解く際、2番と3番の処理において別の方法、&lt;strong&gt;つまりカウントを毎回更新する方式や、一度使用した熟したトマトの座標を削除しない場合、タイムリミットオーバーになる可能性があるが…&lt;/strong&gt; ここでかなり迷いながら解決した。&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;p&gt;コードがかなり長いが…11重のforループを使用し、隣接する座標を表現している点から、やむを得ない部分だと考えている。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.io.*;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.util.*;

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Main&lt;/span&gt; {

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; tomatoLeft;

    &lt;span class=&quot;hljs-comment&quot;&gt;/**
     * 토마토가 익는 메커니즘을 반영하여 1일 뒤의 배열로 변경하는 함수
     */&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;ripeTomato&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][][][][][][][][][][] target, Queue&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[]&amp;gt; tomatoQueue, &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[] sizeInfo)&lt;/span&gt; {

        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][] movements = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[][]{
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;},
                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;},
        };

        ArrayList&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[]&amp;gt; ripeList = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;ArrayList&lt;/span&gt;&amp;lt;&amp;gt;();

        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[] nowIdx : tomatoQueue) {

            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[] movement : movements) {

                &lt;span class=&quot;hljs-type&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;isNotOverIndex&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;;

                &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt;; i++) {
                    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &amp;gt; nowIdx[i] + movement[i] || nowIdx[i] + movement[i] &amp;gt;= sizeInfo[i]) {
                        isNotOverIndex = &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;;
                        &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
                    }
                }

                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nextIdx00&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowIdx[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;] + movement[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;];
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nextIdx01&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowIdx[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;] + movement[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;];
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nextIdx02&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowIdx[&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;] + movement[&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;];
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nextIdx03&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowIdx[&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;] + movement[&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;];
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nextIdx04&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowIdx[&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;] + movement[&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;];
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nextIdx05&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowIdx[&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;] + movement[&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;];
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nextIdx06&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowIdx[&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;] + movement[&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;];
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nextIdx07&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowIdx[&lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;] + movement[&lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;];
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nextIdx08&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowIdx[&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;] + movement[&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;];
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nextIdx09&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowIdx[&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;] + movement[&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;];
                &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nextIdx10&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; nowIdx[&lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;] + movement[&lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;];

                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (

                        isNotOverIndex

                                &amp;amp;&amp;amp; target[nextIdx00][nextIdx01][nextIdx02]
                                [nextIdx03][nextIdx04][nextIdx05][nextIdx06]
                                [nextIdx07][nextIdx08][nextIdx09][nextIdx10]
                                == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

                ) {

                    ripeList.add(

                            &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{
                                    nextIdx00, nextIdx01, nextIdx02,
                                    nextIdx03, nextIdx04, nextIdx05, nextIdx06,
                                    nextIdx07, nextIdx08, nextIdx09, nextIdx10
                            }

                    );

                }

            }

        }

        tomatoQueue.clear();

        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[] ripeCoord : ripeList) {

            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (

                    target[ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;]]
                            [ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;]]
                            [ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;]] == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

            ) {

                target[ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;]]
                        [ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;]]
                        [ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;]][ripeCoord[&lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;]] = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;

                tomatoLeft -= &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;

                tomatoQueue.add(ripeCoord);

            }

        }

    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String[] args)&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt; IOException {

        &lt;span class=&quot;hljs-type&quot;&gt;BufferedReader&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedReader&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;InputStreamReader&lt;/span&gt;(System.in));
        &lt;span class=&quot;hljs-type&quot;&gt;BufferedWriter&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedWriter&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;OutputStreamWriter&lt;/span&gt;(System.out));

        &lt;span class=&quot;hljs-comment&quot;&gt;// 배열 사이즈 입력&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[] storageSize = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[&lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt;];
        &lt;span class=&quot;hljs-type&quot;&gt;StringTokenizer&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;sizeInput&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;StringTokenizer&lt;/span&gt;(input.readLine(), &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;[ ]&amp;quot;&lt;/span&gt;);

        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; &lt;span class=&quot;hljs-number&quot;&gt;11&lt;/span&gt;; i++) {
            storageSize[i] = Integer.parseInt(sizeInput.nextToken());
        }

        &lt;span class=&quot;hljs-comment&quot;&gt;// 창고 정보 입력&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[][][][][][][][][][][] tomatoStorage = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[storageSize[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;]][storageSize[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]][storageSize[&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;]]
                [storageSize[&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;]][storageSize[&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;]][storageSize[&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;]][storageSize[&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;]]
                [storageSize[&lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;]][storageSize[&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;]][storageSize[&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;]][storageSize[&lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;]];

        Queue&amp;lt;&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt;[]&amp;gt; ripeTomatoQueue = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;LinkedList&lt;/span&gt;&amp;lt;&amp;gt;();

        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;idx10&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; idx10 &amp;lt; storageSize[&lt;span class=&quot;hljs-number&quot;&gt;10&lt;/span&gt;]; idx10++) {
            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;idx09&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; idx09 &amp;lt; storageSize[&lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;]; idx09++) {
                &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;idx08&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; idx08 &amp;lt; storageSize[&lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;]; idx08++) {
                    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;idx07&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; idx07 &amp;lt; storageSize[&lt;span class=&quot;hljs-number&quot;&gt;7&lt;/span&gt;]; idx07++) {
                        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;idx06&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; idx06 &amp;lt; storageSize[&lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;]; idx06++) {
                            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;idx05&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; idx05 &amp;lt; storageSize[&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;]; idx05++) {
                                &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;idx04&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; idx04 &amp;lt; storageSize[&lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;]; idx04++) {
                                    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;idx03&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; idx03 &amp;lt; storageSize[&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;]; idx03++) {
                                        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;idx02&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; idx02 &amp;lt; storageSize[&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;]; idx02++) {
                                            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;idx01&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; idx01 &amp;lt; storageSize[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]; idx01++) {

                                                &lt;span class=&quot;hljs-type&quot;&gt;StringTokenizer&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;storageInfo&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;StringTokenizer&lt;/span&gt;(input.readLine(), &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;[ ]&amp;quot;&lt;/span&gt;);

                                                &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;idx00Counter&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; idx00Counter &amp;lt; storageSize[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;]; idx00Counter++) {

                                                    &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;nowInput&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; Integer.parseInt(storageInfo.nextToken());

                                                    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (nowInput == &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;) {

                                                        ripeTomatoQueue.add(
                                                                &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;int&lt;/span&gt;[]{
                                                                        idx00Counter, idx01, idx02,
                                                                        idx03, idx04, idx05, idx06,
                                                                        idx07, idx08, idx09, idx10
                                                                }
                                                        );

                                                    } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (nowInput == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) {

                                                        tomatoLeft += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;

                                                    }

                                                    tomatoStorage[idx00Counter][idx01][idx02]
                                                            [idx03][idx04][idx05][idx06]
                                                            [idx07][idx08][idx09][idx10]
                                                            = nowInput;

                                                }

                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        &lt;span class=&quot;hljs-comment&quot;&gt;// 지난 날짜 카운팅 변수 및 모두 익지 못하는 상황을 체크하기 위한 Flag 선언&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;dayCounter&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;
        &lt;span class=&quot;hljs-type&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;cantComplete&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;false&lt;/span&gt;;

        &lt;span class=&quot;hljs-comment&quot;&gt;// 모두 익지 않았다면 반복&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; (tomatoLeft &amp;gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) {

            &lt;span class=&quot;hljs-comment&quot;&gt;// 함수를 호출하여 기존 배열 깊은 복사 후 1일 뒤의 배열 확인&lt;/span&gt;
            &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;lastTomato&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; tomatoLeft;
            ripeTomato(tomatoStorage, ripeTomatoQueue, storageSize);

            &lt;span class=&quot;hljs-comment&quot;&gt;// 날짜 1 카운트&lt;/span&gt;
            dayCounter += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;

            &lt;span class=&quot;hljs-comment&quot;&gt;// 아직 다 익지 않았지만 기존이랑 차이가 없다면 전부 익을 수 없는 상황이므로 Flag 변경 후 break&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (tomatoLeft != &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &amp;amp;&amp;amp; tomatoLeft == lastTomato) {
                cantComplete = &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;;
                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;;
            }

        }

        &lt;span class=&quot;hljs-comment&quot;&gt;// 문제 조건에 따라서 출력&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (cantComplete) {
            output.write(&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;-1&amp;quot;&lt;/span&gt;);
        } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {
            output.write(Integer.toString(dayCounter));
        }

        output.flush();
        output.close();

    }

}

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[BOJ 3865, Java] 学会会員</title><link>https://www.traceoflight.dev/ja/blog/boj3865/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj3865/</guid><description>BOJ 3865、「学会員」問題のJavaによる解答</description><pubDate>Mon, 12 Dec 2022 13:50:33 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/3865&quot;&gt;BOJ 3865&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;幅優先探索(bfs)、データ構造(data_structures)、深さ優先探索(dfs)、グラフ理論(graphs)、グラフ探索(graph_traversal)、ハッシュを用いた集合とマップ(hash_set)、パーシング(parsing)、文字列(string)&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;最近直面したコーディングテストでは、文字列に関する問題がよく出題される傾向にあるようで、どうしても文字列に関連する問題を探していたところ見つけた問題。&lt;/p&gt;
&lt;p&gt;深さ優先探索を使う問題だったので、やはり馴染みがあり、まだJava言語への習熟度が不足しているため、解法には少し時間がかかったが、大枠は深さ優先探索の範囲から外れることはなかった。&lt;/p&gt;
&lt;p&gt;文字列データをうまく加工し、学会と学生名について訪問記録の集合を常にチェックしながら、まだ訪問していない場合は各ケースに対して再帰＋カウント処理で仕上げることができる問題だった。&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.io.*;
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; java.util.*;

&lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;Main&lt;/span&gt; {

    &lt;span class=&quot;hljs-comment&quot;&gt;/**
     * 해당 학회의 총 인원수를 반환하는 함수
     */&lt;/span&gt;

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;getTotalPerson&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String target)&lt;/span&gt; {

        &lt;span class=&quot;hljs-comment&quot;&gt;// 결과값 변수 선언&lt;/span&gt;
        &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;;

        &lt;span class=&quot;hljs-comment&quot;&gt;// 아직 방문하지 않은 경우에 대해서만 처리&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (!visitLog.contains(target)) {

            &lt;span class=&quot;hljs-comment&quot;&gt;// 방문 기록&lt;/span&gt;
            visitLog.add(target);

            &lt;span class=&quot;hljs-comment&quot;&gt;// 사람이 아닌 학회일 경우&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (clubGraph.containsKey(target)) {

                &lt;span class=&quot;hljs-comment&quot;&gt;// 해당 학회의 방문하지 않은 구성원에 대해 재귀함수를 호출, 결과값에 합산&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (String eachPerson : clubGraph.get(target)) {

                    &lt;span class=&quot;hljs-comment&quot;&gt;// 구성원이 학회라면 재귀함수 호출&lt;/span&gt;
                    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (clubGraph.containsKey(eachPerson)) {
                        result += getTotalPerson(eachPerson);

                    &lt;span class=&quot;hljs-comment&quot;&gt;// 학생이라면 아직 방문하지 않았을 경우 결과값 1 추가&lt;/span&gt;
                    } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {

                        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (!visitLog.contains(eachPerson)) {

                            visitLog.add(eachPerson);
                            result += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;;

                        }

                    }

                }

            }

        }

        &lt;span class=&quot;hljs-comment&quot;&gt;// 결과값을 반환&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; result;

    }

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;strToInt&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String inputString)&lt;/span&gt; {
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; Integer.parseInt(inputString);
    }

    &lt;span class=&quot;hljs-comment&quot;&gt;// 학회 수, 첫 학회, 학회 관계 그래프, 학생 기록 집합 정적 변수 선언&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; clubNumber;
    &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; String firstClub;
    &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; HashMap&amp;lt;String, ArrayList&amp;lt;String&amp;gt;&amp;gt; clubGraph = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;HashMap&lt;/span&gt;&amp;lt;&amp;gt;();
    &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; Set&amp;lt;String&amp;gt; visitLog = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;HashSet&lt;/span&gt;&amp;lt;&amp;gt;();

    &lt;span class=&quot;hljs-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;(String[] args)&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;throws&lt;/span&gt; IOException {

        &lt;span class=&quot;hljs-type&quot;&gt;BufferedReader&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;BufferedReader&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;InputStreamReader&lt;/span&gt;(System.in));

        &lt;span class=&quot;hljs-comment&quot;&gt;// 학회의 수 입력, 입력값이 0이라면 반복 종료&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; ((clubNumber = strToInt(input.readLine())) != &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) {

            clubGraph.clear();
            visitLog.clear();

            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-type&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;; i &amp;lt; clubNumber; i++) {

                &lt;span class=&quot;hljs-comment&quot;&gt;// 줄 단위 입력&lt;/span&gt;
                &lt;span class=&quot;hljs-type&quot;&gt;StringTokenizer&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;clubInfo&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;StringTokenizer&lt;/span&gt;(input.readLine(),&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;[:,.]&amp;quot;&lt;/span&gt;);

                &lt;span class=&quot;hljs-comment&quot;&gt;// 학회 이름 변수 선언&lt;/span&gt;
                &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;clubName&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; clubInfo.nextToken();

                &lt;span class=&quot;hljs-comment&quot;&gt;// 첫 학회라면 따로 변수에 기록&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (i == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) {
                    firstClub = clubName;
                }

                &lt;span class=&quot;hljs-comment&quot;&gt;// 기존에 없던 학회라면 추가&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (!clubGraph.containsKey(clubName)) {
                    clubGraph.put(clubName, &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-title class_&quot;&gt;ArrayList&lt;/span&gt;&amp;lt;&amp;gt;());
                }

                &lt;span class=&quot;hljs-comment&quot;&gt;// 나머지를 전부 학회의 원소로 추가&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; (clubInfo.hasMoreTokens()) {
                    clubGraph.get(clubName).add(clubInfo.nextToken());
                }

            }

            &lt;span class=&quot;hljs-comment&quot;&gt;// 함수를 호출하여 결과값을 출력 스택에 추가&lt;/span&gt;
            System.out.println(getTotalPerson(firstClub));

        }

    }

}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>SQLD合格体験記と資料</title><link>https://www.traceoflight.dev/ja/blog/sqld/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/sqld/</guid><description>SQLD合格体験記</description><pubDate>Tue, 29 Nov 2022 15:32:31 GMT</pubDate><content:encoded>&lt;p&gt;&lt;span class=&quot;md-media-frame media-load-frame&quot; data-media-shell&gt;&lt;img src=&quot;/media/image/imported-0d43c36638e8bf56-image.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; data-md-fallback data-media-load&gt;&lt;span class=&quot;md-media-fallback md-image-fallback&quot; hidden&gt;이미지를 불러올 수 없습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;第47回SQL開発者資格試験に合格した。進路を完全に転換してから初めて取得した資格なので、とてもやりがいを感じている。&lt;/p&gt;
&lt;p&gt;当初は1ヶ月ほど時間をかけようと思っていたが、他の用事に追われたり、理論的にばかりアプローチしすぎたりして……かなり時間を無駄にしてしまった気がして、残念な点もある。 勉強しながら確認した点をここに記しておく。&lt;/p&gt;
&lt;p&gt;最後のパートには個人的に整理した概念が記載されているが、その後で実戦的な部分や、自分が覚えやすいように編集した点が所々に残っており、整合しない部分などが存在するかもしれない！それでも、もし誰かが勉強する際に役立つかもしれないので、全体の内容を残しておき、後で思い出したら編集する予定だ。&lt;/p&gt;
&lt;h1&gt;所要時間および勉強方法&lt;/h1&gt;
&lt;p&gt;実質的に費やした時間は約2週間、問題演習には約1週間を費やした。&lt;/p&gt;
&lt;p&gt;最初は[Data on Air](&lt;a href=&quot;https://dataonair.or.kr/&quot;&gt;https://dataonair.or.kr/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)が提供する概念解説を通じて、王道に近い方向で勉強を進めたかったが、SQLD自体が概念的な部分よりも実戦的なSQL構文の形で出題される問題の方がはるかに多いことを知り、序盤で断念することになった。しかし、依然として内容自体は良いと思うので、時間があれば一度確認することをお勧めする！&lt;/p&gt;
&lt;p&gt;次に、YouTubeにある様々な形式の講義を通じて、大まかな概要を把握した。SQLDに限っては、かなり多くの整理された講義が存在するため、良さそうなものを選んで視聴するだけで十分だろう。&lt;/p&gt;
&lt;p&gt;最後に問題演習だが、問題に関しては関連するカフェやブログに過去問を復元した資料が存在する。いわゆる「ノランイ」と呼ばれる本も良いが、過去問の解説も疎かにしないことが重要だ！ノランイの場合は第2章まで1回通読し、誤答ノートを整理するにとどめ、残りの時間はすべて過去問の演習に費やした。&lt;/p&gt;
&lt;p&gt;個人的に推奨する過去問復元サイトは、[このブログ](&lt;a href=&quot;https://yunamom.tistory.com/category/%EC%9E%90%EA%B2%A9%EC%A6%9D/SQLD%20%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C&quot;&gt;https://yunamom.tistory.com/category/자격증/SQLD 기출문제&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)をお勧めしたい。解答を入力するだけで、即座にその問題の正誤を確認できるからだ。&lt;/p&gt;
&lt;h1&gt;概念の整理&lt;/h1&gt;
&lt;p&gt;参考事項：第1章は第2章に比べて問題の比重が低いため後回しにされ、それに伴い必要な内容のみを記載しているため、内容が不十分である可能性がある&lt;/p&gt;
&lt;h2&gt;第1章&lt;/h2&gt;
&lt;h2&gt;エンティティの分類&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;基本／キーエンティティ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;中心エンティティ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;行為エンティティ&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;データモデリング&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;情報システム構築のための、データ視点による業務分析手法&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;現実世界のデータを、定められた表記法によって表現&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;データベースを構築するための分析／設計のプロセス&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;データモデリングを行う際の留意点&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;重複&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;柔軟性の欠如&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;不整合&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;データモデリングの種類&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;概念的：抽象化レベルが高く、業務中心に包括的に進める&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;論理的：キー、属性、関係などを正確に表現し、再利用性が高くなるよう設計する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;物理的：実際のデータベースに移植できるようにし、物理的な特性を考慮する&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;データベーススキーマの構造&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;外部&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;概念&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;内部&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;ERDの作成手順&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;エンティティを描く。&lt;/li&gt;
&lt;li&gt;エンティティを適切に配置する。&lt;/li&gt;
&lt;li&gt;エンティティ間の関係を設定する。&lt;/li&gt;
&lt;li&gt;関係名を記述する。&lt;/li&gt;
&lt;li&gt;関係参加度を記述する。&lt;/li&gt;
&lt;li&gt;関係の必須・非必須を記述する。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;エンティティの特徴&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;当該業務において必要であり、管理すべき情報&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一意の識別子でなければならない。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2つ以上のインスタンスを持つ。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;実際に使用されなければならない。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;属性を持たなければならない。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;少なくとも1つ以上の関係を形成しなければならない。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;1개 엔터티: 2개 이상의 인스턴스 집합 + 2개 이상의 속성
1개 속성: 1개 이상의 속성값
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;属性の特性による分類&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;基本属性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設計属性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;派生属性&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;ドメイン&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;各属性が持つことができる値の範囲&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;エンティティ内の属性に対するデータ型、サイズ、制約の指定&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;属性の命名&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;当該業務で使用される名称でなければならない。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;記述的な属性名は使用しない。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;略語の使用は控える。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;データモデル全体で一意性を確保しなければならない。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ERDでは実体関係と行為関係を区別しない。
しかし、クラス図では区別し、関連関係、依存関係を記述しなければならない。&lt;/p&gt;
&lt;h2&gt;関係の表記法&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;関係名：関係の名前&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;関係次数：1：1、1：M、M：N&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;関係選択仕様：必須、選択&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;関係の読み方&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;基準エンティティを「1つ（One）」または「各（Each）」と読む。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;対象エンティティの関係参加度を読み取る。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;関係の選択仕様と関係名を読み取る。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;識別子の種類&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;代表性：主識別子 vs 副識別子&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;自己生成の有無：内部 vs 外部&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;単一属性識別：単一 vs 複合&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;意味の有無：本質的 vs 人工的&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;主識別子の特徴&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;一意性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;希少性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;不変性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;存在性&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;パフォーマンスデータモデリング&lt;/h2&gt;
&lt;p&gt;データベースのパフォーマンス向上を目的として、パフォーマンス関連事項をデータモデリングに反映&lt;/p&gt;
&lt;h2&gt;第1正規化の対象&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;重複属性の分離&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;行単位の重複&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;カラム単位の重複&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;半正規化&lt;/h2&gt;
&lt;p&gt;正規化されたエンティティ、属性、関係の重複、統合、分離を通じて
システムのパフォーマンスを向上させ、開発および運用の簡素化を図る
整合性が損なわれる可能性があるにもかかわらず、パフォーマンスの低下が予想される場合に実施する。&lt;/p&gt;
&lt;h3&gt;手順&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;半正規化の対象の調査&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;範囲処理の頻度&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;大量の範囲処理&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;統計的処理&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;テーブル結合（JOIN）の数&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;他の方法で対応可能な場合は、その方法への誘導を検討&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;結合（JOIN）が多い場合は、ビュー（view）やテーブルを使用&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;大量のデータ処理時にはクラスタリング&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;大量のデータを保有する場合は、パーティショニングによるデータ分割&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;インデックスのメンテナンス&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;アプリケーションのロジック変更&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;スーパー／サブタイプ データモデル変換技術&lt;/h2&gt;
&lt;p&gt;個別に発生するトランザクション → 個別テーブル
スーパー＋サブタイプ → スーパー＋サブテーブル
全体 → 単一のテーブル&lt;/p&gt;
&lt;h2&gt;PKの順序を決定する基準&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;インデックスを効率的に利用できるよう指定&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;先頭にある属性の値が比較対象となること&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;可能な限り「=」、「BETWEEN」、「&amp;lt;&amp;gt;」&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;分散データベースの長所および短所&lt;/h2&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;長所&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;局所性、システムの容量を段階的に拡張可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;信頼性と可用性／有用性と柔軟性&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;高速な応答速度、通信コストの削減、地域ユーザーのニーズへの対応力向上&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;データの可用性と信頼性の向上、システム規模の調整&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;短所&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;開発コストおよびエラー発生の可能性の増加、処理コストの増加、データの完全性を脅かす&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;設計プロセスの困難さ、管理の複雑さとコスト、不安定な応答速度、制御の難しさ&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;第2章&lt;/h2&gt;
&lt;h2&gt;SQL文の種類&lt;/h2&gt;
&lt;h3&gt;DCL&lt;/h3&gt;
&lt;p&gt;Data Control Language、権限を管理するコマンド&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;GRANT&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;権限を付与する役割&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;``GRANT {permission} ON {table} TO {user};`&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;の形式で使用&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```text
WITH GRANT, WITH ADMIN의 비교

GRANT: 특정 사용자에게 권한 부여가 가능한 권한을 부여, 부여한 부모의 권한이 회수될 때 자식의 권한도 회수
ADMIN: 테이블에 대한 모든 권한을 부여, 부여한 부모의 권한 회수와 관계 없는 권한
```
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;`&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;REVOKE&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;権限を取り消す役割&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;``REVOKE {permission} ON {table} FROM {user};`&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;` の形式で使用&lt;/p&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;権限の種類&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;ALL&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;-- 모든 권한 부여&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;INSERT&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;UPDATE&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;DELETE&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;/*  */&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;REFERENCES&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;ALTER&lt;/span&gt; INDEX &lt;span class=&quot;hljs-comment&quot;&gt;/*  */&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;/* ROLE: 다양한 권한을 하나의 그룹으로 묶어서 관리 */&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;CREATE&lt;/span&gt; ROLE {role_name}; &lt;span class=&quot;hljs-comment&quot;&gt;-- 권한 그룹 생성&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;GRANT&lt;/span&gt; {permission_type} &lt;span class=&quot;hljs-keyword&quot;&gt;TO&lt;/span&gt; {role_name}; &lt;span class=&quot;hljs-comment&quot;&gt;-- 해당 그룹에 권한 등록&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;GRANT&lt;/span&gt; {role_name} &lt;span class=&quot;hljs-keyword&quot;&gt;TO&lt;/span&gt; {user_1}, {user_2}...; &lt;span class=&quot;hljs-comment&quot;&gt;-- 다른 유저들에게 권한 그룹 부여&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;DDL&lt;/h3&gt;
&lt;p&gt;Data Definition Language、データを定義するコマンド&lt;/p&gt;
&lt;p&gt;SQL Server では Auto Commit をサポート&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;CREATE&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;テーブル構造の作成&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;「&lt;code&gt;CREATE TABLE {table_name} {table_elements};&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;」の形式で使用&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```sql
CREATE TABLE EXAMPLE (
/* 
  컬럼명은 영어, 한글, 숫자 전부 가능 
  첫 글자를 문자로 지정해야 하며, 컬럼의 데이터 타입은 반드시 설정해야 한다.
*/
		NAME  varchar2(max_length)  -- 최대 길이를 가진 가변길이 문자열
  	ID번호 char(length)          -- 고정된 길이 문자열
		나이_2 number(max_length)    -- 숫자형 데이터 타입
  	생일   date                  -- 날짜형 데이터 타입
);
```
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;##### CONSTRAINT (制約)

* default: デフォルト値の指定

* not null: NULL値の入力不可

* primary key: 主キーの指定 (not null, unique, 複数可)

* foreign key: 外部キーの指定 (複数可)
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;ALTER&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;テーブルおよびカラムに対して、名前や属性の変更、追加、削除などの構造修正を行う&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;「&lt;code&gt;ALTER TABLE {table_name} {detail_order} {detail_property(if need)} TO {change_target};&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;」の形式で使用&lt;/p&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#### 詳細なコマンド

* RENAME: テーブル、カラムの名前を変更

* MODIFY: カラムの属性を変更

* ADD: カラムを追加

* DROP: カラムを削除

* ADD CONSTRAINT / DROP CONSTRAINT: 制約を追加、削除
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;RENAME&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ALTERを使用せずに、テーブルやカラムの名前を変更できる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;複数のテーブル名を同時に変更可能&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;DROP&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ALTERを使用せずに、テーブルやカラムを削除できる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#### TABLE {table_name} CASCADE CONSTRAINT

* Oracleにのみ存在するオプションで、SQL Serverには存在しない

* 外部キー制約において、参照テーブルを先に削除し、その後、対象テーブルを削除する。

* 対象テーブルのデータおよび外部キー参照制約もすべて削除する
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;TRUNCATE&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;テーブルの初期化 （削除ではない！）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;内部データのみが削除され、テーブルの存在およびカラムは残る。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#### DROP vs TRUNCATE vs DELETE

* DROP: テーブルを丸ごと削除した後、メモリを解放

* TRUNCATE: テーブル、カラムの存在は残り、残りのデータに対するメモリを解放

* DELETE: レコードを削除。データに対するログが残るため、反映されるまではロールバックが可能。メモリは解放されない
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;DML&lt;/h3&gt;
&lt;p&gt;Data Manipulation Language（データ操作言語）。レコードを操作するコマンド&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;INSERT&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;データをレコードに入力&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;``INSERT INTO {table_name} {column_name} VALUES {change_column_name};`&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;` の形式で使用する&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;カラム名を指定しなくても入力可能だが、指定しない場合はすべての値を入力する必要がある。&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;UPDATE&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;既存のデータを修正&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;``UPDATE {table_name} SET {column_name} = {column_value} WHERE {condition};`&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;` の形式で使用する&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;DELETE&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;既存のデータを削除&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;``DELETE FROM {table_name} WHERE {condition};`&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;` の形式で使用する&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FROM&lt;/code&gt; は省略可能&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;SELECT&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;特定のデータを照会&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;``SELECT {select_target} FROM {select_origin} WHERE {condition};`&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;` の形式で使用する&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;``GROUP BY {calc_type} HAVING {condition} / ORDER BY {sort_condition}`&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;` の形式で条件を指定することもある&lt;/p&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#### DISTINCT

重複値を除いて照会する条件 (a, b, NULL, a, b, NULL) =&amp;amp;gt; (a, b, NULL)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;COUNT&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;(\*): NULL値を含めて全行数をカウント

({column\_name}): NULLを除いて特定のカラムの行数をカウント
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;TCL&lt;/h3&gt;
&lt;p&gt;Transaction Control Language、トランザクション制御コマンド&lt;/p&gt;
&lt;p&gt;Transaction: DBの状態を変化させる操作&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;* transaction의 특징
고립성: 실행되는 동안 다른 transaction에 영향을 받아 잘못된 결과를 만들면 안됨
일관성: 실행 전 데이터베이스에 잘못된 점이 없다면 transaction 수행 후에도 내용에 오류가 있으면 안됨
지속성: transaction이 갱신한 데이터베이스 내용은 영구적으로 저장
원자성: transaction에서 정의한 연산은 모두 성공적으로 실행되거나 전혀 실행되지 않음 (All or Nothing)
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;COMMIT&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;データへの変更をDBに反映&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;SAVEPOINT&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;コード分割の分岐点となるようsavepointを指定&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;``SAVEPOINT {savepoint_name};`&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;` の形式で使用&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;ROLLBACK&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;以前の状態に戻すコマンド&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SAVEPOINTまたは直前のCOMMITまでロールバックが可能&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;code&gt;ROLLBACK TO {rollback_point};&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;の形式で使用&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;セーブポイントがない場合は、最新のCOMMIT時点に復元&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;TCLの効果&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;データ整合性の保証&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;永続的なデータ変更前に、変更内容を確認&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;論理的に関連する処理をグループ化して処理可能&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;関数&lt;/h2&gt;
&lt;h3&gt;文字列関数&lt;/h3&gt;
&lt;p&gt;SELECT、WHEREなどの条件を指定する際によく使用される&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;LOWER&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;英字文字列を小文字に変換&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;UPPER&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;英字文字列を大文字に変換&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;CONCAT&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;2つの文字列を結合&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Oracleの&apos;||&apos;、SQL Serverの&apos;+&apos;と同様の役割&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;SUBSTR&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;文字列のM番目の位置からN文字を残して削除&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;LENGTH, LEN&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;空白を含む文字列の長さ&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;TRIM, LTRIM, RTRIM&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;両端の指定された文字をすべて削除。指定された文字がない場合は空白を削除&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;数値型関数&lt;/h3&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;ROUND&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;四捨五入&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;TRUNC&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;切り捨て&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;CEIL&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;それ以上の最小の整数&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;FLOOR&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;以下となる最大の整数&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;MOD&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;剰余演算&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;SIGN&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;正の数は1、0は0、負の数は-1を返す&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;ABS&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;絶対値&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;日付型関数&lt;/h3&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;SYSDATE&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;クエリを実行している現在の日付および時刻を出力&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;EXTRACT&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;``EXTRACT ({information} FROM {data})`&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;` の形式で使用&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;日付型データから必要な値を抽出する方法&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;型変換&lt;/h3&gt;
&lt;p&gt;これらの関数を使用してデータ型を変更できる&lt;/p&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;TO_NUMBER&lt;/h4&gt;
&lt;p&gt;文字列 &amp;gt; 数値&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;TO_CHAR&lt;/h4&gt;
&lt;p&gt;数値、日付 &amp;gt; 文字列（フォーマットによって生成結果が異なる）&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;TO_DATE&lt;/h4&gt;
&lt;p&gt;文字列 &amp;gt; 日付（フォーマットによって生成結果が異なる）&lt;/p&gt;
&lt;h3&gt;基本構造&lt;/h3&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;DECODE&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;IF文&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;条件がシンプルに整理できる場合&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;CASE WHEN&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;長くなったIF文&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;条件の整理に多くの行数が必要な場合&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;ORDER BY&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;取得したテーブルのソート&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;基準を複数使用可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;WHERE&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;IN, NOT IN: リスト内の値のいずれか一つでも一致、または不一致であれば条件を満たす&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;IS NULL, IS NOT NULL: NULLかどうかを判断して T / F を返す&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;BETWEEN a AND b: a と b の間に値が存在するかどうかを確認して T / F を返す（a と b を含む）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;比較演算子：=、&amp;gt;、&amp;lt;、&amp;gt;=、&amp;lt;= など&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A LIKE B：a に対して b と類似した文字列を検索する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;%：1文字以上が存在することを意味する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;_：1文字&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;명시적 형변환 vs 암시적 형변환

명시적 형변환: 함수를 활용하여 데이터 타입을 변경
암시적 형변환: 데이터베이스가 알아서 바꿔주는 것
&amp;gt;&amp;gt; 숫자 타입의 PK는 암묵적으로 인덱스가 되는데 데이터의 조회 등으로 암시적 형변환이 발생한 경우, 인덱스로 사용이 불가능
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;WITH&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;サブクエリを使用して、一時テーブルやビューのように使用可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;別名を指定可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;インラインビューまたは一時テーブルとして扱われる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;``WITH {table_name} AS {table_condition}`&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;` の形式で使用&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;GROUP BY&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;条件に基づいてグループ化を行う命令&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;値の組み合わせが異なれば別のグループ&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;HAVING&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;グループ化後の状態に基づく条件文&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;COUNT（カウント）、SUM（合計）、AVG（平均）、MAX（最大）、MIN（最小）、STDDEV（標準偏差）、VARIAN（分散）など&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DISTINCT（重複除去）、ALL（すべて）などの条件を使用可能&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;NULL関数&lt;/h3&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;NVL、ISNULL&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;NULLの場合、別の値に変更する関数&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;データ型が異なる場合は使用できない&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;NVL2&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;NULLかどうかによって異なる結果を返す関数&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;NULLでない場合は第1引数、NULLの場合は第2引数を返す&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;NULLIF&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;2つの引数が同じ場合はNULLを返し、異なる場合は第1引数を返す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;COALESCE&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;NULLではない最初の値を返す&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;GROUP関数&lt;/h3&gt;
&lt;p&gt;グループ化対象の列値、集計対象の列値はNULLとして出力される&lt;/p&gt;
&lt;p&gt;一般的なグループ関数でも同様の結果を抽出できる&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;ROLLUP&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;部分合計と全体合計を表示する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;関数の引数が与えられた順序によって結果値が異なり、階層構造で集計値を返す。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;CUBE&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;グループ化可能なすべてのケースについて、引数の集合を生成する&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;GROUPING SETS&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;括弧で囲んだ集合ごとの集計が可能&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;GROUPING&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;小計、合計などが計算された場合は1を返し、そうでない場合は0を返す関数&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;JOIN&lt;/h3&gt;
&lt;p&gt;一般的にテーブル間の結合であり、集合に類似している&lt;/p&gt;
&lt;p&gt;テーブルとテーブル、結合結果とテーブル、結合結果同士のJOINが可能&lt;/p&gt;
&lt;p&gt;関連する2つのテーブルに少なくとも1つの共通属性が存在する場合に適用可能&lt;/p&gt;
&lt;p&gt;JOINを明示するANSI標準形式のクエリと、そうでない非標準形式のクエリが存在する。&lt;/p&gt;
&lt;p&gt;JOINが列挙されている場合、一度に2つずつ処理され、すべてを同時に処理することはできない&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;共通部分&lt;/p&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;INNER JOIN&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;非標準形式の表記では、に省略&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;両方のテーブルの共通部分（交差）を結合&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;LEFT JOIN&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;非標準表記を使用する場合、左側に (+) を表記&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;左側のテーブルの全レコードと、右側のテーブルの共通部分のみを結合&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;RIGHT JOIN&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;非標準表記を使用する場合、右側に (+) を表記&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;右側のテーブルの全レコードと、左側のテーブルの共通レコードのみを結合&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;OUTER JOIN&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;両側に「+」を使用できないためOUTER JOINは使用できず、ANSI標準形式のクエリを使用する必要がある。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UNIONとは異なり、共通属性が1つだけ存在しても適用可能。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;和集合&lt;/p&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;UNION (ALL)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;照会対象の列数が同じで、各列の属性が同一の場合に適用できる結合方式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;データ量は Data1 + Data2 となる。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;UNION ALL は重複データを削除せずに結合する&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;差集合&lt;/p&gt;
&lt;p&gt;交集合を除外し、一つの集合のみを確認したい場合に適用可能&lt;/p&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;MINUS(Oracle)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;EXCEPT(SQL Server)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;結合対象間の一致度&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;EQUI JOIN: 同一の列を使用して2つのリレーションを結合&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;non-EQUI JOIN: 正確に一致しない列を使用して2つのリレーションを結合&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;ex) A.key &amp;lt;, &amp;gt;, &amp;lt;=, &amp;gt;= B.key
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;CROSS JOIN&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;キーなしでJOINすると、2つのテーブルに対してデカルト積が発生する&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;5개의 행 * 3개의 행 = 15개의 행으로 조회
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;SELF JOIN&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;1つのテーブル内で関連性を持つ2つのカラム間のJOIN&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;テーブル名およびカラム名がすべて一致するため、ALIASの使用が必須&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;オプティマイザ・ジョイン&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;JOINを実行する過程で、パフォーマンス最適化のための方式を選択し、Hintとして指定する&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;階層型クエリ&lt;/h3&gt;
&lt;p&gt;ツリー形式のデータに対してクエリを実行すること&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;階層構造の開始点はSTART WITHで設定（ROOT NODE）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;子ノードを持たないノード = LEAF NODE&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;階層をLEVELで表記&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h4&gt;CONNECT BY&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;階層構造の接続方向性を確認&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;子 &amp;gt; 親&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;親 &amp;gt; 子&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;##### CONNECT BY PRIOR a = b

* a 列と b 列が同一レコード間で階層化が発生

* b -&amp;amp;gt; a の順に再配置
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;SIBLINGS BY&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;兄弟ノード間の配置順序を決定&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;WINDOW関数&lt;/h3&gt;
&lt;p&gt;レコード間の関係を簡単に定義するための関数。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SELECT WINDOW_FUNCTION {arguments} OVER {partition by column} {order_style} FROM {table};&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;の形式で使用&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;WINDOW_FUNCTION&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ウィンドウ関数&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;グループ内の集計関数：COUNT、SUM、MIN、MAX、AVGなど&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;グループ内の順位関数&lt;/p&gt;
&lt;p&gt;順位関数を作成しても自動的にソートは行われないため、ORDER BY句を活用する必要がある。&lt;/p&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;RANK&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;同一の順位に対しては同一の順位を付与&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;同一の順位を1件としてカウントしない&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;DENSE_RANK&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;同一順位には同一の順位を付与&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;同一順位を1件としてカウント&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;ROW_NUMBER&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;同一順位には一意の順位を付与&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;グループ内の比率関連関数&lt;/p&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;PERCENT_RANK&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;値ではなく「順序」を対象とし、パーティション内での順序ごとの百分率を照会する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;NTILE(n)&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;パーティションごとに総件数をn等分した値を返す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;CUME_DIST&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;パーティション全体において、現在の行の値以下のレコード数に対する累積割合を取得する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;累積分布上で0～1の値をとる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;グループ内の行順序関数&lt;/p&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;FIRST_VALUE&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;パーティション内で最初に現れる値を返す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;LAST_VALUE&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;パーティション内で最後に現れる値を返す&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;LAG(column_name, record_difference)&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;前の行を取得する&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;LEAD(column_name, record_difference, value_if_null)&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;次の行を取得する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DEFAULT = 1&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;ARGUMENTS&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;引数（列名など、関数の処理が行われる対象）&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;PARTITION BY&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;テーブルのレコードを分割する基準&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;ORDER BY&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;分割されたレコード内、またはテーブル全体において、レコードをどのような基準で並べ替えるかを指定&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;WINDOWING&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;関数の演算対象となるレコードの範囲を指定&lt;/p&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;RANGE&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;範囲指定時に使用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;BETWEEN a AND b&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;aからbまでを適用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;UNBOUNDED PRECEDING&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;開始位置 = 最初の行&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;UNBOUNDED FOLLOWING&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;開始位置 = 最後の行&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h5&gt;CURRENT ROW&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;開始位置 = 現在の行&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;テーブルパーティション&lt;/h3&gt;
&lt;p&gt;大容量のテーブルを複数のデータファイルに分割して保存すること&lt;/p&gt;
&lt;p&gt;物理的に分離されたデータファイルに保存 =&amp;gt; パフォーマンスの向上および独立した管理が可能&lt;/p&gt;
&lt;p&gt;検索範囲を狭める効果 =&amp;gt; パフォーマンスの向上&lt;/p&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;RANGE PARTITION&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;値の範囲を基準にパーティションを分割して保存する方法&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;LIST PARTITION&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;特定の値を基準に分割&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;ハッシュパーティション&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;データベース管理システムが独自にハッシュ関数を使用して分割・管理する方式&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;オプティマイザ&lt;/h2&gt;
&lt;p&gt;同じSQL文であっても、その実行方法によってパフォーマンスが異なる（パフォーマンスの指標：所要時間、リソース使用量など）&lt;/p&gt;
&lt;p&gt;したがって、SQL文を分析し、一定の基準に基づいて実行計画を立てる必要があり、この際にオプティマイザを使用する。&lt;/p&gt;
&lt;p&gt;オプティマイザは実行パフォーマンスに影響を与える可能性はあるが、結果値は変わらない。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-test&quot;&gt;SQL문 작성 =&amp;gt; 파싱 (문법 검사, 구문 분석) =&amp;gt; 옵티마이저 (비용 기반 / 규칙 기반) =&amp;gt; 실행 계획 (PLAN_TABLE 저장) =&amp;gt; SQL 실행
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;コストベース&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;最新のOracleでは、コストベースのオプティマイザがデフォルトで使用される&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;システム統計とオブジェクト統計を通じて、当該SQL文の実行にかかる総コストを計算した後、最小コストの実行計画を策定&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;コストベース&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;最新のOracleでは、コストベースのオプティマイザがデフォルトで使用される&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;システム統計とオブジェクト統計を通じて、当該SQL文の実行にかかる総コストを計算し、最小コストの実行計画を策定する&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;ルールベース&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;15種類の優先順位に基づいて実行計画を策定する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一般的に、ROWIDに基づいてスキャンすることが最も優先順位が高い&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;インデックス&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;インデックスキーに基づいてソートされる =&amp;gt; 検索が高速化される&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;PKは自動的にインデックス化される&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;1つのテーブルに複数のインデックスを作成でき、1つのインデックスが複数のカラムで構成されることもある&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;降順で作成およびソートされる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;頻繁に変化する属性をインデックスに設定するのは好ましくない&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;セカンダリインデックスには、UNIQUE属性のインデックスでない限り、重複データの入力が可能である。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;インデックススキャンよりもフルスキャンの方が効率的であり、コスト面でも有利な場合がある&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;パーティションテーブルでは、パーティションに対してパーティションキーインデックスを作成可能であり、これをグローバルインデックスと呼ぶ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;インデックスが増えると当然データ量も増加するため、挿入、削除、更新の速度低下を招く可能性がある&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;すべてのデータ型でインデックスの作成が可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;インデックスの種類として、シーケンシャルインデックス、ビットマップ、結合インデックス、クラスター、ハッシュインデックスが存在する。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#### SCAN方式

*&amp;lt;br /&amp;gt;



  ##### Index Unique SCAN

  * インデックスキーの値が重複しない場合、そのキーを通じて検索を行う

*&amp;lt;br /&amp;gt;



  ##### Index Unique SCAN

  * 特定の範囲を照会するWHERE句を使用して、該当領域をスキャン

  * 範囲によっては、1件または0件の結果が出力されることもある

*&amp;lt;br /&amp;gt;



  ##### Index Full SCAN

  * インデックスの先頭から末尾まで全てをスキャン
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;オプティマイザ結合の種類&lt;/h3&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#### Nested Loop JOIN

* 外部（先行、Driving）テーブルを先に検索して結合対象データを見つけ、内部（後続）テーブルと結合

* 先行テーブルの処理範囲によって処理量が決定されるため、先行テーブルのサイズが小さいものを見つける必要がある

* 行間処理、テーブル間処理のいずれも順次発生

* 最適な順序を見つけることが重要

* ランダムアクセスが発生するため（先行テーブルから2番目のテーブルを参照する際に発生）、パフォーマンスの遅延を低減するために、ランダムアクセスの発生を少なくする必要がある

* 先行テーブルの処理範囲が広かったり、ランダムアクセスの範囲が広かったりする場合は、SORT MERGE JOINよりも不利になるケースがある

* 「インデックス必須」、一意インデックスの場合は有利

* オンライントランザクション処理（OLTP）に有用

* ネストされたループと同じ形式で、先行テーブルの条件を満たすケースの数だけ反復的に実行
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;*&lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#### ソートマージ結合（Sort Merge JOIN）

* 2つのテーブルをそれぞれソートし、完了後にマージ

* ソートが発生するため、データ量が多い場合は処理が遅くなる。

* ソート対象のデータ量が多い場合、一時ディスクを使用するため、パフォーマンスが低下する。

* EQIU JOIN、non-EQIU JOINの両方が可能
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;HASH JOIN&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;* 2つのテーブルのうち小さい方のテーブルをHASHメモリにロードし、2つのテーブルのJOINキーを使用してハッシュテーブルを作成

* 2つのテーブルを同時にスキャン

* 先行テーブルには「データ量の少ない方」が先に来る必要がある

* システムリソースを最大限に活用可能だが、リソースを過剰に消費する可能性があり、負荷などの懸念がある

* 大容量処理において高速な処理速度を示す

* EQUI JOINでのみ可能

* インデックスを使用しない

* JOIN方式

  ```text
  먼저 선행 테이블을 결정, 선행 테이블에서 주어진 조건에 해당하는 레코드를 선택
  해당 행이 선택되면 JOIN Key를 기준으로 해시 함수를 사용
  해시 테이블을 메인 메모리에 생성, 후행 테이블에서 주어진 조건을 만족하는 행을 찾음
  후행 테이블의 JOIN Key를 사용해서 해시함수를 적용, 해당 버킷을 검색
  ```
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;PL/SQL&lt;/h2&gt;
&lt;p&gt;SQLを拡張し、多様な手続き型プログラミングを可能にした言語&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ブロック構造になっているため、機能別にモジュール化が可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DECLARE文で始まり、変数および定数を宣言して使用可能&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DECLARE、BEGIN ～ ENDは必須、EXCEPTIONは任意&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DML、IF、LOOPなど、様々な手続き型言語を使用&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Oracleに組み込まれており、同じ言語を使用するプログラムとの互換性がある&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;アプリケーションのパフォーマンスを向上させる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Procedure、User Defined Function、Triggerオブジェクトを作成できる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;プロシージャ内部に記述された手続き型コードはPL/SQLエンジンが処理し、一般的なSQL文はSQL実行エンジンが処理する。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;分散データベース&lt;/h2&gt;
&lt;p&gt;単一のデータベースシステム（DBMS）がネットワークを介して物理的に分離されたデータベース群を制御する形態のDB&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;性能向上：分散データベースは並列処理を行うため、処理速度が速い&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;モジュール化されているため、他のモジュールに影響を与えることなくシステムの更新が可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;分散データベースの追加による容量の拡張が可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;重要データの保護が容易&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;信頼性が高い&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;管理および制御の難しさ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;セキュリティ管理、整合性制御の難しさ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;複雑な構造&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;메모

count(*): 전체 행의 수를 카운팅, null 포함
count({column_name}) null 을 제외한 행의 수를 카운팅
null: 모르는 값을 상징, 값의 부재를 말함
(null is null) = TRUE
null과의 모든 비교는 null 반환
0 혹은 &amp;#x27; &amp;#x27;과 동일한 값이 아님 

서브쿼리: SELECT문 내의 SELECT문이 반복 사용된 쿼리, 단일행 및 다중행으로 구분
- 정렬을 수행하는 ORDER BY를 사용할 수 없다.
- 여러 행을 반환하는 서브 쿼리는 다중 행 연산자를, 단일 행을 반환하는 서브쿼리는 단일 행 연산자를 사용
- 메인 쿼리에서 서브 쿼리의 컬럼을 자유롭게 사용할 수 없음
- EXIST는 True 혹은 False를 반환한다

스칼라 서브쿼리: 한 행과 한 컬럼만 반환하는 서브쿼리
인라인뷰: 서브쿼리가 FROM 절 내에 쓰여진 것

view 테이블
- 사용상의 편의를 위해 사용
- 수행속도의 향상을 위해 사용
- SQL의 성능을 향상시키기 위해 사용
- 임시적인 작업을 위해 사용
- 보안관리를 위해 사용

실행 순서
SELECT ALIAS =&amp;gt; FROM =&amp;gt; WHERE =&amp;gt; GROUP BY =&amp;gt; HAVING =&amp;gt; SELECT =&amp;gt; ORDER BY

조회 행수 제한
몇 번째 행을 조회하는지 부여하는 조건문
ROWNUM {row_number}: Oracle
TOP {row_number}: SQL Server
LIMIT {row_number}: MySQL

ROWID
해당 데이터가 어떤 데이터 파일 상에서 어느 블록에 저장되었는지 알려준다.
데이터베이스에 저장되어 있는 데이터를 구분할 수 있는 유일한 값이다.
ROWID의 번호는 데이터 블록에 데이터가 저장된 순서이다.
테이블에 데이터를 입력하면 자동으로 생성된다.
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[BOJ 17471, Python] ゲリマンダーリング</title><link>https://www.traceoflight.dev/ja/blog/boj17471/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj17471/</guid><description>BOJ 17471、「ゲリマンダーリング」問題のPythonによる解法</description><pubDate>Mon, 07 Nov 2022 11:14:53 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17471&quot;&gt;BOJ 17471&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;幅優先探索(bfs)、ブルートフォースアルゴリズム(bruteforcing)、組み合わせ論(combinatorics)、深さ優先探索(dfs)、グラフ理論(graphs)、グラフ探索(graph_traversal)、数学(math)&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;最初は、この問題をユニオン・ファインド問題だと考えてアプローチし、辺を削除してみたり、他の制約条件を設定してみたりしたが、むしろ正直にアプローチして解くべき問題だった。&lt;/p&gt;
&lt;p&gt;0.5秒という制約条件を取り除いてみると、すべての組み合わせについて深さ優先探索を通じてチェックしようという考えが浮かぶが、Pythonを使用していたため、時間が短く与えられると正直な解法を排除してしまうことが敗因となった。&lt;/p&gt;
&lt;p&gt;区域の数が最大10個と限られていることを考慮すれば、十分にブルートフォースで解決可能であり、かえって別の方向に力を注ぐと痛い目を見る問題だ。&lt;/p&gt;
&lt;p&gt;したがって、この問題はすべての区域を2つに分割して選挙区が成立するかを確認し、成立する場合は2つの選挙区の人口差を確認して、既存の人口差の値より小さい値が出たら更新するという方向で解決できる。&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 게리맨더링&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sys
&lt;span class=&quot;hljs-keyword&quot;&gt;from&lt;/span&gt; itertools &lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; combinations

&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt; = sys.stdin.readline

&lt;span class=&quot;hljs-comment&quot;&gt;# 상한값 선언&lt;/span&gt;
INF = &lt;span class=&quot;hljs-number&quot;&gt;2000000000&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 구역 갯수 입력&lt;/span&gt;
area_number = &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;())

&lt;span class=&quot;hljs-comment&quot;&gt;# 구역별 인구 정보 입력&lt;/span&gt;
people_number = [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;] + &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split()))

&lt;span class=&quot;hljs-comment&quot;&gt;# 인접 구역 관계 그래프 입력&lt;/span&gt;
graph = [[] &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(area_number + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]
&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; area_idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, area_number + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;):
    near_area, *graph[area_idx] = &lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split())

&lt;span class=&quot;hljs-comment&quot;&gt;# 총 인구수 확인&lt;/span&gt;
max_people = &lt;span class=&quot;hljs-built_in&quot;&gt;sum&lt;/span&gt;(people_number)

&lt;span class=&quot;hljs-comment&quot;&gt;# 최소 차이값 변수 선언&lt;/span&gt;
min_difference = INF

&lt;span class=&quot;hljs-comment&quot;&gt;# 한 선거구의 포함될 모든 구역 수에 대해 체크 &lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; areas &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, area_number // &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;):

    &lt;span class=&quot;hljs-comment&quot;&gt;# 모든 구역 중에서 한 선거구에 포함될 구역 확정&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; target_areas &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; combinations(&lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, area_number + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;), areas):

        &lt;span class=&quot;hljs-comment&quot;&gt;# 해당 선거구에 포함되는 구역 집합 선언 및 해당 선거구 인원수 변수 선언&lt;/span&gt;
        target_set = &lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt;(target_areas)
        sum_areas = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# Depth First Search&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 집합에 포함된 한 구역에서 시작하는 깊이 탐색&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; first_area &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; target_set:

            &lt;span class=&quot;hljs-comment&quot;&gt;# 선거구 내 구역 수 체크 카운터 선언&lt;/span&gt;
            counter = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

            &lt;span class=&quot;hljs-comment&quot;&gt;# 방문 리스트 선언&lt;/span&gt;
            is_visited = [&lt;span class=&quot;hljs-literal&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(area_number + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]

            &lt;span class=&quot;hljs-comment&quot;&gt;# 깊이 탐색을 진행할 스택 선언 및 초기 조건 입력&lt;/span&gt;
            progress_stack = [first_area]
            sum_areas += people_number[first_area]
            is_visited[first_area] = &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;

            &lt;span class=&quot;hljs-comment&quot;&gt;# 탐색 진행&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; progress_stack:

                &lt;span class=&quot;hljs-comment&quot;&gt;# 현재 구역 확인&lt;/span&gt;
                now_area = progress_stack.pop()

                &lt;span class=&quot;hljs-comment&quot;&gt;# 모든 인접 구역에 대해 확인&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; next_area &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; graph[now_area]:

                    &lt;span class=&quot;hljs-comment&quot;&gt;# 같은 선거구에 속해있고 방문하지 않았을 경우만 조사&lt;/span&gt;
                    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; next_area &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; target_set:
                        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; is_visited[next_area]:

                            &lt;span class=&quot;hljs-comment&quot;&gt;# 방문 처리, 인구수 합산, 선거구 카운팅&lt;/span&gt;
                            is_visited[next_area] = &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;
                            sum_areas += people_number[next_area]
                            counter += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

                            &lt;span class=&quot;hljs-comment&quot;&gt;# 다음 구역 스택에 추가&lt;/span&gt;
                            progress_stack.append(next_area)

            &lt;span class=&quot;hljs-comment&quot;&gt;# 1회의 조사로 선거구의 모든 정보를 획득하므로 반복하지 않음&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 남은 구역들에 대해서 다른 하나의 선거구라 가정하고 깊이 탐색 진행&lt;/span&gt;

        other_set = &lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, area_number + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)) - &lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt;(target_set)
        sum_other_areas = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; first_other_area &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; other_set:

            other_counter = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;
            sum_other_areas += people_number[first_other_area]

            progress_stack = [first_other_area]
            is_visited[first_other_area] = &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;

            &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; progress_stack:
                
                now_area = progress_stack.pop()

                &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; next_area &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; graph[now_area]:
                    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; next_area &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; other_set:
                        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; is_visited[next_area]:
                            is_visited[next_area] = &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;
                            sum_other_areas += people_number[next_area]
                            progress_stack.append(next_area)
                            other_counter += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

            &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 양쪽 선거구를 조사했을 때 남는 구역이 없을 경우만 성립&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; counter + other_counter == area_number:

            &lt;span class=&quot;hljs-comment&quot;&gt;# 두 선거구의 인구 차이를 확인하여 기존값보다 작다면 갱신&lt;/span&gt;
            now_min = &lt;span class=&quot;hljs-built_in&quot;&gt;abs&lt;/span&gt;(sum_areas - sum_other_areas)
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; min_difference &amp;gt; now_min:
                min_difference = now_min

&lt;span class=&quot;hljs-comment&quot;&gt;# 한 번도 갱신하지 못했다면 선거구 분할 실패이므로 -1 출력&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; min_difference == INF:
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

&lt;span class=&quot;hljs-comment&quot;&gt;# 갱신한 경우 결과를 출력&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(min_difference)

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[BOJ 14438, Python] 数列とクエリ 17</title><link>https://www.traceoflight.dev/ja/blog/boj14438/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj14438/</guid><description>BOJ 14438、「数列とクエリ 17」の問題のPythonによる解法</description><pubDate>Tue, 01 Nov 2022 13:52:01 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;[BOJ 14438](&lt;a href=&quot;https://www.acmicpc.net/problem/14438&quot;&gt;https://www.acmicpc.net/problem/14438&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;h3&gt;カテゴリ&lt;/h3&gt;
&lt;p&gt;セグメントツリー(segtree)、データ構造(data_structures)&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;セグメントツリーを初めて学ぶ人が最もよく遭遇するセグメントツリー系の問題だと考えられる。&lt;/p&gt;
&lt;p&gt;区間和、区間積、区間内の最大値など、様々な値について、線形リストを基準としたO(NlogN)の時間で構築でき、各区間に関する情報にO(logN)という高速な速度でアクセスできるという利点がある。&lt;/p&gt;
&lt;p&gt;この問題は、大きく分けてセグメントツリーを構築する関数、区間情報を検索する関数、変更された値を反映する関数に分けることができる。&lt;/p&gt;
&lt;h4&gt;生成関数&lt;/h4&gt;
&lt;p&gt;まず、セグメントツリーを生成する関数&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;make_segtree&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;target_list: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, result_list: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, start: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, end:&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, now_node: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;:
    &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&amp;#x27;
    최소 숫자 정보를 담는 세그먼트 트리를 생성하는 함수
    &amp;#x27;&amp;#x27;&amp;#x27;&lt;/span&gt;

    &lt;span class=&quot;hljs-comment&quot;&gt;# 포인터가 한 곳으로 모인 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; start == end:

        &lt;span class=&quot;hljs-comment&quot;&gt;# 해당 노드는 포인터가 가리키는 인덱스의 값과 동일&lt;/span&gt;
        result_list[now_node] = target_list[start]

    &lt;span class=&quot;hljs-comment&quot;&gt;# 포인터가 범위를 나타내는 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:

        &lt;span class=&quot;hljs-comment&quot;&gt;# Devide and Conquer Algorithm&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 중간 지점 선언&lt;/span&gt;
        mid = (start + end) // &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 중간 지점을 기준으로 구간을 분할하여 최소값으로 갱신&lt;/span&gt;
        val_1 = make_segtree(target_list, result_list, start, mid, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node)
        val_2 = make_segtree(target_list, result_list, mid + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, end, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

        &lt;span class=&quot;hljs-comment&quot;&gt;# 두 구간의 최소값을 비교하여 둘 중 최소값을 현재 노드에 기록&lt;/span&gt;
        result_list[now_node] = &lt;span class=&quot;hljs-built_in&quot;&gt;min&lt;/span&gt;(val_1, val_2)

    &lt;span class=&quot;hljs-comment&quot;&gt;# 현재 노드의 값을 반환&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; result_list[now_node]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;を見ると、基本的にはリスト全体を区間ごとに分割し、各区間に関する情報をセグメントツリーの各ノードに格納する過程を示している。&lt;/p&gt;
&lt;p&gt;再帰方式を使用しているため、区間の長さが1になるまで再帰が進行するにつれて再帰スタックが積み上げられ、到達した場合はそのアドレスにリスト1つの値に関する情報を入力する。&lt;/p&gt;
&lt;p&gt;その後、返された値を通じて、リーフノードではないノードは条件に合う値を選別しながら、最終的にルートに到達することになる。&lt;/p&gt;
&lt;p&gt;したがって、ルートノードに含まれる値は、全区間において問題で要求された条件に最も適合する値となる。&lt;/p&gt;
&lt;h4&gt;探索関数&lt;/h4&gt;
&lt;p&gt;次に、区間内の最小値を探す関数について確認すると、&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;find_min_number&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;target_tree: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, start: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, end: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, left: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, right: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, now_node: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;:
    &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&amp;#x27;
    해당 구간의 최소값을 찾는 함수
    &amp;#x27;&amp;#x27;&amp;#x27;&lt;/span&gt;

    &lt;span class=&quot;hljs-comment&quot;&gt;# 범위 내로 포인터가 좁혀진 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; left &amp;lt;= start &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; right &amp;gt;= end:

        &lt;span class=&quot;hljs-comment&quot;&gt;# 현재 노드값을 반환&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; target_tree[now_node]

    &lt;span class=&quot;hljs-comment&quot;&gt;# 범위를 아예 벗어난 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;elif&lt;/span&gt; left &amp;gt; end &lt;span class=&quot;hljs-keyword&quot;&gt;or&lt;/span&gt; right &amp;lt; start:

        &lt;span class=&quot;hljs-comment&quot;&gt;# None 값을 반환&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;

    &lt;span class=&quot;hljs-comment&quot;&gt;# 범위가 걸친 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:

        &lt;span class=&quot;hljs-comment&quot;&gt;# Devide and Conquer Algorithm&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 중간 지점 선언&lt;/span&gt;
        mid = (start + end) // &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 중간 지점을 기준으로 구간을 분할하여 값을 확인&lt;/span&gt;
        val_1 = find_min_number(target_tree, start, mid, left, right, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node)
        val_2 = find_min_number(target_tree, mid + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, end, left, right, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

        &lt;span class=&quot;hljs-comment&quot;&gt;# 반환된 값들 중 None이 존재하는 경우&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; val_1 &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; val_2 &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;

        &lt;span class=&quot;hljs-keyword&quot;&gt;elif&lt;/span&gt; val_1 &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; val_2

        &lt;span class=&quot;hljs-keyword&quot;&gt;elif&lt;/span&gt; val_2 &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; val_1

        &lt;span class=&quot;hljs-comment&quot;&gt;# None이 없다면&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:

            &lt;span class=&quot;hljs-comment&quot;&gt;# 두 구간의 최소값 중에서 더 작은 값을 반환&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;min&lt;/span&gt;(val_1, val_2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;基本的に、探している区間が含まれている場所であれば詳細に処理を進め、完全に探している区間のみが含まれるようになるまで処理を行い、その値を返して親関数で確認できるようにコードを構成した。&lt;/p&gt;
&lt;p&gt;もし範囲外の場合はNoneを返すようにし、条件を通じてPruningを行うだけで、完全に範囲内にある区間のみを選択して比較することができる。&lt;/p&gt;
&lt;h4&gt;修正関数&lt;/h4&gt;
&lt;p&gt;最後に、値の修正が行われた場合に反映する関数を見てみよう。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;change_segtree&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;target_tree: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, start: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, end: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, target_idx: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, target_val: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, now_node: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
    &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&amp;#x27;
    리스트에 생긴 변경점을 트리에 반영하는 함수
    &amp;#x27;&amp;#x27;&amp;#x27;&lt;/span&gt;
    
    &lt;span class=&quot;hljs-comment&quot;&gt;# 포인터가 한 곳으로 모인 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; start == end:

        &lt;span class=&quot;hljs-comment&quot;&gt;# 목표로 하는 인덱스랑 동일하다면 변경값을 반영&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; start == target_idx:
            target_tree[now_node] = target_val

    &lt;span class=&quot;hljs-comment&quot;&gt;# 포인터가 범위로 주어진 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:

        &lt;span class=&quot;hljs-comment&quot;&gt;# 목표 인덱스가 범위 내에 존재할 경우에만 갱신 가능성 존재&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; start &amp;lt;= target_idx &amp;lt;= end:

            &lt;span class=&quot;hljs-comment&quot;&gt;# Devide and Conquer Algorithm&lt;/span&gt;

            &lt;span class=&quot;hljs-comment&quot;&gt;# 중간 지점 선언&lt;/span&gt;
            mid = (start + end) // &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;

            &lt;span class=&quot;hljs-comment&quot;&gt;# 중간 지점을 기준으로 변경될 수 있는 인덱스를 재조사&lt;/span&gt;
            change_segtree(target_tree, start, mid, target_idx, target_val, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node)
            change_segtree(target_tree, mid + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, end, target_idx, target_val, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

        &lt;span class=&quot;hljs-comment&quot;&gt;# 하위 노드들의 갱신이 진행된 이후 현재 노드의 갱신 진행&lt;/span&gt;
        target_tree[now_node] = &lt;span class=&quot;hljs-built_in&quot;&gt;min&lt;/span&gt;(target_tree[&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node], target_tree[&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;])

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;現在変更された値のインデックスが含まれる区間であればすべて変更する必要があるため、そのインデックスを含む区間かどうかを基準に判別を行う。&lt;/p&gt;
&lt;p&gt;生成関数と同様に、1つのインデックスに絞り込まれるまで再帰スタックを積み上げ、そのインデックス1つだけを含むノードの値の変更から返却を進めながら修正された値を反映し、最終的にルートノードまでチェックして完了することになる。&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;p&gt;上記の過程を通じて、問題で要求された動作をすべてモジュール化することができ、以下に全体コードを確認できる。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 수열과 쿼리 17&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sys
&lt;span class=&quot;hljs-keyword&quot;&gt;from&lt;/span&gt; math &lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; ceil, log2

&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt; = sys.stdin.readline

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;make_segtree&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;target_list: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, result_list: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, start: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, end:&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, now_node: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;:
    &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&amp;#x27;
    최소 숫자 정보를 담는 세그먼트 트리를 생성하는 함수
    &amp;#x27;&amp;#x27;&amp;#x27;&lt;/span&gt;

    &lt;span class=&quot;hljs-comment&quot;&gt;# 포인터가 한 곳으로 모인 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; start == end:

        &lt;span class=&quot;hljs-comment&quot;&gt;# 해당 노드는 포인터가 가리키는 인덱스의 값과 동일&lt;/span&gt;
        result_list[now_node] = target_list[start]

    &lt;span class=&quot;hljs-comment&quot;&gt;# 포인터가 범위를 나타내는 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:

        &lt;span class=&quot;hljs-comment&quot;&gt;# Devide and Conquer Algorithm&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 중간 지점 선언&lt;/span&gt;
        mid = (start + end) // &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 중간 지점을 기준으로 구간을 분할하여 최소값으로 갱신&lt;/span&gt;
        val_1 = make_segtree(target_list, result_list, start, mid, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node)
        val_2 = make_segtree(target_list, result_list, mid + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, end, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

        &lt;span class=&quot;hljs-comment&quot;&gt;# 두 구간의 최소값을 비교하여 둘 중 최소값을 현재 노드에 기록&lt;/span&gt;
        result_list[now_node] = &lt;span class=&quot;hljs-built_in&quot;&gt;min&lt;/span&gt;(val_1, val_2)

    &lt;span class=&quot;hljs-comment&quot;&gt;# 현재 노드의 값을 반환&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; result_list[now_node]

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;find_min_number&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;target_tree: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, start: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, end: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, left: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, right: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, now_node: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;:
    &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&amp;#x27;
    해당 구간의 최소값을 찾는 함수
    &amp;#x27;&amp;#x27;&amp;#x27;&lt;/span&gt;

    &lt;span class=&quot;hljs-comment&quot;&gt;# 범위 내로 포인터가 좁혀진 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; left &amp;lt;= start &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; right &amp;gt;= end:

        &lt;span class=&quot;hljs-comment&quot;&gt;# 현재 노드값을 반환&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; target_tree[now_node]

    &lt;span class=&quot;hljs-comment&quot;&gt;# 범위를 아예 벗어난 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;elif&lt;/span&gt; left &amp;gt; end &lt;span class=&quot;hljs-keyword&quot;&gt;or&lt;/span&gt; right &amp;lt; start:

        &lt;span class=&quot;hljs-comment&quot;&gt;# None 값을 반환&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;

    &lt;span class=&quot;hljs-comment&quot;&gt;# 범위가 걸친 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:

        &lt;span class=&quot;hljs-comment&quot;&gt;# Devide and Conquer Algorithm&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 중간 지점 선언&lt;/span&gt;
        mid = (start + end) // &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 중간 지점을 기준으로 구간을 분할하여 값을 확인&lt;/span&gt;
        val_1 = find_min_number(target_tree, start, mid, left, right, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node)
        val_2 = find_min_number(target_tree, mid + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, end, left, right, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

        &lt;span class=&quot;hljs-comment&quot;&gt;# 반환된 값들 중 None이 존재하는 경우&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; val_1 &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; val_2 &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;

        &lt;span class=&quot;hljs-keyword&quot;&gt;elif&lt;/span&gt; val_1 &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; val_2

        &lt;span class=&quot;hljs-keyword&quot;&gt;elif&lt;/span&gt; val_2 &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; val_1

        &lt;span class=&quot;hljs-comment&quot;&gt;# None이 없다면&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:

            &lt;span class=&quot;hljs-comment&quot;&gt;# 두 구간의 최소값 중에서 더 작은 값을 반환&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;min&lt;/span&gt;(val_1, val_2)

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;change_segtree&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;target_tree: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, start: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, end: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, target_idx: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, target_val: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, now_node: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
    &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&amp;#x27;
    리스트에 생긴 변경점을 트리에 반영하는 함수
    &amp;#x27;&amp;#x27;&amp;#x27;&lt;/span&gt;
    
    &lt;span class=&quot;hljs-comment&quot;&gt;# 포인터가 한 곳으로 모인 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; start == end:

        &lt;span class=&quot;hljs-comment&quot;&gt;# 목표로 하는 인덱스랑 동일하다면 변경값을 반영&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; start == target_idx:
            target_tree[now_node] = target_val

    &lt;span class=&quot;hljs-comment&quot;&gt;# 포인터가 범위로 주어진 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:

        &lt;span class=&quot;hljs-comment&quot;&gt;# 목표 인덱스가 범위 내에 존재할 경우에만 갱신 가능성 존재&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; start &amp;lt;= target_idx &amp;lt;= end:

            &lt;span class=&quot;hljs-comment&quot;&gt;# Devide and Conquer Algorithm&lt;/span&gt;

            &lt;span class=&quot;hljs-comment&quot;&gt;# 중간 지점 선언&lt;/span&gt;
            mid = (start + end) // &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;

            &lt;span class=&quot;hljs-comment&quot;&gt;# 중간 지점을 기준으로 변경될 수 있는 인덱스를 재조사&lt;/span&gt;
            change_segtree(target_tree, start, mid, target_idx, target_val, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node)
            change_segtree(target_tree, mid + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, end, target_idx, target_val, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

        &lt;span class=&quot;hljs-comment&quot;&gt;# 하위 노드들의 갱신이 진행된 이후 현재 노드의 갱신 진행&lt;/span&gt;
        target_tree[now_node] = &lt;span class=&quot;hljs-built_in&quot;&gt;min&lt;/span&gt;(target_tree[&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node], target_tree[&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; * now_node + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;])

&lt;span class=&quot;hljs-comment&quot;&gt;# 수열의 크기 및 수열 정보 입력&lt;/span&gt;
target_length = &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;())
target_arr = [&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;*&amp;#x27;&lt;/span&gt;] + &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split()))

&lt;span class=&quot;hljs-comment&quot;&gt;# 수열의 구간 최소 숫자를 담을 세그먼트 트리 리스트 선언&lt;/span&gt;
segtree_arr = [&lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;pow&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;, ceil(log2(target_length) + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)))]

&lt;span class=&quot;hljs-comment&quot;&gt;# 함수를 호출하여 트리 생성&lt;/span&gt;
make_segtree(target_arr, segtree_arr, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, target_length, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

&lt;span class=&quot;hljs-comment&quot;&gt;# 퀴리 갯수 입력 및 출력 리스트 선언&lt;/span&gt;
query_number = &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;())
output = []

&lt;span class=&quot;hljs-comment&quot;&gt;# 쿼리 실행&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(query_number):

    &lt;span class=&quot;hljs-comment&quot;&gt;# 각 쿼리의 정보&lt;/span&gt;
    order_type, num_1, num_2 = &lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split())

    &lt;span class=&quot;hljs-comment&quot;&gt;# 타입 1의 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; order_type == &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:

        &lt;span class=&quot;hljs-comment&quot;&gt;# 리스트 값을 변경 및 함수를 호출하여 트리에 반영&lt;/span&gt;
        target_arr[num_1] = num_2
        change_segtree(segtree_arr, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, target_length, num_1, num_2, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

    &lt;span class=&quot;hljs-comment&quot;&gt;# 타입 2의 경우&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;elif&lt;/span&gt; order_type == &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;:

        &lt;span class=&quot;hljs-comment&quot;&gt;# 함수를 호출하여 해당 구간의 최소 숫자를 출력 리스트에 추가&lt;/span&gt;
        output.append(find_min_number(segtree_arr, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, target_length, num_1, num_2, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;))

&lt;span class=&quot;hljs-comment&quot;&gt;# 결과 출력&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; result &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; output:
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(result)
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Git入門</title><link>https://www.traceoflight.dev/ja/blog/git-intro/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/git-intro/</guid><description>Git以前のバージョン管理システムと、Gitの動作およびコマンドに関するまとめ</description><pubDate>Fri, 28 Oct 2022 13:19:01 GMT</pubDate><content:encoded>&lt;h1&gt;はじめに&lt;/h1&gt;
&lt;p&gt;Gitについて学習する中で、必要な内容をまとめた記事です。大きな変更がない限り、あるいは追加の学習が必要とならない限り、これがイントロであり、最後の記事になると思います。&lt;/p&gt;
&lt;h2&gt;Gitとは？&lt;/h2&gt;
&lt;p&gt;バージョン管理ツールの一種であり、バージョン管理を通じてファイルの変更履歴を記録し、特定の時点の状態を再び利用できるようにするシステムです。&lt;/p&gt;
&lt;h3&gt;ローカルでのバージョン管理&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;ディレクトリのコピー&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;最も単純な方法&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;誤ってファイルを間違って修正したり、間違ってコピーしたりする可能性がある。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;VCS (Version Control System)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;DBを活用してファイルの変更情報を管理&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Revision Control Systemが代表的&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Patch Set（ファイルの変更部分）を管理&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一連のPatch Setを活用して、すべてのファイルを特定の時点に戻すことができる&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;集中型バージョン管理&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;プロジェクトを進める場合、他の開発者との共同作業が頻繁にある&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;このような場合、ファイルを管理するサーバーが別途存在し、クライアントが中央サーバーからファイルを取得して使用する方式が有利&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;中央サーバーに問題が発生した場合、システムのバックアップが存在しなければすべての履歴を失う可能性があり、これはローカルにも存在していた問題&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;分散型バージョン管理システム&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;単にスナップショットを保管するだけでなく、リポジトリと履歴を同時に複製する。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;サーバーに問題が発生した場合、その複製を通じて作業を再開できる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;クライアントの中からどれか一つを選んでサーバーを復元することも可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;リモートリポジトリの存在により、多様な形式のコラボレーションが可能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GitHubもこのリモートリポジトリの一種&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;一般的な使用法&lt;/h2&gt;
&lt;h3&gt;設定およびファイルアクセスコマンド&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 전역 사용자 설정&lt;/span&gt;
git config --global user.name {name} &lt;span class=&quot;hljs-comment&quot;&gt;# 이름&lt;/span&gt;
git config --global user.email {email_address} &lt;span class=&quot;hljs-comment&quot;&gt;# 이메일&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 로컬 사용자 설정 (해당 디렉토리에서 실행)&lt;/span&gt;
git config user.name {name} &lt;span class=&quot;hljs-comment&quot;&gt;# 이름&lt;/span&gt;
git config user.email {email_address} &lt;span class=&quot;hljs-comment&quot;&gt;# 이메일&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 설정 조회&lt;/span&gt;
git config --list

&lt;span class=&quot;hljs-comment&quot;&gt;# 생성&lt;/span&gt;
git &lt;span class=&quot;hljs-built_in&quot;&gt;mkdir&lt;/span&gt; {path}/{folder_name} &lt;span class=&quot;hljs-comment&quot;&gt;# 폴더&lt;/span&gt;
git &lt;span class=&quot;hljs-built_in&quot;&gt;touch&lt;/span&gt; {file_name} &lt;span class=&quot;hljs-comment&quot;&gt;# 파일&lt;/span&gt;
git init &lt;span class=&quot;hljs-comment&quot;&gt;# 파일 관리 시스템&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 저장소 및 히스토리 복제&lt;/span&gt;
git &lt;span class=&quot;hljs-built_in&quot;&gt;clone&lt;/span&gt; {repository_url}

&lt;span class=&quot;hljs-comment&quot;&gt;# 원격 저장소&lt;/span&gt;
git remote add {remote_repo_name} {remote_repo_url} &lt;span class=&quot;hljs-comment&quot;&gt;# 추가&lt;/span&gt;
git remote -v &lt;span class=&quot;hljs-comment&quot;&gt;# 정보 확인&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# commit history&lt;/span&gt;
git &lt;span class=&quot;hljs-built_in&quot;&gt;log&lt;/span&gt;
git &lt;span class=&quot;hljs-built_in&quot;&gt;log&lt;/span&gt; --oneline &lt;span class=&quot;hljs-comment&quot;&gt;# 정보 표시 간략화&lt;/span&gt;
git &lt;span class=&quot;hljs-built_in&quot;&gt;log&lt;/span&gt; --all &lt;span class=&quot;hljs-comment&quot;&gt;# 현재 head 이후의 최신 기록들을 포함한 전체 정보를 표시&lt;/span&gt;
git &lt;span class=&quot;hljs-built_in&quot;&gt;log&lt;/span&gt; --graph &lt;span class=&quot;hljs-comment&quot;&gt;# 브랜치를 시각화하여 분기를 표현한 그래프 형태로 정보를 표시&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;リポジトリ管理に使用するコマンド&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git status &lt;span class=&quot;hljs-comment&quot;&gt;# 변경사항을 확인하는 명령어&lt;/span&gt;
git commit -m {message} &lt;span class=&quot;hljs-comment&quot;&gt;# 현재 스테이지에 존재하는 변경 사항을 커밋&lt;/span&gt;

git add {file_name} &lt;span class=&quot;hljs-comment&quot;&gt;# 특정한 파일을 스테이지에 추가하는 경우&lt;/span&gt;
git add . &lt;span class=&quot;hljs-comment&quot;&gt;# 해당 레포지토리의 변경사항을 전부 스테이지에 추가하는 경우&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Gitの取り消し&lt;/h2&gt;
&lt;h3&gt;ステージのクリア&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git &lt;span class=&quot;hljs-built_in&quot;&gt;rm&lt;/span&gt; --cached &lt;span class=&quot;hljs-comment&quot;&gt;# root commit이 존재하지 않을 때&lt;/span&gt;
git restore --staged &lt;span class=&quot;hljs-comment&quot;&gt;# root commit이 존재할 때&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;コミットの修正&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git commit --amend 
&lt;span class=&quot;hljs-comment&quot;&gt;# 스테이지에 파일이 없는 경우: 직전 커밋의 메시지를 수정&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;# 스테이지에 파일이 있는 경우: 기존 커밋에 현재 스테이지를 더하여 덮어쓰기 진행&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;コミットを特定の時点まですべて元に戻す&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git reset --soft {commit_id} &lt;span class=&quot;hljs-comment&quot;&gt;# 미래 파일들 전부 stage에 돌려놓음&lt;/span&gt;
git reset --mixed {commit_id} &lt;span class=&quot;hljs-comment&quot;&gt;# default, 미래 파일들을 전부 working directory에 유지 (add 필요)&lt;/span&gt;
git reset --hard {commit_id} &lt;span class=&quot;hljs-comment&quot;&gt;# 미래 파일 전부 제거&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;過去のコミットを削除&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git revert {commit_id} &lt;span class=&quot;hljs-comment&quot;&gt;# 과거 commit을 제거 후, 제거했음을 commit으로 추가&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;resetはコミット数が減るため共同作業には不向き。したがって、共同作業時はresetの代わりにrevertの使用を推奨&lt;/p&gt;
&lt;h2&gt;Git Branch&lt;/h2&gt;
&lt;p&gt;Branch: 作業領域を分割し、独立して作業できるようにする仕組み&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;元の状態を維持できるため安全&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;1つのブランチで1つの作業を進めることで、共同作業の効率が向上&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gitの場合、ブランチの作成速度も速く、ファイル容量も大きくない&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;関連コマンド&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 조회&lt;/span&gt;
git branch &lt;span class=&quot;hljs-comment&quot;&gt;# 로컬 저장소의 브랜치 대상&lt;/span&gt;
git branch -r &lt;span class=&quot;hljs-comment&quot;&gt;# 원격 저장소의 브랜치 대상&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 생성&lt;/span&gt;
git branch {branch_name}
git branch {branch_name} {commit_id} &lt;span class=&quot;hljs-comment&quot;&gt;# 특정 커밋 지점을 기준점으로 생성&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 제거&lt;/span&gt;
git branch -d {branch_name} &lt;span class=&quot;hljs-comment&quot;&gt;# 병합 완료된 경우&lt;/span&gt;
git branch -D {branch_name} &lt;span class=&quot;hljs-comment&quot;&gt;# 병합하지 못한 브랜치 강제 삭제&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 브랜치 이동&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;# 이동 전 반드시 현재 브랜치의 변경사항을 기록할 것&lt;/span&gt;
git switch {branch_name} &lt;span class=&quot;hljs-comment&quot;&gt;# 이미 있는 브랜치로 이동&lt;/span&gt;
git switch -c {branch_name} &lt;span class=&quot;hljs-comment&quot;&gt;# 해당 이름의 브랜치를 생성 후 이동&lt;/span&gt;
git switch -c {branch_name} {commit_id} &lt;span class=&quot;hljs-comment&quot;&gt;# 특정 커밋 지점을 기준점으로 하는 해당 이름의 브랜치를 생성 후 이동&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Git Merge&lt;/h2&gt;
&lt;p&gt;分岐したブランチを統合するプロセス&lt;/p&gt;
&lt;h3&gt;マージの種類&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Fast-Forward: ブランチが指すコミットを先頭に移動&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;3-Way Merge: 各ブランチの最新のコミット2つ + 両ブランチの共通の祖先を使用したマージ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Merge Conflict: 同じファイルを修正した場合に発生する衝突 =&amp;gt; 衝突を解決した後、3-Way Mergeを実行&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 해당 브랜치를 현재 위치한 브랜치에 병합&lt;/span&gt;
git merge {merged_branch}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Git Fork&lt;/h2&gt;
&lt;p&gt;所有権のないリモートリポジトリを複製すること。主にオープンソースのような、多数の協力者がいる場合に使用される&lt;/p&gt;
&lt;h3&gt;Forkされたソースに自分のコミットが反映されるプロセス&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;#    원본 원격 저장소 (upstream) &amp;lt;----------- 복제본 원격 저장소 (origin)&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;#                \           merge request      /|&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;#                 \                              |&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;#                  \                 push branch | pull master&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;#                   \                            |&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;#                    \     ( pull upstream )     |/&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;#                     ------------------&amp;gt; 로컬 저장소 (user)&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;#&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;元のリポジトリを自分のリモートリポジトリに複製&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;当該リモートリポジトリからローカルに保存&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ローカルでブランチを作成し、作業後にその変更をコミット&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;元のリモートリポジトリに変更内容に関するマージリクエストをプッシュ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;元のリモートリポジトリでその変更をマージ&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;元のリモートリポジトリから変更内容をプル&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;pull upstream&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;sync origin &amp;amp; pull origin&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ローカルでマージされた自分のブランチを削除&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>[BOJ 7579, Python] アプリ</title><link>https://www.traceoflight.dev/ja/blog/boj7579/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj7579/</guid><description>BOJ 7579, &quot;アプリ&quot;問題のPythonによる解決方法</description><pubDate>Fri, 28 Oct 2022 10:13:23 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/7579&quot;&gt;BOJ 7579&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;分類&lt;/h3&gt;
&lt;p&gt;ダイナミックプログラミング(dp), バックパック問題(knapsack)&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;この問題を解く時、個人的に重要視した部分を挙げるなら、問題条件だと思います。&lt;/p&gt;
&lt;p&gt;使用中のメモリバイトの条件は10^7で、活性化アプリの数は最大100個、コストの場合も100以下の条件を満たさなければなりませんでした。&lt;/p&gt;
&lt;p&gt;数値を確認する用途でメモリバイト条件を活用するには範囲が非常に広く、それに応じて適切な変数でコストを設定し、すべてのコストごとにアドレスを割り当てて最大限減らすことができるメモリを記録する方法を使うことにしました。&lt;/p&gt;
&lt;p&gt;ここでDPを使わなければならないことを推測し、さらに、cost、value値がそれぞれ存在する時、値によって既存の値を更新する方式を使用したknapsackアルゴリズムを利用して解決するという設計を試みることができました。&lt;/p&gt;
&lt;h3&gt;解決コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 앱&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sys

&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt; = sys.stdin.readline

&lt;span class=&quot;hljs-comment&quot;&gt;# 앱 갯수, 필요 메모리 입력&lt;/span&gt;
app_number, need_memory = &lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split())

&lt;span class=&quot;hljs-comment&quot;&gt;# 각 앱의 메모리와 비활성화 시의 비용 입력&lt;/span&gt;
app_memories = &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split()))
disable_costs = &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split()))

&lt;span class=&quot;hljs-comment&quot;&gt;# 앱의 메모리와 비용 합쳐서 짝을 지어줌&lt;/span&gt;
memories_and_costs = &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;zip&lt;/span&gt;(app_memories, disable_costs))

&lt;span class=&quot;hljs-comment&quot;&gt;# 최대 필요 비용 연산&lt;/span&gt;
sum_cost = &lt;span class=&quot;hljs-built_in&quot;&gt;sum&lt;/span&gt;(disable_costs)

&lt;span class=&quot;hljs-comment&quot;&gt;# 각 비용별 최대 절약 가능한 메모리 리스트 선언&lt;/span&gt;
cost_list = [&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _ &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(sum_cost + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]

&lt;span class=&quot;hljs-comment&quot;&gt;# Knapsack Algorithm&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 모든 앱에 대해 확인&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; now_memory, now_cost &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; memories_and_costs:

    &lt;span class=&quot;hljs-comment&quot;&gt;# 최대 필요 비용까지 조사&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; last_cost &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(sum_cost, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;):

        &lt;span class=&quot;hljs-comment&quot;&gt;# 최대 비용을 넘지 않는 선에서 확인&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; last_cost + now_cost &amp;lt;= sum_cost:

            &lt;span class=&quot;hljs-comment&quot;&gt;# 기존 최대값보다 컸다면 갱신&lt;/span&gt;
            cost_list[last_cost + now_cost] = &lt;span class=&quot;hljs-built_in&quot;&gt;max&lt;/span&gt;(
                cost_list[last_cost + now_cost], cost_list[last_cost] + now_memory
            )

&lt;span class=&quot;hljs-comment&quot;&gt;# 비용을 0에서부터 조사해서 기준 메모리 이상을 절약한 경우의 비용을 출력&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(sum_cost + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;):
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; cost_list[idx] &amp;gt;= need_memory:
        &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(idx)
        &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

```@&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>[BOJ 15683, Python] 監視</title><link>https://www.traceoflight.dev/ja/blog/boj15683/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/boj15683/</guid><description>BOJ 15683、「監視」問題のPythonによる解法</description><pubDate>Sun, 23 Oct 2022 10:46:34 GMT</pubDate><content:encoded>&lt;h3&gt;問題リンク&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/15683&quot;&gt;BOJ 15683&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;分類&lt;/h3&gt;
&lt;p&gt;ブルートフォースアルゴリズム(bruteforcing)、実装(implementation)、シミュレーション(simulation)&lt;/p&gt;
&lt;h3&gt;説明&lt;/h3&gt;
&lt;p&gt;分類はブルートフォースアルゴリズムとなっている問題だが、この問題を実装する際にはバックトラッキングアルゴリズムを使用した。&lt;/p&gt;
&lt;p&gt;基本的には、すべての監視カメラが見ることができる方向について調査を行い、すべての監視カメラの方向設定が完了した時点で関数を呼び出し、監視の死角の数を確認し、既存の最小値より小さければその値を更新するという方法を採用した。&lt;/p&gt;
&lt;p&gt;解法を作成した後、すぐにコメント処理を行う傾向があるため、今後の投稿においても詳細な解法はコードのコメントに記載される予定。&lt;/p&gt;
&lt;h3&gt;解答コード&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# 감시&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; sys

&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt; = sys.stdin.readline

&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;check_blind_spot&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;matrix: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, y_range: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, x_range: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;:
    &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&amp;#x27;
    현재 사무실 내 사각지대 갯수를 반환하는 함수
    &amp;#x27;&amp;#x27;&amp;#x27;&lt;/span&gt;

    &lt;span class=&quot;hljs-comment&quot;&gt;# 사각지대 변수 선언&lt;/span&gt;
    blind_here = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

    &lt;span class=&quot;hljs-comment&quot;&gt;# 모든 좌표에 대해서 조사&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; y_idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(y_range):
        &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; x_idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(x_range):

            &lt;span class=&quot;hljs-comment&quot;&gt;# 해당 좌표값이 0일 경우만 카운팅&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; matrix[y_idx][x_idx]:
                blind_here += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;hljs-comment&quot;&gt;# 결과 반환&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; blind_here

&lt;span class=&quot;hljs-comment&quot;&gt;# 사무실 가로 및 세로 크기 입력&lt;/span&gt;
height, width = &lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split())

&lt;span class=&quot;hljs-comment&quot;&gt;# CCTV 정보 및 사무실 정보를 담을 리스트 선언&lt;/span&gt;
cctvs = []
work_space = []

&lt;span class=&quot;hljs-comment&quot;&gt;# 초기 사각지대 갯수 확인&lt;/span&gt;
blind_spot = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;# 사무실 정보 입력&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; y_idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(height):

    &lt;span class=&quot;hljs-comment&quot;&gt;# 행 정보 확인&lt;/span&gt;
    temp = &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;().split())

    &lt;span class=&quot;hljs-comment&quot;&gt;# 모든 요소들에 대해 조사&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; x_idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(width):

        &lt;span class=&quot;hljs-comment&quot;&gt;# 만약 CCTV가 있다면 리스트에 추가&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; temp[x_idx] &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;12345&amp;#x27;&lt;/span&gt;:
            cctvs.append(((y_idx, x_idx), &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(temp[x_idx])))

        &lt;span class=&quot;hljs-comment&quot;&gt;# CCTV도 아니고 벽도 아니라면 초기 사각지대&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; temp[x_idx] == &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;0&amp;#x27;&lt;/span&gt;:
                blind_spot += &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;hljs-comment&quot;&gt;# 행 정보를 리스트에 추가&lt;/span&gt;
    work_space.append(&lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;map&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;lambda&lt;/span&gt; x: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt;(x), temp)))

&lt;span class=&quot;hljs-comment&quot;&gt;# CCTV 갯수 변수 선언&lt;/span&gt;
cctv_amount = &lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(cctvs)

&lt;span class=&quot;hljs-comment&quot;&gt;# CCTV 방향 정보 딕셔너리 선언&lt;/span&gt;
cctv_directions = {
    &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;: {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;: [(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;)], &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;: [(-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;)], &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;: [(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)], &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;: [(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]},
    &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;: {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;: [(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;), (-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;)], &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;: [(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;), (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]},
    &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;: {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;: [(-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;), (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)], &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;: [(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;), (&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;)], &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;: [(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;), (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)], &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;: [(&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;), (-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;)]},
    &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;: {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;: [(-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;), (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;), (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)], &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;: [(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;), (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;), (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)], &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;: [(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;), (-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;), (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)], &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;: [(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;), (-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;), (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]},
    &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;: {&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;: [(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;), (-&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;), (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;), (&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, -&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)]},
}

&lt;span class=&quot;hljs-comment&quot;&gt;# 각 CCTV의 방향 정보를 담은 리스트 선언&lt;/span&gt;
max_direction = [&lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;dummy&amp;#x27;&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]

&lt;span class=&quot;hljs-comment&quot;&gt;# CCTV가 존재하지 않는 경우 기존 사각지대의 갯수를 출력&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; cctv_amount:
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(blind_spot)

&lt;span class=&quot;hljs-comment&quot;&gt;# 만약 존재한다면 CCTV 방향에 따른 사각지대의 갯수를 조사&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:

    &lt;span class=&quot;hljs-comment&quot;&gt;# 최종 사각지대 갯수 변수 선언&lt;/span&gt;
    result = blind_spot

    &lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title function_&quot;&gt;min_blind_spot&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;field: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, cctv_list: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;, sight: &lt;span class=&quot;hljs-built_in&quot;&gt;dict&lt;/span&gt;, max_direction: &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;,
                       now_cctv: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, y_range: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt; = height, x_range: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt; = width,
                       limit_cctv: &lt;span class=&quot;hljs-built_in&quot;&gt;int&lt;/span&gt; = cctv_amount&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;:
        &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;&amp;#x27;&amp;#x27;
        CCTV를 모두 최적의 상태로 설치할 때 최소 사각지대 갯수를 확인하는 함수
        &amp;#x27;&amp;#x27;&amp;#x27;&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 결과값 전역 변수 등록&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;global&lt;/span&gt; result

        &lt;span class=&quot;hljs-comment&quot;&gt;# Back Tracking&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 모든 CCTV를 전부 확인한 경우&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; now_cctv == limit_cctv:

            &lt;span class=&quot;hljs-comment&quot;&gt;# 현재 사각지대 갯수 확인&lt;/span&gt;
            now_result = check_blind_spot(field, y_range, x_range)

            &lt;span class=&quot;hljs-comment&quot;&gt;# 기존 최소값보다 작은 경우 갱신&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; result &amp;gt; now_result:
                result = now_result

            &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt;

        &lt;span class=&quot;hljs-comment&quot;&gt;# 아직 확인하지 않은 CCTV가 존재하는 경우&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:

            &lt;span class=&quot;hljs-comment&quot;&gt;# 현재 확인할 CCTV 정보 확인&lt;/span&gt;
            cctv_idx, cctv_type = cctv_list[now_cctv]

            &lt;span class=&quot;hljs-comment&quot;&gt;# 좌표 분리&lt;/span&gt;
            y_cctv, x_cctv = cctv_idx

            &lt;span class=&quot;hljs-comment&quot;&gt;# CCTV에 종류에 따라 감시 방향의 경우의 수만큼 조사&lt;/span&gt;
            &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; direction_code &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(max_direction[cctv_type]):

                &lt;span class=&quot;hljs-comment&quot;&gt;# 현재 주시 방향 확인&lt;/span&gt;
                cctv_directions_now = sight[cctv_type][direction_code]

                &lt;span class=&quot;hljs-comment&quot;&gt;# 해당 주시 방향에서 볼 수 있는 좌표를 담을 리스트 선언&lt;/span&gt;
                now_view = []

                &lt;span class=&quot;hljs-comment&quot;&gt;# 깊이 탐색을 진행할 방향 설정&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; direction &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; cctv_directions_now:

                    &lt;span class=&quot;hljs-comment&quot;&gt;# 이동 방향 좌표 분리&lt;/span&gt;
                    move_y, move_x = direction

                    &lt;span class=&quot;hljs-comment&quot;&gt;# 초기 좌표 설정&lt;/span&gt;
                    now_y, now_x = y_cctv, x_cctv

                    &lt;span class=&quot;hljs-comment&quot;&gt;# 해당 방향에 대해서 반복 조사&lt;/span&gt;
                    &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;:

                        next_y, next_x = now_y + move_y, now_x + move_x

                        &lt;span class=&quot;hljs-comment&quot;&gt;# 사무실 범위를 벗어나지 않은 경우&lt;/span&gt;
                        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &amp;lt;= next_y &amp;lt; y_range &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &amp;lt;= next_x &amp;lt; x_range:

                            &lt;span class=&quot;hljs-comment&quot;&gt;# 벽을 만났다면 반복 종료&lt;/span&gt;
                            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; field[next_y][next_x] == &lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;:
                                &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

                            &lt;span class=&quot;hljs-comment&quot;&gt;# 벽을 만난 것이 아닐 경우&lt;/span&gt;
                            &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:

                                &lt;span class=&quot;hljs-comment&quot;&gt;# 해당 좌표가 사각지대일 경우&lt;/span&gt;
                                &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;not&lt;/span&gt; field[next_y][next_x]:

                                    &lt;span class=&quot;hljs-comment&quot;&gt;# 리스트에 기록 후 비사각지대 처리&lt;/span&gt;
                                    now_view.append((next_y, next_x))
                                    field[next_y][next_x] = &lt;span class=&quot;hljs-string&quot;&gt;&amp;#x27;#&amp;#x27;&lt;/span&gt;

                                &lt;span class=&quot;hljs-comment&quot;&gt;# 현재 좌표 갱신&lt;/span&gt;
                                now_y, now_x = next_y, next_x

                        &lt;span class=&quot;hljs-comment&quot;&gt;# 사무실 범위를 벗어났다면 반복 종료&lt;/span&gt;
                        &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
                            &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;

                &lt;span class=&quot;hljs-comment&quot;&gt;# 수집한 좌표들을 다음 CCTV에 조사&lt;/span&gt;
                min_blind_spot(field, cctvs, cctv_directions, max_direction, now_cctv + &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;)

                &lt;span class=&quot;hljs-comment&quot;&gt;# 초기화&lt;/span&gt;
                &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; y_idx, x_idx &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; now_view:
                    field[y_idx][x_idx] = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;

    &lt;span class=&quot;hljs-comment&quot;&gt;# 함수를 호출하여 결과 도출&lt;/span&gt;
    min_blind_spot(work_space, cctvs, cctv_directions, max_direction)

    &lt;span class=&quot;hljs-comment&quot;&gt;# 결과값 출력&lt;/span&gt;
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(result)

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>最初の投稿</title><link>https://www.traceoflight.dev/ja/blog/intro/</link><guid isPermaLink="true">https://www.traceoflight.dev/ja/blog/intro/</guid><description>このブログを始めた理由</description><pubDate>Sat, 22 Oct 2022 18:26:40 GMT</pubDate><content:encoded>&lt;p&gt;以前は、記録を個人的なものとして、自分だけが読めるように整理していました。&lt;/p&gt;
&lt;p&gt;しかし、それならわざわざきれいに整理する必要もないのではないかと思い、悩み始めました。そして、「きれいに整理して見やすい場所に掲載する」か「適当に書く」かの間で、見やすい場所に掲載することを選びました。&lt;/p&gt;
&lt;p&gt;勉強してまとめた内容が、私自身にとっても、そして万が一この記事を読むことになった他の誰かのためにも、役立つことを願っています。&lt;/p&gt;
</content:encoded></item></channel></rss>