この質問には浮き沈みがあります


33

入力は次の文字で構成されます。

  • ^:1つ上へ
  • v:1つ下に行く
  • またはk:2つ上に移動します
  • またはj:2つ下に移動します

たとえば、次の入力:

^^▲^v▼▲^^v

次の出力が生成されます。

        ^
   ^   ^ v
  ▲ v ▲

 ^   ▼
^

などのカーソルを移動するエスケープシーケンス\e[Bは許可されません。スペースと改行を使用して出力を生成する必要があります。

ここにさらにいくつかのテストケースがあります。

▲v^v^v^v^v^v^v^v▲

                ▲
▲ ^ ^ ^ ^ ^ ^ ^ 
 v v v v v v v v

^^^^^^^▲▲▲▼▼▼vvvvvv

         ▲

        ▲ ▼

       ▲   ▼

      ^     ▼
     ^       v
    ^         v
   ^           v
  ^             v
 ^               v
^                 v

v^^vv^^vvv^v^v^^^vvvv^^v^^vv

  ^   ^         ^
 ^ v ^ v       ^ v       ^
v   v   v ^ ^ ^   v   ^ ^ v
         v v v     v ^ v   v
                    v

1
末尾のスペースは許可されますか?空行?
xnor

2
Unicodeをサポートしない言語はどうですか?代替文字を使用できますか?
ドアノブ

1
@xnor末尾のスペースや空行が許可されます。
アブサン

2
@Doorknob私はj二度降りることと二度上がることを許しますk
アブサン

1
@xnor私の悪い:/コメントは正しく、ルールを間違って編集しました。今修正します。
アブサン

回答:


9

Pyth、27バイト

jCm.<.[*5lzd\ =+Ztx"v ^k"dz

オンラインで試す:デモンストレーションまたはテストスイート

kandのj代わりにand を使用します。前後に空の行がたくさんあります。画像を見つけるにはかなり検索する必要があります。これは34バイトバージョンで、先頭と末尾の空行をすべて削除します。

j.sCm.<.[*5lzd\ =+Ztx"v ^k"dz]*lzd

オンラインで試す:デモンストレーションまたはテストスイート

説明:

jCm.<.[*5lzd\ =+Ztx"v ^k"dz  implicit: Z = 0
  m                       z  map each char d from input string z to:
                  x"v ^k"d     find d in the string "v ^k", -1 if not found
                 t             -1, that gives -2 for j, -1 for v, 1 for ^ and 2 for k
              =+Z              add this number to Z
     .[*5lzd\                  append spaces on the left and on the right of d, 
                               creating a 5*len(input_string) long string
   .<           Z              rotate this string to the left by Z chars
jC                           transpose and print on lines

16

読み取り不可2199 2145 2134 2104 2087 2084バイト

両方をサポートk/ jなど/ 構文。

読みやすくない伝統では、アポストロフィと二重引用符の区別をわかりにくくするために、プロポーショナルフォントでフォーマットされたプログラムがあります。

'"" "" ""' "" "" "" "" '"" "'" "'" "'" "'" "'" "" '"" "" "'" "" "" "'' "" '""' "" "" "'" ""' "" '"" "" ""' "" "" "" "" "" "" "" '"" "" ""' " "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""' "" "" "" "" "'"" ""' "" "" '"" "" ""' "" '""' "" '""' "" '"" "'" "'" ""' "" "" "" '""' "" '""' "" '"" "'" "" "" "" "" "" "" "" "" "" "" "" "'" "'" "''" "'" ""' "" "" "" "" '"" "" "" "" ""' "" '""' "" "" "" '"" "" "" "" """'" "'" "" "" '""' "" '"" "'" "" "" "" "" '"" "" "" "'" "'" "'" "'" " '""' "" "'" "" "" "" "'" "" "" "" '""' "" '""' "" '""' "" "'" "'" "' "" "" "" "" "'" ""' "" "" "" "" "'" "" "" "" "" "" "" "" "" "" ""'"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "" "" ""' '" "" '"" "" "" "" "'" "'" "" "" ""' "" "'" "" "" "" "" ""' "" '"" "" "" "" "" '"" "" "" "'" "'" "'" "" '""' "" "'" "" "" "" ""' "" "" "" "'""' "" '""' "" "" "'" ""' "" "'" "'" "'" ""' "" "" "" '"" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "'" "'" "" "" "" "" "" "" "" "" "" " "" "" '"" "" "'" "'" "'" "" "" "" '"" "'" "" '""' "" '"" "'" "'" ""'" "" "" "" "" "" "" "" "" ""' "" '""' "" '"" "" ""' "" "" "" "" '" "" "" "" "" "" "" "" '""' "" "" "'" "'" "" "" "" "" "" '"" "" "" "'" "'" "'" "" "" '"" "'" "" "'" "" "'" "" "" "" "" "" "" "" "'" "'" "'""' "" "'" "" "" "'" "'" "'" "'" ""' "" '"" "" "" "'" "'" "'" "'" " "'" "" "" "" "" "'" "'" "'" "" '""' "" "" "" "'" "'" "'" ""' "" "" "" '""' "" "'" "" "" "" "'" "" "" "" '""' "" "" "" "" "" "" "" "'" ""'"" "" "" "" "" "" "" "'" ""' "" "" '"" "" "" "" "" "" "'" "'" "" "" " '"" "" "" ""' "" "" "" "'" "" ""' "" '"" "" "" "" "" "" "" "" "" ""' " "'" "'" "" '"" "" ""' "" '""' "" "'" "" "" "" "" "" "" ""' "" '""'"" "'" "" '"" "" ""' "" '"" "'" "'" "" "" ""' "" '"" "'" "" "" "'" " '"" "" "" "'" "" "" "" "'" ""' "" '"" "" "" "'" "'" ""' "" "" "" "" "" "" "" '"" "" ""' "" '""' "" '"" "'" "'" "" "" "'" "'" "'" "'" ""'"" ""' "" "" "" '""' "" "'" "" "" "" "'" "" "" "" '""' "" "'" "" "" "" '""' "" '"" "'" "'" "" "" ""' "" '""' "" "" "" "" "" "" "" "" "'" "" "" "" "" "" "" "" '"" "" "" "'" "'" "" "" "" "" "" "" "" "" "'" "'"" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "'" "" "" "" "" "" "" " "'" "" "" "" "" "" "'" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "" '"" "'" "'" "" "" ""' "" "" "" "'" ""' "" "" "'" "'" "'" "" "" "'"" "" "" "" "" "" "" "" "" "" "" "" "'" "" "" "" "" "" ""' "" "" "" "" "'" "" "" "" "" "" "" "" "" "" ""' "" '""' "" "" "" "" "'" "'" "'" " '"" "" "" "" "" "" "" "" "" ""' "" "" "" "" "" "" "" "" "" "" "" "" ""'" "" "" "" "" "" "" "" "" "" "" ""' "" "" "" "" "" "'" "" "" ""' '" "" "" "" '"" "" "" ""' "" "'"' "" "" "" "" "" "" "" "" '"" "" "" ""' '" "" '""' "" '"" "" "" "'" "" '"" "" "" ""' "" "" "" "'" "'" "" "" ""'" "" "" "" ""' "" '""' "" "" "'" "'" "'" "'" "'" "'" "'" "'" "'" " '""' "" '""' "" '""' "" '""' "" "" "" "" "" "" "" '"" "" "" "" "" "" " "" '"" "'" "" "" "'" "" "" "" "'" "" '"" "" "" "" "" ""' "" "'"' """" "" "'" "'" ""

これは驚くべき挑戦でした。投稿していただきありがとうございます!

説明

Unreadableができることとできないことの感覚をつかむために、両方向に無限のテープを持つBrainfuckを想像してください。しかし、一度に1つのセルを移動するメモリポインターの代わりに、ポインターを逆参照することで任意のメモリセルにアクセスできます。これは、このソリューションでは非常に役立ちますが、モジュロを含む他の算術演算は手動で行う必要があります。

以下は、監督のコメント付きの擬似コードとしてのプログラムです。

// Initialize memory pointer. Why 5 will be explained at the very end!
ptr = 5

// FIRST PASS:
// Read all characters from stdin, store them in memory, and also keep track of the
// current line number at each character.

// We need the +1 here so that EOF, which is -1, ends the loop. We increment ptr by 2
// because we use two memory cells for each input character: one contains the actual
// character (which we store here); the other will contain the line number at which the
// character occurs (updated at the end of this loop body).
while ch = (*(ptr += 2) = read) + 1:

    // At this point, ch will be one more than the actual value.
    // However, the most code-economical way for the following loop is to
    // decrement inside the while condition. This way we get one fewer
    // iteration than the value of ch. Thus, the +1 comes in handy.

    // We are now going to calculate modulo 4 and 5. Why? Because
    // the mod 4 and 5 values of the desired input characters are:
    //
    //  ch  %5  %4
    //  ^   1
    //  v   2
    //  k   3
    //  j   4
    //  ▲   0   2
    //  ▼   0   0
    //
    // As you can see, %5 allows us to differentiate all of them except ▲/▼,
    // so we use %4 to differentiate between those two.

    mod4 = 0      // read Update 2 to find out why mod5 = 0 is missing
    while --ch:
        mod5 = mod5 ? mod5 + 1 : -4
        mod4 = mod4 ? mod4 + 1 : -3

    // At the end of this loop, the value of mod5 is ch % 5, except that it
    // uses negative numbers: -4 instead of 1, -3 instead of 2, etc. up to 0.
    // Similarly, mod4 is ch % 4 with negative numbers.

    // How many lines do we need to go up or down?
    // We deliberately store a value 1 higher here, which serves two purposes.
    // One, as already stated, while loops are shorter in code if the decrement
    // happens inside the while condition. Secondly, the number 1 ('""") is
    // much shorter than 0 ('""""""""'""").
    up = (mod5 ? mod5+1 ? mod5+3 ? 1 : 3 : 2 : mod4 ? 3 : 1)
    dn = (mod5 ? mod5+2 ? mod5+4 ? 1 : 3 : 2 : mod4 ? 1 : 3)

    // As an aside, here’s the reason I made the modulos negative. The -1 instruction
    // is much longer than the +1 instruction. In the above while loop, we only have
    // two negative numbers (-3 and -4). If they were positive, then the conditions in
    // the above ternaries, such as mod5+3, would have to be mod5-3 etc. instead. There
    // are many more of those, so the code would be longer.

    // Update the line numbers. The variables updated here are:
    // curLine = current line number (initially 0)
    // minLine = smallest linenum so far, relative to curLine (always non-positive)
    // maxLine = highest linenum so far, relative to curLine (always non-negative)
    // This way, we will know the vertical extent of our foray at the end.

    while --up:
        curLine--
        minLine ? minLine++ : no-op
        maxLine++

    while --dn:
        curLine++
        minLine--
        maxLine ? maxLine-- : no-op

    // Store the current line number in memory, but +1 (for a later while loop)
    *(ptr + 1) = curLine + 1

// At the end of this, minLine and maxLine are still relative to curLine.
// The real minimum line number is curLine + minLine.
// The real maximum line number is curLine + maxLine.
// The total number of lines to output is maxLine - minLine.

// Calculate the number of lines (into maxLine) and the real minimum
// line number (into curLine) in a single loop. Note that maxLine is
// now off by 1 because it started at 0 and thus the very line in which
// everything began was never counted.
while (++minLine) - 1:
  curLine--
  maxLine++

// Make all the row numbers in memory positive by adding curLine to all of them.
while (++curLine) - 1:
  ptr2 = ptr + 1
  while (ptr2 -= 2) - 2:    // Why -2? Read until end!
    *ptr2++

// Finally, output line by line. At each line, we go through the memory, output the
// characters whose the line number is 0, and decrement that line number. This way,
// characters “come into view” in each line by passing across the line number 0.
while (--maxLine) + 2:    // +2 because maxLine is off by 1
  ptr3 = 5
  while (ptr -= 2) - 5:
    print (*((ptr3 += 2) + 1) = *(ptr3 + 1) - 1) ? 32 : *ptr3   // 32 = space
  ptr = ptr3 + 2
  print 10  // newline

プログラムロジックについてはこれだけです。次に、これを判読不能変換し、さらにいくつかの興味深いゴルフトリックを使用する必要があります。

変数は、読み取り不能で数値的に常に間接参照されます(例:のa = 1ようになります*(1) = 1)。数値リテラルの中には、他のものよりも長いものがあります。最短は1で、2が続きます。負の数がどれだけ長いかを示すために、-1〜7の数を次に示します。

-1  '""""""""'""""""""'"""  22
 0  '""""""""'"""           13
 1  '"""                     4
 2  '""'"""                  7
 3  '""'""'"""              10
 4  '""'""'""'"""           13
 5  '""'""'""'""'"""        16
 6  '""'""'""'""'""'"""     19
 7  '""'""'""'""'""'""'"""  22

明らかに、コード内で最も頻繁発生する変数に変数#1割り当てます。最初のwhileループでは、これは間違いなくmod5であり、10回出現します。しかしmod5、最初のwhileループの後はもう必要ないため、後で使用する他の変数に同じメモリ位置を再割り当てできます。これらはptr2ptr3です。これで、変数は合計21回参照されます。(発生回数を自分で数えようとする場合はa++、値を取得するために1回と設定するために1回、2回などを数えることを忘れないでください。)

再利用できる変数は他に1つしかありません。モジュロ値を計算した後chは、もう必要ありません。upそしてdnそのいずれかで結構です、同じ回数を思い付きます。とマージchしましょうup

これにより、合計8つの一意の変数が残ります。変数0〜7を割り当て、8でメモリブロック(文字と行番号を含む)を開始できます。しかし!7はコードの-1と同じ長さなので、変数-1〜6を使用してメモリブロックを7から開始することもできます。このように、メモリブロックの開始位置へのすべての参照はコードでわずかに短くなります。これにより、次の割り当てが行われます。

-1    dn
 0                      ← ptr or minLine?
 1    mod5, ptr2, ptr3
 2    curLine
 3    maxLine
 4                      ← ptr or minLine?
 5    ch, up
 6    mod4
 7... [data block]

これは、最上部の初期化を説明していますこれは、 7(メモリブロックの開始)-2(最初のwhile条件での必須増分)であるため、5です。同じことが、最後のループの他の2つのオカレンス5にも当てはまります。

0と4はコードの長さが同じでptrあり、minLineどちらの方法でも割り当てることができることに注意してください。...それともできますか?

2番目の最後のwhileループの謎の2はどうですか?これは6ではないでしょうか?データブロック内の数値を減らすだけですよね?6に達すると、データブロックの外にいるので、停止する必要があります。これは、バッファオーバーフローバグエラーエラーセキュリティ脆弱性です!

停止しないとどうなるか考えてください。変数6と4を減らします。変数6はmod4です。これは最初のwhileループでのみ使用され、ここではもう必要ないため、害はありません。変数4はどうですか?変数4はどうあるべきですか、ptrそれともあるべきminLineですか?そうminLineです、この時点ではもう使用されていません!したがって、変数#4はminLine安全にデクリメントでき、ダメージを与えません!

更新1!の値の計算にまだ使用されているにも関わらず、マージdnできること認識してmod5、2199バイトから2145バイトまでゴルフをしmod5ましたdn。新しい変数の割り当ては次のとおりです。

 0    ptr
 1    mod5, dn, ptr2, ptr3
 2    curLine
 3    maxLine
 4    minLine
 5    ch, up
 6    mod4
 7... [data block]

更新2!while ループで0にカウントさmod5れると同じ変数になったため、明示的に0に初期化する必要がなくなったことを認識して、2145バイトから2134バイトにゴルフしdnましたmod5

更新3!2つのことを実現することにより、2134バイトから2104バイトまでゴルフしました。第一に、「負のモジュロ」のアイデアは価値がありましたmod5が、同じ推論は当てはまりません。これは、などmod4に対してテストしないためですmod4+2。したがって、変更mod4 ? mod4+1 : -3するmod4 ? mod4-1 : 3と2110バイトになります。第二に、mod4常に0または2であるmod4ため、0の代わりに2に初期化し、2つの3成分を(のmod4 ? 3 : 1代わりにmod4 ? 1 : 3)逆にすることができます。

更新4!モジュロ値を計算するwhileループが常に少なくとも1回実行されることを認識して、2104〜2087バイトまでゴルフを行います。したがって、while --ch: [...]; up = (mod5 ? mod5+1 ? [...]今ではなくup = ((while --ch: [...]) ? mod5+1 ? [...](そしてwhileループ内でmod4最初に計算するので、これmod5が最後のステートメントです)。

更新5!定数3210(スペースと改行)を書き込む代わりに、(今は未使用の)変数#2に数値10を格納できることを認識して、2087バイトから2084バイトまでゴルフを行います(呼び出しましょうten)。ptr3 = 5書く代わりにten = (ptr3 = 5) + 5、に32なりten+22、にprint 10なりprint tenます。


これは...ひどい... +1
kirbyfan64sos

6

CJam、37バイト

r_,2*:L3*S*f{\_iImd8-g\8>)*L+:L\t}zN*

これにより、OPで許可されている目的の出力の前後に空の行が出力されます。ます。

CJamインタープリターでオンラインで試す

使い方

r_     e# Read a token from STDIN and push a copy.
,2*:L  e# Compute its length, double it and save it in L.
3*S*   e# Push a string of 6L spaces.
f{     e# For each character C in the input, push C and the string of spaces; then
  \    e#   Swap C with the string of spaces.
  _i   e#   Push a copy of C and cast it to integer.
  Imd  e#   Push quotient and remainder of its division by 18.
  8-g  e#   Push the sign((C%18) - 8). Gives -1 for ^ and ▲, 1 for v and ▼.
  \    e#   Swap the result with the quotient.
  8>)  e#   Push ((C/18) > 1) + 1. Gives 2 for ▲ and ▼, 1 for ^ and v.
  *    e#   Multiply both results. This pushes the correct step value.
  L+:L e#   Add the product to L, updating L.
  \t   e#   Replace the space at index L with C.
}      e# We've built the columns of the output.
z      e# Zip; transpose rows with columns.
N*     e# Join the rows, separating by linefeeds.

私は...それが唯一のソリューションは、所望の出力の前後に余分な改行の大量を生産することを警告として明示的な状態に公正だと思う
Timwi

追加されました。(OPが空行を明示的に許可しているため、必要だとは思わなかった。)
デニス

3

Python 2、102

s=input()
j=3*len(s)
exec"w='';i=j=j-1\nfor c in s:i-='kv_^j'.find(c)-2;w+=i and' 'or c\nprint w;"*2*j

行ごとに印刷します。

入力内の文字をループし、現在の高さを追跡します。高さは+2, +1, -1, -2、で計算されたのいずれかによって更新され'kv_^j'.find(c)-2ます。おそらくもっと短いmodチェーンがあります

現在の高さが行番号(負の場合もあります)と等しい場合、現在の文字を行に追加し、それ以外の場合はスペースを追加します。次に、行を印刷します。実際には、現在の行番号で高さを開始し、値がヒットしたときに文字を追加して、高さの変更を減算する方が短くなります0

行番号は、アップ2またはダウン2のシーケンスがその中に留まるのに十分な範囲を網羅しています。実際には、かなりの量の過剰があります。入力の長さに上限がある場合、たとえばを書くと短くなりますj=999

驚いたことに、i and' 'or c通常よりも短かった[' ',c][i==0]。はi負の値になる可能性があることに注意してください。


2

MATLAB、116

function o=u(a)
x=0;y=1;o='';for c=a b=find(c=='j^ vk')-3;y=y+b;if y<1 o=[zeros(1-y,x);o];y=1;end
x=x+1;o(y,x)=c;end

始まりです。私は数学的にからマップする方法を見つけることができないように首の痛み作るにし、MATLABがUnicode認識していないと(MATLAB。囲碁の図の26の値を持って明らかにアップとダウンの両方を!)がありますマッピングを行うために多くのバイトが無駄になりました。jkj^vk[-2 -1 1 2]

@xnorsソリューションからインスピレーションを得て、forループ内で制御文字をマッピングすることにより、コードをさらに14文字減らすことができます。

また、入力文字列がパターンを開始位置のインデックスよりも下に送り返すかどうかを考慮するために無駄になっているバイトも多くあります(文字列の長さに制限がある場合は、そのビットを単純化できます)。

そして、読み取り可能な形式で:

function o=u(a)
%We start in the top left corner.
x=0; %Although the x coordinate is 1 less than it should be as we add one before storing the character
y=1;
o=''; %Start with a blank array
for c=a
    %Map the current character to [-2 -1 1 2] for 'j^vk' respectively.
    b=find(c=='j^ vk')-3;
    y=y+b; %Offset y by our character
    if y<1 %If it goes out of range of the array
        o=[zeros(1-y,x); o]; %Add enough extra lines to the array. This is a bit of a hack as 0 prints as a space in MATLAB.
        y=1; %Reset the y index as we have now rearranged the array
    end
    x=x+1; %Move to the next x coordinate (this is why we start at x=0
    o(y,x)=c; %Store the control character in the x'th position at the correct height.
end

だろうb=[-2 -1 1 2](a==[106 107 94 118])動作しますか?Octaveで動作します。または、b=[-2 -1 1 2](a-94==[12 13 0 24])もう1バイト削りたい場合でも!
wchargin

@WCharginは、MATLABでは機能しません。残念なことに、動作が==停止するのは停止します。また、MATLABでは、()後にaを置くことはできません[]
トムカーペンター

うーん...あなたは言語をOctaveに変えることができます!:)(オクターブもあり+=、fwiw。)
wchargin

@WCharginそれは不正行為= Pですが、私は同意します、OctaveにはMatlabにはない多くのショートカットがあります。
flawr

2

JavaScript(ES6)、140

EcmaScript 6準拠のブラウザー(Firefoxでテスト済み)で以下のスニペットを実行してテストします。

f=s=>[...s].map(c=>{for(t=r[y+=c>'▲'?2:c>'v'?-2:c>'^'?1:-1]||x;y<0;y++)r=[,...r];r[y]=t+x.slice(t.length)+c,x+=' '},y=0,r=[x=''])&&r.join`
`

// Less golfed

f=s=>(
  y=0,
  x='',
  r=[],
  [...s].forEach( c =>
    {
      y += c > '▲' ? 2 : c > 'v' ? -2 : c > '^' ? 1 : -1;
      t = r[y] || x;
      while (y < 0)
      {
        y++;
        r = [,...r]
      }  
      r[y] = t + x.slice(t.length) + c;
      x += ' '
    }
  ),
  r.join`\n`
)  


//Test

;[
  '^^▲^v▼▲^^v'
, '▲v^v^v^v^v^v^v^v▲'
, '^^^^^^^▲▲▲▼▼▼vvvvvv'
, 'v^^vv^^vvv^v^v^^^vvvv^^v^^vv'  
].forEach(t=>document.write(`${t}<pre>${f(t)}</pre>`))
pre { border:1px solid #777 }


1

GS2、34バイト

これは出力境界を正しく計算するため、余分な空白は生成されません。これが16進数のソリューションです

5e 20 76 6a 05 3e 26 ea 30 e0 6d 40 28 26 cf d3
31 e9 d0 4d 42 5e e2 b1 40 2e e8 29 cf d3 5c e9
9a 54

少し説明があります。スタックには、ASCII入力の配列としてユーザー入力があります。プログラムは、のために文字列リテラルで始まり05ます。さあ。

  5e 20 76 6a      # ascii for "^ vj"
  05               # finish string literal and push to stack
  3e               # index - find index in array or -1 if not found
  26               # decrement
ea                 # map array using block of 3 instructions (indented)

  30               # add 
e0                 # create a block of 1 instruction
6d                 # scan (create running total array of array using block)
40                 # duplicate top of stack
28                 # get minimum of array
26                 # decrement
cf                 # pop from stack into register D (this is the "highest" the path goes)

  d3               # push onto stack from register D
  31               # subtract
e9                 # map array using block of 2 instructions

d0                 # push onto stack from register A (unitialized, so it contains stdin)

  4d               # itemize - make singleton array (also is single char string)
  42               # swap top two elements in stack
  5e               # rjust - right justify string
e2                 # make block from 3 instructions
b1                 # zipwith - evaluate block using parallel inputs from two arrays
40                 # duplicate top of stack

  2e               # get length of array/string
e8                 # map array using block of 1 instruction
29                 # get maximum of array
cf                 # pop from stack into register D (this is the "lowest" the path goes)

  d3               # push from register D onto stack
  5c               # ljust - left justify string
e9                 # map array using block of two instructions
9a                 # transpose array of arrays
54                 # show-lines - add a newline to end of each element in array

GS2、24バイト

また、出力サイズの計算にそれほど注意を払わずに、余分な空白文字で終わる24バイトのソリューションもあります。ただし、ホワイトスペースが最小限に抑えられている方が好きです。

5e 20 76 6a 05 3e 26 ea 30 e0 6d d0 08 4d 42 d1
30 5e d1 5c 09 b1 9a 54

1

クレヨン、13バイト(非競合)

O"^ vj"\CynIq

オンラインでお試しください!本当の矢印を使用する理由

クレヨンはこの課題よりもずっと新しいため、競合しません。

使い方

Crayonは、ASCIIアートの課題を解決するために設計されたスタックベースの言語です。これは、2次元の出力「キャンバス」と、このキャンバスの周りを移動するカーソルである「クレヨン」に基づいて構築されています。出力に送信されるものはすべて、クレヨンの位置、およびクレヨンが向いている方向のキャンバスに描画されます。デフォルトでは、クレヨンは東(右)を指します。

O"^ v▼"\CynIq   Implicit: input string is on top of the stack
O               For each char I in the input string:
 "^ v▼"          Push this string.
       \         Swap the top two items (so I is on top).
        C        Take the index of I in the string.
                 This returns 3 for ▼, 2 for v, 0 for ^, and -1 for ▲.
         y       Move the crayon by this number of spaces on the Y-axis (south).
          n      Move the crayon one position north.
                 The crayon has now been translated 2 positions south for ▼,
                 1 south for v, 1 north for ^, and 2 north for ▲.
           Iq    Draw I at the crayon. This automatically moves the crayon forward
                 by the length of I, which is 1 in this case.

0

pb -136バイト

^w[B!0]{>}v[3*X]<[X]<b[1]^[Y]^>w[B!0]{t[B]<vw[B=0]{v}>w[T=107]{^^b[T]t[0]}w[T=94]{^b[T]t[0]}w[T=118]{vb[T]t[0]}w[T!0]{vvb[T]t[0]}^[Y]^>}

kandのj代わりにandを使用しますます。

いくつかのメモ:

  • Escape sequences that move the cursor such as \e[B are not allowed. You must produce the output using spaces and newlines.私はこのルールに従います!pbは、「ブラシ」の概念を使用して文字を出力します。ブラシは「キャンバス」の周りを動き、その直下に文字を印刷できます。ただし、実際の実装では、スペースと改行を使用して文字が出力されます。
  • 私はそれが決定を見るまで、私はそれがpbで楽しいだろうと思っていたにもかかわらず、私はこの挑戦を気にしません You are allowed trailing spaces and/or empty lines。これにはいくつかの理由があります。
    • できませ末尾にスペースを。常に長方形の出力が生成され、必要に応じてスペースが埋め込まれます。
    • このプログラムは多くの空行を生成します。出力の作成時の高さはわからないため、長さの入力のn場合はから始まりY=3n+1ます。これ-1は、から下降3nY=-1Y=2n-1allの入力に対して開始が失敗するためkです。

YouTubeでこのプログラムの動作を見ることができます!このバージョンは、わずかに変更されているだけn-1です。この入力に対しては機能しますが、他の入力に対しては失敗します。ただし、より優れたキャプチャーを行います。

コメント付き:

^w[B!0]{>}             # Go to the end of the input
v[3*X]                 # Go down 3 times the current X value
<[X]<                  # Go to X=-1 (off screen, won't be printed)
b[1]                   # Leave a non-zero value to find later
^[Y]^>                 # Back to the beginning of the input
w[B!0]{                # For every byte of input:
    t[B]                 # Copy it to T
    <vw[B=0]{v}>         # Go 1 to the right of the character to the left
                         # (either the last one printed or the value at X=-1)
                         # Move the correct amount for each character and print it:
    w[T=107]{^^b[T]t[0]} # k
    w[T=94]{^b[T]t[0]}   # ^
    w[T=118]{vb[T]t[0]}  # v
    w[T!0]{vvb[T]t[0]}   # j (Every other possibility sets T to 0, so if T is not 0
                         #    it must be j. T!0 is shorter than T=106)
    ^[Y]^>               # To the next byte of input to restart the loop
}

0

セイロン、447バイト

import ceylon.language{o=null,v=variable,s=shared}s void y(){v L c;v L f;v L l;v Integer i=0;class L(v L?p,v L?n){s v String t="";s L u=>p else(f=p=L(o,this));s L d=>n else(l=n=L(this,o));s void a(Character c)=>t=t+" ".repeat(i-t.size)+c.string;}f=l=c=L(o,o);for(x in process.readLine()else""){switch(x)case('^'){c=c.u;}case('v'){c=c.d;}case('▲'|'k'){c=c.u.u;}case('▼'|'j'){c=c.d.d;}else{}c.a(x);i++;}print(f.t);while(f!=l){f=f.d;print(f.t);}}

または、「読みやすさ」のために改行してください: import ceylon.language{o=null,v=variable,s=shared}s void y(){v L c;v L f;v L l;v Integer i=0;class L(v L?p,v L?n){s v String t="";s L u=>p else(f=p=L(o,this));s L d=>n else(l=n=L(this,o));s void a(Character c)=>t=t+" ".repeat(i-t.size)+c.string;}f=l=c=L(o,o);for(x in process.readLine()else""){switch(x)case('^'){c=c.u;}case('v'){c=c.d;}case('▲'|'k'){c=c.u.u;}case('▼'|'j'){c=c.d.d;}else{}c.a(x);i++;}print(f.t);while(f!=l){f=f.d;print(f.t);}}

これは、▲/▼入力とj / k入力の両方で機能します(これらの1つだけをサポートする必要がある場合、プログラムは8バイト短くなります)。最後の出力行は、開始位置にある場合は空です(つまり、最初の入力がまたはで^、後でその下に戻ることはありませんでした)。指定された文字のいずれでもない入力は、行を切り替えずに、そのまま印刷されます。

v^^vv^^vvv^v^v^^^Hellovvvv^^v^^vv

  ^   ^         ^Hello
 ^ v ^ v       ^      v       ^
v   v   v ^ ^ ^        v   ^ ^ v
         v v v          v ^ v   v
                         v

フォーマット済みバージョン(753バイト)は次のとおりです。

shared void y() {
    variable L c;
    variable L f;
    variable L l;
    variable Integer i = 0;
    class L(variable L? p, variable L? n) {
        shared variable String t = "";
        shared L u => p else (f = p = L(null, this));
        shared L d => n else (l = n = L(this, null));
        shared void a(Character c) => t = t + " ".repeat(i - t.size) + c.string;
    }
    f = l = c = L(null, null);
    for (x in process.readLine() else "") {
        switch (x)
        case ('^') { c = c.u; }
        case ('v') { c = c.d; }
        case ('▲' | 'k') { c = c.u.u; }
        case ('▼' | 'j') { c = c.d.d; }
        else {}
        c.a(x);
        i++;
    }
    print(f.t);
    while (f != l) {
        f = f.d;
        print(f.t);
    }
}

これはほとんど単純な「オブジェクト指向」プログラムです...(ローカル)クラスL(ラインバッファー)は、テキストの行(in内t)と、次の(n)および前の(null可能)ポインターを格納します(p)ライン。(null不可)属性u(上向き)およびd(下向き)は、必要に応じて(自身への逆ポインターで)それらを初期化し、この場合も、最初と最後の行全体を追跡します(fおよびl変数)をます。

a(APPEND)メソッドは、最終的に必要ないくつかのスペースを含めて、この行に文字を追加します。

c現在の行です。入力文字列を解析します(使用readLine現在の行を更新してからappendメソッドを呼び出すswitchステートメントをして入力は1行にする必要があります)。

解析が完了したら、最初から最後まで行を反復処理し、それぞれを印刷します。(これにより、fポインターされます。後で必要になった場合は、このために別の変数を使用する必要がありました。)

いくつかのゴルフのトリックを使用しました:

  • 他の言語ではキーワードとなるものは、実際にはceylon.languageパッケージ内の単なる識別子であり、エイリアスインポートで名前を変更できます。これをアノテーションshared(使用5x)およびvariable(使用6x)、およびオブジェクトに使用しましたnull(4xを使用):

    import ceylon.language{o=null,v=variable,s=shared}
    

    (トリビア:セイロンIDEでのフォーマッタは、それらの間に、いくつかの組み込みの言語の注釈フォーマットvariableshared、宣言上記の別の行に置かれているカスタム注釈とは対照的注釈付きの宣言、同じラインでそれらを置くことによってこれを。ゴルフプログラムのフォーマットされたバージョンが読めなくなるため、このバージョンのエイリアスインポートを元に戻しました。)

    thisvoidcaseelse実際のキーワードであり、このように名前を変更することはできない、とIntegerStringと、Characterそうインポートすることにより得られることは何もない、ただ各いったん表示されます。

  • 元々、別のScreenBufferクラス(ラインバッファーのリンクリスト、現在のインデックスなどを追跡する)もありましたが、そのオブジェクトは1つしかなかったため、最適化されました。

  • そのScreenbufferクラスにはup、およびdownパーサーから呼び出されたメソッドがあります(currentLine = currentLine.upそれぞれ実行されましたcurrentLine = currentLine.down)。パーサーのスイッチでこれを直接行う方が短いことが示されました。また、の代わりにcurrentLine = currentLine.up.up(後になってc = c.u.u)書くこともできましたcurrentLine = currentLine.up;currentLine = currentLine.up

  • もともと、現在のインデックスを引数としてappendメソッドに(そしてループからパーサーにさえ)渡しました。それを含む関数の変数を短くすることです。

  • 当初、私のprintAllメソッドは現在のポインターを使用し、現在の行が空になるまで最初に上に移動し、次に各行の印刷中に下に移動しました。▲と▼を使用して行をジャンプするとこれが壊れたため、代わりにそれらのジャンプした行に明示的に何かを追加する必要がありました。最初/最後の行の追跡が簡単であることがわかりました(ただし、Ceylonにはdo-while-loopがないため、2つのprintステートメントを使用する必要がありました)。

  • もともと私はこのようなものを持っていました:

      String? input = process.readLine();
      if(exists input) {
         for(x in input) {
             ...
         }
      }
    

    process.readLinenull(入力が閉じられているため)読み取ることができる行がない場合に戻り、Ceylonコンパイラーは、アクセスする前にそのことを確認する必要がありますinput。この場合、何もしたくないので、elsenullでない場合は最初の引数を返し、それ以外の場合は2番目の引数を返す演算子を使用して、変数とifステートメントを保存できます。(これにより、テスト用のデフォルト入力をエンコードすることもできます。for (x in process.readLine() else "^^▲^v▼▲^^v") {


0

JavaScript(ES6)、228バイト

E=(r,p=(' '[M='repeat'](Z=r.length)+',')[M](Z*4),i=Z*2,k=0)=>Z>k?E(r,(p.split(',').map((o,q)=>q==i?o.slice(0,k)+r[k]+o.slice(k++):o)).join`,`,i+(H={'^':-1,k:-2,j:2,v:1})[r[k]],k):p.split(',').join`
`.replace(/\s+\n$|^\s+\n/g,'')

さて、ここに、与えられたすべてのテストケースに合格する(かなり長い)再帰的なソリューションがあります。いい挑戦でした。これはkとのj代わりにとを使用します。

テストスニペット

提出自体は処理できるだけですがk,j、次のスニペットはk,jとの両方を処理でき▼,▲ます。

E=(r,p=(' '[M='repeat'](Z=r.length)+',')[M](Z*4),i=Z*2,k=0)=>Z>k?E(r,(p.split(',').map((o,q)=>q==i?o.slice(0,k)+r[k]+o.slice(k++):o)).join`,`,i+(H={'^':-1,k:-2,j:2,v:1})[r[k]],k):p.split(',').join`
`.replace(/\s+\n$|^\s+\n/g,'')
Input: <input type="text" oninput=o.textContent=E(this.value.replace(/▲/g,'k').replace(//g,'j'))></input>
<pre id='o'></pre>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.