Văn bản hoạt hình nghệ thuật hình sin ASCII


11

Tôi phần nào nhớ những bản demo cũ cho thấy khả năng của máy tính khi chúng được gọi là x86 thay vì i3, i5 và i7. Một trong những sản phẩm đầu tiên tôi xem trong năm 386 là bản demo Unreal từ Future Crew hiện đang kỷ niệm 25 năm thành lập. Vào phút 3:43 , phần đầu tiên của bản demo bắt đầu và chúng ta thấy một văn bản cuộn theo con đường hình sin. Hãy thử bắt chước hiệu ứng đó trong nghệ thuật ASCII!

Các thách thức

Đưa ra con đường này:

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

và một văn bản đầu vào, vẽ văn bản theo đường dẫn đó, như thế này:

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

Lưu ý rằng các khoảng trắng được tính là các ký tự trong đường dẫn và đường dẫn đó lặp lại nếu văn bản dài hơn mẫu.

Phần hoạt hình

Khi bạn đã vẽ văn bản, hãy đợi 100 ms (để tạo một hình động khoảng 10 khung hình / giây) và vẽ lại văn bản nhưng bắt đầu từ vị trí tiếp theo của đường dẫn. Vì vậy, đối với khung #n, tính toán n modulo 40và bắt đầu vẽ ở vị trí sau của đường dẫn với văn bản luôn được căn chỉnh ở bên trái của khung vẽ:

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

Vì vậy, đối với khung 10 chúng ta sẽ có:

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

Ghi chú

  • Đầu vào sẽ là một string(hoặc charmảng, bất cứ thứ gì) với văn bản để tạo hiệu ứng và sẽ luôn có ít nhất 1 ký tự.
  • Các ký tự hợp lệ để tạo hiệu ứng là các ký tự trong bộ ASCII có thể in được .
  • Con đường để làm theo sẽ chính xác như được đưa ra.
  • Văn bản sẽ luôn được căn chỉnh ở bên trái của khung vẽ, do đó, hiệu ứng sẽ là văn bản vẫy như một lá cờ, không có sự dịch chuyển văn bản. Và bằng vải, ý tôi là màn hình hoặc bất cứ thứ gì bạn sẽ sử dụng để hiển thị văn bản . ;-)
  • Các khung phải rõ ràng về bất kỳ ký tự / pixel nào từ các khung trước trừ khi ký tự / pixel giống nhau trong cả hai khung.
  • Tốc độ của hình ảnh động không quan trọng miễn là nó chạy trơn tru hoặc nhanh như thiết bị của bạn (chúng tôi có thể đặt tối thiểu 5 khung hình / giây, nhưng đây không phải là một yêu cầu). Chỉ cần điều chỉnh tốc độ để làm cho nó trôi chảy và đừng lo lắng nếu thời gian chờ đợi không hoàn toàn giống nhau.
  • Các hình ảnh động sẽ lặp đi lặp lại vô tận.

Đây là , vì vậy có thể chương trình hoặc chức năng ngắn nhất có khả năng tạo hiệu ứng cho văn bản giành chiến thắng!



1
Tôi có thể đếm 38 cột thay vì 40.
Arnauld

1
@Arnauld đó là vì những gì được tính là vị trí trong đường dẫn, không phải các cột.
Charlie

Ồ tôi hiểu rồi. Có ý nghĩa.
Arnauld

này sao như đầu ra? Nó hiển thị đầu vào dưới dạng sóng hình sin và các vòng lặp vô tận. Tất nhiên, vì video ở định dạng Trao đổi đồ họa, nên thực tế nhanh hơn.
R. Kap

Câu trả lời:


9

HTML + ES6, 241 244 237 byte

Phá vỡ:

  • HTML: 16 byte
  • Hàm JS: 221 byte

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>

Làm sao?

Xây dựng đường dẫn

Đoạn mã sau xây dựng đường dẫn:

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

Điều này đưa ra một mảng các mảng [j, y, z]trong đó j là vị trí modulo 20, y là tọa độ y tại vị trí này và z không được sử dụng sau này (nó chỉ được tính ở đây để lưu một số byte).

Vì đường dẫn đối xứng, chúng ta chỉ cần mã hóa 20 vị trí đầu tiên. Chúng tôi làm điều đó bằng cách sử dụng một số nhị phân trong đó mỗi 1bit có nghĩa là y phải được cập nhật (+1 cho nửa đầu, -1 cho nửa sau).

001
   001
      01
        1
         1
         1
          1
           01
             001
                000

Với vị trí đầu tiên được ánh xạ tới bit ít quan trọng nhất, điều này mang lại:

00010010111110100100 as binary = 77732 as decimal

Bởi vì số nhị phân này tự nó cũng đối xứng, chúng ta có thể đọc nó theo thứ tự tương tự cho nửa thứ hai.

Do đó công thức:

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

cũng có thể được viết là:

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

Trong đó k là vị trí và j là vị trí modulo 20.

Cập nhật x dễ dàng hơn nhiều: chúng ta chỉ có một trường hợp đặc biệt để phát hiện bằng cách so sánh vị trí modulo 20 với 9.

Vẽ văn bản

Trong đoạn mã sau, mã xây dựng đường dẫn được mô tả ở trên đã được thay thế bằng một pathbiến để dễ đọc.

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

Điều này thật tuyệt vời và khá gần với con đường được hỏi, nhưng con đường không chính xác là con đường tôi đã vẽ. Hai cột chứa hai *theo chiều dọc không được căn chỉnh (ở cùng độ cao) và một cột nhỏ khác. Nhưng tôi phải nói rằng tôi vẫn không biết làm thế nào mã của bạn tạo ra hiệu ứng sóng ( y+=155464làm gì?). Xin chúc mừng!
Charlie

@CarlosAlejo Tôi nghĩ rằng đường dẫn nên được sửa chữa. Bạn có thể vui lòng kiểm tra lại? Tôi sẽ thêm một lời giải thích về phương pháp được sử dụng.
Arnauld

1
Đường dẫn đã được kiểm tra, và cảm ơn bạn rất nhiều vì lời giải thích!
Charlie
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.