Windows ME 화면 보호기를 ASCII로 다시 작성


19

이 문제는에서 영감 물어보기 우분투 스택 거래소 대답.

소개

파이프가 있는 Windows ME 화면 보호기를 기억 하십니까? 향수를 되 찾을 시간입니다!

여기에 이미지 설명을 입력하십시오

도전

화면 보호기의 ASCII 표현을 출력하는 프로그램이나 함수를 작성해야합니다. 스크린 세이버에는 반 무작위 방향으로 자라는 단일 파이프가 있어야합니다.
파이프의 시작은 화면의 테두리에 무작위로 배치되며 파이프 조각은 테두리와 수직이어야합니다 (첫 번째 파이프는 수평 또는 수직 일 수 있음). 각 진드기가 파이프가 80%우연히 마주 보는 방향 (수평 / 수직)으로 자라 거나 우연히 코너를 20%돌 것입니다.

파이프 표현

파이프를 만들려면 6 개의 유니 코드 문자가 사용됩니다.

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

입력

프로그램 / 기능은 3 개의 입력 값을 가지는데, 이는 기능 매개 변수를 통해 수집되거나 사용자에게 프롬프트 될 수 있습니다.

  • 진드기의 양
  • 화면 너비
  • 화면 높이

진드기의 양

모든 진드기마다 파이프 조각이 화면에 추가됩니다. 파이프는 같은 위치에 생성되면 오래된 파이프 조각을 덮어 씁니다.

예를 들어 3x3 크기의 화면을

ticks == 3
─┐ 
 ┘ 


ticks == 4
─┐ 
└┘ 


ticks == 5
│┐ 
└┘ 

마지막 예에서와 같이 파이프가 화면을 종료 할 때마다 임의의 경계에 새 파이프가 생성됩니다. 예를 들면 다음과 같습니다.

ticks == 6
│┐ 
└┘ 
  ─

새 파이프는 50 %의 수평 또는 수직 확률을 가져야합니다.

화면 너비 / 높이

원하는 언어로 화면 너비와 높이를 단일 값으로 결합 할 수 있습니다. 화면 너비와 높이는 항상 최소값 1과 최대 값 255입니다. 선택한 언어가 255x255 문자 격자보다 작은 콘솔 또는 출력 화면을 지원하는 경우 너비와 높이가 콘솔의 경계를 넘지 마십시오. (예 : Windows 80x25 cmd 창)

산출

프로그램 / 기능의 출력은 화면에 인쇄되거나 기능에서 반환되어야합니다. 프로그램을 실행할 때마다 다른 파이프 세트가 생성되어야합니다.

테스트 사례

다음 테스트 사례는 모두 유효한 출력의 임의의 예입니다.

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

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

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

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

분명히, 진드기가 많을수록 프로그램의 유효성을 증명하기가 더 어려워집니다. 따라서, 실행중인 출력의 gif를 게시하는 것이 좋습니다. 이것이 가능하지 않은 경우, 출력 인쇄가 포함 된 코드 버전을 게시하십시오. 분명히 이것은 점수에 포함되지 않습니다.

규칙

  • 이것은 가장 짧은 바이트 수의 .
  • 표준 허점 적용
  • 소스 코드에서 유니 코드 파이프 문자를 사용하는 경우 단일 바이트로 계산할 수 있습니다

이것은 많은 창조적 인 방법으로 해결 될 수있는 매우 어려운 도전입니다. 이미 짧은 esolang으로 답변이 있더라도 더 자세한 언어로 답변을 작성하는 것이 좋습니다. 언어별로 가장 짧은 답변의 카탈로그가 만들어집니다. 화려한 컬러 GIF에 대한 보너스 공감;)

행복한 골프!

면책 조항 : 유니 코드 문자는 ASCII가 아니지만 더 나은 이름이 없으면 ASCII 아트라고 부릅니다. 제안은 환영합니다 :)


9
출력에서 원하는 유니 코드 문자는 ASCII가 아닙니다.
밀 마법사

2
나는 이것이 태그 ascii-art대신 태그되어야한다고 생각한다 graphical-outputreference
AdmBorkBork

13
향수Windows ME 는 같은 라인에 적합하지 않습니다.
Luis Mendo

1
3D 파이프 화면 보호기는 Windows ME보다 먼저 예정되었습니다.
Neil

1
@ 요르단 나는 그가 튜플을 의미한다고 생각했다.
KarlKastor

답변:


9

자바 스크립트 (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`
`)

유니 코드 그리기 문자를 각각 1 바이트로 계산합니다. (OP에서 지정한대로)

덜 골프

(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`
}

애니메이션 테스트

참고 : 애니메이션 시간을 30 초 미만으로 유지하려고하면 더 두꺼울수록 애니메이션 속도가 빨라집니다

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>


QBasic이 실제로 골프 도전에서 이길 수 있다고 생각했을 때. ;) 공감하십시오.
DLosc

12

향수 같은 것이 아무것도 없습니다 ...

QBasic, 332 바이트

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은 다음과 같은 이유로 작업에 적합한 언어입니다.

  • 인코딩에는 상자 그리기 문자가 포함되어 있으며 유니 코드가 필요 없습니다.
  • LOCATE 화면의 어느 위치로나 인쇄하여 이전에 있던 것을 덮어 쓸 수 있습니다.
  • 마이크로 소프트 ®

사양

이것은 QBasic의 골프 이며, 자동 서식이 해제 된 상태 에서 QB64 에서 작성 및 테스트되었습니다 . 실제 QBasic IDE에 입력 / 붙여 넣기하면 많은 공간이 추가되고 확장됩니다.?PRINT,하지만 정확히 같은 실행해야합니다.

프로그램은 틱, 너비 및 높이의 세 가지 쉼표로 구분 된 값을 입력합니다. 그런 다음 난수 시드를 요청합니다. 이 동작이 허용되지 않으면 두 번째 줄을RANDOMIZE TIMER +6 바이트 . 마지막으로 파이프를 화면에 그립니다.

입력 할 수있는 최대 치수는 80 (너비) x 25 (높이)입니다. QBasic이 "계속하려면 아무 키나 누르십시오"라고 말하면 높이가 25가되면 맨 아래 줄이 잘립니다.

어떻게?

TL; DR : 많은 수학.

현재 행과 열은 rc; 현재 방향은 d이전 방향입니다 b. 방향 값 0-3은 아래쪽, 오른쪽, 위쪽, 왼쪽입니다. 산술은 이들을 올바른 단계 값으로 변환 r하고c 에 시작하는 올바른 모서리 좌표로 변환합니다.

상자 그림 문자 │┐└─┘┌ 는 QBasic의 코드 포인트 179, 191, 192, 196, 217 및 218입니다. 그것들은 꽤 무작위로 보이지만, 많은 조건문을 수행하는 것보다 약간의 문자를 사용하여 (꽤 복잡한, 나는 확실하지 않습니다-나는 이해하지 못합니다) 수학으로 숫자를 생성했습니다.

방향을 변경하는 코드는 -0.125와 1.125 사이의 난수를 생성하고 바닥을 취합니다. 이것은 -1시간의 10 %, 시간의 080 % 및 시간의 110 %를 제공합니다. 그런 다음 이것을 현재 값에 추가합니다d mod 4에 추가합니다. 0을 추가하면 현재 방향이 유지됩니다. +/- 1을 추가하면 회전합니다.

제어 흐름에 관해서 WHILE t ... WEND는 메인 루프입니다. 줄 번호 1( 1b=INT(RND*4))로 시작하기 전의 섹션 은 임의의 가장자리에서 파이프를 다시 시작합니다. r그리고 c창문 밖에 있을 때마다GOTO 1 .

GIF를 보여주세요!

여기 있습니다 :

파이프!

이것은 애니메이션, 색상 및 자동 임의 시드가있는 다소 ungolfed 버전으로 생성되었습니다.

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

이것을 MS-DOS v6.22 VM에 입력했습니다. :-)
Neil

9

파이썬 2.7, 624 616 569 548 552 바이트

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

첫 번째 매개 변수는 시드이며 동일한 시드는 동일한 출력을 생성하여 각 단계를 500ms 지연으로 인쇄합니다.

  • @TuukkaX 덕분에 -10 바이트

그것을 다시

예제 실행

f(5,6,3,3)

출력합니다

   

 ─┐ 
   

──┐ 
   

┘─┐ 
   
┐  
┘─┐ 

자세한 버전

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
에 쓸모없는 공백이 if x*y<0 or있습니다. 0.5로 줄일 수 있습니다 .5. import *될 수 있습니다 import*. ''.join(k) for쓸모없는 공백이 있습니다. 또한 dict변수 를 유지 하고 사용할 때마다 호출 할 수 있어야 합니다. 이것이 얼마나 절약되는지 테스트하지는 않았지만 dict(zip(a,b))두 줄 (a, b)에 대한 작업을 수행하는 람다 에 저장하여 일부를 잘라야합니다. +1.
Yytsi

7

C (GCC / 리눅스) 402 353 352 302 300 298 296 288 바이트

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

방향을 단일 4 비트 숫자로 저장하는 데 edc65가 제공됩니다.

화면 보호기를 영원히 반복하기 전에 stdin에서 너비 / 높이를 읽습니다. 예 :

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

또는 전체 화면 스크린 세이버의 경우 :

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

가독성을 위해 줄 바꿈을 추가했습니다. ANSI 코드를 준수하는 터미널이있는 Linux 시스템이 필요합니다. 색상이 있습니다! 색상 지원을 제거하면 비용이 17 바이트 감소합니다.

예


5

루비, 413 403 396 바이트

루비 파이프

입력으로 많은 틱과 너비를 사용하고 최종 화면을 문자열로 반환하는 함수입니다. 의심 할 여지없이 더 골프를 칠 수있었습니다.

->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에서 참조하십시오 : https://repl.it/Db5h/4

실제로 작동하는지 확인하려면 시작하는 줄 뒤에 다음을 삽입하십시오 b[n*w+n+m]=.

puts b; sleep 0.2

... 예를 들어 변수에 람다를 할당하고 (100 틱 및 20x20 화면) pipes=->...처럼 호출하십시오 pipes[100,20].

언 골프 및 설명

# 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]
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.