Verificando uma cobra ASCII horizontal


22

Recentemente, houve alguns desafios ASCII para cobras de estimação (por exemplo, aqui )

            0 0               
  0        0 0 000            
00 0     00       000 0      0
    000 0            0 0   00 
       0                000   

Esse desafio é pegar uma cobra de estimação horizontal gerada aleatoriamente (altura de cinco linhas, comprimento de 30) e verificar se:

  • Cada coluna possui apenas um 0
  • Cada 0um deles é "conectado" ao 0antes e depois (espaçado verticalmente apenas por 0 ou 1 linha)

O resultado final pode ser trueou 1se a cobra é válida falseou 0se a cobra é inválida

Editar - Esclarecimento

Suponha a entrada:

  • É uma string
  • Contém apenas '', '0' e '\ n'
  • Tem exatamente 30 caracteres cada linha
  • Tem exatamente 5 linhas

Ou seja, verifique se a cobra está conectada e se não há caracteres perdidos. Não há necessidade de validar a "tela" em que a cobra está impressa.


4
Olá e bem-vindo ao PPCG :) Esse é um bom desafio para um primeiro post, mas você provavelmente deseja adicionar mais alguns casos de teste que capturam cobras excepcionais. Você provavelmente também desejará decidir se a cobra deve ser representada por zeros ou se pode ser algum personagem. No futuro, considere usar a sandbox . Boa sorte :)
FryAmTheEggman 22/02

5
Isso é tomado como uma picada? Ou pode ser inserido como uma matriz 2D?
JSchiff

6
Temos a garantia de que a entrada consiste em 0 e espaços? Que cada linha tem um comprimento de 30? Que existem 5 linhas?
Xnor

9
Uma vez que este é um problema de decisão, que tal truthy/falseye não true/false?
Jonathan Allan

3
@JSchiff Tenho certeza de que uma cobra Bytes?
MarioDS 22/02

Respostas:


14

JavaScript (ES2018), 62 54 bytes

s=>!/0(.{30}|.{60,62}(.{31})*)0|( .{30}){4} /s.test(s)

Entrada é uma única sequência:

  • sem rastrear nova linha
  • contém apenas espaço, '0' e '\ n'
  • 30 caracteres cada linha, 5 linhas, 154 caracteres no total

Sinalizador ssignifica que um ponto corresponde a qualquer coisa (incluindo '\ n'). Este recurso actualmente suportados pelo Chrome 63+, 50+ Opera, Safari 11.1+, com base em compat-mesa . Você pode testar esta função com estes navegadores suportados. Você receberá uma exceção ao carregar a página se o seu navegador não suportar esse recurso.

Como funciona:

  • Nenhuma coluna sem 0:
    • não combina /( .{30}){4} /
  • Não há dois 0s em uma coluna:
    • não combina /0.{30}(.{31})*0/
  • Não, 0não conecte-se a seus vizinhos:
    • não combina /0.{60}(.{31})*0/,/0.{62}(.{31})*0/

Mesclar todos esses regex, e você finalmente terá este.

Graças a Martin Ender, observe que um único !operador pode economizar 8 bytes.


8

SnakeEx , 51 bytes

Esse é obviamente o idioma certo para a tarefa. : ^ D

s:({c<L>}{c<R>}0[(<R> <L>)(<L> <R>)_?])%{30}
c:0 *$

Corresponde a entrada inteira se for uma cobra válida; falha em corresponder se não estiver. Experimente aqui!

Explicação

SnakeEx é uma linguagem de correspondência de padrões 2D . Um programa consiste em uma lista de definições para "cobras", que rastreiam os caracteres correspondentes de entrada, mudam de direção e geram outras cobras. Em nosso programa, definimos duas cobras, se c.

Vamos começar cporque é mais simples. Sua definição é 0 *$, que deve ser bastante legível se você souber regex: match 0, seguido por zero ou mais espaços, seguido pela borda da grade. O principal problema aqui: essa correspondência pode prosseguir em qualquer direção. Vamos usar para ccima e para baixo da cobra, para verificar se não há 0s extras em cada coluna.

Agora para a cobra principal s,. Ele assume a forma (...)%{30}, que significa "combinar o conteúdo dos parênteses 30 vezes" - uma vez para cada um 0na cobra. Por enquanto, tudo bem. O que se passa dentro dos parênteses?

{c<L>}

Isso gera uma nova ccobra, virou à esquerda 90 graus. A direção é relativa à sdireção da cobra, então a nova cobra se move em direção ao topo da grade (a cobra principal está se movendo em direção à direita). A ccobra verifica se a célula da grade atual é uma 0e se todas as células acima dela são um espaço. Se falhar, a correspondência inteira falhará. Se for bem-sucedido, continuamos com

{c<R>}

que faz a mesma coisa, apenas virou à direita (na parte inferior da grade).

Observe que esses spawns não afetam a posição do ponteiro da partida na cobra principal. Eles são um pouco parecidos com lookaheads no regex. (Talvez aqui possamos chamá-los de "lookbesides"?). Depois de verificar se estamos apontando para ae 0o restante da coluna contém apenas espaços, precisamos realmente corresponder a 0:

0

Agora, o ponteiro da partida está no caractere à direita do 0. Precisamos verificar três opções diferentes: a cobra inclina-se para baixo, a cobra inclina-se para cima ou a cobra segue em linha reta. Para isso, podemos usar uma expressão OR:

[...]

Dentro da nossa sala de cirurgia, temos três possibilidades:

(<R> <L>)

Vire à direita, combine um espaço e vire novamente à esquerda (ângulos de cobra para baixo).

(<L> <R>)

Vire à esquerda, combine um espaço e vire à direita novamente (a cobra está inclinada para cima).

_?

Corresponder zero ou um sublinhado. Como não há sublinhados na entrada, sempre será uma correspondência vazia (a cobra vai direto).

Depois de corresponder a uma das três opções acima, o ponteiro de correspondência deve estar apontando para o 0na próxima coluna, pronto para corresponder à expressão entre parênteses novamente.


2

CJam , 35 34 bytes

{z_{'0e=1=}%:*\'0f#2ew::-[W0X]-!*}

Experimente online! Entrada é uma matriz retangular de matrizes de caracteres. Assume que a entrada contém apenas e 0.

Explicação:

{z_{'0e=1=}%:*\'0f#2ew::-[W0X]-!*}   Function taking a character matrix:
 z                                      Transpose.
   {      }%                            Consider whether each row
      e=                                  contains
        1=                                exactly one
    '0                                    of the character '0'.
            :*                            This must be true for every row.
                  #                     Next, find the position
               '0                         of the character '0'
                 f                        at every row
  _           \                           in the original input.
                       :-               Find the differences between
                      :                   each
                   2                      pair
                    ew                    of adjacent elements (in other words, compute
                                            the increments).
                                        For the snake to be valid, this array of increments
                                            must only contain {0, 1, -1}, so
                              -         Remove from this list
                         [   ]            the elements
                          W                 -1,
                           0                0,
                            X               and 1,
                               !          and then check whether the array is empty.
                                *       The previous code tested two different properties
                                          of the matrix; they both must be true for a
                                          valid snake.

2

05AB1E , 18 bytes

ζDε0k}¥Ä2‹sεþg}ìPΘ

Experimente online!

Explicação

ζ                    # transpose
 D                   # duplicate
  ε  }               # for each row in the first copy (column of input)
   0k                # get the index of the first 0
      ¥Ä             # calculate absolute delta's
        2‹           # check that each is less than 2
          sε  }      # for each row in the second copy (column of input)
            þg       # calculate the length of the string with non-digits removed
               ì     # concatenate the lists
                P    # calculate product
                 Θ   # truthify (turn false values to 0)

2

Casca , 12 bytes

Dependendo dos esclarecimentos da regra, pode ser de 11 bytes ou 13 bytes .

±Λ=;1Ẋ×≈mηfT

Experimente online!

Entrada é uma lista de linhas contendo apenas espaços e 0s; se uma única sequência for necessária, anteceda o programa para dividir em linhas. O link TIO já faz isso para maior clareza. A saída é 0 ou 1; se algum valor falso e verdadeiro estiver correto, ele ±poderá ser removido.

Explicação

±Λ=;1Ẋ×≈mηfT  Implicit input: a list of lines.
           T  Transpose into list of columns.
        m     For each column,
         ηf   get list of indices of truthy elements.
              In Husk, whitespace characters are falsy and other are truthy,
              so this gets us the indices of 0s on each column.
     Ẋ        For each adjacent pair of these index lists,
      ×       for all pairs drawn from the two lists,
       ≈      give 1 if they differ by at most 1, otherwise 0.
              For each adjacent pair, this produces a list of 1s and 0s.
 Λ            Do all of these lists
  =;1         equal [1]? Return either 0 or 30 (length of the outer list + 1).
±             Signum; convert to 0 or 1.

A idéia é usar ×≈para garantir que (a) todas as colunas contenham precisamente um 0 e (b) suas posições diferam em no máximo uma. Como exemplo, considere a entrada de 8 colunas

0  0  0 
 000 0  
  00   0

Primeiro, mηfTtransforma-o na lista de listas de índices

[[1],[2],[2,3],[1,2,3],[],[2],[1],[3]]

Então Ẋ×≈

[[1],[1,1],[1,1,0,1,1,1],[],[],[1],[0]]

Cada um 1corresponde a um par de índices que diferem no máximo 1 e cada um 0corresponde a um par que não. Cada resultado é igual a [1]precisamente quando ambas as listas têm um índice e os índices diferem em no máximo 1.


2

Python 2 , 71 bytes

f=lambda s:s[1]<' 'or'0'in s[::31]in' %s '%s[1::31]in'%6s'%0*2*f(s[1:])

Experimente online!

Recebe a entrada como uma sequência multilinha. Caso de testes do Bubbler .

A primeira coluna é extraída como s[::31]e a segunda como s[1::31]e são verificadas quanto à validade. Recorremos ems remover o primeiro caractere, fazendo com que pares sucessivos de colunas sejam verificados.

A verificação de duas colunas usa o encadeamento de comparação do Python para incombinar várias verificações:

  • '0'in s[::31] verifica se a primeira coluna possui pelo menos um 0
  • s[::31]in' %s '%s[1::31] verifica se a primeira coluna é uma subcadeia da segunda coluna entre dois espaços, o que garante a posição do 0 deslocamento tenha mudado no máximo um espaço
  • ' %s '%s[1::31]in'%6s'%0*2verifica se a segunda coluna contém no máximo uma 0.

O final *f(s[1:])também força o caso recursivo a ser verdadeiro.


Agora que penso nisso, o Python é uma linguagem incrível para esses desafios de "cobra". : P
BigodeMeses

2

C (gcc) ,246 245 232 215 212 bytes

#define F)exit(1);
#define L for(i=l=0;i<30;i++)
#define X b[7][i]
char b[8][31];k,j,l;main(i){for(;j++<5;){gets(b);L{if(i[*b]>47){if(X++F memset(b[j+1]+i-1,l=1,3);}else if(!X&b[j][i]F}k+=!!l;}if(k<5 F L if(!X F}

Experimente online!

Achei que eu levaria meu idioma favorito para isso (embora, como eu possa ver em muitas outras entradas menores, provavelmente esteja longe de ser ideal para esse tipo de desafio) e C, o que eu poderia gerenciar. A abordagem do programa para o problema é relativamente direta, apenas com muitos bytes de bytes; pega a cobra no stdin e dá seu resultado no valor de retorno de main (assim, o código de saída;conforme solicitado no problema 0 indica uma cobra inválida e 1 válida, mesmo que para um código de saída estranhocomo é típico para os códigos de saída 0 é uma cobra válida e 1 é uma cobra inválida). Com as macros expandidas e alguns espaços em branco, parece mais com o seguinte:

char b[8][31];l,j,k;                           //Declares a buffer to work in, initialized all to 0; l j and k default to int and as globals are init to 0
main(i) {                                      //This is run no-args, so argc is 1 and the undeclared type defaults to int.
  for (; j++ < 5;) {                           //Iterating over each row, 1-indexed for convenience accessing the buffer
    gets(b);                                   //Reads into b[0] because of stack array decl layout
    for (i = l = 0; i < 30; i++) {             //j and l both init each time we begin this overall loop
      if (i[*b] > 47) {                        //Did we read a zero?
        if(b[7][i]++) exit(1);                 //If the snake already had a zero in this column, fail out
        memset(b[j+1] + i-1, l = 1, 3);        //Expect them on the next row in the columns left and right of this one (also set l)
      } else if (!b[7][i] & b[j][i]) exit(1);  //If we didn't read a zero, and we had reason to expect one this row, and there wasn't already a zero in this column, fail out
    }
    k+=!!l;                                    //Adds 1 to k iff l is nonzero 
  } if (k < 5) exit(1);                        //If less than 5 rows had zeroes in them, fail out
  for(i = l = 0 ; i < 30; i++) {               //l isn't relevant in this loop but saves some bytes when sharing a macro with the other horizontal loop
    if(!b[7][i]) exit(1);                      //If any columns didn't have zeroes, fail out
  }                                            //Else, snake is valid. main default returns 0.
}

As linhas de entrada são lidas na primeira linha do buffer, as próximas cinco são para rastrear quais locais devem (zerar: devem) ter zeros na linha após cada atual e a última é para rastrear se um zero já foi lido em uma determinada coluna, em qualquer linha. O programa processa cada linha por vez.

Não é nada robusto (gets() é apenas o começo) e a entrada deve conter todos os espaços relevantes (sem espaços em branco à esquerda, por exemplo), e o gcc envia avisos e notas sobre a funcionalidade stdlib deixada implicitamente declarada e assim por diante, mas C la vie.

Ele também assume que a cabeça da cobra não precisa estar na linha central e que uma cobra válida deve ter pelo menos um zero em cada linha (ou seja, nenhuma linha de todos os espaços nas 5 linhas de entrada). Se o último não for um requisito, pode ser um pouco mais curto - tudo a ver com ke lno programa pode ser reduzido ou substituído por menos bytes de código nesse caso.

Agradecimentos a user202729 por aprox. 26 bytes salvos.



Você pode deixar de fora o espaço entre #define Fe )para -1 byte.
user202729

Além disso, como a entrada possui apenas \n(10), <space>(32) e 0(48), é possível verificar ==48com >47(-1 byte). / Você pode remover o ={0}quando inicializar bse a variável for global. Da mesma forma, torne kglobal e ium intparâmetro (sem tipo -> ) de main(no lugar do argcqual é 1).
user202729

Obrigado! Editado antes de ver as últimas sugestões; Vou assinalar o meu caminho através deles (que icomo argcé um gênio). Os primeiros rascunhos disso tinham mais de 400 bytes; demorei o suficiente apenas para arrastá-lo para meus objetivos pessoais de 300 e 256, para que possa haver mais maneiras de reduzi-lo que eu perdi.
SevenStarConstellation 23/02

Decidi fazer k, je ltodos os globais para economizar em ter intdeclarações separadas , depois percebi que os padrões me permitiriam deixar de lado o tipo completamente. Obrigado novamente!
SevenStarConstellation

1

MATL , 18 17 bytes

32>&fun30=wd|2<vA

A entrada é uma matriz de caracteres 2D. Qualquer caractere não espacial pode ser usado para a cobra.

Experimente online!

Explicação

32>      % Implicit input. Transform non-space into 1, space into 0
&f       % Push vector of row indices and vector of column indices of nonzeros
u        % Unique: vector of deduplicated entries
n        % Length
30=      % Does it equal 30? (*)
w        % Swap. Moves vector of row indices to top
d|       % Absolute consecutive differences
2<       % Is each value less than 2? (**)
v        % Concatenate results (*) and (**) vertically
A        % All: true if all entries are nonzero. Implicit display

1
A especificação implica que os comprimentos de linha sendo 30 são garantidos, então eu acho que você pode economizar alguns.
Jonathan Allan

@JonathanAllan Thanks! Estou usando un30=para verificar se todos os índices da coluna são diferentes e nenhuma das 30 colunas está vazia. Talvez eu possa testar isso mais diretamente, mas não vejo como
Luis Mendo


1

Geléia , 19 bytes

Zn⁶T€L€=1$$;FIỊ$$$Ạ

Experimente online!

-2 bytes graças ao Sr. Xcoder

Explicação

Zn⁶T€L€=1$$;FIỊ$$$Ạ  Main Link
Z                    Transpose the matrix of characters
                         (string -> list of chars in Jelly)
 n⁶                  != " " (vectorizing)
   T€                For each column, get (row) indices of snake parts
     L€=1$$          For each index list, is its length 1? (that is, exactly one snake part per column)
           ;     $   Append (helper part)
            FIỊ$$    helper part:
            F        flatten index list
             I       get increments/forward differences
              Ị      are the values insignificant? (|z| <= 1)
                  Ạ  Are these all true?

Entrada é como uma lista de strings


@ Mr.Xcoder Huh falhar, questões de representação de cadeia de geléia lol. corrigido por ungolfing o byte 1
HyperNeutrino 22/02

1

Geléia , (14? *) 13 bytes

Zn⁶T€z-IỊ0-¦Ȧ

Um link monádico que obtém uma lista de cinco cadeias *, cada uma com comprimento 30 que consiste em espaços e quaisquer outros caracteres (por exemplo, 0s) e retorna um número inteiro (1 se uma cobra como definida, 0 caso contrário)

* Se a entrada precisar ser uma única sequência (lista de caracteres), adicione um para dividir a sequência nos feeds de linha.

Experimente online!

Quão?

Zn⁶T€z-IỊ0-¦Ȧ - Link: list of lists of characters, Lines
Z             - transpose the lines -> columns
  ⁶           - literal space character
 n            - not equal? -> 0 where there were spaces and 1 where there were "0"s
   T€         - truthy indices for each -> e.g. [0,0,1,0,0] -> [3] or [0,1,1,0,0] -> [2,3]
              -                           note: [0,0,0,0,0] -> []
      -       - literal minus one
     z        - transpose with filler (-1) -> {valid: a single list of heights {top:1,...,bottom:5}
              -                              invalid: list of >1 lists, some of which contain -1
              -                                       ...OR an empty list (no 0s in the input at all)}
       I      - differences -> {up:-1; down:1; flat:0; invalid:-6,-5,...,-2,2,...4}
        Ị     - insignificant (abs(z)<=1) -? {up/down/flat:1; invalid:0}
           ¦  - sparse application///
         0    - ...action: literal zero
          -   - ...to indices: [-1] -> make penultimate list into a zero (when one exists)
            Ȧ - any & all -> when flattened:{empty or contains a 0:0; otherwise:1}

Eu pensei que tinha tentado todos os casos extremos, obrigado pelo aviso; terá que resolver mais tarde.
Jonathan Allan

@LuisMendo heh e ao consertar que eu salvei três, então obrigado novamente!
Jonathan Allan

... mas eu apresentei outro. Corrigido outro 3 :(
Jonathan Allan

Não é um mau byte-count embora :-)
Luis Mendo

1

Stax , 20 bytes CP437

Å┴m▐◘5)ît╢V¼≥+╝╜►º½ê

24 bytes quando descompactado,

LM{'0|Ic%vChm:-{Jh!f%29=

Execute e depure online!

Pode não ser o melhor jogador de golfe, mas acho que o método é novo e interessante.

Explicação

LM                          Load the input string as a 2d array of characters, and transpose it

  {         m               Map array with block
   '0|I                     Get all indices of substring "0"
       c%vC                 Map to nothing if the indices are not unique
           h                Otherwise map to the unique index

             :-             Take pairwise difference

               {   f        Filter array with block
                Jh!         Only keep 0, 1 and -1

                    %29=    Check whether the final array has exactly 29 elements

1

J , 38, 37 30 bytes

-8 bytes graças ao FrownyFrog

[:($e.~[:(-:*)2-/\])@:I.'0'=|:

Experimente online!


1
Que tal [:(-:*)2-/\, verifique se todas as diferenças são -1, 0 ou 1.
FrownyFrog 23/02

@FrownyFrog Sim, é muito melhor! Obrigado!
Galen Ivanov

@ FrownyFrog Hmm, eu não percebi isso. Vou tentar consertar isso. Obrigado por apontar isso.
Galen Ivanov

1
[:(#@{.=[:(-:*)2-/\])@:I.'0'=|:
FrownyFrog

1
Ah, isso também funciona #[:($e.~[:(-:*)2-/\])@:I.'0'=|:
21008 FrownyFrog

1

Gelatina , 16 bytes

Zµi€”0IỊ;ċ€⁶=4ƊẠ

Experimente online!

Supõe que a sequência de entrada sempre contenha apenas espaços e zeros. Recebe a entrada como uma lista de seqüências de caracteres (cada uma representando uma linha) e gera 1 se for verdade, 0 caso contrário.

Explicação

Zµi€”0IỊ;ċ€⁶=4ƊẠ | Monadic full program.
Z                | Transpose.
 µ               | Start a new monadic chain.
  i€”0           | Retrieve the first index of 0 in each column.
      IỊ         | Check whether their increments are insignificant (element-wise).
        ;     Ɗ  | Append the result of the following:
         ċ€⁶     | In each list of characters, count the occurrences of a space.
            =4   | Check whether they equal 4 (returns a boolean array).
               Ạ | All. Check whether all the elements are truthy.

0

Python 2 , 141 bytes

lambda g:(lambda a:all(map(len,a)+[-2<x-y<2 for b in[sum(a,[])]for x,y in zip(b,b[1:])]))([[i for i in range(5)if"0"==r[i]]for r in zip(*g)])

Experimente online!

Entrada é uma grade de caracteres.


0

Python 2 e Python 3 , 122 120 119 bytes

lambda s:s.count('0')<31and all(s[i-31*(i>30):31*(i<124)-~i:31].strip(' ')for i,x in enumerate(s,1)if' '<x)and' '<s[62]

Experimente online!

O formato de entrada é uma sequência de comprimento 154 (5 x 30 caracteres, 4 novas linhas):

'''
            0 0               
  0        0 0 000            
00 0     00       000 0      0
    000 0            0 0   00 
       0                000   '''[1:] # to exclude starting newline

Se a cabeça não precisar ser a linha central

O requisito de cabeça de linha central estava no desafio original, mas descobri que não é o caso aqui (pelo menos, não é mencionado explicitamente).

Python 2 e Python 3 , 124 123 bytes

lambda s:s.count('0')<31and all(s[i-31*(i>30):31*(i<124)-~i:31].strip(' ')for i,x in enumerate(s,1)if' '<x)and'0'in s[::31]

Experimente online!


Editar:

  • 2 bytes reduzidos alterando iguais (== ) em desigualdades para cada código.
  • Encontrou erros na versão menos limitadora e a revisou. (Felizmente, não é tão terrível, então eu poderia manter todas as versões similares.) Você pode ver casos de teste adicionais nos dois últimos links TIO.
  • Encontrou um byte danificado nas soluções Py2, tornando o all()truque sem sentido no Py3, então fundiu as duas versões.

0

Excel (VBA), 68 bytes

Usando Janela Imediata, Cell[A6]como saída.

[A1:AD5]="=CHOOSE(ROUND(RAND()+1,),0,"""")":[A6]="=COUNT(A1:AD5)=30"




0

JavaScript (Node.js) , 128 126 bytes

Editado após o esclarecimento da entrada, informando que a entrada é "uma sequência".

F=(a,l=29,r=0,t=/^( *)0 *$/.exec(a.split`
`.map(p=>p[l]).join``),q=t&&~t[1].length)=>q&&(s=q-(r=r||q))>-2&s<2?l?F(a,l-1,q):1:0

Experimente online!


0

Python 3 , 197 185 bytes

No prompt de comando do verify.py<snake.txtou no bash docat snake.txt | python verify.py . Onde snake.txtestá um arquivo que contém uma cobra para verificar.

Se a cobra estiver correta, nada será produzido. Se não estiver correto, o Python gerará um erro de índice.

import sys
s=sys.stdin.read().split("\n")
x=0
exec('t,y="",0\nwhile y<5:t+=s[y][x];y+=1\ns+=[t];x+=1;'*30)
s=list(map(lambda l:len(l.rstrip()),s))
while y<35:"ee"[abs(s[y]-s[y+1])];y+=2

Ah, não percebi que minha saída tinha que ser verdadeira ou falsa. O código de erro retornado conta?
BigodeMoses

Golfed 12 bytes.
BigodeMoses
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.