Windows ME ekran koruyucusunu ASCII olarak yeniden oluşturun


19

Bu zorluk Ask Ubuntu Stack Exchange'deki bu cevaptan esinlenmiştir .

giriş

Windows ME ekran koruyucuyu hatırlıyor musunuz? Nostaljiyi geri getirme zamanı!

resim açıklamasını buraya girin

Meydan okuma

Ekran koruyucunun ASCII temsilini verecek bir program veya işlev yazmalısınız. Ekran koruyucusunda yarı rastgele yönlerde büyüyecek tek bir boru olmalıdır.
Borunun başlangıcı, ekranın sınırlarından herhangi birine rastgele yerleştirilir ve boru parçası sınıra dik olmalıdır (ilk köşe köşeleri yatay veya dikey olabilir). Her bir kene borunun baktığı yönde (yatay / dikey) bir 80%şansta büyüyecek veya bir şansı köşeye alacaktır 20%.

Boru gösterimi

Yöneltme oluşturmak için 6 unicode karakter kullanılacaktır

─    \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

Giriş

Program / fonksiyon, fonksiyon parametreleri aracılığıyla toplanabilen veya kullanıcıya sorulabilecek 3 giriş değeri alacaktır.

  • Kenelerin miktarı
  • Ekran genişliği
  • Ekran yüksekliği

Kenelerin miktarı

Her kene için ekrana bir parça boru eklenir. Borular, aynı konumda ortaya çıkarlarsa eski boru parçalarının üzerine yazılır.

Örneğin, 3x3 boyutunda bir ekran alın

ticks == 3
─┐ 
 ┘ 


ticks == 4
─┐ 
└┘ 


ticks == 5
│┐ 
└┘ 

Bir boru ekrandan her çıktığında, son örnekte olduğu gibi 5 kenede, yeni bir boru rastgele bir sınırda ortaya çıkar. Örneğin:

ticks == 6
│┐ 
└┘ 
  ─

Yeni borunun yatay veya dikey olma olasılığı% 50 olmalıdır.

Ekran genişliği / yüksekliği

Ekran genişliği ve yüksekliği, tercih ettiğiniz dilde tercih edilirse, tek bir değerde birleştirilebilir. Ekran genişliği ve yüksekliği her zaman minimum 1 ve maksimum 255 değerine sahip olacaktır. Seçtiğiniz dil 255x255 karakterlik bir ızgaradan daha küçük bir konsol veya çıktı ekranını destekliyorsa, genişlik ve yüksekliğin asla konsolunuzun sınırlarını aşmayın. (Örnek: Windows 80x25 cmd penceresi)

Çıktı

Programınızın / fonksiyonunuzun çıktısı ekrana yazdırılmalı veya bir fonksiyondan döndürülmelidir. Programınızın her çalışması için farklı bir boru kümesi oluşturulmalıdır.

Test senaryoları

Aşağıdaki test durumlarının tümü geçerli çıktıların rastgele örnekleridir

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

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

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

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

Açıkçası, daha fazla keneler meydana geldiğinde, programınızın geçerliliğini kanıtlamak zorlaşır. Bu nedenle, çıkış çalışmanızın bir gif'ini yayınlamak tercih edilecektir. Bu mümkün değilse, lütfen kodunuzun çıktıyı yazdırmayı içeren bir sürümünü gönderin. Açıkçası, bu puanınıza sayılmaz.

kurallar

  • Bu , en kısa miktarda bayt kazanır
  • Standart boşluklar geçerlidir
  • Kaynak kodunuzda unicode kanal karakterlerini kullanırsanız, bunları tek bir bayt olarak sayabilirsiniz

Bu, birçok yaratıcı yolla çözülebilecek oldukça zor bir sorundur, kısa esolanglarda zaten cevaplar olsa bile, daha ayrıntılı bir dilde cevap yazmanız önerilir. Bu, dil başına en kısa cevapların bir kataloğunu oluşturacaktır. Süslü renkli gif için bonus upvotes;)

Mutlu golf!

Feragatname: Unicode karakterlerin ASCII olmadığının farkındayım, ancak daha iyi bir isim olmadığına sadece ASCII sanatı diyorum. Öneriler bekliyoruz :)


9
Çıktıda olmasını istediğiniz unicode karakterler ASCII değildir.
Buğday Büyücüsü

2
Bence bu etiketlenmeli ascii-art yerinegraphical-output - referans
AdmBorkBork

13
Nostalji ve Windows ME aynı hatta iyi uymuyor
Luis Mendo

1
3D Pipes ekran koruyucusu Windows ME'den önce geldi.
Neil

1
@Jordan tuples demek istediğini sanıyordum.
KarlKastor

Yanıtlar:


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`
`)

Unicode çizim karakterlerini her biri 1 bayt olarak sayma. (OP tarafından belirtildiği gibi)

Daha az 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`
}

Animasyonlu test

Not: Animasyon süresini 30 saniyenin altında tutmaya çalışırken, daha fazla kalınlık animasyon hızını daha hızlı hale getirir

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>


Tam olarak QBasic'in bir golf maçı kazanabileceğini düşündüğümde. ;) Bir oy verin.
DLosc

12

Hiçbir şey nostalji gibi değil ...

QBasic, 332 bayt

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 görev için doğru dildir çünkü:

  • Kodlaması kutu çizim karakterleri içerir - Unicode'a gerek yoktur
  • LOCATE daha önce orada olanların üzerine yazarak ekrandaki herhangi bir konuma yazdırmanıza olanak tanır
  • Microsoft ®

Ayrıntılı Bilgiler

Bu golf QBasic, üzerinde yazılı ve test golf , otomatik biçimlendirme kapalı QB64 . Gerçek QBasic IDE'ye yazarsanız / yapıştırırsanız, bir grup boşluk ekler ve ?içine genişler PRINT, ancak tamamen aynı şekilde çalışmalıdır.

Program, virgülle ayrılmış üç değer girer: keneler, genişlik ve yükseklik. Daha sonra rastgele bir tohum ister. (Bu davranış kabul edilebilir değilse, ikinci satırı şu şekilde değiştirin:RANDOMIZE TIMER +6 bayt olarak değiştirin.) Son olarak, boruları ekrana çizer.

Girilebilecek maksimum boyutlar 80 (genişlik) x 25 (yükseklik) şeklindedir. QBasic "Devam etmek için herhangi bir tuşa basın" dediğinde, 25 yüksekliğinin verilmesi alt satırın kesilmesine neden olur.

Nasıl?

TL; DR: Çok fazla matematik.

Geçerli satır ve sütun rve c; geçerli yön dve önceki yön b. 0-3 yön değerleri aşağı, sağ, yukarı, sol. Aritmetik tercüme için doğru adım değerlere olanlar rvec başlangıç ​​için doğru kenar koordinatlarının yanı sıra .

Kutu çizim karakterleri │┐└─┘┌ QBasic'teki kod noktaları 179, 191, 192, 196, 217 ve 218'dir. Bunlar oldukça rasgele görünüyor, ancak yine de bazı koşullu ifadeler yapmaktan çok (çok kıvrımlı, emin değilim bile-anlıyorum) matematiği ile sayıları üretmek için daha az karakter kullanıyordu.

Yön değiştirme kodu, -0.125 ile 1.125 arasında rastgele bir sayı üretir ve yerini alır. Bu -1zamanın% 10'unu, zamanın 0% 80'ini ve zamanın% 10'unu verir 1. Daha sonra bunu dmod 4'ün geçerli değerine ekliyoruz. 0 eklenmesi geçerli yönü korur; +/- 1 eklemek dönüş yapar.

Kontrol akışına gelince WHILE t ... WEND, ana döngü; ondan önceki bölüm, satır numarası 1( 1b=INT(RND*4)) ile başlayarak boruyu rastgele bir kenardan yeniden başlatır. Ne zaman rve cpencerenin dışında olursak, biz GOTO 1.

Bana GIF'i göster!

Hadi bakalım:

Borular!

Bu, animasyon, renk ve otomatik rastgele bir tohum içeren biraz ungolfed versiyonu tarafından oluşturuldu:

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

Bunu MS-DOS v6.22 VM'ye yazdım :-)
Neil

9

Python 2.7, 624 616 569 548 552 bayt

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

İlk parametre bir tohumdur, aynı tohumlar aynı çıktıyı üretecek ve her adımı 500 ms'lik bir gecikmeyle basacaktır.

  • @TuukkaX sayesinde -10 bayt

cevapla

Örnek çalışma

f(5,6,3,3)

çıktı olacak

   

 ─┐ 
   

──┐ 
   

┘─┐ 
   
┐  
┘─┐ 

ayrıntılı versiyon

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

1
Konumunda yararsız bir boşluk var if x*y<0 or. 0.5azaltılabilir .5. import *olabilir import*. ''.join(k) foryararsız bir boşluğa sahiptir. Ayrıca dictbir değişkeni tutabilmeniz ve her kullandığınızda onu çağırabilmeniz gerekir. Bunun ne kadar tasarruf ettiğini test etmedim, ancak dict(zip(a,b))iki dize (a, b) için işi yapan bir lambda'yı kaydederek, biraz doğraması gerekir. +1.
Yytsi

7

C (GCC / Linux), 402 353 352 302 300 298 296 288 bayt

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

Yönü tek bir 4 bitlik sayıya kaydetmek için edc65'e teşekkür ederiz.

Ekran koruyucu sonsuza kadar döngü önce stdin bir genişlik / yükseklik okur. Örneğin:

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

Veya tam ekran bir ekran koruyucu için:

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

Okunabilirlik için satırsonu ekledim. ANSI kodlarına uygun terminalli bir linux makinesi gerektirir. Renkleri var! Renk desteğini kaldırırsanız maliyeti 17 bayt daha az olur.

misal


5

Yakut, 413 403 396 bayt

Yakut borular

Giriş olarak bir dizi keneyi ve genişliği alan ve son ekranı dize olarak döndüren bir işlev. Kuşkusuz daha fazla golf olabilir.

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

Repl.it sitesinde görün: https://repl.it/Db5h/4

Çalışırken görmek için, başlayan satırdan sonra aşağıdakileri ekleyin b[n*w+n+m]=:

puts b; sleep 0.2

... sonra lambda'yı bir değişkene atayın pipes=->...ve şöyle adlandırınpipes[100,20] (100 keneler ve 20x20 ekran için).

Açıklanmamış ve açıklama

# 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]
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.