『正規表現でどう書くの?』ひねくれた別解
(※ジョーク記事です。)
問題及び模範解答
増井雄一郎(@masuidrive)さんの「正規表現でどう書くの?」問題解説記事 #正規表現|CodeIQ MAGAZINE より:
(引用ここから)
問題
Perl、Rubyの最新版でサポートしている正規表現を利用して、下記の条件にマッチするようにア、イ、ウを埋めて下さい。
正規表現: “123456″ =~ /([0-9]+ア
)/
条件: $1 == “1″
正規表現: “123456″ =~ /(イ
[0-9]+ア
)([0-9]+)/
条件: $1 == “23456″
正規表現: “123456″ =~ /123(ウ
45)4/
条件: マッチする
正規表現: “123456″ =~ /123(ウ
45)6/
条件: マッチしない
解答
ア:?
イ:?:
ウ:?= (もしくは、?<!)
(引用ここまで)
(まともな)別解現る
(イ)「?>」が不正解な理由は? http://t.co/VY9vNKfIcz /増井雄一郎(@masuidrive)さんの「正規表現でどう書くの?」問題解説記事 #正規表現|CodeIQ MAGAZINE https://t.co/RUbszlfLOw @codeiqさんから
— カニ戯(ry (@bananawani_mc) 2014, 10月 6
ひねくれた別解
私も別解を考えてみました。方針としては、模範解答がいずれも「?」を含んでいるので、「?」を使わない方向で。
ア:A|1*
イ:23456)( もしくは \B.*)(
ウ:|A
Ideone で実行:
http://ideone.com/nZojmy
どうだエヘン!
ちなみに、動作確認は Perl でのみ行っています。 Ruby のことは知りません。
以下、一応説明です。
1つ目の式:
“123456″ =~ /([0-9]+A|1*)/
説明:「A」は、文字列に現れない文字なら何でもいいのですが、ともかくこれで | の左側はマッチしないのでキャンセルできます。結局 $1 は 1* にマッチする "1" になります。
2つ目の式:
“123456″ =~ /(23456)([0-9]+A|1*)([0-9]*)/
説明:$1 == "23456" になるようにするのですから、先頭に (23456) と書いてしまうのが素直な書き方というものです(多分ね!)。ちなみに $2 と $3 には空文字列がマッチします。
3つ目・4つ目の式:
"123456" =~ /123(|A45)4/
"123456" =~ /123(|A45)6/
説明:これも「A」はほぼ何でもよく、 | の右側をキャンセルしています。これで、上側の式は "1234" の部分がマッチしますが、下側の式はマッチしません。
『第6回デスマコロシアム』に参加しました
デスマコロシアムとは(テンプレート)
大雑把に説明すると、
- 問題文で与えられたある文字列を出力するコード(プログラム)を提出する。
- 言語は ideone で利用可能なものから選ぶ。
- コードのサイズが短いほどよい。(1文字につき1点減点)
- 同じ言語を選択した人が少ないほどよい。(1人につき10点減点)
- その他、コーディングとは無関係な運の要素も加えて、トーナメントで競う。
といった感じです。要するに、コードゴルフに運の要素を加えたトーナメントです。
第6回の問題
今回の出力は
2:3:5:7:11:13:17:19:23:29:31:37:41:43:47:53:59:61:67:71:73:79:83:89:97:101:103:107:109:113:127:131:137:139:149:151:157:163:167:173:179:181:191:193:197:199:211:223:227:229:233:239:241:251:257:263:269:271:277:281:283:293:307:311:313:317:331:337:347:349:353:359:367:373:379:383:389:397:401:409:419:421:431:433:439:443:449:457:461:463:467:479:487:491:499:503:509:521:523:541:547:557:563:569:571:577:587:593:599:601:607:613:617:619:631:641:643:647:653:659:661:673:677:683:691:701:709:719:727:733:739:743:751:757:761:769:773:787:797:809:811:821:823:827:829:839:853:857:859:863:877:881:883:887:907:911:919:929:937:941:947:953:967:971:977:983:991:997
という文字列です。997以下の素数を ":" で区切ったものになっています。ちなみに、私の出題予想はフィボナッチ数列でした。
今回は算術系な気がする… フィボナッチ数列とか “@tbpgr: 第6回デスマコロシアムは明日の朝受付開始です #デスマコロシアム #CodeIQ”
— 齊藤 (tails) (@saito_ta) 2014, 8月 25
素数列も一瞬頭をよぎったのですが、言語によっては素数が組み込みで用意されていて単に出力するだけになってしまうので、まあ無いだろうと思って脳内却下したのですが…
ちなみに期待していた言語はPARI/GPでした。
— tbpgr | peco | cat (@tbpgr) 2014, 8月 26
というか、むしろ Perl を除け者にするための問題としか思えないのですが!
私が提出した解答
1. Perl (45)
今回もPERLerの本気が見られるのを期待+(0゚・∀・) + #コードな情報戦 #デスマコロシアム
— カニ戯(ry (@bananawani_mc) 2014, 8月 26
期待されては、本気を見せざるを得ません。本気の Perl (45) を提出しました。
$,=":";print grep+(1x$_)!~/^(11+)\1+$/,2..999
正規表現で素数判定するコードです。具体的には、2~999の範囲の整数 $_
が素数かどうかを判定するために、 1x$_
で 1 を n 個並べた文字列を作り、その文字列が 2 文字以上の文字列の 2 回以上の繰り返しになっているかどうかを判定しています。ちなみに、私が最初にこの方法を知ったのは、 tybalt89 さんのこのコードです。感動したのを覚えています。
http://golf.shinh.org/reveal.rb?Gaussian+Prime/tybalt89_1323996492&pl
第6回デスマコロシアム(http://t.co/52r9L6nNd1)。やはりPerlが強い。「持たざるもの」の中では圧倒的 #デスマコロシアム #CodeIQ
— tbpgr | peco | cat (@tbpgr) 2014, 8月 27
2. Perl (44)
Perl (45) は本気のコードのはずだったのですが、翌日になって見直してみたらあっさり縮んでしまい、 Perl (44) を提出しなおしました。素数判定の方法は同じです。
print 2,map":$_"x(1x$_)!~/^(11+)\1+$/,3..999
なお、同日に Octave (26) を提出したため、この Perl (44) は集計に反映されませんでした。
3. Octave (26)
この時点での集計では Octave (27) が最短でした。最短賞狙いの私としては、早速試してみたのですが、リファレンスとにらめっこしつつどう書いても (34) より短くなりません。
printf("%d:",primes(991));disp 997
ヒントを求めていろいろやっている中、 Google で「octave delimiter」で検索してみたところ、このようなページが見つかりました。
GNU Octave: Simple File I/O
これぞ求めていた情報です!
dlmwrite(1,primes(999),58)
dlmwrite という関数は、指定した区切り文字を用いて出力するという、まさにこの問題のために存在するような関数です。短くならないわけがありません。ていうか、このコードは (26) なので、最短更新です。喜び勇んで提出しました。
この後しばらく、最短は Octave (26) で動きがなく、今回の最短コードはこれで決まりかと思われたのですが…
4. Perl (5)
とある言語で、デスマコロシアムのQAページに記述されている細則を利用して文字数を稼いでいる賢い解答者の方がおられますが、これ活用するとトップが変わるような・・・ #デスマコロシアム
— tbpgr | peco | cat (@tbpgr) 2014, 9月 7
と、トップが変わるですと!?
第6回デスマコロシアム(http://t.co/52r9L6nNd1)。全言語中最小文字数はRub(22)が1名になりました。 #デスマコロシアム #CodeIQ
— tbpgr | peco | cat (@tbpgr) 2014, 9月 10
本当だ! しかも、よりによって Ruby ですか! Ruby は触ったことがないので、さっぱりわからりません(ゴルフで Ruby が Perl より有利になることなんて滅多にないのでスルーし続けてきました)。困った…。
ところで、細則を利用して賢く文字数を稼ぐって、どういうことでしょうね? 短縮に使えそうな細則といえば、モジュールのインポートくらいでしょうか。モジュールを賢くインポート… って、もしかして、 Perl で書けば、こういうこと!?
use 5.01;
use constant a,"2:3:5:7:11:13:17:……中略……:991:997";
say a
1行目はひとまず置いておくとして、2行目は constant.pm というモジュールをインポートしていますが、(当時の)細則によればこれは文字数にカウントされません。結局、このコードの長さは、3行目だけがカウント対象なので (5) になってしまいます。
まあ、当然のごとく、この解答は却下され、モジュールのインポートの際にパラメータを渡した場合には文字数にカウントするというルールが整備されることとなりました。
5. Ruby (22)
どうやら最短を目指すためには Ruby を書かなければならないようです。 Ruby には手を出さないというアイデンティティと、デスマコロシアムは最短賞・最小賞を獲りに行くというアイデンティティとが、激しくコンフリクトしています。まあ、少しやってみて駄目だったら諦めるということで…
Ruby での短縮ということで、まず思ったのが goruby です(こんなことだけは知っている)。 goruby 自体はコマンドですが、モジュールとしては golf_prelude.rb というものになるようです。しかし、このモジュールは Ideone にはインストールされていないようです。
ということは、別のモジュールでしょうか。とりあえず Ruby の標準モジュールを片っ端から見て回ることにします。何せ Ruby を触るのはほぼ初めてなので、どのようなモジュールがあるのかさっぱり知らないのです。 CSV モジュールとかは Octave の dlmwrite に似ていて怪しい気もしますが、どうもコンマ区切り専用のようで、使えそうもありません。むむ…
まあ、とりあえずモジュールのことは置いておいて、普通に書いてみましょうか。ええとなに、 Prime は Enumerable で Object なのか。さっぱりわからんが、こんな感じ?
require 'prime'
$><<Prime.take(168)*?:
おや!? 普通に (22) で書けてしまいました! うわ、モジュールのドキュメントをひたすら読みまくったあれは一体何だったんだ…
生まれて初めて Ruby ゴルフやった。 #デスマコロシアム
— 齊藤 (tails) (@saito_ta) 2014, 9月 14
結果
Ruby (22) でなんとか無事に最短賞を獲得できました。デスマコロシアムでの最短賞・最小賞は、これで5回連続5回目です。おめでとうございます。ありがとうございます。せっかくなので、これからもトーナメントそっちのけで最短賞・最小賞を狙っていきたいと思います。
『ワンライナーでクールに解く!』所感(ネガティブ注意)
はじめに
CodeIQ で『ワンライナーでクールに解く!』と題した2問の出題に解答してみました。どちらも、与えられた問題の答えを解くためのワンライナーを書けという問題です。「解答評価のポイント」は「冗長さをそぎ落とし、どれだけ簡潔に問題を解決できているかが評価のポイントとなります。」とのことです。(この「解答評価のポイント」は、次のリンクから読むことができます。)
挑戦者求む!【プログラミング】ワンライナーでクールに解く!その1 by 無形ソフトウェアLLC 代表社員:村山 男也│CodeIQ
挑戦者求む!【プログラミング】ワンライナーでクールに解く!その2 by 無形ソフトウェアLLC 代表社員:村山 男也│CodeIQ
その1
問題
「一番大きいマトリョーシカの中に、6つの少しずつ小さなマトリョーシカが入って10500円で売っています。(マトリョーシカは全部で7つです。) マトリョーシカはひとつ大きくなるにつれて、150円ずつ値上がりします。一番小さなマトリョーシカの値段はいくらですか?」
要するに、等差数列の総和が与えられたときの初項を求める問題です。
私の解法
真ん中の大きさ(小さいほうから4番目)のマトリョーシカが 10500 / 7 円なので、それより3つ小さい一番小さなマトリョーシカは 10500 / 7 - 150 * 3 円です。これを Perl ワンライナーで素直に書くと、
perl -e 'print 10500/7-150*3'
となります。これが私の解答です。これ以上、複雑になりようがありませんね。逆に、これ以上簡単にしようとすると単に答えを表示するだけになってしまうので、まあこんなもんでしょう。
評価結果
評価は「4」でした。
今回はプログラム言語のワンライナーというカテゴリーですので、 ループ処理や組み込みのリスト演算などをクールに使用している 回答者様に高得点を差し上げております。ご了承いただければ幸いです。
とのことで、「高評価を獲得した解答例」として示されていたのが、次のコードです。
perl -e 'for($n=10500,$i=0;$i<7;$n-=150*$i++){}print $n/7'
…へ?
まあ確かにワンライナーですが、なんというか、普通のスクリプトから改行を機械的に取り除いただけですよね。
ていうか、「冗長さをそぎ落とし、どれだけ簡潔に問題を解決できているかが評価のポイント」じゃないんですか? 上記の「高評価を獲得した解答例」は、むしろ可能な限り複雑に書いてあるようにしか見えないんですが。
まあ、どのようなコードを「クール」と感じるかは人それぞれなのでそれはいいのですが、評価基準を示した以上、それに従って評価してもらわないと困ります。これではただの価値観の押し付けです。ともあれ、この問題や評価からは、出題意図がさっぱり見えてきません。
その2
問題
「1個の値段が40円、50円、77円の品物を合わせて11個買ったところ、代金が601円になりました。それぞれ何個ずつ買いましたか?」
私の解法
これは非常に困りました。ワンライナーで書くのに適したような簡単な解法を思いつかなかったからです。
ところで、「解答評価のポイント」には、「変数名などにキラリと光るネーミングセンスを感じるものなどは、高評価につながります。」とも書いてあります。そこで、変数名(の扱い)に趣向を凝らして、こんなコードにしてみました。
perl -e '@a=(50,40,77);$n50=11;do{$total=0;$total+=$_*${n.$_}for@a;++${n.$a[$cond=$total<=>601]};--$n50}while$cond;print"$_=>${n.$_}\n"for@a'
到底ワンライナーと呼べるような代物ではありませんが(それこそ改行を機械的に取り除いただけ)、簡単な解法を思いつかないので、仕方ありません。しかも、趣向を凝らしたせいで、可読性もさっぱりです。
評価結果
Perlの特徴を思う存分に発揮されており、文句なしの「5」評価です。
なんと、気に入られてしまいました。どうも、こういうコードが「クール」なようです。どうも私とは価値観が正反対です。
まとめ
結局、この出題者は、どのような意図でこれらの問題を出し、解答者に何を求めたかったのか、さっぱりわかりません。
CodeIQ では、以前にもひどい問題が出されたことがありますが(ボゴソートの計算量のやつとか)、 CodeIQ の中の人は、もっと問題や評価の質に気を配るべきだと思います。出題の質が低下したときに、最初に離れていくのは、スキルの高いユーザです。自分よりレベルが低い(と感じる)出題者から評価を受けようなどと思う人はいませんから。つまり、 CodeIQ の存在価値を維持し高めていくためには、出題の質は非常に重要だということです。
誕生日
誕生日
誕生日でした。ある意味、今までで一番賑やかな誕生日だったように思います。
もしかして:モテ期到来?
「2014/9/10に追記」で気付いたけど、今日俺の誕生日だw “@tbpgr: Q11に説明追加 #デスマコロシアム #CodeIQ http://t.co/HEuW86HD3p”
— 齊藤 (tails) (@saito_ta) 2014, 9月 9
あ、今日、誕生日だ。と思って何となくつぶやいたのです。そしたら、
デスコロ参加者各位。Perlゴルフ神 @saito_ta 様が誕生日だそうです。 #デスマコロシアム #CodeIQ
— tbpgr | peco | cat (@tbpgr) 2014, 9月 9
いや、神だなんて! 私は、ただ、短くて、小さいだけです。私がというか、私のが。それを、なぜかみんな褒めてくれるんです。
お祝いコード
お祝いコードをいただきました。
@saito_ta http://t.co/kZyMG6JhHZ #codeiq @tbpgr
— しえる (@cielavenir) 2014, 9月 9
いきなり Lazy-K ですね。以前、誰かが確か「Lispがバイナリダンプのような言われようだ」と言ったのに対して「バイナリダンプがSKIコンビネータのような言われようだ」と返したのを思い出します。ていうか、 Lazy-K は私が挫折した言語の一つです。素晴らしいです。ありがとうございます!
@saito_ta 改めまして、誕生日おめでとうございます。http://t.co/nvX5IRABIh
— tbpgr | peco | cat (@tbpgr) 2014, 9月 9
ありがとうございます! ていうか、なぜ修造w
それにしても、皆さん難解言語好きですねw
@cielavenir print("ありがとうございます!¥n"); ←ひどいやっつけw
— 齊藤 (tails) (@saito_ta) 2014, 9月 9
↑これではあんまりなので、私も難解言語で返事を書いてみました。
00607988772869385095152818394450817988297758363+9*+P1^6?77*3-c
Hack VM という処理系用の言語です。
Hack VM - A Virtual Machine for Hackers
実行方法は、↑このリンクのページの「Enter your code here」の所に上のコードをコピペしてから「Run!」を押してください。(コードに改行や余分な文字が入るとエラーになるので注意!)
お祝いメッセージ
コード以外にも、多数のお祝いメッセージをいただきました。本当にありがとうございます。
@saito_ta お誕生日おめでとうございます!
— tbpgr | peco | cat (@tbpgr) 2014, 9月 9
@saito_ta お誕生日おめでとうございます。
— suppy(すっぴー) (@suppy193) 2014, 9月 9
@tbpgr @saito_ta 神さま、お誕生日おめでとうございます
— нiяоко iп пеtщоякs (@millionsmile) 2014, 9月 9
@saito_ta お誕生日、おめでとうございます! RT @tbpgr: デスコロ参加者各位。Perlゴルフ神 @saito_ta 様が誕生日だそうです。 #デスマコロシアム #CodeIQ
— CodeIQ [コードアイキュー] (@codeiq) 2014, 9月 10
なんと CodeIQ 公式さんまで!
@saito_ta Constant.pm wwww お誕生日おめでとうございます
— べーにー (@jczni) 2014, 9月 10
constant.pm の件は反省しておりますですw
年齢
@saito_ta こちらこそ今年もよろしくお願い致します(?)これで、年齢が素数だったら面白いのですが。
— tbpgr | peco | cat (@tbpgr) 2014, 9月 9
— 齊藤 (tails) (@saito_ta) 2014, 9月 9
(説明:「今日俺の誕生日だ」ツイートは、素数に関する問題を出題中の『第6回デスマコロシアム』のQAを受けてのものなので、「年齢が素数だったら面白い」わけです。しかし実際には素数ではなく3の倍数なので、「Fizz歳」と返しました。具体的な年齢・年代を一切明かさずに素数でないことを端的に示すのみならず、ちょうど前回の『第5回デスマコロシアム』が FizzBuzz 問題だったのでタイムリーな表現になっています。)
2D マップ上の最短パスを求める新しいアルゴリズム S* の提案
はじめに
ゲームのキャラクタを自動で移動させる場合などに、 2D マップ上の2点間の最短パスを求めることが行われます。
典型的なやり方としては、マップを格子状のマス目に分割し、マス目ごとに通れるか通れないかを決定しておき、キャラクタの現在地である開始点と、目的地となる終了点との2点間のパス(経路)を A* アルゴリズムで求める、という方法が一般的かと思います。
しかし、マップをマス目に分割するのは、本当に必要なことなのでしょうか? もっと直接的に、幾何学的な最短パスを A* で求めればいいのではないでしょうか? ちょっと実装して実験してみました。
デモ
未署名の Java アップレットですすんません。 Java の設定でセキュリティを下げて実行してくださいすんません。
線の色は、パスの長さを表しています。パスが切り替わったときにも線の色が不連続には変化していないことから、等しい長さのパスの間で切り替わっていることが確認できます。
2点を変化させながらリアルタイムに探索していますが、 CPU をほとんど使っていないことがわかります。
S* アルゴリズム
上のデモで実装したアルゴリズムを、とりあえず「S*」と呼ぶことにします。「 Saito の A*」 の略です。単純なアルゴリズムなので、考え付いたのは私が最初というわけでもないでしょうし、既にちゃんとした名前があるようにも思いますが、知りません。
アルゴリズムの内容は、上のデモから一目瞭然なのですが、次のような感じです。
準備
- マップ上の障害物を、多角形で近似する。(上のデモでは、障害物の形状自体を三角形にしています。)
- 多角形の頂点同士を結ぶ線分のうち、多角形の内部を通過しないもののリスト(頂点間リスト)を作成する。
探索
- 頂点間リストに、開始点と終了点を一時的に追加する。
- 開始点から終了点に向かって、頂点間リストに A* アルゴリズムを適用する。このとき、 A* のヒューリスティック関数には、終了点までのユークリッド距離を用いる。
以上です。とてもシンプルですね!
マス目 A* との比較
従来の探索方法を、ここでは「マス目 A* 」と呼ぶことにします。
S* の利点
- マス目に分割する必要がない。(マス目 A* では、マス目の分割のパラメータ(特にマス目の大きさ)で探索結果が変化しうるが、 S* はそのようなパラメータの影響がない。)
- 常にユークリッド距離での最短パスが求まる。(マス目 A* では、通過するマス目の数が最小になるようなパスが求まるが、必ずしもユークリッド距離で最短とはならない…ですよね?)
- パスが最初から折れ線で求まるので、折れ線化するための後工程が不要。(マス目 A* では、折れ線化が必要。)
S* の欠点
- 見晴らしの良い広大なマップでは、頂点間リストを素朴に作ると、遠くの多角形同士の頂点間で無駄に多い線分が頂点間リストに登録されるので、工夫が必要。
- 移動する障害物が多数あるような場合には不向きかも。
- ていうか、実際のゲームなどのアプリケーションで試したことがないので、本当に実用に耐えうるのか疑問。誰かやってみてください!
S* アルゴリズムの利用について
S* アルゴリズムに関しては、私は、何らの主張もしません。しかし、他者が特許を取っている(またはこれから取る)可能性などについては関知しませんので、その点は自己責任でお願いします。
デモアプレットについては、著作権を主張します。 All rights reserved です。ていうか、突貫で作ったウンコードなので恥ずかしいから解析するな、ってことです。
『第5回デスマコロシアム』に参加しました
はじめに
『第5回デスマコロシアム』に参加しました。
「第5回デスマコロシアム」問題のトーナメント結果発表です!──優勝者は…! #デスマコロシアム|CodeIQ MAGAZINE
要は FizzBuzz ですが、15の倍数のときは大文字の FIZZBUZZ にするというのが特徴です。
問題を読んで、とりあえず書いた Perl (51文字) のコードに「とりあえず」とだけコメントを付けて、とりあえず提出しました。後で日々の集計を見て、短く書けそうな言語で再提出するつもりでした。「とりあえず」のコードは、暫定の全言語最短になりました。
第5回デスマコロシアム(http://t.co/5Bwq4clHQs)。全言語中最小文字数はPerl(51)が1名になりました。 #デスマコロシアム #CodeIQ
— tbpgr | peco | cat (@tbpgr) 2014, 7月 23
毎度Perlerの本気にはチビらされるなぁ RT @tbpgr 第5回デスマコロシアム(http://t.co/Hd0xCknbXW)。全言語中最小文字数はPerl(51)が1名になりました。 #デスマコロシアム #CodeIQ
— カニ戯(ry (@bananawani_mc) 2014, 7月 23
— ニクモ (@nikumo) 2014, 7月 23
ところが、それから何日経っても記録が更新されず、帯状疱疹を患って入院したり退院したりしているうちに締め切りを迎えました。結局、「とりあえず」のコードのまま最短賞をいただきました。チャンピオンバッジは、これで4回連続4個目です。(「決勝進出おめでとうございます!」と書いてあるのですが、決勝どころか準決勝にすら進んだことがない私が4個も持っていていいのかという妙な背徳感が…)
コード
print$_%5?$_%3?$_:fizz:$_%3?buzz:FIZZBUZZ for 1..50
Perl (51文字) です。5の倍数かどうかで場合分けし、それぞれの場合を3の倍数かどうかで場合分けするという、なんの工夫もないコードですが、これで実際に最短賞が取れてしまったので仕方ありません。
ちなみに、15の倍数のときが小文字の fizzbuzz ならば工夫の余地があって、 Perl で 45 文字で書けますので、挑戦してみてください(ググる前に!)
『3番目のダンジョン』私の解答
テンプレ
この問題(に限らずダンジョンシリーズ)の面白いところは、定められた文字数制限と使用禁止文字列を満たす JavaScript のコードを提出すれば正解となってバッジが付与されるのですが、実際には場外(Twitter とか CodeIQ MAGAZINE とか)で出題者様主導で解答コードの短さが競われているのです! いわゆるコードゴルフです。このことは問題文には一切書かれていなくて、バッジほしさに適当に解答を送ると、知らずにコードゴルフに引きずり込まれるという、恐ろしい罠が仕掛けられているのです!
はじめに
今回の問題は、相異なる5個の数値 a, b, c, d, e が与えられたときに、3番目の大きさのものを求める、というものでした。具体的な問題は、解説記事をご覧ください。
解説記事(CodeIQ MAGAZINE)
https://codeiq.jp/magazine/2014/08/14753/
今回もいつものように、途中経過を見ながら縮めていこうと思って、とりあえず様子見でコードを提出したのですが、いつもと違って途中経過の発表がほとんどありませんでした。いぶかしく思っているうちに、帯状疱疹を患って入院してしまい、入院中に締め切りとなってしまいました。しかし、蓋を開けてみると、とりあえず提出したコードがそのまま最短コードになっていました。途中経過の発表がほとんど無かったのは、そもそも動きがほとんど無かったからのようですね。
LV2の私のコード
(a<b)-(a>c)^(a>d)-(a<e)?arguments.callee(b,c,d,e,a):a
53文字です。コードゴルフでは忌み嫌われる優先順位の括弧が、なんと4組も使われています。しかし +
と /
が使用禁止なので、まあ仕方ないところです。
(a<b)-(a>c)^(a>d)-(a<e)
の部分がやや解りにくいですが、 ^ の両辺を表にすると次のようになります。
条件 | (a<b)-(a>c) の値 |
---|---|
a < b,c | 1 |
b < a < c | 0 |
c < a < b | |
b,c < a | -1 |
条件 | (a>d)-(a<e) の値 |
---|---|
d,e < a | 1 |
d < a < e | 0 |
e < a < d | |
a < d,e | -1 |
この表から、 a の大きさが3番目のときに限り (a<b)-(a>c)^(a>d)-(a<e)
が 0 になることがわかります。
LV2の私の面白コード
上記のような経緯のため提出はしませんでしたが、私の考えた面白いコードです。
f=Math.min,-f(-f(a,b,c),-f(a,b,d),-f(a,b,e),-f(a,c,d),-f(a,c,e),-f(a,d,e),-f(b,c,d),-f(b,c,e),-f(b,d,e),-f(c,d,e))
114文字です。 -f()
だけで答えを求めています。