Fammi un gestore di finestre!


14

Odio il codice gonfio!

Quindi ho deciso di sostituire il mio sistema Windows 7 con una versione da golf. Tuttavia, so che non è facile, quindi costruiamo prima un prototipo. Prenderà un elenco di finestre dall'utente e le mostrerà usando un display pseudo-grafico sull'output standard.

Ad esempio: input dell'utente:

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

Le uscite di Code Golf® Window Manager ™:

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

Ingresso:

  • Tratto da input standard (o, se il tuo sistema non ha stdin, qualsiasi metodo che può fornire diverse righe di input)
  • Ogni riga contiene 4 numeri, delimitati da virgole - coordinate di una finestra
  • Primi due numeri: angolo in alto a sinistra; ultimi due numeri: angolo in basso a destra
  • Usando la x,ynotazione

Produzione:

  • Scrivilo nello standard output (o, se il tuo sistema non ha stdout, tutto ciò che mostra testo monospaziato)
  • Utilizzare i singoli caratteri di disegno a riquadro dalla pagina di codice 437 per disegnare i confini della finestra
  • Windows specificato in seguito nell'input oscura quelli specificati in precedenza
  • Riempi le finestre con il carattere due punti: :
  • Gli spazi iniziali e finali sono OK, purché non interrompano l'allineamento delle finestre

Appunti:

  • Risoluzione massima che voglio supportare: 76 (orizzontale) per 57 (verticale)
  • Non è necessario supportare input errati
  • Numero massimo di finestre: 255 (se è necessario un limite)
  • La mia cmdshell di Windows 7 visualizza la tabella codici 437 caratteri per impostazione predefinita; se qualcuno ha un modo per farlo su Linux (usando xtermo altro), descrivilo qui

Per riferimento, i codici dei caratteri sono:

┌da   ─c4   ┬c2   ┐bf

│b3   :3a   │b3   │b3

├c3   ─c4   ┼c5   ┤b4

└c0   ─c4   ┴c1   ┘d9

Totale: 12 personaggi diversi.


Nota che puoi visualizzare belle finestre su questa pagina se incolli il seguente codice nella barra degli indirizzi del browser:javascript:$('pre').css('line-height','1em')
Michael M.

Ho avuto la corretta visualizzazione in gnome-terminal seguendo le istruzioni a stackoverflow.com/questions/5509829/...
BRM

Risposte:


3

Python, 397 caratteri

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

Passa C="...a C=u"...e verrà invece stampato in Unicode! Potrebbe essere complicato salvare correttamente il file perché i caratteri della tabella codici 437 non sono sottoposti a escape (è richiesta la prima riga di commento "codifica").

L'approccio è quello di costruire una mappa in modo incrementale usando operatori bit-saggi. Versione meno giocata a golf con commenti:

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

6

JavaScript ES6 (FF ≥ 31,0), 404 caratteri

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'))}

Senza 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'); genera correttamente l'esempio dell'OP.

I bordi delle finestre vengono creati utilizzando operatori bit per bit (Su = 8, In basso = 4, Sinistra = 2, Destra = 1).


Non testato esaurientemente, ma sembra funzionare bene con stringhe letterali anziché array, in 548 caratteri. (Testato solo su Firefox.)
manatwork

Puoi salvare un sacco di personaggi usando ECMAScript 6: function w(s){...}diventa w=(s)=>{...}(e come saggio per tutti gli altri letterali delle funzioni). E la tabella di ricerca dei caratteri può probabilmente essere sostituita da una stringa con gli stessi caratteri.
Martin Ender,

Più tardi oggi, dopo il rilascio di Firefox 31.0, sarai in grado di utilizzare Array.fill()per inizializzare il "desktop".
arte

@manatwork, ho provato con FF Aurora [].fill([].fill(0,0,76),0,57), peccato che non funzioni. Posso scrivere più corto di new Array(57).fill(new Array(76).fill(0))?
Michael M.,

Prova a saltare i newgestori: Array(57).fill(Array(76).fill(0)).
arte

0

Python, 672 caratteri

La versione meno leggibile:

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

Iniziato dalla versione seguente:

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')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.