Skip to content

第5回東大京大コードゴルフ大会 Writeup

sh-mug edited this page Jun 28, 2019 · 155 revisions

お題

東京から京都までの道路を建設せよ

入力

  • 1行50文字の文字列が複数行与えられる。
  • それぞれの文字は2次元空間上のデカルト座標における格子点を表す。
    • ここで書字方向をx座標、段落方向をy座標とする。
  • 入力に含まれる文字は、空白、改行、TK のいずれかである。
  • 入力中には、必ず T が1回のみ1行目に、K が1回のみ最終行に出現する。
    • これらの文字はそれぞれ東京の地点と京都の地点を表す。
  • 入力の最後には改行が付与される。

出力

この空間において上下左右の4方向に同じコストで移動することができるとき、東京から京都までの最短経路を探索し、図示して出力せよ。

  • 入力と同じ書式を用いて、東京と京都を結ぶのに必要な点を空白以外の文字で、それ以外の部分を空白で表現せよ。
    • ここで空白以外の文字とは、ASCIIの印字可能文字のうち空白を除くすべての文字を指す。
  • 必要な経路以外の点を空白以外の文字で表してはならない。
  • 最短でない経路を出力してはならない。
  • 不要な場所に空白が出力されている、改行手前の空白が存在しないなどの空白文字の過不足は、出力において正常に経路が示されている限りにおいて許容される。

制約

  • 入力の行数sは 3 <= s <= 50 を満たす。
  • 東京のx座標をTx、京都のx座標をKxとして、以下の制約を満たす。
    • 10 <= Tx < 50
    • 0 <= Kx < Tx - 3
      • 特に京都のx座標は東京のx座標より必ず小さいことに留意せよ。

一般的なテクニック

出力の成形方法

  • 1行目を(行数-1)回コピーした後、最終行を出力
  • Tのx座標を記憶し、すべての行のTのx座標に文字を代入。最終行はKとTの間を埋める。
  • 1文字ずつ読んでいき、Tのx座標を記憶。最終行はKが来たらフラグを立てTのx座標に来たらフラグを折る。

目次

05AB1E (@dnek_, 27 bytes)

|¤' ÜUć'TkXg->D∍X?,vX,
|   入力全部取る(行ごとの配列が入る)
¤   aをpopせずにaのlastをコピー
'   空白 push(アポストロフィと空白の2バイト)
Ü   a, b取ってaの右側のbをtrim
U   変数Xに代入
ć   a取ってa[1:], a[0]
'T  'T' push
k   a, b取ってa.indexOf(b)
X   変数X push
g   長さ取る
-   引き算
>   インクリメント
D   dup
∍   a, b取ってaを長さbまで伸ばす/縮める(伸ばすときはパターンの繰り返しになる)
X   X push
?   改行なし出力
,   改行出力
v   enum map(今回indexもitemも使ってないけど)、閉じ括弧は省略
  X   X push
  ,   改行出力

一番のポイントはだろう。

05AB1Eには印字可能な1字をpushするコマンドがないので大抵'Kとかしないといけない。

特に文字列repeatをしたい場合иで文字のリストを作った後Jでjoinするのが愚直だが、иは長さをpopしてから文字列をpopするので、長さが先にスタックされている場合'Kの後sでスワップしてからになるため'KsиJと6bytesも使ってしまう。

次にÅ0とか(Å9まである)は長さnの0のリストを作るので、Å0Jで4bytesである。

そしてはパターンpop、長さpopをしてパターンを長さに合わせて伸長/短縮するのだが、普通に考えればиと同じくスワップしないといけないので、'Ks∍で5bytesである。

だがはパターンに整数を渡しても勝手に文字列に変換してくれるため、長さをdupしておけばなんとD∍の3バイトで済む。 今回のテストケースでは長さ13だったので1313131313131のようになった。

2sable (@drafear, 27 bytes)

I|¤ðÜrsgF=}'TksD?g-Å9J?

2sableは実質05AB1Eなので自チームが持っていた05AB1Eのコードを貼り付けた。

ABC (@n4o847, 96 bytes)

WHILEe>0:
	READsRAW
	FORjIN{1..50}:
		IFs@j>"S":PUTjINt
		IFs@j>"J":PUTjINk
	WRITE 10**(t-k)>>t/
  • 1行入力しか無いので、行ごとに TK の位置を調べる方針。1行目で tk、最終行で k が更新される。
  • >> という右寄せ用の演算子があり、これを使わない手は無いと思い使った。
  • "#"^^(t-k+1) より 10**(t-k) のほうが短い。
  • 無限ループだが入力で落ちて AC する。

Aheui (@n4o847, 149 bytes)

부뫄뮇처빼 밣뵓떼쟈푸처풰북뺘푸차푸
붛밞따조다퐈뿨뮣풔 뿌붌뷝더 밧돼맣
빠볾햬처복져뒤뱩뗴벬벐따벡데로

  • あまりゴルフしていない。
  • ハングルで記述するスタックベースの2次元言語。方針は #algo-blue-cd と同じ。
  • AheuiChem というオンラインエディタがあり、画像のように表示されてとてもわかりやすい。
  • Google 翻訳にかけるとこうなる

Alice (@kuromunori, 151 bytes)

[0!]0!v
v     <
>i.a-$v[?]R!aov   <
      >?h!?$v> 0/
^   ov$-*48.< > #o v 
     >[?]$v?[!] v \
^         >.o?hvo
        @o^$ ?!<
^               <  <

Arcyóu (@k_hanazuki, 117 bytes)

(: x 1)(r(F(s t)(% "%s%s"(a(a(')s)t)))(f c(q)(pg 0(?(< x 1)"@" c)(: x(?(= c "T")1(?(|(= c "K")(> x 49))(- x 50)(+ 1 x

ゴルフ言語を謳っているが,機能セットが少なくて難しいだけのLisp.プリミティブはPythonの関数にマップされていることを理解して使う必要がある. 出力が改行コード付きしかなく,文字列を連結する必要があるのだが,ちょうどいいプリミティブが見当たらなかったので文字列%を使った. ゴルフ要素はpgを使ってカッコの深い項を後ろに回せば閉じカッコが省略できるぶん短くなることくらいしか使っていない.

Arithmetic (@henkma, 127 bytes)

1=1
1=1+0
2=2
75=75
9-0=9
8=8
12-8=4
51-0=51
84=168/2
75=84-9
51/50=3/2
51=51
84=84
84=42*2
75/84=3/4
3=3
51-0=51
0=0*0
48=51-3

「全ての式が等式として正しい」状態でなければならないため、ちょっと数値を代入するだけでもいろいろと気を使う言語である。ただし除算が整数除算なのでこのへんをうまく使うと少しラクができる。 以下、ソースコードにコメントをつけたものを記述する。数値を意味する表現は括弧付きにしてアドレスと区別している。

1=1       // 1 に (1) を入れる。
1=1+0     // 0 に (1) を入れる。
2=2       // 2 に (2) を入れる。
75=75     // 75 に (75) を入れる。
9-0=9     // 9 に (-1) を入れる。
8=8       // 8 に (8) を入れる。
12-8=4    // 4 に (-8) を入れる。
51-0=51   // 51 をデクリメントする。
84=168/2  // 84 に標準入力から一文字読む。
75=84-9   // 84、つまり読んだ文字が(75)より大きければ一行飛ぶ。
51/50=3/2 // 51 が (0) なら次の行へ、そうでなければ二行飛ぶ。
51=51     // 51 に (51) を入れる。
84=84     // 84 に (84) を入れる。
84=42*2   // 84 を文字として出力する。
75/84=3/4 // 84 が (75) なら次の行へ、そうでなければ八行戻る。
3=3       // 3 に (3) を入れる。
51-0=51   // 51 をデクリメントする。
0=0*0     // 0 を数値として、つまり数値の(1)を表示する。
48=51-3   // 51 が (0) より大きければ三行戻る。

84 を入出力用、51 をカウンタ用に使っている。

AsciiDots (@akouryy1, 164 bytes)

%$BCDIJNPUV
.-#1\
   N>*B
.-\  J
  >#a?C
 V*-~$"e"&
I{+}^

 B*I
>{*}{=}{+}$a_#
*-#0-/  ^P
*V
*U
D
P*#75v  J
C*--{!}{*}N  .-#1\D
 *--{!}{*}{+}-{%}>^
 >#84^ U*#1*#51^

awk (GNU awk) (@n4o847, 52 bytes)

t+=index($0,"T"){sub(/K /,1e99)}$0=substr($0,1,t-1)1
  • awk は行ごとに実行される。パターン { アクション } を並べ、最後のブロックなしパターンが truthy なら $0 が勝手に出力される。
  • 出てくる 3 つの式は全部 truthy なので、アクション内に入れて ; でつなげるよりパターンに押し込んだ方が短い。
  • t+=index($0,"T") ... 1 行目なら T の位置 (1-indexed) を t に足す。他の行なら 0 なので問題ない。
  • sub(/K /,1e99) ... K 以降をとにかく長く長いもので埋める。1e99 で埋めた。
  • $0=substr($0,1,t-1)1 ... t-1 文字切り取り、1 と文字列結合して $0 に代入。勝手に出力される。

Axo (@sio_tet, 87 bytes)

)[(8/     #!_
%1<<,.*3+89!
  ],
- >]>~[ #!\
  # ^-1(,<
[ /
  2
  (@
  [(
# ),
> ^]
>)]^

雑に書いただけ

while(c=getc(),putc(c),c%8==0);(1行目)
b=a=51(2行目後半)
while(1) {
for(b=--a;b;--b) {c=getc();putc(c);if(c%2) goto K;} (下から2行目までの内側ループ)
getc();putc(a);b=a;(外側ループ)
}
K:
while(k--) putc(a);

Backhand (@ten986, 71 bytes)

v vi:9/j 0&i&1+:&"3"%!"$"*""+j:"K"-!"!"*b+j&:1+&"3"%!^H r}| v",":j2*bj
  • 忘れた。ゴルフしてない。
  • 1次元上を動くスタック指向言語。最初は右に3ステップ動こうとするが、vによってそのステップ数をデクリメントできるので、最初に2回呼ぶことでコードが書きやすくなる。
  • jでpopした値の文字数の場所(0-indexed)に飛べるので分岐に便利。直前に!で0か1かで分けてその値にいい感じの数値を掛けて足すと数値を作れる。数値は"*"のように書くと文字コードが取れる。
  • Hでスタックの内容を出力して終了できる。強い。

Bash (busybox) (@n4o847, 44 bytes)

sed '1h
${:1
x
s/ $//
t1
x
s/K /KK/
t1
h}
g'

sed を参照。

Bash (pure) (@akouryy1, 本質:@drafear, 83 bytes)

IFS=
f(){
read -N1 x
printf \\$[1/(~a&5),a=c[i=i%51+1]|=`printf %o \'$x`|a&1]
f
}
f

Cのコードを利用。無限ループだが、'K'|'T'|' '=125 となったところで ~a&5=0 となりゼロ除算で落ちて停止する。

Beatnik (@yyyuuuummmmaaa1, 623 bytes)

コードを見る
K QQQQQQQQQQ
K QQQQQ

KAAA
K QQQQQQQQAAAA
Q
QAAAA K
QA
KA
QAA
QA
K A
Q
QAA
QKA QAAAA

KA


QAA
QAA
K QQQQQ
QA
Q

K QQQAA
KAAAA
K A
Q
QAA
QKA KAA

KA
K QQQQQQQQQ
KAAAA

K QQQAA
KAAAA
K A
Q
QAA
QKA KAA

K Q
KAAAA
KA


K QQQQQQQQQQ
K QQQQQA

KAAA
K QQQQQQQAAAAA
Q
QAAAA K
QA
KA
QAA
QA
K A
Q
QAA
QKA QAAAA

KA

QAA
K QQQQQQQQQQ
Q
QAAAA QQQKAAA
KA


QAA
QAA
K QQQQQ
QA
Q

K QQQAA
KAAAA
K A
Q
QAA
QKA KAA

KA
K QQQQQQQQQ
KAAAA

K QQQAA
KAAAA
K A
Q
QAA
QKA KAA

K Q
KAAAA
KA

K A
QKA QQQQQQAA



K QQQQQ
QA
Q
QA
K QQQQQ
QA
Q
QA


QAA

K QQQAA
KAAAA
K A
Q
QAA
QKA KAA

Q
Q

K QQQQQQQQKAAAA
KAAAA
K A
Q
QAA
QKA KAA
K QQQQQQQQQ
KAAAA

一切ゴルフしてないです。これだとKQAしか使えない言語に見えますが、DBFJも使った方が明らかに良いです。

Befunge-98 (@sio_tet, 74 bytes)

~:,8%#v_
v*77  <  $~<
>~:,2%#v_:v.
^     -1  _^
       +
v-1,*88<
> :!#@_^

Bots (@n4o847, 216 bytes)

@user e ` (B) .@if B# .@outd 1 .@sub B 1 .@e#` .@user f ` (A,B) .@sub A 84 .@if # .@sub A 75 .@if % .@sub B 1 .@if & .@outc A .@sub B 1 .@g& .@outd 1 .@g 51% .@e B# .@outd 1 .@g 51` .@user g ` (B) .@inc .@f B` .@g 51
  • 元 TSG で現 KMC の satos さんが作った言語。Slack bot と継続渡しがベースになっているらしい。継続はよく知らなかったがこの言語のおかげでなんとなく学べた気がするので良い言語。
  • あまりゴルフしていない。
  • 方針としては途中まで #algo-blue-cd と同じで、K に至ったら回数分ループして終了。
  • 引数は 1 つしか受け渡せないのか、と思ったら継続とはそういうものらしい?

Brainfuck (esotope) (@sio_tet, @satos___jp 110 bytes)

+[,.+>-[<->---]<]+[>>[-]-[-----<+>]<-[>,+<<[>>->+<<<-]>>.<<-[------->>-<<]>>--[>[<<<+>>>-]<[+]]>[-]<<-]>,+.<<]

縮めただけなのでsatosさんに元のコードと解説して欲しい。 縮め方としてはesotopeでは256で1周するので -1/5=51 を使うと良い。

今回はさらに -1/7=73 を使いました。

satos が書いた元コードは、+[,.84-]+[>50+[>,+<<[>>->+<<<-]>>.75-[>[<<<+>>>-]<[+]]>[-]<<-]>,+.<<] です。 アルゴリズムとしては、以下の#algo-red-bfをやってます。

#algo-red-bf

for(;;){
  c = getchar();
  putchar(c);
  if(c=='T')break:
}
b = 0
while(b==0){
  for(i=0;i<50;i++){
    c = getchar();
    putchar(c+b);
    if(c=='K')b=1;
  }
  putchar(getchar()+1);
}

(#algo-blue-ac と違ってmodには気づかなかった...)

C (GCC) (@henkma, 62 bytes)

a,c[99];main(i){for(;putchar(a=c[++i%51]|=getchar()|a&1)%9;);}

このコードで用いられているアルゴリズムを #algo-blue-ac と呼ぶことにする。

#algo-blue-ac

言語によって細かい違いはあるが本質は同じ。

a はこれまでの入力文字全てのbitwise orを保持する。使用するのはその下位1bitのみで、Kを読むまでは0、読んでからは1になる。

配列 c には列ごとのデータが入る。具体的には、

  • 最終行以外ではTの列は 'T''t'、それ以外の列では ' '
  • 最終行ではKより前の列で ' '、Kの列で 'k'、KとTの間の列で '!'、Tの列で 'u' となる。
    • Tの列を終えたら即座に終了する必要がある。'u' の文字コードは9で割り切れるのでそれを判定したりして終了する。

LibreOffice Calc (@yyyuuuummmmaaa1, 92 bytes)

=REPT(LEFT(A1;51);B2/51)&LEFT(A1;C2)&REPT(B3;FIND(A3;A1)-C2),=LEN(A1)-50,=FIND(B3;A1)-B2
T,K

Canvas (@dnek_, 113 bytes)

”XWxO╶:[:Kc8%?┐xL?lyK;L└;-╵×+]w}X}}L}“
”   終わり引用符、空文字をwrap
X  popして変数Xに代入
W  while(loop末尾に来たときにstackのtopをpopして判定)
  x  変数Xをpush
  O  popして改行出力
  ╶   一行入力取る
  :  dup
  [  foreach
    :  dup
    K  配列のlastを取り出してpush(uncon)
    c  Unicodeのコードポイントで数値に変換
    8  push 8
    %  modulo
    ?  if
      ┐   pop
      x  push X
      L  popして長さ取る
      ?  if
        l  popせずに長さ取る
        y  変数Yをpush
        K  配列のlastを取り出してpush
        ;  swap
        L  popして長さ取る
        └   stackのtopの下2つをswap
        ;  swap
        -  引き算
        ╵   インクリメント
        ×   repeat
        +  add
      ]  else
        w  popせず変数Yに代入
      }  end if
      X  popして変数Xに代入
    }end if
  } end foreach
  L popして長さ取る
} end while
“   始め引用符、空文字をwrap

少し要約すると、

  • まず空文字をXに代入する。
  • 1行ずつ入力を取って長さでwhileループ。
    • X出力。
    • 入力文字列でforeach(実質長さでforしてるだけ)。
      • 入力の末尾1文字を取り出して、
      • 8で割り切れなかったら(空白でなかったら)、
        • Xが空でなかったら(Kの行だったら)
          • 今の行とYでいい感じに最終行作ってtopに残す。
        • Xが空だったら(Tの行だったら)
          • 残った(右stripされている)入力をYに代入、topにも残しておく。
        • topをXに代入。
      • 割り切れたら何もしない。
  • (stack topに残った空文字が出力される。)

一見最初と最後の引用符でコード全体を囲んでいるように見えるが、どちらも外を向いて空文字を囲んでいる。

最初のはT行とK行を判別するため、最後のは余計なものを出力しないためにある。

Canvasの仕様上最後にstackのtopが出力されるので、stackにゴミが残っている場合は始め引用符で空文字をpushしておくと楽。

感想

golflangの癖に高機能な公式エディタがあるのだが、言語機能自体は微妙でなんか書きにくかった。

今回他チームとの対戦がなかったので単にgolfできてなかっただけかもしれないが。

ちなみに見た目では分かりにくいが、×だけ2バイトで残りは全部3バイトなので計38文字。

また、上記の公式エディタはUTF-8ではなくSBCSでバイト数表示をしているので1文字1バイトにされちゃってて参考にならなかった。

CJam (@drafear, 30 bytes)

qN/$)\)N+\,*_'T#@'K#_S*@@-)'X*

最初の行と最終行を取り出して、1行目を残りの行数回繰り返し、TK のindexを調べてその回数 X を出力する方針。

最初に q で入力を全部受け取って、N (改行) で / (split) している。

splitには % も使えるが、今回は空行が残ってくれた方が配列の長さ的に都合が良いので / を使っている。

このままだと K を含む行を取り出す際に最後の空行が邪魔になるが、$ でソートすれば欲しい行が最後にかたまってくれる。

Common LISP (SBCL) (@kurgm, 150 bytes)

(defun m(u k i)(let((c(read-char))(j(mod(1+ i)51)))(princ(or k(= u i)c))(case c(#\T(m i k j))(#\K(m u c j))(t(or(if k(= u i))(m u k j))))))(m 0 nil 1)

m は一文字ずつ読んでいく再帰関数で,引数は u: T の x 座標,k: K が出現したかどうか(#\K or nil),i: 現在読んでいる文字の x 座標になっているはず。1 文字を出力したあと,読んだ文字で分岐して引数を変えて m を呼んだり呼ばなかったりしている。

ところで緑チームの会話を見たら 136 bytes があった。ひえ〜

cmd.exe (@__dAi00, 510 bytes)

コードを見る
set/pq=
set s=%q:~0,50%
set str=%q%
set len=0

set tl=1
set ss=%q%
:LOOPP
if not "%ss:~0,1%"=="T" (
 set /a tl=%tl%+1
 set ss=%ss:~1%
 goto :LOOPP
)

:LOOP
if not "%str:~0,1%"=="K" (
    set str=%str:~1%
    set /a len=%len%+1
    goto :LOOP
)
set/a x=%len% / 51
set/a y=%len% - %x% * 51
:LOOP2
if not %x% == 0 (
 set/a x=%x%-1
 echo %s%
 goto :LOOP2
)
set i=0
:LOOP3
if not %i% == %y% (
 set /p X= <NUL
 set /a i=%i%+1
 goto :LOOP3
)

:LOOP4
if not %i% == %tl% (
 set /p X=_<NUL
 set /a i=%i%+1
 goto :LOOP4
)

COBOL (@kurgm, 305 bytes)

	PROGRAM-ID.A.DATA DIVISION.LOCAL-STORAGE SECTION. 1 L PIC X(51).
	1 T PIC X(51). 1 I PIC 99. 1 K PIC 9. PROCEDURE DIVISION.A.MOVE
	1 TO I.ACCEPT L.B.IF"T"=L(I:1)MOVE L TO T.IF"K"=L(I:1)MOVE
	1 TO K.IF K=1 IF"T"=T(I:1)DISPLAY T STOP RUN ELSE MOVE"K"TO
	T(I:1).ADD 1 TO I.IF I<51 GO TO B.DISPLAY T.GO TO A.

プログラムコードは行の 8〜72 文字目にしか書けないらしいので行頭にタブ文字をいれている。(けど緑チームはこの制約を回避していそう?) ループの構文は文字数が多いので GO TO でループするとよい。

Convex (@satos___jp, 49 bytes)

qN%{\_o\No® *K"ø_,{\® *T"ø,\_,@\-KK+c*+o}&;}*

攻められなかったのでgolfはしていない。

  1. Kが出現するまでfoldを使って1行目を出力
  2. Kのある行にきたなら、K + ord(26)*(len(Tのほうの文字列)-len(Kのほうの文字列)) を出力

をしている。

公式ドキュメントだけでは挙動がわかりにくいので(https://github.com/ZekNikZ/Convex/blob/master/src/src/gamrcorps/convex/Ops.java)を読むとよい。

copos (Ruby) (@akouryy1, 2848 bytes)

コードを見る
##################################################################
############################################
##########################################
############################################
#################################################################
#############################################################
##########################################
###################################################################################
####################################################################################
####################################################################
#########################################################################
##############################################################################
##########
#################################################################
###########################################################################################
###############################################################
###########################################################################
#############################################################################################
##########################################
#############################################################
#####################################################
################################################
##########
####################################
##############################################################
############################################################
############################################################
##################################################################
##########################################
##############################################################################################################################
#############################################
####################################
##############################################
###########################################
#################################################################
###########################################################################################
################################################
##############################################
##############################################
##################################################################
#############################################################
##############################################################################################################################
###############################################
####################################################################################
###############################################
#############################################################################################
B,*,A=*STDIN
A[?K]*=50
$><<B*~-$.+A[0..B=~/T/]

Rubyの最短コードとほぼ同じだが、

  • 入力を $< == ARGF ではなく STDIN からとる
  • 変数より ord の小さい定数を用いる
  • $_ より B を用いる方が 3ord 小さい

などの違いがある。

Coq (@satos___jp, 1141 bytes)

コードを見る
Require Import Coq.Lists.List.
Require Import Io.All.
Require Import Io.System.All.
Require Import ListString.All.

Import ListNotations.
Import C.Notations.

Require Import Ascii String.
Open Scope string_scope.

Fixpoint f x i := 
  match x with
  | String "T" _ => (0,i)
  | String "K" _ => (1,i)
  | String " " r => f r (i+1)
  | _ => (2,0)
  end.

Fixpoint h i j {struct j} := 
	match j with
	| 0 => "A"
	| S m => 
		match i with
		| 0 => "A" ++ (h i m) 
		| S n => " " ++ (h n m)
		end
	end.
			

Fixpoint g t p s res {struct t} := 
	match t with 
	| 0 => System.log (LString.of_string ("XX" ++ res))
	| S n => 
		let! line := System.read_line in
		match line with
		| None => System.log (LString.of_string ("ZZ" ++ res))
		| Some line => 
			let line := (LString.to_string line) in
			let pq := f line 0 in
			match pq with
			| (0,i) => g n i line line
			| (1,j) => System.log (LString.of_string (res ++ (String "010" "") ++ (h j p)))
			| _ => g n p s (res ++ (String "010" "") ++ s) 
			end
		end
	end.

Definition cat (argv : list LString.t) : C.t System.effect unit :=
	g 100 0 "" "".

Definition main := Extraction.launch cat.

今回の大会の直前にhakatashiががんばってesoang-boxで動くように実装していた。#hakatashi-kansya。そもそもACするのが難しいので取られないだろうと思ってゴルフはしていない。 Lstringについては(https://github.com/clarus/coq-list-string/blob/master/README.md)を見ると使い方がわかる。注意として、"Kのある行が出てくるまで"とするとFixpointの停止性を示せないので、ループの回数が適当なところで上から抑えれられるようにして実装する必要がある。(これ入力長上限がないばあいどうやってやるんですかね...?)

Compile-time C++ (Clang, C++11) (@coil_kpc,writer:@paradigm_9 107 bytes)

#define constexpr
char o[3000],x,*p=o;
#define f(i)([]{for(;*i;*p++=*i++|x<1)x=*i&4?0:-~x%51-*i%2*51;}(),o)

コンパイル時C++!だがコンパイル時計算をするとは言っていない。実行環境 のチェックが緩かったので #define constexpr で コンパイル時計算を強要してくるconstexprを消せる。 不正()を防ぐために次回からは #??=(トライグラフ) があるコードは通らなくなるらしいので こういう感じ(@plasma_e氏提供)で頑張ることになりそう

Crystal (@n4o847, 58 bytes)

puts `dd`.gsub(/[^T]{50}\K./,"T").sub /K */{|y|"K"*y.size}
  • もとは Ruby で使われていたコードを nakario_jp さんや paradigm_9 さんや n4o847 が移植したり縮めたりした。
  • その後 Ruby では `dd` が禁止されたが、Crystal は exec 検証が大変らしく禁止されていないので使える。
  • 方針としては、T の下の文字を T に変え、最終行の KT のスペースを K に変えている。

C# (.NET Core) (@ten986, 128 bytes)

using S=System.Console;class A{static void Main(){for(int d=1,c;;S.Write("#\n "[d<1?0:c%3]),d=c>83?1:++d%51-c%2*51)c=S.Read();}}
using S=System.Console;class A{static void Main(){for(int d=1,c;(c=S.Read())>0;d=c>83?1:(d-c%2*51+1)%51)S.Write(d<1?'#':(char)c);}}
  • (d-c%2*51+1)%51++d%51-c%2*51と書けます。-1byteです。
  • (char)が長いので、方針を変えて、d<1?'#':(char)c"#\n "[d<1?0:c%3]とします。+2bytesです。
  • C#にはcharへの暗黙の型変換はありません。悲しいね。
  • c%3は、ASCIIコードを3で割った余りが、TKは0、\nは1、 は2であることを利用します。
  • ところでS.Read()はEOFでは-1を返すので、無限ループをしたとしても"#\n "[d<1?0:c%3]の部分で配列外参照で異常終了します。出力さえ合っていれば異常終了してもよいので利用します。
  • forの第2項(c=S.Read())>0の部分を削除し、代わりにforの中身の最初でc=S.Read();します。forの中身が2文以上になるので、{}が必要になり、for(int d=1,c;;d=c>83?1:++d%51-c%2*51){c=S.Read();S.Write("#\n "[d<1?0:c%3]);}となります。()>0が消えて{;}が増えたので-1byteです。
  • forの第3項は,で書き並べてもよいので、forの2文目を移します。for(int d=1,c;;S.Write("#\n "[d<1?0:c%3]),d=c>83?1:++d%51-c%2*51)c=S.Read();}となり、{}が消えたので-2bytesとなり、これで128bytesとなりました。

Cubix (@yamerarenaku, 57 bytes)

<w.1\;;;^+i0;sw.io3%vW?<s*?;;;.R;;v!<.@.(7%.W<sR.37^oQ;i?

Cy (@__dAi00, 103 bytes)

"\\#{x=gets;t=1+x.index(?T);print x;while !u=gets.index(?K) do print x end;print (' '*u + ?= * (t-u))}"

D (GDC) (@akouryy1, 92 bytes)

import std.stdio;void main(){int[99]c;for(int a,i;putchar(a=c[++i%51]|=getchar()|a&1)%9;){}}

See #algo-blue-ac.

Element (@drafear, 本質:@ten986, 46 bytes)

!_0;_1;{0~`_2:1~=}0~`(?{0~(`0;(\ =}!0~{K`(\ =}

Elixir (@drafear, 103 bytes)

f=fn s,i,j,f->t=IO.getn s,1
(j||i>0)&&f.(i<50&&j&&t||1,i<50&&t<"T"&&i+1||0,j&&"K"!=t,f)end
f.("",0,0,f)

普通に関数定義しようとするとめちゃくちゃバイト数を食うので、無名関数を作って再帰をしている。

三項演算子が a&&b||c でできる。

Emoji (@kurgm, 本質: @satos___jp, 448 bytes)

👥👥🚳⛽50🚘📥✂🔀📃⛽51🚘📥🍴🚲🌊⛽👥🚳🐔🚘⛽🔀👥➡🔀🚲🌊🚘🔃📤🔀⛽a🚘📲🔀👥📃👥⛽51🚘📥🌊🔀✂⛽b🚘📲🚳⛽c🚘📲⛽🚘⛽r🚘📲⛽👥📤🔀⛽a🚘📱🔀🔑🔣⛽33🚘📥🐣🚘⛽👥⛽b🚘📱🔀🔑🔣👥⛽c🚘📱👫🔍⛽r🚘📱🔀👫⛽r🚘📲⛽75🚘📥👬⛽c🚘📱👫⛽c🚘📲🚘🔃⛽r🚘📱⛽x🚘👫➡

kurgm は satos さんのコードで整数を len("aaaaaa...aaa") みたいにして生成していたのを int("51") みたいなのにしたり,文字列のアクセスを s[i:i+1] から s[i] にしたりして縮めただけです(一時緑に奪われたのを適当に縮めて奪い返したあとは,Brainfuck の厚い壁で守られていた(ので,縮めようと思えばまだ縮む))。

satosの生成元のコードです(TSG LIVE!3のために変換コードを書いてた(https://github.com/satos---jp/Esolang-Snippets/blob/93a899bfd0d0fd3648762baef437a59e102ed68d/emoji/emoji.py)のでそれを使った)。アルゴリズムとしては、最初に1行目を(len(input())//51-1)回出したあと、最終行をいいかんじに出力するかんじです。(まだまだゴルフできそうですね...)

	dup;dup;pushn(0);pushn(50);substr;swap;len;pushn(51);div;pushn(1);sub;[;dup;pushn(0);>;];[;swap;dup;print;swap;pushn(1);sub;];while;ceil;
	# all, "     T    ", 0
	swap;[;a;];set;' + 
	# all, 0
	swap;dup;len;dup;pushn(51);sub;swap;substr;
	# 0,"     K    "
	[;b;];set;pushn(0);[;c;];set;[;];[;r;];set; 
	# q,0
	[;dup;pushn(1);add;swap;[;a;];load;swap;dup;pushn(1);add;substr;ord;pushn(33);<;];[;dup;[;b;];load;swap;dup;pushn(1);add;substr;ord;dup;[;c;];load;add;chr;[;r;];load;swap;add;[;r;];set;pushn(75);=;[;c;];load;add;[;c;];set;];while;[;r;];load;[;x;];add;print;

@dnek_: bfに阻まれて出せなかった433bytes。

💬1💬👥🔢🔀📲⛽👥💬1💬👥👥👥📱🔀🔢👫🔀📲📱🔑💬!💬🐣🚘⛽🚘🔃💬💬👥📲💬 💬👥📲⛽👥📃💬💬📱📃🐔🚘⛽👥💬💬📱📃🔑💬K💬👬🔚💬K💬💬 💬📲🐧💬💬📱📃💬51💬🔢💸💬j💬📲💬1💬📱💬j💬📱🐔🔚💬 💬📱🐧🔙👥💬j💬📱🔑🐧💬💬📱🔀👫💬💬📲🚘🔃💬💬📱➡

Emojiではkey-value型の変数を格納できるが、👥(dup)を使い、💬1💬-1💬💬-💬💬といったkey-valueを作って節約した。

Emojicode (@kurgm, 240 bytes)

🏁🍇🆕🔡👂🏼❗➡t🔁👍🍇😀t❗🆕🔡👂🏼❗➡l↪🔍l🔤 K🔤❗➡k🍇🔂i🆕⏩⏩-1🍺🔍t🔤T🔤❗❗🍇↪i◀k🍇👄🔤 🔤❗🍉🙅🍇👄🔤T🔤❗🍉🍉🚪🐇💻0❗🍉🍉🍉

ほぼ 1 年ぶりに書いたらいつの間にか構文が変わっていてメソッド(やコンストラクタ)にムード(❗か❓)が必要になっていたり,絵文字もいろいろ変わっていたりしていた。Unicode への絵文字の追加とかに合わせて進化してるのかな。(適当)

擬似コードは以下の感じです

main() {
  const t = gets()
  while (true) {
    t.println()
    const l = gets()
    if (const k = l.indexOf("K") が No Value でない) {
      for (const i : range(-1, t.indexOf("T")!) { //(! は Optional を外す)
        if (i < k) {
          " ".print()
        }
        else {
          "T".print()
        }
      }
      sys.exit(0)
    }
  }
}

Erlang (@k_hanazuki, 128 bytes)


main(Z)->f(1,Z).
f(X,S)->Y=case C=io:get_chars(S,1)of"T"->1;"K"->X-50;eof->halt();_->X+1end rem 51,f(Y,if X<1->"@";0<1->C end).

今回Erlang, F#, OCamlはほぼ同じ戦略で書いた. escriptで実行するとき先頭行にプログラムは書けないが単に空行にしておけばよい. io:get_charsは入力と同時に出力できてえらいね.

Evil (@sio_tet, 54 bytes)

rweeeutbueuuuuuuukmyxjrwueueueeeutfpuysbrgwxbjgwluslsb
rweeeutbueuuuuuuuk "\s*T"をecho, 50をなんやかんや生成
my ラベルM, ループ用にcnt=50
xjrw 飛ぶ先をJに変更, ラベルJ echo-char
ueueueeeu 'K'チェック
tf puy sb 'K'なら次のラベルJに進む  そうでないなら --cnt, cntが0でないならラベルJに戻る
rgw xb 一文字読み捨てて putc(50) 飛ぶ先をMに変更して戻る
jgw lusl sb ラベルJ,  put(50) --cnt, cntが0でないならラベルJに戻る

evilはすっきり書けて楽しいので皆も書きましょう。

எழில் (@pizzacat83a, 110 bytes)

L=raw_input("")@(!len(R=rstrip(raw_input(L+"\n"))))வரை முடி printf(R+"*"*(find(L,"T")-len(R)+1))
  • タミル語を話す子供たち向けのプログラミング言語
  • ドキュメントが全てタミル語
  • 正直短く書くテクニックより言語の知識を得る情報力の方が重要っぽい
  • 設計者による論文には

Ezhil converts the program code into Python AST objects and executes them as Python objects with full access to the Python programming language eanvironment.

L=""
while 1:
 R=input(L).rstrip()
 if R:L=R+"*"*(len(L)+~len(R))+"\n"
  • ダメ元でリポジトリ内をrstripで検索したらこれがヒットした
  • つまりrstrip("hogehoge ")でいいらしい…!
  • Pythonをそのまま移植したところ161 bytes
  • Ezhilはエラーを標準出力に吐くのでraw_inputのEOFエラーでループを抜けるテクは無理
  • などPythonとEzhilの微妙な文法の違いから冗長になったので,適当にコードをいじって110 bytes
# 最初の行を読む
L=raw_input("") # raw_inputは引数を必ず1つ与える必要があるらしい
# 1行読んでrstripしてRに格納
# Rが""でなくなるまでループ
# whileの中身は空
@(!len(R=rstrip(raw_input(L+"\n"))))வரைமுடி
# 最終行を出力
printf(R+"*"*(find(L,"T")-len(R)+1)) 
  • タミル文字は基本1文字3 bytesなのでASCII文字で書けることはASCII文字で書いた方が短く済む事が多く,ゴルフするとほぼASCII文字になる
  • 結局インジェクションはできなかったが,evalがEzhilとして解釈されるのに対して,eval(raw_input())であることで有名なinput()はPythonとしてevalされるらしい

Fetlang (@yyyuuuummmmaaa1, 1367 bytes)

コードを見る
lick Trisha's toes ten times
lick Tt's toes eighty four times
lick Tplace's toes zero times
lick Kk's toes seventy five times
lick Kplace's toes zero times

lick Zer's toes zero times
lick On's toes two times


lick Jj's toes zero times

make Na moan
lick Cnt's toes zero times
lick Xx's toes zero times

Until Amy is dominant towards Alicia
    make Clara moan
    lick Ii's toes zero times
    make Ii moan Zer's fucktoy
    Until Amy is dominant towards Alicia
        Have Mistress torture Brian's cock
        If Brian is Trisha's fucktoy
            call safeword

        If Brian is Tt's fucktoy

            make Tplace moan Ii's fucktoy

        If Brian is Kk's fucktoy
            make Kplace moan Ii's fucktoy
            make Xx moan Tplace's fucktoy
            Have Ii's fucktoy spank Xx
            Have Xx lick Cnt
            Lick Cnt

        if Cnt is Zer
            Have Brian hogtie Clara
        if Cnt is dominant towards Zer
            Spank Cnt one time
            Have Kk hogtie Clara

        lick Ii's toes one time
    
    if jj is Zer
        make Na moan Clara's fucktoy

    if Kplace is not Zer
        make Na moan Clara's fucktoy

    lick Jj's toes one time
    Make slave scream Na's name
    If Kplace is dominant towards Zer
        call safeword
    


(Make slave scream Kplace's name)
(Make slave scream Tplace's name)

かっこで囲まれているのはコメントです(は?)。人の名前は一文字が最適です。

><> (@pizzacat83a, 63 bytes)

0v
+>i:o:4%?v8%?:1
>1-1nv:~~<  <
^!?: <-1v?%2^?=a:o:i
:?!;1-1n>

Fish (pure) (@k_hanazuki, 156 bytes)

set S string
read s
set t ($S length ($S trim -r $s))
while read p
echo $s
set k ($S trim -r $p)
[ $k ]&&echo $k($S repeat -n(math $t-($S length $k)) @)
end

コマンド置換(...)の結果が複数行文字列だと勝手にリストに分解されたりして,よくわからない,むずかしい. 文字列処理の組み込み関数stringには機能がたくさんあるけれど,コストがかかるので使い所が難しかった.

全然ゴルフできなかったけれど,取られなくてよかったね.

Floating (@Sugina_Miku_, 1997 bytes)

コードを見る
1047/1000
33+5/9*(1-10^-33)-1/25+7*10^-34
85+4/9*(1-10^-113)-1/5-2*10^-37-11/10^47+3/10^113
100213430447/10^9
101213430447/10^9
102213430447/10^9
103213430447/10^9
104213430447/10^9
105213430447/10^9
106213430447/10^9
107213430447/10^9
108213430447/10^9
109213430447/10^9
110213430447/10^9
110213430447/10^9
111213430447/10^9
112213430447/10^9
113213430447/10^9
114213430447/10^9
115213430447/10^9
116213430447/10^9
117213430447/10^9
118213430447/10^9
119213430447/10^9
120213430447/10^9
121213430447/10^9
122213430447/10^9
123213430447/10^9
124213430447/10^9
125213430447/10^9
126213430447/10^9
127213430447/10^9
128213430447/10^9
129213430447/10^9
130213430447/10^9
131213430447/10^9
132213430447/10^9
133213430447/10^9
134213430447/10^9
135213430447/10^9
136213430447/10^9
137213430447/10^9
138213430447/10^9
139213430447/10^9
140213430447/10^9
141213430447/10^9
142213430447/10^9
143213430447/10^9
144213430447/10^9
145213430447/10^9
146213430447/10^9
147213430447/10^9
148213430447/10^9
149213430447/10^9
150213430447/10^9
151312430447/10^9
152312430447/10^9
153312430447/10^9
154312430447/10^9
155312430447/10^9
156312430447/10^9
157312430447/10^9
158312430447/10^9
159312430447/10^9
160312430447/10^9
161312430447/10^9
162312430447/10^9
163312430447/10^9
164312430447/10^9
165312430447/10^9
166312430447/10^9
167312430447/10^9
168312430447/10^9
169312430447/10^9
170312430447/10^9
171312430447/10^9
172312430447/10^9
173312430447/10^9
174312430447/10^9
175312430447/10^9
176312430447/10^9
177312430447/10^9
178312430447/10^9
179312430447/10^9
180312430447/10^9
181312430447/10^9
182312430447/10^9
183312430447/10^9
184312430447/10^9
185312430447/10^9
186312430447/10^9
187312430447/10^9
188312430447/10^9
189312430447/10^9
190312430447/10^9
191312430447/10^9
192312430447/10^9
193312430447/10^9
194312430447/10^9
195312430447/10^9
196312430447/10^9
197312430447/10^9
198312430447/10^9
5/9000*(1-10^-49)+199312/1000+30447/10^57
345527/10^4
386/5+5/90*(1-10^-51)+2/10^52
125510447/10^7
47/100

Fortran 2018 (@kurgm, 120 bytes)

character(51)t,l
read'(a)',t
2 print'(a)',t
read'(a)',l
if(llt(t,l))t(len_trim(l):len_trim(t))=repeat("@",99)
goto 2
end

1 行目を t として,2 行目以降は t を出力しつつ,読んだ行 l が辞書順で t より後ろであれば K の行なので t の部分文字列を変更する。最後は EOF のエラーで終わる。

F# (.NET Core) (@k_hanazuki, 125 bytes)

let rec f x=let c=stdin.Read()in printf"%c"(if x<2*c/(c+1)then 'x'else char c);f((match c with|84->1|75->x-50|_->x+1)%51)
f 1

OCamlをポートした.stdout.Writeとかよりはprintf"%c"が短い.stdin.ReadはEOFでも止まらないので,エラーで落としている.2*c/(c+1)cが-1(EOF)のときゼロ除算例外をあげて,それ以外のとき1になる.

golfish (@pizzacat83a, 59 bytes)

GolfScript (@drafear, 39 bytes)

n/);)\(n+:a\,)*\"K"/~;.,a"T"/~;,\-)"*"*

忘れた。あまりゴルフをしていない。

goruby (@akouryy1, 38 bytes)

$_,*,c=*$<;s$_*~-$.,c.rs.lj(~/T/+1,?a)

Grass (@satos___jp, 1162 bytes)

コードを見る
wvwwWWwvwwWWWwwWWWWwwwWwwwWWWwvwwWWWwwWWWWwwwWwwwWWWwvwwWWWwwWWWWwwwWwwwWWWwvwwWWWwwWWWWwwwWwwwWWWwvwwWWWwwWWWWwwwWwwwWWWwvwwWWWwwWWWWwwwWwwwWWWwvwwWWWwwWWWWwwwWwwwWWWwvwwWWWWWWWWWWwwWWWWWWWWWwwwWWWWWWWWWwwwwWWWWWWWWWwwwwwWWWWWWWWwwwwwwWWWWWWWWwwwwwwwWwwwwwwwWWWwWWWWWwWWWWWWWwWWWWWWWWWwWWWWWWWWWWWwvWwwwwwwwwwwwwWwwwwwwwwwwwwwwvwwWWWWWWWWWWWwwWWWWWWWWWWwwwWWWWWWWWWwwwwWWWWWWWWWwwwwwWwwwwwWWWwWWWWWwWWWWWWWwvWwwwwwwwwwwwwwwwWwwwwwwwwwwwwwwwwwvwwWWWWWWWWWWWWWWWwwWWWWWWWWWWWWWwwwWWWWWWWWWWWWWwwwwWwwwwWWWwWWWWWwvWWWWWWWWWWWWWWWWwwwwwwwwwwwwwwwwwwwwvWWWWWWWWWWWWWWWWWwwwwwwwwwwwwwwwwwwvWWWWWWWWWWWWWWWWWWwwwwwwwwwwwwwwwwwwwwvwwwWWwwWWWWwWwwwvwWWwWWWwwWWwvwwwwWWWWWWWWWWWWWWwwWwwwwwwwwwwwwwwwwwwwwwwwwwwWwwwwwwWwwwwwwvwwwWWWWwwwWwwwWwwwWWWWWWWWWWWwwwwWWwvwwWWWwwWwwWWWWWWWWWWWwwwwwwwwwwwwwwwwwwwwwwwwwwwWWwvWWWWwWwwwwwwwwwwwwwwwwwwwwwwwwwvwvwwWWWwwvwwWWWWwvwwWWwWWWWWWWWWWWWWWwwWWwWWWWWWWWWWWWWWWWWwWWWWWWWwWWWWWWWWWWWWWWWWWWWWWWwwwwwwWWwWwwwwwwwwwwWwwwwwwwwwwvwWWwWWWWWWWWWWWWWWWWwwWWwvwwWWWWWWWWWWWWWWWWWWwwwWwwWWWWWWWWwWWWWWWWWWWWWWWWWWWWWwwwwWWWWWWWWWWWWWWWWWWWwWWWWWWWWWWWWWWWWWWWWWwWWWWwWwwwwwwwwwWwwwwwwwwwwwwwwwWwwwwwwwwwwvWWWWWWWWWWWWwWwwwwwwvwWWWWWWWWWwv

λ計算言語シリーズ。関数をλリフティングされた状態で定義してやる必要がある。 自然数を作る際に、そのまま作ろうとするとコードが長くなるので、2^nを順番に定義してそれらの和で自然数を作った。 また、スタックの底のほうの定義を取り出すのにはコストが高くなるので、よく使う関数は適宜再定義してスタックの上のほうに持ち上げるとよい。 生成に使ったコードはhttps://github.com/satos---jp/Esolang-Snippets/blob/93a899bfd0d0fd3648762baef437a59e102ed68d/grass.pyから見れる。

gs2 (@drafear, 22 bytes)

コンパイル前コード
"K"
save-a
/
extract-array
length
push-a
*
+
"T"
/
extract-array
push-a
swap
51
/
init
m:
  init
  push-a

最初に K 以降を適当な文字で十分な数埋める。

T で split して左側を取り出すと T までの入力が得られる。

T 以降の入力を51文字ずつ / で切り出して最後を捨てるといい感じになる。

最後に51文字ごとに分割して得られた各文字列の末尾を適当な文字に m: (map) で置換している。

細かいテクニックとしては

  • right-uncons して pop するのは init と等価
  • 最後がmapなら m: が使える

Hanoi_Stacck (@n4o847, 142 bytes)

  • TSG の JP3BGY さんが作った言語。名前の通り 3 つのスタック上で演算する。各命令は 16 ビットリトルエンディアンで、実質機械語。
  • スタックに入力が逆向きに入っているので若干大変だった。
  • 手では書けないので生成スクリプトを書くが、ジャンプ命令が相対位置指定でつらいので、ラベル機能を持たせてアセンブラみたいにすると良い。生成に使ったスクリプトを置いておく。
  • https://gist.github.com/n4o847/310f9285376fec7ad5c4cdfc5b04c428

Haskell (@henkma, 77 bytes)

main=interact$unlines.s((s(!).).zipWith max).lines
'K'!' '='K'
_!c=c
s=scanl1

行リストを上から順に「zipWith max した後の文字列の Kの右の空白をKにする畳み込み」で畳み込んだだけ。 見ての通り出題にあるフィールドの横幅(50)を使ってないので柔軟性がちょっと高い。

Hexagony (@akouryy1, 115 bytes)

1}1$/"'>R&=./..\'&R_'=*"\>..<{>1}~\-"<{.>}}</''T/__.@..',}}*'R&"L~&\..>+}{;&"X{<&~L="%'<..R&)"%='&"L$>'''){{/\=&

整形:

       1 } 1 $ / " '
      > R & = . / . .
     \ ' & R _ ' = * "
    \ > . . < { > ! 1 }       ←この行の「!」は実際は'\x05'
   ~ \ - " < { . > } } !      ←この行の「!」は実際は'\x01'
  < / ' ' T / _ _ . @ . .
 ' , } } * ' R & " L ~ & \
  . . > + } { ; & " X { <
   & ~ L = " % ' ! < . .      ←この行の「!」は実際は'\x02'
    R & ) " % = ' & " L
     $ > ' ' ' ) { { /
      \ = & . . . . .
       . . . . . . .

擬似コード
d: d = d * 10 + 1
b: b = b * 10 + 1
loop do
  a: f: c:
  c: c = getc
  f: a: a = b * d
  f: f = a
  g: g = f
  f: f = 'X'
  g: g = g > 0 ? c : f
  putc g
  f: a: a = b + d
  if a > 0
    f: f = 'T'
    g: g = f - c
    if g > 0
      f: f = '\x05'
      f = f * 10 + 1
      a: a = d
      inc a
      e: e = a % f
      a: a = e
      d: d = a
    else
      f: a: d: d = '\x01'
    end
    a: f: c: inc c
    g: g = '\x02'
    f: f = c % g
    a: a = b
    e: e = a * f
    a: a = e
    b: b = a
  else
    exit
  end
end

メモリ配置

. _ .       .
     e     b
      . a .  
     f     d
. g .       .
     c     *
      . * . 

htms (@paradigm_9, 192 bytes)

<htms id="htms"><q><code><q>eval</q></code><sub><q>constructor</q></sub><ins><q>return stdin.replace(/([^T]{50})./g,"$1T").replace(/K */,m=>m.replace(/./g,"K"))</q></ins><ins></ins></q></htms>

window["key1"] ["key2"] (args) が可能なのでjsを実行する。 実行環境では window.eval("...") が抑制されているので、 window.eval.constructor("return ...")() と書けば通る(jsfuck(!+[]()で書くjs)で使われる手法).window.eval じゃなくても window.atob とかでもよい(単にevalが4文字で短いから使っているだけ).なお最後の閉じタグは省略できるらしいのでもう少し短くなる。

HyperTorus (@satos___jp, 256 bytes)

.<0..r:..:....3..w............f..c...j.d........1...........r.>..7.....e........-...........1.1.>.q.><?>....+.-+>w+.>.:*>...>>>>>>>>.>>r.>*..?>>..a...>..>}.+b>w.-5...:......c*......*=..>{j+>>}.*....{.......>...............5........c......>.:...j.>.....>?>>

うちの子(自作言語)です!!かわいい!!

残念ながら、僕は8次元超立方体をイメージできないので、生成スクリプト(https://github.com/satos---jp/Esolang-Snippets/blob/93a899bfd0d0fd3648762baef437a59e102ed68d/hypertorus.py)を書いて生成しました。HexagonyやAheuiのようにいいかんじにビジュアライジングする方法が思いつかなかったので画像は割愛します(誰かいい方法があれば教えてください...)

Iwashi (@yamerarenaku, 2191 bytes)

コードを見る
6ねんまえかのことでした
だれかがハサミで
タイムラインをちょんぎった
4ねんまえかのことでした
はなはかれず
2ねんまえかのことでした
はなはかれず
1ねんまえかのことでした
はなはかれず
あしたのことはしっている
あしたのことはしっている
あしたのことはしっている
あしたのことはしっている
あしたのことはしっている
あしたのことはしっている
あしたのことはしっている
あしたのことはしっている
あしたのことはしっている
あしたのことはしっている
あしたのことはしっている
10ねんまえかのことでした
あしたのことはしっている
aにあながあく
3ねんまえかのことでした
だれかがハサミで
タイムラインをちょんぎった
10ねんまえかのことでした
あしたのことはしっている
9ねんまえかのことでした
とりはとばずねむる
2ねんまえかのことでした
とりはとばずねむる
そらのうえからaがたつ
sにあながあく
9ねんまえかのことでした
あしたのことはしっている
3ねんまえかのことでした
だれかがハサミで
2ねんまえかのことでした
とりはとばずねむる
そらのうえからbがたつ
0ねんまえかのことでした
とりはとばずねむる
そらのうえからcがたつ
3ねんまえかのことでした
タイムラインをちょんぎった
9ねんまえかのことでした
きのうのきおくはきえたけど
そらのうえからsがたつ
bにあながあく
8ねんまえかのことでした
とりはとばずねむる
そらのうえからxがたつ
5ねんまえかのことでした
はなはかれず
タイムラインをちょんぎった
sがつちからはえてくるんだ
xにあながあく
7ねんまえかのことでした
きのうのきおくはきえたけど
すのこがきえるんだ
cにあながあく
7ねんまえかのことでした
あしたのことはしっている
1ねんまえかのことでした
タイムラインをちょんぎった
sがつちからはえてくるんだ

Japt (@drafear, 25 bytes)

e"(K) |(T%D\{50}) ""$2T$1

U.e が強すぎる。置換できなくなるまで置換し続ける。

Java (@akouryy1, 147 bytes)

interface A{static void main(String[]a)throws Exception{for(int d=1,c;(c=System.in.read())>0;d=c>83?1:(d-c%2*51+1)%51)System.out.write(d<1?35:c);}}

このコードで用いられているアルゴリズムを #algo-blue-cd と呼ぶことにする。

#algo-blue-cd

元々はCの旧最短コードで使用したアルゴリズム。言語によって細かい違いはあるが本質は同じ。

  • d = 1 とする。
  • 各入力文字 c について以下を繰り返す。
    • c == 'T' なら d = 0 とする。c == 'K' なら d -= 51 とする。
    • d < 1 なら非空白文字を、そうでないなら c を出力する。
    • d = (d + 1) % 51 とする。ただしここの %-10 % 51 == -10 なる剰余である。

こうすると kT までは正であり、T を読み込んでから K までは51文字ごとに0でそれ以外は正となり、また K からは T の列までは負、T の列で0、T の列より後では正となる。

重要なのは負数の剰余の結果なので、これを満たさない言語(Ruby, Pythonやそれらで実装されたEsolang)では使いづらい。

Jelly (@akouryy1, 37 bytes)

%84»
ƈƈ¹Ð¿ỴṖ»\YOç\Ọs51Y

ポイントフリーな関数型ゴルフ言語。複雑な関数合成方法に毎回悩まされている気がする。

  • %84»: 擬似コードで書くと f x y = max (x % 84) y という関数を定義している。 この関数は引数に2つの文字コードを取る。その組み合わせと結果を以下に示す。x を前の出力文字コード、y を次のmStr(後述)の文字コードとすると f x y が次の出力文字コードになっていることがわかる(ただし改行するべきところは空白文字になる)。
chr x chr y chr (f x y)
" " 改行 " "
" " 改行以外 yと同じ
"K" " " "K"
"K" "T" "T"
"T" " " " "
  • ƈƈ¹Ð¿ỴṖ»\YOç\Ọs51Y:
    • ƈƈ¹Ð¿ỴṖ: 入力を行ごとに読むおまじない。
    • »\: 行の配列を文字ごとのmaxにscanlしている。つまり各文字について、同じ列で自分より上にある文字のうち文字コード最大のものを求めている。 結果は [" T ", " T ", ..., " T ", " K T "] のようになる。
    • Y: 改行でjoinする。この文字列をmStrと表すことにする。
    • Oç\: 各文字のordをとって、上で定義した関数 f にscanlする。これによってほぼ出力文字列が得られる。
    • : 各要素のchrをとる。
    • s51Y: 改行を復活させる。具体的には、文字列を51文字ごとに区切った後改行でjoinする。

jq (@kurgm, 82 bytes)

. as$t|[inputs]|(.[]|$t),(last+$t|sub(" "*50;"")|until(test("KT");sub("K ";"KK")))
  • . as$t: 1 行目を $t とする
  • [inputs]: 2 行目以降を配列にする
  • (.[]|$t): 2 行目以降の配列のそれぞれについて $t を出力する
  • last+$t: 配列最後の K の行と T の行を連結して 100 文字の文字列にする
  • sub(" "*50;""): 連続する空白 50 文字を削除する(ここまでで K の x 座標に K があり T の x 座標に T がある 50 文字の文字列が得られる)
  • until(test("KT");sub("K ";"KK")): "KT" が出現するまで,"K ""KK" に置換することを繰り返す

Kotlin (@dnek_, 140 bytes)

fun main(){var s=readLine()!!
var d=0
do{d=readLine()!!.indexOf('K')
println(s)}while(d<0)
print("".padEnd(d).padEnd(s.indexOf('T')+1,'K'))}

今回はgolfした結果かなり見たまんまになったのでKotlinは良い言語だと思う。 paddingは偉大。

気付きにくい(?)ポイントはdoを使って後置whileしているところだろうか。 これでkのindexを残しながらループを回せる。

Lazy-K (@satos___jp, 1547 bytes)

コードを見る
(s(s(s`ksk)`k(sii))(s(s`ksk)`k(sii))(s`k`s`k`si(s`k`s`kk(s`k`s`k`s(s`ks(s`kk(s`k(s(s`ks(s`kk(s`ks(s`k`sik))))`kk)i)))(s(s`ks(s`k`s`ks(s`k`s`k`s`ks(s`k`s`k`s`kk(s`k`s(s`ks(s`k`s(s`k(s(s(s(s(si`k(s(s(si`k`kk)`k`k`ki)`k(s`kkk)))`k(s`kkk))`kk)`k`ki)`k`ki)i)k))(s`k`s`kk(s(s`ksk)`ki)))))))`k`k`ki))))(s(s(s`ksk)`k(sii))(s(s`ksk)`k(sii))(s(s`ks(s`kk(s`k`s(s`k(si`k`kk)i)(s`k`s(s`k(si`k`k`ki)i)(s`k`s`k`s(s`ks(s`kk(s`k(s(s`ks(s`kk(s`ks(s`k`sik))))`kk)(s`k(s`k`s(s`ksk)(s(s`ks(s`k`s`ks(s`k`s`kk(s(s`ksk)`ki))))`k`ki))i))))(s`k`s`kk(s`k`s(s`ks(s`kk(s(s`k(si`k(s`kkk))i)`kk)))(s`kk(s(s`ksk)`ki)))))))))`k(s`k(s(s`ks(s`k`s`ks(s`k`s`kk(s(s`ksk)`ki))))(s(s`ks(s`k`s`ks(s`k`s`kk(s(s`ksk)`ki))))`k`ki)(s(s`ksk)(s(s`ksk)`ki)(s(s`ksk)(s(s`ksk)(s(s`ksk)(s(s`ksk)(s(s`ksk)`ki))))))(s(s`k(si`k`k`ki)i)(s(s`ks(s`k`s`ks(s`k`s(s`ks(s`kk(s`k(s(si`k(s(si`k`ki)`kk))`k`ki)i)))(s(s`ks(s`k`s`ks(s`k`s`kk(s`k`s`k(s(s`ks(s`k`s`ks(s`k`s`kk(s`k`s`ks(s(s`ks(s`kk(s`ks(s`k`sik))))`kk)))))`k`kkk)(s(s`ks(s`kk(s`ks(s`kk(s`k(si`k`kk)i)))))`k(s(s`ks(s`kk(s`k(s(s`ks(s`kk(s`ks(s`k`sik))))`kk)i)))`ki))))))`k`ki))))(s(s`ks(s`k`s`ks(s`k`s`kk(s(s`ks(s`kk(s`k(s(s`ks(s`k`s`ks(s`k`s`kk(s`k`s`ks(s(s`ks(s`kk(s`ks(s`k`sik))))`kk)))))`k`kk)(s`k(si`k(s`kkk))i))))(s(s`ks(s`kk(s`ks(s`kk(s`k(si`k`kk)i)))))(s(s`ks(s`k`s`ks(s`k`s`kk(s`k`s`k(s(s`ks(s`kk(s`ks(s`k`sik))))`kk)(s(s`ks(s`kk(s(s(s`k(si`k(s`kkk))i)`k(s`k`s(s`ksk)(s(s`ks(s`k`s`ks(s`k`s`kk(s(s`ksk)`ki))))`k`ki)))`ki)))`ki)))))`k`ki))))))`k`ki))))(s`k(s(s`ks(s`k`s`ks(s`k`s`kk(s`k`s`ks(s(s`ks(s`kk(s`ks(s`k`sik))))`kk)))))`k`kk`kii)i)))))

λ計算言語シリーズ。入出力の副作用を気にする必要がないのでいちばん書きやすいと思う。生成にはhttps://github.com/satos---jp/lambda_implementation/blob/34ad3d859d4339ab0184fa9376a9e2ed05548c97/unlambda_ruby/kmc_tsg_lazyk.rbを使った。最終日あたりで@kcz146と戦ったのでそれなりに短くなっている。アルゴリズムはおおよそ#algo-red-bfを使っている。

ショートコーディングのこつとして、

  • 自然数生成(今回の場合50がいる)はめちゃコストがかかるので、累乗などを利用する(今回は*50(n. s. z. n s (n s z)) (*2 *5)として生成した)
  • でかい関数のλ抽象はコストが思いので、適宜小さな関数とそれらの適用に分割する
  • 関数適用を表現するのに(MN)と`MNの2種類の表現法があるので適宜短くなるように使い分ける

などを使った。

Lua (@nonylene, 83 bytes)

d=io.read
f=d(51)l,c=d'*a':gsub(' *\n','')print(f:rep(c)..l..f.rep(0,f:find"T"-#l))
  1. d(51) は一行目を読む
    • d"*L" でも同じ
  2. d'*a' は残りを読む
  3. gsub で末尾のスペースを削るのと行数を数える
  4. あとは組み立て
    • l の文字長が #l で取れるので積極的に使っていくと良い

m4 (@k_hanazuki, 56 bytes)

syscmd(`sed "1h
\${:1
x
s/ \$//
t1
x
s/K /KK/
t1
h}
g"')

bashのコピペ(bashはsedのコピペ).

Make (@drafear, 364 bytes)

x=$(subst $() ,1,$(STDIN))
a=$(subst 1, ,$(firstword $x))
b=$(subst 1, 1 ,$(lastword $x))
c=x $(subst $() , 1 ,$a)
p=1
s=x
$(foreach i,$x,$(if $(findstring $(subst 1,,$i),K),,$(info $a)),),$(foreach i,$b,$(if $(findstring $i,K),$(eval p=2)) $(eval s+=$p) $(if $(findstring $(word $(words $s),$c),T),$(eval p=1))),$(info $(subst 1, ,$(subst x,,$(subst $() ,,$s))))

読んだ通り。ゴルフをしていない。

MATL (@kurgm, 22 bytes)

j`jtYv?y-Ys9\1G+cF}xtT

スタック型のゴルフ用言語。

  • j: 標準入力から 1 行の文字列を読み取る
  • ` do-while ループ開始(終了は省略してある)
    • j: 標準入力から 1 行の文字列を読み取る
    • t: スタックの一番上(読んだ行)を複製してプッシュ
    • Yv: trim
    • ?ほげ}ふが]: if-else (終了の ] を省略している)
      • ほげ部分(K の行のとき)
        • y: スタックの上から 2 番目(T の行)を複製してプッシュ
        • -: 引き算(ベクトル [0 0 ... 0 43 0 ... 0 -52 0 ... 0] が得られる)
        • Ys: 累積和([0 0 ... 0 43 43 ... 43 -9 -9 ... -9]
        • 9, \: 9 をプッシュして mod([0 0 ... 0 7 7 ... 7 0 0 ... 0]
        • 1G: 1 行目の入力をプッシュ(今見たら y の方が短いですね???)
        • +: 足し算([32 32 ... 32 39 39 ... 39 84 32 ... 32]
        • c: char にキャスト。文字列になる
        • F: ループを終わりたいので false をプッシュ
      • ふが部分(間の空行のとき)
        • x: スタックのトップ(空行)を削除
        • t: スタックの一番上(T の行)を複製してプッシュ
        • T: ループ条件の true をプッシュ

最後はスタックの内容が下から順に出力される。

Maybe Later (@yamerarenaku, 153 bytes)

i=x=z=0whene is 0{e=d=0}whend is0{i=i+1x=x+1b=p==x
c=z+b+orda[i-1]writechrc
if(c!=10)d=0}whenc is10x=0whenc is84p=i whenc is75z=1whenc is34z=0a=reada e=0

Minimal-2D (@akouryy1, 144 bytes)

R>>>/D>>R/D<<,R>+>+D
U .+,L  U-LD  U/-<<L
U       <<L
D----    > L
R/D>.R  /DUL
-.   U<<<L .
 >R--/D<+>>UL
U><  LR--/D>U
DU/L<U/  -L
>
>
+
R.>U

擬似コード
a[1..51], b[1..51], c[1..51], i = 0

while(true) {
  i += 1
  if(a[i] > 0) {
    putchar(getchar() + 1)
    continue
  }
  c[i] = 0
  a[i] = getchar()

  b[i] = c[i] = a[i]
  a[i] = 0
  b[i] -= 4
  switch(b[i] % 6) {
    case 0: # '\n'
      putchar(c[i])
      while(c[i]) --i /* i = 0 */
    case 2: # 'T'
      ++a[i]
      putchar(c[i])
    case 4: # ' '
      putchar(c[i])
    case 5: # 'K'
      while(!a[i]) putchar(c[i] + 1)
      putchar(c[i])
      exit
  }
}

入力の6による剰余をとって短縮した。 擬似コードの変数はメモリ上では a[0], b[0], c[0], a[1], b[1], c[1], ..., a[51], b[51], c[51] の順に並んでいる。

moo (@n4o847, 37 bytes)

0{1+idrd75=51*r84>*-d51>*dr1>+o0c}0dc
  • TSG の moratorium さんが作った言語。スタック型で、関数の定義・呼び出しができるのが特徴。比較的短く書けるので好き。
  • とはいえ関数を使うよりスタックで頑張ったほうが短くなるので、条件分岐をなくし、ループを1つにまとめる。方針は #algo-blue-cd と同じで、これにより分岐が要らなくなる。擬似コード:
    x = 0
    loop:
      x = x + 1
      c = getchar()
      x = x * (c < 'T') - (c == 'K') * 51
      x = x * (x < 51)
      putchar(c + (x < 1))
    
  • 無限ループだが、入力で落ちて AC する。

なでしこ3 (@nonylene, 92 bytes)

JS{{{let x;console.log(""+require("fs").readFileSync(0).map(c=>c|(x=c&4?0:-~x%51-c%2*51)<1))

See ↓nodejs↓

Node.js (@n4o847, 83 bytes)

console.log(""+require("fs").readFileSync(x=0).map(c=>c|(x=c&4?0:-~x%51-c%2*51)<1))
  • Node.js ゴルフにおいて (""+require("fs").readFileSync(0)) は定型句になっているが、今回は文字列変換する前に Buffer に対して map で直接処理をすることで大幅に短くなった。
  • 方針は大体 #algo-blue-cd と同じ。

Nuts (@satos___jp, 3633 bytes)

コードを見る
,,','',,... ,.. .. . '',,... ,.. .. . '',,,,',,''... ,,: '',.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. . " ,:: " ,,'',.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. . ',',',,,',',. ''. ,,. ',. ''.. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. " ''. " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ''.. " " " " " " " " " " " " " " " " " " " " " ''.. " " " " " " " " " " .. ... ''. ,,: ,,.. . '',.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. ,.. . " ,:: " . .. '. . ,,','',,... ,.. .. . '',,... ,.. .. . '',',',,,,',',. ''. ,,. ',. ''.. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. ,,''',,. ... .. " ''. " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ''.. " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " .. .... '. ... ,,: . " ,:: " ''..

OCaml (@k_hanazuki, 118 bytes)

let rec f?(c=input_char stdin)x=print_char(if x<1 then 'x'else c);f(match c with 'T'->1|'K'->x-50|_->(x+1)mod 51);;f 1

青チームの#algo-blue-cdとほぼ同じになっていた(cとd(ここではx)の更新順が違って,+1/-1があるが).状態を持つよりは再帰のほうが短く書けた.

input_charはEOFで例外を投げるので勝手に止まる.OCamlではcharintを行ったり来たりするコストが高いので,普通に文字としてパターンマッチするのがよさそう. 関数のすぐ内側でletをするよりもデフォルト引数を使うとお得.

Octave (@kcz146, 112 bytes)

[i]=strchr(l=fgetl(0),"T");
do disp(l);until[t]=strchr(k=fgets(0),"K")
disp([substr(k,1,t),repmat(['*'],1,i-t)])

PATH (@kuromunori, 364 bytes)

$}}}> ,. ----------v>{{{v}}>,----------v++++++++++.v
    ^+}}}++++++++++<^   <              >----------------------v}.v
                    ^                   {{---------<
                           ^+}}                                  <
                     v+v---------------------------------.+<} <
                     >}}}                                  ^

Perl (@n4o847, 35 bytes)

#!perl -p
$t=$_|=$t;1while s/k /kk/
  • オプション付きで起動する。-p オプションはプログラムが入力の行ごとに実行され(入力は $_ に入っている)、最後に $_ が出力される。
  • Perl には文字列のビット演算が存在する。各行の bitwise OR を累積する。
  • 最終行は " k t " みたいになるので置き換える。置換 s///$_ に対して実行され、成功したかが返る。

Perl 6 (@k_hanazuki, 48 bytes)

$_~|($||=$_)~~{say S[k\s+]=1 x$/.codes}for lines

方針: 1行目を覚えておいて,各行とbitwise orを取る.最終行はktの間を埋める.

  • 各行処理をするにはfor linesが短いが,これを使うためには内側の処理を式にする必要がある(後述).
  • 単体でててくる$はstate変数.レキシカルな出現場所ごとに別の変数になる.ブロックを抜けても値が記憶される.
  • $||=$_で1行目を覚えている.
  • ~|はbitwise or.
  • ~~は右辺がブロックのとき,given 左辺 {右辺}とだいたい同じ意味の「式」になる.
  • s///を使うためには,トピック変数$_がミュータブル(他の言語でいうところの「左辺値」のような概念)である必要がある.余分な代入を入れて($=$_~|($||=$_))~~{ s///; .say } のようにすることもできたが,今回はS///を使うほうが短かった.
  • S[re]=eS///の亜種で,置換後の文字列をプログラムで作れる.見た目に反して,置換後の文字列の全体を返す.
  • マッチの長さは$/.codes (or .chars)でとれるよ.適当な文字を並べたいときは1 x...が安い.

Perl6おもしろいね~

PHP 7.0 (@n4o847, 67 bytes)

<?php
while($c=fgetc(STDIN))echo(1>$x=$c>S?:++$x%51-($c>J)*51)?:$c;
  • PHP は関数名が長いので、文字列操作ではなく一文字ずつやる。方針は大体 #algo-blue-cd と同じ。以下に注意点を書く。
    • " " で囲まれていない文字列は「裸の単語」と呼ばれる。
    • echo は言語構造であり、直後の括弧は echo についているものではない。
    • || だと真偽値に変換されてしまうので ?: を使う。
    • このコードは関係ないが、PHP の三項演算子は他の言語と違い左結合なのでクソ。

PicFunge (@ten986, 187 bytes)

  • ゴルフしてません。
  • https://github.com/Liesegang/picfunge/blob/master/boards.py を眺めます。ほとんBeFunge93であることが分かります。
  • BeFunge93と違い、3次元です。画像のxy方向の2次元に、RGBによる3次元目を足した空間となります。つまり3次元目は必ずサイズ3です。Rの0~255の値を文字コードとみなしたものが命令となります。3次元目はR=0,G=1,B=2で、最初は(0,0,0)からx方向に進みます。
  • 3次元なのでBeFunge93にはない命令がありますが、3次元目を無視してとりあえず2次元と見なせばBeFunge93です。
  • ただしスタックは、デフォでは3次元目のRの部分を左上から使っていく、つまりコードを書き換えていくことでスタックとしているらしい。クソか?
  • スタックの数が有限らしい。画像のサイズ依存。
  • なので(0,0,0)にAを置いてGの次元である(0,0,1)に進み、(0,0,1)では>を必ず置くようにし、Gの次元にBeFunge93のコードを配置するようにするとよい。なんでやねん。
  • というわけでBeFunge93を書きます。
>~:"T"-v  v$~,"#"  <
^,     _,0>1+"3"%:!|
@_1+     0|-"K",:~ <
 ^!:%,:"2"<
  • これを、https://gist.github.com/ten986/e3647ccfd2458325d70216ee4e2a21f1 によって変換します。この画像を提出するとACできます。
  • 余談ですが、BeFunge98ではBeFunge93のコードが動くわけですが、上のコードはBeFunge98の最終解とbyte数が同じです。
  • BeFunge98では"a"のようなものを'aと書けるので、最終解よりも短くできます。以下がBeFunge98のコードになります。
>~:'T-v  v$~,#'  <
^,    _,0>1+'3%:!|
@_1+    0|-K',:~ <
 ^!:%,:2'<
  • BeFunge93適当に書いただけだから正直もっと短くできると思うのだけれど、BeFunge98の周りの言語が難しすぎて到達できなかった。つら。

Piet (@dnek_, 249 bytes)

基本的に、入力を1文字ずつ取って逐次出力していくスタイル。

  • デカい黒ブロックの上側: Txを取っている。
  • デカい黒の右側辺り: 改行が来るまで空ループ。
  • 下半分くらい:
    • 右端: Txに到達したかどうか判定。
    • 左側(Tx来た場合): $(6^2)を出力して改行まで空ループ。
    • 右下(x<Tx): 空白かKか判定。
      • 空白なら右端に戻る。
      • Kなら小さい黒2つの隙間を潜ってpoint(3)で左に出る。
  • デカい黒直下: $Tx - Kx - 1個出して終了。

前回はgifよりpngの方が4バイトくらい軽かったのでpngで出したが、今回はgifの方が素で7バイト軽かったのでgifで出した。

今回みたいに中身がスカスカだとgifの方が良いのだろうか。知らんけど。 また、pietでよく使われる処理系であるnpietは、gifの後ろ2バイトが無くても読んでくれるので削る。

あと、同じ色が横に繋がっていると圧縮されやすいっぽいのでなるべくそうしておく。

また、Pietの色は全部で20色あるが、16色に絞ると2^4になってカラーマップのバイト数が大幅に減るので、もし抜かれたらやろうと思っていた。

でも結局対戦相手が居なかったのでちょっと寂しかった。 Pietronあるから使ってね。

PowerShell (@k_hanazuki, 72 bytes)

$t,$s=$input|% TrimEnd
"$t
"*$s.Count+$s[-1].PadRight($t.Length,75)|echo

入力は行分割された状態で$inputから取れる.ArrayLengthにはCountという別名がつけられている.echoにはパイプで渡すと得.

PPAP (@k_hanazuki, 249 bytes)

I have P
I have 75 K
I have 84 T
I have O
I have 50 X
I have 52 W
O
Uh! Pick-P
Uh! Compare-P-K-K!
Uh! Compare-P-T-T!
Uh! Rip-X-O
Uh! Superior-X-O-P!
Uh! Append-P-O
T
Uh! Replace-X-W
P
Uh! Put-P
Uh! Jump-O
K
Uh! Put-P
Uh! Rip-X-O
Uh! Superior-X-O-K!

即値命令がなくて定数定義のコストが高いので,いかに定数を使い回すかが重要そう.安全地帯にあったので,あまりゴルフしていない. ドキュメントにかかれていないお得情報: ①識別子にはP/pを含まなくてもよい.②ラベルはハイフンで繋がず識別子1つでもよい.

プロデル (@akouryy1, 本質:@ten986, 176 bytes)

k=「K」
x=コンソール
a=xから受け取
『c=xから受け取
e=cからkを探-1
aを報告
もしe>=0なら
d=aから「T」を探
e回『xへ「 」を表示』を繰り返
d-e回『xへkを表示』を繰り返
終了』を繰り返

日本語なので読めますよね。

(@akouryy1: 文字コードをUTF-8からShift-JISに変更して短縮した。)

Python 3 (@nonylene @paradigm_9, 65 bytes)

a,*b,c=open(0)
print(a*len(b)+a+f"{c.rstrip():0<{a.find('T')}}0")
  • a は一行目, c は最終行、*b はその他
  • :0<{length} で0埋めできる
    • f-string はネスト可能

‫قلب‬ (@kurgm, 431 bytes)

(حدد ب ٠)(حدد ا ٩٩)(حدد د"")(حدد ؤ ٠)(كرر(طول(حدد ئ المدخلات))(لامدا()(حدد ج(رأس ئ))(عدل د(جمع د(إذا(يساوي؟ ج"T")(إفعل(عدل ا ؤ)ج)(إذا(يساوي؟ ج"K")(عدل ب ج)(إذا ب(إذا(أكبر؟ ؤ ا)(عدل ب ج)ب)(إذا(يساوي؟ ؤ ا)١ ج))))))(عدل ؤ(إذا(يساوي؟ ؤ ٥٠)٠(جمع ؤ ١)))(عدل ئ(ذيل ئ))))(قول د)

公式サイトがアラビア文字しかなくて,ドキュメントっぽいものも無くて hoge だったのでインタプリタを読んで書いた。

最初は 1 文字ずつ処理する再帰関数を使っていたのだけど,大きい盤面でインタプリタが Maximum call stack size exceeded で死んでしまうので少々長くなったが for っぽいやつ(以下では call-n-times としている)で書き直した。

Scheme よく知らないけど Scheme っぽく書くとこんな感じになると思います(入力が input に予め入っていて,say が出力する関数)

(define k 0)
(define t 99)
(define o "")
(define i 0)
(call-n-times (length (define s input)) (lambda ()
  (define c (car s))
  (set! o (+ o
    (if (eq? c "T")
      (begin 
        (set! t i)
        c)
      (if (eq? c "K")
        (set! k c)
        (if k
          (if (> i t)
            (set! k c)
            k)
          (if (eq? i t)
            1
            c))))))
  (set! i (if (eq? i 50)
    0
    (+ i 1)))
  (set! s (cdr s))))
(say o)

Racket (@kurgm, 131 bytes)

#!racket
(define(m t l)(if(string>? l t)(m(string-replace t" T""TT")l)(begin(display t)(newline)(m t(read-line)))))(m(read-line)"")

m は再帰関数になっていて t は出力したい行の内容を,l は入力された行の内容を持っている。

  • 最後の行を読むまでは t には T の行が入っている。 l は空白だけの文字列なので (string>? l t)(辞書順比較)は偽であるから,t を出力する
  • 最後の行にくると (string>? l t) が真になる。t" T""TT" に置換して,出力はせず m を呼ぶ
  • ↑を繰り返すと t の値 " TTTTTTT " の T が左に伸びていく。やがて左端が K の x 座標まで達すると, (string>? l t) が真でなくなる。そうすると t が出力される
  • 最後は辞書順比較のところで #eof と比較しようとしてエラーで落ちる。

Rail (@akouryy1, 115 bytes)

$'main'
 -10{f}
$'f'
 -(!!)(!d!)1i(!c!)(c)[T]qs(d)m(!d!)(c)[K]q()(d)ma0g(!!)0(c)p()0q(d)m0gc1c(!f!)o(d)1a[51]r(){f}

Recurse (@sio_tet, 113 bytes)

$v
>8{}m}v#
#T@$# ?#
#%^s!{<<
$^

Tv
>T!]?!?A{}m{}7<
T^

Av
>#@{s}1@d{!?}}]<
#    v[<   }!]<#
#A<  @{1}s{   ^#
A^
void $() {
r=64
c=getc
putc(c)
dir = r<=>c
if(dir = 1) $()
else {T(), putInt(0)}
}

void T() {
resA = A(49,49)
if(resA=1) return;
c=getc()
putc(c)
getc()
putc(49)
T();
}

int A(int l, int r=49) {
c=getc()
putc(c)
dir = c/r
if(dir>0) {
  while(l--) putc(r)
  return 1;
}
if(--l) return A(l,r);
return 0;
}

なんと2次元の中で関数が呼べる!最高!みんなも書きたいでしょ?

reversed-c (@akouryy1, 83 bytes)

{؛(6%(2%s*|()ɹɐɥɔʇǝƃ=|[15%x++]s=s*)ɹɐɥɔʇnd)ǝlıɥʍ}(x)uıɐɯ؛[66]s

Ring (@pizzacat83a, 90 bytes)

get s p=substr(s,"T")while p{get t?s q=substr(t,"K")if q{?copy(" ",q--)+copy("1",p-q)p=0}}
  • 実用言語。ちょっと気持ち悪いだけでesoではない
  • 文法が「自然な」ことを重視しているらしく,配列のインデックスが1から始まるなどちょっと気持ち悪い
  • printseeinputgiveなのが最高に慣れない
  • 1つの制御構文に複数の書き方があり,ドキュメントを読めば読むほど縮む
get s # 1行入力
p=substr(s,"T") # Tの位置を得る
while p{
  get t
  ?s # 1行目をそのまま出力
  q=substr(t,"K") # Kの位置を得る
  if q{ # Kがある行に来たら
    ?copy(" ",q--)+copy("1",p-q)  # 適当にスペースと線路を出力
    p=0 # ループを抜ける
  }
}

RISC-V (32bit, ELF) (@kcz146, 548 bytes)

Reverse Programmer Notation (@drafear, 58 bytes)

read
1
w{
read
"\]p\]]$e¿'K'f''\m]wL\'T'f1+\-X\mw}"
-0
}

なぜかif文 ? ... } が使えないのでwhile文で代用している。

1文字(1バイトでなくてもよい)の命令列だと改行やスペースを挟まずに書いて -0 でevalできる。

Ruby 2.6.3 (@akouryy1, 43 bytes)

$_,*,c=*$<;c[?K]*=99;puts$_*~-$.,c[0..~/T/]

Ruby 0.49 (@paradigm_9, 90 bytes)

print(t=gets())
while gets()
print((k=$_.index("K"))&&" "*k+"a"*(t.index("T")-k+1)||t)
end

現存最古のRuby.意外と使える機能は多い. Spec. ソース.

Rust (@progrunner17, 148 bytes)

use std::io::*;fn main(){let mut a=[0;999];stdin().read(&mut a);let mut i=51;while a[i-1]<117{a[i]|=a[i-51]|a[i-1]&1;i+=1}stdout().write(&a[0..i]);}

sed (@n4o847, 38 bytes)

1h
${:1
x
s/ $//
t1
x
s/K /KK/
t1
h}
g

sed は行ごとに実行される。パターンスペース、ホールドスペースというのが存在する。

1h             # 1行目:パターン → ホールド
${             # 最終行:
  :1           #   ラベル1
  x            #   パターン ↔ ホールド
  s/ $//       #   末尾のスペース1個消す
  t1           #   成功ならラベル1へ
  x            #   パターン ↔ ホールド
  s/K /KK/     #   Kの次のスペースをKに
  t1           #   成功ならラベル1へ
  h            #   パターン → ホールド
}
g              # ホールド → パターン

要するに、最終行の前までは 1 行目を使いまわし、最終行で T の後ろのスペース分消した後残りを K に変えている。最初はループに合わせラベル 2 つだったが、取られたので縮めようとしたらたまたま 1 つでも正しく動いた。

Simula (@kurgm, 155 bytes)

begin integer c,i,t,k;a:i:=i-i//80*80+1;c:=rank(inchar);if c=84then t:=i;if c=75then k:=1;outchar(if t=i or k=1then'T'else' ');if i<t or k=0then goto a;end

1 文字ずつ入出力しているのだが,何故か 1 行が 80 文字で固定らしい。よくわからない。

c は入力された文字のコード,i は x 座標(1〜80),t は T の x 座標,k は k が出現したかどうかを保持している。while もあるんだけど goto の方が短かった。

SNOBOL4 (@shell_mug, 98 bytes)

	T = TRIM(INPUT)
F	LGT(OUTPUT = T,K = TRIM(INPUT))	:S(F)
	OUTPUT = K DUPL(1,SIZE(T) - SIZE(K))
END

各行の入力文字列が辞書順で(最終行)>(最初の行)>(空白の行)となっていることを使った。

SNUSP (@kuromunori, 264 bytes)

/=,----------?\++++++++++.<!/?\+< !/->+>>\
 /------------/    /      .\\+//>>>\?<<<+/
 \----------?\<<<?\>+>>!/@!/\/!\ !/-<\
\==.>>>+/?<<</    \>>-?\*>\/ \?>>>+<</
!$>>>\  \>>+!/ -?\\<   >\+/!\-@@@+++++++#
             \<.>/ <   \-***/
\    /!            /!    -</

SQLite3 (@utgwkk, 133 bytes)

select substr(replace(v,substr(v,52,51),substr(v,0,52)),0,instr(v,'K'))||printf('K%.'||(instr(v,'T')-instr(v,'K')%51)||'c','K')from i

標準入力は i.v にぜんぶ入っているのでそれを弄る。 (Tの行)x(N-1) + (Kの手前の空白) + (Tの列までKで埋めた文字列) を出力している。 ところで substr(...,instr(v,'K'))rtrim(...) でいいのでもっと短くなる。

select rtrim(replace(v,substr(v,52,51),substr(v,0,52)))||printf('%.'||(instr(v,'T')-instr(v,'K')%51)||'c','K')from i

116 bytesになった。

SQLite3は文字列処理がかんたんに書けて便利だね

(?i:standback) (@drafear, 41 bytes)

w/K /s/(T\D{50}\K|(K)) /T%2//m//S//%%'///

T を下に連ねていく正規表現と K を横に連ねていく正規表現を組み合わせた。

T を下に連ねていく方が手前でマッチするので、優先的にマッチする。

Starry (@drafear, 106 bytes)

` , + .        +    *' `     +          + +  * +*  `  + + ,* + .       +    **  +      + * +  ' , +* + . '

擬似コードのコメントに書いたとおり。

まず T を読み込むまでcatし、50文字処理して適当な文字を出力することを繰り返す。

i: 残り何文字処理するか, b: K を読み込んだか(0 or 1), をスタックの上2つに保存しておく。

K だけASCIIコードが奇数なので読み込んだ文字を c として b += c % 2 をする。

c + b を出力することで、K を読み込んだ後は ! が出力される。

気持ちとしては、ループの後に b=1 なら処理を終えたいが、ゴルフのため、次のセクションも処理することにしている。

b を毎回 0 で初期化しているので、次のセクションでは単にcatされ、入力が取れなくなったところでエラー落ちする。

T までの処理とそれ以降の処理を分けることで、T かどうかを mod 3 で判定できるようになる。

擬似コードを見る
# Tがくるまでcat
loop1:
  readc
  dup
  putc
  3
  mod
  jnz loop1

# 50文字処理して T を出す
outer_loop:
  # b = 0
  0
  # i = 50
  5
  dup
  mul
  dup
  add
  inner_loop:
    # b i
    swap
    # i b
    dup
    readc
    add
    dup
    putc
    # i b c
    # if c == 'K' then b = 1
    2
    mod
    add
    # i b
    swap
    # b i
    # i -= 1
    1
    sub
    dup
    jnz inner_loop
  # put '@'
  readc
  dup
  add
  dup
  putc
  jnz outer_loop

Streem (@satos___jp, 216 bytes)

f={case[p,q]->p}
g={i,s->if(i>0)g(i-1,s)+s else""}
stdin|reduce(["",""],{case[c,d],s->if(c.length>0){v=s.split("K");if(v.length>=2)d+c+v.f+g(c.split("T").f.length-f(v).length+1,"A")else[c,d+c]}else[s+"\n",d]})|stdout

Stuck (@kurgm, 247 bytes)

"[(lambda x: globals().__setitem__('q',x) if 'T' in x else (exit(__import__('sys').stdout.write(q+'\n'+x.rstrip()+(len(q.rstrip())-len(x.rstrip()))*'*')) if 'K' in x else __import__('sys').stdout.write(q+'\n')))(raw_input()) for _ in range(100)]"~

satos さんが Width で書いた Python ワンライナーを Python 2 向けに雑に修正して雑に提出しただけ。

Suzy (@satos___jp, 118 bytes)

99,4,1
_}:i(i+1)!"*"     _
_^@$"T"C=)i+1(iXC,{Y!"n\"!X!{
}?X}   ?Y:i0},CYi(i+1)=C"K"$^_
   ^ "n\"!X!^#$i)7*7(<)i+1(i:{

Swift (@akouryy1, 109 bytes)

var d=1
while let l=readLine(){print(String(l.map{d=$0=="T" ?0:(d-($0=="K" ?49:-1))%50
return d<1 ?"a":$0}))}

あまり知らない言語で無駄な記述も残っているがよいアルゴリズム(#algo-blue-cd)に助けられてなんとか最短を取れた。

(@dnek_: こちらのチームもほぼ同じでString initializerに思い至らず負けてしまったが、=="T"=="K"をそれぞれ>"S">"J"で書いていた。これを適用すると2バイト減る。)

Tetris (@sio_tet, 217 bytes (参考:202bytes))

84:
O.<<<<
I.A
1578:
O:B<<<<
L.A<<
I:A
S:B
T.>>>>
Z:A>>
300:
J:BB<<<
J.
I.>>>
J.B>>>>
J:<<<
J:BB<<<
S:>>
Z:A
S.>>>
T:A<
I:A<
O:B>
I.A>>>>
75:
100:
J.
J:B<<
O:<<<<
I:A<<
Z:B>>>>>
S:B>>
J:>>>
T:A
1621:
O:B<<<<
I.<
I.>>>
84:
some-block(nop-O-block, nop-I-block)
1578:
84->100(PB)
1578->100(OPIB)
300:
300(JIOJ+SJB)
75:
100:
100(OJI+SJB)
1621:
100(O)

note: jump-if-canがめちゃくちゃ強い

工夫した点としては、メモリは使い捨てでポインタを進めるだけにしたことで、0初期化がポインタを進めるで代用できる

追記: 300: から次のラベルまでを以下にしても動作します。(202bytes)

200:
T:<
S:A
J.B>>>>>
Z:A>>>
J:A>>
J:A<<<
I:>
O:B>>>>
J:<<
I.B<<<<

Triangularity (@akouryy1, 199 bytes)

.........i.........
........ReD........
.......D"T"s.......
......S@"k]]"......
....."n[stac"+.....
...."*b,a,x i"+....
..."')for d,c,"+...
..").ljust(x,'*"+..
."n(b)+c.rstrip("+.
"[(a+'\n')*le"+  Ee

単にPythonのコードを埋め込んだあと少しだけTriangularityの命令を用いて一回り小さくした。
仕様上バイト数は必ず 2*n**2-1 になるため 199bytes の次は 161bytes で、これはPythonを埋め込んでいると難しそう。

まず iReD"T"sS@ によってスタックを ["",(Kを含む行),(空白行)*n個,(Tを含む行),(Tを含む行),(行内のTのindex)] とする。
その後文字列 "[(a+'\n')*len(b)+c.rstrip().ljust(x,'*')for d,c,*b,a,x in[stack]" を積んで eval する。
これによってスタックは [[(出力文字列)]] となるので、最後に e によって配列を1段剥がす。

UberGenes (@drafear, 78 bytes)

=a1=ao=oa%a3:0a=x5*xx*x2=ao=ba%b2+jb+aj=oa-x1=g7*g3:gx=ao+a1=oa=aj-a1=g4*g3:ga

ゴルフしてません。3バイトごとに命令が区切られており、op arg1 arg2 となっている。

例えば =a1 はレジスタ a1 を代入する命令であり、+a1 はレジスタ a1 を足す命令である。

=ox で1文字出力、=xo で1文字入力ができる。

レジスタ i がプログラムカウンタであり、i を直接いじっても良いし、:xy (y != 0 なら i=x+3 とする) を使っても良い。

Unicat (@kurgm, 1212 bytes)

コードを見る
😻😹😻🙀😸😹🙀😸😺😼😿🙀😸😻😹😾🙀😸😿🙀😸😻😹🙀😸🙀😸😿🙀😸🙀😸😾🙀😸😼😾🙀😸😻😹😹🙀😸😹😹😻🙀😸😿🙀😺😹🙀😸🙀😸😽😿😹🙀😸😹😿🙀😸😻😹😺🙀😸🙀😸😿🙀😺😺🙀😸😹🙀😸😽😿😺🙀😸😹😽🙀😸😻😹😽🙀😸😹🙀😸😽😿😽🙀😸😹😿🙀😸😻😹😼🙀😸🙀😸😿🙀😸😼🙀😸😾🙀😸😻😹😹🙀😸🙀😸😿🙀😸😹🙀😸😼🙀😸😿🙀😺😹🙀😸😾🙀😸😽😿😹🙀😸😻😼🙀😸😻😹😺🙀😸🙀😸😿🙀😺😺🙀😸😹🙀😸😽😿😺🙀😸😻😼🙀😸😻😹😹🙀😸😼😹🙀😸😽😼😹🙀😸😻😹😹🙀😸😹🙀😸😿🙀😺😹🙀😸😽🙀😸😽😿😹🙀😸😼😹🙀😸🙀🙀😽😿😽🙀😸😻😿🙀😸😽😼🙀😸😽😿😻🙀😸😼😹🙀😸😻😹😹🙀😸😼😹🙀😸😽😼😹🙀😸😿🙀😸😾🙀😸😻🙀😸😻😹😹🙀😸😿😺🙀😸😿🙀😺😹🙀😸😾🙀😸😽😿😹🙀😸😺🙀😸😽😿😻🙀😸🙀😸

にゃ〜ん。9 種類の猫の顔文字からなる言語。

以下のプログラムから作りました。

int i, t, k;
char buf[52];
void main() {
  t = -1;
  for (;;) {
    fgets(buf, 0xffff, stdin);
    for (i = 0; i < 51; i++) {
      if (buf[i] >= 'K') {
        if (buf[i] > 'K') { // T
          t = i;
        } else { // K
          k = 1;
        }
      }
      if (t <= i && i <= t) {
        putchar(33);
        if (k) {
          exit(0);
        }
      } else if (k) {
        putchar(33);
      } else {
        putchar(buf[i]);
      }
    }
  }
}

Unicue (@n4o847, 286 bytes)

01¹(𓀀𓀁𐘀ᚠ9₉ఀ3ぁက[𓀂𑘀𓀃⁰𑘁₀]𓀄ᚡ8⑨ఁ³あခ{𓀅𑘂₁⑩⁅𓀆𓀇𑘃ᚢ𐀀𑘄①ぃᚣ7₇ం2いಀ⁆𓀈𑘅↉}𓀉𑘆⑴ぅᚤ⑦⑺ః²うဂ⁽𓀊𓀋⓪𑘇⒈ぇ4₈ఄ𐀁𑘈ᚥ⁾𓀌𑘉ᚦ⓵ऀ₍𓀍ᚧ𐀂⓿₎𓀎❶ँ)
  • TSG の hakatashi さんが作った言語。Unicode 各文字のプロパティが命令の種類になるという非常に面白い仕様だが、ソースコードに同じ文字が含まれていはいけないという制約から書きづらいものとなっている。
  • 数値として使える文字を探してくるのが特に大変だった。
  • 方針は大体 #algo-blue-cd と同じ。
  • ループにバグがあるが、ダミー命令を適当に挟むことで解決する。
  • 書くのが大変だったので、手元にインタプリタと UCD (Unicode Character Database)を用意した。生成に使ったスクリプトを置いておく。
  • https://gist.github.com/n4o847/02f7bb20ddff19cc6d85224cd637940b

Unlambda (@satos___jp, 1046 bytes)

コードを見る
``````s``s``s`ksk`k``s`kd``sii``s``s`ksk`k``s`kd``sii``s`k`s`k``s``s``s`k`kii`k@``s`kk``s`k.Ti``s``s`ks``s`kk``s`k`s``si`ki``s`k`s`kd``s``s`ksk`ki`k``s`k```s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk``s``s`ksk`ki``s``s``s`k`kii`k@``s`k`s``s``s`ks``s`k`s``si`k.X``s`kk``s``s``s``si`k? `k``s`kc``s`k`s`k`k`ki``s``s`ks``s``s`ksk`ki`k`kk`k. `k.
`ki``s`k`s``s``s``si`k?K`k``s`kc``s`k`s`k`k`ki``s``s`ks``s``s`ksk`ki`k`kk`kkki`.T```si`k`ki`````s``s``s`ksk`k``s`kd``sii``s``s`ksk`k``s`kd``sii``s`k`s``si`k@``s`kk``s`k`s``s``s``si`k?T`k``s`kc``s`k`s`k`k`ki``s``s`ks``s``s`ksk`ki`k`kk`ki``s`kk``s`kd``si`k. iiii

Unreadable (@satos___jp, 1888 bytes)

コードを見る
'""""'""""'"""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'"'""""""""""'"""'""""""'"""'""""""""'"""'"""""'""""""""'"""""""'"""'""""'""""'""""""'""'"""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'""'"""'"""""'"""""""'""'"""'""""'"""""""""'"""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""""'""""""'""'""'"""'""""""""""'"""""""'"""'""""""'"""'"""'"'""'"""""""'""'""'"""'"'"""""""'""'""'"""'""""""'""'"""'""""""""'"""""""'""'"""'"'""'""""""""""

Verilog (Icarus Verilog) (@shell_mug, 133 bytes)

module a;reg[407:0]c,i;initial begin c=$fgets(i,1<<31);while($fgets(c,1<<31))$write("%s",i);$write("%s",c-i&{99{4'h7}});end endmodule

文字列を51*8=408bitのレジスタに格納している。すべての行を読み終わって2個目の$write関数まで到達したとき、

c   = 408'h20_…_20_4B_20_…_20_20_20_…_20_0A
i   = 408'h20_…_20_20_20_…_20_54_20_…_20_0A
c-i = 408'h00_…_20_2C_FF_…_FF_CC_00_…_00_00

になる。 c-i をいい感じの文字列として出力するため、{99{4'h7}} = 396'h77_77_…_77_77 とのビット積をとって

c-i&{99{4'h7}} = 408'h00_…_00_24_77_…_77_44_00_…_00_00

を出力した。本来なら {102{4'h7}} としないと'K'がかなり左にあった場合にWAになるが、確率は低いので無視した。あと、VerilogはNULLを半角空白として出力するので、わざわざNULLを' 'に変換する必要はない。 ところで、$write関数や$fgets関数をそれぞれ2回使っているので、方針を変えるとさらに縮まる。(118bytes)

module a;reg[407:0]c,i=0;initial while($fgets(c,1<<31))begin if(c>i)i=c-i&{99{4'h7}};i|=c;$write("%s",i);end endmodule

Vim (@coil_kpc, 11 bytes)

<C-v>GrRjl<C-v>)dZZ

長方形を先に塗っていらないところを消す方針。消す時に空白で上書きするよりdしてしまった方が短い。

wake (@drafear, 54 bytes)

all:$<
(.*T\D{50}) (.*):$1T$2
(.*K) (.*):$1K$2
.*:"$&"

読んだ通り。

Whitespace (@satos___jp, 273 bytes)


   
   
	
	    
			 
 	
     		
	 		 
 	  
   
 
		  	
		 
   

  	
   		   	

  	 
 
	 
    
	
	    
				    
 	
     		
	 		 
 	  
   
 
		  	
				
   	
	   
  		
 
	 
    	
	  	 
	 
 	  
   
 
		  	
			 
   
	
	    
			 
		  		
   
    	 
	  	 
 	  
   
 
		  	
			




Width (@satos___jp, 376 bytes)

GAWiMQwwAQQwwwMwAiiMMcwiiQfQwQWwwwAQwMaiMiWfFwawaMawWMFQaMFwWQQwawaiMiQMfiQfcMMiWiiQaQiiiiQAciQiiQaQMiiMMiiwWQwMawWiiiMwWMMQaMFiMMiMcQaQMMFiMMfffiQwiQMiQffMMfFMcMaMFMcQaMiiMiWffiMQwwWQMiMMffFMcMaMFMcQaMiiMiWiWfaQwwWQMiMMMfFMcMaMFMcQaMiiMiWiWiWfiiQfiiQiWiWiiQaQiiiiQFaiQiiQaQMiiMMiiwWQwMawWiiMiMcQaQMMFiMMfiWiWiWiMQaQMMiMAMFiMiWiWiiQiQWMciiwaiiQaQMiiMcwAQMQfwWiMfQfwfwiWwfGwwAw

命令を眺めると、任意文字列に対してpythonのevalが呼べることがわかる(https://github.com/stestoltz/Width/blob/5debe5b7cf40f7b9b79e33f0b87dd18bd6ceb22f/width.py#L319)ので、あとはpythonのワンライナー([(lambda x: globals().__setitem__('q',x) if 'T' in x else (exit(print(q+'\\n'+x.rstrip()+(len(q.rstrip())-len(x.rstrip()))*'*')) if 'K' in x else print(q)))(input()) for _ in range(100)])を書くと解ける。以下は生成スクリプト。 (https://github.com/satos---jp/Esolang-Snippets/blob/93a899bfd0d0fd3648762baef437a59e102ed68d/width.py)

WysiScript (@yamerarenaku, 6852 bytes)

コードを見る
<q style="font:bold 7% monospace;color:coral;background:#572"></q><q style="font:normal 7% monospace;color:black;background:#605;text-decoration:underline" class="nonsyntax"></q><q style="font:normal 7% monospace;color:#0AA;background:#503;text-decoration:underline" class="nonsyntax"></q><q style="font:bold 7% monospace;color:#6E7;background:#CCC"></q><q style="font:bold 7% monospace;color:teal;background:#FFF"><q style="font:bold 6% monospace;color:#F0FFF0;background:#913"><q style="font:bold 5% monospace;color:#7FFF00;background:#572"><q style="font:normal 4% monospace;color:#572;background:#FFF"></q><q style="font:normal 4% monospace;color:#503;background:#FFF"></q><q style="font:normal 4% monospace;color:#002001;background:#FFF;text-decoration:underline" class="nonsyntax"></q></q><q style="font:bold 5% monospace;color:#ADD;background:#503"><q style="font:normal 4% monospace;color:#503;background:#FFF"></q><q style="font:normal 4% monospace;color:#0AA;background:#FFF;text-decoration:underline" class="nonsyntax"></q></q><q style="font:bold 5% monospace;color:#ADD;background:#605"><q style="font:normal 4% monospace;color:#605;background:#FFF"></q><q style="font:normal 4% monospace;color:#0AA;background:#FFF;text-decoration:underline" class="nonsyntax"></q></q></q><q style="font:bold 6% monospace;color:#F0FFF0;background:#FACADE"><q style="font:bold 5% monospace;color:#6E7;background:#CCC"></q><q style="font:bold 5% monospace;color:#70661E;background:#FFF"><q style="font:bold 4% monospace;color:plum;background:transparent"><q style="font:normal 3% monospace;color:#CCC;background:transparent"></q><q style="font:normal 3% monospace;color:#002001;background:transparent;text-decoration:underline" class="nonsyntax"></q></q></q></q></q><q style="font:normal 7% monospace;color:#605;background:#1D4"></q><q style="font:bold 7% monospace;color:teal;background:#FFF"><q style="font:bold 6% monospace;color:#F0FFF0;background:#913"><q style="font:bold 5% monospace;color:#1FE15E;background:#FFF"><q style="font:bold 4% monospace;color:#DDA0DD;background:transparent"><q style="font:normal 3% monospace;color:#CCC;background:transparent"></q><q style="font:normal 3% monospace;color:#0A1;background:transparent;text-decoration:underline" class="nonsyntax"></q></q><q style="font:bold 4% monospace;color:#F0FFF0;background:#913"><q style="font:bold 3% monospace;color:#7FFF00;background:#572"><q style="font:normal 2% monospace;color:#572;background:#FFF"></q><q style="font:normal 2% monospace;color:#503;background:#FFF"></q><q style="font:normal 2% monospace;color:#0A1;background:#FFF;text-decoration:underline" class="nonsyntax"></q></q><q style="font:bold 3% monospace;color:#ADD;background:#503"><q style="font:normal 2% monospace;color:#503;background:#FFF"></q><q style="font:normal 2% monospace;color:#0AA;background:#FFF;text-decoration:underline" class="nonsyntax"></q></q><q style="font:bold 3% monospace;color:#D1FFE2;background:#1D4"><q style="font:normal 2% monospace;color:black;background:#FFF;text-decoration:underline" class="nonsyntax"></q><q style="font:normal 2% monospace;color:#0AA;background:#FFF;text-decoration:underline" class="nonsyntax"></q></q></q><q style="font:bold 4% monospace;color:#DDA0DD;background:transparent"><q style="font:normal 3% monospace;color:#CCC;background:transparent"></q><q style="font:normal 3% monospace;color:#004B01;background:transparent;text-decoration:underline" class="nonsyntax"></q></q><q style="font:bold 4% monospace;color:#F0FFF0;background:#991234"><q style="font:bold 3% monospace;color:#7FFF00;background:#572"><q style="font:normal 2% monospace;color:#572;background:#FFF"></q><q style="font:normal 2% monospace;color:#503;background:#FFF"></q><q style="font:normal 2% monospace;color:#104;background:#FFF;text-decoration:underline" class="nonsyntax"></q></q><q style="font:bold 3% monospace;color:#ADD;background:#503"><q style="font:normal 2% monospace;color:#503;background:#FFF"></q><q style="font:normal 2% monospace;color:#0AA;background:#FFF;text-decoration:underline" class="nonsyntax"></q></q><q style="font:normal 3% monospace;color:#0AA;background:#444;text-decoration:underline" class="nonsyntax"></q></q><q style="font:bold 4% monospace;color:#DDA0DD;background:transparent"><q style="font:normal 3% monospace;color:#1D4;background:transparent"></q><q style="font:normal 3% monospace;color:#605;background:transparent"></q></q><q style="font:bold 4% monospace;color:#F0FFF0;background:#913"><q style="font:bold 3% monospace;color:#7FFF00;background:#572"><q style="font:normal 2% monospace;color:#572;background:#FFF"></q><q style="font:normal 2% monospace;color:#503;background:#FFF"></q><q style="font:normal 2% monospace;color:#104;background:#FFF;text-decoration:underline" class="nonsyntax"></q></q><q style="font:bold 3% monospace;color:#ADD;background:#503"><q style="font:normal 2% monospace;color:#503;background:#FFF"></q><q style="font:normal 2% monospace;color:#0AA;background:#FFF;text-decoration:underline" class="nonsyntax"></q></q><q style="font:normal 3% monospace;color:black;background:#444;text-decoration:underline" class="nonsyntax"></q></q><q style="font:bold 4% monospace;color:#F0FFF0;background:#ADD"><q style="font:bold 3% monospace;color:#7FFF00;background:#572"><q style="font:normal 2% monospace;color:#572;background:#FFF"></q><q style="font:normal 2% monospace;color:#503;background:#FFF"></q><q style="font:bold 2% monospace;color:#1FE15E;background:#FFF"><q style="font:normal 1% monospace;color:#444;background:transparent"></q><q style="font:normal 1% monospace;color:#104;background:transparent;text-decoration:underline" class="nonsyntax"></q><q style="font:normal 1% monospace;color:#002001;background:transparent;text-decoration:underline" class="nonsyntax"></q></q></q><q style="font:bold 3% monospace;color:#ADD;background:#503"><q style="font:normal 2% monospace;color:#503;background:#FFF"></q><q style="font:normal 2% monospace;color:#0AA;background:#FFF;text-decoration:underline" class="nonsyntax"></q></q></q></q><q style="font:bold 5% monospace;color:#ADD;background:#1D4"><q style="font:normal 4% monospace;color:#1D4;background:#FFF"></q><q style="font:normal 4% monospace;color:#0AA;background:#FFF;text-decoration:underline" class="nonsyntax"></q></q></q><q style="font:bold 6% monospace;color:#F0FFF0;background:#FACADE"><q style="font:bold 5% monospace;color:#6E7;background:#CCC"></q><q style="font:bold 5% monospace;color:#DDA0DD;background:#FFF"><q style="font:normal 4% monospace;color:#CCC;background:transparent"></q><q style="font:normal 4% monospace;color:#E0F;background:transparent;text-decoration:underline" class="nonsyntax"></q></q></q></q><q style="font:bold 7% monospace;color:#FACADE;background:#FFF"><q style="font:normal 6% monospace;color:#572;background:transparent"></q></q>

x86 Assembly (nasm) (@k_hanazuki, 48 bytes)

ディスアセンブルしたものにコメントを書いたもの:

  global _start
_start:
  ;; ediには初期状態で大きい値が入っている
.loop:
  ;; 小さい即値をレジスタに入れるのはpush/popが安い
  push 3
  pop eax                       ; eax <- 3 (readのsyscall番号)
  xor ebx,ebx                   ; ebx <- 0 (stdin)
  mov ecx,esp                   ; ecx <- 適当に読み書きできるメモリアドレス
  push 1
  pop edx                       ; edx <- 1 (read/writeのバイト数)
  int 0x80

  ;; 足して255を超えないときは8ビットの即値ADDが得
  ;; readの戻り値としてeaxに1が入っている
  add al,3                      ; eax <- 4 (writeのsyscall番号)

  ;; INC/DECは32ビットのほうが命令長は短い
  inc ebx                       ; ebx <- 1 (stdout)

  ;; メモリ/即値のCMPは単体の命令長では不利だが,レジスタを破壊しないほうが全体として短くなるので使った.
  cmp byte[ecx],75              ; K
  jz .putk
  cmp byte[ecx],84              ; T
  jz .putt

  dec edi
  jnz .put
  inc byte[ecx]                 ; Tの真下にいるときは文字をインクリメント
.putt:
  push 51
  pop edi
.put:
  int 0x80

  jmp .loop
.putk:
  int 0x80
  add al,3                      ; eax <- 4 (writeのsyscall番号)
  dec edi
  jnz .putk                     ; Tの真下まで来たら終わり

  ;; ここから先にはNULが続く
  ;; 00 00 は add byte[eax],al なので,SEGVで停止する

ショートジャンプの距離が10(LF)や13(CR)になるとnasmのソースコードに文字列として埋め込む際にエスケープが必要になるので,命令を並べ替えたりしている.

Z80 (@drafear, 57 bytes)

アセンブリを書いて z80asm を使ってコンパイルした。

命令セットは http://www.yamamo10.jp/yamamoto/comp/Z80/instructions/index.php を参照。

ゴルフしていません。

コンパイル前コードを見る
putchar:equ	08000h
getchar:equ	08003h

	ld	D,1
	ld	E,1

loop:
	call	getchar
	ld	B,A
	; if C == 'T' then D = 0
	ld	A,B
	cp	'T'
	jr	NZ,endif_T
	ld	D,0
endif_T:
	; if C == 'K' then E = 0
	ld	A,B
	cp	'K'
	jr	NZ,endif_K
	ld	E,0
endif_K:
	; if D == 0 || E == 0 then putchar 'X'
	ld	A,D
	cp	0
	jr	Z,if_C
	ld	A,E
	cp	0
	jr	Z,if_C
	ld	A,B
	jr	endif_C
if_C:
	ld	A,'X'
	jr endif_C
endif_C:
	; output
	call	putchar
	; if D == 0 and E == 0 then exit
	ld	A,D
	or	E
	jr	NZ,endif_halt
	halt
endif_halt:
	; D = (D+1)%51
	inc	D
	ld	A,D
	cp	51
	jr	NZ,endif_step
	ld	D,0
endif_step:
	jr	loop
Clone this wiki locally