文字列から正方形を彫る


21

今日の課題は、複数行の文字列を取得し、左上隅を含む文字列に含まれる最大の正方形を出力することです。

四角い文字列は次のようなものです:

  • 各行の文字数は同じです
  • 各行の文字数は、行数と同じです。

次の可能な入力文字列を考慮してください。

abcde
fgh
asdf
foobar

最初の文字(a左上隅)を含む、そこから取得できる最大の正方形は次のとおりです。

abc
fgh
asd

2行目の長さが足りないため、辺の長さ4の正方形はありません。次に、この潜在的な入力を検討します。

a
bcd
edf
ghi

ここで最大の広場はちょうどaです。下部に形成された3x3の正方形には最初の文字が含まれておらず、カウントされません。

以下に、さらにいくつかのテストケースを示します。

a

a

abc
def
gh

ab
de

ab
cd

ab
cd

abcde
fghij
klm
no

abc
fgh
klm

a
b

a

LF、CR、またはCRLFの選択により、入力を区切る必要がある場合があります。

改行文字は、行の長さの一部とは見なされません。

入力に末尾の改行があるかどうかを要求する場合がありますが、これは追加行としてカウントされません。

入力は文字列または1D文字配列です。文字列のリストではありません。

入力は空ではなく、すべての行は空ではなく、スペースと改行(行区切り記号)を含む印刷可能なASCIIのみを含み、タブは含まないと想定できます。

これは、最少バイトが勝ちます!



5
興味深いチャレンジの場合は+1、厳密なI / Oの場合は-1
デニス

@Dennisは、すべてのソリューションを使用する必要.split('\n')があるわけではないため、一部のソリューションを無料で入手する必要がある理由はわかりません。
パベル

2
退屈なボイラープレートのためにバイトを追加する必要はありません。前処理または後処理がある場合、一部のアプローチ(再帰関数など)は完全に非実用的になります。
デニス

@Dennisそんなことは考えていませんでした。今すぐ変更する必要があると思いますか、それとも遅すぎますか?
パベル

回答:


5

Brachylog、11バイト

ṇ⊇ᵐẹa₀ṁcᵐ~ṇ

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

説明

ṇ             Split on linebreaks
 ⊇ᵐ           Take a subset of each line
   ẹ          Split the lines into list of chars
    a₀        Take a prefix of this list of lists of chars
      ṁ       It is a square matrix
       cᵐ     Concatenate the list of chars back into strings
         ~ṇ   Join the strings with linebreaks

最短の解決策(これまでのところ)で良い仕事をしました。Brachylogは確かに正方形が好きですね。
パベル

@Pavel 組み込みは確かに非常に便利です!
致命的

7

、13バイト

►oΛ≈S+TzṀ↑Nḣ¶

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

説明

►oΛ≈S+TzṀ↑Nḣ¶  Implicit input, say "ab\nc".
            ¶  Split at newlines: ["ab","c"]
           ḣ   Take prefixes: [["ab"],["ab","c"]]
       z  N    Zip with [1,2,3..
        Ṁ↑     by taking that many characters from each row: [["a"],["ab","c"]]
►o             Find rightmost element that satisfies this:
  Λ            all strings in
    S+T        the list concatenated to its transpose
   ≈           have the same length: ["a"]
               Implicitly print separated by newlines.

1
これはプログラミング言語でもありますか?あいまいなUnicode文字を貼り付けたところです!;)
カブ

1
@Petarゴルフ言語の世界へようこそ。ゴルフ言語は、特定のタスクを実行するためにできるだけ少ないバイト数を使用するように特別に設計されています。これの一部は、通常の95の印刷可能なASCIIの代わりに、可能なバイトごとに文字が存在するように、カスタムコードページを持つことです。しかし、心配しないでください、もっと読みやすいゴルフ言語もあります。たとえば、私のMATLエントリ[/恥知らずな自己宣伝]
-Sanchises

5

GNU sed106 + 1 94 + 2 = 96バイト

-rzフラグ用に+2バイト。ここに示すように、印刷できない文字NULおよびBELを使用@#ます。xxdダンプについては、以下を参照してください。

への道を送ってくれた@seshoumaraに感謝し-zます。

s/^/@/gm
s/.*/#&\n/
:B
s/@(.)/\1@/mg
s/#(.+\n)/\1#/m
/#.*@./M!b
/@\n.*#/!bB
:
s/@[^\n]*|#.*//g

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

説明

これは、2つのカーソルをテキストに挿入することで機能します。1つは行をステップオーバーし、もう1つは列をステップオーバーします。カーソルはそれぞれNUL(0x00)とBEL(0x07)で表されますが、以下の例ではとを使用@#ます。次の入力があるとします:

abcde
fgh
asdf
foobar

BELカーソルは0番目の列の前に挿入され、BELカーソルは0番目の行の前に挿入されます(ここでは読みやすくするために列を揃えていますが、実際には左のパディングはありません)。

#@abcde
 @fgh
 @asdf
 @foobar

ループでは、カーソルはそれぞれ1文字右および1行下に移動します。

 a@bcde
#f@gh
 a@sdf
 f@oobar
 ab@cde
 fg@h
#as@df
 fo@obar
 abc@de
 fgh@
 asd@f
#foo@bar

各反復後、2つの条件をチェックします。

  1. 行カーソルがある行に列カーソルがあり、列カーソルを右に移動できますか?
  2. 行カーソルの前の行で、すべての列カーソルを右に移動できますか?

いずれかの条件が偽の場合、ループは終了します。スクリプトは@、各行の後のすべてと#パターンスペース内の後のすべてを削除して終了します。

xxdダンプ

00000000: 732f 5e2f 002f 676d 0a73 2f2e 2a2f 0726  s/^/./gm.s/.*/.&
00000010: 5c6e 2f0a 3a42 0a73 2f00 282e 292f 5c31  \n/.:B.s/.(.)/\1
00000020: 002f 6d67 0a73 2f07 282e 2b5c 6e29 2f5c  ./mg.s/.(.+\n)/\
00000030: 3107 2f6d 0a2f 072e 2a00 2e2f 4d21 620a  1./m./..*../M!b.
00000040: 2f00 5c6e 2e2a 072f 2162 420a 3a0a 732f  /.\n.*./!bB.:.s/
00000050: 005b 5e5c 6e5d 2a7c 072e 2a2f 2f67       .[^\n]*|..*//g

最初のループAを削除できます。ステートメントでは、入力を文字列として読み取る必要があるため、「line1 \ nline2 \ nline3」などを受け取ることができます。他の回答もこれを行いました。カウントは100未満になります:)
seshoumara

@seshoumara他の答えはline1\nline2\nline3どこに\nあり\x5C\x6Eますか?どっち?
ヨルダン

リンクをお願いします。(回答の下部にある[共有]をクリックします。)またはTiOで何を意味しているのか教えてください。PythonおよびPHPのすべての回答では\n、改行文字(\x0A、ではなく\x5C\x6E)として解釈され、sedに改行文字を1行として入力させる方法が見つかりません。
ヨルダン

@seshoumaraああ、気にしないで、-zフラグを思い出しただけです。ありがとう!
ヨルダン

4

Python 2、81バイト

l=input().split('\n')
i=0
while zip(*l[:i+1])[i:]:i+=1
for x in l[:i]:print x[:i]

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


興味深い方法ですが、2バイト長くなります。

Python 2、83バイト

l=input().split('\n')
while len(zip(*l))<len(l):l.pop()
for x in l:print x[:len(l)]

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


1
input1行しか読み取らないのですか?
パベル

@Pavel、オンラインの例を見ると、明示的な改行文字を使用して入力を1行の文字列に維持していることがわかります。raw_input()バイトを追加するため、おそらくこの方法を選択します。
ザビエルダス

4

JavaScript(ES6)、77バイト

f=(s,i=1,m=s.match(`^${`(.{${i}}).*
`.repeat(i)}`))=>m?f(s,i+1)||m.slice(1):0

正規表現を再帰的に使用して、何も見つからなくなるまで、より大きな正方形を探します。

3x3正方形の場合、正規表現は次のようになります。

^(.{3}).*
(.{3}).*
(.{3}).*

入力は改行で終わることが期待され、出力はリストです。

説明:

f = (s,                                            //input
     i = 1,                                        //start searching for a 1x1 square
     m = s.match(`^${`(.{${i}}).*\n`.repeat(i)}`)  //match on the regex
    )=>
    m ? f(s, i+1)                   //if there's a match, recurse on the next-sized square
        || m.slice(1) :             //if there's not a next-sized square, return the match
        0                           //no match for this square, so stop recursing

スニペット:




3

R84 83 81 76バイト

デニスのアプローチを移植する-5バイトsum

cat(substr(x<-readLines(),1,m<-sum(cummin(nchar(x))>=seq(x)))[1:m],sep='\n')

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

stdinから読み取り、末尾の改行なしでstdoutに出力します。

わずかに未使用:

x <- readLines()                    # read in input one line at a time;
                                    # saved as a vector of strings
minChar <- cummin(nchar(x))         # rolling minimum of all line lengths
lineNum <- seq(x)                   # line number
mins <- minChar>=lineNum            # the min between the line number and the line lengths
m <- sum(mins)                      # the sum of those is the size of the square
cat(substr(x,1,m)[1:m],sep='\n')    # print the first m characters of the first m lines,
                                    # and join with newlines


3

C(gcc)162 159 151 147 144 142 137バイト

ここでゴルフをするにはいくつかのストロークが必要です...

i,l=9;char*p,s[9][8];main(t){for(p=s;~(*p=getchar());)p=*p<32?*p=0,l=(t=strlen(s+i))<l?t:l,s[++i]:p+1;for(i=0;i<l;puts(s+i++))s[i][l]=0;}

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


ことが可能!=-1であること>-1やないgetchar()マイナス1より出力値が小さいですか?それもあり+1ますか?
ジョナサンフレッチ


@JonathanFrech ~マイナス1を検出するために使用できます。
cleblanc

1
@RickHitchcockは最新のゴルフバージョンで動作するようです。
cleblanc

2

ゼリー、15バイト

L€«\‘>Jx@Z
ỴÇÇY

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

使い方

ỴÇÇY        Main link. Argument: s (string)

Ỵ           Split s at linefeeds, yielding a string array.
 Ç          Apply the helper link.
  Ç         Apply the helper link again.
   Y        Join, separating by linefeeds.


L€«\‘>Jx@Z  Helper link. Argument: A (string array/2D character array)

L€          Compute the length of each row/line.
  «\        Take the cumulative minimum.
    ‘       Increment each minimum.
      J     Indices; yield [1, ..., len(A)].
     >      Perform elementwise comparison. If the output should have n lines, this
            yields an array of n ones and len(A)-n zeroes.
         Z  Zip/transpose A.
       x@   For each string t in the result to the right, repeat its characters as
            many times as indicated in the result to the left, discarding all but
            the first n characters.

2

Java 8、150バイト

s->{String q[]=s.split("\n"),r="";int l=q[0].length(),i=0,t;for(;i<l;l=t<l?t:l)t=q[i++].length();for(i=0;i<l;)r+=q[i++].substring(0,l)+"\n";return r;}

説明:

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

s->{                          // Method with String as both parameter and return-type 
  String q[]=s.split("\n"),   //  Split the input on new-lines, and put it in an array
         r="";                //  Result-String, starting empty
  int l=q[0].length(),        //  Length of the lines, starting at the length of line 1
      i=0,                    //  Index-integer, starting at 0
      t;                      //  Temp integer
  for(;i<l;                   //  Loop (1) from 0 to `l` (exclusive)
      l=t<l?                  //    After every iteration: if `t` is smaller than `l`:
         t                    //     Change `l` to `t`
        :                     //    Else:
         l)                   //     Leave `l` the same
    t=q[i++].length();        //   Set `t` to the length of the current line
                              //  End of loop (1) (implicit / single-line body)
  for(i=0;i<l;                //  Loop (2) from 0 to `l` (the determined square dimension)
    r+=                       //   Append the result-String with:
       q[i++].substring(0,l)  //    The current row chopped at `l-1`
       +"\n"                  //    + a new-line
  );                          //  End of loop (2)
  return r;                   //  Return the result-String
}                             // End of method

2

MATL、33バイト

10-~ft1)wdhqY<tn:vX<X>:GYbowt3$)c

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

私のスパイシーな感覚は、おそらくもっと短い方法があることを教えてくれます(Ybo最初から何かを考えています)...最後に改行が必要です。(注:これは少し余分に設計しました。これは空行も処理するためです。これは必須ではありません。


1
@Pavel Guiseppeは別のバージョンについて言及していましたが、実際にはバグがあったため、ロールバックしました。
Sanchises



1

JavaScript(ES6)、95バイト

f=
s=>(g=s=>s.slice(0,a.findIndex((e,i)=>a.some((s,j)=>j<=i&!s[i]))))(a=s.split`
`).map(g).join`
`
<textarea oninput=o.textContent=f(this.value+`\n`)></textarea><pre id=o>

入力には末尾の改行が必要です。



1

APL(Dyalog)、25バイト*

暗黙のプレフィックス機能。マトリックスを返します。

(↑↑⍨2⍴(⌊/≢,≢¨))⎕AV[3]∘≠⊆⊢

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

これは、2つの独立した関数の⎕AV[3]∘≠⊆⊢最上部です。つまり、厄介な入力形式↑↑⍨2⍴(⌊/≢,≢¨)を処理し、実際の興味深い作業を行います。

⎕AV[3]∘≠ LF(AトミックVの 3番目の要素)と違い –文字セット)

 パーティション(前の値よりも大きい値で始まり、0でドロップするサブストリング)

 引数

() 次の暗黙関数を適用します。

2⍴() 次の長さを2に変更します。

  ⌊/ 最小の

   文字列の数

  , に続く

  ≢¨ 各文字列の文字数

↑⍨ その数の行と列を

 マトリックスを形成するために一緒に混合された文字列(スペースで埋める)


*付きでクラシック⎕MLM igrationのLの EVEL) 3(多くのシステムではデフォルト)と置き換えるため左端のためにティオ!


Dyalog Classicで同じ長さの場合は、Dyalog Classicであると言い、脚注を使用しないでください。
パベル

@Pavelクラシックと⎕ML←3非推奨の両方であるため、通常表示される言語を表示します。実際、ほとんどの私のDyalog APLソリューションは、文字ではなくバイトをカウントするという理由だけでClassicを想定していますが、Unicodeバージョンでも256文字未満に意味を割り当てています。
アダム

1

PHP、123バイト

for(;preg_match("#^(\S{".++$i."}.*
){"."$i}#",$s="$argv[1]
"););while($k<$i-1)echo substr(split("
",$s)[+$k++],0,$i-1),"
";

PHP 5.4、5.5、または5.6が必要です。交換splitexplode、後でPHPのため。

で実行するphp -nr '<code> '<string>'
、オンラインで試してください。(適切なPHPバージョンを選択してください!)



1

Perl 5、60 +5(-0777p)バイト

$.++while/^(.{$.}.*
){$.}/;$_=join"
",(/.{$.}/gm)[0..--$.-1]

オンラインで試す

  • 入力の最後の行は、出力に属する場合に備えて改行で終わる必要があります。
  • 2つの連続する改行の場合、-00は-0777でオプションを変更できます。

2つの連続した改行が可能であるため、が必要-0777です。とにかく何をし-00、何をし-0777ます。
パベル

-0進形式でレコードセパレータを指定することで777、ファイル全体が読み込まれるように、何の区切りがないことを示すために特別な値であり、0「段落モード」を示すために、別の特別な値があり、セパレータは、1つの以上の連続した改行である
ナウエルFouilleul

1

Perl 6の158の 140バイト

my$c;for ^(my@b=lines).elems {any(@b.head(++$c).map({.substr(0,$c).chars <$c}))&&$c--&&last;};say @b.head($c).map({.substr(0,$c)}).join("
")

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

はじめてのPerl 6の回答に感謝します。これをもう少しゴルフできるかどうかを確認するために、いくつかのコマンドラインオプションを試します。バイトを節約するすべての助けを歓迎します!


1

Scala、201バイト

type S=String
def c(s:S):S={val? =s split "\n"
var(z,q:Seq[S])=(Seq(?size,?(0).size).min,Nil)
while(1<2){?map(i=>{if(i.size>=z)q=q:+i.take(z)
if(q.size==z)return q mkString "\n"})
q=Nil;z-=1}
return""}

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

この言語で初めてゴルフをするので、おそらく最高ではありません。

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