Detectar texto retangular com código retangular

19

Dada uma sequência de texto ASCII imprimível (incluindo novas linhas e espaços) que contém pelo menos um caractere que não é uma nova linha nem um espaço, produz um valor verdadeiro se a sequência for retangular e um valor falsey caso contrário. Além disso, o código fonte da sua solução deve ser retangular .

Uma cadeia de caracteres é retangular se atender a todas as seguintes condições:

  1. A primeira linha e a última linha não contêm espaços.
  2. O primeiro e o último caractere de cada linha não é um espaço.
  3. Todas as linhas têm o mesmo número de caracteres.

Por exemplo, o seguinte texto é retangular:

abcd
e fg
hijk

Este texto, no entanto, não é retangular (requisito nº 3):

1234
567
8900

Casos de teste

Verdade:

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

Isso é , então a solução mais curta em bytes vence.

Mego
fonte
Sandbox
Mego
2
Relacionado .
AdmBorkBork
9
Então, uma linha sem espaço é um envio válido, correto?
Arnauld
1
relacionado
Rod
1
Podemos considerar a entrada como uma matriz de strings, uma para cada linha? Ou devemos inserir uma única cadeia longa que inclua as quebras de linha?
BradC

Respostas:

12

C (gcc) , 127 125 124 118 bytes

  • Salva dois bytes jogando golfe r*=!e&(!t|t==c);em r>>=e||t&&t-c;. (Este golfe foi a inspiração para minhas recentes dicas em C, resposta à atualização inversa da bandeira .)
  • Guardou um byte jogando golfe *(_-2)em_[~1] .
  • Salvo seis bytes de golfe *_++-10||(...)para *_++<11?...:0e utilizando o marcador de zero ...:0(o que não é utilizado de forma construtiva) para golfe o c++incremento. Esses campos de golfe permitiram uma nova mudança de loop.
  • Quando se pode usar vários valores falsey, 114 bytes podem ser possíveis.
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;}

Experimente online!

Layout de origem atingindo um retângulo mais alto.

Explicação

A seguir, é apresentada a versão longa 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)`

Experimente online!

Jonathan Frech
fonte
10
+1 parar,e,c,t
Magic Octopus Urn
4

Java 10, 214 176 169 152 144 139 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 graças a @Neil .

Usa em String[]avez de var a; return-r<0;em vez de return r>0;; e adicionou um comentário //no final, para que não haja espaços na primeira e na última linha.

Observe que esse retângulo é mais curto que uma entrada de linha única, porque int r=1,...;deve ser substituída por int[]v{1,...};e todos os usos dos números inteiros se tornam então v[n](em que n é o índice da variável na matriz v).

Experimente online.

Explicação:

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

Aqui está o mesmo programa base com espaços ( 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 graças a @Neil .

Experimente online.

Kevin Cruijssen
fonte
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])))

Saídas 1 para retangular, 0 caso contrário. Eu tive que usar toneladas de parênteses extras e suportes para eliminar espaços, tenho certeza de que há um vasto espaço para melhorias.

Explicação :

De acordo com nossas opções de E / S permitidas e o esclarecimento nos comentários da pergunta, a entrada é tomada como linhas separadas em uma tabela preexistente t . Como os dados no SQL são inerentemente desordenados, essa tabela inclui um campo de identidade "número da linha" i :

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

Basicamente, meu SQL executa 3 subconsultas, cada uma das quais retorna 0ou1 base nos 3 critérios do código "retangular". Esses 3 valores são multiplicados juntos, retornando apenas 1para um código que satisfaça todos os 3.

EDIT : critérios combinados 2 e 3 no mesmo SELECT para economizar espaço

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

o TRIM(v) função é suportada apenas pelo SQL 2017 e acima. Seriam necessárias versões anteriores LTRIM(RTRIM(v)), o que exigiria reequilibrar as linhas.

Uma observação aleatória: a LEN()função no SQL ignora espaços à direita, então LEN('foo ') = 3. Para obter um comprimento "verdadeiro", você precisa prender um personagem até o final e subtrair um: P

BradC
fonte
3

C ++, 199 183 181 175 bytes

Essa função de modelo aceita linhas como uma coleção de seqüências de caracteres (que podem ser amplas), passadas como um 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();});}

Agradecemos ao usuário Erroneous por me lembrar o back()membro std::stringe por apontar quenpos+1 é zero.

Equivalente não destruído

O único verdadeiro golfe é concatenar a primeira e a última linhas, para que possamos executar uma única findpara espaços nessas.

#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 teste

#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
fonte
Isso pode ser aumentado para 183 bytes com uma largura de linha de 22, usando .find(' ')+1==0e em s.back()vez de *s.rbegin().
Erroneous
2

JavaScript (Node.js) , 85 bytes

x=>(x=x.split`\n`).some(s=>s.length-x[0].length|s.trim()!=s)<!/\s/.test(x[0]+x.pop())

Experimente online!

l4m2
fonte
@KevinCruijssen sorry :(
DanielIndie
Eu amo o seu NORoperador!
Neil
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])

Experimente online!

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

Lynn
fonte
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

Obrigado a @nimi e @Laikoni por um byte cada!

Experimente online!

Angs
fonte
2

Haskell , 79 bytes

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

Experimente online! Recebe a entrada como uma lista de linhas.

O padrão g(x:r)= ...vincula a primeira linha xe a lista (possivelmente vazia) das linhas restantes r. Em seguida, all((==(0<$x)).(0<$))rverifica se todas as linhas rtêm o mesmo comprimento de x(Usando esta dica ).

Caso contrário, a combinação provoca &&curto-circuito e retorna False, caso contrário, o lado direito é avaliado. Lá é criada uma string que consiste xna primeira linha, last(x:r)na última linha de r(ou na primeira linha novamente, caso resteja vazia) e (head<$>r)no primeiro e (last<$>r)no último caractere de cada linha. Para essa sequência, all(>='!')verifica se ela não contém espaços (não podemos usar (>' ')devido à restrição do código-fonte).

Laikoni
fonte
Erros em "\ n \ n"
Angs
@ Angs Boa captura. Felizmente, o OP esclareceu que a entrada contains at least one character that is neither a newline nor a space, que também permite descartar a lista vazia.
Laikoni
Oh, legal, não percebi que isso foi adicionado #
037 Angs
2

MATL , 13 bytes

ctgF6Lt&()32>

Entrada é uma matriz de seqüências de caracteres, no formato {'abc' 'de'}.

A saída é uma matriz que contém apenas as que são verdadeiras ou uma matriz que contém pelo menos um zero, que é falsey .

Experimente online! Ou verifique todos os casos de teste , incluindo teste de veracidade / falsidade.

Explicação

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
fonte
11 bytes: cO6Lt&(32=~ Experimente online! Apenas anula as partes que não são de borda e verifica se há espaços.
sundar - Restabelece Monica
@sundar Boa ideia! Isso é diferente o suficiente, poste você mesmo
Luis Mendo
1
Não, parece muito com a sua resposta, especialmente se eu escrever como cF6Lt&(32=~. Sinta-se à vontade para editá-lo ou, caso contrário, podemos simplesmente deixá-lo nos comentários.
sundar - Restabelece 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))

Experimente online!

Arnauld
fonte
1

Tela , 17 15 bytes

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

Experimente aqui!

Explicação (ASCII-fied for 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
dzaima
fonte
4
Acho irônico que esses caracteres UTF8 em uma fonte monoespaçada dê a sensação de que há muitos espaços na fonte. (Pelo menos, eles fazem no meu navegador.)
Arnauld
1
Caracteres de largura total @Arnauld fazem isso. E é por isso que eu fiz uma fonte para o meu intérprete para torná-los mais bonita: p
dzaima
1

Perl 5 , 70 bytes

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

Experimente online!

Saídas 0para verdade, qualquer outro número para falsey.

Xcali
fonte
1

Vermelho , 216 191 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]

Experimente online!

Coloquei muitos parênteses não necessários na primeira e na última linha.

Galen Ivanov
fonte
0

Geléia , 17 bytes

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

Experimente online!

Erik, o Outgolfer
fonte
@JonathanFrech Ah, corrigido. > _>
Erik the Outgolfer
@MagicOctopusUrn Huh? Você pode vincular a uma entrada em que isso não se comporta corretamente?
Erik the Outgolfer
Oh, não, você chamou o meu porque Does not seem to enforce equal line lengthtambém é tudo o que eu estava dizendo.
Magic Octopus Urn
Não parece funcionar para " \n " Experimente online!
Angs
1
@Angs Tente citá-lo. Aparentemente, é analisado como nada se você colocar assim.
Erik the Outgolfer
0

Gelatina , 15 bytes

Usa um método desenvolvido pela Mnemonic em um envio Pyth excluído (atualmente - devido a uma falha no caso de borda). (se já estiver consertado, dê algum crédito !)

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

Um link monádico que aceita uma lista de caracteres que retorna 1 ou 0.

Experimente online!

Quão?

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

Japt , 22 bytes

Resposta não-competitiva: há um bug conhecido no Japt , em que as rotações bidimensionais da matriz truncam os resultados. Devido a esse bug, o código abaixo funciona apenas em entradas quadradas. Se o bug não estava presente, o código abaixo deve funcionar completamente corretamente.

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.

Recebe entrada como uma matriz de seqüências de caracteres. Usar parênteses em vez de espaços facilita bastante o requisito de código retangular.
Experimente aqui .

Nit
fonte
0

Ruby 2.5+, 63 bytes

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

Recebe entrada como uma matriz de seqüências de caracteres. Nenhum link de teste, pois a versão no TIO (2.4) é muito antiga para este. Em vez disso, aqui está uma versão um pouco mais longa (69 bytes) para teste:

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

Experimente online!

A diferença é que, já que o 2.5 Ruby suporta a passagem direta de um padrão Regex aos all?, any?, none?métodos, o que nos salva alguns bytes. O método em si é bastante auto-explicativo - testamos:

  1. Se houver apenas 1 tamanho de linha exclusivo
  2. Se houver algum espaço nos limites da linha
  3. Se houver espaços na primeira e na última linha.
Kirill L.
fonte
0

C (gcc) , 119 bytes

Recebe a entrada como uma lista (s) de n strings.

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

Experimente online!

gastropner
fonte
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;

Experimente online!

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
fonte
Não há espaços na primeira linha.
FrownyFrog
O @FrownyFrog S[0].IndexOf(" ")está pesquisando um espaço na primeira linha e S[S.Count()-1].IndexOf(" ")na última linha. Se não houver espaço na primeira e na última linha, é -2, o que é verdadeiro em -2 < -1.
Hille
2
Quero dizer o desafio, seu código tem a mesma restrição, então você não pode ter espaços na primeira linha.
FrownyFrog
1
Seu código deve retornar Truequando passado para o seu programa. É uma restrição adicional neste desafio.
FrownyFrog