mitchsさんはすごい。

1st 2nd 3rd 4th

perl

51byte

#!perl -p
s/.$/$&.((0,st,nd,rd)[$`%10-1&&$&]||th)/e

mitchs氏/teebee氏/tails氏/nai氏 41byte

#!perl -pl
$_.=(!/1?.$/,st,nd,rd)[$&]||th

まったく同一。きれい。

sed 47byte

s/$/th/
/1.t/b
s/1th/1st/
s/2th/2nd/
s/3th/3rd/

mitchs氏 tails氏と並んで1位。 問題が単純だった。 解答もかなり似ている。

brainfuck 277byte

>
,+[-
    [>+>>+>+<<<<-] dup dup
    ++++++++++[>->>-----<<<-] is not newline and minus two based number
    + then >[<->[-]]> + else <<[- if newline
        >>>[+]>[<+++++++++++>>+<-]<<<<
        +<<[>>-<<-[>>+<<[-]]]>>[ if not teen
            <
            [- [- [- [- >[-]< ] switch
            >[-
                >>>++++.<+[>-------<-]>.<<< rd
            ] <] >[-
                >>>.----------.<-<< nd
            ] <] >[-
                >>>+++++.+.<-<< st 1
            ] <] >[-]
        ]
        >>[- if not put yet
            >++++++.------------.< th
        ]<
        >>>>.> newline
    ]>>[-
        >++[<<<+>>>-]>.[-]<< move
    ]<
    shift one
,+]

golfするには重たい問題だったように思う。1位に100byte差。

mitchs氏 168byte

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

いたるところunbarancedなwhileで怖い。

解読
,+[-. until eof
    >-
    [
        +[+++++++++.>] 1 9
        ,
        >++++++++ 8
        [<-<------>>-] 1 6
        <-- 2
    ] while not newline
    <<-
    [<[-]] if c1 ne 1
    >>>+
    <--
    [ break if 2
        >+>-<<-
        [ break if 3
            [+>>] twice
            +<+++<<<+ 3
            [ break if 1
                >>+>->-
            ]
        ]
    ]
    -
    >[>>+>>]
    <<<<++ 2
    [
        +
        [>+++++<-] 5
        ++++++++++ 10
        [<+>>+++++++++<-] 9
        >.
        [-]>
    ]
    <<<.
,+]
        >-
        [
            +[+++++++++.>] 1 9
            ,
            >++++++++ 8
            [<-<------>>-] 1 6
            <-- 2
        ] while not newline

1行読む。[cn] ... 0 0 0から始めて、改行を読んだ後cn-48 ... c1-48 c0-48 [0]で終わる。読んだ内容は改行を除いてechoされる。

            +[+++++++++.>] 1 9

-1でないなら総計$10$足して出力しずれる。

        ,
        >++++++++ 8
        [<-<------>>-] 1 6
        <-- 2

次の文字を読み、前の文字に$-48$、今読んだ文字に$-10$。 newlineなら脱出し、そうでないなら$-10$されたまま次へ。

    <<-
    [<[-]] if c1 ne 1

$10$の位が$1$のときの処理。 そうか否かに応じてずれる。 $10$の位c1が$1$ならcn ... c2 [0] c0 0。そうでないならcn ... [0] c1-1 c0 0

    >>>+
    <--
    [ break if 2
        >+>-<<-
        [ break if 3
            [+>>] twice
            +<+++<<<+ 3
            [ break if 1
                >>+>->-
            ]
        ]
    ]

ふたつ右の値でswitch。基本は$1$の位で変化するが、$10$の位が$1$によりずれているなら$1$の位は$0$と認識される。

  • $1$の位が$2$
    • x 0 y [0] 1
  • $1$の位が$3$
    • x 0 y [0] 2 -1
  • $1$の位が$1$
    • x 0 y [0] 2 0 3 1
  • それ以外
    • 2 1 2 [0]
    -
    >[>>+>>]
    <<<<++ 2

素材の向きを揃える。

  • $1$の位が$2$
    • [3] 0 1 0
  • $1$の位が$3$
    • [4] -1 1 0
  • $1$の位が$1$
    • [4] 0 4 1
  • それ以外
    • [4] 1 2 -1
    [
        +
        [>+++++<-] 5
        ++++++++++ 10
        [<+>>+++++++++<-] 9
        >.
        [-]>
    ]
    <<<. newline

出力。 loopの1周はx [a] b cからx+10 0 0 [c]で、$95 + 5a + b$が.される。

char code $a$ $b$
t $116$ $4$ $1$
h $104$ $2$ $-1$
s $115$ $4$ $0$
n $110$ $3$ $0$
d $100$ $1$ $0$
r $114$ $4$ $-1$

控えておいたnewlineを出力して次へ。右側はきれいな状態。

mitchs氏 (cheat) 168byte

-<+],+[-.+>-[+[+++++++++.+>],>++++++++[<-<------>>-]<--]<-<--[+<[-]]+>+>[>+<-[>+<-[>+<-[>]]]]+>[[<]-[>]<-]+[<]>.>.>-[++>>>-]+>.[>],+\x00rd\x00nd\x00st\x00th\x01\n_]
解読
-<+]
,+[-.
    +
    >-
    [
        +[+++++++++.+>] 1 9 1
        ,
        >++++++++ 8
        [<-<------>>-] 1 6
        <-- 2
    ] while not newline
    <-<--
    [+<[-]]
    +>+>
    [>+<-
        [>+<-
            [>+<-
                [>]
            ]
        ]
    ]
    +>
    [[<]-[>]<-]
    +[<]>.>.>-
    [++>>>-]
    +>.
    [>]
,+
    \0rd\0nd\0st\0th\x01\n_
]
-<+]

cheat。]ではinstruction pointerはcode先頭まで戻る。data pointerがcode領域に乗り上げ、その終端で止まる。getcによるEOFがあって$-1$のため。 ... \n _ ] [0]

    +
    >-
    [
        +[+++++++++.+>] 1 9 1
        ,
        >++++++++ 8
        [<-<------>>-] 1 6
        <-- 2
    ] while not newline

1行読む。非cheatedとだいたい同じ。... code cn-48+1 ... c1-48+1 c0-48+1 [0]。 1-based numberを作る。

    <-<--
    [+<[-]]
    +>+>

$10$の位が$1$のときの処理。 $10$の位c1の表現が$2$なら... code cn+1 ... c2+1 1 c0+1 [0]。そうでないなら... code cn+1 ... 1 c1+1 [c0] 0。 0-basedに戻す。

1行目の処理の際にはcode領域が近い。例えば... \n _ ] 1 [0]から始まると、... \n 1 ] [1] 0である。_が破壊される。この文字は\x01等でもよい。

    [>+<-
        [>+<-
            [>+<-
                [>]
            ]
        ]
    ]
    +>

$4$以上を$0$に。高々$3$つまで右に動かしてずれ、穴を埋める。[c] 0 0から、

  • $1$の位が$0$
    • 1 [0] 0 0
  • $1$の位が$1$
    • 1 [1] 0 0
  • $1$の位が$2$
    • 1 [2] 0 0
  • $1$の位が$3$
    • 1 [3] 0 0
  • それ以上
    • c-3 3 1 [0]

左にはnon-zeroなごみがcodeまで続いている。

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

    ...
,+
    \0rd\0nd\0st\0th\x01\n_
]

出力。 code ... , + \0 r d \0 n d \0 s t \0 t h \x01 \n _ ] nonzeros ... [c]から。 cの数だけ\0を$-1$で埋め、cのあった場所を$1$にし、残った\0で最も右のものの右ふたつの文字を出力。 この時点で入力によらずcode領域の右側に2個以上のnon-zeroがあり、次のloopではcodeの破壊(1周目では_の位置が壊された)がなされないことに注意。

    >-
    [++>>>-]
    +>.
    [>]
,+
    \0rd\0nd\0st\0th\x01\n_
]

足場にした$-1$を$0$に変えながら右に動き、\x01を$0$にして止まる。これを$1$に戻して隣のnewlineを出力。その後右に脱出。