Advent of CodeをAlteryxでやってみる2025_9日目

Advent of code

Advent of Codeをデータ分析ツールAlteryxでやってみるシリーズ、2025年9日目です。

※過去記事はこちら。AlteryxユーザーのためのAdvent of Codeの始め方1日目2日目3日目4日目5日目6日目7日目8日目

Day 9「Movie Theater」

タイトルは「映画館」。

遊び場から消防士が使うようなポールを使って下の階に降りたようです。今度は床のタイルの張替えをしているようです(映画館の模様替えとのこと)。

赤いタイルがどこにあるのか、というのをX、Y座標で示すリストがあります。

7,1
11,1
11,7
9,7
9,5
2,5
2,3
7,3

赤いタイルを#、その他を「.」とすると、以下のようになります。

..............
.......#...#..
..............
..#....#......
..............
..#......#....
..............
.........#.#..
..............

上の#の赤いタイルは2つ選択して長方形を作ることができます。Part1では、最も面積が大きく取れる2つの長方形を見つけ、面積を計算することです。

Part2は、、、赤いタイルは上下左右の直線上に配置されたもの同士で接続できます。

..............
.......#XXX#..
.......X...X..
..#XXXX#...X..
..X........X..
..#XXXXXX#.X..
.........X.X..
.........#X#..
..............

つまり、上のようになります。

この範囲内に含まれるPart1で出した長方形のうち、最も面積の大きな長方形を発見し、その面積がPart2の答えとなります。

・ネ

・タ

・バ

・レ

Part1、2を解いてみる

正直、Part2のオリジナルの問題文がよくわからずずっとやってたんですが、問題文でミスリードを誘う(というか、AIを混乱させる?)感じですね・・・。

さて、Part1は5分で完了する問題です。

すべてのポイントの組み合わせを作り、面積を出して一番大きいものを算出すればオッケーです。面積は、単純に差分を取り、ABS関数で正にして1を足したものを掛け算します。

(ABS([x]-[Source_x])+1)*
(ABS([y]-[Source_y])+1)

ワークフローとしては以下の通りシンプルです。

次に、Part2が厄介です。基本的には、、、空間ツールで処理するのが楽かと思います。

外側のポリゴンを作り、それが各ポイントを組み合わせた四角形がその外側のポリゴンの中にあるかどうかを判定する必要があります。

各ポイントのポリゴンを作るのは簡単です。Part1の時点でできているので・・・。

それほど対したことはしていないですね・・・。

次が、外側のポリゴンです。

今回は、直線上に乗ってくるポイントをまず計算し、各相棒を作ります。これは単純な計算で求められます。Part1で作った対角線情報の組み合わせのうち、以下のようにX軸もしくはY軸が一致するものを取得します。

[x]=[Source_x]
OR
[y]=[Source_y]

あとはこの組み合わせに対して一つの大きなポリゴンを描くだけです。まぁ、ここが一番のポイントなのですが・・・。

今回は上の計算で求められたポイントの組み合わせでラインを作り、隣接するラインを求めるマクロを作りました。これで、ラインの順番が並び替えられます。しかしながら、ラインの中身(始点と終点)の順番は作ったときのものがそのまま採用されるので、このままだとポイントにしたときに並びません(大きい一つのポリゴンにするために、ポイントに分割して、並び順を指定する必要があります)。

結構な力技ですが、以下のように隣接するラインを上から順に並べ、x(項目名は0)とy(項目名は1)が前の行と異なるように、始点もしくは終点を選択するような数式を複数行フォーミュラで組み立てました。

IF IsNull([Row-1:newpoint]) THEN 
 IF [0]=[Row+1:0] THEN [1]
 ELSEIF [1]=[Row+1:1] THEN [0]
 ELSEIF [0]=[Row+1:1] THEN [1]
 ELSEIF [1]=[Row+1:0] THEN [0]
 ELSE Null() ENDIF
ELSE
 IF [0]=[Row-1:0] THEN [0]
 ELSEIF [1]=[Row-1:1] THEN [1]
 ELSEIF [0]=[Row-1:1] THEN [0]
 ELSEIF [1]=[Row-1:0] THEN [1]
 ELSE Null() ENDIF
ENDIF

これで、ポイントのシーケンス番号が求められたので、あとはシーケンスポリゴンで大きなポリゴンを作成します。

マクロ:

最後に、マッチングをかけていきます。大きなポリゴンの内側に来る四角形を探しますが、なぜかはみ出たものが出てきたので、Intersectで重なりポリゴンを作成し、重なりポリゴンと元のポリゴンが同じ面積の四角形の中で、最大の面積を持つものを取り出しました。

ワークフロー全景です。

ネタバレ

コミュニティやらWhatsAppなどで聞いたあと見てみたのですが、問題文に元の提示されたポイントのリストはそのままの並びで書けばポリゴンになる、ということでした。これにより、以下のようなポリゴンがかけるので、、、

この範囲内にある一番大きな四角形を選べば良い、という話だったようです。これにより、元々のワークフローは以下のように短縮されます。

まとめ

  • Part1は5分で終わるのに、Part2は時間切れで延長線的な感じでした(打ち合わせとかでしばらくできなかった)
  • いつかどこかで見たような問題なのですが、うまく処理しきれなかった感じです。もっと効率良くできる気がするんだけどなぁ・・・無理なのかしら・・・。

コメント

タイトルとURLをコピーしました