Câu hỏi này có những thăng trầm của nó


33

Đầu vào sẽ bao gồm các ký tự sau:

  • ^: Đi lên một
  • v: Đi xuống một
  • hoặc k: Đi lên hai
  • hoặc j: Đi xuống hai

Ví dụ: đầu vào sau:

^^▲^v▼▲^^v

sẽ tạo ra đầu ra sau:

        ^
   ^   ^ v
  ▲ v ▲

 ^   ▼
^

Trình tự thoát di chuyển con trỏ như \e[Bkhông được phép. Bạn phải tạo đầu ra bằng cách sử dụng khoảng trắng và dòng mới.

Dưới đây là một vài trường hợp thử nghiệm.

▲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
Được dấu không gian cho phép? Dòng trống?
xnor

2
Còn những ngôn ngữ không hỗ trợ Unicode thì sao? Nhân vật thay thế có thể được sử dụng?
Doorknob

1
@xnor Bạn được phép theo dấu dấu cách và / hoặc dòng trống.
absinthe

2
@Doorknob Tôi sẽ cho phép jđi xuống hai lần và cũng ksẽ tăng gấp đôi.
absinthe

1
@xnor Cái xấu của tôi: / Nhận xét là đúng và tôi đã chỉnh sửa các quy tắc sai. Sẽ sửa ngay.
absinthe

Câu trả lời:


9

Bình thường, 27 byte

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

Dùng thử trực tuyến: Trình diễn hoặc Test Suite

Tôi sử dụng kjthay vì . Có rất nhiều dòng trống hàng đầu và dấu. Bạn phải tìm kiếm khá nhiều để tìm thấy hình ảnh. Đây là phiên bản 34 byte , loại bỏ tất cả các dòng trống hàng đầu và dấu.

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

Dùng thử trực tuyến: Trình diễn hoặc Test Suite

Giải trình:

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

Không thể đọc được , 2199 2145 2134 2104 2087 2084 byte

Hỗ trợ cả k/ jcũng như / cú pháp.

Theo truyền thống tốt không thể đọc được, đây là chương trình được định dạng theo phông chữ tỷ lệ, để làm xáo trộn sự khác biệt giữa dấu nháy đơn và dấu ngoặc kép:

"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" """" "" "" "" "" ""

Đây là một thử thách đáng kinh ngạc. Cảm ơn đã đăng bài viết!

Giải trình

Để cảm nhận những gì Unreadable có thể và không thể làm, hãy tưởng tượng Brainfuck với một cuộn băng vô hạn theo cả hai hướng, nhưng thay vì một con trỏ bộ nhớ di chuyển một ô tại một thời điểm, bạn có thể truy cập bất kỳ ô nhớ nào bằng cách hủy bỏ một con trỏ. Điều này khá hữu ích trong giải pháp này, mặc dù các phép toán số học khác - bao gồm cả modulo - phải được thực hiện bằng tay.

Đây là chương trình dưới dạng mã giả với lời bình luận của đạo diễn:

// 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

Quá nhiều cho logic chương trình. Bây giờ chúng tôi cần dịch cái này sang Unreadable và sử dụng một vài thủ thuật chơi golf thú vị hơn.

Các biến luôn được quy định số lượng trong Không thể đọc được (ví dụ: a = 1trở thành một cái gì đó giống như *(1) = 1). Một số chữ số dài hơn những chữ khác; ngắn nhất là 1, theo sau là 2, v.v. Để chỉ ra số âm dài hơn bao nhiêu, đây là các số từ -1 đến 7:

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

Rõ ràng, chúng tôi muốn phân bổ biến số 1 cho biến xảy ra thường xuyên nhất trong mã. Trong vòng lặp while đầu tiên, điều này chắc chắn mod5, xuất hiện 10 lần. Nhưng chúng ta không cần mod5nữa sau vòng lặp while đầu tiên, vì vậy chúng ta có thể phân bổ lại cùng một vị trí bộ nhớ cho các biến khác mà chúng ta sử dụng sau này. Đây là ptr2ptr3. Bây giờ biến được tham chiếu tổng cộng 21 lần. (Nếu bạn đang cố gắng tự đếm số lần xuất hiện, hãy nhớ đếm thứ gì đó như a++hai lần, một lần để nhận giá trị và một lần để đặt giá trị đó.)

Chỉ có một biến khác mà chúng ta có thể sử dụng lại; sau khi chúng tôi tính toán các giá trị modulo, chkhông còn cần thiết nữa. updnđưa ra cùng một số lần, vì vậy hoặc là tốt. Hãy hợp nhất chvới up.

Điều này để lại tổng cộng 8 biến số duy nhất. Chúng ta có thể phân bổ các biến từ 0 đến 7 và sau đó bắt đầu khối bộ nhớ (chứa các ký tự và số dòng) ở 8. Nhưng! Vì 7 có cùng độ dài mã với −1, chúng tôi cũng có thể sử dụng các biến −1 đến 6 và bắt đầu khối bộ nhớ ở mức 7. Bằng cách này, mọi tham chiếu đến vị trí bắt đầu của khối bộ nhớ đều ngắn hơn một chút trong mã! Điều này để lại cho chúng tôi các bài tập sau:

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

Bây giờ điều này giải thích việc khởi tạo ở trên cùng: đó là 5 vì nó là 7 (bắt đầu của khối bộ nhớ) trừ 2 (mức tăng bắt buộc trong điều kiện đầu tiên). Điều tương tự cũng xảy ra với hai lần xuất hiện khác của 5 trong vòng lặp cuối cùng.

Lưu ý rằng, vì 0 và 4 có cùng độ dài mã ptrminLinecó thể được phân bổ theo cách khác. ... Hay họ có thể?

Điều gì về 2 bí ẩn trong vòng lặp thứ hai cuối cùng? Đây không phải là số 6 sao? Chúng tôi chỉ muốn giảm số trong khối dữ liệu, phải không? Khi chúng tôi đạt đến 6, chúng tôi ở ngoài khối dữ liệu và chúng tôi nên dừng lại! Nó sẽ là một lỗi tràn bộ đệm lỗi lỗi bảo mật lỗi!

Chà, nghĩ về những gì sẽ xảy ra nếu chúng ta không dừng lại. Chúng tôi giảm các biến 6 và 4. Biến 6 là mod4. Điều đó chỉ được sử dụng trong vòng lặp while đầu tiên và không còn cần thiết ở đây nữa, vì vậy không có hại gì. Còn biến 4 thì sao? Bạn nghĩ gì, biến 4 nên ptrhay nên là minLine? Điều đó đúng, minLinecũng không còn được sử dụng tại thời điểm này! Do đó, biến số 4 là minLinevà chúng ta có thể giảm nó một cách an toàn và không gây sát thương!

CẬP NHẬT 1! Được đánh gôn từ 2199 đến 2145 byte bằng cách nhận ra rằng cũngdn có thể được hợp nhất với , mặc dù vẫn được sử dụng trong tính toán giá trị cho ! Việc gán biến mới hiện là:mod5mod5dn

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

CẬP NHẬT 2! Đã đánh gôn từ 2145 đến 2134 byte bằng cách nhận ra rằng, vì mod5bây giờ có cùng biến với dn, được tính thành 0 trong một vòng lặp while, mod5không còn cần phải được khởi tạo rõ ràng thành 0.

CẬP NHẬT 3! Chơi gôn từ 2134 đến 2104 byte bằng cách nhận ra hai điều. Đầu tiên, mặc dù ý tưởng modulo phủ định của YouTube là đáng giá mod5, nhưng lý do tương tự không áp dụng mod4vì chúng tôi không bao giờ kiểm tra, mod4+2v.v. Do đó, việc thay đổi mod4 ? mod4+1 : -3sẽ mod4 ? mod4-1 : 3đưa chúng tôi đến 2110 byte. Thứ hai, vì mod4luôn là 0 hoặc 2, chúng ta có thể khởi tạo mod4thành 2 thay vì 0 và đảo ngược hai ternary ( mod4 ? 3 : 1thay vì mod4 ? 1 : 3).

CẬP NHẬT 4! Được đánh dấu từ 2104 đến 2087 byte bằng cách nhận ra rằng vòng lặp while tính toán các giá trị modulo luôn chạy ít nhất một lần và trong trường hợp đó, Unreadable cho phép bạn sử dụng lại giá trị của câu lệnh cuối cùng trong một biểu thức khác. Do đó, thay vì while --ch: [...]; up = (mod5 ? mod5+1 ? [...]bây giờ chúng ta có up = ((while --ch: [...]) ? mod5+1 ? [...](và bên trong vòng lặp while đó, chúng ta tính toán mod4trước, vì vậy đó mod5là câu lệnh cuối cùng).

CẬP NHẬT 5! Được đánh gôn từ 2087 đến 2084 byte bằng cách nhận ra rằng thay vì viết ra các hằng số 3210(dấu cách và dòng mới), tôi có thể lưu trữ số 10 trong biến số 2 (hiện chưa được sử dụng) (hãy gọi nó ten). Thay vì ptr3 = 5chúng ta viết ten = (ptr3 = 5) + 5, sau đó 32trở thành ten+22print 10trở thành print ten.


Đây là ... khủng khiếp ... +1
kirbyfan64sos

6

CJam, 37 byte

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

Điều này in các dòng trống trước và sau đầu ra mong muốn, đã được OP cho phép .

Hãy thử trực tuyến trong trình thông dịch CJam .

Làm thế nào nó hoạt động

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.

Tôi nghĩ sẽ chỉ công bằng khi tuyên bố một cách rõ ràng rằng giải pháp của bạn tạo ra số lượng lớn các dòng mới trước và sau đầu ra mong muốn ...
Timwi

Thêm. (Tôi không nghĩ rằng điều đó là cần thiết vì OP rõ ràng cho phép các dòng trống.)
Dennis

3

Con trăn 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

In từng dòng.

Vòng lặp thông qua các ký tự trong đầu vào và theo dõi chiều cao hiện tại. Chiều cao được cập nhật bởi một trong những +2, +1, -1, -2tính toán của 'kv_^j'.find(c)-2. Có lẽ có một chuỗi mod ngắn hơn

Khi chiều cao hiện tại bằng với số dòng (có thể âm), chúng ta sẽ thêm ký tự hiện tại vào dòng và nối thêm một khoảng trắng. Sau đó, chúng tôi in dòng. Trên thực tế, nó ngắn hơn để bắt đầu chiều cao ở số dòng hiện tại và trừ đi thay đổi chiều cao, nối thêm ký tự khi giá trị chạm 0.

Các số dòng bao gồm một phạm vi đủ lớn để một chuỗi tăng hoặc giảm hai sẽ ở trong phạm vi đó. Trên thực tế, có một lượng dư thừa tốt. Nếu chúng ta có một giới hạn trên về độ dài đầu vào, nó sẽ ngắn hơn để viết j=999.

Đáng ngạc nhiên, i and' 'or clà ngắn hơn bình thường [' ',c][i==0]. Lưu ý rằng icó thể là tiêu cực, mà cắt bỏ một số thủ thuật thông thường.


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

Đó là một sự khởi đầu. Các jklàm cho nó một cơn đau ở cổ như tôi không thể tìm thấy một cách để toán học bản đồ từ j^vkđến [-2 -1 1 2]và với MATLAB không công nhận Unicode (rõ ràng cả lên xuống có giá trị 26 trong MATLAB. Go con số!), Có rất nhiều byte bị lãng phí khi thực hiện ánh xạ.

Bằng cách lấy cảm hứng từ giải pháp @xnors, mã có thể giảm 14 ký tự khác bằng cách ánh xạ ký tự điều khiển bên trong vòng lặp for.

Ngoài ra còn có nhiều byte bị lãng phí khi cố gắng tính toán nếu chuỗi đầu vào gửi lại mẫu bên dưới chỉ mục mà nó bắt đầu (có thể nếu có giới hạn về độ dài chuỗi tôi có thể đơn giản hóa bit đó).

Và ở dạng dễ đọc của nó:

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

Sẽ b=[-2 -1 1 2](a==[106 107 94 118])làm việc? Nó hoạt động trong Octave. Hoặc thậm chí b=[-2 -1 1 2](a-94==[12 13 0 24])nếu bạn muốn cạo thêm một byte!
wchargein

@WChargin không hoạt động trong MATLAB. Thật không may, hành vi của các ==điểm dừng hoạt động và cả trong MATLAB bạn không thể đặt ()sau [].
Tom Carpenter

Hmm, bạn có thể thay đổi ngôn ngữ thành Octave! :) (Octave cũng có +=, fwiw.)
wchargein

@WChargin Đó là gian lận = P Nhưng tôi đồng ý, Octave có rất nhiều phím tắt mà Matlab không có.
flawr

2

JavaScript (ES6), 140

Kiểm tra chạy đoạn mã dưới đây trong trình duyệt tuân thủ EcmaScript 6 (đã thử nghiệm trên 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 byte

Điều này tính toán chính xác các giới hạn đầu ra để không có khoảng trắng thừa được tạo ra. Đây là giải pháp của tôi trong hex

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

Một lời giải thích nhỏ là theo thứ tự. Trên ngăn xếp, chúng ta có đầu vào của người dùng dưới dạng một mảng mã ascii. Chương trình bắt đầu bằng một chuỗi ký tự vì 05. Ở đây chúng tôi đi.

  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 byte

Tôi cũng có một giải pháp 24 byte không cần nhiều tính toán kích thước đầu ra và kết thúc với khoảng trắng thừa. Tôi thích cái có khoảng trắng được giữ ở mức tối thiểu.

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

Crayon , 13 byte (không cạnh tranh)

O"^ vj"\CynIq

Hãy thử trực tuyến! Sử dụng các mũi tên thực sự tại sao không.

Không cạnh tranh vì Crayon mới hơn thử thách này.

Làm thế nào nó hoạt động

Crayon là một ngôn ngữ dựa trên ngăn xếp được thiết kế để trở thành kẻ giết người tại các thử thách nghệ thuật ASCII. Nó được xây dựng trên cơ sở của "canvas" đầu ra 2 chiều và "bút chì", một con trỏ di chuyển xung quanh khung vẽ này. Bất cứ điều gì được gửi đến đầu ra đều được vẽ trên khung vẽ ở vị trí của bút màu, và theo hướng bút chì đang đối mặt. Theo mặc định, bút chì chỉ hướng Đông (bên phải).

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 byte

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

Sử dụng kjthay vì .

Một vài lưu ý:

  • Escape sequences that move the cursor such as \e[B are not allowed. You must produce the output using spaces and newlines.Tôi làm theo quy tắc này! pb sử dụng khái niệm "cọ" để xuất ký tự. Bàn chải di chuyển xung quanh "khung vẽ" và có thể in một ký tự ngay bên dưới nó. Tuy nhiên, việc thực hiện thực tế in nhân vật bằng cách sử dụng khoảng trắng và dòng mới.
  • Tôi sẽ không bận tâm với thử thách này mặc dù tôi nghĩ nó sẽ vui với pb cho đến khi tôi thấy phán quyết đó You are allowed trailing spaces and/or empty lines. Điều này là vì một vài lý do:
    • pb không thể có dấu cách. Nó luôn tạo ra đầu ra hình chữ nhật, đệm với khoảng trắng nếu cần thiết.
    • Chương trình này tạo ra rất nhiều dòng trống. Nó không biết đầu ra sẽ cao bao nhiêu khi nó bắt đầu tạo ra nó, vì vậy đối với đầu vào có độ dài nthì nó bắt đầu từ Y=3n+1. Các -1là bởi vì nó sẽ xuống 3ntừ Y=-1, và bắt đầu từ Y=2n-1thất bại cho một đầu vào của tất cả k.

Bạn có thể xem chương trình này hoạt động trên YouTube!Phiên bản này được sửa đổi một chút ở chỗ nó chỉ đi xuống n-1. Nó hoạt động cho đầu vào này, nhưng sẽ thất bại cho những người khác. Nó, tuy nhiên, chụp đẹp hơn rất nhiều.

Với nhận xét:

^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

Ceylon, 447 byte

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);}}

Hoặc với ngắt dòng cho "khả năng đọc": 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);}}

Điều này hoạt động với cả đầu vào / ▼ và j / k (Nếu chúng tôi chỉ hỗ trợ một trong số chúng, chương trình sẽ ngắn hơn 8 byte). Dòng đầu ra cuối cùng trống khi vị trí bắt đầu nằm trên nó (tức là đầu vào đầu tiên là một hoặc ^chúng tôi không bao giờ có được dưới đó một lần nữa sau đó). Đầu vào không phải là một trong các ký tự được chỉ định sẽ được in đơn giản, mà không cần chuyển dòng:

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

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

Đây là một phiên bản được định dạng (753 byte):

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);
    }
}

Đây là một chương trình "hướng đối tượng" gần như thẳng về phía trước ... lớp (cục bộ) L(bộ đệm dòng) lưu trữ một dòng văn bản (trong t), cũng như các con trỏ (nullable) cho các con trỏ tiếp theo ( n) và trước ( p) hàng. Các thuộc tính (không phải nullable) u(để tăng) và d(cho xuống) khởi tạo các thuộc tính nếu cần (với một con trỏ ngược lại chính nó) và trong trường hợp này cũng theo dõi tổng thể dòng đầu tiên và cuối cùng (trongfl biến và biến).

Các a (chắp thêm) nối thêm một ký tự vào dòng này, bao gồm một số khoảng trắng cuối cùng là cần thiết.

clà dòng hiện tại. Chúng tôi phân tích chuỗi đầu vào (sử dụngreadLine làm đầu vào phải nằm trên một dòng) bằng cách sử dụng câu lệnh chuyển đổi cập nhật dòng hiện tại và sau đó gọi phương thức chắp thêm.

Sau khi phân tích xong, chúng tôi lặp lại các dòng từ đầu đến cuối, in từng dòng. (Điều này sẽ phá hủy fcon trỏ, nếu cần sau đó, chúng ta nên sử dụng một biến riêng cho việc này.)

Một số thủ thuật được sử dụng để chơi golf:

  • Một số nội dung trong các ngôn ngữ khác sẽ là từ khóa thực sự chỉ là định danh trong ceylon.languagegói và có thể được đổi tên bằng nhập khẩu bí danh - chúng tôi đã sử dụng từ này cho các chú thích shared(được sử dụng 5 ×) và variable(được sử dụng 6 ×), cũng như cho đối tượng null(được sử dụng 4 ×):

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

    (Thông tin bên lề: Trình định dạng trong IDE Ceylon định dạng một số chú thích ngôn ngữ tích hợp, giữa chúng variableshared , bằng cách đặt chúng trong cùng một dòng như tuyên bố chú thích, trái ngược với chú thích tùy chỉnh, được đặt trên một dòng riêng trên tờ khai này. làm cho phiên bản được định dạng của chương trình chơi gôn không thể đọc được, do đó tôi đã thay đổi nhập khẩu bí danh cho phiên bản này.)

    this, void, case, elseLà các từ khóa thực tế và không thể đổi tên theo cách này, và Integer, StringCharacterxuất hiện chỉ một lần mỗi, vì vậy không có gì để đạt được bằng cách nhập là.

  • Ban đầu tôi cũng có một lớp ScreenBuffer riêng (theo dõi danh sách các bộ đệm dòng được liên kết, chỉ mục hiện tại, v.v.), nhưng vì chỉ có một đối tượng của nó, nên nó được tối ưu hóa.

  • Lớp Screenbuffer đó cũng có updowncác phương thức, được gọi từ trình phân tích cú pháp (và chỉ thực hiện currentLine = currentLine.uptương ứng currentLine = currentLine.down). Nó cho thấy rằng trực tiếp làm điều này trong chuyển đổi trình phân tích cú pháp ngắn hơn. Nó cũng được phép viết currentLine = currentLine.up.up(mà sau này trở thành c = c.u.u) thay vì currentLine = currentLine.up;currentLine = currentLine.up.

  • Ban đầu chúng tôi đã chuyển chỉ mục hiện tại làm đối số vào phương thức chắp thêm (và thậm chí cho trình phân tích cú pháp từ vòng lặp) - có một biến trong hàm chứa là ngắn hơn.

  • Ban đầu phương thức printAll của tôi đã sử dụng con trỏ hiện tại và di chuyển nó trước tiên cho đến khi dòng hiện tại trống, sau đó xuống trong khi in từng dòng. Điều này đã bị phá vỡ khi sử dụng ▲ và để nhảy qua các dòng, vì vậy chúng tôi phải nối thêm một cách rõ ràng vào những dòng nhảy đó. Theo dõi dòng đầu tiên / cuối cùng đã được chứng minh dễ dàng hơn (mặc dù điều đó khiến nó cần thiết phải sử dụng hai câu lệnh in, vì không có vòng lặp do-while-loop trong Ceylon).

  • Ban đầu tôi có một cái gì đó như thế này:

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

    process.readLinetrả về nullnếu không có dòng nào có thể đọc được (vì đầu vào đã bị đóng) và trình biên dịch Ceylon yêu cầu tôi kiểm tra xem trước khi tôi truy cập input. Như trong trường hợp này tôi không muốn làm gì, tôi có thể sử dụng elsetoán tử một cách tương đương trả về đối số đầu tiên của nó nếu không phải là null và nếu không thì đối số thứ hai của nó, lưu biến và câu lệnh if. (Điều này cũng sẽ cho phép chúng tôi mã hóa đầu vào mặc định để kiểm tra for (x in process.readLine() else "^^▲^v▼▲^^v") {:)


0

JavaScript (ES6), 228 byte

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,'')

Vâng, đây là một giải pháp đệ quy (khá dài) vượt qua tất cả các trường hợp thử nghiệm được đưa ra. Đó là một thử thách tốt đẹp. Điều này sử dụng kjthay thế .

Kiểm tra đoạn trích

Mặc dù bản đệ trình chỉ có thể xử lý k,j, đoạn mã sau có thể xử lý cả 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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.