คำถามนี้มีทั้งอัพและดาวน์


33

ข้อมูลที่ป้อนจะประกอบด้วยอักขระต่อไปนี้:

  • ^: ขึ้นไปหนึ่ง
  • v: ลงไปหนึ่งอัน
  • หรือk: ขึ้นสอง
  • หรือj: ลงไปสองอัน

ตัวอย่างเช่นอินพุตต่อไปนี้:

^^▲^v▼▲^^v

จะผลิตผลลัพธ์ต่อไปนี้:

        ^
   ^   ^ v
  ▲ v ▲

 ^   ▼
^

\e[Bไม่อนุญาตให้ใช้Escape sequences ที่เลื่อนเคอร์เซอร์เช่น คุณต้องสร้างเอาต์พุตโดยใช้ช่องว่างและบรรทัดใหม่

ต่อไปนี้เป็นกรณีทดสอบเพิ่มเติมอีกสองสามข้อ

▲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 ล่ะ? สามารถใช้อักขระทางเลือกได้หรือไม่
Doorknob

1
@xnor คุณได้รับอนุญาตให้เว้นวรรคและ / หรือบรรทัดว่าง
absinthe

2
@ Doorknob ฉันจะอนุญาตให้jลงไปสองครั้งและkสำหรับการขึ้นสองครั้งเช่นกัน
absinthe

1
@xnor ไม่ดีของฉัน: / ความคิดเห็นถูกต้องและฉันแก้ไขกฎผิด จะแก้ไขทันที
absinthe

คำตอบ:


9

Pyth, 27 ไบต์

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

ลองใช้ออนไลน์: การสาธิตหรือชุดทดสอบ

ผมใช้kและjแทนและ มีจำนวนบรรทัดว่างและนำหน้าจำนวนมาก คุณต้องค้นหาค่อนข้างน้อยเพื่อค้นหาภาพ นี่คือ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 ด้วยเทปที่ไม่มีที่สิ้นสุดในทั้งสองทิศทาง แต่แทนที่จะใช้ตัวชี้หน่วยความจำเคลื่อนที่หนึ่งเซลล์ในแต่ละครั้งคุณสามารถเข้าถึงเซลล์หน่วยความจำใดก็ได้โดยการยกเลิกการชี้ สิ่งนี้มีประโยชน์มากในการแก้ปัญหานี้แม้ว่าการคำนวณทางคณิตศาสตร์อื่น ๆ รวมถึงโมดูโลจะต้องทำด้วยมือ

นี่คือโปรแกรมเป็น pseudocode พร้อมคำอธิบายของผู้อำนวยการ:

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

มากสำหรับตรรกะของโปรแกรม ตอนนี้เราต้องแปลสิ่งนี้เป็น Unreadableและใช้เทคนิคการตีกอล์ฟที่น่าสนใจ

ตัวแปรจะถูกอ้างอิงเป็นตัวเลขใน Unreadable เสมอ (เช่น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 ให้กับตัวแปรที่เกิดขึ้นบ่อยที่สุดในรหัส ในขณะแรกที่วนซ้ำนี่จะเป็นmod510 เท่า แต่เราไม่ต้องการmod5อีกต่อไปหลังจากครั้งแรกในขณะที่วนรอบดังนั้นเราสามารถจัดสรรตำแหน่งหน่วยความจำเดียวกันให้กับตัวแปรอื่น ๆ ที่เราใช้ในภายหลัง เหล่านี้เป็นและptr2 ptr3ตอนนี้ตัวแปรอ้างอิงไปแล้ว 21 ครั้ง (หากคุณกำลังพยายามนับจำนวนครั้งที่เกิดขึ้นด้วยตัวเองอย่าลืมนับบางสิ่งเช่นa++สองครั้งหนึ่งครั้งเพื่อรับค่าและอีกครั้งสำหรับการตั้งค่า)

มีอีกหนึ่งตัวแปรที่เราสามารถใช้ซ้ำได้ หลังจากที่เราคำนวณค่าโมดูโลแล้วchไม่จำเป็นอีกต่อไป upและdnมีจำนวนเท่ากันดังนั้นก็ดี ผสาน Let 's ด้วยchup

ทำให้มีตัวแปรเฉพาะทั้งหมด 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 (การเพิ่มภาระผูกพันในขณะที่เงื่อนไขแรก) สิ่งเดียวกันจะเกิดขึ้นอีกสองเหตุการณ์ที่เกิดขึ้น 5 ครั้งในลูปสุดท้าย

โปรดทราบว่าตั้งแต่ 0 และ 4 มีความยาวเท่ากันในรหัสptrและminLineสามารถจัดสรรได้ทั้งสองทาง ... หรือพวกเขาจะ?

สิ่งที่เกี่ยวกับ 2 ลึกลับในวินาทีสุดท้ายขณะที่วนรอบ? นี่ไม่ควรเป็น 6 หรือ เราต้องการลดจำนวนลงในบล็อคข้อมูลใช่ไหม เมื่อเราไปถึง 6 เราจะอยู่นอกบล็อคข้อมูลและเราควรหยุด! มันจะเป็นข้อผิดพลาดบัฟเฟอร์ล้นข้อผิดพลาดความปลอดภัยช่องโหว่!

ลองคิดดูว่าจะเกิดอะไรขึ้นถ้าเราไม่หยุด เราพร่องตัวแปร 6 และ 4 ตัวแปร mod46 ใช้เฉพาะในครั้งแรกขณะที่วนซ้ำและไม่ต้องการที่นี่อีกต่อไปจึงไม่เกิดอันตรายใด ๆ แล้วตัวแปร 4 ล่ะ? คุณคิดว่าตัวแปร 4 ptrควรเป็นหรือควรเป็นminLineอย่างไร ใช่แล้วminLineไม่ใช้ตอนนี้อีก! ดังนั้นตัวแปร # 4 คือminLineและเราสามารถลดมันได้อย่างปลอดภัยและไม่เกิดความเสียหาย!

อัปเดต 1! แข็งแรงเล่นกอล์ฟ 2199-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ซึ่งนับเป็น 0 ในขณะที่ลูปmod5ไม่จำเป็นต้องเริ่มต้นเป็น 0 อย่างชัดเจนอีกต่อไป

อัปเดต 3! เล่นกอล์ฟตั้งแต่ 2134 ถึง 2104 ไบต์โดยตระหนักถึงสองสิ่ง ครั้งแรกแม้ว่าแนวคิด "เชิงลบแบบโมดูโล" นั้นมีค่าสำหรับมันmod5แต่การใช้เหตุผลแบบเดียวกันไม่สามารถทำได้mod4เพราะเราไม่เคยทดสอบกับmod4+2อื่น ๆ ดังนั้นการเปลี่ยนmod4 ? mod4+1 : -3เป็นmod4 ? mod4-1 : 3พาเราไปที่ 2110 ไบต์ ที่สองเนื่องจากmod4เป็น 0 หรือ 2 เสมอเราสามารถกำหนดค่าเริ่มต้นmod4เป็น 2 แทน 0 และย้อนกลับทั้งสามส่วน ( mod4 ? 3 : 1แทนmod4 ? 1 : 3)

อัพเดท 4! มีขนาดตั้งแต่ 2104 ถึง 2087 ไบต์โดยตระหนักว่าขณะที่ลูปที่คำนวณค่าโมดูโล่ทำงานอย่างน้อยหนึ่งครั้งและในกรณีเช่นนี้ Unreadable ช่วยให้คุณสามารถใช้ค่าของข้อความสั่งสุดท้ายในนิพจน์อื่นได้อีกครั้ง ดังนั้นแทนที่จะเป็นwhile --ch: [...]; up = (mod5 ? mod5+1 ? [...]ตอนนี้เรามีup = ((while --ch: [...]) ? mod5+1 ? [...](และภายในขณะที่วนซ้ำเราจะคำนวณmod4ก่อนเพื่อให้mod5เป็นคำสั่งสุดท้าย)

อัพเดท 5! เล่นกอล์ฟตั้งแต่ 2087 ถึง 2084 ไบต์โดยตระหนักว่าแทนที่จะเขียนค่าคงที่32และ10(เว้นวรรคและขึ้นบรรทัดใหม่) ฉันสามารถเก็บหมายเลข 10 ในตัวแปร (ตอนนี้ไม่ได้ใช้) # 2 (ลองเรียกมันว่าten) แทนการptr3 = 5ที่เราเขียนten = (ptr3 = 5) + 5แล้ว32จะกลายเป็นten+22และจะกลายเป็นprint 10print 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 อนุญาตบรรทัดว่างไว้อย่างชัดเจน)
Dennis

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 chain ที่สั้นกว่า

เมื่อความสูงปัจจุบันเท่ากับจำนวนบรรทัด (ซึ่งอาจเป็นลบได้) เราจะเพิ่มอักขระปัจจุบันต่อท้ายบรรทัดและเพิ่มช่องว่าง จากนั้นเราพิมพ์บรรทัด 0ที่จริงมันสั้นกว่าที่จะเริ่มต้นความสูงที่หมายเลขบรรทัดปัจจุบันและลบการเปลี่ยนแปลงความสูงผนวกตัวอักษรเมื่อฮิตคุ้มค่า

หมายเลขบรรทัดรวมช่วงที่มีขนาดใหญ่พอที่ลำดับของการ up-two หรือ down-two จะยังคงอยู่ภายใน อันที่จริงมีจำนวนเกินที่ดี 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

มันเป็นการเริ่มต้น jและkทำให้มันเป็นอาการปวดคอที่ผมไม่สามารถหาวิธีการทางคณิตศาสตร์ map จากj^vkไป[-2 -1 1 2]และกับ MATLAB ไม่ได้ตระหนักถึง Unicode (เห็นได้ชัดทั้งขึ้นและลงมีค่าเป็น 26 ในรูป MATLAB. Go!) มี ไบต์จำนวนมากทำให้การทำแผนที่เสียไป

โดยการวาดแรงบันดาลใจจากวิธีการแก้ปัญหา @ xnors รหัสสามารถลดลงอีก 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 คุณไม่สามารถใส่หลังจากที่() []
Tom Carpenter

อืม…คุณสามารถเปลี่ยนภาษาเป็นอ็อกเทฟ! :) (อ็อกเทฟมี+=, fwiw.)
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 ไบต์

อันนี้คำนวณขอบเขตเอาท์พุทได้อย่างถูกต้องดังนั้นจึงไม่มีการสร้างช่องว่างส่วนเกิน นี่คือทางออกของฉันใน 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

คำอธิบายเล็กน้อยอยู่ในการสั่งซื้อ ในสแต็คเรามีการป้อนข้อมูลของผู้ใช้เป็นอาร์เรย์ของรหัส 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

Crayon , 13 ไบต์ (ไม่ใช่การแข่งขัน)

O"^ vj"\CynIq

ลองออนไลน์! ใช้ลูกศรจริงเพราะเหตุใด

ไม่ใช่การแข่งขันเพราะ Crayon นั้นใหม่กว่าความท้าทายนี้

มันทำงานอย่างไร

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

การใช้ประโยชน์kและการjแทนและ

หมายเหตุสองประการ:

  • 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จนกว่าฉันจะเห็นพิพากษาว่า นี่คือเหตุผลสองประการ:
    • pb ไม่มีช่องว่างต่อท้าย มันมักจะผลิตสี่เหลี่ยมออก, ช่องว่างภายในหากมีความจำเป็น
    • โปรแกรมนี้สร้างบรรทัดว่างจำนวนมาก มันไม่ทราบวิธีการที่สูงการส่งออกเป็นไปได้เมื่อมันเริ่มทำมันดังนั้นสำหรับการป้อนข้อมูลของความยาวมันเริ่มต้นที่n เป็นเพราะมันจะลงจากและเริ่มต้นที่ล้มเหลวสำหรับใส่ของทั้งหมดY=3n+1-13nY=-1Y=2n-1k

คุณสามารถรับชมโปรแกรมนี้ได้บน 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

Ceylon, 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 ไบต์) บรรทัดสุดท้ายของเอาต์พุตว่างเปล่าเมื่อตำแหน่งเริ่มต้นอยู่บนมัน (เช่นอินพุตแรกคือ a หรือ^และเราไม่เคยได้ต่ำกว่านั้นอีกในภายหลัง) อินพุตที่ไม่ใช่อักขระที่ระบุอย่างใดอย่างหนึ่งจะพิมพ์ตามที่เป็นโดยไม่ต้องสลับบรรทัด:

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) รวมถึงตัวชี้ (nullable) ไปยังถัดไป ( n) และก่อนหน้า ( p) เส้น แอ็ตทริบิวต์ (ไม่เป็นโมฆะ) u(ขึ้น) และd(ลง) เตรียมใช้งานหากจำเป็น (ด้วยตัวชี้ย้อนกลับเพื่อตัวเอง) และในกรณีนี้ยังติดตามการรวมของบรรทัดแรกและบรรทัดสุดท้ายโดยรวม (ในfและlตัวแปร)

วิธีการa(ผนวก) ต่อท้ายอักขระในบรรทัดนี้รวมถึงช่องว่างที่จำเป็นในที่สุด

cเป็นบรรทัดปัจจุบัน เราแยกวิเคราะห์สตริงอินพุต (ใช้readLineเป็นอินพุตควรเป็นหนึ่งบรรทัด) โดยใช้คำสั่ง switch ที่อัพเดตบรรทัดปัจจุบันแล้วเรียกเมธอดผนวก

หลังจากแยกวิเคราะห์เสร็จแล้วเราวนซ้ำบรรทัดจากบรรทัดแรกถึงบรรทัดสุดท้ายโดยพิมพ์แต่ละบรรทัด (สิ่งนี้จะทำลายfตัวชี้หากจำเป็นหลังจากนั้นเราควรใช้ตัวแปรแยกต่างหากสำหรับสิ่งนี้)

เทคนิคบางอย่างที่ใช้สำหรับการเล่นกอล์ฟ:

  • บางสิ่งที่ภาษาอื่น ๆ จะเป็นคำหลักเป็นเพียงตัวระบุในceylon.languageแพ็คเกจและสามารถเปลี่ยนชื่อด้วยการนำเข้านามแฝง - เราใช้สิ่งนี้สำหรับบันทึกย่อshared(ใช้ 5 ×) และvariable(ใช้ 6 ×) เช่นเดียวกับวัตถุnull(ใช้ 4 ×):

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

    (สิ่งละอันพันละน้อย: ตัวจัดรูปแบบใน Ceylon IDE จัดรูปแบบหมายเหตุประกอบภาษาที่มีอยู่แล้วบางส่วนระหว่างพวกเขาvariableกับsharedโดยวางไว้ในบรรทัดเดียวกับการประกาศที่มีคำอธิบายประกอบเปรียบเทียบกับคำอธิบายประกอบที่กำหนดเองซึ่งวางอยู่บนบรรทัดแยกต่างหากเหนือการประกาศ ทำให้เวอร์ชันที่ฟอร์แมตแล้วของโปรแกรม golfed ไม่สามารถอ่านได้ดังนั้นฉันจึงเปลี่ยน alias-import กลับสำหรับรุ่นนี้)

    this, void, case, elseเป็นคำหลักที่เกิดขึ้นจริงและไม่สามารถเปลี่ยนชื่อด้วยวิธีนี้และInteger, StringและCharacterปรากฏเพียงครั้งเดียวในแต่ละครั้งเพื่อให้มีอะไรที่จะได้รับโดยการนำเข้า

  • เดิมทีฉันมีคลาส ScreenBuffer ที่แยกต่างหาก (ซึ่งติดตามรายการที่เชื่อมโยงของบัฟเฟอร์บรรทัดดัชนีปัจจุบันและอื่น ๆ ) แต่เนื่องจากมีเพียงวัตถุเดียวเท่านั้นมันจึงถูกปรับให้เหมาะสม

  • คลาส Screenbuffer นั้นมีupและdownวิธีการซึ่งถูกเรียกจาก parser (และเพิ่งทำcurrentLine = currentLine.upตามลำดับcurrentLine = currentLine.down) มันแสดงให้เห็นว่าการทำสิ่งนี้โดยตรงในสวิตช์ของ parser นั้นสั้นกว่า นอกจากนี้ยังได้รับอนุญาตให้เขียนcurrentLine = currentLine.up.up(ซึ่งต่อมากลายเป็นc = c.u.u) currentLine = currentLine.up;currentLine = currentLine.upแทน

  • ในขั้นต้นเราได้ส่งดัชนีปัจจุบันเป็นอาร์กิวเมนต์ไปยังเมธอดผนวก (และถึงตัวแยกวิเคราะห์จากลูป) ด้วยการให้ตัวแปรในฟังก์ชันที่บรรจุนั้นสั้นลง

  • เดิมวิธีการของฉัน printAll ใช้ตัวชี้ปัจจุบันและย้ายไปก่อนจนกว่าบรรทัดปัจจุบันจะว่างเปล่าและจากนั้นลงในขณะที่พิมพ์แต่ละบรรทัด สิ่งนี้หักเมื่อใช้▲และ▼เพื่อข้ามเส้นดังนั้นเราจึงต้องผนวกบางอย่างในบรรทัดที่เพิ่มขึ้นเหล่านั้นแทน การติดตามบรรทัดแรก / บรรทัดสุดท้ายนั้นพิสูจน์ได้ง่ายขึ้น (แม้ว่าจะจำเป็นต้องใช้สองงบการพิมพ์เพราะไม่มีลูปทำในขณะที่ใน Ceylon)

  • แต่เดิมฉันมีบางอย่างเช่นนี้:

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

    process.readLineผลตอบแทนnullถ้ามีเส้นซึ่งสามารถอ่านได้ (เพราะการป้อนข้อมูลที่ได้รับการปิด) ไม่มีและคอมไพเลอร์ศรีลังกาต้องการให้ฉัน checkfor inputว่าก่อนที่ผมจะเข้าถึง เช่นในกรณีนี้ฉันไม่ต้องการทำอะไรเลยฉันสามารถใช้elseโอเปอเรเตอร์ที่คืนค่าอาร์กิวเมนต์แรกหากไม่เป็นโมฆะและอาร์กิวเมนต์ที่สองจะบันทึกตัวแปรและ if-statement (นอกจากนี้ยังจะช่วยให้เราสามารถเข้ารหัสการป้อนข้อมูลเริ่มต้นสำหรับการทดสอบ: 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.