Zrób ze mnie menedżera okien!

14

Nienawidzę nadęty kod!

Postanowiłem więc zastąpić mój system Windows 7 wersją golfową. Wiem jednak, że nie jest to łatwe, więc najpierw zbudujmy prototyp. Spowoduje to pobranie listy okien od użytkownika i wyświetlenie ich za pomocą pseudo-graficznego wyświetlacza na standardowym wyjściu.

Na przykład: dane wejściowe użytkownika:

0,0,15,10
15,10,20,15
10,13,15,15
9,1,16,3
17,5,20,7
11,2,17,4
15,4,19,6
13,3,18,5

Wyjście Code Golf® Window Manager ™:

┌──────────────┐
│ :::::::: ┌─────┴┐
│ :::::::: │: ┌────┴┐
│ :::::::: └─┤: ┌───┴┐
│ :::::::::: └─┤ :::: ├┐
│ ::::::::::::: └─┬──┘├┐
│ :::::::::::::: ├─┬─┘│
│ ::::::::::::::: │ └──┘
│ :::::::::::::: │
│ :::::::::::::: │
└──────────────┼────┐
               │ :::: │
               │ :::: │
          ┌────┤ :::: │
          │ :::: │ :::: │
          └────┴────┘

Wejście:

  • Pobrane ze standardowego wejścia (lub, jeśli twój system nie ma stdin, jakiejkolwiek metody, która może zapewnić kilka linii wejściowych)
  • Każda linia zawiera 4 liczby, oddzielone przecinkami - współrzędne okna
  • Pierwsze dwie cyfry: lewy górny róg; dwie ostatnie cyfry: prawy dolny róg
  • Za pomocą x,ynotacji

Wynik:

  • Zapisz go na standardowym wyjściu (lub, jeśli twój system nie ma stdout, cokolwiek, co wyświetla tekst o stałej szerokości)
  • Do rysowania granic okien używaj pojedynczych znaków do rysowania ramek ze strony Kod 437
  • System Windows określony później w danych wejściowych zasłania te określone wcześniej
  • Wypełnij okna znakiem dwukropka: :
  • Wiodące i końcowe spacje są OK, o ile nie naruszają wyrównania okien

Uwagi:

  • Maksymalna rozdzielczość, którą chcę obsługiwać: 76 (poziomo) na 57 (pionowo)
  • Nie ma potrzeby obsługi złych danych wejściowych
  • Maksymalna liczba okien: 255 (jeśli potrzebujesz limitu)
  • Moja cmdpowłoka systemu Windows 7 domyślnie wyświetla 437 znaków strony kodowej; jeśli ktoś ma sposób to zrobić na Linuksie (używając xtermlub cokolwiek), opisz to tutaj

Dla porównania, kody znaków to:

┌da   ─c4   ┬c2   ┐bf

│b3   :3a   │b3   │b3

├c3   ─c4   ┼c5   ┤b4

└c0   ─c4   ┴c1   ┘d9

Łącznie: 12 różnych postaci.

anatolig
źródło
Zauważ, że możesz wyświetlić ładne okna na tej stronie, jeśli wkleisz następujący kod w pasku adresu przeglądarki:javascript:$('pre').css('line-height','1em')
Michael M.
Poprawny sposób wyświetlania uzyskałem w terminalu gnome, postępując zgodnie z instrukcjami na stackoverflow.com/questions/5509829/...
brm,

Odpowiedzi:

3

Python, 397 znaków

#coding:437
import os
J=range
M=[[0]*76 for _ in J(57)]
for A,C,B,D in[map(int,q.split(','))for q in os.read(0,9999).split('\n')]:
 for x in J(A+1,B):
    for y in J(C+1,D):M[C][A]|=5;M[C][B]|=6;M[D][A]|=9;M[D][B]|=10;M[C][x]|=3;M[D][x]|=3;M[y][A]|=12;M[y][B]|=12;M[y][x]=16;M[y][x-1]&=~1;M[y][x+1]&=~2;M[y-1][x]&=~4;M[y+1][x]&=~8
C=" rl─d┌┐┬u└┘┴│├┤┼:"
for l in M:print''.join((C+C[1:])[m]for m in l)

Zmień C="...na C=u"...i zamiast tego wydrukuje w Unicode! Prawidłowe zapisanie pliku może być trudne, ponieważ znaki strony 437 strony kodowej nie są poprzedzane znakami (wymagana jest pierwsza linia komentarza „kodującego”).

Podejście polega na stopniowym budowaniu mapy przy użyciu operatorów bitowych. Wersja mniej golfowa z komentarzami:

#coding:437
import os
J=range
# set up the field
# Each element is a bitfield. Flags are:
# 16 - inside a window?
# 8  - up
# 4  - down
# 2  - left
# 1  - right
M=[[0]*76 for _ in J(57)]
# for each window...
for A,C,B,D in[map(int,q.split(','))for q in os.read(0,9999).split('\n')]:
    # add the directions for the corners
    M[C][A]|=5;M[C][B]|=6;M[D][A]|=9;M[D][B]|=10
    # add the top and bottom edges
    for y in J(C+1,D):M[y][A]|=12;M[y][B]|=12
    # add the left and right edges
    for x in J(A+1,B):M[C][x]|=3;M[D][x]|=3 
    # deal with the middle
    for x in J(A+1,B):
       for y in J(C+1,D):
           # Clear the current spot by setting to inside a window
           M[y][x]=16
           # Remove the right direction from the left spot, top from the bottom, etc
           M[y][x-1]&=~1;M[y][x+1]&=~2;M[y-1][x]&=~4;M[y+1][x]&=~8
 # print it out
 C=u" rl─d┌┐┬u└┘┴│├┤┼:"
 for l in M:print''.join((C+C[1:])[m]for m in l)
Claudiu
źródło
6

JavaScript ES6 (FF ≥ 31,0), 404 znaków

w=s=>{a=[];for(i=0;i<57;)a[i++]=Array(76).fill(0);s.split('\n').map(e=>{r=e.split(',');a[x=r[1]][w=r[0]]|=5;a[x][y=r[2]]|=6;a[z=r[3]][w]|=9;a[z][y]|=10;for(i=x;++i<z;)a[i][w]|=12,a[i][w]&=14,a[i][y]|=12,a[i][y]&=13;for(i=w;++i<y;)a[x][i]|=3,a[x][i]&=11,a[z][i]|=3,a[z][i]&=7;for(i=x;++i<z;)for(j=w;++j<y;)a[i][j]=16});console.log(a.map(e=>e.map(t=>t==16?':':' xx─x┌┐┬x└┘┴│├┤┼'[t&15]).join('')).join('\n'))}

Bez ES6:

function w(s){a=[];for(i=0;i<57;i++){a[i]=[];for(j=0;j<76;j++)a[i][j]=0}s.split('\n').forEach(function(e){r=e.split(',');a[r[1]][r[0]]|=5;a[r[1]][r[2]]|=6;a[r[3]][r[0]]|=9;a[r[3]][r[2]]|=10;for(i=r[1];++i<r[3];)a[i][r[0]]|=12,a[i][r[0]]&=14,a[i][r[2]]|=12,a[i][r[2]]&=13;for(i=r[0];++i<r[2];)a[r[1]][i]|=3,a[r[1]][i]&=11,a[r[3]][i]|=3,a[r[3]][i]&=7;for(i=r[1];++i<r[3];)for(j=r[0];++j<r[2];)a[i][j]=16});console.log(a.map(function(e){return e.map(function(t){return t==16?':':' xx─x┌┐┬x└┘┴│├┤┼'[t&15]}).join('')}).join('\n'))}

w('0,0,15,10\n15,10,20,15\n10,13,15,15\n9,1,16,3\n17,5,20,7\n11,2,17,4\n15,4,19,6\n13,3,18,5'); wypisuje poprawnie przykład PO.

Krawędzie okien są budowane przy użyciu bitowych operatorów (góra = 8, dół = 4, lewo = 2, prawo = 1).

Michael M.
źródło
Nie przetestowano wyczerpująco, ale wydaje się, że działa dobrze z literałem łańcuchowym zamiast z tablicą, w 548 znakach. (Testowane tylko w przeglądarce Firefox.)
manatwork
Możesz zapisać wiele znaków, korzystając z ECMAScript 6: function w(s){...}staje się w=(s)=>{...}(i podobnie jak w przypadku wszystkich innych literałów funkcji). I tablicę odnośników można prawdopodobnie zastąpić ciągiem zawierającym te same znaki.
Martin Ender
Później dzisiaj, po wydaniu Firefoksa 31.0, będzie można korzystać Array.fill() do zainicjowania na „pulpicie”.
manatwork
@manatwork, próbowałem z FF Aurora [].fill([].fill(0,0,76),0,57), szkoda, że ​​to nie działa. Czy mogę pisać krócej new Array(57).fill(new Array(76).fill(0))?
Michael M.
Spróbować pominąć newoperatorów: Array(57).fill(Array(76).fill(0)).
manatwork
0

Python, 672 znaki

Mniej czytelna wersja:

import sys
r=range
M=[0,0,0,191,0,196,218,194,0,217,179,180,192,193,195,197]
Z=[map(int,l.split(",")) for l in sys.stdin.readlines()]
S=[[[0]*5 for x in r(77) ] for y in r(58)]
for i in r(len(Z)):
 A,C,B,D=Z[i]
 for a,b,c in [(C,A,2),(C,A,3),(D,A,1),(D,A,2),(C,B,3),(C,B,4),(D,B,1),(D,B,4)]:S[a][b][c]=1
 for x in r(A+1,B):
  for a,b in [(C,2),(C,3),(C,4),(D,1),(D,2),(D,4)]:S[a][x][b]=(b+1)&1
 for y in r(C+1,D):
  for a,b in [(A,1),(A,2),(A,3),(B,1),(B,3),(B,4)]:S[y][a][b]=b&1
 for x in r(A+1,B):
  for y in r(C+1,D):S[y][x]=[i+1]+[0]*4
O=sys.stdout.write
for l in S:
 for k in l:
  c=' ';x=M[k[1]*8|k[2]*4|k[3]*2|k[4]]
  if k[0]:c=':'
  if x:c=chr(x) 
  O(c)
 O('\n')

Rozpoczęty od wersji poniżej:

import sys

coords = [ tuple(map(int,l.strip().split(","))) for l in sys.stdin.readlines() ]

screen = [ [ [-1, [False,False,False,False]] for x in range(0, 77) ] for y in range(0, 58) ]

def mergeBorders(screen, w):
    x0,y0,x1,y1 = w
    screen[y0][x0][1][1] = True
    screen[y0][x0][1][2] = True
    screen[y1][x0][1][0] = True
    screen[y1][x0][1][1] = True
    screen[y0][x1][1][2] = True
    screen[y0][x1][1][3] = True
    screen[y1][x1][1][0] = True
    screen[y1][x1][1][3] = True

    for x in range(x0+1,x1):
        screen[y0][x][1][1] = True
        screen[y0][x][1][2] = False
        screen[y0][x][1][3] = True
        screen[y1][x][1][0] = False
        screen[y1][x][1][1] = True
        screen[y1][x][1][3] = True

    for y in range(y0+1,y1):
        screen[y][x0][1][0] = True
        screen[y][x0][1][1] = False
        screen[y][x0][1][2] = True
        screen[y][x1][1][0] = True
        screen[y][x1][1][2] = True
        screen[y][x1][1][3] = False

def paintInside(screen, w, wId):
    x0,y0,x1,y1 = w
    for x in range(x0+1,x1):
        for y in range(y0+1,y1):
            screen[y][x][0] = wId 
            screen[y][x][1] = [False, False, False, False]

for wId in range(len(coords)):
    w = coords[wId]
    mergeBorders(screen, w)
    paintInside(screen, w, wId)

borderMap = { (False, True, True, False): 0xda,
              (False, True, False, True): 0xc4,
              (False, True, True, True):  0xc2,
              (False, False, True, True): 0xbf,
              (True, False, True, False): 0xb3,
              (True, True, True, False):  0xc3,
              (True, True, True, True):   0xc5,
              (True, False, True, True):  0xb4,
              (True, True, False, False): 0xc0,
              (True, True, False, True):  0xc1,
              (True, False, False, True): 0xd9 }

def borderChar(c):
    return chr(borderMap[(c[0],c[1],c[2],c[3])])


for screenLine in screen:
    for contents in screenLine:
        c = ' '
        if True in contents[1]:
            c = borderChar(contents[1])
        elif contents[0] >= 0:
            c = ':'
        sys.stdout.write(c)
    sys.stdout.write('\n')
brm
źródło