Dibuje una imagen de arte ASCII simple que contenga una línea recta. Es similar a esto y a esto pero con especificaciones diferentes.
Entrada
Puede modificar este formato de entrada para adaptarlo a su código.
- entero
width
- entero
height
- entero
x0
- entero
y0
- entero
x1
- entero
y1
Salida
Una imagen artística ASCII rellena del ancho y alto especificados que contiene una línea de píxel (x0, y0)
a píxel (x1, y1)
.
Cualquier forma estándar de salida de texto es aceptable, pero no utilice funciones de dibujo de líneas integradas.
Detalles
La línea se debe dibujar con un solo carácter imprimible (como #
), mientras que el fondo se rellena con un carácter diferente (como .
). Debe imprimir los caracteres finales necesarios para que el tamaño de la imagen sea correcto.
Las coordenadas de píxel pueden estar indexadas a 0 o indexadas a 1 y pueden comenzar en cualquier esquina de la imagen. La línea debe dibujarse imaginando una línea de subpíxel de ancho 0 que conecta los centros de los píxeles inicial y final. Cada píxel que ingrese la línea debe completarse.
Victorioso
Reglas habituales de código de golf. El código más corto gana.
Ejemplos
IN: width, height, x0, y0, x1, y1
IN: 7, 6, 0, 0, 6, 5
OUT:
.....##
....##.
...##..
..##...
.##....
##.....
IN: 3, 3, 1, 1, 1, 1
OUT:
...
.#.
...
IN: 3, 3, 0, 2, 2, 0
OUT:
#..
.#.
..#
IN: 6, 3, 0, 0, 5, 2
OUT:
....##
.####.
##....
IN: 4, 4, -1, -1, 0, 3
OUT:
#...
#...
#...
....
Respuestas:
Mathematica,
166137bytesVersión más legible:
Esto define una función llamada
f
. Interpreté las especificaciones de entrada y salida de manera bastante liberal. La funciónf
toma la entrada en el formatof[{x0, y0}, {x1, y1}, height, width]
, y la cuadrícula está indexada en 1, comenzando en la esquina superior izquierda. Las salidas se ven comocon la línea mostrada como
1
sy el fondo como0
s (se muestra aquí paraf[{2, 6}, {4, 2}, 5, 7]
). La tarea de convertir una matriz de1
s y0
s de Mathematica en una cadena de#
s y.
s ya ha sido desarrollada en muchos otros desafíos, por lo que podría usar un método estándar, pero no creo que eso agregue nada interesante.Explicación:
La idea general es que si la línea pasa por algún píxel, entonces al menos una de las cuatro esquinas del píxel está por encima de la línea, y al menos una está por debajo. Verificamos si una esquina está arriba o debajo de la línea examinando el ángulo entre los vectores (
{x0,y0}
a la esquina) y ({x0,y0}
a{x1,y1}
): si este ángulo es positivo, la esquina está arriba, y si el ángulo es negativo, la esquina está abajo.Si tenemos dos vectores
{a1,b1}
y{a2,b2}
, podemos verificar si el ángulo entre ellos es positivo o negativo al encontrar el signo del determinante de la matriz{{a1,b1},{a2,b2}}
. (Mi antiguo método de hacer esto usaba la aritmética de números complejos, que era demasiado ... bueno, complejo).La forma en que esto funciona en el código es la siguiente:
{p-l+#,p-q}&/@Tuples[.5{1,-1},2]
obtiene los cuatro vectores de{x0,y0}
y las cuatro esquinas del píxel (conl:={i,j}
, las coordenadas del píxel, definidas anteriormente), y también el vector entre{x0,y0}
y{x1,y1}
.s@Det@...
encuentra los signos de los ángulos entre la línea y las cuatro esquinas (usandos=Sign
). Estos serán iguales a -1, 0 o 1.Abs@Mean[...]<.6
Comprueba que algunos de los ángulos son positivos y otros negativos. Las 4 tuplas de signos que tienen esta propiedad tienen medias entre -0.5 y 0.5 (inclusive), por lo que comparamos con 0.6 para guardar un byte usando<
lugar de<=
.Todavía hay un problema: este código supone que la línea se extiende para siempre en ambas direcciones. Por lo tanto, necesitamos recortar la línea multiplicando por
1-Max[s[p-l]s[q-l],0]
(encontrado por prueba y error), que está1
dentro del rectángulo definido por los puntos finales de la línea, y0
fuera de ella.El resto del código forma una cuadrícula de estos píxeles.
(Como beneficio adicional, aquí hay un intento anterior con un método completamente diferente, para 181 bytes :)
fuente
CJam, 122 bytes
Pruébalo en línea
Básicamente, esto combina dos respuestas que escribí anteriormente para otros desafíos (principalmente los cálculos de la segunda función
l
).(0, 0) es, naturalmente, la esquina superior izquierda, no inferior izquierda, como los ejemplos en la declaración.
Visión general:
{),V>{[I\]E.*A.+}/}:F;
define función F que ayuda a generar todos los pixeles (pares de coordenadas) para un determinado coordenada xl~]2/~@:S~'.*f*\@:A.-_:g:E;:z:D
lee y procesa la entrada, y se crea una matriz de puntos0=:B{D~I2*)*+:U(2/B/FU2/B/:V;}fI
itera sobre todas las coordenadas x, excepto la última, y genera todos los píxeles correspondientesD~\:I;F
hace lo mismo para la última coordenada x{_Wf>\S.<+:*},
mantiene solo los píxeles que deberían aparecer dentro de la imagen{~_3$=@0tt}/
pone un 0 en la matriz para cada píxel seN*
une a la matriz con caracteres de nueva línea para mostrarfuente