Disegna una linea retta


15

Disegna una semplice immagine di arte ASCII contenente una linea retta. È simile a questo e questo, ma con specifiche diverse.

Ingresso

È possibile modificare questo formato di input in base al proprio codice.

  • numero intero width
  • numero intero height
  • numero intero x0
  • numero intero y0
  • numero intero x1
  • numero intero y1

Produzione

Un'immagine di arte ASCII riempita della larghezza e dell'altezza specificate contenente una linea da pixel (x0, y0)a pixel (x1, y1).

È accettabile qualsiasi forma standard di output del testo, ma non utilizzare funzioni di disegno linea incorporate.

Dettagli

La linea deve essere disegnata usando un singolo carattere stampabile (come #), mentre lo sfondo è riempito con un carattere diverso (come .). È necessario stampare i caratteri finali necessari in modo che le dimensioni dell'immagine siano corrette.

Le coordinate pixel possono essere 0-indicizzate o 1-indicizzate e possono iniziare in qualsiasi angolo dell'immagine. La linea dovrebbe essere disegnata immaginando una linea sub-pixel di larghezza 0 che collega i centri dei pixel iniziale e finale. Ogni pixel inserito dalla riga deve essere compilato.

vincente

Regole abituali di code-golf. Il codice più corto vince.

Esempi

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:
#...
#...
#...
....

4
Direi "Benvenuto in PPCG" ma sei stato registrato qui quasi quanto me. :-) Bella prima sfida!
AdmBorkBork,

Possiamo produrre punti reali anziché spazi? o qualsiasi altro personaggio tranne gli spazi? (supponendo che includa ancora i <character> s finali)
Rɪᴋᴇʀ

Sicuro! Farò le modifiche
Curtis Bechtel l'

1
@AlbertRenshaw In realtà, quando guardo Curve su Wikipedia , afferma: " In matematica, una curva (chiamata anche una linea curva nei testi più vecchi) è, in generale, un oggetto simile a una linea ma che non ha bisogno di essere dritta. "; )
Kevin Cruijssen il

1
@KevinCruijssen Implica che una linea deve essere dritta , no? ;)
Albert Renshaw,

Risposte:


2

Mathematica, 166 137 byte

l:={i,j};s=Sign;f[p_,q_,h_,w_]:=Grid@Table[(1-Max[s[p-l]s[q-l],0])Boole[Abs@Mean[s@Det@{p-l+#,p-q}&/@Tuples[.5{1,-1},2]]<.6],{i,h},{j,w}]

Versione più leggibile:

l := {i, j}; s = Sign; 
f[p_, q_, h_, w_] := 
 Grid@Table[(1 - Max[s[p - l] s[q - l], 0]) Boole[
     Abs@Mean[
        s@Det@{p - l + #, p - q} & /@ 
         Tuples[.5 {1, -1}, 2]] < .6], {i, h}, {j, w}]

Questo definisce una funzione chiamata f. Ho interpretato le specifiche di input e output in modo abbastanza libero. La funzione faccetta input nel formato f[{x0, y0}, {x1, y1}, height, width]e la griglia è 1-indicizzata, iniziando in alto a sinistra. Le uscite sembrano

Un output di esempio

con la linea visualizzata come se 1lo sfondo come 0s (mostrato qui per f[{2, 6}, {4, 2}, 5, 7]). Il compito di trasformare una matrice Mathematica di 1s 0in una serie di #s e .s è già stato affrontato in molte altre sfide, quindi ho potuto semplicemente usare un metodo standard, ma non credo che aggiunga qualcosa di interessante.

Spiegazione:

L'idea generale è che se la linea passa attraverso alcuni pixel, almeno uno dei quattro angoli del pixel è sopra la linea e almeno uno è sotto. Controlliamo se un angolo è sopra o sotto la linea esaminando l'angolo tra i vettori ( {x0,y0}all'angolo) e ( {x0,y0}a {x1,y1}): se questo angolo è positivo, l'angolo è sopra e se l'angolo è negativo, l'angolo è sotto.

Se abbiamo due vettori {a1,b1}e {a2,b2}, possiamo verificare se l'angolo tra loro è positivo o negativo trovando il segno del determinante della matrice {{a1,b1},{a2,b2}}. (Il mio vecchio metodo per fare questo usava l'aritmetica dei numeri complessi, che era troppo ... beh, complessa.)

Il modo in cui funziona nel codice è il seguente:

  • {p-l+#,p-q}&/@Tuples[.5{1,-1},2]ottiene i quattro vettori da {x0,y0}e i quattro angoli del pixel (con l:={i,j}, le coordinate del pixel, definite in precedenza) e anche il vettore tra {x0,y0}e {x1,y1}.
  • s@Det@...trova i segni degli angoli tra la linea e i quattro angoli (usando s=Sign). Questi equivalgono a -1, 0 o 1.
  • Abs@Mean[...]<.6controlla che alcuni degli angoli siano positivi e alcuni negativi. Le 4 tuple di segni che hanno questa proprietà hanno tutti un valore compreso tra -0,5 e 0,5 (incluso), quindi confrontiamo con 0,6 per salvare un byte usando <invece di <=.

C'è ancora un problema: questo codice presuppone che la linea si estenda per sempre in entrambe le direzioni. Dobbiamo quindi ritagliare la linea moltiplicando per 1-Max[s[p-l]s[q-l],0](trovato per tentativi ed errori), che si trova 1all'interno del rettangolo definito dai punti finali della linea e 0all'esterno di essa.

Ritaglio di una linea di un rettangolo

Il resto del codice crea una griglia di questi pixel.

(Come bonus, ecco un tentativo precedente con un metodo completamente diverso, per 181 byte :)

Quiet@Grid@Table[(1-Max[Sign[{i,j}-#3]Sign[{i,j}-#4],0])Boole[#3==#4=={i,j}||2Abs@Tr[Cross@@Thread@{{i,j},#3,#4}]/Norm[d=#3-#4]<2^.5Cos@Abs[Pi/4-Mod[ArcTan@@d,Pi/2]]],{i,#},{j,#2}]&

1
Ora che è finito, è ora di pranzo! (Alle 18:30 ...)
Non un albero il

1

CJam, 122 byte

{),V>{[I\]E.*A.+}/}:F;l~]2/~@:S~'.*f*\@:A.-_:g:E;:z:D[0=:B{D~I2*)*+:U(2/B/FU2/B/:V;}fID~\:I;F]{_Wf>\S.<+:*},{~_3$=@0tt}/N*

Provalo online

Questo fondamentalmente combina due risposte che ho scritto in precedenza per altre sfide (principalmente i calcoli della seconda funzione l).
(0, 0) è naturalmente l'angolo in alto a sinistra, non in basso a sinistra come negli esempi nell'istruzione.

Panoramica:

{),V>{[I\]E.*A.+}/}:F;definisce la funzione F che aiuta a generare tutti i pixel (coppie di coordinate) per una determinata coordinata x
l~]2/~@:S~'.*f*\@:A.-_:g:E;:z:Dlegge ed elabora l'input e crea una matrice di punti che
0=:B{D~I2*)*+:U(2/B/FU2/B/:V;}fIscorre su tutte le coordinate x tranne l'ultima, e genera tutti i pixel corrispondenti
D~\:I;Ffa lo stesso per l'ultima coordinata x
{_Wf>\S.<+:*},mantiene solo i pixel che dovrebbero apparire all'interno dell'immagine
{~_3$=@0tt}/inserisce uno 0 nella matrice per ogni pixel che
N*unisce la matrice con i caratteri di nuova riga per la visualizzazione

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.