ASCIIアートチャレンジのクロップ


13

ASCIIアートは楽しいです。最新のテキストエディターは、テキストの操作に非常に優れています。現代のプログラミング言語は仕事に任せていますか?

ASCIIアート操作の一般的なタスクの1つは、2文字の間の長方形にテキストをトリミングすることです。これは、このチャレンジで実装する必要があるタスクです。

詳細

プログラムには3つの入力があります。

  • 最初はブロックの「開始」文字です-左上隅をマークします
  • 2番目はブロックの「終了」文字です-右下隅をマークします
  • 3番目は、文字列、文字列のリスト、ファイル名など、複数行のテキストの形式です。

結果は、指定された入力間の四角形にトリミングされた複数行テキスト(上記の形式のいずれか)になります。最初の2つの入力は一意でない場合があることに注意してください。

エッジケース

ボックスには常に少なくとも2つのボリュームが必要です。したがって、これらは次のとおりです。

()     (
       )

あるボックスが、これらは:

)(     )      (
       (     )

(start = (およびend =を使用))ではありません。

入力には1つのボックスのみが含まれます。したがって、開始文字と終了文字は、同じ文字である場合を除き、一度だけ発生する必要があります。ただし、同じ文字の場合、正確に2回出現する必要があります。

さらに、入力の各行は、少なくとも行の先頭から入力のボックスの右端までの距離と同じ長さでなければなりません。

プログラムは無効な入力を処理する必要はありません。その結果、未定義の動作が発生する場合があります。

ルール

典型的なコードゴルフ規則が適用されます。最短のコードが優先されます。

晴れた日: start: ( end: ) input:

This is some text
. (but this text
  is in a box  ).
So only it is important.

出力:

(but this text
is in a box  )

水平スペースの除去にも注意してください。ASCIIアート作物は2Dです。

雨の日: start: ( end: ) input:

This is some text (
But is that even  )
really a box?

出力:

(
)

同じ開始/終了: start: / end: / input:

Oh, I get how this could be useful
 /----------------------------\
 | All this text is in a box! |
 \----------------------------/

出力:

/----------------------------\
| All this text is in a box! |
\----------------------------/

無効入力: start: ( end: ) input:

Boxes are rectangular ( so this has
0 volume ) which is illegal.

無効な入力2: start: ( end: ) input:

(The lines must already be square 
so this line that is too short
relative to this end, is illegal)

ボックスより短い外線を持つ有効なボックスはどうですか?
seadoggie01

1
明確化され、無効な入力
LambdaBeta

入力が無効な場合の結果はどうなりますか?または、彼らは世話をする必要がないように言及されていますか?
ウリエル

1
結果はCの未定義の動作によく似ていますが、心配する必要はありません。
ラムダベータ

これは厄介な小さな挑戦です。素晴らしい仕事です!
seadoggie01

回答:


15

VIM、16、12バイト/キーストローク

#<C-v>Nj*yggVGp

オンラインでお試しください!Vインタープリターで

最新のテキストエディターは、テキストの操作に非常に優れています。現代のプログラミング言語は仕事に任せていますか?

私は賭け古いテキストエディタでも優れています!:D

必ずしもそうする必要はありませんが、この答えは、指定された「無効な」入力の両方で機能し、出力します

 rectangular (
) which is ill

そして

(The lines must already be square
so this line that is too short
relative to this end, is illegal)

説明:

#               " Move backward to the previous occurrence of the word (or in this case, character) under the cursor
 <C-v>          " Start a visual block selection
      N         " Go to the next occurrence of the last searched term (guaranteed to be line 1)
       j        " Move down a line
        *       " Move forward to the next occurrence of the character under the cursor
         y      " Yank (copy) the whole visually selected block
          gg    " Go to line 1
            VG  " Select every line
              p " And paste what we last copied over it, deleting the whole buffer and replacing it with the block

1
ちなみに、これはまさにこのチャレンジを書くように促すために私がしていたユースケースです。私は自分のqマクロを/\/<cr><c-v>nygv$o0dp非常に長い間持っていました:)
LambdaBeta

2
ええ、長方形が一番悪い
AdmBorkBork

6

ゼリー、13 バイト

=€SŒṪr/,þ/Zœị

左側に開始文字と終了文字のリストを受け入れ、右側に行のリスト(文字のリストとして)を受け入れ、行のリスト(文字のリストとして)を生成するダイアディックリンク。

オンラインでお試しください!(完全なプログラム-入力が有効なPythonである場合、Python文字列引用符が必要です。)

どうやって?

=€SŒṪr/,þ/Zœị - Link: [start, stop], lines
 €            - for each (of [start, stop]):
=             -   equals? (vectorises across the lines)
  S           - sum (vectorises)
   ŒṪ         - multi-dimensional truthy (i.e. non-zero) indices
      /       - reduce by:
     r        -   inclusive range (vectorises)
         /    - reduce by:
        þ     -    outer product with:
       ,      -       pair
          Z   - transpose
           œị - multi-dimensional index-into (the lines)

例として、左= ['a', 'b']および右(文字のリストのリスト-行)を使用します。

--------
--a+++--
--++++--
--+++b--
--------

=€リストの2つのリストのリストを生成します(最初はを実行し'a'=、2番目は実行します'b'=):

00000000         00000000
00100000         00000000
00000000    ,    00000000
00000000         00000100
00000000         00000000

これを合計すると、リストの単一のリストが生成されます(要素ごとに合計):

00000000
00100000
00000000
00000100
00000000

ŒṪ次に、非ゼロの(1インデックス付き)多次元インデックス、[[2,3],[4,6]]つまりを提供し[[top,left],[bottom,right]]ます。

r/次に[2,3]r[4,6]rベクトル化するため、のよう[2r4, 3r6]に評価します[[2,3,4],[3,4,5,6]]-つまり[rows,columns]ます。

,þ/次に、[2,3,4],þ[3,4,5,6]where þがouter-poduct命令で、,pairが実行されます。これにより[row,column]、列ごとにすべての値が得られます。この場合は次のとおりです。

[[[2,3],[3,3],[4,3]],
 [[2,4],[3,4],[4,4]],
 [[2,5],[3,5],[4,5]],
 [[2,6],[3,6],[4,6]]]

これらは行ごとに必要なので、これを次のようZに転置するために使用されます。

[[[2,3],[2,4],[2,5],[2,6]],
 [[3,3],[3,4],[3,5],[3,6]],
 [[4,3],[4,4],[4,5],[4,6]]]

最後œịに、入力行にインデックスを戻します。

a+++
++++
+++b

それの価値の両方の境界文字が同じである場合ことは注目に=€二回が、両方を識別SŒṪするので、正しいことをやって終了する2などして、truthyです['a','a']

--------         00000000   00000000        00000000
--a+++--         00100000   00100000        00200000
--++++--  =€ ->  00000000 , 00000000  S ->  00000000  ŒṪ ->  [[2,3],[4,6]]
--+++a--         00000100   00000100        00000020
--------         00000000   00000000        00000000

...説明を読みましたが、まだ理解できません。o_oおそらく実用的な例を追加してもらえますか?
DLosc

インセンティブ:完全に説明されていれば、あなたの答えを受け入れます。:)
LambdaBeta

1
@DLosc-完了しました。
ジョナサンアラン

@LambdaBeta-Vの回答は短くなります。
ジョナサンアラン

... Vimの回答も誤りです。
ジョナサンアラン

5

APL(Dyalog)38 30バイト

@EriktheOutgolferのおかげで4バイト節約

(1-⍨w-⍨⊃⍸⎕=s)↑(w←∊⊃⌽⍸⎕=s)↑s←↑⎕

オンラインでお試しください!


複雑すぎる。あなたは、行列の代わりに、ベクトルのベクトルを受け入れるとの2つの位置を見つけることができる⍸matrix∊separators、と彼らとテイク/ドロップを行う
NGN

(⍸a=⎕)↓(1+⍸a=⎕)↑a←⎕⎕io←0
ngn

@ngn OPは、行間で文字数が異なるため、入力は処理前にベクトルであると想定しました。それでも、区切り文字が数回表示される場合(最初のテストケースを参照)には、選択部分(最初と回転)が必要ですが、ドロップによって数バイトがカットされると思います。PCに
Uriel

おっと... 3番目のケースを忘れてしまった、ごめんなさい。それから多分:(より⊃{⌽⊖⍵↓⍨⊃⍸⍺=⍵}/⎕⎕⎕簡単な、3つの後続のクワッド)。または... ⎕⎕(↑⎕)、事前に混合されたマトリックスが許可されていない場合。
ngn

3

ゼリー、14バイト

œẹⱮẎQr/Ṛṭþ/œị⁸

オンラインでお試しください!


他のいくつかの例でコードを実行しようとしましたが、クラッシュしました。それはバグですか、それとも何か間違ったことをしていますか?
イルマリカロネン

@IlmariKaronen 2番目の引数を適切に引用していません(投稿で言及していません)。一重引用符または二重引用符で囲みます。呼び出し方法では、2番目の引数は空の(Python)タプル(())であり、ではありません'()'。解析可能であれば、引用符で囲む必要がありますが、my //は引用符で囲む必要はありません(オペランドのない整数除算演算子?hm ...)。
エリックアウトゴルファー

@IlmariKaronen私()はジェリーが何らかの特別なキャラクターとして解釈しているだけだと思います。私が仕事をしようとするキャラクターのほとんどのペア。ゼリーに精通している人々が考えていることを聞きたいです。編集:エリック・ザ・アウトゴルファーによる忍者編
LambdaBeta

ええ、そうです
イルマリカロネン


2

キャンバス、37 バイト

{³⁴⁰;x≡‽┐
X⁸)J╵⁶;┤ω┤⁵X⁶⁸⁰K├;┐┤└∔┘┘∔;@

ここで試してみてください!

文字の座標を取得するために36バイト(およびx、y、w、hに変換するため)、サブセクションを取得するために1バイト。より良いアプローチが必要です。


2

JavaScript(ES6)、98バイト

入力を2つの整数と文字列の配列として受け取ります。文字列の配列を返します。

(x,y,a,X=Y=0)=>a.filter(s=>!Y&&(Y=-~s.indexOf(y,X?X-1:X=-~s.indexOf(x)),X)).map(s=>s.slice(X-1,Y))

オンラインでお試しください!

コメント済み

( x,                          // x = start character
  y,                          // y = end character
  a,                          // a[] = array of strings
  X =                         // X = position of x, plus 1
  Y = 0                       // Y = position of y, plus 1
) =>                          //
  a.filter(s =>               // for each string s in a[]:
    !Y &&                     //   reject this string if Y is non-zero
    (                         //   otherwise, use the 2nd condition:
      Y = -~s.indexOf(        //     update Y:
        y,                    //       by looking for y in s
        X ?                   //       if X is non-zero:
          X - 1               //         start the search at X - 1
        :                     //       else:
          X = -~s.indexOf(x)  //         update X and start the search at X
      ),                      //     end of Y update
      X                       //     keep this string if X is non-zero
    )                         //   end of 2nd condition
  )                           // end of filter()
  .map(s =>                   // for each remaining string s:
    s.slice(X - 1, Y)         //   remove left and right characters outside the box
  )                           // end of map()

filter そして map?!新しいアレイを構築しreduceたり、再帰的なソリューションを短期間で解決することはできませんか?私の電話で、パブに行くか、自分で試してみます。
シャギー

@Shaggyは、おそらく実際に短い方法はありますが、私はと思い、この方法は、2回のパスを使用する運命にある:第2ループは、第一の前に1が終了し、両方を開始することはできませんXし、Y確実に知られています。
アーノールド

2

Java 10、204バイト

(s,e,a)->{int b=-1,i=0;for(;i<a.length;i++)a[i]=(b=b<0?a[i].indexOf(s):b)<0|a[i].length()<b?"":a[i].substring(b);for(b=-1;i-->0;)a[i]=(b=b<0?a[i].indexOf(e):b)<0|a[i].length()<b?"":a[i].substring(0,b+1);}

バイトを節約するために新しい配列を返す代わりに、入力配列を変更します。""ただし、削除された行は代わりになります。これが許可されていない場合は、変更します。

オンラインでお試しください。

説明:

(s,e,a)->{                 // Method with 2 Strings & String-array parameters and no return
  int b=-1,                //  Boundaries-integer, starting at -1
  i=0;for(;i<a.length;i++) //  Loop `i` in the range [0, amountOfLines)
    a[i]=                  //   Change the `i`th line in the array to:
      (b=b<0?              //    If `b` is -1:
          a[i].indexOf(s)  //     Set `b` to the index of `s` in the current line
                           //     (which is still -1 if it's not found)
         :                 //    Else (starting index already found)
          b                //     Leave `b` unchanged
      )<0                  //    Then, if `b` is -1,
         |a[i].length()<b? //    or the current line-length is too short:
       ""                  //     Remove the current line
      :                    //    Else:
       a[i].substring(b);  //     Shorten the line by removing every character before `b`
  for(b=-1;                //  Reset `b` to -1
      i-->0;)              //  Loop `i` in the range (amountOfLines, 0]
    a[i]=                  //  Change the `i`th line in the array to:
       (b=b<0?a[i].indexOf(e):b)<0|a[i].length()<b?"":
                           //   Similar as above (with end `e` instead of start `s`),
         a[i].substring(0,b+1);}
                           //   except we remove every character after `b` this time

例えば:

入力付き start = "("を使用してend = ")"lines =

["This is some text",
 ". (but this text",
 "  is in a box  ).",
 "So only it is important."]

最初のループは、上と左でそれをトリミングし、これに変更します:

["",
 "(but this text",
 "is in a box  ).",
 " only it is important."]

2番目のループは、右下でそれをトリミングし、これに変更します。

["",
 "(but this text",
 "is in a box  )",
 ""]

1

Retina 0.8.2、110バイト

^((.)¶.)(.*¶)+(.*\2)
$1¶$4
^(.)(¶.¶\1)
$2
}s`(?<=^.¶.+)¶.
¶
s`^¶(.)¶(.*\1).*
$2
+m`^((.)+).¶((?<-2>.)+)$
$1¶$3

オンラインでお試しください!説明:

^((.)¶.)(.*¶)+(.*\2)
$1¶$4

ボックスの最初の行の前にある入力行を削除します。

^(.)(¶.¶\1)
$2

開始文字が入力の左側の列にある場合は、削除します。

}s`(?<=^.¶.+)¶.
¶

開始文字がまだ削除されていない場合は、すべての入力列を1つ左にシフトし、最初から繰り返します。

s`^¶(.)¶(.*\1).*
$2

終了文字と、入力内の終了文字の後のすべてを削除します。

+m`^((.)+).¶((?<-2>.)+)$
$1¶$3

すべての行を次の行の長さに切り捨てます。これは、各行で1文字を除くすべてをカウントし、次の行でその数の文字まで一致させようとすることで機能します。これが成功すると、2行目が短くなったため、最後の文字が削除され、ループが繰り返されます。


0

C(gcc)、237バイト

f(c,r,o,p)char*p,*c;{char*_=strchr(p,r),*a,b;*_=0;a=strrchr(p,10);a=(a?a:p);*_=r;r=_-a;p=a;_=strrchr(p,o);*_=0;a=strrchr(p,10);a=(a?a:p);*_=o;o=_-a+1;_[1]=0;for(_=p;_;_=strchr(_+1,10)){b=_[o];_[o]=0;strcat(c,_+r);strcat(c,"\n");_[o]=b;}}

オンラインでお試しください!

これは2回繰り返されるため、文字の水平インデックスと文字へのポインターを見つけるための何らかのヘルパー関数を使用して、これを短縮できると確信しています。残念ながら、それを行うのに十分な短い方法を見つけることができませんでした。時間を見つけたら、後でもう一度試すかもしれません。

説明

f(c,r,o,p)char*p,*c;{
    char*_=strchr(p,r),*a,b;         // find opening char (and declare vars)
    *_=0;a=strrchr(p,10);            // find \n before it
    a=(a?a:p);                       // deal with single line inputs
    *_=r;r=_-a;                      // save left margin width in r
    p=a;                             // crop everything before opening line

    _=strchr(p,o);                   // find closing char
    *_=0;a=strrchr(p,10);            // find \n before it
    a=(a?a:p);                       // deal with single line inputs
    *_=o;o=_-a+1;                    // save width in o
    _[1]=0;                          // crop everything after closing char
    for(_=p;_;_=strchr(_+1,10)){       // for each line
        b=_[o];_[o]=0;
        strcat(c,_+r);
        strcat(c,"\n");
        _[o]=b;
    }
}

1
さらに良い:219バイト
ザカリー

0

スタックス、15 バイト

╛↨½╝v∞░W╧)╗Ö≈☼k

実行してデバッグする

入力の最初の行で一連のボックス区切り文字(1または2)を使用します。残りの行は入力本文です。

開梱されていない、コメントされていない、これはこのように見えます。

            first line of input is the delimiter characters
dL          discard the first line of input and listify the rest into an array
{           begin block for iteration
  Mr        rotate matrix 90 degrees
  {         begin block for while loop
    ch      copy first row of block
    y|&C    if it insersects with the first line of input, break iteration
    D       drop the first line
  W         do-while loop until break
}4*         execute block 4 times
m           display result lines

これを実行する

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