O desafio
O código mais curto por contagem de caracteres para inserir uma representação 2D de uma placa e gerar 'true' ou 'false' de acordo com a entrada .
A placa é composta por 4 tipos de peças:
# - A solid wall
x - The target the laser has to hit
/ or \ - Mirrors pointing to a direction (depends on laser direction)
v, ^, > or < - The laser pointing to a direction (down, up, right and left respectively)
Existe apenas um laser e apenas um alvo . As paredes devem formar um retângulo sólido de qualquer tamanho, onde o laser e o alvo são colocados no interior. Paredes dentro da 'sala' são possíveis.
O raio laser dispara e viaja desde a origem até a direção em que está apontando. Se um raio laser atinge a parede, ele para. Se um raio laser atinge um espelho, ele oscila 90 graus na direção em que o espelho aponta. Os espelhos são de duas faces, o que significa que ambos os lados são 'refletivos' e podem refletir um raio de duas maneiras. Se um raio laser atinge o próprio laser ( ^v><
), ele é tratado como uma parede (o raio laser destrói o projetor e nunca atinge o alvo).
Casos de teste
Entrada: ########## # / \ # # # # \ x # #> / # ########## Resultado: verdade Entrada: ########## # vx # # / # # / # # \ # ########## Resultado: falso Entrada: ############# # # # #> # # # # # # # x # # # # ############# Resultado: falso Entrada: ########## # / \ / \ / \ # # \\ // \\\ # # // \ / \ / \\ # # \ / \ / \ / x ^ # ########## Resultado: verdade
A contagem de códigos inclui entrada / saída (ou seja, programa completo).
fonte
Respostas:
Perl,
166160 caracteresPerl,
251248246222214208203201193190180176173170166 -> 160 caracteres.A solução teve 166 tacadas quando o concurso terminou, mas A. Rex encontrou algumas maneiras de cortar mais 6 caracteres:
A primeira linha carrega a entrada em
%t
uma tabela do quadro onde$t{99*i+j}
mantém o caractere na linha i , coluna j . Então,ele procura nos elementos
%t
um caractere que corresponda a> ^ <
ouv
e define simultaneamente$d
um valor entre 0 e 3 que indica a direção inicial do feixe de laser.No início de cada iteração no loop principal, atualizamos
$d
se o feixe estiver atualmente em um espelho. XOR'ing by 3 fornece o comportamento correto para um\
espelho e XOR'ing by 1 fornece o comportamento correto para um/
espelho.Em seguida, a posição atual
$r
é atualizada de acordo com a direção atual.Atribuímos o personagem na posição atual
$_
para fazer uso conveniente dos operadores da partida.Continue se estiver em um espaço em branco ou em um caractere de espelho. Caso contrário, terminaremos
true
se estivermos no alvo ($_ =~ /x/
) oufalse
não.Limitação: pode não funcionar em problemas com mais de 99 colunas. Essa limitação pode ser removida à custa de mais 3 caracteres,
fonte
s!.!$t{$s++}=$&!ge,$s=$r+=99for<>;
, altere%d=split//,.." to
% d = .. = ~ /./ g, and change
grep {..}% t` paragrep..,%t
Perl, 177 caracteres
A primeira quebra de linha pode ser removida; os outros dois são obrigatórios.
Explicação:
Se um feixe que se move para a direita esbarra em um {espaço vazio, espelho em ângulo para cima, espelho em ângulo para baixo}, ele se torna um {feixe de movimento direito, feixe de movimento para cima, feixe de movimento para baixo}. Inicialize
$/
ao longo do caminho - felizmente "6" não é um caractere de entrada válido.Leia o quadro em
$_
.$s
é o símbolo do que quer que o feixe esteja no topo agora. Como o emissor a laser deve ser tratado como uma parede, defina-o como uma parede para começar.Se o raio laser estiver apontando de qualquer maneira, exceto para a direita, gire seu símbolo e gire toda a placa no lugar (também gire os símbolos dos espelhos). É uma rotação à esquerda de 90 graus, realizada efetivamente revertendo as linhas enquanto transpõe linhas e colunas, de maneira um pouco diabólica
s///e
com efeitos colaterais. No código golfed, o tr é escrito no formatoy'''
que permite pular uma barra invertida.Termine com a mensagem certa se atingirmos o alvo ou uma parede.
Se houver um espaço vazio na frente do laser, siga em frente. Se houver um espelho na frente do laser, avance e gire o feixe. Em qualquer um dos casos, coloque o "símbolo salvo" de volta no local antigo do feixe e coloque o que acabamos de sobrescrever no símbolo salvo.
Repita até o término.
{...;redo}
é dois caracteres menor quefor(;;){...}
e três menor quewhile(1){...}
.fonte
C89 (209 caracteres)
Explicação
Essa monstruosidade provavelmente será difícil de seguir se você não entender C. Apenas um aviso.
Essa pequena macro verifica se o caractere atual (
*p
) é igual ao quea
está no formato de caractere (*#a
). Se forem iguais, defina o vetor de movimento comob
(m=b
), marque esse caractere como uma parede (*p=1
) e defina o ponto inicial para o local atual (q=p
). Essa macro inclui a parte "else".Declare algumas variáveis. *
q
é a localização atual da luz. *G
é o tabuleiro do jogo como uma matriz 1D. *p
é o local de leitura atual ao preencherG
. *w
é a largura do quadro.Óbvio
main
.m
é uma variável que armazena o vetor de movimento. (É um parâmetro paramain
otimização.)Repete todos os caracteres, preenchendo
G
usandop
. PuleG[0]
como uma otimização (não é necessário desperdiçar um personagem escrevendop
novamente na terceira parte dofor
).Use a macro mencionada acima para definir o lazer, se possível.
-1
e1
correspondem à esquerda e à direita, respectivamente,-w
e paraw
cima e para baixo.Se o caractere atual for um marcador de fim de linha (ASCII 10), defina a largura se ainda não tiver sido definido. O ignorado
G[0]
nos permite escrever emw=p-G
vez dew=p-G+1
. Além disso, isso termina a?:
cadeia a partir doM
.Mova a luz pelo vetor de movimento.
Reflita o vetor de movimento.
Se for uma parede ou
x
, saia com a mensagem apropriada (m=0
finaliza o loop). Caso contrário, não faça nada (noop;m=m
)fonte
g.c:3: declaration expected
:(puts
da declaração ajudou, mas não o suficiente para colocá-la abaixo de 170. 209 é muito boa, então acho que vou deixar por isso mesmo. Obrigado pela ajuda, pessoal. Eu realmente gostei disso. =] (Qualquer coisa para destronar aquelas bruxas Perl!) #Aposto que as pessoas estão esperando por este há um tempo LOOOOONG. (Como assim, o desafio acabou e ninguém se importa mais?)
Eis que aqui apresento uma solução em
Befunge-93!
Ele pesa 973 caracteres (ou 688 se você for caridoso o suficiente para ignorar espaço em branco, que é usado apenas para formatação e não faz nada no código real).
Advertência : Eu escrevi meu próprio intérprete Befunge-93 em Perl há pouco tempo e, infelizmente, é tudo o que realmente tenho tempo para testá-lo. Estou razoavelmente confiante em sua correção em geral, mas pode ter uma limitação estranha em relação ao EOF: Como o
<>
operador do Perl retorna undef no final do arquivo, isso é processado como um 0 no contexto numérico. Para implementações baseadas em C em que o EOF tem um valor diferente (-1 digamos), esse código pode não funcionar.Explicação
Se você não estiver familiarizado com a sintaxe e a operação do Befunge, verifique aqui .
Befunge é uma linguagem baseada em pilha, mas existem comandos que permitem escrever caracteres no código Befunge. Aproveito isso em dois lugares. Primeiro, copio toda a entrada no quadro Befunge, mas localizei algumas linhas abaixo do código escrito real. (Obviamente, isso nunca é realmente visível quando o código é executado.)
O outro local fica perto do canto superior esquerdo:
Nesse caso, a área que destaquei acima é onde guardo algumas coordenadas. A primeira coluna na linha do meio é onde eu armazeno a coordenada x para a atual "posição do cursor"; a segunda coluna é onde eu armazeno a coordenada y; as próximas duas colunas são para armazenar as coordenadas x e y da fonte do feixe de laser quando isso é encontrado; e a coluna final (com o caractere 'a') é substituída para conter a direção atual do feixe, que obviamente muda conforme o caminho do feixe é traçado.
O programa começa colocando (0,27) como a posição inicial do cursor. Então a entrada é lida um caractere de cada vez e colocada na posição do cursor; as novas linhas apenas fazem com que a coordenada y aumente e a coordenada x retorne a 0, exatamente como um retorno de carro real. Eventualmente, undef é lido pelo intérprete e esse valor de 0 caractere é usado para sinalizar o final da entrada e seguir para as etapas de iteração do laser. Quando o caractere a laser [<> ^ v] é lido, ele também é copiado para o repositório de memória (sobre o caractere 'a') e suas coordenadas são copiadas para as colunas à esquerda.
O resultado final de tudo isso é que o arquivo inteiro é basicamente copiado no código Befunge, um pouco abaixo do código real percorrido.
Posteriormente, o local do feixe é copiado de volta para os locais do cursor e a seguinte iteração é executada:
Se houver demanda suficiente, tentarei apontar exatamente onde no código tudo isso é realizado.
fonte
F #, 36 linhas, muito legível
Ok, apenas para obter uma resposta por aí:
Amostras:
fonte
Golfscript - 83 caracteres (mashup do meu e do strager)
A nova linha está aqui apenas para embalar
Golfscript - 107 caracteres
A nova linha existe apenas para maior clareza
Como funciona.
A primeira linha calcula a localização e a direção iniciais.
A segunda linha passa pelo giro sempre que o laser atinge um espelho.
fonte
353 caracteres em Ruby:314277 caracteres agora!OK, 256 caracteres em Ruby e agora estou pronto. Número redondo agradável para parar. :)247 caracteres. Eu não consigo parar223203201 caracteres em RubyCom espaço em branco:
Um pouco refatorado:
fonte
ch
paraC
ou qualquer outra letra de 1 caractere para salvar 2 caracteres!i++
(em vez dei+=1
)?Pitão
294277253240232 caracteres, incluindo novas linhas:(o primeiro caractere nas linhas 4 e 5 é uma guia, não espaços)
Eu tinha esquecido que o Python tinha até ponto e vírgula opcional.
Como funciona
A idéia principal por trás desse código é usar números complexos para representar posições e direções. As linhas são o eixo imaginário, aumentando para baixo. As colunas são o eixo real, aumentando para a direita.
l='>v<^';
uma lista dos símbolos do laser. A ordem é escolhida para que o índice de um caractere de direção do laser corresponda a uma potência de sqrt (-1)x={'/':'^<v>','\\':'v>^<',' ':l};
uma tabela de transformação que determina como a direção muda quando a viga sai de blocos diferentes. O bloco é a chave e as novas direções são os valores.b=[1];
mantém o conselho. O primeiro elemento é 1 (avaliado como verdadeiro) para que o loop while seja executado pelo menos uma vez.r=p=0
r
é o número da linha atual da entrada,p
é a posição atual do feixe de laser.while b[-1]:
parar de carregar os dados da placa quando raw_input retornar uma sequência vaziab+=[raw_input()];r+=1
acrescente a próxima linha de entrada ao quadro e aumente o contador de linhasfor g in l:
adivinhar cada direção do laser, por sua vezc=b[r].find(g)
defina a coluna para a localização do laser ou -1 se não estiver na linha (ou estiver apontando em uma direção diferente)if-1<c:p=c+1j*r;d=g
se encontrarmos um laser, defina a posiçãop
e a direção atuaisd
.d
é um dos caracteres eml
Após carregar a placa
b
, a posiçãop
e a direção atuaisd
foram definidas para as da fonte de laser.while' '<d:
O espaço tem um valor ASCII mais baixo do que qualquer um dos símbolos de direção, portanto, o usamos como um sinalizador de parada.z=l.find(d);
índice da direção atual char nal
string.z
é usado posteriormente para determinar a nova direção do feixe usando ax
tabela e para incrementar a posição.p+=1j**z;
aumente a posição usando uma potência de i. Por exemplo,l.find('<')==2
-> i ^ 2 = -1, que seria movido para a coluna da esquerda.c=b[int(p.imag)][int(p.real)];
leia o caractere na posição atuald=x.get(c,' '*4)[z]
procure a nova direção da viga na tabela de transformação. Se o caractere atual não existir na tabela, definad
como espaço.print'#'<c
print false se pararmos em algo que não seja o alvo.fonte
p+=1j**z
: Isso é doce.Este
éera uma porta directa de solução de Brian para C # 3, menos as interacções da consola. Esta não é uma entrada no desafio, uma vez que não é um programa completo, eu estava apenas imaginando como algumas das construções de F # que ele usou poderiam ser representadas em C #.Edit: Após algumas experiências, o seguinte código de pesquisa bastante detalhado:
foi substituído por um código LINQ to Objects muito mais compacto:
fonte
F #, 255 caracteres (e ainda bastante legível!):
Ok, depois de uma noite de descanso, eu melhorei bastante isso:
Vamos falar disso linha por linha.
Primeiro, agrupe toda a entrada em uma grande matriz unidimensional (as matrizes 2D podem ser ruins para o código de golfe; basta usar uma matriz 1D e adicionar / subtrair a largura de uma linha ao índice para subir / descer uma linha).
Em seguida, calculamos 'w', a largura de uma linha de entrada e 'c', a posição inicial, indexando em nossa matriz.
Agora vamos definir a 'próxima' função 'n', que assume uma posição atual 'c' e uma direção 'd' que é 0,1,2,3 para cima, esquerda, direita, baixo.
O índice-epsilon 'e' e o que-nova-direção-se-batermos-uma-barra são calculados por uma tabela. Por exemplo, se a direção atual 'd' é 0 (para cima), o primeiro elemento da tabela diz "-w, 2", o que significa que diminuímos o índice por w e, se pressionarmos uma barra, a nova direção será 2 (certo).
Agora recuamos para a próxima função 'n' com (1) o próximo índice ("c + e" - corrente mais epsilon) e (2) a nova direção, que calculamos olhando para a frente para ver o que está na matriz em aquela próxima célula. Se o char lookahead é uma barra, a nova direção é 's'. Se for uma barra invertida, a nova direção é de 3 s (nossa escolha de codificar 0123 faz esse trabalho). Se for um espaço, continuamos na mesma direção 'd'. E se houver outro caractere 'c', o jogo termina, imprimindo 'true' se o caractere for 'x' e false caso contrário.
Para começar, chamamos a função recursiva 'n' com a posição inicial 'c' e a direção inicial (que faz a codificação inicial da direção em 0123).
Acho que ainda posso raspar mais alguns personagens, mas estou muito satisfeito com isso (e 255 é um bom número).
fonte
A pesagem de 18203 caracteres é uma solução Python que pode:
Ele ainda precisa ser arrumado um pouco e eu não sei se a física 2D determina que o feixe não pode se cruzar ...
Um script do bash para exibir o relatório de erros de cores:
Os unittests usados no desenvolvimento:
fonte
Ruby, 176 caracteres
Eu usei uma máquina de estado simples (como a maioria dos pôsteres), nada extravagante. Eu apenas continuei usando todos os truques que consegui pensar. O XOR bit a bit usado para mudar de direção (armazenado como um número inteiro na variável
c
) foi uma grande melhoria em relação aos condicionais que eu tinha nas versões anteriores.Suspeito que o código que aumente
x
ey
possa ser reduzido. Aqui está a seção do código que faz o incremento:Edit : Consegui reduzir um pouco o acima:
A direção atual do laser
c
é armazenada da seguinte forma:O código depende desse fato para incrementar
x
ey
pela quantidade correta (0, 1 ou -1). Tentei reorganizar quais números são mapeados para cada direção, procurando um arranjo que me permitisse fazer alguma manipulação bit a bit para aumentar os valores, porque tenho uma sensação incômoda de que seria mais curto que a versão aritmética.fonte
C # 3.0
259 caracteres
Um pouco mais legível:
O principal desperdício de caracteres parece estar em encontrar a largura do mapa e a posição da fonte do laser. Alguma idéia de como encurtar isso?
fonte
while(1)
C + ASCII, 197 caracteres:
Esta solução C assume um conjunto de caracteres ASCII, permitindo o uso do truque do espelho XOR. Também é incrivelmente frágil - todas as linhas de entrada devem ter o mesmo comprimento, por exemplo.
Ele quebra abaixo da marca de 200 caracteres - mas, porra, ainda não derrotou as soluções Perl!
fonte
Golfscript (83 caracteres)
Olá, gnibbler!
fonte
Python - 152
Lê a entrada de um arquivo chamado "L"
Para ler a partir de stdin, substitua a primeira linha por esta
Se você precisar de minúsculas verdadeiro / falso, altere a última linha para
fonte
True
paratrue
eFalse
parafalse
? ;-)D<5
" para "print D <5"? Ou há algo que estou perdendo?JavaScript - 265 caracteres
Atualização IV - As chances são de que esta será a última rodada de atualizações, conseguiu salvar mais alguns caracteres alternando para um loop do-while e reescrevendo a equação do movimento.
Atualização III - Graças à sugestão do strager em remover o Math.abs () e colocar as variáveis no espaço de nomes global, que, juntamente com alguma reorganização das atribuições de variáveis, reduziu o código para 282 caracteres.
Atualização II - Mais algumas atualizações no código para remover o uso de! = -1, bem como um melhor uso de variáveis para operações mais longas.
Atualização - Ao concluir e fazer algumas alterações, crie uma referência à função indexOf (obrigado LiraNuna!) E remova os parênteses que não eram necessários.
Esta é minha primeira vez em um código de golfe, então não tenho certeza de quanto isso poderia ser melhor, qualquer feedback é apreciado.
Versão totalmente minimizada:
Versão original com comentários:
Página da Web para testar:
fonte
index != -1
porindex > 0
favor! (Espero que ninguém coloque o lazer no canto superior esquerdo para0
que não seja retornado. =]) Você pode encadear asvar
instruções ou se livrar delas completamente (colocando as variáveis no espaço de nomes global). Eu acho queMath.abs(m)==1
pode ser substituído porm==-1|m==1
. Podemovement = ...; location += movement
ser otimizado paralocation += movement =
?function(a){return g.indexOf(a)}
pode ser substituído porfunction(a)g.indexOf(a)
nas versões recentes do JavaScript.Casa dos Espelhos
Não é uma entrada real para o desafio, mas escrevi um jogo baseado nesse conceito (não muito tempo atrás).
Está escrito em Scala, de código aberto e disponível aqui :
Faz um pouco mais; lida com cores e vários tipos de espelhos e dispositivos, mas a versão 0.00001 fez exatamente o que esse desafio pede. Porém, perdi essa versão e ela nunca foi otimizada para a contagem de caracteres.
fonte
c (K&R) 339 caracteres necessários após mais sugestões do strager.
O físico em mim observou que as operações de propagação e reflexão são invariantes com inversão de tempo; portanto, esta versão lança raios do alvo e verifica se eles chegam ao emissor do laser.
O restante da implementação é muito direto e é retirado mais ou menos exatamente do meu esforço anterior.
Comprimido:
Não compactado (ish):
Não há validação de entrada e entradas ruins podem enviá-las para um loop infinito. Funciona corretamente com entradas não maiores que 99 por 99. Requer um compilador que vinculará a biblioteca padrão sem incluir nenhum dos cabeçalhos. E eu acho que terminei, o strager me fez bater bastante, mesmo com a ajuda dele.
Espero que alguém demonstre uma maneira mais sutil de realizar a tarefa. Não há nada de errado nisso, mas não é uma mágica profunda.
fonte
=0
nos globais, pois eles são inicializados em 0 por padrão. Substitua constantes de caracteres pelo seu equivalente em decimal. Use em>0
vez de!=EOF
para verificar o EOF (e\0
). Provavelmente você pode#define
afastar parte do códigocase
como eu fiz comif
o. Não há necessidade de extra\n
noputs
comoputs
deve imprimir uma nova linha de qualquer maneira.for(;;)
é mais curto quewhile(1)
. Espero que isto ajude. =]"There is no input validation"
- Não deveria haver nenhum. Para facilitar as coisas para os golfistas, presume-se que a entrada seja sempre 'limpa', a menos que especificado de outra forma.Ruby - 146 Chars
fonte
PostScript , 359 bytes
Primeira tentativa, muito espaço para melhorias ...
fonte
Haskell,
395391383361339 caracteres (optimizado)Ainda usa uma máquina de estado genérica, em vez de algo inteligente:
Uma versão legível:
fonte
Acredito na reutilização de código, eu usaria um de seu código como uma API :).
32 caracteres \ o / ... wohoooo
fonte
C ++: 388 caracteres
( 318 sem cabeçalhos)
Como funciona:
Primeiro, todas as linhas são lidas e, em seguida, o laser é encontrado. O seguinte será avaliado
0
enquanto nenhuma seta do laser for encontrada ainda e, ao mesmo tempo, será atribuído àx
posição horizontal.Então, olhamos em que direção encontramos e a armazenamos
i
. Os valoresi
pares de são superior / esquerdo ("decrescente") e os valores ímpares são inferior / direito ("crescente"). De acordo com essa noção,d
("direção") er
("orientação") são definidos. Indexamos a matriz de ponteirosz
com orientação e adicionamos a direção ao número inteiro que obtemos. A direção muda apenas se atingirmos uma barra, enquanto permanece a mesma quando atingimos uma barra invertida. Obviamente, quando atingimos um espelho, sempre mudamos a orientação (r = !r
).fonte
Caracteres Groovy @ 279
fonte
C #
1020 caracteres.1088 caracteres (entrada adicionada do console).925 caracteres (variáveis refatoradas).875 caracteres (inicializador de dicionário redundante removido; alterado para Binário e operadores)
Fez questão de não olhar para as outras pessoas antes de postar. Tenho certeza de que poderia ser um pouco LINQ. E todo o método FindLaser na versão legível parece terrivelmente suspeito para mim. Mas, funciona e é tarde :)
Observe que a classe legível inclui um método adicional que imprime a Arena atual à medida que o laser se move.
Versão legível (não exatamente a versão final do golfe, mas a mesma premissa):
fonte
Perl 219
Minha versão perl tem
392342 caracteres (eu tive que lidar com o caso do raio atingindo o laser):Atualize , obrigado Hobbs por me lembrar
tr//
, agora são 250 caracteres:Atualize , remova o
m
inm//
, altere os doiswhile
loops trazidos algumas economias; agora há apenas um espaço necessário.(
L:it;goto L
tem o mesmo comprimento quedo{it;redo}
):Eu raspei alguns, mas
malapenas compete com algumas delas, embora tarde.Parece um pouco melhor como:
Bem ... Honestamente, isso deve ser auto-explicativo se você entender que
@b
é uma matriz de caracteres em cada linha e pode ler a simples expressão regular etr
declarações.fonte
$_=$s;tr/^v<>/<>^v/
e$_=$s;tr/v^<>/<>^v/
respectivamente. Além disso, você não precisa dom
nom//
.$_=$s;tr/v^></<>^v/;
if m/.../
que podem estarif/.../
salvando dois caracteres por pop.y///
vez detr///
salvar dois caracteres.F # - 454 (ou próximo)
Um pouco atrasado para o jogo, mas não resisto a postar minha tentativa 2D.
Atualização modificada ligeiramente. Agora pára corretamente se o transmissor for atingido. Beliscou a ideia de Brian para IndexOfAny (pena que essa linha seja tão detalhada). Na verdade, não consegui descobrir como fazer com que o ReadToEnd retorne do console, por isso estou confiando um pouco ...
Estou satisfeito com esta resposta, como se ela fosse muito curta, ainda é bastante legível.
fonte