Escuela de clasificación de aeronaves

8

Dada una cadena que representa una serie de señales manuales de clasificación de aeronaves , escriba una función o programa para calcular la posición final de una aeronave después de estas señales.

NB: las coordenadas en este reto se representan como un par de coordenadas cartesianas, además de un encabezado de dirección de la brújula: (x, y, h)donde xes la coordenada x, yes la coordenada y, y hes uno de N, E, S, o W.

Comienzas con un avión en (0, 0, N)una grilla imaginaria, con los motores apagados. Su entrada es una cadena que contiene pares de caracteres delimitados por comas, donde cada par representa una señal de clasificación. Debe seguir cada señal de clasificación por turnos y generar las coordenadas en (x, y, h)forma de la posición final de la aeronave.

Si una señal requiere que su avión se mueva, suponga que mueve una unidad en la dirección requerida para cada señal de ese tipo que recibe. Si una señal requiere que su avión gire, suponga que gira 90 grados en la dirección requerida para cada señal de ese tipo que recibe.

Un avión no puede moverse si sus motores están apagados. Si los motores de su avión están apagados y recibe una señal de movimiento / giro, no aplique el movimiento / giro.

Señales

Cada señal de clasificación está representada por un par de caracteres. El primero del par representa la posición del brazo izquierdo del mariscal, desde el punto de vista del avión , y el segundo el brazo derecho desde el mismo punto de vista . Este útil cuadro de señales puede ayudar.

o/  —  START ENGINES (no movement, no turn)
-/  —  CUT ENGINES   (no movement, no turn)
-~  —  TURN LEFT     (no movement, left turn)
~-  —  TURN RIGHT    (no movement, right turn)
~~  —  COME FORWARD  (forward movement, no turn)
::  —  MOVE BACK     (backward movement, no turn)
/\  —  NORMAL STOP   (no movement, no turn)

Esta no es la lista completa de señales de clasificación, pero es todo lo que debe admitir.

Entrada

La entrada es una cadena delimitada por comas que contiene pares de caracteres. Esta cadena siempre será válida; no es necesario que valide la entrada.

Salida

La salida es un conjunto de coordenadas como se describe anteriormente. Puede devolverlo en cualquier formato conveniente: si su idioma admite múltiples valores de retorno, puede usarlo; alternativamente, puede usar una cadena (los corchetes que rodean las coordenadas no son obligatorios), matriz, tupla, lista o cualquier otra cosa que le resulte conveniente. La única regla es que debe contener x, yy hlos valores, en ese orden.

Casos de prueba

Input  —  Output
o/,~~,~~,~-,::  —  (-1, 2, E)
::,~-,o/,/\,~~,-~,~~,~~,~~  —  (-3, 1, W)
o/,::,-/,~~,o/,~-,~~,~~,~-  —  (2, -1, S)
o/,~-,~-,::,::,~-,~~,-~  —  (-1, 2, S)
~-,~-,o/,::,::,-/,~~,-~  —  (0, -2, N)
ArtOfCode
fuente
1
¿Qué hacen realmente los motores de arranque y los motores de corte? ¿Solo se ejecutarán esos movimientos entre los motores de arranque y los motores de corte? De lo contrario, no veo la relevancia.
Level River St
@LevelRiverSt "Un avión no puede moverse si sus motores están apagados". He pasado por eso en el texto.
ArtOfCode
Si escribimos una función, ¿podemos tomar la entrada como una lista de instrucciones?
FlipTack
@ Flp.Tkc ¿Puedes cambiar el desafío para hacerlo más fácil? No :)
ArtOfCode
No me di cuenta de que usar una función de "división" incorporada era tan desafiante. No se recomienda tener un formato de entrada rígido en code-golf; el estándar es "tomar la entrada en cualquier formato conveniente".
FlipTack

Respuestas:

2

Java 8, 505 bytes

Golfizado (con la ayuda de @ masterX244 para afeitarse una gran parte)

class f{static boolean T(String u,String v){return u.equals(v);}public static void main(String[]a){java.util.Scanner q=new java.util.Scanner(System.in);String s=q.nextLine();int x=0;int y=0;int d=0;int[][]v={{0,1},{-1,0},{0,-1},{1,0}};int b=1;for(String r:s.split(",")){if(T(r,"o/")||T(r,"-/"))b=~1;if(b<0){if(T(r,‌​"~-"))d=(d+3)%4;if(T‌​(r,"-~"))d=(d+1)%4;i‌​f(T(r,"~~")){x+=v[d]‌​[0];y+=v[d][1];}if(T‌​(r,"::")){x-=v[d][0]‌​;y-=v[d][1];}}}Syste‌​m.out.println("("+x+‌​","+y+","+"NWSE".cha‌​rAt(d)+")");}}

Más legible

class f {
    static boolean T(String u,String v){return u.equals(v);}
    public static void main(String[] a) {
        java.util.Scanner q=new java.util.Scanner(System.in);
        String s=q.nextLine();
        int x=0;
        int y=0;
        int d=0;
        int[][] val = {
                {0,1},  // N
                {-1,0}, // W
                {0,-1}, // S
                {1,0}   // E
        };
        int b=1;
        for (String r: s.split(",")) {
            // toggle b if either start or stop engine
            if(T(r,"o/") || T(r,"-/"))
                b=~1;
            if(b<0){
                // right
                if(T(r,"~-")) d=(d+3)%4;
                // left
                if(T(r,"-~")) d=(d+1)%4;
                // come forward
                if(T(r,"~~")) {
                    x+=val[d][0];
                    y+=val[d][1];
                }
                // move back
                if(T(r,"::")) {
                    x-=val[d][0];
                    y-=val[d][1];
                }
            }
        }
        System.out.print("("+x+","+y+","+"NWSE".charAt(d)+")");
    }
}
Bobas_Pett
fuente
algunos bytes libres: la clase que contiene main () no tiene que ser pública (vea los consejos de golf para Java aquí) y un montón de espacios en blanco que se pueden optimizar (cualquier cosa al lado de los símbolos no alfanuméricos se puede eliminar). también falso se puede escribir como 0> 1
masterX244
Además: reemplazar el bool con un int y compararlo por ser mayor o menor que cero también redujo algunos bytes. (usando * = - 1 para alternarlo) código en el siguiente comentario. Y siempre use print () sobre println cuando solo necesite una línea de salida
masterX244
class f{static boolean T(String u,String v){return u.equals(v);}public static void main(String[]a){java.util.Scanner q=new java.util.Scanner(System.in);String s=q.nextLine();int x=0;int y=0;int d=0;int[][]v={{0,1},{-1,0},{0,-1},{1,0}};int b=1;for(String r:s.split(",")){if(T(r,"o/")||T(r,"-/"))b*=-1;if(b<0){if(T(r,"~-"))d=(d+3)%4;if(T(r,"-~"))d=(d+1)%4;if(T(r,"~~")){x+=v[d][0];y+=v[d][1];}if(T(r,"::")){x-=v[d][0];y-=v[d][1];}}}System.out.print("("+x+","+y+","+"NWSE".charAt(d)+")");}}
masterX244
@ masterX244 thx Estoy claramente un poco al tanto de esto. Agregaré en la edición para imprimir
Bobas_Pett
La importación también es un lugar para optimizar. para una o dos menciones, una referencia totalmente calificada en ambas es más corta que la importación. (el código que pegué en el comentario contiene todas las optimizaciones que encontré)
masterX244
1

Befunge, 201 185 bytes

p10p2p3pv
~/3-*95~<v:+-"/"
  v!:-*53_v
 #_7-:v v0-1
vv!:-3_100>p
 _69*-:v NESW v+g01g
v v-*93_g10g\->4+4%10p
v<_100g >*:10g:1\-\2%!**03g+03p10g:2\-\2%**02g+02p
>>~65*`#v_2g.3g.10g9+5g,@

Pruébalo en línea!

Befunge no tiene un tipo de cadena como tal, por lo que para hacer que las señales sean más fáciles de comparar, cada par de caracteres se convierte en un entero utilizando la fórmula (c1 - 45)/3 + c2 - 47. Esto puede significar que obtendremos coincidencias falsas en una entrada no válida, pero eso no importa si se garantiza que la entrada sea válida.

El resto del código se basa en la manipulación de cuatro "variables": el estado del motor (1 o 0), el encabezado (0 a 3 para NESW) y las posiciones x e y . Los cálculos para cada señal son los siguientes:

Arranque el motor: engine = 1
corte el motor: engine = 0
gire a la izquierda: heading = (heading - engine + 4) % 4
gire a la derecha: heading = (heading + engine) % 4
movimiento: (donde dir es 1 para adelante y -1 para atrás)
y += dir*engine*(1-heading)*!(heading%2)
x += dir*engine*(2-heading)*(heading%2)

Una vez que llegamos al final de la secuencia de entrada, es solo una cuestión de generar el x , y y el encabezado (convertido a un carácter con una simple búsqueda en la tabla).

James Holderness
fuente
1

Python 2.7.12, 295 bytes

from operator import*
l=[0,0]
m=[['N',[0,1]],['E',[1,0]],['S',[0,-1]],['W',[-1,0]]]
n=0
x=raw_input()
for c in x.split(','):
 if'o/'==c:n=1
 if'-/'==c:n=0
 if n:
    if'-~'==c:m=m[-1:]+m[:-1]
    if'~-'==c:m=m[1:]+m[:1]
    if'~~'==c:l=map(add,l,m[0][1])
    if'::'==c:l=map(sub,l,m[0][1])
print l+[m[0][0]]

El primer nivel de sangría después forusa un solo \s. La sangría del segundo nivel utiliza una sola \t. (el wysiwyg reemplaza \tcon múltiples espacios, así que tenga esto en cuenta cuando pruebe el tamaño)

Eric
fuente
3
Hay muchos espacios en blanco extraños que puedes eliminar aquí.
ArtOfCode
No solo espacios en blanco, sino otras ineficiencias fáciles de solucionar. Pruebe los consejos para jugar golf en python para ejemplos específicos.
Ad Hoc Garf Hunter
Tenga en cuenta que en code-golf no tiene que tener ningún indicador de entrada: simplemente puede hacerlo raw_input().
FlipTack
Este código me errores en la línea 15: TypeError: Argument to map() must support iteration(estoy usando Python 2.7.12).
clismique
@ Qwerp-Derp, creo que arreglé el error del mapa ().
Eric
1

Python 2, 142 bytes

s=raw_input()
e=p=0;d=1
while s:exec'd-=e d+=e p+=1j**d*e e=0 0 e=1 p-=1j**d*e 0'.split()[ord(s[0])+ord(s[1])*2&7];s=s[3:]
print p,'ESWN'[d%4]

Ejemplo:

% python2.7 ams.py <<<'o/,~~,~~,~-,::'
(-1+2j) E

Esto imprime números complejos, lo que debería estar bien, creo. El x, y, hel fin es todavía allí, y el 'j'no causa ninguna confusión. Dime si debería cambiarlo.

Lynn
fuente