Retina , 353 339 178 175 150 130 129 117 bytes
R
5$*r
T`aq\we\ds`so`r.+
)`r(.*)
$1
^
:
a
sq
e
wd
+`(.+)q
w$1
+`(.+)d
s$1
+`sw
(.*)(\1w?):
$0$2
+`sw|ws
w+
-$0
\w
1
A saída é unária, separada por dois pontos. Isso significa que você realmente não verá zeros na saída (embora a presença de dois pontos indique qual das duas coordenadas é zero, se houver apenas uma).
Experimente online!
Isso foi muito divertido e acabou sendo surpreendentemente curto. :)
Explicação
Alguns antecedentes primeiro. Existem vários sistemas de coordenadas para descrever grades hexagonais. A pessoa solicitada usa coordenadas de deslocamento. Isso é essencialmente como coordenadas retangulares da grade, exceto que um eixo "oscila" um pouco. Em particular, a pergunta solicita o layout "ímpar-q" mostrado na página vinculada. Esse sistema de coordenadas é um pouco chato de se trabalhar, porque o modo como as coordenadas mudam durante um movimento depende não apenas da direção do movimento, mas também da posição atual.
Outro sistema de coordenadas usa coordenadas axiais. Isso é essencialmente imaginar a hexgrid como uma fatia diagonal através de um volume de cubos e usar dois dos eixos (por exemplo, x e z) para encontrar uma posição no plano 2D. Na grade hexagonal, isso significa que os dois eixos formam um ângulo de 60 (ou 120) graus. Esse sistema é um pouco menos intuitivo, mas muito mais fácil de trabalhar, pois todas as direções correspondem a um vetor "delta" fixo. (Para uma melhor explicação de como chegar a esse sistema de coordenadas, confira o link e os adoráveis diagramas e animações.)
Então, aqui está o que faremos: calculamos o movimento em coordenadas axiais (cuidando da rotação como sugerido no desafio, remapeando o significado dos comandos) e, quando terminamos, convertemos axial em offset-q impar coordenadas.
Os seis movimentos são mapeados para os seguintes vetores delta em coordenadas axiais (xz):
q => (-1, 0)
w => ( 0, -1)
e => ( 1, -1)
d => ( 1, 0)
s => ( 0, 1)
a => (-1, 1)
Espera, aqui é Retina, teremos que trabalhar com números unários. Como trabalhamos com números unários negativos? A idéia é usar dois dígitos diferentes. Um representa +1
e o outro representa -1
. Isso significa que, independentemente de querermos adicionar ou subtrair 1
da posição atual, sempre podemos fazer isso adicionando um dígito. Quando terminamos, reduzimos o resultado em sua magnitude (do dígito correspondente) cancelando dígitos balanceados. Depois descobrimos o sinal com base no dígito restante e substituímos todos os dígitos por 1
.
O plano é construir os componentes axiais x e z à esquerda e à direita de a :
(como um separador), na frente da entrada. w
e s
será adicionado ao lado direito. q
e d
será adicionado ao lado esquerdo e
e a
será adicionado aos dois lados. Como w
e s
já estamos no lado correto do :
(que irá na frente), os usaremos como os dígitos -1
e +1
, respectivamente.
Vamos analisar o código.
R
5$*r
Começamos transformando cada um R
em cinco r
segundos. Obviamente, uma curva à esquerda é igual a cinco curvas à direita em uma grade hexadecimal e, ao fazer isso, podemos duplicar bastante na etapa de remapeamento.
T`aq\we\ds`so`r.+
Este é um estágio de transliteração que gira os seis comandos, se forem encontrados após o primeiro r
(processando assim o primeiro r
). w
e d
precisa ser escapado para impedir que eles se expandam para as classes de personagens. Ele o
insere o conjunto de origem no conjunto de destino, o que economiza um monte de bytes para essas tarefas de rotação. O mapeamento de caracteres é, portanto:
aqweds
saqweds
onde o último s
na segunda linha pode ser simplesmente ignorado.
)`r(.*)
$1
Isso remove o primeiro r
da string, porque foi processado (eu gostaria de já ter implementado limites de substituição ...). O )
comando também diz ao Retina para executar todos os estágios até este em um loop até que a string pare de mudar. Nas iterações subseqüentes, o primeiro estágio é um no-op porque não há mais se R
o segundo estágio aplicará outra rotação enquanto houver r
s restantes na string.
Quando terminamos, mapeamos todos os comandos na direção a que correspondem na grade não rotacionada e podemos começar a processá-los. É claro que esse movimento é apenas uma soma desses vetores delta e as somas são comutativas, portanto, não importa realmente em que ordem os processamos agora que as rotações foram eliminadas.
^
:
Insira o delimitador de coordenadas na frente.
Agora realmente não precisamos processar s
e w
. Eles são nossos +1
e -1
dígitos e já estão no lado correto da tela, :
para que acabem desistindo conforme necessário no final. Podemos fazer outra simplificação: a
é simples s + q
e e
é w + d
. Vamos fazer isso:
a
sq
e
wd
Mais uma vez, aqueles s
e w
simplesmente desistirão. Tudo o que precisa fazer é mover essas q
s e d
s para a frente e transformá-los em w
s e s
s eles mesmos. Fazemos isso com dois loops separados:
+`(.+)q
w$1
+`(.+)d
s$1
Então está feito. Hora da conversão de coordenadas axiais para deslocadas. Para isso, precisamos recolher os dígitos. No entanto, por enquanto, nos preocupamos apenas com o lado esquerdo. Devido à forma como temos processados os q
s e d
s, sabemos que todas as s
s em lado esquerdo vai aparecer na frente de quaisquer w
s, por isso, só precisa verificar um par para o colapso do-los:
+`sw
Agora a conversão real. Aqui está o pseudocódigo, retirado do link acima:
# convert cube to odd-q offset
col = x
row = z + (x - (x&1)) / 2
Certo, então o lado esquerdo já está correto. O lado direito precisa do termo de correção (x - (x&1)) / 2
. Tomar &1
é o mesmo que o módulo 2. Isso basicamente analisa como x/2
, divisão inteira, arredondada para menos infinito. Portanto, para positivo x
, adicionamos metade do número de dígitos (arredondado para baixo) e, para negativo x
, subtraímos metade do número de dígitos (arredondado para cima). Isso pode ser expresso surpreendentemente concisa na regex:
(.*)(\1w?):
$0$2
Devido à ganância, para o par x
, o grupo 1 corresponderá exatamente a metade dos dígitos, \1
a outra metade e podemos ignorar o w?
. Nós inserimos essa metade após o :
(que é x/2
). Se x
for par, precisamos distinguir positivo e negativo. Se x
for positivo, w?
nunca corresponderá, portanto os dois grupos ainda terão que corresponder ao mesmo número de dígitos. Não há problema se o primeiro s
for simplesmente pulado, então arredondamos para baixo. Se x
for negativo e ímpar, a possível correspondência será com \1
(metade do x
arredondado para baixo) e opcional w
. Como os dois entram em grupo 2
, escreveremos x/2
com a magnitude arredondada para cima (conforme necessário).
+`sw|ws
Agora, reduzimos os dígitos no lado direito. Desta vez, não sabemos a ordem do s
e w
, portanto, precisamos considerar os dois pares.
w+
-$0
Agora, ambas as partes são reduzidas a um único dígito repetido (ou nada). Se esse dígito for w
, inserimos um sinal de menos na frente.
\w
1
E, finalmente, transformar tanto em w
e s
para um único dígito unário razoável. (Suponho que eu poderia salvar um byte usando w
ou s
como o dígito unário, mas isso parece um pouco exagerado.)
Python (3,5)
193185182 bytesEu também calculo em coordenadas axiais e converto no final.
Eu adiciono alguma otimização de acordo com a solução @Martin Büttner: substituo R por r * 5, ele não altera a contagem de bytes. Mas com essa mudança, podemos substituir o segundo teste
elif j=='r'
apenaselse
A solução assume que não podemos ter caracteres inválidos na entrada.
Ungolfed
Uso
fonte
Lote,
708636586569 bytesEu usei coordenadas y duplicadas porque tornava a matemática mais simples. Não tenho certeza de ter levado em consideração a rotação da maneira mais ideal, mas é melhor contar o número de
r
s.Editar: economizou 72 bytes melhorando o manuseio de
R
s. Economizei 60 bytes otimizando minhasset/a
declarações. Economizou 17 bytes com algumas otimizações menores.fonte
05AB1E , 60 bytes
Experimente online ou verifique todos os casos de teste .
Explicação:
Explicação geral:
Começamos com uma seqüência de caracteres
"qwedsa"
e uma coordenada[0,0]
, e passamos pelos caracteres da entrada.Se for um "r" ou "R", rotacionamos essa corda para a esquerda ou direita, respectivamente.
Caso contrário, obtemos o índice com base em 0 nessa sequência e o mapeamos da seguinte maneira:
Explicação do código:
Veja este 05AB1E ponta do meu (seção Como cordas compressa não fazem parte do dicionário? ) Para entender por que
.•F?äM•
é"qwedsa"
.fonte
Python 3, 227 bytes
fonte
Python 3.5.0b3
no MacOS e, apesar de ter recebido um erro nos dias 5 e 6, devido ao arredondamento, o restante estava correto. (Desde que corrigido via Editar). Qual versão do Python você está usando?