Buat kembali screensaver Windows ME sebagai ASCII

19

Tantangan ini terinspirasi dari jawaban ini di Ask Ubuntu Stack Exchange.

Intro

Ingat screensaver Windows ME dengan pipanya ? Saatnya mengembalikan nostalgia!

masukkan deskripsi gambar di sini

Tantangan

Anda harus menulis program atau fungsi yang akan menampilkan representasi ASCII dari screensaver. Di screensaver harus ada satu pipa yang akan tumbuh ke arah semi-acak.
Awal pipa akan ditempatkan secara acak di salah satu perbatasan layar dan potongan pipa harus tegak lurus terhadap perbatasan (sudut pertama-pipa bisa horisontal atau vertikal). Setiap tik pipa akan tumbuh ke arah yang dihadapinya (horizontal / vertikal) pada 80%kesempatan atau mengambil sudut pada 20%kesempatan.

Representasi pipa

Untuk membuat pipa, 6 karakter unicode akan digunakan

─    \u2500    horizontal pipe
│    \u2502    vertical pipe
┌    \u250C    upper left corner pipe
┐    \u2510    upper right corner pipe
└    \u2514    lower left corner pipe
┘    \u2518    lower right corner pipe

Memasukkan

Program / fungsi akan mengambil 3 nilai input, yang dapat dikumpulkan melalui parameter fungsi atau diminta kepada pengguna.

  • Jumlah kutu
  • Lebar layar
  • Tinggi layar

Jumlah kutu

Untuk setiap centang, sepotong pipa akan ditambahkan ke layar. Pipa akan menimpa potongan pipa lama jika mereka bertelur pada posisi yang sama.

Misalnya, ambil layar berukuran 3x3

ticks == 3
─┐ 
 ┘ 


ticks == 4
─┐ 
└┘ 


ticks == 5
│┐ 
└┘ 

Setiap kali pipa keluar dari layar, seperti pada contoh terakhir di 5 ticks, maka pipa baru akan muncul di perbatasan acak. Sebagai contoh:

ticks == 6
│┐ 
└┘ 
  ─

Pipa baru harus memiliki peluang 50% untuk horisontal atau vertikal.

Lebar layar / tinggi

Lebar dan tinggi layar dapat digabungkan menjadi satu nilai jika itu lebih disukai dalam bahasa pilihan Anda. Lebar dan tinggi layar akan selalu memiliki nilai minimum 1 dan nilai maksimum 255. Jika bahasa pilihan Anda mendukung layar konsol atau output yang lebih kecil dari karakter grid 255x255 maka Anda dapat mengasumsikan bahwa lebar dan tinggi akan jangan pernah melebihi batas konsol Anda. (Contoh: Jendela Windows 80x25 cmd)

Keluaran

Output dari program / fungsi Anda harus dicetak ke layar, atau dikembalikan dari suatu fungsi. Untuk setiap proses program Anda, set pipa yang berbeda harus dihasilkan.

Uji kasus

Kasus uji berikut adalah contoh acak dari output yang valid

f(4, 3, 3)
 │
─┘
  │

f(5, 3, 3)
 │
─┘┌
  │

f(6, 3, 3)
─│
─┘┌
  │

f(7, 3, 3)
──
─┘┌
  │

Jelas, semakin banyak kutu yang terjadi, semakin sulit untuk membuktikan validitas program Anda. Karenanya, memposting gif dari output Anda yang berjalan akan lebih disukai. Jika ini tidak memungkinkan, silakan kirim versi kode Anda yang mencakup pencetakan output. Jelas, ini tidak akan dihitung dalam skor Anda.

Aturan

  • Ini adalah , jumlah byte terpendek yang menang
  • Celah standar berlaku
  • Jika Anda menggunakan karakter pipa unicode dalam kode sumber Anda, Anda dapat menghitungnya sebagai satu byte

Ini adalah tantangan yang cukup sulit yang mungkin dapat dipecahkan dengan banyak cara kreatif, Anda didorong untuk menulis jawaban dalam bahasa yang lebih verbal meskipun sudah ada jawaban dalam esolang pendek. Ini akan membuat katalog jawaban terpendek per bahasa. Bonus upvotes untuk gif berwarna mewah;)

Selamat bermain golf!

Penafian: Saya sadar bahwa karakter Unicode bukan ASCII, tetapi karena tidak memiliki nama yang lebih baik, saya hanya menyebutnya sebagai seni ASCII. Saran dipersilahkan :)

Bassdrop Cumberwubwubwub
sumber
9
Karakter unicode yang Anda inginkan dalam output bukan ASCII.
Wheat Wizard
2
Saya pikir ini harus ditandai ascii-artbukan graphical-output- referensi
AdmBorkBork
13
Nostalgia dan Windows ME tidak cocok pada baris yang sama
Luis Mendo
1
Screensaver Pipa 3D mendahului Windows ME.
Neil
1
@ Jordan, saya pikir maksudnya adalah tupel.
KarlKastor

Jawaban:

9

JavaScript (ES6), 264 266 274 281

(t,w,h,r=n=>Math.random()*n|0,g=[...Array(h)].map(x=>Array(w).fill` `))=>((y=>{for(x=y;t--;d&1?y+=d-2:x+=d-1)x<w&y<h&&~x*~y?0:(d=r(4))&1?x=r(w,y=d&2?0:h-1):y=r(h,x=d?0:w-1),e=d,d=r(5)?d:2*r(2)-~d&3,g[y][x]="─└ ┌┐│┌  ┘─┐┘ └│"[e*4|d]})(w),g.map(x=>x.join``).join`
`)

Menghitung karakter gambar unicode masing-masing 1 byte. (Seperti yang ditentukan oleh OP)

Kurang golf

(t,w,h)=>{
  r=n=>Math.random()*n|0; // integer range random function
  g=[...Array(h)].map(x=>Array(w).fill(' ')); // display grid
  for (x=y=w;t--;)
    x<w & y<h && ~x*~y||( // if passed boundary
      d = r(4), // select random direction
      d & 1? (x=r(w), y=d&2?0:h-1) : (y=r(h), x=d?0:w-1) // choose start position 
    ),
    e=d, d=r(5)?d:2*r(2)-~d&3, // change direction 20% of times
    g[y][x]="─└ ┌┐│┌  ┘─┐┘ └│"[e*4|d], // use char based on current+prev direction
    d&1 ? y+=d-2 : x+=d-1 // change x,y position based on direction
  return g.map(x=>x.join``).join`\n`
}

Tes animasi

Catatan: mencoba menjaga waktu animasi di bawah 30 detik, lebih tebal membuat laju animasi lebih cepat

f=(t,w,h,r=n=>Math.random()*n|0,g=[...Array(h)].map(x=>Array(w).fill` `))=>
{
  z=[]
  for(x=y=w;t--;d&1?y+=d-2:x+=d-1)
    x<w&y<h&&~x*~y?0:(d=r(4))&1?x=r(w,y=d&2?0:h-1):y=r(h,x=d?0:w-1),
    e=d,d=r(5)?d:2*r(2)-~d&3,g[y][x]="─└ ┌┐│┌  ┘─┐┘ └│"[e*4|d],
    z.push(g.map(x=>x.join``).join`\n`)
  return z
}

function go() {
  B.disabled=true
  var [t,w,h]=I.value.match(/\d+/g)
  var r=f(+t,+w,+h)
  O.style.width = w+'ch';
  var step=0
  var animate =_=>{
    S.textContent = step
    var frame= r[step++]
    if (frame) O.textContent = frame,setTimeout(animate, 30000/t);
    else   B.disabled=false
  }
  
  animate()
}

go()
#O { border: 1px solid #000 }
Input - ticks,width,height
<input value='600,70,10' id=I><button id=B onclick='go()'>GO</button>
<span id=S></span>
<pre id=O></pre>

edc65
sumber
Tepat ketika saya berpikir QBasic mungkin benar-benar memenangkan tantangan golf. ;) Selamat mencoba.
DLosc
12

Tidak ada yang mengatakan nostalgia seperti ...

QBasic, 332 byte

INPUT t,w,h
RANDOMIZE
CLS
1b=INT(RND*4)
d=b
IF b MOD 2THEN c=(b-1)/2*(w-1)+1:r=1+INT(RND*h)ELSE c=1+INT(RND*w):r=b/2*(h-1)+1
WHILE t
LOCATE r,c
m=(b+d)MOD 4
IF b=d THEN x=8.5*m ELSE x=13*m+(1<((b MOD m*3)+m)MOD 5)
?CHR$(179+x);
r=r-(d-1)MOD 2
c=c-(d-2)MOD 2
b=d
d=(4+d+INT(RND*1.25-.125))MOD 4
t=t-1
IF(r<=h)*(c<=w)*r*c=0GOTO 1
WEND

QBasic adalah bahasa yang tepat untuk tugas tersebut karena:

  • Pengkodeannya mencakup karakter menggambar kotak - tidak perlu untuk Unicode
  • LOCATE memungkinkan Anda mencetak ke lokasi mana pun di layar, menimpa apa yang ada sebelumnya
  • Microsoft ®

Spesifik

Ini QBasic golf, ditulis dan diuji pada QB64 dengan autoformatting dimatikan. Jika Anda mengetik / menempelkannya ke IDE QBasic yang sebenarnya, itu akan menambah banyak ruang dan memperluas ?kePRINT , tetapi harus dijalankan persis sama.

Program memasukkan tiga nilai yang dipisahkan koma: kutu, lebar, dan tinggi. Kemudian meminta benih nomor acak. (Jika perilaku ini tidak dapat diterima, ubah baris kedua menjadiRANDOMIZE TIMER +6 byte.) Akhirnya, ia menarik pipa ke layar.

Dimensi maksimum yang bisa dimasukkan adalah 80 (lebar) kali 25 (tinggi). Memberikan ketinggian 25 akan menghasilkan baris bawah terputus ketika QBasic mengatakan "Tekan tombol apa saja untuk melanjutkan."

Bagaimana?

TL; DR: Banyak matematika.

Baris dan kolom saat ini adalah rdan c; arah saat ini ddan arah sebelumnya adalah b. Nilai arah 0-3 turun, kanan, atas, kiri. Aritmatika menerjemahkannya ke dalam nilai langkah yang benar untuk rdanc , serta koordinat tepi yang benar untuk memulai.

Karakter kotak menggambar │┐└─┘┌ adalah titik kode 179, 191, 192, 196, 217, dan 218 di QBasic. Itu tampak sangat acak, tetapi masih menggunakan lebih sedikit karakter untuk menghasilkan angka dengan beberapa (cukup berbelit-belit, saya-tidak-yakin-bahkan-saya-mengerti-itu) matematika daripada melakukan banyak pernyataan kondisional.

Kode untuk mengubah arah menghasilkan angka acak antara -0,125 dan 1,125 dan mengambil dasarnya. Ini memberikan -110% dari waktu, 080% dari waktu, dan 110% dari waktu. Kami kemudian menambahkan ini ke nilai saat ini d, mod 4. Menambahkan 0 menjaga arah saat ini; menambahkan +/- 1 berbelok.

Adapun aliran kontrol, WHILE t ... WENDadalah loop utama; bagian sebelumnya, dimulai dengan nomor baris 1( 1b=INT(RND*4)), restart pipa di tepi acak. Kapan saja rdan di cluar jendela, kitaGOTO 1 .

Tunjukkan pada saya GIF!

Ini dia:

Pipa!

Ini dihasilkan oleh versi yang agak tidak disunat dengan animasi, warna, dan seed acak otomatis:

INPUT t, w, h
RANDOMIZE TIMER
CLS

restart:
' Calculate an edge to start from

b = INT(RND * 4)
'0: top edge (moving down)
'1: left edge (moving right)
'2: bottom edge (moving up)
'3: right edge (moving left)
d = b

' Calculate column and row for a random point on that edge
IF b MOD 2 THEN
    c = (b - 1) / 2 * (w - 1) + 1
    r = 1 + INT(RND * h)
ELSE
    c = 1 + INT(RND * w)
    r = b / 2 * (h - 1) + 1
END IF
COLOR INT(RND * 15) + 1

WHILE t
    ' Mathemagic to generate the correct box-drawing character
    m = (b + d) MOD 4
    IF b = d THEN
        x = 17 * m / 2
    ELSE
        x = 13 * m + (1 < ((b MOD m * 3) + m) MOD 5)
    END IF
    LOCATE r, c
    PRINT CHR$(179 + x);

    ' Update row and column
    r = r - (d - 1) MOD 2
    c = c - (d - 2) MOD 2
    ' Generate new direction (10% turn one way, 10% turn the other way,
    ' 80% go straight)
    b = d
    d = (4 + d + INT(RND * 1.25 - .125)) MOD 4

    ' Pause
    z = TIMER
    WHILE TIMER < z + 0.01
        IF z > TIMER THEN z = z - 86400
    WEND

    t = t - 1
    IF r > h OR c > w OR r = 0 OR c = 0 THEN GOTO restart
WEND
DLosc
sumber
Saya telah mengetik ini ke dalam MS-DOS v6.22 VM saya :-)
Neil
9

Python 2.7, 624 616 569 548 552 byte

from random import*
from time import*
i=randint
z=lambda a,b:dict(zip(a,b))
c={'u':z('lur',u'┐│┌'),'d':z('ldr',u'┘│└'),'l':z('uld',u'└─┌'),'r':z('urd',u'┘─┐')}
m=z('udlr',[[0,-1],[0,1],[-1,0],[1,0]])
def f(e,t,w,h):
 seed(e);s=[w*[' ',]for _ in' '*h]
 while t>0:
  _=i(0,1);x,y=((i(0,w-1),i(0,1)*(h-1)),(i(0,1)*(w-1),i(0,h-1)))[_];o=('du'[y>0],'rl'[x>0])[_]
  while t>0:
   d=c[o].keys()[i(7,16)//8];s[y][x]=c[o][d];x+=m[d][0];y+=m[d][1];t-=1;sleep(.5);print'\n'.join([''.join(k)for k in s]);o=d
   if(x*y<0)+(x>=w)+(y>=h):break

Parameter pertama adalah seed, seed yang sama akan menghasilkan output yang sama, mencetak setiap langkah dengan jeda 500 ms.

  • -10 byte berkat @TuukkaX

ganti itu

Contoh dijalankan

f(5,6,3,3)

akan menampilkan

   

 ─┐ 
   

──┐ 
   

┘─┐ 
   
┐  
┘─┐ 

versi verbose

import random as r
from time import *
char={
'u':{'u':'│','l':'┐','r':'┌'},
'd':{'d':'│','l':'┘','r':'└'},
'l':{'u':'└','d':'┌','l':'─'},
'r':{'u':'┘','d':'┐','r':'─'}
}
move={'u':[0,-1],'d':[0,1],'l':[-1,0],'r':[1,0]}
def f(seed,steps,w,h):
 r.seed(seed)
 screen=[[' ',]*w for _ in ' '*h]
 while steps > 0:
  if r.randint(0,1):
   x,y=r.randint(0,w-1),r.randint(0,1)*(h-1)
   origin='du'[y>0]  
  else:
   x,y=r.randint(0,1)*(w-1),r.randint(0,h-1)
   origin = 'rl'[x>0]
  while steps > 0:
   direction = char[origin].keys()[r.randint(0,2)]
   screen[y][x]=char[origin][direction]
   x+=move[direction][0]
   y+=move[direction][1]
   steps-=1
   sleep(0.5)
   print '\n'.join([''.join(k) for k in screen]),''
   if x<0 or y<0 or x>=w or y>=h:
    break
   origin=direction
tongkat
sumber
1
Ada ruang kosong yang tidak berguna di if x*y<0 or. 0.5dapat dikurangi menjadi .5. import *bisa jadi import*. ''.join(k) formemiliki ruang putih yang tidak berguna. Anda juga harus bisa menyimpan dictdalam variabel dan memanggilnya setiap kali Anda menggunakannya. Belum diuji berapa banyak ini menghemat, tetapi dengan menyimpan dict(zip(a,b))dalam lambda yang melakukan pekerjaan untuk dua string (a, b), itu harus memotong beberapa. +1.
Yytsi
7

C (GCC / linux), 402 353 352 302 300 298 296 288 byte

#define R rand()%
x,y,w,h,r;main(c){srand(time(0));scanf(
"%d%d",&w,&h);for(printf("\e[2J");x%~w*
(y%~h)||(c=R 8,(r=R 4)&1?x=1+R w,y=r&2
?1:h:(y=1+R h,x=r&2?1:w));usleep('??'))
printf("\e[%dm\e[%d;%dH\342\224%c\e[H\n",
30+c,y,x,2*"@J_FHAF__L@HL_JA"[r*4|(r^=R 5
?0:1|R 4)]),x+=--r%2,y+=~-r++%2;}

Kredit untuk edc65 untuk menyimpan arah dalam satu nomor 4-bit.

Membaca lebar / tinggi pada stdin sebelum menggulung screensaver selamanya. Misalnya:

gcc -w golf.c && echo "25 25" | ./a.out

Atau untuk screensaver layar penuh:

gcc -w golf.c && resize | sed 's/[^0-9]*//g' | ./a.out

Untuk keterbacaan saya menambahkan baris baru. Membutuhkan mesin linux dengan terminal yang menghormati kode ANSI. Memiliki warna! Jika Anda menghapus dukungan warna harganya lebih murah 17 byte.

contoh

orlp
sumber
5

Ruby, 413 403 396 byte

Pipa Ruby

Fungsi yang mengambil sejumlah kutu dan lebar sebagai input dan mengembalikan layar akhir sebagai string. Tidak diragukan lagi bisa bermain golf lebih banyak.

->t,w{k=[-1,0,1,0,-1]
b=(" "*w+$/)*w
f=->t,a=[[0,m=rand(w),2],[w-1,m,0],[m,0,1],[m,w-1,3]].sample{n,m,i=a
d=k[i,2]
q=->n,m,i{_,g,j=rand>0.2?[[1,0],[3,0],[0,1],[2,1]].assoc(i):"021322033132243140251350".chars.map(&:to_i).each_slice(3).select{|c,|c==i}.sample
v,u=k[j||=i,2]
y=n+v
x=m+u
[g,y,x,j]}
g,y,x,j=q[n,m,i]
b[n*w+n+m]="─│┌┐┘└"[g]
y>=0&&y<w&&x>=0&&x<w ?t>1?f[t-1,[y,x,j]]:b:f[t]}
f[t]}

Lihat di repl.it: https://repl.it/Db5h/4

Untuk melihatnya beraksi, masukkan berikut ini setelah baris yang dimulai b[n*w+n+m]=:

puts b; sleep 0.2

... kemudian tetapkan lambda ke variabel eg pipes=->...dan beri nama sepertipipes[100,20] (untuk 100 ticks dan layar 20x20).

Tidak dikelompokkan & penjelasan

# Anonymous function
# t - Number of ticks
# w - Screen width
->t,w{
  # The cardinal directions ([y,x] vectors)
  # Up = k[0..1], Right = k[1..2] etc.
  k = [-1, 0, 1, 0, -1]

  # An empty screen as a string
  b = (" " * w + $/) * w

  # Main tick function (recursive)
  # t - The number of ticks remaining
  # a - The current position and vector index; if not given is generated randomly
  f = ->t,a=[[0,m=rand(w),2], [w-1,m,0], [m,0,1], [m,w-1,3]].sample{
    # Current row, column, and vector index
    n, m, i = a
    d = k[i,2] # Get vector by index

    # Function to get the next move based on the previous position (n,m) and direction (d)
    q = ->n,m,i{
      # Choose the next pipe (`g` for glyph) and get the subsequent vector index (j)
      _, g, j = (
        rand > 0.2 ?
          [[1,0], [3,0], [0,1], [2,1]].assoc(i) : # 80% of the time go straight
          "021322033132243140251350".chars.map(&:to_i).each_slice(3)
            .select{|c,|c==i}.sample
      )

      # Next vector (`v` for vertical, `u` for horizontal)
      # If straight, `j` will be nil so previous index `i` is used
      v, u = k[j||=i, 2]

      # Calculate next position
      y = n + v
      x = m + u

      # Return next glyph, position and vector index
      [g, y, x, j]
    }

    # Get next glyph, and subsequent position and vector index
    g, y, x, j = q[n, m, i]

    # Draw the glyph
    b[n * w + n + m] = "─│┌┐┘└"[g]

    # Check for out-of-bounds
    y >= 0 && y < w && x >=0 && x < w ?
      # In bounds; check number of ticks remaining
      t > 1 ?
        f[t-1, [y,x,j]] : # Ticks remain; start next iteration
        b : # No more ticks; return final screen

      # Out of bounds; repeat tick with new random start position
      f[t]
  }
  f[t]
}
Yordania
sumber