Rileva testo rettangolare con codice rettangolare


19

Data una stringa di testo ASCII stampabile (inclusi righe e spazi nuovi) che contiene almeno un carattere che non è né una riga nuova né uno spazio, genera un valore di verità se la stringa è rettangolare e un valore di falsa in caso contrario. Inoltre, il codice sorgente per la soluzione deve essere rettangolare .

Una stringa è rettangolare se soddisfa tutte le seguenti condizioni:

  1. La prima riga e l'ultima riga non contengono spazi.
  2. Il primo e l'ultimo carattere di ogni riga non è uno spazio.
  3. Tutte le righe hanno lo stesso numero di caratteri.

Ad esempio, il seguente testo è rettangolare:

abcd
e fg
hijk

Questo testo, tuttavia, non è rettangolare (requisito n. 3):

1234
567
8900

Casi test

Truthy:

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

Questo è , quindi vince la soluzione più breve in byte.




9
Quindi, un one-liner senza spazio è una presentazione valida, giusto?
Arnauld,


1
Possiamo prendere l'input come una matrice di stringhe, una per ogni riga? Oppure dobbiamo inserire una singola stringa lunga che include le interruzioni di riga?
BradC,

Risposte:


12

C (gcc) , 127 125 124 118 byte

  • Salvato due byte giocando r*=!e&(!t|t==c);a r>>=e||t&&t-c;. (Questo golf è stato l'ispirazione per i miei recenti suggerimenti C in risposta a aggiornamento inverso della bandiera .)
  • Salvato un byte giocando *(_-2)a _[~1].
  • Hai salvato sei byte giocando *_++-10||(...)a golf *_++<11?...:0e utilizzando lo zero segnaposto ...:0(che non viene utilizzato in modo costruttivo) per golfare l' c++incremento. Quei campi da golf hanno permesso un ulteriore rimescolamento del circuito.
  • Quando si possono usare più valori di falso, potrebbero essere possibili 114 byte .
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;}

Provalo online!

Layout della sorgente che raggiunge un rettangolo più alto.

Spiegazione

Di seguito viene descritta la versione lunga 124 byte.

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

Provalo online!


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

4

Java 10, 214 176 169 152 144 139 byte

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 byte grazie a @Neil .

Utilizza String[]ainvece di var a; return-r<0;invece di return r>0;; e ha aggiunto un commento //alla fine, quindi non ci sono spazi nella prima e nell'ultima riga.

Si noti che questo rettangolo è più corto di un input a riga singola, perché int r=1,...;dovrebbe essere sostituito int[]v{1,...};e tutti gli usi degli interi diventerebbero v[n](dove n è l'indice della variabile nell'array v).

Provalo online.

Spiegazione:

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

Ecco lo stesso programma di base con spazi ( 128 126 byte ):

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 byte grazie a @Neil .

Provalo online.



3

T-SQL, 237 207 byte

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

Uscite 1 per rettangolare, 0 altrimenti. Ho dovuto usare tonnellate di parentesi e parentesi extra per eliminare gli spazi, sono sicuro che ci sia un ampio margine di miglioramento.

Spiegazione :

In base alle nostre opzioni I / O consentite e ai chiarimenti nei commenti alle domande, l'input viene preso come righe separate in una tabella preesistente t . Poiché i dati in SQL sono intrinsecamente non ordinati, quella tabella include un campo di identità "numero di riga" i :

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

Fondamentalmente il mio SQL esegue 3 sottoquery, ognuna delle quali restituisce 0o in 1base ai 3 criteri del codice "rettangolare". Questi 3 valori vengono moltiplicati insieme, restituendo solo il 1codice che soddisfa tutti e 3.

MODIFICA : Combina i criteri 2 e 3 nello stesso SELEZIONA per risparmiare spazio

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)funzione è supportata solo da SQL 2017 e versioni successive. Avrebbero bisogno di versioni precedenti LTRIM(RTRIM(v)), che richiederebbero il riequilibrio delle file.

Una nota a caso: la LEN()funzione in SQL ignora gli spazi finali, quindi LEN('foo ') = 3. Per ottenere una lunghezza "vera" devi virare un personaggio fino alla fine, quindi sottrarne uno: P


3

C ++, 199 183 181 175 byte

Questa funzione modello accetta le linee come una raccolta di stringhe (che possono essere stringhe estese), passate come una coppia di iteratori.

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

Grazie all'utente Erroneous per avermi ricordato il back()membro di std::stringe per aver sottolineato che npos+1è zero.

Equivalente non golfato

L'unico vero golf è concatenare la prima e l'ultima riga in modo da poter eseguire un singolo findper gli spazi in quelli.

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

Programma di 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();});}",})
        ;
}

Questo può essere ulteriormente golfato a 183 byte con una larghezza della linea di 22, usando .find(' ')+1==0e s.back()invece di *s.rbegin().
Erroneo


2

Python 2 , 82 byte

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

Provalo online!

Invoke as f("abcd", "e fg", "hijk").


2

Haskell , 106 102 98 110 109 102 byte

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

Grazie a @nimi e @Laikoni per un byte ciascuno!

Provalo online!


2

Haskell , 79 byte

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

Provalo online! Accetta input come un elenco di righe.

Il modello g(x:r)= ...lega la prima riga a xe l'elenco (possibilmente vuoto) delle righe rimanenti a r. Quindi all((==(0<$x)).(0<$))rcontrolla se tutte le linee rhanno la stessa lunghezza di x(Utilizzando questo suggerimento ).

In caso contrario, la congiunzione &&cortocircuita e ritorna False, altrimenti viene valutata la parte destra. Lì viene creata una stringa che consiste xper la prima riga, last(x:r)per l'ultima riga di r(o nuovamente la prima riga nel caso rsia vuota) e (head<$>r)per il primo e (last<$>r)l'ultimo carattere di ogni riga. Per questa stringa, all(>='!')verifica che non contenga spazi (non possiamo utilizzarli a (>' ')causa della restrizione del codice sorgente).


Errori su "\ n \ n"
Angs

@Angs Buona cattura. Fortunatamente, OP ha chiarito che l'input contains at least one character that is neither a newline nor a space, che consente anche di eliminare il caso elenco vuoto.
Laikoni,

Oh bello, non ho notato che l'aggiunta
Angs

2

MATL , 13 byte

ctgF6Lt&()32>

L'input è una matrice di stringhe, nel formato {'abc' 'de'}.

L'output è un array contenente solo quelli, che è veritiero , o un array contenente almeno uno zero, che è falso .

Provalo online! Oppure verifica tutti i casi di test , incluso il test di veridicità / falsità.

Spiegazione

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 byte: cO6Lt&(32=~ provalo online! Annulla semplicemente le parti non di confine, quindi controlla se ci sono spazi.
Sundar - Ripristina Monica il

@sundar Buona idea! È abbastanza diverso, pubblicalo tu stesso
Luis Mendo il

1
No, mi sento troppo simile alla tua risposta, specialmente se la scrivo come cF6Lt&(32=~. Sentiti libero di modificarlo o, in caso contrario, possiamo semplicemente lasciarlo nei commenti.
Sundar - Ripristina Monica il

1

JavaScript (ES6), 88 byte

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

Provalo online!


1

Tela , 17 15 byte

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

Provalo qui!

Spiegazione (ASCII-fied per 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
Trovo ironico che questi personaggi UTF8 in un carattere monospaziale diano la sensazione che ci siano molti spazi nella fonte. (Almeno, lo fanno nel mio browser.)
Arnauld

1
I personaggi @Arnauld a tutta larghezza lo fanno. Ed è per questo che ho creato un font per il mio interprete per renderli più
belli

1

Perl 5 , 70 byte

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

Provalo online!

Uscite 0per la verità, qualsiasi altro numero per la falsità.


1

Rosso , 216 191 byte

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]

Provalo online!

Ho messo molte parentesi altrimenti non necessarie nella prima e nell'ultima riga.


0

Gelatina , 17 byte

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

Provalo online!


@JonathanFrech Ah, risolto. > _>
Erik the Outgolfer,

@MagicOctopusUrn Huh? Puoi collegarti a un input in cui questo non si comporta correttamente?
Erik the Outgolfer,

Oh, no, hai chiamato il mio perché Does not seem to enforce equal line lengthanche quello che stavo dicendo.
Magic Octopus Urn

Non sembra funzionare per " \n " Provalo online!
Angs,

1
@Angs Prova a citarlo. Apparentemente è analizzato come niente se lo metti così.
Erik the Outgolfer,

0

Gelatina , 15 byte

Utilizza un metodo sviluppato da Mnemonic in una trasmissione Pyth eliminata (attualmente - a causa di un errore del case-edge). (se è stato risolto, vai a dare un po 'di credito !)

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

Un collegamento monadico che accetta un elenco di caratteri che restituisce 1 o 0.

Provalo online!

Come?

Ỵµ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 byte

Risposta non competitiva: esiste un bug noto in Japt , in cui le rotazioni di array bidimensionali troncano i risultati. A causa di quel bug, il codice seguente funziona solo su input quadrati. Se il bug non era presente, tuttavia, il codice seguente dovrebbe funzionare in modo completamente corretto.

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.

Accetta input come una matrice di stringhe. L'uso delle parentesi al posto degli spazi rende abbastanza semplice il requisito del codice rettangolare.
Provalo qui .


0

Rubino 2.5+, 63 byte

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

Accetta input come una matrice di stringhe. Nessun link di test, poiché la versione su TIO (2.4) è troppo vecchia per questa. Invece, ecco una versione leggermente più lunga (69 byte) per il test:

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

Provalo online!

La differenza è che dal 2.5 Ruby supporta il passaggio diretto di un modello Regex ai all?, any?, none?metodi, il che ci consente di risparmiare qualche byte. Il metodo stesso è abbastanza autoesplicativo - testiamo:

  1. Se esiste solo 1 dimensione di linea unica
  2. Se ci sono spazi sui confini della linea
  3. Se ci sono spazi sulla prima e sull'ultima riga.

0

C (gcc) , 119 byte

Prende l'input come un elenco di n stringhe.

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

Provalo online!


0

C # (.NET Core) , 145 167 byte

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;

Provalo 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

Nessuno spazio nella prima riga.
FrownyFrog,

@FrownyFrog S[0].IndexOf(" ")sta cercando uno spazio nella prima riga e S[S.Count()-1].IndexOf(" ")sta cercando nell'ultima riga. Se non c'è spazio nella prima e nell'ultima riga, è -2 che è quindi vero su -2 < -1.
Hille,

2
Intendo la sfida, il tuo codice ha la stessa restrizione, quindi non puoi avere spazi nella prima riga.
FrownyFrog,

1
Il codice deve restituire una Truevolta passato al programma. È un'ulteriore limitazione in questa sfida.
FrownyFrog,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.