Relativo vs Absoluto


17

Se alguém de frente para o norte no ponto A nesta grade quiser que as direções sigam o caminho verde (como elas só podem seguir linhas de grade) até o ponto B, você pode dizer a elas:

North, North, West, East, East, South, East, East.

ou equivalente

Forward, Forward, Left, Back, Forward, Right, Left, Forward.
(Onde um comando de Direita , Esquerda ou Voltar implicitamente significa virar nessa direção e depois avançar).

Caminho A para B

Escreva uma função com um argumento que traduza entre essas direções absolutas e relativas no mesmo caminho , não apenas no mesmo ponto. Suponha que a pessoa direcionada sempre comece voltada para o norte.

Se o argumento for uma sequência de letras NSEW, retorne as direções relativas equivalentes.
por exemplo, f("NNWEESEE")retorna a string FFLBFRLF.

Se o argumento for uma sequência de letras FBLR, retorne as direções absolutas equivalentes.
por exemplo, f("FFLBFRLF")retorna a string NNWEESEE.

A cadeia vazia produz-se. Suponha que não haja outros casos de entrada.

Se seu idioma não possui funções ou seqüências de caracteres, use o que parecer mais apropriado.

O código mais curto em bytes vence.


Supomos que uma pessoa sempre comece com a cabeça voltada para o norte? Dessa forma, em termos relativos para ir em direção ao leste, seria necessário que ele virasse à direita, em vez de simplesmente dizer para frente
Optimizer

@ Otimizador Sim, norte. E sim ao seu outro ponto. Ré igual Eno início.
Passatempos de Calvin

11
Yay! Você mudou sua foto para confirmar o que eu sempre pensei!
Justin justin

4
Você está viciado em PPCG novamente? ;)
Martin Ender

4
@ MartinBüttner Ou sou muito bom em disfarçar meus problemas de dever de casa. ;)
Calvin's Hobbies

Respostas:


6

CJam, 57 53 49

{"NESW""FRBL"_3$&!!:Q$:R^^f#0\{{+0\}Q*_@-R=\}%);}

Versão anterior

{"NESW""FRBL"_3$0=#W>:Q{\}*:R;f#0\{{+0\}Q*_@-R=\}%);}

Exemplo:

{"NESW""FRBL"_3$0=#W>:Q{\}*:R;f#0\{{+0\}Q*_@-R=\}%);}:T;
"NNWEESEE"T
N
"FFLBFRLF"T

Resultado:

FFLBFRLF
NNWEESEE

Como funciona

{
  "NESW""FRBL"             " Push the two strings. ";
  _3$0=#W>                 " Check if the first character is in FRBL. ";
  :Q                       " Assign the result to Q. ";
  {\}*                     " Swap the two strings if true. ";
  :R;                      " Assign the top string to R and discard it. ";
  f#                       " Find each character of the input in the string. ";
  0\                       " Push a 0 under the top of the stack. ";
  {                        " For each item (index of character): ";
    {                      " If Q: ";
      +0\                  " A B -> 0 (A+B) ";
    }Q*
    _@-                    " C D -> D (D-C) ";
    R=                     " E -> E-th character in R ";
    \                      " Swap the top two items. ";
  }%
  );                       " Discard the last item in the list. ";
}

6

C ++, 99 97

O seguinte é formatado como uma expressão lambda. Ele pega um char*argumento e o substitui.

[](char*s){for(int d=0,n=0,c=*s*9%37&4;*s;d+=n)c?n=*s%11/3-d:n+=*s%73%10,*s++="NESWFRBL"[c|n&3];}

Para aqueles que não estão familiarizados com esse recurso (como eu há uma hora atrás), use-o da seguinte maneira:

#include <iostream>

int main()
{
    char s[] = "NNWEESEE";
    auto x = [](char*s){for(int d=0,n=0,c=*s*9%37&4;*s;d+=n)c?n=*s%11/3-d:n+=*s%73%10,*s++="NESWFRBL"[c|n&3];};

    x(s); // transform from absolute to relative
    std::cout << s << '\n';

    x(s); // transform from relative to absolute
    std::cout << s << '\n';
}

Algumas explicações:

  • Ao usar código como flag ? (x = y) : (x += z) , o segundo par de parênteses é necessário em C. Então, usei C ++!
  • C ++ requer a especificação de um tipo de retorno para uma função. A menos que eu use uma expressão lambda, é isso! Um bônus adicional é que eu não preciso desperdiçar 1 caractere no nome da função.
  • O código *s*9%37&4testa o primeiro byte; o resultado é 4 se for um dosNESW ; 0 caso contrário
  • O código *s%11/3converte os bytesNESW em 0, 1, 2, 3
  • O código *s%73%10converte os bytesFRBL em 0, 9, 6, 3 (que é 0, 1, 2, 3 módulo 4)
  • Ao converter direções relativas para absolutas, não preciso da dvariável. Tentei reorganizar o código para eliminá-lo completamente, mas parece impossível ...

11
Eu gosto muito da maneira como você converte as letras em números. :)
Emil

6

JavaScript (E6) 84 86 88 92 104

Edit: usando & em vez de%, diferentes precedências do operador (menos colchetes) e funciona melhor com números negativos
Edit2: | em vez de +, op precedência novamente, -2. Obrigado DocMax
Edit3: a compreensão da matriz é 2 caracteres menor que map (), para strings

F=p=>[o+=c[d=n,n=c.search(i),n<4?4|n-d&3:n=n+d&3]for(i of n=o='',c='NESWFRBL',p)]&&o

Teste no console do FireFox / FireBug

console.log(F('NNWEESEE'),F('FFLBFRLF'))

Resultado

FFLBFRLF NNWEESEE

@Optimizer não mais. E esperando encolher ainda mais.
Edc65 27/09/14

O que significa && ono final?
bebe

2
@bebe a função map retorna um array, dentro dele, como efeito colateral, preencho a string o que é o que preciso retornar. array && valueavaliar valuecomo qualquer matriz é avaliada paratruthy
edc65

11
Finalmente! Eu estou olhando para este desde que atingiu 88. A menos que esteja faltando alguma coisa, você pode substituir 4+(n-d&3)por 4|n-d&3e salvar 2 caracteres.
DocMax 30/09/14

4

APL, 72

{^/⍵∊A←'NESW':'FRBL'[1+4|-2-/4,3+A⍳⍵]⋄A[1+4|+\'RBLF'⍳⍵]}

Se as configurações do intérprete puderem ser alteradas sem penalidade, a pontuação será 66 , alterando ⎕IOpara 0:

{^/⍵∊A←'NESW':'FRBL'[4|-2-/0,A⍳⍵]⋄A[4|+\'FRBL'⍳⍵]}

3

Python, 171 139

Não é tão curto quanto as outras soluções, mas acho que deve ser relativamente bom para o que pode ser feito com o Python:

def f(i):a,b='NWSE','FLBR';I=map(a.find,'N'+i);return''.join((b[I[k+1]-I[k]],a[sum(map(b.find,i)[:k+1])%4])[-1in I]for k in range(len(i)))

Versão expandida para melhor legibilidade:

def f(i):
    a, b = 'NWSE', 'FLBR'
    I = map(a.find,'N'+i)     # translate to numbers assuming abs. directions
    J = map(b.index,i)        # translate to numbers assuming rel. directions
    if not -1 in I:
        o = [b[I[k+1]-I[k]] for k in range(len(i))]    # rel. dir. is differences of abs. dir.
    else:
        o = [a[sum(J[:k+1])%4] for k in range(len(i))] # abs. dir. is sum of all rel. dir. so far
    return ''.join(o)

1

Go, 201

type q string;func F(s q)q{d,z:=byte(0),make([]byte,len(s));for i,c:=range[]byte(s){if(c^4)*167%3<2{c=c*156%5;z[i],d="LBRF"[(d-c)%4],c-1;}else{c=(c^43)*3%7-1;d=(d+c)%4;z[i]="NESW"[d];};};return q(z);}

Versão legível:

func F(s string) string {
    d, z, R, A := 0, make([]byte, len(s)), "LBRFLBR", "NESW"
    for i, c := range []byte(s) {
        switch c {
        case 'N': c = R[d+3]; d = 0
        case 'E': c = R[d+2]; d = 1
        case 'S': c = R[d+1]; d = 2
        case 'W': c = R[d]; d = 3
        case 'F': c = A[d]
        case 'R': d = (d + 1) % 4; c = A[d]
        case 'B': d = (d + 2) % 4; c = A[d]
        case 'L': d = (d + 3) % 4; c = A[d]
        }
        z[i] = c
    }
    return string(z)
}


1

GNU sed, 356 bytes

O desafio exige uma transformação simples em um fluxo de caracteres. sed, o editor de stream é a escolha óbvia do idioma ;-)

/[FRBL]/bx                                     # Jump to label x if relative
:y                                             # label y (start of abs->rel loop)
/[FRBL]$/q                                     # quit if string ends in rel char
s/(^|[FRBL])N/\1F/;ty                          # Substitute next abs char with
s/(^|[FRBL])E/\1R/;tr                          #     rel char, then jump to
s/(^|[FRBL])S/\1B/;tb                          #     relevant rotation label if
s/(^|[FRBL])W/\1L/;tl                          #     a match was found
by                                             # loop back to y
:r;y/NESW/WNES/;by                             # Rotation labels: transform then
:b;y/NESW/SWNE/;by                             #     loop back to y
:l;y/NESW/ESWN/;by
:x                                             # label x (start of rel->abs loop)
/^[NESW]/q                                     # quit if string starts w/ abs char
/F([NESW]|$)/s/F([NESW]|$)/N\1/                # Matches for each direction:
/R([NESW]|$)/y/NESW/ESWN/;s/R([NESW]|$)/E\1/   #     rotate, then substitute
/B([NESW]|$)/y/NESW/SWNE/;s/B([NESW]|$)/S\1/
/L([NESW]|$)/y/NESW/WNES/;s/L([NESW]|$)/W\1/
bx                                             # loop back to x

(Comentários e espaços removidos para fins de cálculo da pontuação do golfe)

Resultado:

$ sed -rf absrel.sed <<< NNWEESEE
FFLBFRLF
$ sed -rf absrel.sed <<< FFLBFRLF
NNWEESEE
$ 

Explicação:

A idéia aqui é que, quando alteramos o quadro de referência, sempre existe um mapeamento direto entre {N, E, S, W}e{F, R, B, L} .

No caso de absoluto para relativo, trabalhamos na cadeia de caracteres. Para cada personagem que mapear {N, E, S, W}para {F, R, B, L}, em seguida, gire as restantes [NESW]personagens de acordo com o personagem que apenas mapeada, em seguida, passar para a próxima personagem.

Para o caso de relativo ao absoluto, fazemos o inverso. Trabalhamos para trás na sequência, girando todos os seguintes [NESW]caracteres de acordo com o caractere imediatamente à frente. Em seguida, mapeamos esse caractere {N, E, S, W}para {F, R, B, L}, até chegarmos ao início da string.


0

Haskell, 224

import Data.Function
i=flip(\x->length.takeWhile(/=x))
r=['F','R','B','L']
a=['N','E','S','W']
f s@(x:_)|elem x a=map((r!!).(`mod`4).(4-))$zipWith((-)`on`(i a))('N':s)(s)|True=tail$map((a!!).(`mod`4)).scanl(+)(0)$map(i r) s

Isso atribui números de rotação às direções relativas e números de orientação às direções absolutas; em seguida, encontra as rotações entre orientações sucessivas ou as orientações após rotações sucessivas. A ifunção encontra o índice nas duas legendas.

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.