Detectar texto rectangular con código rectangular

19

Dada una cadena de texto ASCII imprimible (que incluye líneas nuevas y espacios) que contiene al menos un carácter que no es una línea nueva ni un espacio, genera un valor verdadero si la cadena es rectangular, y un valor falso de lo contrario. Además, el código fuente de su solución debe ser rectangular .

Una cadena es rectangular si cumple con todas las siguientes condiciones:

  1. La primera línea y la última línea no contienen espacios.
  2. El primer y último carácter de cada línea no es un espacio.
  3. Todas las líneas tienen el mismo número de caracteres.

Por ejemplo, el siguiente texto es rectangular:

abcd
e fg
hijk

Este texto, sin embargo, no es rectangular (requisito # 3):

1234
567
8900

Casos de prueba

Verdad:

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

Este es el , por lo que gana la solución más corta en bytes.

Mego
fuente
Sandbox
Mego
2
Relacionados .
AdmBorkBork
99
Entonces, una línea sin ningún espacio es una presentación válida, ¿correcto?
Arnauld
1
relacionado
Rod
1
¿Podemos tomar la entrada como un conjunto de cadenas, una para cada línea? ¿O debemos ingresar una sola cadena larga que incluye los saltos de línea?
BradC

Respuestas:

12

C (gcc) , 127 125 124 118 bytes

  • Ahorró dos bytes jugando r*=!e&(!t|t==c);al golf en r>>=e||t&&t-c;. (Este golf fue la inspiración para mi reciente actualización de consejos de respuesta C ).
  • Salvó un byte jugando *(_-2)al golf _[~1].
  • Se ahorraron seis bytes jugando *_++-10||(...)al golf *_++<11?...:0y utilizando el marcador de posición cero ...:0(que no se usa de manera constructiva) para jugar el c++incremento. Esos campos de golf permitieron una nueva reorganización del circuito.
  • Cuando uno puede usar múltiples valores de falsey, 114 bytes podrían ser posibles.
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;}

Pruébalo en línea!

Diseño de origen logrando un rectángulo más alto.

Explicación

A continuación se explica la versión larga de 124 bytes.

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)`

Pruébalo en línea!

Jonathan Frech
fuente
10
+1 parar,e,c,t
Urna de pulpo mágico
4

Java 10, 214 176 169 152 144 139 bytes

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 bytes gracias a @Neil .

Usos en String[]alugar de var a; return-r<0;en lugar de return r>0;; y agregó un comentario //al final, para que no haya espacios en la primera y última fila.

Tenga en cuenta que este rectángulo es más corto que una entrada de una sola línea, ya que int r=1,...;debería reemplazarse por int[]v{1,...};, y todos los usos de los enteros se convertirían en v[n](donde n es el índice de la variable en la matriz v).

Pruébalo en línea.

Explicación:

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

Aquí está el mismo programa base con espacios ( 128 126 bytes ):

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 bytes gracias a @Neil .

Pruébalo en línea.

Kevin Cruijssen
fuente
1
tio.run/…
Neil
3

T-SQL, 237 207 bytes

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])))

Salidas 1 para rectangular, 0 de lo contrario. Tuve que usar toneladas de parens y brackets adicionales para eliminar espacios, estoy seguro de que hay mucho espacio para mejorar.

Explicacion :

Según nuestras opciones de E / S permitidas y la aclaración en los comentarios de las preguntas, la entrada se toma como filas separadas en una tabla preexistente t . Debido a que los datos en SQL están inherentemente desordenados, esa tabla incluye un campo de identidad "número de fila" i :

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

Básicamente, mi SQL realiza 3 subconsultas, cada una de las cuales devuelve 0o se 1basa en los 3 criterios del código "rectangular". Esos 3 valores se multiplican juntos, solo devuelven 1un código que satisface los 3.

EDITAR : criterios combinados 2 y 3 en el mismo SELECCIONAR para ahorrar espacio

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)función solo es compatible con SQL 2017 y versiones posteriores. Se necesitarían versiones anteriores LTRIM(RTRIM(v)), lo que requeriría reequilibrar las filas.

Una nota al azar: la LEN()función en SQL ignora los espacios finales, entonces LEN('foo ') = 3. Para obtener una longitud "verdadera", debe agregar un carácter al final y luego restar uno: P

BradC
fuente
3

C ++, 199 183 181 175 bytes

Esta función de plantilla acepta líneas como una colección de cadenas (que pueden ser cadenas anchas), pasadas como un par de iteradores.

#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();});}

Gracias al usuario Erroneous por recordarme al back()miembro de std::stringy por señalar que npos+1es cero.

Equivalente sin golf

El único juego de golf real es concatenar la primera y la última línea para que podamos realizar un solo findespacio en ellas.

#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(); });
}

Programa de prueba

#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();});}",})
        ;
}
Toby Speight
fuente
Esto se puede ampliar a 183 bytes con un ancho de línea de 22, usando .find(' ')+1==0y en s.back()lugar de *s.rbegin().
Erroneo
2

Python 2 , 82 bytes

lambda*s:len(set(map(len,s)))<2<'!'<=min(tuple(s[0]+s[-1])+zip(*s)[0]+zip(*s)[-1])

Pruébalo en línea!

Invocar como f("abcd", "e fg", "hijk").

Lynn
fuente
2

Haskell , 106 102 98 110 109 102 bytes

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

¡Gracias a @nimi y @Laikoni por un byte cada uno!

Pruébalo en línea!

Angs
fuente
2

Haskell , 79 bytes

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

Pruébalo en línea! Toma la entrada como una lista de líneas.

El patrón g(x:r)= ...une la primera línea xy la lista (posiblemente vacía) de líneas restantes a r. Luego all((==(0<$x)).(0<$))rverifica si todas las líneas rtienen la misma longitud que x(Uso de este consejo ).

Si no, entonces la conjunción &&cortocircuita y regresa False, de lo contrario se evalúa el lado derecho. Allí se crea una cadena que consiste xen la primera línea, last(x:r)la última línea de r(o la primera línea nuevamente en caso de que resté vacía) y (head<$>r)el primer y (last<$>r)el último carácter de cada línea. Para esta cadena, all(>='!')verifica que no contenga espacios (no podemos usarla (>' ')debido a la restricción del código fuente).

Laikoni
fuente
Errores en "\ n \ n"
Angs
@ Angulos Buena captura. Afortunadamente, OP aclaró que la entrada contains at least one character that is neither a newline nor a space, que también permite descartar el caso de la lista vacía.
Laikoni
Oh, bien, no me di cuenta de que se agregaba
Angs
2

MATL , 13 bytes

ctgF6Lt&()32>

La entrada es una matriz de cadenas, en el formato {'abc' 'de'}.

La salida es una matriz que contiene solo unos, que es verdadera , o una matriz que contiene al menos un cero, que es falsey .

Pruébalo en línea! O verifique todos los casos de prueba , incluida la prueba de veracidad / falsedad.

Explicación

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
Luis Mendo
fuente
11 bytes: ¡ cO6Lt&(32=~ Pruébelo en línea! Simplemente anula las partes no fronterizas, luego verifica si hay espacios.
sundar - Restablecer Monica
@sundar Buena idea! Eso es lo suficientemente diferente, publíquelo usted mismo
Luis Mendo
1
No, se siente demasiado similar a tu respuesta, especialmente si la escribo como cF6Lt&(32=~. Siéntase libre de editarlo, o si no podemos dejarlo en los comentarios.
sundar - Restablecer Monica
1

JavaScript (ES6), 88 bytes

s=>!s.split`\n`.some((s,i,a)=>s[L='length']-a[0][L]|(++i%a[L]>1?/^\s|\s$/:/\s/).test(s))

Pruébalo en línea!

Arnauld
fuente
1

Lienzo , 17 15 bytes

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

Pruébalo aquí!

Explicación (ASCII-fied para monoespacio):

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
dzaima
fuente
44
Me parece irónico que estos caracteres UTF8 en una fuente tipo monoespacio den la sensación de que hay muchos espacios en la fuente. (Al menos, lo hacen en mi navegador).
Arnauld
1
Los caracteres de ancho completo de @Arnauld hacen eso. Y es por eso que hice una fuente para mi intérprete para hacerlos más bonitos: p
dzaima
1

Perl 5 , 70 bytes

$f||=$_;$l||=y///c;$,||=/^\s|\s$/||$l-y///c;$e=$_}{$\="$f$e"=~/\s/||$,

Pruébalo en línea!

Salidas 0para la verdad, cualquier otro número para falsey.

Xcali
fuente
1

Rojo , 216191 bytes

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]

Pruébalo en línea!

Puse muchos paréntesis que de otra manera no serían necesarios en la primera y última fila.

Galen Ivanov
fuente
0

Jalea , 17 bytes

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

Pruébalo en línea!

Erik el Outgolfer
fuente
@ JonathanFrech Ah, arreglado. > _>
Erik the Outgolfer
@MagicOctopusUrn ¿Eh? ¿Puede vincular a una entrada donde esto no se comporta correctamente?
Erik the Outgolfer
Oh, no, llamaste a la mía porque Does not seem to enforce equal line lengtheso es todo lo que estaba diciendo.
Magic Octopus Urn
No parece funcionar para ¡ " \n " Pruébelo en línea!
Angs
1
@ Angs Intenta citarlo . Aparentemente se analiza como nada si lo pones así.
Erik the Outgolfer
0

Jalea , 15 bytes

Utiliza un método desarrollado por Mnemonic en un envío Pyth eliminado (actualmente, debido a un fallo de caso límite). (si ahora está arreglado, ¡ ve a dar algo de crédito !)

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

Un enlace monádico que acepta una lista de caracteres que devuelve 1 o 0.

Pruébalo en línea!

¿Cómo?

Ỵµ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)
Jonathan Allan
fuente
@Mnemonic - Jelly-fied :)
Jonathan Allan
0

Japt , 22 bytes

Respuesta no competitiva: hay un error conocido en Japt , donde las rotaciones de matriz bidimensionales truncan los resultados. Debido a ese error, el siguiente código solo funciona en entradas que son cuadradas. Sin embargo, si el error no estaba presente, el código a continuación debería funcionar completamente correctamente.

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.

Toma la entrada como una matriz de cadenas. El uso de paréntesis en lugar de espacios hace que el requisito del código rectangular sea bastante fácil.
Probar aquí .

Liendre
fuente
0

Ruby 2.5+, 63 bytes

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

Toma la entrada como una matriz de cadenas. Sin enlace de prueba, ya que la versión en TIO (2.4) es demasiado antigua para esta. En cambio, aquí hay una versión un poco más larga (69 bytes) para probar:

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

Pruébalo en línea!

La diferencia es que desde 2.5 Ruby admite pasar directamente un patrón Regex a los all?, any?, none?métodos, lo que nos ahorra algunos bytes. El método en sí mismo se explica por sí mismo: probamos:

  1. Si solo hay 1 tamaño de línea único
  2. Si hay espacios en los límites de la línea
  3. Si hay espacios en la primera y última línea.
Kirill L.
fuente
0

C (gcc) , 119 bytes

Toma la entrada como una lista (s) de n cadenas.

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

Pruébalo en línea!

gastropner
fuente
0

C # (.NET Core) , 145 167 bytes

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;

Pruébalo en línea!

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
Hille
fuente
No hay espacios en la primera línea.
FrownyFrog
@FrownyFrog S[0].IndexOf(" ")está buscando un espacio en la primera línea y S[S.Count()-1].IndexOf(" ")está buscando en la última línea. Si no hay espacio en la primera y última línea, es -2, que es cierto en -2 < -1.
Hille
2
Me refiero al desafío, su código tiene la misma restricción, por lo que no puede tener espacios en la primera línea.
FrownyFrog
1
Su código debe regresar Truecuando se pasa a su programa. Es una restricción adicional en este desafío.
FrownyFrog
1
Continuemos esta discusión en el chat .
Hille