最短コードで世界のナベアツ

今日大学で、友人から

某大学で、どれくらい短い Java のコードで世界のナベアツを再現できるか、というコンテストがあったらしいよ

ってことを聞いたので、俺もやってみようと思った。
1から40まで表示して、3の倍数と3のつく数字のときには、その数字の隣に「aho」を表示させる、というようにやってみた。
つまり

1
2
3:aho
4
(略)
38:aho
39:aho
40

ってなカンジに出力する。


俺の結果は以下のコード。132文字でした。

public class j{public static void main(String[] a){int i=0;while(i++<40)System.out.println(i%3*(i+"").indexOf(51)>=0?i+":aho":i);}}

空白も省略したせいで、相当読みにくい。.indexOf(51) は .indexOf('3') のことです。51にすることで一文字省略。
適宜にインデントしたコード*1は以下。

public class j
{
  public static void main(String[] a)
  {
    int i = 0;
    while (i++ < 40)
      System.out.println(i%3 * (i+"").indexOf(51) >= 0 ? i+":aho" : i);
  }
}

.indexOf() は、見つかったときにゼロ以上、見つからなかったときに-1を返すため、>= で判定することになってしまっている。
i+"" によって i を String にすることができることは、このコンテストがあったことを教えてくれた友人からのアドバイス
よくよく考えれば、いつも System.out.println(i + "hoge") とかやってたっけ。
俺は全然気づけずに Integer.toString(i) とかやってた。まぁこっちの方が普通にコーディングするときには使うべきなんだろうけど。


本題は Java だったけど、C でもチャレンジ。やはり Java より多く、163文字でした。

#include<stdio.h>
#include<string.h>
int main(){int i=0;char buf[4];while(i++<40){sprintf(buf,"%d",i);printf("%d%s\n",i,i%3*!strchr(buf,51)?"":":aho");}return 0;}

インデントしたものは以下

#include <stdio.h>
#include <string.h>
int main()
{
  int i = 0;
  char buf[4];
  while (i++ < 40) {
    sprintf(buf, "%d", i);
    printf("%d%s\n", i, i%3 * !strchr(buf, 51) ? "" : ":aho");
  }
  return 0;
}

main の引数を省略してるけど、きっと問題ないはず。
こっちの場合、strstr() が、3が見つかったときに非ゼロ(つまり真)、見つからなかったときにゼロ(つまり偽)を返すため、
! でその結果をひっくり返して、3の倍数でなくかつ3を含まない場合に論理積が真になるようにした。
こっちのほうが Java より判定部分が素直な気がする。

番外編

こういうときに、Perl を使うのは反則だろうなーと思いつつも Perl でも書いてみた。結果、46文字。恐るべし。

print $_,$_%3*!/3/?'':':aho',"\n" for(1..40);

say が使えればさらに省略できて

say $_,$_%3*!/3/?'':':aho' for(1..40);

39文字。
他の LL ではもっと短く書けたりするのかな?俺は Ruby とか Python はほとんど書けないからわからないけど。

*1:ってか、実際に最初にコーディングし終えたときのコード