ข้อความภาพเคลื่อนไหว ASCII ของศิลปะไซนัส


11

ฉันคิดถึงการสาธิตเก่า ๆ ที่แสดงความสามารถของคอมพิวเตอร์เมื่อพวกเขาถูกเรียกว่า x86 แทนที่จะเป็น i3, i5 และ i7 หนึ่งในคนแรกที่ฉันดูใน 386 ของฉันคือการสาธิตแบบไม่จริงจาก Future Crewที่ตอนนี้ฉลองครบรอบ 25 ปี ในนาทีที่ 0:43ส่วนแรกของการสาธิตจะเริ่มขึ้นและเราจะเห็นข้อความเลื่อนตามเส้นทางไซน์ มาลองเลียนแบบเอฟเฟกต์นั้นในศิลปะ ASCII กันเถอะ!

ความท้าทาย

รับเส้นทางนี้:

***                                ***
   ***                          ***
      **                      **
        *                    *
         *                  *
         *                  *
          *                *
           **            **
             ***      ***
                ******

และข้อความป้อนเข้าให้วาดข้อความตามเส้นทางดังกล่าว:

Thi                                Golf! 
   s i                          de       Yay
      s                       Co            !
        P                     
         r                  d
         o                  n
          g                a
           ra            s 
             mmi      zle
                ng Puz

โปรดทราบว่าช่องว่างนับเป็นตัวอักษรในเส้นทางและเส้นทางซ้ำตัวเองหากข้อความยาวกว่าตัวอย่าง

ส่วนภาพเคลื่อนไหว

เมื่อคุณวาดข้อความแล้วให้รอ 100 ms (เพื่อสร้างภาพเคลื่อนไหวประมาณ 10 fps) และวาดข้อความอีกครั้ง แต่เริ่มจากตำแหน่งถัดไปของเส้นทาง ดังนั้นสำหรับเฟรม#nให้คำนวณn modulo 40และเริ่มวาดในตำแหน่งต่อไปนี้ของเส้นทางด้วยข้อความที่จัดชิดซ้ายของผืนผ้าใบเสมอ:

***                                ***
|  ***                          ***  |
|     **                      **     |
|       *                    *       |
|        *                  *        |
|        *                  *        |
|         *                *         |
|          **            **          |
|            ***      ***            |
|               ******               |
Position 0                 Position 39

ดังนั้นสำหรับเฟรม 10 เราจะได้:

                           and Co
                        es       de 
                      zl            Go
                     z                l
                    u                  f
T                   P                  !
 h                                       
  is             ng                       Ya
     is       mmi                           y!
        Progra

หมายเหตุ

  • อินพุตจะเป็นหนึ่งเดียวstring(หรือcharอาเรย์อะไรก็ตาม) พร้อมข้อความที่ทำให้เคลื่อนไหวและจะมีอักขระอย่างน้อย 1 ตัวเสมอ
  • อักขระที่ถูกต้องในการเคลื่อนไหวคืออักขระในชุด ASCII ที่พิมพ์ได้
  • เส้นทางที่จะติดตามจะเป็นไปตามที่กำหนด
  • ข้อความจะถูกจัดตำแหน่งชิดซ้ายของผืนผ้าใบเสมอดังนั้นเอฟเฟกต์จะเป็นข้อความที่โบกมือเหมือนธงโดยไม่มีการกระจัดข้อความ และผ้าใบฉันหน้าจอเฉลี่ยหรือสิ่งที่คุณจะใช้ในการแสดงข้อความ ;-)
  • เฟรมต้องมีความชัดเจนของตัวละคร / พิกเซลจากเฟรมก่อนหน้ายกเว้นว่าอักขระ / พิกเซลจะเหมือนกันในเฟรมทั้งสอง
  • ความเร็วของแอนิเมชั่นนั้นไม่สำคัญว่ามันจะทำงานได้อย่างราบรื่นหรือเร็วเท่าที่อุปกรณ์ของคุณสามารถทำได้ (เราสามารถตั้งค่าขั้นต่ำ 5 fps แต่นี่ไม่ใช่ข้อกำหนด) เพียงปรับความเร็วเพื่อให้ลื่นไหลและไม่ต้องกังวลหากเวลาในการรอไม่เท่ากัน
  • ภาพเคลื่อนไหวจะวนซ้ำไม่รู้จบ

นี่คือดังนั้นโปรแกรมหรือฟังก์ชั่นที่สั้นที่สุดอาจทำให้แอนิเมชั่นชนะได้!


ที่เกี่ยวข้อง Sandbox
Charlie

1
ฉันสามารถนับได้ 38 คอลัมน์แทนที่จะเป็น 40
Arnauld

1
@Annauld นั่นเป็นเพราะสิ่งที่นับเป็นตำแหน่งในเส้นทางไม่ใช่คอลัมน์
Charlie

อ้อเข้าใจแล้ว. มีเหตุผล.
Arnauld

คือนี้โอเคเป็นผลผลิต? มันแสดงอินพุตในรูปของคลื่นไซน์และวนซ้ำไม่รู้จบ แน่นอนเนื่องจากวิดีโออยู่ในรูปแบบ Graphics Interchange มันจึงเร็วขึ้นตามความเป็นจริง
R. Kap

คำตอบ:


9

HTML + ES6, 241 244 237 ไบต์

แตกหัก:

  • HTML: 16 ไบต์
  • ฟังก์ชัน JS: 221 ไบต์

let f =

s=>setInterval(_=>o.innerHTML=[...s].map((c,i)=>([j,y]=[...Array(40)].map((_,k)=>[j=k%20,y,y+=77732>>j&1?k<20||-1:0],y=0)[(i+p)%40],a[y]=a[y]||[...s].fill` `)[x]=(x+=j!=9,c),x=0,a=[],p++)&&a.map(r=>r.join``).join`
`,p=30)

f("This is Programming Puzzles and Code Golf! Yay!")
<pre id=o></pre>

อย่างไร?

สร้างเส้นทาง

รหัสต่อไปนี้สร้างเส้นทาง:

[...Array(40)].map((_, k) =>
  [
    j = k % 20,
    y,
    y += 77732 >> j & 1 ? k < 20 || -1 : 0
  ],
  y = 0
)

นี่จะให้อาร์เรย์ของอาร์เรย์[j, y, z]โดยที่jคือตำแหน่งโมดูโล 20, yคือพิกัด y ที่ตำแหน่งนี้และzไม่ได้ถูกใช้ในภายหลัง

เนื่องจากเส้นทางนั้นสมมาตรเราจึงต้องเข้ารหัสตำแหน่ง 20 อันดับแรกเท่านั้น เราทำเช่นนั้นโดยใช้เลขฐานสองที่แต่ละ1บิตหมายความว่าyต้องได้รับการอัปเดต (+1 สำหรับครึ่งแรก, -1 สำหรับครึ่งหลัง)

001
   001
      01
        1
         1
         1
          1
           01
             001
                000

เมื่อตำแหน่งแรกถูกแมปกับบิตที่มีนัยสำคัญน้อยที่สุดสิ่งนี้จะทำให้:

00010010111110100100 as binary = 77732 as decimal

เนื่องจากเลขฐานสองนี้เองก็สมมาตรเราจึงสามารถอ่านได้ในลำดับเดียวกันสำหรับครึ่งหลัง

ดังนั้นสูตร:

y += (77732 >> j) & 1 ? (k < 20 ? 1 : -1) : 0

ซึ่งสามารถเขียนเป็น:

y += (77732 >> j) & 1 ? k < 20 || -1 : 0

โดยที่kคือตำแหน่งและjคือตำแหน่งโมดูโล 20

การอัพเดตxนั้นง่ายกว่ามาก: เรามีกรณีพิเศษเพียงหนึ่งกรณีที่จะตรวจจับโดยการเปรียบเทียบตำแหน่งโมดูโล 20 กับ 9

การวาดข้อความ

ในรหัสต่อไปนี้รหัสการสร้างพา ธ ที่อธิบายไว้ข้างต้นถูกแทนที่ด้วยpathตัวแปรเพื่อให้สามารถอ่านได้

s => setInterval(                       // set a periodic timer:
  _ =>                                  //   with an anonymous callback
    o.innerHTML =                       //   which updates the content of 'o'
      [...s].map((c, i) => (            //   for each character c of the string s
          [j, y] = path[(i + p) % 40],  //     retrieve j and y from the path
          a[y] = a[y] || [...s].fill` ` //     initialize a[y] if it's undefined
        )[x] = (x += j! = 9, c),        //     update a[y][x] / update x
        x = 0,                          //     initialize x
        a = [],                         //     initialize a[]
        p++                             //     increment the phase
      ) &&                              //   end of map()
      a.map(r => r.join``).join`\n`,    //   join everything together
  p = 30                                //   initial phase = interval period = 30
)                                       // end of timer definition

นี่เป็นสิ่งที่ยอดเยี่ยมและค่อนข้างใกล้กับเส้นทางที่ถาม แต่เส้นทางนั้นไม่ตรงกับที่ฉันวาด คอลัมน์สองคอลัมน์ที่มีสองคอลัมน์*ในแนวตั้งจะไม่จัดแนว (ที่ความสูงเท่ากัน) และ nitpick ขนาดเล็กอีกอัน แต่ฉันต้องบอกว่าฉันยังไม่รู้ว่าโค้ดของคุณสร้างเอฟเฟกต์คลื่นได้อย่างไร (จะy+=155464ทำอย่างไร) ขอแสดงความยินดี!
Charlie

@CarlosAlejo ฉันคิดว่าเส้นทางควรได้รับการแก้ไขแล้ว คุณกรุณาตรวจสอบอีกครั้งได้ไหม ฉันจะเพิ่มคำอธิบายของวิธีการที่ใช้
Arnauld

1
ตรวจสอบเส้นทางแล้วและขอบคุณมากสำหรับคำอธิบาย!
Charlie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.