また今年もAdvent of Codeのシーズンがやってまいりました。ブログに貼る画像をいつもどうしようかと困るのですが、今年はAIに作らせてみました。AI禁止ルールではありますが、ブログの画像は良いですよね?GoogleのNano Bananaちゃんに作らせたら、微妙にツールアイコンが似て非なるものが混じっているというのが面白いですね・・・。
さて、今年でAdvent of CodeをAlteryxで解きはじめて6年目です(最初の1年目とアカウントを変えてしまったので、記録は今年含めて5年分しか残っていませんが、そのうちサルベージしたいと思います)。
ちなみに、今年は一番古いAdvent of Codeを20日目までときました。その後忙しくて中途半端に残したままですが、そのうちチャレンジしたいところです。
3年連続で見事に★50個を達成していますが、今年は何個いけるでしょうか。そもそも今年はルールが大きく変わり、12日しか問題が出ないそうです(ということは★24?今年は年内に片付きそうですね!)。一体難易度はどうなってしまうのか、気になるところです。
※AOCの説明はこちら。
2025年のAOCも、Alteryx Communityでかなりお祭りムードになってきました(そういえば、Marveryx Communityってブランディングしていたのがいつのまに戻ってしまったのでしょうか)。今年もJoshuaがブログに書いてくれて盛り上げてくれています。昨年からコミュニティバッジが進捗に応じてもらえるようになりましたが、今年引き続き同様です。12日クリアのバッジを目標にがんばりましょう!!!
ということでさっそく1日目を見てみましょう。

Day 01「Secret Entrance」
タイトルは「秘密の入口」。
今年は12日間のパズルとなりましたが、なんとストーリー的にちゃんと理由付けされています。12月12日までに北極の飾り付けを終わらせなければならない、ということになっています。
1日目は、その北極基地に入るために入口のパスワードを求める問題です。
入力データは以下のようなLもしくはRの横に数字があるようなものです。
L68
L30
R48
L5
R60
L55
L1
L99
R14
L82
Lは左回り、Rは右回りに、数字の分だけダイヤルを回転させます。このときに、Part1は0に止まった回数、Part2は0を通過した数をカウントします。ダイヤル自体は0~99で、最初は50の位置にあります。
・ネ
・
・タ
・
・バ
・
・レ
Part1,2を解いてみる
Part1はダイヤル位置が0になった時が何回かカウントする問題なので、複数行フォーミュラツールで計算するだけですが、ダイヤルを回す時に100を超える数などもあるので要注意です。
まずは、インプットデータを処理できる形に持っていく必要があるので、今回は正規表現ツールで分割しました。以下のような正規表現で問題なく取得できると思います。
([L|R])(\d+)
次にダイヤルの位置を計算します。前の行のダイヤル位置に対して、回すダイヤルの数を方向がLならマイナス、Rならプラスします。この時に100を超えることがあるのでMOD100を取ります。左回りの場合はマイナスになることがあるので、100を足します。以下のような計算式を使っています。
IF IsNull([Row-1:dial]) THEN
IF [Dir]="L" THEN
IF 50-[Num]<0 THEN
Mod(50-[Num],100)+100
ELSE
Mod(50-[Num],100)
ENDIF
ELSE
Mod(50+[Num],100)
ENDIF
ELSE
IF [Dir]="L" THEN
IF [Row-1:dial]-[Num]<0 THEN
Mod([Row-1:dial]-[Num],100)+100
ELSE
Mod([Row-1:dial]-[Num],100)
ENDIF
ELSE
Mod([Num]+[Row-1:dial],100)
ENDIF
ENDIF
初期値の判断のために、IsNull([Row-1:dial])を使って判定し、Trueなら初期値としてダイヤルの位置に50を入れるようにしています。
Part1は0の数をカウントすればオッケーです(上記の式だと100が出ることがあるのであとから0にしています)。
Part2はいわば100で割って何回0を通過したかを出すだけといえば出すだけですが、左周りの時の処理が難しいです(いつもAoCでマイナス方向でMODをしないといけないときは悩んでる気がします)。
結果的には以下の計算式で対応しました。右回りは単に足して100で割るだけ、左回りは右回りのやり方に変換しています。左回りはMODしていますが、dial位置が0の時に100になってしまい余計にカウントしてしまうのでMODしています。
IF [Dir]="L" THEN
IF IsNull([Row-1:RecordID]) THEN
FLOOR((50+[num])/100)
ELSE
FLOOR((MOD(100-[Row-1:dial],100)+[num])/100) //dial位置が0の時のためにMODする
ENDIF
ELSE
IF IsNull([Row-1:RecordID]) THEN
FLOOR((50+[num])/100)
ELSE
FLOOR(([row-1:dial]+[num])/100)
ENDIF
ENDIF
これで何回0を越したか出るので合計したらオッケーです。

Part1は比較的さくっと解けたのですが、Part2でスタックしてしまいました。いや、初日からMODとか結構今年も意地悪ですね・・・(まぁ、AI対策なんでしょうけど・・・)。
まとめ
- 今年は・・・まぁ、苦手なところが出たのもありますが、難易度高いなーって思いました。
- 一度スタックするとだめですね・・・。今年はちょっと厳しい気がしますが、まぁ、ゆっくりやりましょう!12月中に12日分全部クリアできたらオッケーってことで・・・。


コメント