Inspetor oficial de Ruby

30

Aqui está um simples rubi de arte ASCII :

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \/_\/

Como joalheiro da ASCII Gemstone Corporation, seu trabalho é inspecionar os rubis recém-adquiridos e deixar uma nota sobre os defeitos encontrados.

Felizmente, apenas 12 tipos de defeitos são possíveis, e seu fornecedor garante que nenhum rubi terá mais de um defeito.

Os defeitos 12 correspondem à substituição de um dos 12 interiores _, /ou \caracteres do rubi com um carácter de espaço ( ). O perímetro externo de um rubi nunca apresenta defeitos.

Os defeitos são numerados de acordo com o caráter interno que possui um espaço em seu lugar:

números de defeitos

Portanto, um rubi com defeito 1 se parece com isso:

  ___
 /\_/\
/_/  _\
\ \_/ /
 \/_\/

Um rubi com defeito 11 se parece com isso:

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \ _\/

É a mesma idéia para todos os outros defeitos.

Desafio

Escreva um programa ou função que utilize a sequência de um único rubi potencialmente defeituoso. O número do defeito deve ser impresso ou devolvido. O número do defeito é 0 se não houver defeito.

Obtenha entrada de um arquivo de texto, stdin ou um argumento de função de sequência. Retorne o número do defeito ou imprima-o no stdout.

Você pode supor que o ruby ​​tenha uma nova linha à direita. Você não pode presumir que ele tenha espaços à direita ou novas linhas iniciais.

O código mais curto em bytes vence. ( Contador de bytes acessíveis ) .

Casos de teste

Os 13 tipos exatos de rubis, seguidos diretamente pelo resultado esperado:

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \/_\/
0
  ___
 /\_/\
/_/  _\
\ \_/ /
 \/_\/
1
  ___
 /\ /\
/_/ \_\
\ \_/ /
 \/_\/
2
  ___
 /\_/\
/_  \_\
\ \_/ /
 \/_\/
3
  ___
 /\_/\
/_/ \_\
\  _/ /
 \/_\/
4
  ___
 /\_/\
/_/ \_\
\ \ / /
 \/_\/
5
  ___
 /\_/\
/_/ \_\
\ \_  /
 \/_\/
6
  ___
 /\_/\
/_/ \ \
\ \_/ /
 \/_\/
7
  ___
 /\_ \
/_/ \_\
\ \_/ /
 \/_\/
8
  ___
 / _/\
/_/ \_\
\ \_/ /
 \/_\/
9
  ___
 /\_/\
/ / \_\
\ \_/ /
 \/_\/
10
  ___
 /\_/\
/_/ \_\
\ \_/ /
 \ _\/
11
  ___
 /\_/\
/_/ \_\
\ \_/ /
 \/_ /
12
Passatempos de Calvin
fonte
Para esclarecer, o rubi não pode ter espaços à direita, certo?
Optimizer
@Optimizer Correct
Calvin's Hobbies
@ Calvin'sHobbies Também podemos assumir que a entrada não tem uma nova linha à direita?
orlp
@orlp Sim. Esse é o objetivo de maio .
Calvin's Hobbies
Os rubis são simétricos. Portanto, o erro 7 não deve ser o mesmo que o erro 10, por exemplo?
DavidC

Respostas:

13

CJam, 27 23 bytes

F7EC5ZV4DI8G6]qBb67%J%#

Converta a base 11, pegue o mod 67, pegue o mod 19 do resultado e encontre o índice do que você tem na matriz

[15, 7, 14, 12, 5, 3, 0, 4, 13, 18, 8, 16, 6]

Magia!

Experimente online .

Sp3000
fonte
34

Ruby 2.0, 69 bytes

#!ruby -Kn0rdigest
p'×ñF<ìX‚ɲŸ_'.index Digest::MD5.digest(gets)[0]

Hexdump (para mostrar fielmente os dados binários na string):

00000000  23 21 72 75 62 79 20 2d  4b 6e 30 72 64 69 67 65  |#!ruby -Kn0rdige|
00000010  73 74 0a 70 27 d7 f1 46  3c 1f ec 58 82 c9 b2 9f  |st.p'..F<..X....|
00000020  5f 02 27 2e 69 6e 64 65  78 20 44 69 67 65 73 74  |_.'.index Digest|
00000030  3a 3a 4d 44 35 2e 64 69  67 65 73 74 28 67 65 74  |::MD5.digest(get|
00000040  73 29 5b 30 5d                                    |s)[0]|

Explicação:

  1. A -Knopção lê o arquivo de origem como ASCII-8BIT(binário).
  2. A -0opção permite getsler toda a entrada (e não apenas uma linha).
  3. A -rdigestopção carrega o digestmódulo, que fornece Digest::MD5.
  4. O código então faz um MD5 da entrada, pega o primeiro byte do resumo e obtém seu índice na sequência binária fornecida.
Chris Jester-Young
fonte
Sorte que MD5 é único na primeira si de char
Optimizer
15
Não é necessária sorte. Cada byte tem 256 possibilidades, portanto o primeiro byte diferente para 13 hashes não é incomum. Mas se eles colidissem por qualquer motivo, eu usaria o segundo byte do hash.
Chris Jester-Young
14
Escreva um inspetor Ruby em Ruby. Naturalmente!
mastro
Próximo desafio: Inspecionar este post em si
Programas Redwolf
7

Julia, 90 59 bytes

Definitivamente não é o mais curto, mas a donzela justa Julia cuida muito da inspeção dos rubis reais.

s->search(s[vec([18 10 16 24 25 26 19 11 9 15 32 34])],' ')

Isso cria uma função lambda que aceita uma string se retorna o número do defeito de ruby ​​correspondente. Para chamá-lo, dê um nome, por exemplo f=s->....

Ungolfed + explicação:

function f(s)
    # Strings can be indexed like arrays, so we can define d to
    # be a vector of indices corresponding to potential defect
    # locations

    d = vec([18 10 16 24 25 26 19 11 9 15 32 34])

    # Check the specified locations for defects, returning the
    # defect number as the index where a space was found and
    # was not expected. If no spaces are found, 0 is returned.

    search(s[d], ' ')
end

Exemplos:

julia> f("  ___
 /\\ /\\
/_/ \\_\\
\\ \\_/ \/
 \\/_\\/")
2

julia> f("  ___
 /\\_/\\
/_/ \\_\\
\\ \\_/ \/
 \\/_\\/")
0

Observe que as barras invertidas devem ser escapadas na entrada. Confirmei com o @ Calvin'sHobbies que está tudo bem.

Deixe-me saber se você tiver alguma dúvida ou sugestão!


Edit: Salvo 31 bytes com a ajuda de Andrew Piliser!

Alex A.
fonte
Você pode se livrar do loop for com searche indexação de array. s->(d=reshape([18 10 16 24 25 26 19 11 9 15 32 34],12);search(s[d],' ')). Não gosto da remodelação, mas não consegui pensar em uma maneira mais curta de obter uma matriz 1d.
Andrew diz Reinstate Monica
@AndrewPiliser: Obrigado, eu realmente aprecio a sua opinião! Eu editei para usar sua sugestão. Além disso, é uma maneira mais curta do que reshape()a utilizada vec(). :)
Alex A.
7

> <> (Peixe) , 177 bytes

Esta é uma solução longa, mas única. O programa não contém aritmética ou ramificação além da inserção de caracteres de entrada em locais fixos no código.

Observe que todos os caracteres de construção de rubi inspecionados ( / \ _) podem ser "espelhos" no código> <> que altera a direção do ponteiro de instrução (IP).

Podemos usar esses caracteres de entrada para construir um labirinto a partir deles com a instrução de modificação de código pe a cada saída (criada por um espelho ausente na entrada), podemos imprimir o número correspondente.

iiiiiiiii19pi1cpi18piiii2bpi27pii28pi3apiiiii37pi49pi36piiiii00pi45pii46p

    ;
   ;n
  ;nb
 ;n6S    0n;
 n3SB   cn;
 8SB!  4n;
 SB!  1n;
>B! U9n;
 ! U5
  U7n
 Uan;
 2n;
 n;
 ;

As S B Uletras foram alteradas para / \ _respectivamente. Se a entrada for um ruby ​​completo, o código final se tornará:

\iiiiiiii19pi1cpi18piiii2bpi27pii28pi3apiiiii37pi49pi36piiiii00pi45pii46p

    ;
   ;n
  ;nb
 ;n6/    0n;
 n3/\   cn;
 8/\!  4n;
 /\!  1n;
>\! _9n;
 ! _5
  _7n
 _an;
 2n;
 n;
 ;

Você pode experimentar o programa com este excelente intérprete visual online . Como você não pode inserir novas linhas lá, é necessário usar alguns caracteres fictícios para inserir um ruby ​​completo, como por exemplo SS___LS/\_/\L/_/S\_\L\S\_/S/LS\/_\/. (Os espaços também mudaram para S por causa da redução.)

randomra
fonte
5

CJam, 41 31 29 28 bytes

"-RI)11a!"q103b1e3%A/c#

Como de costume, para caracteres não imprimíveis, siga este link .

Experimente online aqui

Explicação em breve


Abordagem anterior:

Certamente isso pode ser reduzido alterando a lógica de dígitos / conversão. Mas aqui vai a primeira tentativa:

"<KJ[]\"O=":iqN-"/\\_ "4,er4b1e3%A/#

Como sempre, use este link para caracteres não imprimíveis.

A lógica é bem simples

  • "Hash for each defect":i - Isso me dá o hash por defeito como o índice
  • qN-"/\\_ "4,er - isso converte os caracteres em números
  • 4b1e3%A/ - este é o número único no número convertido base
  • # Então, simplesmente encontro o índice do número único no hash

Experimente online aqui

Optimizer
fonte
Tão perto, eu sou um personagem mais baixo que você!
orlp
Oh, eu já tenho 28. estava muito ocupado para atualizar
Optimizer
Eu acho que minha resposta é ótima para Pyth. Pyth realmente precisa de uma função hash ( .hno momento é inútil porque usa o embutido não confiável e ruim hash()), até então não posso fazer melhor.
orlp
4

Deslizamento , 123 108 + 3 = 111 bytes

^6 (`\\`_.?<?.?[ _]?|`_(`\.?(<.?|>)|`/.?.?>.?.?).?)| `_(`\.?<.?>?.?.?|`/(.?>.?.?.?|<`_))| `/\`_.?(.<.?>?.?)?

Corra com os sinalizadores ne o, ou seja,

py -3 slip.py regex.txt input.txt no

Como alternativa, tente online .


Slip é uma linguagem semelhante a regex que foi criada como parte do desafio de correspondência de padrões 2D . O deslizamento pode detectar a localização de um defeito com o psinalizador de posição através do seguinte programa:

^6? `_[/\]|( `/|^6 `\)\`_

que procura um dos seguintes padrões (aqui Sindica aqui a partida começa):

S_/    S_\    /_S    \_S    S/      _
                              _      \S

Experimente online - as coordenadas são produzidas como um par (x, y). Tudo parece um regex normal, exceto que:

  • ` é usado para escapar,
  • <> vire o ponteiro da partida para a esquerda / direita, respectivamente,
  • ^6 define o ponteiro da correspondência para a esquerda e
  • \ desliza o ponteiro da partida ortogonalmente para a direita (por exemplo, se o ponteiro estiver voltado para a direita, ele desce uma linha)

Infelizmente, porém, precisamos de um número único de 0 a 12, dizendo qual defeito foi detectado, não onde foi detectado. O deslizamento possui apenas um método para gerar um único número - o nsinalizador que gera o número de correspondências encontradas.

Para isso, expandimos a regex acima para corresponder ao número correto de vezes para cada defeito, com a ajuda do omodo de correspondência sobreposto. Divididos, os componentes são:

1 11:    `_`\.?<.?>?.?.?
2 10:    `/\`_.?(.<.?>?.?)?
4 9:     `_`/(.?>.?.?.?|<`_)
3 12:   ^6 `_`/.?.?>.?.?.?
5 7:    ^6 `\\`_.?<?.?[ _]?
6 8:    ^6 `_`\.?(<.?|>).?

Sim, é um uso excessivo ?para acertar os números: P

Sp3000
fonte
Haha, incrível. Preciso adicionar mais tipos de saída ao meu idioma.
BMAC
4

JavaScript (ES6), 67 72

Simplesmente procura espaços em branco nos 12 locais

Editar 5 bytes salvos, thx @apsillers

F=b=>[..."0h9fnopia8evx"].map((v,i)=>b[parseInt(v,34)]>' '?0:d=i)|d

Teste no console Firefox / FireBug

x='  ___\n /\\_/\\\n/_/ \\_\\\n\\ \\_/ /\n \\/_\\/' // no defects
;[...x].forEach((c,p,a)=>{
  a[p]=' ' // put a blank
  y=a.join('') // rebuild a string
  d=F(y) // check
  if (d) console.log('\n'+y+'\n'+d) // if defect, output
  a[p]=c // remove the blamk
})

Saída

  ___
 / _/\
/_/ \_\
\ \_/ /
 \/_\/
9

  ___
 /\ /\
/_/ \_\
\ \_/ /
 \/_\/
2

  ___
 /\_ \
/_/ \_\
\ \_/ /
 \/_\/
8

  ___
 /\_/\
/ / \_\
\ \_/ /
 \/_\/
10

  ___
 /\_/\
/_  \_\
\ \_/ /
 \/_\/
3

  ___
 /\_/\
/_/  _\
\ \_/ /
 \/_\/
1

  ___
 /\_/\
/_/ \ \
\ \_/ /
 \/_\/
7

  ___
 /\_/\
/_/ \_\
\  _/ /
 \/_\/
4

  ___
 /\_/\
/_/ \_\
\ \ / /
 \/_\/
5

  ___
 /\_/\
/_/ \_\
\ \_  /
 \/_\/
6

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \ _\/
11

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \/_ /
12
edc65
fonte
@apsillers é bom e ainda melhor, obrigado. Como a string de entrada sempre começa com '', o 0 inicial força a inicialização de d a i no primeiro loop, portanto, o 'd = 0' pode ser removido.
Edc65
2

C, 98 84 bytes

g(char*b){char*c="/'-5670(&,=?",*a=c;for(;*c&&!(*b=b[*c++-30]-32?0:c-a););return*b;}

ATUALIZAÇÃO: Um pouco mais inteligente sobre a string e corrigiu um problema com rubis não defeituosos.

Desvendado:

g(char*b){
    char*c="/'-5670(&,=?",*a=c;
    for(;*c&&!(*b=b[*c++-30]-32?0:c-a);)
        ;
    return*b;
}

Muito simples e pouco menos de 100 bytes.

Para teste:

#include "stdio.h"
int main() {
    char b[100];
    scanf("%35c", b);
    printf("%d\n", g(b));
    return 0;
}

Entrada para STDIN.

Como funciona

Cada defeito no ruby ​​está localizado em um caractere diferente. Esta lista mostra onde cada defeito ocorre na cadeia de entrada:

Defect 1: 17
Defect 2: 9
Defect 3: 15
Defect 4: 23
Defect 5: 24
Defect 6: 25
Defect 7: 18
Defect 8: 10
Defect 9: 8
Defect 10: 14
Defect 11: 31
Defect 12: 33

Desde que {17,9,15,23,24,25,18,10,8,14,31,33}fazemos uma série de custos com muitos bytes, encontramos uma maneira mais curta de criar essa lista. Observe que adicionar 30 a cada número resulta em uma lista de números inteiros que podem ser representados como caracteres ASCII imprimíveis. Esta lista é a seguinte: "/'-5670(&,=?". Assim, podemos definir uma matriz de caracteres (no código c) para essa string e simplesmente subtrair 30 de cada valor que recuperamos dessa lista para obter nossa matriz original de números inteiros. Definimos acomo igual cpara manter o controle de quanto tempo chegamos na lista. A única coisa que resta no código é o forloop. Ele verifica se ainda não atingimos o final ce, em seguida, verifica se o caractere batual cé um espaço (ASCII 32). Se for, definimos o primeiro elemento não utilizado deb ao número do defeito e devolva-o.

BrainSteel
fonte
2

Python 2, 146 88 86 71 bytes

A função ftesta cada localização de segmento e retorna o índice do segmento de defeito. Um teste no primeiro byte na cadeia de entrada garante que retornemos 0se nenhum defeito for encontrado.

Agora empacotamos as compensações de segmento em uma sequência compacta e usamos ord()para recuperá-las:

f=lambda s:sum(n*(s[ord('ARJPXYZSKIO`b'[n])-65]<'!')for n in range(13))

Testando com um rubi perfeito:

f('  ___\n /\\_/\\\n/_/ \\_\\\n\\ \\_/ /\n \\/_\\/')
0

Teste com o segmento 2 substituído por um espaço:

f('  ___\n /\\ /\\\n/_/ \\_\\\n\\ \\_/ /\n \\/_\\/')
2

EDIT: Obrigado a @xnor pela boa sum(n*bool for n in...)técnica.

EDIT2: Obrigado ao @ Sp3000 por dicas extras sobre golfe.

Cavaleiro Lógico
fonte
2
Eu acho que você pode salvar caracteres usando uma soma de indicadores sum(n*(s[...]==' ')for ...).
Xnor
1
Considerando que os caracteres substituídos são todos após o espaço, você provavelmente pode fazer algo como em <'!'vez de ==' 'por um byte. Você também pode gerar a lista com map(ord, ...), mas eu não sei como você se sente sobre unprintables :)
SP3000
1

Pitão, 35 31 28 bytes

hx"*6#,54@"C%imCds.zT67

Requer um Pyth corrigido , a versão mais recente atual do Pyth possui um bug .zque remove os caracteres finais.

Esta versão não usa uma função hash, mas abusa da função de conversão básica no Pyth para calcular um hash muito estúpido, mas funcional. Em seguida, convertemos esse hash em um caractere e procuramos seu índice em uma string.

A resposta contém caracteres não imprimíveis. Use este código Python3 para gerar o programa com precisão em sua máquina:

garbage = [42, 22, 54, 35, 44, 28, 31, 53, 52, 64, 16, 11]
prg = 'hx"' + "".join(chr(c) for c in garbage) +'"C%imCds.zT67'
open("golf_gen.pyth", "w").write(prg)
print(len(prg))
orlp
fonte
1

Haskell, 73 bytes

f l=last[x|x<-[0..12],l!!([0,17,9,15,23,24,25,18,10,8,14,31,33]!!x)==' ']

Mesma estratégia que muitas outras soluções: procurar espaços nos locais indicados. A pesquisa retorna uma lista de índices dos quais eu tiro o último elemento, porque sempre há um acerto para o índice 0.

nimi
fonte
0

05AB1E , 16 bytes

•W)Ì3ô;4(•₆вèðk>

Experimente online ou verifique todos os casos de teste .

Explicação:

W3ô;4(•        # Push compressed integer 2272064612422082397
          ₆в      # Converted to Base-36 as list: [17,9,15,23,24,25,18,10,8,14,31,33]
            è     # Index each into the (implicit) input-string
             ðk   # Get the 0-based index of the first space in the indexed characters
                  # (-1 if not found, which means the ruby had no defects)
               >  # And increase it by 1 (which is output implicitly as result)

Consulte esta dica 05AB1E (seções Como compactar números inteiros grandes? E Como compactar listas de números inteiros? ) Para entender por que •W)Ì3ô;4(•é 2272064612422082397e •W)Ì3ô;4(•₆вé [17,9,15,23,24,25,18,10,8,14,31,33].

Kevin Cruijssen
fonte