Esculpir um quadrado de uma corda

21

Hoje, seu desafio é pegar uma sequência de múltiplas linhas e gerar o quadrado maior contido na sequência que inclui o canto superior esquerdo.

Uma cadeia quadrada é aquela em que:

  • Cada linha tem o mesmo número de caracteres
  • O número de caracteres em cada linha é igual ao número de linhas.

Considere a seguinte sequência de entrada possível:

abcde
fgh
asdf
foobar

O maior quadrado que você pode extrair dele que inclui o primeiro caractere (o ano canto do pé) é este:

abc
fgh
asd

Não pode haver um quadrado de comprimento lateral 4, porque a segunda linha não é longa o suficiente. Agora considere esta entrada em potencial:

a
bcd
edf
ghi

A maior praça aqui é justa a. O quadrado 3x3 formado na parte inferior não contém o primeiro caractere e não conta.

Aqui estão mais alguns casos de teste:

a

a

abc
def
gh

ab
de

ab
cd

ab
cd

abcde
fghij
klm
no

abc
fgh
klm

a
b

a

Você pode exigir que a entrada seja delimitada por sua escolha de LF, CR ou CRLF.

Os caracteres da nova linha não são considerados parte do comprimento da linha.

Você pode exigir que exista ou não uma nova linha à direita na entrada, que não conta como uma linha adicional.

Input é uma string ou um array de caracteres 1D; não é uma lista de strings.

Você pode assumir que a entrada não está vazia e que todas as linhas não estão vazias, e que ela contém apenas ASCII imprimível, incluindo espaços e novas linhas (para o delimitador de linha), mas não as guias.

Isso é , o menor número de bytes vence!

Pavel
fonte
relacionado
Pavel
5
+1 para um desafio interessante, -1 para E / S estrita
Dennis
@ Dennis nem toda solução precisa usar, .split('\n')então não vejo por que alguns deveriam obtê-la gratuitamente.
Pavel
2
Não se trata apenas de adicionar bytes para um clichê chato. Algumas abordagens (por exemplo, funções recursivas) tornam-se completamente impraticáveis ​​se houver pré ou pós-processamento.
Dennis
@ Dennis eu não tinha pensado nisso assim. Você acha que eu deveria mudar isso agora ou é tarde demais?
Pavel

Respostas:

5

Braquilog , 11 bytes

ṇ⊇ᵐẹa₀ṁcᵐ~ṇ

Experimente online!

Explicação

ṇ             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
Fatalizar
fonte
Bom trabalho na solução mais curta (até agora), Brachylog com certeza gosta de quadrados, não é?
Pavel
@ Pavel O built-in é realmente bastante útil!
Fatalize
7

Casca , 13 bytes

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

Experimente online!

Explicação

►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.
Zgarb
fonte
1
Como isso é mesmo uma linguagem de programação - você acabou de colar alguns caracteres unicode obscuros! ;)
nabo
1
Bem-vindo ao mundo das linguagens de golfe, projetadas especificamente para usar o mínimo de bytes possível para realizar uma determinada tarefa. Parte disso é ter uma página de código personalizada, para que haja um caractere para cada byte possível, em vez do usual 95 ASCII imprimível. Mas não se preocupe, também existem idiomas de golfe muito mais legíveis; por exemplo, a minha entrada MATL [/ auto-promoção descarada]
Sanchises
5

GNU sed , 106 + 1 94 + 2 = 96 bytes

+2 bytes para -rzsinalizadores. Usa caracteres não imprimíveis NUL e BEL, mostrados como @e #aqui. Veja abaixo um despejo xxd.

Obrigado a @seshoumara por me enviar o caminho para -z.

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

Experimente online!

Explicação

Isso funciona inserindo dois cursores no texto - um para passar por cima de linhas e outro para passar por cima de colunas. Os cursores são representados por NUL (0x00) e BEL (0x07), respectivamente, mas nos exemplos abaixo vou usar @e #. Suponha que tenhamos esta entrada:

abcde
fgh
asdf
foobar

O cursor BEL é inserido antes da coluna 0 e o cursor BEL antes da linha 0 (aqui mantive as colunas alinhadas para facilitar a legibilidade; mas, na realidade, não há preenchimento esquerdo):

#@abcde
 @fgh
 @asdf
 @foobar

Em um loop, os cursores são movidos um caractere para a direita e uma linha para baixo, respectivamente:

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

Após cada iteração, ele verifica duas condições:

  1. Na linha com o cursor da linha, existe um cursor da coluna e o cursor da coluna pode se mover para a direita?
  2. Nas linhas antes do cursor da linha, cada cursor da coluna pode se mover para a direita?

Se uma das condições for falsa, o loop termina. O script termina excluindo tudo depois @de cada linha e tudo depois #no espaço do padrão.

despejo 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
Jordânia
fonte
Você pode remover o primeiro loop, A, porque a instrução diz que você deve ler a entrada como uma sequência, para receber "line1 \ nline2 \ nline3" etc. etc. Outras respostas também o fizeram. Isso deve obter a contagem abaixo de 100 :)
seshoumara
@seshoumara Outras respostas do line1\nline2\nline3where \nis \x5C\x6E? Qual?
Jordan
Você pode me dar um link? (Clique em "compartilhar" na parte inferior de qualquer resposta.) Ou mostre-me em um TiO o que você quer dizer? Em todas as respostas em Python e PHP que vejo \nsão interpretadas como um caractere de nova linha ( \x0A, não \x5C\x6E) e não consigo encontrar uma maneira de fazer com que o sed receba a entrada com caracteres de nova linha como uma única linha.
Jordan
@seshoumara Hah, deixa pra lá, acabei de me lembrar da -zbandeira. Obrigado!
Jordan
4

Python 2 , 81 bytes

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

Experimente online!


Um método interessante, mas com 2 bytes a mais.

Python 2 , 83 bytes

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

Experimente online!

xnor
fonte
1
Não inputlê apenas uma linha?
Pavel
@Pavel, se você olhar para o exemplo online, poderá ver que ele está usando caracteres de nova linha explícitos para manter a entrada como uma string de uma linha. Provavelmente, optando por esse método porque raw_input()adicionaria mais bytes.
Xavier Dass
4

JavaScript (ES6), 77 bytes

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

Recursivamente usa uma expressão regular para procurar um quadrado cada vez maior até que nenhum seja encontrado.

A expressão regular seria esta para um quadrado 3x3:

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

A entrada deve terminar com uma nova linha e a saída é uma lista.

Explicação:

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

Snippet:

Rick Hitchcock
fonte
3

Braquilog , 16 bytes

ṇ{ẹa₀ᵐa₀ṁ}ᶠtcᵐ~ṇ

Experimente online!

Erik, o Outgolfer
fonte
Explicação, por favor?
Pavel
3

Perl 5 , 84 bytes

chomp(@a=<>);map$.&&=y///c>$i,@a[0..$i]while$.&&$i++<$#a;say/(.{$i})/ for@a[0..$i-1]

Experimente online!

Cumpre o "abcde\nfghij\nklm\nno"caso de teste.

Xcali
fonte
você poderia usar chopem vez de chompe ++$i<@aem vez de$i++<$#a
Nahuel FOUILLEUL
3

R , 84 83 81 76 bytes

-5 bytes, portando a abordagem de Dennis comsum

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

Experimente online!

lê de stdin, imprime em stdout sem uma nova linha à direita.

Ligeiramente não destruído:

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

Giuseppe
fonte
3

C (gcc) , 162 159 151 147 144 142 137 bytes

Deve haver alguns cursos para jogar golfe aqui ...

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

Experimente online!

cleblanc
fonte
Pode !=-1ser >-1ou não getchar()valores de saída menor do que um menos? Poderia mesmo ser +1?
Jonathan Frech
158 bytes potenciais .
Jonathan Frech
@ JonathanFrech Eu posso usar ~para detectar menos um.
Cleblanc #
1
@ RickHitchcock Parece funcionar na versão mais recente do golfe.
Cleblanc 8/11
2

Gelatina , 15 bytes

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

Experimente online!

Como funciona

ỴÇÇ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.
Dennis
fonte
2

Java 8, 150 bytes

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

Explicação:

Experimente aqui.

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
Kevin Cruijssen
fonte
2

MATL , 33 bytes

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

Experimente online!

Meu senso de aranha me diz que provavelmente há uma maneira mais curta (estou pensando em algo Ybocerto desde o início) ... Requer uma nova linha no final. (Observação: eu projetei demais isso um pouco, pois isso também manipula linhas vazias, o que não é necessário. Vou ver se consigo reduzir o número de bytes, porque no código golf, não é um recurso, mas um bug)

Sanchises
fonte
1
@Pavel Guiseppe estava se referindo a outra versão, que eu revirei porque realmente tinha um bug.
Sanchises
1

Python 2 , 132 bytes

def f(s):s=s.split("\n");return["\n".join([l[:j+1]for l in s[:j+1]])for j,v in enumerate(s[0])if all(len(l)>j for l in s[:j+1])][-1]

Experimente online!

Jonathan Frech
fonte
1

Python 2 , 103 bytes

def f(i):
 i=i.split('\n');x=0
 while all(v[x:]for v in i[:x+1])*i[x:]:x+=1
 for v in i[:x]:print v[:x]

Experimente online!

ovs
fonte
1

JavaScript (ES6), 95 bytes

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>

Requer uma nova linha à direita na entrada.

Neil
fonte
1

APL (Dyalog) , 25 bytes *

Função de prefixo tácito. Retorna uma matriz.

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

Experimente online!

É realmente o topo de duas funções independentes, a saber, ⎕AV[3]∘≠⊆⊢que trata do formato de entrada estranho e ↑↑⍨2⍴(⌊/≢,≢¨)que faz o trabalho realmente interessante.

⎕AV[3]∘≠ diferença de LF (o terceiro elemento da Um Tomic V ector - o conjunto de caracteres)

 partições (substrings começando com valores maiores que seu antecessor e caindo em 0s)

 o argumento

() Aplique a seguinte função tácita:

2⍴() Remodelar o seguinte para o comprimento 2:

  ⌊/ o mínimo de

   o número de strings

  , Seguido por

  ≢¨ o número de caracteres em cada sequência

↑⍨ pegue tantas linhas e colunas de

 as cordas misturadas para formar uma matriz (preenchimento com espaços)


* No clássico com ⎕ML( M igration L evel) 3(padrão em muitos sistemas) e substituindo por e para o mais à esquerda . Tio!

Adão
fonte
Se tiver o mesmo comprimento no Dyalog Classic, você também pode dizer que é o Dyalog Classic e não usar a nota de rodapé.
Pavel
@ Pavel Ambos Classic e ⎕ML←3estão obsoletos, então eu prefiro mostrar o idioma como ele normalmente aparece. De fato, quase todas as minhas soluções Dyalog APL assumem o Classic apenas porque contamos bytes em vez de caracteres, embora até a versão Unicode atribua significado a menos de 256 caracteres.
Adám
1

PHP, 123 bytes

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

requer PHP 5.4, 5.5 ou 5.6. Substituirsplit porexplode para o PHP posterior.

Corra com php -nr '<code> '<string>'
ou experimente online . (Certifique-se de selecionar uma versão adequada do PHP!)

Titus
fonte
1

Perl 5, 60 +5 (-0777p) bytes

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

Experimente online

  • A última linha de entrada deve terminar com uma nova linha, caso pertença à saída.
  • No caso de duas novas linhas consecutivas, a opção -00 pode ser alterada por -0777.
Nahuel Fouilleul
fonte
Duas novas linhas consecutivas são possíveis, então você precisará -0777. O que fazer -00e -0777fazer, de qualquer maneira.
Pavel
-0é especificar o separador de registro em formato octal 777é um valor especial para indicar nenhum separador assim todo o arquivo é lido, 0é outro valor especial para indicar "modo de parágrafo", separador é mais do que 1 novas linhas consecutivas
Nahuel FOUILLEUL
1

Perl 6 , 158 140 bytes

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("
")

Experimente online!

Viva minha primeira resposta em Perl 6. Vou brincar com algumas opções de linha de comando para ver se consigo jogar um pouco mais. Toda ajuda para salvar bytes é bem-vinda!

Luke
fonte
1

Scala , 201 bytes

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

Experimente online!

Golfe pela primeira vez nesse idioma, talvez não seja o melhor.

TheInitializer
fonte