直線を描く


15

直線を含む単純なASCIIアートイメージを描画します。これこれに似ていますが、仕様が異なります。

入力

コードに合わせてこの入力形式を変更できます。

  • 整数 width
  • 整数 height
  • 整数 x0
  • 整数 y0
  • 整数 x1
  • 整数 y1

出力

ピクセルからのラインを含む、指定された幅と高さの塗りつぶされたASCIIアートイメージ (x0, y0)への(x1, y1)

テキスト出力の標準形式はすべて受け入れられますが、組み込みの線描​​画関数は使用しないでください。

詳細

線は、単一の印刷可能な文字(など#)を使用して描画する必要がありますが、背景には別の文字(.)が使用されます。画像サイズが正しいように、必要な末尾の文字を印刷する必要があります。

ピクセル座標は0インデックスまたは1インデックスにすることができ、画像の任意のコーナーから開始できます。線は、開始ピクセルと終了ピクセルの中心を結ぶ幅0のサブピクセル線を想像して描画する必要があります。線が入るすべてのピクセルを塗りつぶす必要があります。

勝ち

通常のコードゴルフ規則。最短のコードが優先されます。

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
「PPCGへようこそ」と言いますが、あなたは私とほぼ同じ期間ここに登録されています。:-)素敵な最初の挑戦!
-AdmBorkBork

スペースの代わりに実際のドットを出力できますか?またはスペース以外の文字?(まだ末尾<文字> Sを含むと仮定)
Rɪᴋᴇʀ

承知しました!編集します
カーティスベクテル

1
@AlbertRenshaw実際、WikipediaCurveを見ると、「数学では、曲線( 古いテキストで曲線 とも呼ばれます)は、一般的には 直線に似ていますが、直線である必要はありません」と述べています。 )
ケビンクルーッセン

1
@KevinCruijssen ライン が直線である必要があることを暗示していますか?;)
アルバートレンショー

回答:


2

Mathematica、166 137バイト

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

より読みやすいバージョン:

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

これはと呼ばれる関数を定義しますf。入出力仕様をかなり自由に解釈しました。この関数fは、形式f[{x0, y0}, {x1, y1}, height, width]で入力を受け取り、グリッドは左上から1のインデックスが付けられます。出力は次のようになります

サンプル出力

線が1s として表示され、背景が0s として表示されます(ここではf[{2, 6}, {4, 2}, 5, 7])。1sと0sのMathematica行列を文字列に変換するタスク# Sと.私は標準的な方法を使用することができますので、前に他の多くの課題にgolfedされたS、私はそれが何も面白いが追加されますとは思いません。

説明:

一般的な考えは、線がピクセルを通過する場合、ピクセルの4つの角の少なくとも1つが線の上にあり、少なくとも1つが下にあるというものです。ベクトル({x0,y0}to corner)と({x0,y0}to {x1,y1})の間の角度を調べることにより、コーナーがラインの上または下にあるかどうかを確認します:この角度が正の場合、コーナーは上にあり、角度が負の場合、コーナーは下にあります。

2つのベクトル{a1,b1}{a2,b2}がある場合、行列の行列式の符号を見つけることで、それらの間の角度が正か負かを確認できます。{{a1,b1},{a2,b2}}ます。(これを行う私の古い方法は、複素数の算術を使用しましたが、これはあまりにも…複雑でした。)

コードでこれが機能する方法は次のとおりです。

  • {p-l+#,p-q}&/@Tuples[.5{1,-1},2]以下からの4つのベクトルを取得{x0,y0}し、画素の四隅(有するl:={i,j}、先に定義した画素の座標)、また間のベクトル{x0,y0}とを{x1,y1}
  • s@Det@...線と四隅の間の角度の符号を見つけます(を使用s=Sign)。これらは、-1、0、または1になります。
  • Abs@Mean[...]<.6一部の角度が正で、一部が負であることを確認します。このプロパティを持つ符号の4タプルはすべて-0.5〜0.5(両端を含む)の平均を持っているため、0.6の<代わりにを使用してバイトを節約します<=

まだ問題があります。このコードは、線が両方向に永久に伸びていると想定しています。そのため、線の端点で定義された長方形の内側と外側で乗算する1-Max[s[p-l]s[q-l],0](試行錯誤で見つけた)ことにより、線をトリミングする必要があります。10

長方形で線を切り抜く

残りのコードは、これらのピクセルのグリッドを作成します。

(おまけとして、これは181バイトのまったく異なる方法での以前の試みです。)

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
これで終了です。昼食の時間です!(午後6時30分…)
木ではない

1

CJam、122バイト

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

オンラインで試す

これは基本的に、以前に他の課題(主に2番目の計算-関数)について書いた2つの 答えを組み合わせたものlです。
(0、0)は当然、ステートメントの例のような左下ではなく、左上隅です。

概要:

{),V>{[I\]E.*A.+}/}:F;定義は、座標指定されたxについて全ての画素を(座標対)を生成するのに役立つ関数f
l~]2/~@:S~'.*f*\@:A.-_:g:E;:z:D読み出して入力を処理し、ドットのマトリクス作成
0=:B{D~I2*)*+:U(2/B/FU2/B/:V;}fI最後のものを除くすべてのX座標を反復し、そしてすべての対応する画素を生成する
D~\:I;Fために同じことを最後のx座標
{_Wf>\S.<+:*},は、画像内に表示されるピクセルのみを保持します。
{~_3$=@0tt}/各ピクセルのマトリックスに0を追加し
N*、表示用の改行文字とマトリックスを結合します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.