Tracez une ligne droite

15

Dessinez une image d'art ASCII simple contenant une ligne droite. C'est similaire à ceci et cela mais avec des spécifications différentes.

Contribution

Vous pouvez modifier ce format d'entrée en fonction de votre code.

  • entier width
  • entier height
  • entier x0
  • entier y0
  • entier x1
  • entier y1

Production

Une image d'art ASCII remplie de la largeur et de la hauteur spécifiées contenant une ligne de pixel (x0, y0)en pixel (x1, y1).

Toute forme standard de sortie de texte est acceptable, mais n'utilisez pas de fonctions de dessin au trait intégrées.

Détails

La ligne doit être dessinée en utilisant un seul caractère imprimable (comme #), tandis que l'arrière-plan est rempli avec un caractère différent (comme .). Vous devez imprimer les caractères de fin nécessaires pour que la taille de l'image soit correcte.

Les coordonnées des pixels peuvent être indexées 0 ou 1 et peuvent commencer dans n'importe quel coin de l'image. La ligne doit être dessinée en imaginant une ligne de sous-pixels de largeur 0 reliant les centres des pixels de début et de fin. Chaque pixel que la ligne entre doit être rempli.

Gagnant

Règles de code-golf habituelles. Le code le plus court gagne.

Exemples

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:
#...
#...
#...
....
Curtis Bechtel
la source
4
Je dirais "Bienvenue à PPCG" mais vous êtes inscrit ici presque aussi longtemps que moi. :-) Beau premier défi!
AdmBorkBork
Pouvons-nous produire des points réels au lieu d'espaces? ou tout autre personnage mais des espaces? (en supposant toujours inclure les <caractères> de fin)
Rɪᴋᴇʀ
Sûr! Je ferai les modifications
Curtis Bechtel
1
@AlbertRenshaw En fait, quand je regarde Curve sur Wikipedia, il dit: " En mathématiques, une courbe (également appelée ligne courbe dans les textes plus anciens) est, en général, un objet similaire à une ligne mais qui n'a pas besoin d'être droite. "; )
Kevin Cruijssen
1
@KevinCruijssen Impliquer qu'une ligne doit être droite , non? ;)
Albert Renshaw

Réponses:

2

Mathematica, 166 137 octets

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}]

Version plus lisible:

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}]

Cela définit une fonction appelée f. J'ai interprété les spécifications d'entrée et de sortie assez généreusement. La fonction faccepte les entrées au format f[{x0, y0}, {x1, y1}, height, width]et la grille est indexée 1, en commençant en haut à gauche. Les sorties ressemblent

Un exemple de sortie

avec la ligne affichée en 1s et l'arrière-plan en 0s (montré ici pour f[{2, 6}, {4, 2}, 5, 7]). La tâche de transformer une matrice Mathematica de 1s et 0s en une chaîne de #s et .s a été jouée dans de nombreux autres défis auparavant, donc je pourrais simplement utiliser une méthode standard, mais je ne pense pas que cela ajoute quelque chose d'intéressant.

Explication:

L'idée générale est que si la ligne passe par un pixel, alors au moins l'un des quatre coins du pixel est au-dessus de la ligne et au moins un est en dessous. Nous vérifions si un coin est au-dessus ou au-dessous de la ligne en examinant l'angle entre les vecteurs ( {x0,y0}vers le coin) et ( {x0,y0}vers {x1,y1}): si cet angle est positif, le coin est au-dessus et si l'angle est négatif, le coin est en dessous.

Si nous avons deux vecteurs {a1,b1}et {a2,b2}, nous pouvons vérifier si l'angle entre eux est positif ou négatif en trouvant le signe du déterminant de la matrice {{a1,b1},{a2,b2}}. (Mon ancienne méthode pour ce faire utilisait l'arithmétique des nombres complexes, ce qui était trop… eh bien, complexe.)

La façon dont cela fonctionne dans le code est la suivante:

  • {p-l+#,p-q}&/@Tuples[.5{1,-1},2]obtient les quatre vecteurs de {x0,y0}et les quatre coins du pixel (avec l:={i,j}, les coordonnées du pixel, définies précédemment), ainsi que le vecteur entre {x0,y0}et {x1,y1}.
  • s@Det@...trouve les signes des angles entre la ligne et les quatre coins (en utilisant s=Sign). Ceux-ci seront égaux à -1, 0 ou 1.
  • Abs@Mean[...]<.6vérifie que certains angles sont positifs et certains négatifs. Les 4 tuples de signes qui ont cette propriété ont tous des moyennes comprises entre -0,5 et 0,5 (inclus), nous comparons donc à 0,6 pour enregistrer un octet en utilisant à la <place de <=.

Il y a toujours un problème: ce code suppose que la ligne s'étend indéfiniment dans les deux sens. Nous devons donc recadrer la ligne en multipliant par 1-Max[s[p-l]s[q-l],0](trouvé par essais et erreurs), qui se trouve 1à l'intérieur du rectangle défini par les extrémités de la ligne, et à l' 0extérieur.

Couper une ligne par un rectangle

Le reste du code fait une grille de ces pixels.

(En bonus, voici une tentative antérieure avec une méthode complètement différente, pour 181 octets :)

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}]&
Pas un arbre
la source
1
Maintenant que c'est fini, c'est l'heure du déjeuner! (À 18h30…)
Pas un arbre du
1

CJam, 122 octets

{),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*

Essayez-le en ligne

Cela combine essentiellement deux réponses que j'ai écrites précédemment pour d'autres défis (principalement les calculs de la 2ème fonction l).
(0, 0) est naturellement le coin supérieur gauche, pas en bas à gauche comme les exemples de l'instruction.

Aperçu:

{),V>{[I\]E.*A.+}/}:F;définit la fonction F qui permet de générer tous les pixels (paires de coordonnées) pour une coordonnée x donnée
l~]2/~@:S~'.*f*\@:A.-_:g:E;:z:Dlit et traite l'entrée, et crée une matrice de points
0=:B{D~I2*)*+:U(2/B/FU2/B/:V;}fIitère sur toutes les coordonnées x sauf la dernière, et génère tous les pixels correspondants
D~\:I;Ffait de même pour la dernière coordonnée x
{_Wf>\S.<+:*},ne conserve que les pixels qui devraient apparaître à l'intérieur de l'image
{~_3$=@0tt}/met un 0 dans la matrice pour chaque pixel
N*rejoint la matrice avec des caractères de nouvelle ligne pour l'affichage

aditsu
la source