这个问题有起有落


33

输入将包含以下字符:

  • ^:上一个
  • v:下去一个
  • k:上两个
  • j:下两个

例如,以下输入:

^^▲^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我的错:/注释正确,我编辑了错误的规则。现在将修复。
2015年

Answers:


9

Pyth,27个字节

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

在线尝试:演示测试套件

我使用kj代替。有很多前导和尾随的空行。您必须进行大量搜索才能找到图像。这是一个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以及/ 语法。

按照良好的不可读传统,以下是按比例字体设置的程序,以消除撇号和双引号之间的区别:

'“”“”“”“”“”“”“”“”“”“”“”“”“”“'”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”'“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“” '“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“ '“”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'“”'“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “'”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'“”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”“'”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”'“”“”“”“”“”“”“”“”“”“” “'”“”“”“”“”“”“”“”“”“”“”“”“”“'”“”“”“”“”“”“”“”“” '“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” '“”'“”'“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“” “”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“'”“”“”

这是一个了不起的挑战。感谢您的发表!

说明

为了了解不可读的功能和不可读的功能,可以想象Brainfuck在两个方向上都有无限长的磁带,但是您可以通过取消引用指针来访问任何一个存储单元,而不必每次移动一个存储单元。尽管必须手动完成其他算术运算(包括模),这在此解决方案中非常方便。

这是带有导演注释的伪代码程序:

// 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++两次,一次用于获取值,一次用于设置值。)

我们只有一个变量可以重用。在我们计算出模数值之后,ch就不再需要了。updn出现相同的次数,所以两者都可以。让我们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]

现在,这在最顶层解释了初始化:它是5,因为它是7(存储块的开始)减去2(在第一个while条件中的强制性增量)。在最后一个循环中,其他两次出现5的情况相同。

需要注意的是,因为0和4中的代码相同的长度,ptrminLine倒过来,可以任意分配。...或者他们可以吗?

倒数第二个while循环中的神秘2怎么样?这不应该是6吗?我们只想减少数据块中的数字,对吗?一旦达到6,我们就位于数据块之外,应该停止!这将是缓冲区溢出错误错误失败安全漏洞!

好吧,想想如果我们不停下来会发生什么。我们递减变量6和4。变量6为mod4。这仅在第一个while循环中使用,在这里不再需要,因此不会造成任何危害。那么变量4呢?您如何看待,变量4应该ptr还是应该minLine?是的,minLine现在也不再使用!因此,变量#4是minLine,我们可以放心地减小它,并且不造成损坏!

更新1!通过实现从2199 Golfed到2145个字节dn可以可以用合并mod5,即使mod5在该值的计算仍然使用dn!现在,新的变量分配为:

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

更新2!通过意识到从2145字节到2134字节,因为mod5现在与处于同一变量dn,并且在while循环中被计数为0,mod5因此不再需要将其显式初始化为0。

更新3!通过实现两件事从2134字节达到2104字节。首先,尽管“负模”的想法是值得的mod5,同样的逻辑并不适用于mod4因为我们从来没有对测试mod4+2等。因此,转变mod4 ? mod4+1 : -3mod4 ? mod4-1 : 3把我们带到了2110个字节。其次,由于mod4始终为0或2,我们可以将其初始化mod4为2而不是0,然后反转两个三元数(mod4 ? 3 : 1而不是mod4 ? 1 : 3)。

更新4!通过意识到计算模数值的while循环始终至少运行一次,可以将其从2104字节扩展到2087字节,在这种情况下,“不可读”使您可以在另一个表达式中重用最后一个语句的值。因此,while --ch: [...]; up = (mod5 ? mod5+1 ? [...]我们现在有了up = ((while --ch: [...]) ? mod5+1 ? [...](在while循环内,我们mod4首先计算,所以这mod5是最后一条语句)。

更新5!通过实现2087到2084个字节,我意识到不必写常数3210(空格和换行符),而是可以将数字10存储在(现在未使用的)变量#2中(我们称之为ten)。而不是ptr3 = 5我们写的ten = (ptr3 = 5) + 5,然后32变成ten+22print 10print ten


真是

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明确允许使用空行,所以我认为没有必要。)
Dennis 2015年

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。可能有一个较短的改装链

当当前高度等于行号(可以为负)时,我们将当前字符附加到该行上,否则添加一个空格。然后,我们打印该行。实际上,以当前行号开始的高度并减去高度变化,并在值达到时附加字符会变短0

行号包含一个足够大的范围,以至于其中有两个上下两个的序列。实际上,有很多多余的东西。如果我们在输入长度上有一个上限,则写起来会短一些,比如说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

这是一个开始。在jk使其在颈部疼痛,因为我无法找到一个方法来从数学映射j^vk[-2 -1 1 2]与MATLAB无法识别的Unicode(显然上下都在MATLAB,去图一个26价值!),有映射浪费了大量字节。

通过从@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])工作吗?它可以在八度使用。或者,即使b=[-2 -1 1 2](a-94==[12 13 0 24])您想再剃掉一个字节!
wchargin

@WChargin在MATLAB中不起作用。不幸的是,==停靠点的行为可以正常工作,而且在MATLAB中,您也不能在a ()之后加上a []
汤姆·卡彭特

嗯...您可以将语言更改为八度!:)(八度音也有+=,稍等)
wchargin

@WChargin那是作弊= P,但是我同意,Octave有很多Matlab没有的快捷方式。
瑕疵

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个字节

这个可以正确计算输出范围,因此不会产生多余的空格。这是我的十六进制解决方案

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艺术挑战。它基于二维输出“画布”和“蜡笔”(在此画布上移动的光标)的基础构建。发送到输出的所有内容都会在蜡笔位置和蜡笔面向的方向上绘制在画布上。默认情况下,蜡笔指向东(向右)。

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]^>}

使用kj代替

一些注意事项:

  • Escape sequences that move the cursor such as \e[B are not allowed. You must produce the output using spaces and newlines.我确实遵守这条规则!pb使用“画笔”的概念来输出字符。画笔在“画布”周围移动,并可以在其下方立即打印一个字符。但是,实际的实现使用空格和换行符来打印字符。
  • 即使我认为铅会很有趣,直到我看到裁决后,我才不会为挑战而烦恼You are allowed trailing spaces and/or empty lines。这有两个原因:
    • 不能有尾随空格。它总是产生矩形输出,必要时用空格填充。
    • 这个程序产生很多空行。它不知道开始制作时输出的高度,因此对于长度为输入的输入,n它始于Y=3n+1-1之所以这样,是因为它3n从下降Y=-1,并且从Y=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输入(如果我们仅支持其中之一,则程序将短8个字节)。当起始位置在其上时,最后一个输出行为空(即,第一个输入为or ^,以后我们再也不会低于该行)。不是指定字符之一的输入将按原样打印,而无需切换行:

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(行缓冲)存储文本(在的线t),以及(可为空)指针到下一个(n)和以前的(p)线。(不可为空)属性u(用于up)和d(用于down)在需要时对其进行初始化(使用指向自身的反向指针),在这种情况下,还应跟踪总体的第一行和最后一行(在fl变量中)。

所述a(附加)方法附加一个字符到该行,包括最终必要一些空间。

c是当前行。我们readLine使用switch语句解析输入字符串(因为输入应在一行上),该语句会更新当前行,然后调用append方法。

解析完成后,我们从头到尾遍历所有行,并打印每行。(这会破坏f指针,如果以后需要的话,我们应该为此使用一个单独的变量。)

一些打高尔夫球的技巧:

  • 用其他语言将某些内容ceylon.language用作关键字的内容实际上只是包中的标识符,并且可以使用别名导入重命名-我们将其用于注释shared(使用5倍)和variable(使用6倍)以及对象null(使用4倍):

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

    (琐事:Ceylon IDE中的Formatter在它们之间variableshared通过放置,方法是将它们放置在与注释声明相同的行中,这与自定义注释形成对比,而自定义注释则放置在声明上方的单独一行中。使高尔夫程序的格式化版本不可读,因此我将别名导入更改为该版本。)

    thisvoidcaseelse是实际的关键字,不能重命名这种方式,并IntegerStringCharacter出现只有一次每个,所以没有什么可通过进口获得。

  • 最初,我还有一个单独的ScreenBuffer类(用于跟踪行缓冲区的链接列表,当前索引等),但是由于只有一个对象,因此对其进行了优化。

  • 该Screenbuffer类也具有updown方法,它们是从解析器中调用的(currentLine = currentLine.up分别是currentLine = currentLine.down)。结果表明,直接在解析器的开关中执行此操作的时间较短。它还允许编写currentLine = currentLine.up.up(后来成为c = c.u.u)而不是currentLine = currentLine.up;currentLine = currentLine.up

  • 最初,我们确实将当前索引作为参数传递给append方法(甚至从循环传递给解析器)–在包含函数中将其作为变量要短一些。

  • 最初,我的printAll方法使用当前指针,并先将其向上移动直到当前行为空,然后在打印每一行时将其向下移动。当使用▲和▼跳过行时,此操作中断了,因此我们不得不在跳过的行中显式附加内容。事实证明,跟踪第一行/最后一行比较容易(尽管这使得必须使用两个打印语句,因为在锡兰中没有do-while循环)。

  • 本来我有这样的事情:

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

    process.readLine返回null如果没有行可读取(因为输入已关闭),而锡兰编译器需要我checkfor,在我的访问input。因为在这种情况下我什么都不做,所以我可以等效地使用else运算符,如果运算符不为null,则返回其第一个参数,否则返回其第二个参数,保存变量和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,'')

好吧,这是一个(相当长的)递归解决方案,可以通过给定的所有测试用例。这是一个很好的挑战。这种用途kj到位的

测试片段

尽管提交本身只能处理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>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.