Вырежьте квадрат из струны


21

Ваша задача сегодня состоит в том, чтобы взять многострочную строку и вывести самый большой квадрат, содержащийся внутри строки, который включает в себя верхний левый угол.

Квадратная строка - это та, где:

  • Каждая строка имеет одинаковое количество символов
  • Количество символов в каждой строке равно количеству строк.

Рассмотрим следующую возможную строку ввода:

abcde
fgh
asdf
foobar

Самый большой квадрат, который вы можете взять из него, который включает в себя первый символ ( aв верхнем углу):

abc
fgh
asd

Не может быть квадрата с длиной стороны 4, потому что вторая строка не достаточно длинна. Теперь рассмотрим этот потенциальный вклад:

a
bcd
edf
ghi

Здесь самая большая площадь a. Квадрат 3х3, сформированный внизу, не содержит самого первого символа и не считается.

Вот еще несколько тестов:

a

a

abc
def
gh

ab
de

ab
cd

ab
cd

abcde
fghij
klm
no

abc
fgh
klm

a
b

a

Вы можете потребовать, чтобы ввод был ограничен вашим выбором LF, CR или CRLF.

Символы новой строки не считаются частью длины строки.

Вы можете потребовать, чтобы в вводе была или не была завершающая новая строка, которая не считается дополнительной строкой.

Ввод - это строка или одномерный массив символов; это не список строк.

Вы можете предположить, что входные данные не пустые, и все строки не пустые, и что он содержит только печатный ASCII, включая пробелы и символы новой строки (для разделителя строк), но не табуляции.

Это , побеждает меньше байтов!



5
+1 за интересный вызов, -1 за строгий ввод-вывод
Деннис

@ Деннис не каждое решение нужно использовать, .split('\n')поэтому я не понимаю, почему некоторые должны получить его бесплатно.
Павел

2
Речь идет не только о том, чтобы добавлять байты для скучного шаблона. Некоторые подходы (например, рекурсивные функции) становятся совершенно непрактичными, если есть предварительная или постобработка.
Денис

@ Денис, я не думал об этом так. Как вы думаете, я должен изменить это сейчас, или уже слишком поздно?
Павел

Ответы:


5

Брахилог , 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
Как это вообще язык программирования - вы только что вставили какие-то непонятные символы юникода! ;)
репа

1
@Petar Добро пожаловать в мир языков для игры в гольф, которые специально разработаны для использования как можно меньшего числа байтов для выполнения определенной задачи. Часть этого состоит в том, чтобы иметь собственную кодовую страницу, так что для каждого возможного байта есть символ, вместо обычного 95-печатаемого ASCII. Но не волнуйтесь, есть также намного более разборчивые языки игры в гольф; например моя запись в MATL [/ бесстыдная самореклама]
Sanchises

5

GNU sed , 106 + 1 94 + 2 = 96 байт

+2 байта для -rzфлагов. Используются непечатаемые символы NUL и BEL, показанные как @и #здесь. Смотрите ниже дамп xxd.

Спасибо @seshoumara за то, что отправили меня по пути к -z.

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

Попробуйте онлайн!

объяснение

Это работает путем вставки двух курсоров в текст - один для перехода по строкам и один для перехода по столбцам. Курсоры представлены NUL (0x00) и BEL (0x07) соответственно, но в следующих примерах я буду использовать @и #. Предположим, у нас есть этот вход:

abcde
fgh
asdf
foobar

Курсор BEL вставляется перед 0-м столбцом, а курсор BEL - перед 0-й строкой (здесь я держал столбцы выровненными для разборчивости; но на самом деле левого отступа нет):

#@abcde
 @fgh
 @asdf
 @foobar

В цикле курсоры перемещаются на один символ вправо и на одну строку соответственно:

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

После каждой итерации проверяются два условия:

  1. Есть ли на строке с курсором строки курсор столбца и может ли курсор столбца двигаться вправо?
  2. На строках перед курсором строки может ли каждый курсор столбца двигаться вправо?

Если какое-либо условие ложно, цикл заканчивается. Сценарий завершается удалением всего после @в каждой строке и всего после #в шаблонном пространстве.

xxd dump

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 принимать ввод с символами новой строки одной строкой.
Иордания

@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
Разве не inputчитает только одну строку?
Павел

@Pavel, если вы посмотрите на онлайн-пример, вы увидите, что он использует явные символы новой строки, чтобы сохранить ввод одной строкой. Вероятно, выбрав этот метод, потому 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

Рекурсивно использует регулярное выражение для поиска большего и большего квадрата, пока ничего не найдено.

Регулярное выражение будет таким для квадрата 3х3:

^(.{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

R , 84 83 81 76 байт

-5 байт переносят подход Денниса сsum

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

Попробуйте онлайн!

читает из стандартного ввода, печатает в стандартный вывод без завершающей строки.

Слегка разгульный

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?
Джонатан Фрех

Потенциал 158 байт .
Джонатан Фрех

@JonathanFrech Я могу использовать, ~чтобы обнаружить минус один.
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 (Дьялог) , 25 байтов *

Функция молчаливого префикса. Возвращает матрицу.

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

Попробуйте онлайн!

Это действительно две независимые функции, а именно, ⎕AV[3]∘≠⊆⊢которые имеют дело с неудобным форматом ввода и↑↑⍨2⍴(⌊/≢,≢¨) выполняют действительно интересную работу.

⎕AV[3]∘≠ отличие от LF (третий элемент A томика V Ector - набор символов)

 разделы (подстроки начинаются со значений, превышающих их предшественник и заканчиваются нулями)

 Аргумент

() Применить следующую молчаливую функцию:

2⍴() Изменить длину до длины 2:

  ⌊/ минимум

   количество строк

  , с последующим

  ≢¨ количество символов в каждой строке

↑⍨ взять столько строк и столбцов из

 строки, смешанные вместе, чтобы сформировать матрицу (заполнение пробелами)


* В классическом с ⎕ML( M 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. Заменить splitс explodeдля последующего PHP.

Запустите php -nr '<code> '<string>'
или попробуйте онлайн . (Убедитесь, что вы выбрали подходящую версию PHP!)



1

Perl 5, 60 +5 (-0777p) байтов

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

Попробуйте онлайн

  • Последняя строка ввода должна заканчиваться символом новой строки, если она принадлежит выходу.
  • В случае двух последовательных новых строк -00 опция может быть изменена на -0777.

Возможны два последовательных перевода строки, так что вам понадобится -0777. Что делать -00и -0777делать, во всяком случае.
Павел

-0для указания разделителя записей в восьмеричном формате 777- это специальное значение, указывающее на отсутствие разделителя, поэтому весь файл читается, 0это другое специальное значение, указывающее на «режим абзаца», разделитель содержит более 1 последовательных
символов

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

Скала , 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""}

Попробуйте онлайн!

Впервые игра в гольф на этом языке, так что, возможно, не самая лучшая.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.