Programa de tabuleiro de damas triangular com validação automática

10

Um programa quadriculado é um programa em que o valor ordinal de cada caractere individual alterna de par para ímpar, excluindo o terminador de linha (que pode ser qualquer final de linha padrão).

Um programa triangular é um programa em que cada linha possui um caractere adicional que a linha anterior, com a primeira linha tendo um caractere. Você não precisa manipular entrada vazia.

Sua tarefa é construir um programa que valide que a entrada fornecida atenda a esses critérios e produza / devolve algo verdadeiro se o programa atender aos critérios ou algo falso de outra forma.

Seu programa também deve atender a esses critérios.

Exemplos de programas válidos

G
`e
@u^
5r{B

^
cB
+$C
VA01

Regras

  • Seu programa pode começar com um byte ímpar ou par, desde que a paridade dos caracteres se alterne.
  • Seu programa deve validar os programas que começam com um caractere ímpar ou par.
  • Para caracteres unicode, os valores de bytes subjacentes devem ter paridade alternada.
  • Você pode assumir que a entrada contém apenas caracteres imprimíveis. Se o seu programa contiver imprimíveis, ele ainda poderá se validar.
  • Seu programa pode incluir uma nova linha à direita. Isso não precisa ser permitido pela sua validação, pois você pode assumir que isso foi removido antes da validação.
  • As brechas padrão são proibidas.
  • O código mais curto em bytes, em cada idioma, vence.
Dom Hastings
fonte
@MartinEnder Obrigado pela sua contribuição! Espero que isso esteja claro agora. Relacionado a isso, devo deixar isso na sandbox por mais tempo?
Dom Hastings
11
é o par / ímpar alternando horizontal e vertical? Suponho que sim do "tabuleiro de damas", mas não vejo onde você diz isso.
Ton Hospel
@DomHastings Parece que uma semana está boa. Se você não receber comentários depois de alguns dias, poderá perguntar no bate-papo se alguém tiver mais comentários.
Martin Ender
11
@TonHospel Meus exemplos originais fez isso, mas contradiz com a minha descrição, portanto, para esta aplicação, não, que deve ser: E\nOE\nOEO. Espero que ajude!
Dom Hastings
2
Minha opinião: deixe as respostas assumirem que a entrada não começa ou termina com uma nova linha.
Lynn

Respostas:

3

Stax , 26 bytes

L
Y$
i:-
 {2%
*OFyF
%vi =*

Executar casos de teste online

Eu tive que introduzir 3 caracteres indesejados. ié um no-op quando está fora de todas as construções de loop. é sempre um não-op. Ocoloca 1 na parte superior da pilha, mas o valor não é usado no programa.

LY      move input lines into a list and store in Y register
$       flatten
i       no-op
:-      get pairwise differences
{2%*OF  foreach delta, mod by 2, and multiply, then tuck a 1 under the top of stack
yF      foreach line in original input do...
  %v    subtract 1 from length of line
  i=    is equal to iteration index?
  *     multiply

Execute este

recursivo
fonte
Ei, espero que isso não mexa muito com seu código, mas você pode descartar a validação líder de nova linha.
Dom Hastings
8

C (gcc), 189 bytes

j
;l
;b;
d;f␉
(char
␉*␉t) 
{b=*␉t%
2;for␉(␉
j=d=0;j=j
+ 1,␉l=j+ 
1,␉*␉t; ) {
for␉(;l=l- 1
 ;t=t+ 1 )b= 
!b␉,␉d=d+ !(␉*
␉t␉*␉(␉*␉t- 10)
*␉(␉*␉t%2-b) ) ;
d␉|=*␉t- 10;t=t+ 
1 ; }b= !d; } ␉ ␉ 

Experimente online!

representa um caractere de tabulação (me desculpe). Observe que existem vários espaços / guias à direita (me desculpe). O original com abas intactas é melhor visualizado no vim com :set tabstop=1(as palavras não podem expressar o quanto sinto muito).

É uma função (chamada f, que não é imediatamente óbvia ao olhar para ela) que pega uma string como argumento e retorna um 0ou outro 1.

Eu poderia reduzir isso em pelo menos uma e provavelmente duas ou mais linhas, mas observe que fica cada vez mais confuso e com pouco esforço no final, principalmente porque escrever um código tão horrível (mesmo para os padrões PPCG) estava me fazendo sentir como uma pessoa má e eu queria parar o mais rápido possível.

A idéia básica aqui é evitar construções que necessariamente quebrar o formato ( ++, +=, return, etc.). Milagrosamente, palavras-chave importantes como for, chare while(que eu não acabei usando) se encaixam na regra de paridade alternada. Então usei espaços (paridade par) e tabulações (paridade ímpar) como preenchimento para fazer o resto se encaixar nas regras.

Maçaneta da porta
fonte
11
Eu não esperava ver uma solução em C!
Dom Hastings
Se você isolar a parte da solução do programa no TIO, colocando outros itens nas seções "Cabeçalho" e "Rodapé", é mais fácil para as pessoas verificarem a contagem de bytes.
Jakob
4

Haskell , 1080 1033 bytes

;
f=
 g 
ij=f
a =hi
hi = g
hij= ij
g ' ' =0
g '"' =0;
 g '$' =0;
 g '&' =0-0
g '(' =0-0-0
g '*' =0-0-0;
 g ',' =0-0-0;
 g '.' =0-0-0-0
g '0' =0-0-0-0-0
g '2' =0-0-0-0-0;
 g '4' =0-0-0-0-0;
 g '6' =0; g '8' =0
g ':' =0; g '<' =0-0
g '>' =0; g '@' =0-0;
 g 'B' =0; g 'D' =0-0;
 g 'F' =0; g 'H' =0-0-0
g 'J' =0; g 'L' =0-0-0-0
g 'N' =0; g 'P' =0-0-0-0;
 g 'R' =0; g 'T' =0-0-0-0;
 g 'V' =0; g 'X' =0-0-0-0-0
g 'Z' =0; g '^' =0; g '`' =0
g 'b' =0; g 'd' =0; g 'f' =0;
 g 'h' =0; g 'j' =0; g 'l' =0;
 g 'n' =0; g 'p' =0; g 'r' =0-0
g 't' =0; g 'v' =0; g 'x' =0-0-0
g 'z' =0; g '\92' =0-0; g '|' =0;
 g '~' =0; g y = 1 ;z=0; i(-0)z=z;
 i m('\10':y ) ="y"; ; ; ; ; ; ; ; 
i m(mnmnmnmnm:y ) = i(m - 1 ) y ; ; 
i k m ="y"; ; k i [ ] =01<1010101010;
 k m('\10':y ) = k(m + 1 )(i m y ) ; ;
 k m y =01>10; m o = k 1$'\10':o ; ; ; 
o i('\10':y ) = o i y ; ; ; ; ; ; ; ; ; 
o i(k:y )|g k<i = o(1 - i ) y ; ; ; ; ; ;
 o i(k:y )|g k>i = o(1 - i ) y ; ; ; ; ; ;
 o i [ ] =01<10; o i y =01>10;v=01>10101010
s y|o 1 y = m y|o(-0) y = m y ; s y =v; ; ; 

Experimente online!

Explicação

Essa tem sido uma tarefa bastante interessante para Haskell.

Paridade

Para começar, precisamos de uma maneira de determinar se um personagem tem um ponto de código par ou ímpar. A maneira normal de fazer isso é obter o ponto de código e modificá-lo com 2. No entanto, como se pode saber, obter o ponto de código de um caracter exige uma importação, o que devido à restrição de origem significa que ele não pode ser usava. Um Haskeller mais experiente pensaria em usar recursão. Charfazem parte da Enumclasse para que possamos obter seus antecessores e sucessores. No entanto prede succtambém são ambos inutilizável porque eles não fazem paridade byte alternativo.

Então, isso nos deixa muito presos, praticamente não podemos fazer nenhuma manipulação com caracteres. A solução para isso é codificar tudo. Podemos representar (a maioria) caracteres pares como literais, probabilidades com as quais temos problemas porque 'é ímpar, por isso não pode estar ao lado do caractere, tornando o literal impossível de expressar a maioria dos caracteres ímpares. Portanto, codificamos todos os bytes pares e adicionamos uma captura de todos os bytes ímpares no final.

Bytes com problema

Você pode perceber que existem alguns bytes pares para os quais literais não podem ser feitos colocando-os entre aspas simples. Eles são os imprimíveis, as novas linhas e \. Não precisamos nos preocupar com imprimíveis, desde que não utilizemos nenhum deles, não precisamos verificar. De fato, ainda podemos usar estranhos não imprimíveis, como tab, simplesmente não preciso. A nova linha pode sabiamente ser ignorada, pois será cortada do programa de qualquer maneira. (Poderíamos incluir nova linha, porque seu ponto de código é bastante conveniente, mas não precisamos). Isso deixa \, agora \tem o ponto de código 92, que convenientemente é um número ímpar seguido por um número par, então \92alterna entre pares e probabilidades, portanto, o'\92'é perfeitamente válido. Mais tarde, quando precisarmos representar a nova linha, perceberemos que ela possui essa mesma propriedade '\10'.

Problemas de espaçamento

Agora, para começar a escrever o código real, precisamos poder colocar um número considerável de caracteres em uma única linha. Para fazer isso, escrevi o cap:

;
f=
 g 
ij=f
a =hi
hi = g
hij= ij

A tampa não faz nada, exceto ser Haskell válido. Inicialmente, eu esperava fazer definições que nos ajudassem no código mais tarde, mas isso não aconteceu. Também existem maneiras mais fáceis de fazer o limite, por exemplo, espaço em branco e ponto-e-vírgula, mas eles não salvam bytes por esse caminho, então não me preocupei em alterá-lo.

Hardcoder

Então agora que tenho espaço suficiente em uma linha, inicio a codificação dos valores. Isso é muito chato, mas há algumas coisas interessantes. Por uma vez, as linhas começam a ficar ainda mais longas, podemos usar ;para colocar várias declarações em uma linha, o que nos economiza uma tonelada de bytes.

A segunda é que, como nem sempre podemos iniciar uma linha de gvez em quando, precisamos recuar um pouco as linhas. Agora, Haskell realmente se importa com o recuo, por isso vai reclamar disso. No entanto, se a última linha antes da linha recuada terminar em ponto e vírgula, será permitida. Por quê? Eu não tenho o menor, mas funciona. Então, precisamos nos lembrar de colocar o ponto e vírgula no final das linhas.

Blocos de Construção de Função

Uma vez feito o codificador, é fácil navegar até o final do programa. Precisamos construir algumas funções simples. Primeiro eu construo uma versão do dropchamado i. ié diferente do dropque, se tentarmos ultrapassar o final da string, ela retornará "y". ié diferente de drop também, pois, se tentar soltar uma nova linha, retornará "y". Isso será útil porque mais tarde, quando verificarmos que o programa é um triângulo, isso nos permitirá retornar Falsequando a última linha não estiver concluída ou quando uma linha termina cedo.

kknssTruenkn+1 1False

Em seguida, fazer um alias para k, m. mé apenas kcom 1no primeiro argumento e uma nova linha é anexada ao segundo argumento.

Em seguida, temos o. opega um número e uma string. Determina se os bytes da string (ignorando novas linhas) se alternam em paridade (usando nossa g) começando com o número de entrada.

Por fim, temos o sque roda ocom ambos 1e 0, se um deles é bem-sucedido, ele adia m. Se falhar, apenas retorna False. Esta é a função que queremos. Determina que a entrada é triangular e alternada.

Caçador Ad Hoc Garf
fonte
11
Uma cadeia triangular começa com uma linha de 1 caractere, não uma linha vazia.
27418 Jakob
@ Jakob Eu acho isso idiota, mas foi uma solução fácil.
Ad Hoc Garf Hunter
3

05AB1E , 34 26 bytes

¶
¡D
©€g
´ā´Q
´sJÇÈ
¥Ä{´нP

Experimente online!

Aceita a entrada como uma sequência de linhas múltiplas (entrada entre "" " ). Explicações a seguir.

Kaldo
fonte
11
A menos que eu tenha entendido mal as regras, o programa precisa ser capaz de validar as entradas, começando também por uma nova linha.
Emigna
@ Emigna Acho que o seu programa deve ser capaz de validar uma nova linha principal apenas se começar com uma nova linha principal.
Ton Hospel
Não sei se isso está correto (sou péssimo em ler as especificações): Experimente online!
Urna de polvo mágico
@MagicOctopusUrn Sua resposta parece boa para mim, mas estou me perguntando sobre a entrada: podemos aceitá-la como uma matriz? No seu link, sua primeira entrada é um espaço vazio, não um caractere de nova linha.
Kaldo 16/03/19
11
Ei, espero que isso não mexa muito com seu código, mas você pode descartar a validação líder de nova linha.
Dom Hastings
1

Java 10, 209 bytes

Um lambda vazio tomando um iterável ou matriz de byte. Indica true retornando normalmente, false lançando uma exceção de tempo de execução. O programa espera que a linha final seja finalizada corretamente, ou seja, termine com um caractere de nova linha. A linha final do programa é encerrada da mesma forma.

Tudo é feito sob UTF-8, com a interpretação de que "caractere" se refere a pontos de código Unicode.

As guias são substituídas por espaços nessa exibição.

d
->
{  
long
f= 1,
 h=0 ,
c = - 1
,e ;for 
( byte a:
 d) {var b
=(e = a^10)
<1&e>- 1 ;f=
b?( h ^ f)> 0
?0/0 : f+ 1: f
;h=b?0 :a>-65 ?
h+ 1: h; c =b? c
:c>=0 & ( (c^a )&
1 )<1 ?0/0 :a ; } 
/*1010101010101*/ }

Experimente Online

Hex dump

Reverta com o xxd -p -rUnix.

640a2d3e0a7b20090a6c6f6e670a663d20312c0a09683d30092c0a63203d
202d20310a2c65203b666f72090a28096279746520613a0a096429207b76
617209620a3d2865203d20615e3130290a3c3126653e2d2031203b663d0a
623f280968095e0966293e09300a3f302f30093a09662b20313a09660a3b
683d623f30093a613e2d3635203f0a682b20313a09683b2063203d623f20
630a3a633e3d30092609280928635e612029260a3120293c31203f302f30
093a61203b207d200a2f2a313031303130313031303130312a2f207d0a

Ungolfed

d -> {
    long f = 1, h = 0, c = ~h, e;
    for (byte a : d) {
        var b = (e = a^10) < 1 & e > -1;
        f = b ?
            (h^f) > 0 ? 0/0 : f + 1
            : f
        ;
        h = b ? 0 :
            a > -65 ? h + 1 : h
        ;
        c = b ? c :
            c >= 0 & ((c^a) & 1) < 1 ? 0/0 : a
        ;
    }
}

fé o número esperado de caracteres na linha atual, hé o número de caracteres vistos até agora na linha atual, cé o último byte visto e bse aé a nova linha.

A condição a > -65testa se aé o primeiro byte em um caractere. Isso funciona porque os caracteres de byte único (ASCII) não são negativos no complemento de dois bits de 8 bits, o primeiro byte de caracteres mais longos possui formato binário 11xxxxxx(pelo menos -64 no complemento de dois) e os bytes não iniciais desses caracteres são de o formulário 10xxxxxx, no máximo -65 no complemento de dois. ( Fonte )

Quando um personagem viola o padrão triangular ou quadriculado (ou seja, uma nova linha aparece cedo ou tarde ou aparece um byte de paridade errada), o ramo esquerdo do ternário correspondente (na atribuição a fou c) é ativado e o método lança uma exceção aritmética.

Jakob
fonte
0

Python 3 (3,4?), 350 bytes

Um desafio complicado para uma linguagem específica sobre espaço em branco como o Python 3. O envio é impresso 0ou 1padronizado e trava para algumas entradas. O programa espera que a linha final seja finalizada corretamente, ou seja, termine com um caractere de nova linha. A linha final do programa é encerrada da mesma forma. UTF-8 é usado para verificar a paridade de bytes.

As guias são substituídas por espaços nessa exibição.

0
i\
= 1
t=(#
 '0'*
 0) ;(
g,) =(#
 open (1
, "w"),) 
k = eval (
'p' + 'rin'
 + 't' ) #01
for  a in (#0
open ( 0) ):#0
#01010101010101
 a = a [:- 1 ] #
 if ( len (a )<i\
or len (a )>i ):[\
k('0' ),1 /0] #0101
 i, t= -~i, t+ a #01
(k( 2-len ({(c^i )&1\
 for  i,c in  eval (#0
 "enu"+"m"+"erate")(#01
 eval ( " byte"+"s")( t#
,' u8' ) ) } ) ) ) #01010

Funciona para mim com o Python 3.4.2; não funciona em nenhum Python 3 no TIO. Parece-me um erro nos intérpretes da TIO.

Hex Dump

Reverta com o xxd -p -rUnix.

300a695c0a3d20310a743d28230a202730272a0a093029203b280a672c29
203d28230a206f70656e0928310a2c09227722292c29200a6b203d206576
616c09280a277027202b202772696e270a202b202774272029202330310a
666f7209206120696e092823300a6f70656e092809302920293a23300a23
30313031303130313031303130310a2061203d2061205b3a2d2031205d20
230a2069660928096c656e09286120293c695c0a6f72096c656e09286120
293e6920293a5b5c0a6b2827302720292c31202f305d2023303130310a20
692c09743d202d7e692c09742b2061202330310a286b2809322d6c656e09
287b28635e69202926315c0a09666f720920692c6320696e09206576616c
092823300a0922656e75222b226d222b2265726174652229282330310a20
6576616c092809220962797465222b22732229280974230a2c2720753827
20292029207d202920292029202330313031300a
Jakob
fonte