Classic VCS ASCII Adventure


21

Quando eu era criança, meu primeiro sistema de console era o Atari 2600 e sempre terei amor por alguns desses jogos que eu tanto gostava quando criança. Muitos dos gráficos ainda são memoráveis, talvez até icônicos.

Acontece que esses sprites são bitmaps muito simplistas, com 8 pixels de largura e altura variável, onde a representação binária é a disposição dos pixels.

Por exemplo, os bytes hexadecimais 0x18, 0x24, 0x18 desenham um círculo bruto da seguinte forma:

0x18: 00011000
0x24: 00100100
0x18: 00011000

Como a largura de 8 pixels cria gráficos bastante pequenos (mesmo para os padrões Atari 2600), era comum dobrar ou quadruplicar a altura, largura ou ambas, para criar uma versão maior (embora mais quadrada e distorcida) da mesma imagem. Eles também seriam virados verticalmente ou horizontalmente para sprites de jogadores e campos de jogos. O jogo Combat é um bom exemplo disso.

O desafio é escrever código para exibir esses sprites como "gráficos" na forma ASCII, incluindo a capacidade de esticá-los ou invertê-los verticalmente, horizontalmente ou ambos. Isso deve estar na forma de um programa completo ou de uma função que pode ser chamada.

Entrada:

  • Uma matriz de bytes, cada um representando os bits horizontais para essa linha.
  • Um valor inteiro diferente de zero para cada direção, horizontal e vertical, representando o fator de escala para essa dimensão.
  • Um valor negativo indica que a dimensão também deve ser invertida ao longo de seu eixo.

Saída:

  • Representação ASCII para STDOUT ou uma sequência separada por nova linha, usando um caractere de espaço para pixels pretos (0) e qualquer caractere imprimível e não espacial de sua escolha para pixels brancos (1).

Dados de teste:

bmp1 = [ 0x06, 0x0F, 0xF3, 0xFE, 0x0E, 0x04, 0x04, 0x1E, 0x3F, 0x7F, 0xE3, 0xC3, 0xC3, 0xC7, 0xFF, 0x3C, 0x08, 0x8F, 0xE1, 0x3F ]
bmp2 = [ 0x07, 0xFD, 0xA7 ]
bmp3 = [ 0x00, 0x8E, 0x84, 0xFF, 0xFF, 0x04, 0x0E, 0x00 ]
bmp4 = [ 0x00, 0xFC, 0xFC, 0x38, 0x3F, 0x38, 0xFC, 0xFC]

Nota: As matrizes de entrada de bytes do exemplo acima são fornecidas como hexadecimais. Se sua plataforma não aceitar literais hexadecimais para representação de bytes, você poderá convertê-los em um literal nativo equivalente a bytes.

Saída de exemplo:

f( bmp1, 1, 1 ) =>
--------
     XX 
    XXXX
XXXX  XX
XXXXXXX 
    XXX 
     X  
     X  
   XXXX 
  XXXXXX
 XXXXXXX
XXX   XX
XX    XX
XX    XX
XX   XXX
XXXXXXXX
  XXXX  
    X   
X   XXXX
XXX    X
  XXXXXX
--------

f( bmp1, -2, 1 ) =>
----------------
  XXXX          
XXXXXXXX        
XXXX    XXXXXXXX
  XXXXXXXXXXXXXX
  XXXXXX        
    XX          
    XX          
  XXXXXXXX      
XXXXXXXXXXXX    
XXXXXXXXXXXXXX  
XXXX      XXXXXX
XXXX        XXXX
XXXX        XXXX
XXXXXX      XXXX
XXXXXXXXXXXXXXXX
    XXXXXXXX    
      XX        
XXXXXXXX      XX
XX        XXXXXX
XXXXXXXXXXXX    
----------------

f( bmp2, 1, 2 ) =>
--------
     XXX
     XXX
XXXXXX X
XXXXXX X
X X  XXX
X X  XXX
--------

f( bmp2, 2, 1 ) =>
----------------
          XXXXXX
XXXXXXXXXXXX  XX
XX  XX    XXXXXX
----------------

f( bmp2, -2, -2 ) =>
----------------
XXXXXX    XX  XX
XXXXXX    XX  XX
XX  XXXXXXXXXXXX
XX  XXXXXXXXXXXX
XXXXXX          
XXXXXX          
----------------

f( bmp3, 1, -1 ) =>
--------

    XXX 
     X  
XXXXXXXX
XXXXXXXX
X    X  
X   XXX 

--------

f( bmp3, 3, 3 ) =>
------------------------



XXX         XXXXXXXXX   
XXX         XXXXXXXXX   
XXX         XXXXXXXXX   
XXX            XXX      
XXX            XXX      
XXX            XXX      
XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX
               XXX      
               XXX      
               XXX      
            XXXXXXXXX   
            XXXXXXXXX   
            XXXXXXXXX   



------------------------

f( bmp4, -1, -1 ) =>
--------
  XXXXXX
  XXXXXX
   XXX  
XXXXXX  
   XXX  
  XXXXXX
  XXXXXX

--------

f( bmp4, 4, 2 ) =>
--------------------------------


XXXXXXXXXXXXXXXXXXXXXXXX        
XXXXXXXXXXXXXXXXXXXXXXXX        
XXXXXXXXXXXXXXXXXXXXXXXX        
XXXXXXXXXXXXXXXXXXXXXXXX        
        XXXXXXXXXXXX            
        XXXXXXXXXXXX            
        XXXXXXXXXXXXXXXXXXXXXXXX
        XXXXXXXXXXXXXXXXXXXXXXXX
        XXXXXXXXXXXX            
        XXXXXXXXXXXX            
XXXXXXXXXXXXXXXXXXXXXXXX        
XXXXXXXXXXXXXXXXXXXXXXXX        
XXXXXXXXXXXXXXXXXXXXXXXX        
XXXXXXXXXXXXXXXXXXXXXXXX        
--------------------------------

Nota: as linhas horizontais acima e abaixo devem mostrar o início e o fim da saída. Eles não são necessários na saída, no entanto, são necessárias linhas vazias (representadas por todos os zeros / espaços) no início e / ou no final, conforme mostrado.

Nota 2: esses bitmaps de teste foram inspirados e redesenhados / codificados com base em capturas de tela de jogos marcadas como "uso justo" na Wikipedia.

Critérios Vencedores

  • Isso é , então o código mais curto em bytes por idioma vence.
  • As brechas padrão são proibidas.

6
"Alguém afaste esse pato de mim!" - Strong Bad
AdmBorkBork 29/01

7
A ironia é que mesmo o golfe mais inteligente aqui provavelmente não será tão inteligente quanto o que os programadores do Atari 2600 realmente tinham que fazer se quisessem algo mais interessante que um clone Pong - a tela inteira era renderizada uma linha de cada vez. A CPU passava a maior parte do tempo fazendo isso. Com apenas 128 bytes de RAM, não havia espaço para um luxo como um buffer de tela ... Os cinco sprites inteiros que você adquiriu eram o luxo.
Jeroen Mostert 29/01

Podemos considerar a entrada como uma lista de cadeias binárias de 8 bits ou formatos semelhantes, onde os bytes já estão descompactados em bits?
Luis Mendo

@LuisMendo " Se sua plataforma não aceitar literais hexadecimais para representação de bytes, você poderá convertê-los em um literal nativo equivalente a bytes. "
Kevin Cruijssen -

@KevinCruijssen Esse é o ponto, não sei o que é aceito como equivalente . Isso abre a porta para a entrada direta do bitmap?
Luis Mendo

Respostas:



5

05AB1E , 27 26 bytes

εS²Ä×J³Äи²0‹ií]³0‹iR}˜0ð:»

Pega a entrada como uma lista de cadeias binárias de 8 bits e produz 1como caractere não espacial.

-1 byte graças a @MagicOctopusUrn .

Experimente online ou verifique todos os casos de teste .

Explicação:

ε         # Map the (implicit) input-list to:
 S        #  Convert the binary-String to a list of characters
  ²Ä      #  Take the absolute value of the second input
    ×     #  And repeat each character that many times
     J    #  And then join it back together to a single string again
 ³Ä       #  Take the absolute value of the third input
   и      #  Repeat that string as a list that many times
 ²0i     #  If the second input is negative:
     í    #   Reverse each string in the list
]         # Close both the if-statement and (outer) map
³0i }    # If the third input is negative:
    R     #  Reverse the list of lists
      ˜   # Flatten the list of lists to a list of strings
0ð:       # Replace all 0s with spaces " "
   »      # And join the strings by newlines (which is output implicitly)

Tem que haver um byter 2 para 0‹i...
Magic Octopus Urn

@MagicOctopusUrn Deveria haver um byte de 0‹verdade ... Temos um byte de 1 >=0, o que é d. Mas também devemos ter um byter para verificar a imo negativa. Agora eu apenas uso 0‹ou d_.
Kevin Cruijssen 29/01

Tudo o que pude apresentar foi: „íR³²‚0‹Ï.V(código completo εε²Ä×}J³Äи0ð:}„íR³²‚0‹Ï.V˜»), o que não é uma melhoria, mas se livra de uma dessas verificações negativas.
Magic Octopus Urn

1
Além disso, com certeza εS²Ä×J³Äи²0‹ií]³0‹iR}˜0ð:»salva um byte. Se você pode obter uma matriz 2D, é possível remover Stotalmente por 25 bytes.
Magic Octopus Urn

@MagicOctopusUrn Ah, claro, em S²Ä×vez de ε²Ä×}. Obrigado! Hmm, se pudermos considerar as entradas binárias como uma lista de 0s e 1s, um byte adicional poderá ser salvo, omitindo o S. Perguntará ao OP se isso é permitido. Eu gosto do seu „íR³²‚0‹Ï.Vno seu outro comentário também. :)
Kevin Cruijssen 29/01

3

MATL , 24 19 bytes

B,!i|1&Y"2M0<?XP]Zc

As entradas são uma matriz de números decimais, escala horizontal e vertical.

Experimente online!

Explicação

B        % Implicit input: array of numbers. Convert to binary. Gives a zero-one
         % matrix, each row containing the binary expansion of a number
,        % Do twice
  !      %   Transpose
  i      %   Input: number
  |      %   Absolute value
  1&Y"   %   Repeat each row that many times
  2M     %   Push the latest input again
  0<     %   Is it negative?
  ?      %   If so:
    XP   %     Flip vertically
  ]      %   End
  Zc     %   Convert each nonzero into '#'. Zeros are displayed as space
         % Implicit end. Implicit display

3

Dyalog APL, 46 42 33 bytes

' #'[⍉⊃{⊖⍣(0>⍺)⍉⍵/⍨|⍺}/⎕,⊂⎕⊤⍨8/2]

Experimente online!

-9 graças a ngn!


each -> reduzir: {' #'[⊃{⌽⍣(0>⍺)⊢(|⍺)/⍉⍵}/⍺,⊂⍉⍵⊤⍨8/2]}dfn -> programa:' #'[⊃{⌽⍣(0>⍺)⊢(|⍺)/⍉⍵}/⎕,⊂⍉⎕⊤⍨8/2]
ngn

mais curto: ' #'[⍉⊃{⊖⍣(0>⍺)⍉⍵/⍨|⍺}/⎕,⊂⎕⊤⍨8/2]. btw, a saída para o segundo teste parece invertida em sua solução original
ngn 7/04

@ngn obrigado! as entradas para o segundo exemplo deveriam ter sido revertidas para corresponder ao segundo caso de teste na pergunta.
dzaima 7/04

3

Prolog (SWI) , 252 bytes

N+E+R:-N<1,R=[];N-1+E+S,R=[E|S].
N*E*R:-R=E,E=[];N<0,reverse(E,F),-N*F*R;[H|T]=E,N+H+S,N*T*U,append(S,U,R).
N/E/R:-N<1,R=[];(E<N,D=E,F=32;D=E-N,F=35),N/2/D/C,R=[F|C].
[H|T]^X^Y^R:-128/H/A,X*A*B,Y*[[10|B]]*C,append(C,D),(T=[],R=D;T^X^Y^S,append(D,S,R)).

Experimente online!

Explicação

N+E+R:-N<1,R=[];N-1+E+S,R=[E|S].   Make `R` a list containing `E` repeated `N` times
       N<1,R=[]                    If `N<1`, let `R` be the empty list
       N-1+E+S                     Else recurse with `N-1`, `E` and `S`
           R=[E|S]                 Let `R` be a new list with `E` as head and `S` as tail
N*E*R:-R=E,E=[];N<0,reverse(E,F),-N*F*R;[H|T]=E,N+H+S,N*T*U,append(S,U,R).
                                   Let `R` be a list
                                   with each element in `E` repeated `N` times
                                   e.g. 2*[3, 6] -> [3, 3, 6, 6]
       R=E,E=[]                    Let `R` be `E` if `E` is the empty list
       N<0,reverse(E,F)            Else if `N<0`, let `F` be the reverse of `E`
           -N*F*R                  Recurse with `-N`, `F` and `R`
       [H|T]=E                     Else let `H` be the head and `T` be the tail of `E`
           N+H+S                   Let `S` be `N+H+S` (our function, not addition)
           N*T*U                   Recurse with `N`, `T` and `U`
           append(S,U,R)           let `R` be the concatenation of `S` and `U`
N/E/R:-N<1,R=[];(E<N,D=E,F=32;D=E-N,F=35),N/2/D/C,R=[F|C].
                                   Make `R` the binary representation of `E`
                                   with `N` as the value of the current bit
                                   where 0 and 1 are space and hash respectively
    N<1,R=[]                       If `N<1` let `R` be the empty list
    (
        E<N,D=E,F=32               If `E<N` the bit isn't set, so `D=E`, `F=space`
        D=E-N,F=35                 Else `D=E-N`, `F=hash`
    )
        N/2/D/C                    Recurse with `N/2`, `D` and `C`
        R=[F|C]                    Let `R` be a new list with `F` as head and `C` as tail
[H|T]^X^Y^R:-128/H/A,X*A*B,Y*[[10|B]]*C,append(C,D),(T=[],R=D;T^X^Y^S,append(D,S,R)).
                                   Make `R` the result,
                                   with inputs being the list `[H|T]`
                                   and the scales `X` and `Y`
   128/H/A                         Let `A` be the binary representation of `H` (8 bits)
   X*A*B                           Let `B` be `A` with each element repeated `X` times
   Y*[[10|B]]*C                    Let `C` be `B` with a newline prepended,
                                   repeated `Y` times
   append(C,D)                     Let `D` be `C` flattened by one level (joining lines)
   (
       T=[],R=D                    If `T` is empty, let `R` be `D` 
       T^X^Y^S                     Else recurse with `T`, `X`, `Y` and `S`
           append(D,S,R)           Let `R` be the concatenation of `D` and `S`
   )

2

Carvão , 28 bytes

FθE↔ζ⭆⮌↨ι²×§ Xμ↔ηF›η⁰‖F‹ζ⁰‖↓

Experimente online! Link é a versão detalhada do código. Explicação:

Fθ

Loop sobre a lista de bytes.

E↔ζ

Mapeie sobre o fator de escala vertical, multiplicando assim as linhas de saída.

⭆⮌↨ι²×§ Xμ↔η

Converta a entrada na base 2, inverta-a, mapeie os dígitos para o espaço e Xmultiplique cada caractere pelo fator de escala horizontal.

F›η⁰‖

Se o fator de escala horizontal for positivo, reflita para obter a imagem da maneira correta novamente.

F‹ζ⁰‖↓

Reflita verticalmente se o fator de escala vertical for negativo.


Não que ele salvasse bytes, mas estou curioso: por que você usou F( For) em vez de ¿( If) para as verificações?
Kevin Cruijssen 29/01

1
@KevinCruijssen No modo sucinto de carvão, elseestá implícito; portanto, a única vez que posso usar ifé se for a última declaração do bloco.
Neil

Ah, ok, não sabia disso. Portanto, usar dois Ifaqui seria realmente um em If ... Else If ...vez de dois soltos If. Hum, é bom saber.
Kevin Cruijssen 29/01


2

Lisp comum , 157 bytes

(lambda(l x y)(dolist(i(if(< y 0)(reverse l)l))(dotimes(j(abs y))(dotimes(n 8)(dotimes(k(abs x))(princ(if(logbitp(if(< x 0)n(- 7 n))i)"#"" "))))(princ"
"))))

Experimente online!

Explicação

(lambda(l x y)                           ; Lambda with parameters `l`, `x`, `y`
    (dolist
        (i                               ; For `i` in the list  
            (if(< y 0)(reverse l)l)      ; The reverse of `l` if `y<0` else `l`
        )
        (dotimes(j(abs y))(dotimes(n 8)(dotimes(k(abs x))
                                         ; Do `y` times, for `n` from 0 to 7, do `x` times
        (princ(if(logbitp(if(< x 0)n(- 7 n))i)"#"" "))))
                                         ; If `x<0` and the `n`th bit is 1
                                         ; or `x>0` and the `7-n`th bit is 1
                                         ; print "#", else print " "
        (princ"
")                                       ; After every `y` loop, print a newline
        )
    )
)

2

Tcl , 192 bytes

proc f {l x y} {lmap i [if $y<0 {lreverse $l} {lindex $l}] {time {lmap n {0 1 2 3 4 5 6 7} {time {puts -nonewline [expr $i&1<<($x<0?$n:7-$n)?{#}:{ }]} [expr abs($x)]};puts {}} [expr abs($y)]}}

Experimente online!

proc f {l x y}                           Define a function `f` with arguments `l`, `x`, `y`
{lmap i                                  For each `i` in
    [if $y<0 {lreverse $l} {lindex $l}]  The reverse of `l` if `y<0` else `l`
    {
        time {                           Do `abs(y)` times
            lmap n {0 1 2 3 4 5 6 7} {   For `n` from 0 to 7
                time {                   Do `abs(x)` times
                    puts -nonewline      Print without newline
                         [expr $i&1<<($x<0?$n:7-$n)?{#}:{ }]
                                         If `x<0` and the `n`th bit is 1 or
                                         `x>0` and the `7-n`th bit is 1
                                         then return "#" else return " "
                } [expr abs($x)]
            };
            puts {}                      Print a newline
        } [expr abs($y)]
    }
}

2

Código de máquina 8088, IBM PC DOS, 77 71 bytes

Montado:

B402 84FF 7906 FD03 F14E F6DF 518A CFAC 5051 B108 8AF3 84F6 7902 F6DE
518A CEB2 2384 DB79 04D0 C8EB 02D0 C072 02B2 2050 CD21 58E2 FA59 E2E4
B20D CD21 B20A CD21 5958 E2CC 59E2 C5

Listagem:

    PR_BMP  MACRO BMP, SZBMP, ZX, ZY
            LOCAL LOOP_Y, LOOP_Y2, LOOP_X, LOOP_X2, X_POS, X_NEG
B4 02   MOV  AH, 2          ; DOS display char function 
84 FF   TEST ZY, ZY         ; is Y scale negative?
79 06   JNS  LOOP_Y         ; if positive, start Y LOOP
FD      STD                 ; direction flag start from end
03 F1   ADD  BMP, CX        ; advance input byte array to end
4E      DEC  BMP            ; zero adjust index
F6 DF   NEG  ZY             ; make counter positive
     LOOP_Y:    
51      PUSH CX             ; save outer byte loop counter
8A CF   MOV  CL, ZY         ; set up repeat counter (Y scale factor)
AC      LODSB               ; load byte into AL
     LOOP_Y2:
50      PUSH AX             ; save original AL
51      PUSH CX             ; save outer loop
B1 08   MOV  CL, 8          ; loop 8 bits
8A F3   MOV  DH, ZX         ; DH is positive X scale used as counter
84 F6   TEST ZX, ZX         ; is X scale negative?
79 02   JNS  LOOP_X         ; if so, make counter positive
F6 DE   NEG  DH             ; compliment X counter 
    LOOP_X:
51      PUSH CX             ; save bit counter
8A CE   MOV  CL, DH         ; set repeat counter (X scale factor)
B2 23   MOV  DL, '#'        ; by default, display a #
84 DB   TEST ZX, ZX         ; is X scale negative?
79 04   JNS  X_POS          ; if so, rotate left 1 bit
D0 C8   ROR  AL, 1          ; else rotate right LSB into CF
EB 02   JMP  X_NEG          ; jump to examine CF
    X_POS:
D0 C0   ROL  AL, 1          ; rotate left MSB into CF
    X_NEG:
72 02   JC   LOOP_X2        ; is a 1?   
B2 20   MOV  DL, ' '        ; if not, display a space
    LOOP_X2:    
50      PUSH AX             ; save AL (since silly DOS overwrites it)
CD 21   INT  21H            ; display char
58      POP  AX             ; restore AL
E2 FA   LOOP LOOP_X2        ; loop repeat counter
59      POP  CX             ; restore bit counter
E2 E4   LOOP LOOP_X         ; loop bit counter
B2 0D   MOV  DL, 0DH        ; display CRLF
CD 21   INT  21H
B2 0A   MOV  DL, 0AH
CD 21   INT  21H
59      POP  CX             ; restore outer loop
58      POP  AX             ; restore original AL
E2 CC   LOOP LOOP_Y2        ; loop row display
59      POP  CX             ; restore byte counter
E2 C5   LOOP LOOP_Y         ; loop byte counter
    ENDM

Isso acabou sendo mais doozy no ASM do que eu pensava originalmente. Vários loops simultâneos e muitas ramificações if / else certamente podem causar dores de cabeça.

Isso é implementado como um MACRO, pois permite a passagem de parâmetro semelhante a uma função para teste.

Saída

Aqui está um programa de teste para o DOS que solicita o fator de escala X e Y e atrai para a tela. Observe que escalar demais o dragão passará para cima, pois a janela padrão do DOS é de apenas 24 linhas.

insira a descrição da imagem aqui

E aqui está o nosso pequeno dragão (pato):

insira a descrição da imagem aqui

Experimente Online!

Você pode testar em uma VM do DOS usando o DOSBox ou o VirtualConsoles.com com as seguintes etapas:

  1. Faça o download do VCS.ZIP (contém todos os quatro executáveis)
  2. Vá para https://virtualconsoles.com/online-emulators/DOS/
  3. Faça o upload do arquivo ZIP que você acabou de baixar, clique em Iniciar
  4. Digite PLANE, KEY, TANKou DRAGON.

1

Perl 5, 105 bytes

($_,$h,$v)=@F;say for map{$_=reverse if$h<0;y/0/ /;s/./$&x abs$h/eg;($_)x abs$v}$v<0?reverse/\d+/g:/\d+/g

TIO

Se a entrada deve ser hexadecimal

126 bytes



1

APL (Dyalog Extended) , SBCS de 23 bytes

método de dzaima

(v,h,B)vhB⎕IO←0

' x'⊇⍨∘⊃{⊖⍣(>⍺)⍉⍵/⍨|⍺}/

Experimente online!

{}/ Reduza da direita para a esquerda usando a seguinte lambda anônima:

|⍺ a magnitude do argumento esquerdo (o fator de escala)

⍵/⍨ use isso para replicar o argumento correto horizontalmente

 transpor

⊖⍣(... ) virar se:

  >⍺ o fator de escala é menor que zero

 divulgar (desde a redução incluída para reduzir a classificação do tensor de 1 a 0)

' x'⊇⍨ selecione elementos da string "x" usando essa matriz



1

T-SQL, 216 bytes

Antes de executar esse gerenciamento do MS-SQL Studio, pressione CRTL-t para mostrar os dados como texto. A altura não pode ser ajustada para exceder o número de elementos na entrada.

Devido à péssima implementação de STRING_AGG , a variável height só funcionará no MSSM. O MS deveria ter feito um terceiro parâmetro opcional para incluir a ordem dos elementos que estão sendo concatenados.

A versão online pode suportar apenas o ajuste da largura. A altura resultará em um resultado descolado, com várias formas de empilhamento.

USE master
DECLARE @ table(v int,i int identity)
INSERT @ values
(0x06),(0x0F),(0xF3),(0xFE),(0x0E),(0x04),
(0x04),(0x1E),(0x3F),(0x7F),(0xE3),(0xC3),
(0xC3),(0xC7),(0xFF),(0x3C),(0x08),(0x8F),
(0xE1),(0x3F)
-- @  = width
-- @h = height
DECLARE @s INT=1,@h INT=1

SELECT iif(@s>0,reverse(x),x)FROM(SELECT
string_agg(replicate(iif(v&n=0,' ','X'),abs(@s)),'')x,i,j
FROM(values(1),(2),(4),(8),(16),(32),(64),(128))x(n)
,@,(SELECT top(abs(@h))i j FROM @)g GROUP BY i,j)f
ORDER BY i*@h

Este script não mostrará as formas corretas na versão online, então fiz alguns pequenos ajustes para compensar. Experimente online

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.