Détecter du texte rectangulaire avec un code rectangulaire


19

Étant donné une chaîne de texte ASCII imprimable (y compris les retours à la ligne et les espaces) qui contient au moins un caractère qui n'est ni un retour à la ligne ni un espace, affichez une valeur véridique si la chaîne est rectangulaire et une valeur falsey dans le cas contraire. En outre, le code source de votre solution doit être rectangulaire .

Une chaîne est rectangulaire si elle remplit toutes les conditions suivantes:

  1. La première ligne et la dernière ligne ne contiennent aucun espace.
  2. Le premier et le dernier caractère de chaque ligne n'est pas un espace.
  3. Toutes les lignes ont le même nombre de caractères.

Par exemple, le texte suivant est rectangulaire:

abcd
e fg
hijk

Ce texte n'est cependant pas rectangulaire (exigence n ° 3):

1234
567
8900

Cas de test

Vérité:

sdghajksfg
asdf
jkl;
qwerty
u i op
zxcvbn
1234
5  6
7890
abcd
e fg
hijk

Falsey:

a b c
123
456
7 9
12
345
qwerty
 uiop
zxcvnm
1234
567
8900

Il s'agit de , donc la solution la plus courte en octets l'emporte.




9
Donc, une ligne sans espace est une soumission valide, n'est-ce pas?
Arnauld


1
Pouvons-nous prendre l'entrée comme un tableau de chaînes, une pour chaque ligne? Ou devons-nous entrer une seule longue chaîne qui inclut les sauts de ligne?
BradC

Réponses:


12

C (gcc) , 127 125 124 118 octets

  • Enregistré deux octets en jouant r*=!e&(!t|t==c);au golf r>>=e||t&&t-c;. (Ce golf a été l'inspiration pour mes récents conseils sur la réponse à la mise à jour du drapeau inversé .
  • Enregistré un octet en jouant *(_-2)au golf _[~1].
  • Économisé six octets en jouant *_++-10||(...)au golf *_++<11?...:0et en utilisant l'espace réservé zéro ...:0(qui n'est pas utilisé de manière constructive) pour jouer au golf l' c++incrément. Ces golfs ont permis un nouveau remaniement de la boucle.
  • Quand on peut utiliser plusieurs valeurs de falsey, 114 octets pourraient être possibles.
r,e,c,t;_(char*_){for(r=1,t=c=0;*_;*_++<11?r*=(t||(t=c,!e))&*_>32&_[~1]>32&t==c,c=e=0:c++)*_-32||(e=1);r>>=e||t&&t-c;}

Essayez-le en ligne!

Disposition source réalisant un rectangle plus haut.

Explication

Ce qui suit explique la version longue de 124 octets.

r,e,c,t;_(char*_){     // `r` is the boolean result flag, `e` a boolean flag if the current line contains
                       //  a space, `t` the first line's width, `c` the current line's current width
 for(r=1,t=c=0;*_;c++) // initialize, loop through entire string
  *_-32||              // if the current char is a space,
   (e=1),              //  the current line contains a space
  *_++-10||            // if the current char is a newline (char pointer `_` now incremented)
   (r*=(t||(t=c,!e))   // if t is not yet set, the current line is the first line; set it
                       //  to this line's length, check that no spaces where found
    &*_>32             // the next line's first char should not be a space
    &_[~1]>32          // this line's last char should not have been a space
    &t==c,c=~0,e=0);   // the line lengths should match, reset `c` and `e` to zero
                       //  (`~0 == -1`, countering the loop's increment of `c`)
 r>>=e||t&&t-c;}       // return boolean flag, check that the last line does not contain spaces,
                       //  there was either no newline or line lengths match
                       //  (here) equivalent to `r*=!e&(!t|t==c)`

Essayez-le en ligne!


10
+1 pourr,e,c,t
Magic Octopus Urn

4

Java 10, 214 176 169 152 152 144 139 octets

s->{String[]a=s.split("\n")
;int r=1,i=0,R=a.length;for
(;i<R;i++)if(i<1|i>R-2?a[i]
.contains(" "):a[i].trim( )
!=a[i])r=0;return-r<0;}////

-5 octets grâce à @Neil .

Utilise String[]aau lieu de var a; return-r<0;au lieu de return r>0;; et ajouté un commentaire //à la toute fin, donc il n'y a pas d'espace sur les première et dernière lignes.

Notez que ce rectangle est plus court qu'une entrée sur une seule ligne, car int r=1,...;devrait être remplacé par int[]v{1,...};, et toutes les utilisations des entiers deviendraient alors v[n](où n est l'index de la variable dans le tableau v).

Essayez-le en ligne.

Explication:

s->{                        // Method with String parameter and boolean return-type
  String[]a=s.split("\n");  //  Input split by new-lines
  int r=1,                  //  Result-integer, starting at 1
      i=0,                  //  Index `i`, starting at 0
      R=a.length;           //  Amount of rows `R`
  for(;i<R;i++)             //  Loop `i` over the rows
    if(i<1                  //   If it's the first row,
       |i>R-2?              //   or the last row:
        a[i].contains(" ")  //   And the current row contains a space
       :a[i].trim()!=a[i])  //   Or either column of the current row contains a space
      r=0;                  //    Set the result `r` to 0
   return-r<0;}             //  Return whether `r` is still 1
////                        // Comment to comply to the rules of the challenge

Voici le même programme de base avec des espaces ( 128 126 octets ):

s->{var a=s.split("\n");int r=1,i=0,R=a.length;for(;i<R;i++)if(i<1|i>R-2?a[i].contains(" "):a[i].trim()!=a[i])r=0;return r>0;}

-2 octets grâce à @Neil .

Essayez-le en ligne.



3

T-SQL, 237 207 octets

SELECT(SELECT(IIF(max(len(v))=min(len(v)),1,0)*IIF(SUM(len(v+'x')-len
(trim(v))-1)=0,1,0))FROM t)*(SELECT(IIF(SUM(charindex(' ',v))=0,1,0))
FROM[t]WHERE[i]IN(SELECT(min(i))FROM[t]UNION(SELECT(max(i))FROM[t])))

Sorties 1 pour rectangulaire, 0 sinon. J'ai dû utiliser des tonnes de parens et de supports supplémentaires pour éliminer les espaces, je suis sûr qu'il y a une grande marge d'amélioration.

Explication :

Conformément à nos options d'E / S autorisées et à la clarification dans les commentaires de la question, l'entrée est considérée comme des lignes séparées dans un tableau préexistant t . Étant donné que les données dans SQL ne sont pas classées par nature, cette table comprend un champ d'identité "numéro de ligne" i :

CREATE TABLE t (i INT IDENTITY(1,1), v VARCHAR(999))

Fondamentalement, mon SQL effectue 3 sous-requêtes, chacune renvoyant 0ou 1basée sur les 3 critères du code "rectangulaire". Ces 3 valeurs sont multipliées ensemble, ne retournant que 1pour un code qui satisfait les 3.

EDIT : Combiné les critères 2 et 3 dans le même SELECT pour économiser de l'espace

SELECT(
SELECT(IIF(max(len(v))=min(len(v)),1,0)                  --All rows same length
      *IIF(SUM(len(v+'x')-len(trim(v))-1)=0,1,0))FROM t) --no leading or trailing spaces
*(SELECT(IIF(SUM(charindex(' ',v))=0,1,0))               --No spaces at all in
FROM[t]WHERE[i]IN(SELECT(min(i))FROM[t]                  --   first row or
            UNION(SELECT(max(i))FROM[t])))               --   last row

La TRIM(v)fonction n'est prise en charge que par SQL 2017 et versions ultérieures. Les versions antérieures auraient besoin LTRIM(RTRIM(v)), ce qui nécessiterait un rééquilibrage des lignes.

Une note aléatoire: la LEN()fonction en SQL ignore les espaces de fin, donc LEN('foo ') = 3. Pour obtenir une "vraie" longueur, vous devez attacher un caractère à la fin, puis soustraire un: P


3

C ++, 199 183 181 175 octets

Cette fonction de modèle accepte les lignes comme une collection de chaînes (qui peuvent être des chaînes larges), transmises comme une paire d'itérateurs.

#include<algorithm>//
template<class I>bool
f(I a,I b){return!~+(
*a+b[-1]).find(' ')&&
std::all_of(a,b,[&a](
auto&s){return' '+-s.
back()&&s[0]-' '&&a->
size()==s.size();});}

Merci à l'utilisateur Erroneous de m'avoir rappelé le back()membre de std::stringet de lui avoir fait remarquer que npos+1c'est zéro.

Équivalent non golfé

Le seul vrai golf est de concaténer les première et dernière lignes afin que nous puissions effectuer un single findpour les espaces dans celles-ci.

#include <algorithm>
template<class It>
bool f(It a, It b)
{
    return (*a+b[-1]).find(' ') == a->npos
        && std::all_of(a, b,
                       [=](auto s) {
                           return s.back() != ' '
                               && s.front() != ' '
                               && s.size() == a->size(); });
}

Programme de test

#include <iostream>
#include <string>
#include <vector>
int expect(const std::vector<std::string>& v, bool expected)
{
    bool actual = f(v.begin(), v.end());
    if (actual == expected) return 0;
    std::cerr << "FAILED " << (expected ? "truthy" : "falsey") << " test\n";
    for (auto const& e: v)
        std::cerr << "  |" << e << "|\n";
    return 1;
}
int expect_true(const std::vector<std::string>& v) { return expect(v, true); }
int expect_false(const std::vector<std::string>& v) { return expect(v, false); }
int main()
{
    return
        // tests from the question
        + expect_true({"sdghajksfg"})
        + expect_true({"asdf", "jkl;",})
        + expect_true({"qwerty", "u i op", "zxcvbn",})
        + expect_true({"1234", "5  6", "7890",})
        + expect_true({"abcd", "e fg", "hijk",})
        + expect_false({"a b c",})
        + expect_false({"123", "456", "7 9",})
        + expect_false({"12", "345",})
        + expect_false({"qwerty", " uiop", "zxcvnm",})
        + expect_false({"1234", "567", "8900",})
        // extra tests for leading and trailing space
        + expect_false({"123", " 56", "789"})
        + expect_false({"123", "45 ", "789"})
        // the function source
        + expect_true({"#include<algorithm>//",
                       "template<class I>bool",
                       "f(I a,I b){return!~+(",
                       "*a+b[-1]).find(' ')&&",
                       "std::all_of(a,b,[&a](",
                       "auto&s){return' '+-s.",
                       "back()&&s[0]-' '&&a->",
                       "size()==s.size();});}",})
        ;
}

Cela peut encore être joué à 183 octets avec une largeur de ligne de 22, en utilisant .find(' ')+1==0et s.back()au lieu de *s.rbegin().
Erroneous



2

Haskell , 106 102 98 110 109 102 102 octets

(\a->all(==[])a||and(e((1<$)<$>a):map(all(>='!').($a))[head,last,map$last,map$head]));e(a:s)=all(==a)s

Merci à @nimi et @Laikoni pour un octet chacun!

Essayez-le en ligne!


2

Haskell , 79 octets

g(x:r)=all((==(0<$x)).(0<$))r&&all(>='!')(x++last(x:r)++(head<$>r)++(last<$>r))

Essayez-le en ligne!Prend l'entrée comme une liste de lignes.

Le modèle g(x:r)= ...lie la première ligne à xet la liste (éventuellement vide) des lignes restantes à r. all((==(0<$x)).(0<$))rVérifie ensuite si toutes les lignes ront la même longueur que x(Utilisation de cette astuce ).

Sinon, la conjonction &&court-circuite et revient False, sinon le côté droit est évalué. Il y a une chaîne qui se compose de xla première ligne, last(x:r)de la dernière ligne de r(ou la première ligne à nouveau au cas où elle rest vide) et (head<$>r)du premier et (last<$>r)du dernier caractère de chaque ligne. Pour cette chaîne, all(>='!')vérifie qu'elle ne contient aucun espace (nous ne pouvons pas l'utiliser en (>' ')raison de la restriction du code source).


Erreurs sur "\ n \ n"
Angs

@Angs Bonne prise. Heureusement, OP a précisé que l'entrée contains at least one character that is neither a newline nor a space, qui permet également de supprimer le cas de liste vide.
Laikoni

Oh gentil,
je

2

MATL , 13 octets

ctgF6Lt&()32>

L'entrée est un tableau de chaînes, au format {'abc' 'de'}.

La sortie est un tableau ne contenant que des unités , ce qui est vrai , ou un tableau contenant au moins un zéro, qui est falsey .

Essayez-le en ligne! Ou vérifiez tous les cas de test , y compris le test de véracité / fausseté.

Explication

c       % Implicit input. Convert to char. This concatenates the
        % strings of the input cell array as rows of a rectangular
        % char array, right-padding with spaces as needed
tg      % Duplicate, convert to logical. Gives a logical array with
        % the same size containing true in all its entries
F       % Push false
6L      % Push the array [2, j-1], where j is the imaginary unit.
        % When used as an index, this is interpreted as 2:end-1
t       % Duplicate
&(      % Assignment indexing with 4 inputs: original array, new
        % value, two indexing arrays. This writes false at the inner
        % rectangle (2:end-1)×(2:end-1) of the logical array that
        % initially only contained true. This will be used as a
        % logical index (mask) into the rectangular char array
)       % Reference indexing. This selects the border of the char
        % array. The result is a column vector of chars
32>     % Is each entry greater than 32? (ASCII code for space)
        % Implicit display

11 octets: cO6Lt&(32=~ essayez-le en ligne! Annule simplement les parties non frontalières, puis vérifie s'il y a des espaces.
sundar

@sundar Bonne idée! C'est assez différent, postez-le vous
Luis Mendo

1
Non, cela ressemble trop à votre réponse, surtout si je l'écris comme cF6Lt&(32=~. N'hésitez pas à le modifier, sinon nous pouvons simplement le laisser dans les commentaires.
sundar


1

Toile , 17 15 octets

4[↷K;}┐){SL]∑4≡

Essayez-le ici!

Explication (ASCII-fied pour monospace):

4[↷K;}┐){SL]∑4=  full program; pushes the input to the stack.
4[   }           repeat 4 times
  ↷                rotate ToS clockwise. This also pads the input with spaces
   K;              take off the last line and put it below the item
      ┐          pop the remaining of the input (the center)
       )         and wrap the rest (the sides) in an array
        {  ]     map over those
         S         split on spaces - should result to one item in the array
          L        and get the length
            ∑    sum those lengths together
             4=  check if equal 4

4
Je trouve ironique que ces caractères UTF8 dans une police de type monospace donnent l'impression qu'il y a beaucoup d'espaces dans la source. (
Arnauld

1
C'est ce que font les caractères @Arnauld pleine largeur. Et c'est pourquoi j'ai fait une police pour mon interprète pour la rendre plus jolie: p
dzaima


1

Rouge , 216 191 octets

func[s][d:(length?(first(s:(split(s)"^/"))))sp:
func[a][none = find a" "]b: on foreach c s[b: b
and(d = length? c )and(c/1 <>" ")and(" "<> last
c)]res:(sp(first(s)))and(sp(last(s)))and(b)res]

Essayez-le en ligne!

J'ai mis beaucoup de parenthèses autrement inutiles dans les première et dernière lignes.


0

Gelée , 17 octets

Ỵµ.ịЀ;ịɗẎ⁶e<L€E$

Essayez-le en ligne!


@JonathanFrech Ah, corrigé. > _>
Erik the Outgolfer

@MagicOctopusUrn Huh? Pouvez-vous s'il vous plaît lier à une entrée où cela ne se comporte pas correctement?
Erik the Outgolfer

Oh, non, tu as appelé le mien parce que Does not seem to enforce equal line lengthc'est tout ce que je disais.
Urne Magic Octopus

Ne semble pas fonctionner pour " \n " Essayez-le en ligne!
Angs

1
@Angs Essayez de le citer. C'est apparemment analysé comme rien si vous le dites comme ça.
Erik the Outgolfer

0

Gelée , 15 octets

Utilise une méthode développée par Mnemonic dans une soumission Pyth supprimée (actuellement - en raison d'une défaillance du cas de bord). (s'il est maintenant réparé, allez donner un crédit !)

ỴµL€Eȧt€⁶ZUƊ4¡⁼

Un lien monadique acceptant une liste de caractères qui renvoie 1 ou 0.

Essayez-le en ligne!

Comment?

ỴµL€Eȧt€⁶ZUƊ4¡⁼ - Link: list of characters
Ỵ               - split at newlines (making a list of lists - the rows)
 µ              - start a new monadic chain, call that ROWS
  L€            - length of €ach row in ROWS
    E           - all equal? (an integer: 1 if so, otherwise 0)
            4¡  - repeat four times:
           Ɗ    -   last three links as a monad:
      t€⁶       -     trim spaces (⁶) from €ach row in current ROWS
         Z      -     transpose that result
          U     -     upend (reverse each new row)
     ȧ          - logical AND (0 if L€E was 0 else the result of the repeated transform)
              ⁼ - equal to X? (the integer 0 is not equal to any listy of characters)

@Mnemonic - Jelly-fied :)
Jonathan Allan

0

Japt , 22 octets

Réponse non concurrente: il existe un bogue connu dans Japt , où les rotations de tableaux bidimensionnels tronquent les résultats. En raison de ce bogue, le code ci-dessous ne fonctionne que sur les entrées carrées. Si le bogue n'était pas présent, le code ci-dessous devrait fonctionner complètement correctement.

e_ʶUÌÊéUeº4o)r_z)mx}U
e_                      // Check if every line in the input array
  ʶUÌÊ                 // has the same length as the last item.
       é               // Also,
               r_z)mx}U // check if rotating and trimming the input array
           º4o)         // four times
         Ue             // is equal to the input array.

Prend l'entrée comme un tableau de chaînes. L'utilisation de parenthèses au lieu d'espaces rend l'exigence de code rectangulaire assez facile.
Essayez-le ici .


0

Ruby 2.5+, 63 octets

->a{!a.uniq(&:size)[1]&&a.none?(/^\s|\s$/)&&!(a[0]+a[-1])[?\s]}

Prend l'entrée comme un tableau de chaînes. Pas de lien de test, car la version sur TIO (2.4) est trop ancienne pour celle-ci. Au lieu de cela, voici une version légèrement plus longue (69 octets) pour les tests:

->a{!a.uniq(&:size)[1]&&a.none?{|l|l=~/^\s|\s$/}&&!(a[0]+a[-1])[?\s]}

Essayez-le en ligne!

La différence est que depuis 2.5 Ruby prend en charge le passage direct d'un modèle Regex aux all?, any?, none?méthodes, ce qui nous fait gagner quelques octets. La méthode elle-même est assez explicite - nous testons:

  1. S'il n'y a qu'une seule taille de ligne unique
  2. S'il y a des espaces sur les limites de ligne
  3. S'il y a des espaces sur les première et dernière lignes.

0

C (gcc) , 119 octets

Prend les entrées sous forme de liste (s) de n chaînes.

f(s,n,m,r,p)char**s,*p;{for(r=m=n;m--;r*=strlen(*s)==strlen(s[m])&(!p||m&&m^n-1&&p!=s[m]&&p[1]))p=strchr(s[m],32);n=r;}

Essayez-le en ligne!


0

C # (.NET de base) , 145 167 octets

S[0].Length>1&&S[0].IndexOf
(" ") + S[ S.Count() - 1 ].
IndexOf(" ")<-1&Array.Find(
S,x=>x[0]==' '| x [x.Length
-1]  ==  ' '  | S[0].Length
!=x.Length)==null?11>0:0>1;

Essayez-le en ligne!

S[0].Length>1&                                    // And if the lenght of the first argument is more than 1 char
Array.Find(                                       // Find a string in an array
    S,                                            // The array which will be searched in
    x=>                                           // For x as the current string from the array
    x.Length!=S[0].Length|                        // If the string lenght match not the first argument lenght
    x[0]==' '|                                    // Or if the string begins with a spacer
    x[x.Length-1]==' '                            // Or if the string ends with a spacer
)==null&                                          // And if there was no string found which matched the conditions
S[0].IndexOf(" ")+S[S.Count()-1].IndexOf(" ")<-1  // And if the first and last string doesn't have a spacer
?                                                 // If all above is true do
1>0                                               // Return True
:                                                 // Else
0>1                                               // Return False

Pas d'espaces sur la première ligne.
FrownyFrog

@FrownyFrog S[0].IndexOf(" ")recherche un espace dans la première ligne et S[S.Count()-1].IndexOf(" ")recherche dans la dernière ligne. S'il n'y a pas d'espace dans la première et la dernière ligne, c'est -2 qui est alors vrai à -2 < -1.
Hille

2
Je veux dire le défi, votre code a la même restriction, donc vous ne pouvez pas avoir d'espaces dans la première ligne.
FrownyFrog

1
Votre code doit revenir Truelorsqu'il est transmis à votre programme. C'est une restriction supplémentaire dans ce défi.
FrownyFrog

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.