Tailler un carré à partir d'une chaîne


21

Votre défi aujourd'hui est de prendre une chaîne multiligne et de produire le plus grand carré contenu dans la chaîne qui comprend le coin supérieur gauche.

Une chaîne carrée est celle où:

  • Chaque ligne a le même nombre de caractères
  • Le nombre de caractères sur chaque ligne est égal au nombre de lignes.

Considérez la chaîne d'entrée possible suivante:

abcde
fgh
asdf
foobar

Le plus grand carré que vous pouvez en prendre qui comprend le premier caractère (le adans le coin supérieur gauche) est le suivant:

abc
fgh
asd

Il ne peut pas y avoir de carré de côté 4, car la deuxième ligne n'est pas assez longue. Considérez maintenant cette entrée potentielle:

a
bcd
edf
ghi

La plus grande place ici est juste a . Le carré 3x3 formé en bas ne contient pas le tout premier caractère et ne compte pas.

Voici quelques cas de test supplémentaires:

a

a

abc
def
gh

ab
de

ab
cd

ab
cd

abcde
fghij
klm
no

abc
fgh
klm

a
b

a

Vous pouvez exiger que l'entrée soit délimitée par votre choix de LF, CR ou CRLF.

Le ou les caractères de nouvelle ligne ne sont pas considérés comme faisant partie de la longueur de la ligne.

Vous pouvez exiger qu'il y ait ou non une nouvelle ligne de fin en entrée, qui ne compte pas comme une ligne supplémentaire.

L'entrée est une chaîne ou un tableau de caractères 1D; ce n'est pas une liste de chaînes.

Vous pouvez supposer que l'entrée n'est pas vide et que toutes les lignes ne sont pas vides et qu'elle ne contient que de l'ASCII imprimable, y compris des espaces et des retours à la ligne (pour le délimiteur de ligne) mais pas des tabulations.

C'est du , le moins d'octets gagne!



5
+1 pour un défi intéressant, -1 pour des E / S strictes
Dennis

@ Dennis n'a pas besoin d'être utilisé par toutes les solutions, .split('\n')donc je ne vois pas pourquoi certains devraient l'obtenir gratuitement.
Pavel

2
Il ne s'agit pas (seulement) d'ajouter des octets pour le passe-partout ennuyeux. Certaines approches (par exemple, les fonctions récursives) deviennent complètement impraticables en cas de pré ou post-traitement.
Dennis

@Dennis Je n'y avais pas pensé comme ça. Pensez-vous que je devrais le changer maintenant, ou est-il trop tard?
Pavel

Réponses:


5

Brachylog , 11 octets

ṇ⊇ᵐẹa₀ṁcᵐ~ṇ

Essayez-le en ligne!

Explication

ṇ             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

Bon travail sur la solution la plus courte (jusqu'à présent), Brachylog aime bien les carrés, n'est-ce pas?
Pavel

@Pavel L' intégré est en effet assez pratique!
Fatalize

7

Husk , 13 octets

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

Essayez-le en ligne!

Explication

►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
Comment est-ce même un langage de programmation - vous venez de coller quelques caractères unicode obscurs! ;)
navet

1
@Petar Bienvenue dans le monde des langues de golf, qui sont conçues spécifiquement pour utiliser le moins d'octets possible pour effectuer une certaine tâche. Une partie de cela consiste à avoir une page de codes personnalisée, de sorte qu'il y ait un caractère pour chaque octet possible, au lieu de l'habituel ASCII imprimable 95. Mais ne vous inquiétez pas, il existe également des langues de golf beaucoup plus lisibles; par exemple mon entrée MATL [/ auto-promotion sans vergogne]
Sanchises

5

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

+2 octets pour les -rzdrapeaux. Utilise les caractères non imprimables NUL et BEL, représentés comme @et# ici. Voir ci-dessous pour un vidage xxd.

Merci à @seshoumara de m'avoir envoyé sur le chemin de -z.

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

Essayez-le en ligne!

Explication

Cela fonctionne en insérant deux curseurs dans le texte: un pour passer les lignes et l'autre pour passer les colonnes. Les curseurs sont représentés respectivement par NUL (0x00) et BEL (0x07), mais dans les exemples ci-dessous, j'utiliserai @et #. Supposons que nous ayons cette entrée:

abcde
fgh
asdf
foobar

Le curseur BEL est inséré avant la 0ème colonne et le curseur BEL avant la 0ème ligne (ici j'ai gardé les colonnes alignées pour plus de lisibilité; mais en réalité il n'y a pas de remplissage gauche):

#@abcde
 @fgh
 @asdf
 @foobar

Dans une boucle, les curseurs sont déplacés d'un caractère vers la droite et d'une ligne vers le bas, respectivement:

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

Après chaque itération, il vérifie deux conditions:

  1. Sur la ligne avec le curseur de ligne, y a-t-il un curseur de colonne et le curseur de colonne peut-il se déplacer vers la droite?
  2. Sur les lignes précédant le curseur de ligne, chaque curseur de colonne peut-il se déplacer vers la droite?

Si l'une ou l'autre condition est fausse, la boucle se termine. Le script se termine en supprimant tout ce qui se trouve après @sur chaque ligne et tout ce qui se trouve après #dans l'espace modèle.

vidage 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

Vous pouvez supprimer la première boucle, A, car l'instruction indique que vous devez lire l'entrée sous forme de chaîne, afin que vous puissiez recevoir "line1 \ nline2 \ nline3" etc. D'autres réponses l'ont fait également. Cela devrait faire passer le nombre en dessous de 100 :)
seshoumara

@seshoumara D'autres réponses font line1\nline2\nline3\nest \x5C\x6E? Lequel?
Jordan

Pouvez-vous me donner un lien? (Cliquez sur "partager" au bas de n'importe quelle réponse.) Ou montrez-moi dans un TiO ce que vous voulez dire? Dans toutes les réponses Python et PHP que je vois \nest interprétée comme un caractère de nouvelle ligne ( \x0A, pas \x5C\x6E) et je ne trouve pas de moyen de faire entrer sed avec des caractères de nouvelle ligne comme une seule ligne.
Jordan

@seshoumara Hah, peu importe, je viens de me souvenir du -zdrapeau. Merci!
Jordan

4

Python 2 , 81 octets

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

Essayez-le en ligne!


Une méthode intéressante, mais 2 octets de plus.

Python 2 , 83 octets

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

Essayez-le en ligne!


1
Ne inputlit pas seulement une ligne?
Pavel

@ Pavel, si vous regardez l'exemple en ligne, vous pouvez voir qu'il utilise des caractères de nouvelle ligne explicites pour conserver l'entrée une chaîne d'une ligne. Opter probablement pour cette méthode car raw_input()cela ajouterait plus d'octets.
Xavier Dass

4

JavaScript (ES6), 77 octets

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

Utilise récursivement une expression régulière pour rechercher un carré de plus en plus grand jusqu'à ce qu'aucun ne soit trouvé.

L'expression régulière serait la suivante pour un carré 3x3:

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

L'entrée devrait se terminer par une nouvelle ligne et la sortie est une liste.

Explication:

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

Fragment:



3

Perl 5 , 84 octets

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

Essayez-le en ligne!

Remplit le "abcde\nfghij\nklm\nno"cas de test.


vous pouvez utiliser à la chopplace de chompet ++$i<@aau lieu de$i++<$#a
Nahuel Fouilleul

3

R , 84 83 81 76 octets

-5 octets portant l'approche de Dennis avecsum

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

Essayez-le en ligne!

lit depuis stdin, imprime vers stdout sans retour à la ligne.

Légèrement non golfé:

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 octets

Il doit y avoir quelques coups pour jouer au golf ici ...

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

Essayez-le en ligne!


Peut !=-1être >-1ou ne les getchar()valeurs de sortie inférieure à un moins? Serait-ce même possible +1?
Jonathan Frech


@JonathanFrech Je peux utiliser ~pour détecter moins un.
cleblanc

1
@RickHitchcock Semble fonctionner dans la dernière version de golf.
cleblanc

2

Gelée , 15 octets

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

Essayez-le en ligne!

Comment ça marche

ỴÇÇ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 octets

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

Explication:

Essayez-le ici.

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 octets

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

Essayez-le en ligne!

Mon sens vague me dit qu'il y a probablement un chemin plus court (je pense à quelque chose avec Ybodès le début) ... Nécessite une nouvelle ligne à la fin. (Remarque: j'ai un peu trop modifié cela, car cela gérera également les lignes vides, ce qui n'est pas nécessaire. Je vais voir si je peux réduire le nombre de bytecards, car dans le code golf, ce n'est pas une fonctionnalité, mais un bug)


1
@ Pavel Guiseppe faisait référence à une autre version, que j'ai annulée car elle avait en effet un bug.
Sanchises



1

JavaScript (ES6), 95 octets

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>

Nécessite une nouvelle ligne de fin en entrée.



1

APL (Dyalog) , 25 octets *

Fonction de préfixe tacite. Renvoie une matrice.

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

Essayez-le en ligne!

C'est vraiment un sommet de deux fonctions indépendantes, à savoir ⎕AV[3]∘≠⊆⊢qui traite du format d'entrée maladroit et ↑↑⍨2⍴(⌊/≢,≢¨)qui fait le travail réellement intéressant.

⎕AV[3]∘≠ différence de LF (le troisième élément du A tomic V ecteur - le jeu de caractères)

 partitions (sous-chaînes commençant à des valeurs supérieures à leur prédécesseur et tombant à 0 s)

 l'argument

() Appliquez la fonction tacite suivante:

2⍴() Remodeler ce qui suit en longueur 2:

  ⌊/ le minimum de

   le nombre de cordes

  , suivi par

  ≢¨ le nombre de caractères dans chaque chaîne

↑⍨ prendre autant de lignes et de colonnes

 les chaînes mélangées pour former une matrice (remplissage avec des espaces)


* En Classique avec ⎕ML( M igration L Evel) 3(par défaut sur de nombreux systèmes) et son remplacement pour et le plus à gauche . Tio!


Si c'est la même longueur dans Dyalog Classic, vous pourriez aussi bien dire que c'est Dyalog Classic et ne pas utiliser la note de bas de page.
Pavel

@Pavel Classic et ⎕ML←3sont obsolètes, je préfère donc afficher la langue telle qu'elle apparaît normalement. En fait, presque toutes mes solutions Dyalog APL supposent Classic simplement parce que nous comptons les octets au lieu des caractères, même si la version Unicode attribue une signification à moins de 256 caractères.
Adám

1

PHP, 123 octets

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

nécessite PHP 5.4, 5.5 ou 5.6. Remplacez splitparexplode pour PHP plus tard.

Courez avec php -nr '<code> '<string>'
ou essayez-le en ligne . (Assurez-vous de sélectionner une version PHP adaptée!)



1

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

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

Essayez-le en ligne

  • La dernière ligne d'entrée doit se terminer par une nouvelle ligne au cas où elle appartiendrait à la sortie.
  • En cas de deux nouvelles lignes consécutives, l'option -00 peut être modifiée d'ici -0777.

Deux nouvelles lignes consécutives sont possibles, vous en aurez donc besoin -0777. Que faire -00et -0777faire, de toute façon.
Pavel

-0est de spécifier que le séparateur d'enregistrement au format octal 777est une valeur spéciale pour indiquer qu'il n'y a pas de séparateur afin que le fichier entier soit lu, 0est une autre valeur spéciale pour indiquer le "mode paragraphe", le séparateur est plus de 1 sauts de ligne consécutifs
Nahuel Fouilleul

1

Perl 6 , 158 140 octets

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

Essayez-le en ligne!

Hourra pour ma première réponse Perl 6. Je vais jouer avec quelques options de ligne de commande pour voir si je peux jouer au golf un peu plus. Toute aide pour économiser des octets est la bienvenue!


1

Scala , 201 octets

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

Essayez-le en ligne!

Golf pour la première fois dans cette langue, donc peut-être pas le meilleur.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.