Relatif vs absolu

17

Si quelqu'un faisant face au nord au point A dans cette grille voulait que les directions suivent le chemin vert (car il ne peut suivre que les lignes de grille) jusqu'au point B, vous pourriez lui dire:

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

ou équivalent

Allez Forward, Forward, Left, Back, Forward, Right, Left, Forward.
(Lorsqu'une commande de droite , gauche ou arrière signifie implicitement tourner dans cette direction, puis aller de l'avant.)

Chemin A à B

Écrivez une fonction avec un argument qui se traduit entre ces directions absolue et relative le long du même chemin , pas seulement au même point. Supposons que la personne dirigée commence toujours face au nord.

Si l'argument est une chaîne de lettres NSEW, retournez les directions relatives équivalentes.
par exemple, f("NNWEESEE")renvoie la chaîne FFLBFRLF.

Si l'argument est une chaîne de lettres FBLR, retournez les directions absolues équivalentes.
par exemple, f("FFLBFRLF")renvoie la chaîne NNWEESEE.

La chaîne vide se donne. Ne supposez aucun autre cas d'entrée.

Si votre langue n'a pas de fonctions ou de chaînes, utilisez ce qui vous semble le plus approprié.

Le code le plus court en octets gagne.

Loisirs de Calvin
la source
Supposons-nous qu'une personne commence toujours avec la tête tournée vers le nord? De cette façon, en termes relatifs pour aller vers l'Est, il lui faudrait tourner à droite, plutôt que de simplement dire Forward
Optimizer
@Optimizer Oui, au nord. Et oui à votre autre point. Rest égal Eau début.
Calvin's Hobbies
1
Yay! Tu as changé ta photo pour confirmer ce que j'ai toujours pensé!
Justin
4
Êtes-vous de nouveau accro à PPCG? ;)
Martin Ender
4
@ MartinBüttner Soit ça, soit je suis très bon pour déguiser mes problèmes de devoirs. ;)
Calvin's Hobbies

Réponses:

6

CJam, 57 53 49

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

La version précédente

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

Exemple:

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

Production:

FFLBFRLF
NNWEESEE

Comment ça fonctionne

{
  "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. ";
}
jimmy23013
la source
6

C ++, 99 97

Ce qui suit est formaté comme une expression lambda. Il prend un char*argument et l'écrase.

[](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];}

Pour ceux qui ne connaissent pas cette fonctionnalité (comme moi il y a 1 heure), utilisez-la comme suit:

#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';
}

Quelques explications:

  • Lorsque vous utilisez du code comme flag ? (x = y) : (x += z), la deuxième paire de parenthèses est requise en C. J'ai donc utilisé C ++ à la place!
  • C ++ nécessite de spécifier un type de retour pour une fonction. À moins que j'utilise une expression lambda, c'est! Un bonus supplémentaire est que je n'ai pas besoin de perdre 1 caractère sur le nom de la fonction.
  • Le code *s*9%37&4teste le premier octet; le résultat est 4 si c'est l'un des NESW; 0 sinon
  • Le code *s%11/3convertit les octets NESWen 0, 1, 2, 3
  • Le code *s%73%10convertit les octets FRBLen 0, 9, 6, 3 (qui est 0, 1, 2, 3 modulo 4)
  • Lors de la conversion de directions relatives en absolu, je n'ai pas besoin de la dvariable. J'ai essayé de réorganiser le code pour l'éliminer complètement, mais cela semble impossible ...
anatolyg
la source
1
J'aime beaucoup la façon dont vous convertissez les lettres en chiffres. :)
Emil
6

JavaScript (E6) 84 86 88 92104

Edit: en utilisant & au lieu de%, priorité de l'opérateur différente (moins de parenthèses) et fonctionne mieux avec des nombres négatifs
Edit2: | au lieu de +, op priorité à nouveau, -2. Merci DocMax
Edit3: la compréhension du tableau est 2 caractères plus courte que map (), pour les chaînes

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

Test dans la console FireFox / FireBug

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

Production

FFLBFRLF NNWEESEE
edc65
la source
@Optimizer plus. Et en espérant rétrécir encore plus.
edc65
Que signifie && oà la fin?
bebe
2
@bebe la fonction map retourne un tableau, à l'intérieur, comme effet secondaire, je remplis la chaîne o qui est ce que je dois retourner. array && valueévaluer valuecomme n'importe quel tableau évaluertruthy
edc65
1
Finalement! Je les yeux fixés sur celui - ci car il a frappé 88. À moins que je manque quelque chose, vous pouvez remplacer 4+(n-d&3)avec 4|n-d&3et enregistrer 2 caractères.
DocMax
4

APL, 72

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

Si les configurations de l'interpréteur peuvent être modifiées sans pénalité, alors le score est de 66 , en changeant ⎕IOen 0:

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

Python, 171 139

Pas aussi court que les autres solutions, mais je suppose que cela devrait être relativement bon pour ce qui peut être fait avec 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)))

Version étendue pour une lisibilité légèrement meilleure:

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)
Emil
la source
1

Allez, 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);}

Version lisible:

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)
}

David
la source
1

GNU sed, 356 octets

Le défi appelle une simple transformation sur un flux de personnages. sed, l'éditeur de flux est le choix évident de la langue ;-)

/[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

(Commentaires et espaces supprimés aux fins du calcul du score de golf)

Production:

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

Explication:

L'idée ici est que lorsque nous changeons le cadre de référence, il y a toujours une correspondance directe entre {N, E, S, W}et {F, R, B, L}.

Dans le cas de l'absolu au relatif, nous travaillons en avant à travers la chaîne. Pour chaque caractère nous dressons la carte {N, E, S, W}à {F, R, B, L}, puis tourner les autres [NESW]caractères selon le caractère que nous venons cartographié, puis passer sur le caractère suivant.

Pour le cas de relatif à absolu, nous faisons l'inverse. Nous travaillons en arrière dans la chaîne, en faisant tourner tous les [NESW]caractères suivants en fonction du caractère immédiatement devant. Ensuite , nous cartographions ce caractère {N, E, S, W}à {F, R, B, L}, jusqu'à ce que nous arrivons au début de la chaîne.

Traumatisme numérique
la source
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

Cela attribue des numéros de rotation aux directions relatives et des numéros d'orientation aux directions absolues, puis trouve les rotations entre les orientations successives ou les orientations après les rotations successives. La ifonction trouve l'index dans les deux légendes.

archaephyrryx
la source