Gráficos en braille

46

Cortar una matriz booleana de 4x2 bloques y hacerlos como caracteres braille U+2800... U+28FF.

[[0,1,0,0,1,0],
 [1,0,0,0,0,0],
 [1,0,0,0,1,0],
 [1,1,1,1,0,0]]

⣎⣀⠅

Rellene con 0-s si las dimensiones no son múltiplos de 4 y 2.

[[0,1,0],
 [1,0,0],
 [1,1,1]]

⠮⠄

Se aplican las reglas habituales de golf, flexible en el formato de entrada. La salida debe tener la estructura de una matriz o verse como una matriz, por ejemplo, una lista de cadenas; cadena única con líneas nuevas.

Sugerencia: chr(0x2800 + 128*b7 + 64*b6 + 32*b5 + 16*b4 + 8*b3 + 4*b2 + 2*b1 + b0)es el patrón de puntos

b0 b3
b1 b4
b2 b5
b6 b7

Prueba más grande:

[[0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,1,0],
 [0,1,1,1,1,1,1,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1],
 [0,1,1,0,0,1,1,1,0,0,0,1,1,1,1,0,0,1,1,0,0,0,1],
 [1,1,0,0,0,0,1,1,0,0,0,0,0,0,1,0,0,1,1,0,0,1,1],
 [1,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,1,1,1,0,1,0],
 [1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0],
 [1,1,0,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0],
 [1,1,0,1,1,1,1,1,0,0,1,1,0,0,1,0,0,1,1,1,1,1,1],
 [1,1,0,1,1,1,1,0,0,1,1,1,1,0,1,0,1,1,1,1,1,1,0],
 [1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,0,0,0,1,1,0,0],
 [1,1,0,0,0,1,1,0,1,0,0,0,1,0,1,1,0,0,0,1,1,0,0],
 [1,1,0,0,0,1,1,0,1,0,0,0,1,0,1,1,1,0,0,1,1,0,0],
 [0,1,1,0,1,1,1,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0],
 [0,1,1,1,1,1,0,0,1,1,1,1,1,0,0,1,1,0,1,1,1,0,0],
 [0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,1,0,1,1,1,1,0]]

⣰⠟⠻⣦⠀⠠⠾⡇⢠⡞⢛⡆
⣿⢠⣬⣥⠄⣀⠀⡇⢈⣻⣈⡀
⣿⠘⢹⡇⡞⠙⡇⣧⡉⢹⡏⠀
⠘⠷⠟⠁⠳⠾⠃⠘⠇⠾⠧⠀
ngn
fuente
Felicidades por el segundo desafío.
Adám
55
Mejor descripción: tiene una matriz 2D de valores booleanos cuyas filas representan las líneas de trama horizontales de un búfer de marco en blanco y negro (1 bit por píxel) o un lienzo de gráficos. Codifique todos los bloques rectangulares de 4x2 de este lienzo en caracteres Unicode Braille. Para manejar bloques fraccionarios en los bordes, rellene el ancho del lienzo a un múltiplo de 2 y la altura a un múltiplo de cuatro, con ceros (o de lo contrario, asegure la salida equivalente, tratando los datos como si estuvieran rellenados).
Kaz
3
@Kaz No lo sé, personalmente aprecio lo concisa que es esta publicación. En mi opinión, no se agregaría mucha claridad escribiendo más (además de algunas pequeñas aclaraciones como señalar que la altura debe ser un múltiplo de 4 y el ancho de 2); Su sugerencia es más difícil de leer que la publicación actual.
Quelklef

Respuestas:

10

Jalea ,  31  30 bytes

sz0Z
ç€2ZF€ç€8Zœ?@€€-36Ḅ+⁽$ṁỌY

Pruébalo en línea!

¿Cómo?

sz0Z - Link 1, split & right-pad with zeros: list, items; number, chunkSize
s    - split items into chunks of length chunkSize
 z0  - transpose with filler zero
   Z - transpose

ç€2ZF€ç€8Zœ?@€€-36Ḅ+⁽$ṁỌY - Main link: list of lists of numbers (1s & 0s), M
ç€2                       - call the last link (1) as a dyad for €ach (left=M, right=2)
                          -  ((left,right) bits read left-right then top-bottom)
   Z                      - transpose the resulting list of lists of lists
                          -  ((left, right) bits read top-bottom then left-right)
    F€                    - flatten €ach
      ç€8                 - call the last link (1) as a dyad for €ach (left=^, right=8)
         Z                - transpose the resulting list of lists of lists
                          -  ("blocks" each and all read left-right top-to bottom)
               -36        - literal -36
             €€           - for €ach (block-wise row) for €ach (block)
          œ?@             -   lexicographical permutation with reversed arguments
                          -    (get the permutation at index -36 (modular) in a list of
                          -     all permutations of the indexes sorted lexicographically.
                          -     That is the 8!-36 = 40284th - equivalently the values at
                          -     indexes [8,7,6,4,2,5,3,1])
                  Ḅ       - convert from binary list to integer (vectorises)
                    ⁽$ṁ   - base 250 literal = 10240
                   +      - add
                       Ọ  - cast to character (vectorises)
                        Y - join with newlines
                          - implicit print
Jonathan Allan
fuente
¿ Admite "dígitos" mayores que 1? En lugar de agregar 10240 (0x2800 - dos bytes) al resultado, puede anteponer 40 (0x28 - un byte) al vector de dígitos binarios. No sé mucho sobre Jelly, así que no estoy seguro de si esto realmente funcionaría.
ngn
de hecho, convertiría un dígito inicial de 40 como sugiere, pero tendríamos que anteponerlo a cada una de esas listas (a una profundidad de 2) que, creo, requeriría más bytes de código ( ;@€€40Ḅ).
Jonathan Allan
6

JavaScript ES7 210 207 201 200 198 194 185 183 bytes

a=>eval('for(y=0,c="";A=a[y];y+=4,c+=`\n`)for(x=0;A[x]+1;x+=2)c+=String.fromCharCode(10240+eval("for(N=k=0;k<6;k++)N+=(g=(X,Y=3)=>(a[Y+y]||0)[X+x]|0)(k>2,k%3)*2**k")|g(0)+g(1)*2<<6)')

4 bytes guardados gracias a ngn

3 bytes guardados gracias a Luke

Cómo funciona

Voy a dividir el código en partes y hablar sobre ellas por separado:

for(y=x=0, c=""; a[y]; x+=2)
    !((a[y] || [])[x]+1) && (y+=4,x=0,c+=`\n`)

Aquí es donde se declara cada variable. xy yes la posición del "cursor" (el borde superior izquierdo del carácter braille actual). La coordenada x aumenta en 2 cada iteración y se detiene cuando no hay una fila con el índice y(a [x] devuelve undefinedsi no existe, que se convierte en falso).

Hay varios trucos en la segunda fila. (a[y] || [])[x]asegura que buscar el valor en la (x, y)posición no arroje un error. El &&es el habitual y el operador, y solo comprueba el lado derecho de la expresión, si el izquierdo era verdadero. Esto se puede traducir a

if (!((a[y] || [])[x] + 1)) 
    y+=4,x=0,c+=`\n`

La siguiente parte:

c+=String.fromCharCode(10240+eval("for(N=k=0;k<6;k++)N+=(g=(x,y)=>(a[y]||[])[x]||0)(~~(k/3)+x,k%3+y)*2**k,N")+g(x,y+3)*64+g(x+1,y+3)*128)

String.fromCharCodesimplemente convierte el número pasado a un carácter unicode con el mismo código de caracteres. La expresión entre paréntesis calcula el índice del carácter Braille:

for(N=k=0;k<6;k++)N+=(g=(x,y)=>(a[y]||[])[x]||0)(~~(k/3)+x,k%3+y)*2**k

Pasa por la posición en el

1 4
2 5
3 6

orden, multiplica los valores en esas posiciones con 2 i , donde i es el índice y los suma. los

g=(x,y)=>(a[y]||[])[x]||0

parte declara una función lambda llamada g, que dada una coordenada xy ydevuelve el valor en la (x, y)posición o 0 si la posición se encuentra fuera de los límites de la matriz.

+g(x,y+3)*64+g(x+1,y+3)*128

Esta parte suma las dos últimas posiciones con los pesos correctos utilizando la función definida un poco antes.

Por último, pero no menos importante, el

a=>eval('...')

La parte tiene 2 funciones. Define una lambda anónima y garantiza que el bucle for no cause ningún problema (una sola línea lambda como esta no puede contener solo un bucle for, una evaluación lo evita).

Bálint
fuente
Algunas sugerencias simples: ||0-> |0; ~~(k/3)-> (k>2); *128-> <<7(reemplazando +-s con |-s)
ngn
¿Por qué no enviar la versión ES7 como su solución principal?
Shaggy
@Shaggy No todos pueden ejecutar ES7 todavía, así que es una copia de seguridad
Bálint
Eso es irrelevante en estas partes;) Siempre que haya un único intérprete (navegador) que pueda ejecutar su código correctamente, se considera válido aquí.
Shaggy
@ngn Gracias por los dos primeros, pero el cambio de bits tiene una precedencia menor que básicamente cualquier cosa, por lo que no funcionará
Bálint
6

Mathematica, 126 110 97 90

FromCharacterCode[10240+ListCorrelate[2^{{0,3},{1,4},{2,5},{6,7}},#,1,0][[;;;;4,;;;;2]]]&

Esta solución aprovecha ListCorrelatepara convolucionar un núcleo (invertido) sobre una matriz , que es esencialmente una multiplicación de matriz deslizante (o producto de puntos). Vea una explicación visual aquí . El relleno se realiza utilizando 0como cuarto argumento. En el siguiente ejemplo, esperamos que el resultado coincida con la sugerencia anterior:

ListCorrelate[
  2^{{0, 3}, {1, 4}, {2, 5}, {6, 7}},
  {{b0, b3}, {b1, b4}, {b2, b5}, {b6, b7}}
]

(* returns {{b0 + 2 b1 + 4 b2 + 8 b3 + 16 b4 + 32 b5 + 64 b6 + 128 b7}} *)

Tenga en cuenta que ListConvolveno es más corto, ya que el tercer argumento sería -1.

Como esto aplica el núcleo en cada posición de la matriz, solo necesitamos extraer los elementos en cada cuarta fila y segunda columna. Utilizamos abreviaturas de Spany Part: [[;;;;4,;;;;2]].

Con ayuda, FromCharacterCodepuede tomar una matriz de códigos de caracteres y devolver una lista de cadenas.


Esta solución devuelve una lista de cadenas, que es uno de los formatos de salida permitidos. Simplemente anteponga Column@para que la salida "parezca una matriz".


Puede jugar con esto en un cuaderno gratuito de Mathematica en línea. Vaya aquí , haga clic en Crear un cuaderno nuevo, espere un momento, pegue este código y luego presione shift+enter.

m1={{0,1,0,0,1,0},{1,0,0,0,0,0},{1,0,0,0,1,0},{1,1,1,1,0,0}};
m2={{0,1,0},{1,0,0},{1,1,1}};
m3={{0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,1,0},{0,1,1,1,1,1,1,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1},{0,1,1,0,0,1,1,1,0,0,0,1,1,1,1,0,0,1,1,0,0,0,1},{1,1,0,0,0,0,1,1,0,0,0,0,0,0,1,0,0,1,1,0,0,1,1},{1,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,1,1,1,0,1,0},{1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0},{1,1,0,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0},{1,1,0,1,1,1,1,1,0,0,1,1,0,0,1,0,0,1,1,1,1,1,1},{1,1,0,1,1,1,1,0,0,1,1,1,1,0,1,0,1,1,1,1,1,1,0},{1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,0,0,0,1,1,0,0},{1,1,0,0,0,1,1,0,1,0,0,0,1,0,1,1,0,0,0,1,1,0,0},{1,1,0,0,0,1,1,0,1,0,0,0,1,0,1,1,1,0,0,1,1,0,0},{0,1,1,0,1,1,1,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0},{0,1,1,1,1,1,0,0,1,1,1,1,1,0,0,1,1,0,1,1,1,0,0},{0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,1,0,1,1,1,1,0}};

MatrixToBraille := Column@
  FromCharacterCode[10240+ListCorrelate[2^{{0,3},{1,4},{2,5},{6,7}},#,1,0][[;;;;4,;;;;2]]]&

MatrixToBraille/@{m1,m2,m3}

Entonces deberías ver esto:

hftf
fuente
5

Dyalog APL, 133 122 114 112 101 100 98 95 94 93 90 88 86 bytes

Asume ⎕IO←0

{C⍴{⎕UCS 10240+2⊥(∊S⌷⍨⍵+⍳¨A)[⍎¨⍕76531420]}¨(,b)/,⍳⍴b←{0 0≡A|⍵}¨⍳⍴S←⍵↑⍨A×C←⌈(⍴⍵)÷A←4 2}

- 8 9 12 bytes gracias a @ Adám en el chat

-2 bytes gracias a @ngn

Pruébalo en línea!

¿Cómo (entrada es )?

  • A←4 2, almacena el vector 4 2en variableA
  • (⍴⍵)÷, las dimensiones de dividido porA
  • , techo
  • C←, guardado en C
  • , multiplicado por A
  • ⍵↑⍨, se ajusta a esas dimensiones
  • S←, guardado en S
  • ⍳⍴, índices de S
  • {0 0≡A|⍵}¨, 1donde está la parte superior izquierda de una celda, en 0cualquier otro lugar
  • (,b)/,⍳⍴b←, índices de verdad
  • {⎕UCS 10240+2⊥(∊S⌷⍨⍵+⍳¨A)[⍎¨⍕76531420]}¨, convierte cada elemento en braille
  • C⍴, remodelar las dimensiones a C
Zacharý
fuente
considerar +/(2*0 3 1,A,4+⍳3)×something2⊥something[⍎¨⍕76524130]
ngn
¿Eso todavía funcionaría ahora que lo cambié ⎕IO←0?
Zacharý
En realidad, solo funcionaría en ⎕IO←0:)
ngn
Lo intenté, ¿estoy haciendo algo mal? tio.run/…
Zacharý
Lo siento, me olvidé de esta estupidez ( ⎕IO) en APL. Para ⎕IO←1, por supuesto, tendría que agregar 1 a cada dígito de 76524130.
ngn
4

JavaScript, 136 bytes

a=>(b=a.map(x=>[]),a.map((l,i)=>l.map((c,j)=>b[i>>2][j>>1]|=c<<'01263457'[i%4+j*4%8])),b.map(l=>l.map(c=>String.fromCharCode(10240+c))))

Gracias a ngn , el uso de cambios de bit ahorra 4 bytes.

tsh
fuente
puedes usar cambios de bit como i/4|0->i>>2
ngn
c*2**también es un poco turno :)
ngn
4

Python 2 + drawille , 141 125 120 116 bytes

Guardado 16 bytes gracias a ngn y L3viathan

Guardado 5 bytes gracias a L3viathan

Guardado 4 bytes gracias a ngn

from drawille import*
def a(d,c=Canvas(),e=enumerate):[c.set(j,i)for i,x in e(d)for j,y in e(x)if y];print c.frame()

Pruébalo en línea!

tio no tiene un drawille instalado, por lo que no funciona

Noskcaj
fuente
Python y sus baterías! :) No deja de sorprenderme. Puede reducir esto a menos de 120 bytes si usa enumerate()una lista de comprensión.
ngn
Ahorre un par de bytes haciendo que la función sea de una sola línea:def b(d,c=l.Canvas()):print([c.set(j,i)for i,x in enumerate(d)for j,y in enumerate(x)if y]and c).frame()
L3viathan
que no es necesario el and ctruco - la comprensión podría ser una declaración sobre su propio seguido de;print c.frame()
NGN
3

APL (Dyalog) , 57 54 bytes *

-3 gracias a OP. Solicita matriz booleana. Imprime la matriz de caracteres.

1↓⎕UCS{240,⌽(,⍉3↑⍵),⊢⌿⍵}⌺(2 24 2)⊢0⍪⍣3⍪∘03⊢⎕,0

Pruébalo en línea!

⎕,0 agregar un cero a la derecha (ignorado si hay un número par de columnas)

 ceder eso (para separar 3y )

⍪∘0⍣3 agregue ceros en la parte inferior tres veces (porque cae ventanas parciales)

0⍪⍣3 apila ceros en la parte superior tres veces (porque comienza en la esquina superior izquierda)

 producir eso (separa el paréntesis y el 0)

{}⌺(2 2⍴4 2) En cada ventana de 4 filas y 2 columnas, con paso vertical de 4 filas y horizontal de 2 filas:

⊢⌿⍵ última fila (encendido, reducción vertical derecha); [b6,b7]

(... ), anteponer:

  3↑ toma tres filas; [[b0,b3],[b1,b4],[b2,b5]]

   transponer; [[b0,b1,b2],[b3,b4,b5]]

  , enmarañar; [b0,b1,b2,b3,b4,b5]

 ahora tenemos [b0,b1,b2,b3,b4,b5,b6,b7]

 marcha atrás; [b7,b6,b5,b4,b3,b2,b1,b0]

40, anteponer 40 (para 40 × 2 9 = 10240);[40,b7,b6,b5,b4,b3,b2,b1,b0]

2⊥ evaluar como base-2 (binario)

⎕UCS convertir a personaje

1↓ soltar la primera fila (todo cero debido al relleno de ')


* En Clásico, contando como ⎕U233A.

Adán
fuente
Hay una manera fácil de guardar algunos bytes, vea mi comentario en la solución Jelly.
ngn
Debe haber un error: el enlace TIO no coincide con el código que publicó aquí.
ngn
es el código de relleno cero cerca del final: 0⍪⍣3⍪∘0⍣3⊢⎕,0vs0⍪∘0⍣3⊢⎕,0
ngn
@ngn fijo, pero tengo la sensación de que ⍪∘0⍣3y ,0sólo son necesarios debido a un error en , y el primero no es necesario para los casos de prueba.
Adám
Mis casos de prueba no son exhaustivos: la solución, por supuesto, debería funcionar para cualquier entrada válida. Puedes acortar 0⍪⍣3⍪∘0⍣3⊢⍵,0a 0(⊖⍪)⍣6⊢⍵,0.
ngn
2

Python 3 , 168 165 161 bytes

def f(m):
 while m:
  r,m,s=[*zip(*m)],m[4:],''
  while r:s+=chr(10240+sum(q<<int(w)for(q,w)in zip((r[0]+(0,)*3)[:4]+(r+[()])[1],'01263457')));r=r[2:]
  print(s)

Pruébalo en línea!

TFeld
fuente
Muy bien golfizado! Puede guardar tres bytes en [*zip(*m[:4])]lugar de llamar list.
Lynn
2

Haskell , 145 bytes

(a!b)c=take b$c++repeat a
r([]:_)=[]
r l=['⠀'..]!!(sum.zipWith(*)[1,8,2,16,4,32,64,128]$l>>=0!2):r(drop 2<$>l)
b[]=[]
b s=r(([]!4)s):b(drop 4s)

Pruébalo en línea!

Angs
fuente
1

Python 3 , 169 bytes

a=[]
y=0
for l in eval(input()):
 y-=1;a+=y%4//3*[-~len(l)//2*[10240]];x=0
 for v in l:a[-1][x//2]|=v<<(6429374>>y%4*6+x%2*3&7);x+=1
for l in a:print(*map(chr,l),sep='')

Pruébalo en línea!

Lynn
fuente
Puede reescribir if y%4<1:a+=-~len(l)//2*[10240],como a+=(y%4<1)*[-~len(l)//2*[10240]]y encajar x=0;y+=1en la misma línea. Creo que ahorra un byte.
ngn
@ngn guardó algunos bytes más de ahí en adelante, ¡gracias!
Lynn
1

Perl 5 , 164 bytes

163 bytes de código + 1 bandera -p

@a=eval}{for(;$r<@a;$r+=4){for($c=0;$c<@{$a[0]};$c+=2){$n="0b";map$n.=0|$a[$r+3][$c+$_],1,0;for$y(1,0){map$n.=0|$a[$r+$_][$c+$y],2,1,0}$\.=chr 0x2800+oct$n}$\.=$/}

Pruébalo en línea!

Toma cada fila con una coma separada en una línea.

Xcali
fuente