Convierta grados a uno de los 32 puntos de la brújula

13

La brújula de 32 puntos es ... interesante, por decir lo menos.

imagen

Por Denelson83 (Trabajo propio) [ GFDL o CC-BY-SA-3.0 ], a través de Wikimedia Commons

Su desafío es tomar una medida de grado y convertirla en una dirección en la brújula de 32 puntos.

Cada dirección es 11.25 (360/32) grados más que la anterior. Por ejemplo, N (norte) es 0 grados, NbE (norte por este) es 11.25 grados, NNE (norte-noreste) es 22.5 grados, etc.

En cuanto a cómo se supone que debes obtener las instrucciones,

  • 0 grados es N, 90 grados es E, 180 grados es S y 270 grados es W.

    • Estas se llaman direcciones cardinales.
  • Los puntos intermedios entre las direcciones cardinales son simplemente las direcciones cardinales que están entre concatenados. N o S siempre van primero, y W o E siempre son segundos.

    • Estas se llaman direcciones ordinales.
  • Los puntos intermedios entre las direcciones cardinales y ordinales son las direcciones entre concatenadas, de nuevo, con un "-" en el medio. Las direcciones cardinales van primero, ordinal segundo.

    • Estas se llaman direcciones secundarias-intercardinales.
  • Los puntos intermedios entre las direcciones secundaria-intercardinal y otras direcciones son las otras direcciones "por" la dirección cardinal a la que están más cercanas (aparte de la que está directamente al lado de ellas, por supuesto).

    • No tengo idea de cómo se llaman: P

Si toda esta explicación le hace tanto daño a su cerebro como al mío, puede consultar este cuadro:

1   North               N
2   North by east       NbE
3   North-northeast     NNE
4   Northeast by north  NEbN
5   Northeast           NE
6   Northeast by east   NEbE
7   East-northeast      ENE
8   East by north       EbN
9   East                E
10  East by south       EbS
11  East-southeast      ESE
12  Southeast by east   SEbE
13  Southeast           SE
14  Southeast by south  SEbS
15  South-southeast     SSE
16  South by east       SbE
17  South               S
18  South by west       SbW
19  South-southwest     SSW
20  Southwest by south  SWbS
21  Southwest           SW
22  Southwest by west   SWbW
23  West-southwest      WSW
24  West by south       WbS
25  West                W
26  West by north       WbN
27  West-northwest      WNW
28  Northwest by west   NWbW
29  Northwest           NW
30  Northwest by north  NWbN
31  North-northwest     NNW
32  North by west       NbW

Aquí hay una tabla más detallada y posiblemente una mejor explicación de los puntos de la brújula.

Su desafío es ingresar datos en grados y generar el nombre completo de la dirección de la brújula a la que corresponde, junto con su abreviatura.

Casos de prueba:

Input  Output
0      North N
23.97  North-northeast NNE
33.7   Northeast by north NEbN
73.12  East-northeast ENE
73.13  East by north EbN
219    Southwest by south SWbS
275    West W
276    West by north WbN
287    West-northwest WNW

Toda capitalización debe ser preservada, como en los casos de prueba. El número máximo de lugares decimales es 2. Todos los números de entrada serán mayores o iguales a 0, y menores que 360. Si hay un punto decimal, habrá dígitos en ambos lados (no tiene que manejar .1o 1.).

Este es el , por lo que gana el código más corto en bytes.

Pomo de la puerta
fuente
@WallyWest Hmm, este permite matrices, tiene diferentes mayúsculas y no tiene "en medio", pero no me di cuenta de eso (posiblemente debido al ... título interesante: P). Veré qué puedo hacer para que sea lo suficientemente diferente ...
Pomo de la puerta
3
@WallyWest Allí, ahora también debe generar la abreviatura. Junto con todas las otras diferencias, eso debería ser suficiente para que no sea dup. (oh, este también tiene guiones)
Pomo de la puerta
@WallyWest No habrá respuestas en "R" a su pregunta anterior (¡ni siquiera hubo ninguna en "C"!) ¡Espero que veamos algunas esta vez, compañeros!
Level River St
Hubiera sido más divertido si hubiera una entrada de -360 a 360 grados (negativo significa en sentido antihorario) y una bonificación.
Mukul Kumar
Para las personas que no buscan un desafío, la solución fácil es encontrar la salida posible para la cual la distancia es mínima desde el ángulo de entrada, utilizando un nombre de ángulo de tabla de búsqueda <->.
Rivenfall

Respuestas:

4

Perl, 250 236 231 188 187

Editar: algunos bytes de la simetría de explotación (como he visto en la solución @bazzargh)

+ Editar: Y algunos trucos malvados ...

+ Editar : Volver a donde comencé (trabajando con la lista, no con la cadena), y explotando más simetría = 1 byte apagado y mucho más feo.

$_=((@_=(1,@_=qw(1b3 1-13 13b1 13 13b3 3-13 3b1),3,map{y/1/2/r}reverse@_)),map{y/312/421/r}@_)[int<>/11.25+.5];print ucfirst s/\w/(' by ',north,south,east,west)[$&]/ger,' ',y/1-4-/NSEW/dr

Bonito estampado:

$_=(
    (@_=
        (
            1,
            @_=qw(1b3 1-13 13b1 13 13b3 3-13 3b1),
            3,
            map{y/1/2/r}reverse@_
        )
    ),map{y/312/421/r}@_
)[int<>/11.25+.5];

print ucfirst s/\w/(' by ',north,south,east,west)[$&]/ger,' ',y/1-4-/NSEW/dr

5.014 requerido debido al rmodificador.

usuario2846289
fuente
Tiene un error tipográfico en su código: sourth debe estar al sur (segunda declaración que comienza con s / b / por ...
RononDex
Esos primeros 3 regexps pueden ser reemplazados por y / NS / SN /; por 10 caracteres
bazzargh
@bazzargh, sí, y no solo eso ;-)
usuario2846289
6

Javascript 470 453 438 434 432 421 404

s=String;s.prototype.a=s.prototype.replace;var a=prompt()/11.25,a=a+0.5|0,b,k,c=a,d=c%8,c=c/8|0,e=["north","east","south","west"],f,g,h;f=e[c];g=e[(c+1)%4];h=f==e[0]|f==e[2]?f+g:g+f;b="1;1 by 2;1-C;C by 1;C;C by 2;2-C;2 by 1".split(";")[d].a(1,f).a(2,g).a("C",h);k=b.a(/north/g,"N").a(/east/g,"E").a(/south/g,"S").a(/west/g,"W").a(/by/g,"b").a(/[\s-]/g,"");b=b[0].toUpperCase()+b.slice(1);alert(b+" "+k)

Puede copiar este código en su consola y ejecutarlo. Le solicita los grados de entrada y genera el resultado conalert();

Puede encontrar Javascript sin campos en este violín: http://jsfiddle.net/AezL3/11

RononDex
fuente
+1 Agradable pero tenga cuidado: "Se debe preservar toda la capitalización, como en los casos de prueba".
@BenH ¿Qué caso de prueba falla la verificación de capitalización? Gracias por esto, por cierto. Esto fue útil para mi interfaz web que estoy escribiendo.
Steven Lu
Por cierto, esto muere de 355 grados a 360 grados. La solución es fácil. Simplemente haga calcPoint(32)lo que hace 0, para que pueda hacer esto con %32o cualquier similar.
Steven Lu
@StevenLu me tomó un tiempo entender lo que quieres decir, pero esta línea var name = calcPoint(input % 32);funciona
Orwellophile
4

Haskell 415 372 347 330 317 304 301C

Terminé convergiendo en una solución como la de @ VadimR (¡y la simetría ha vuelto!). Uso: h 219salidas"Southwest by south SWbS"

d"N"="north"
d"S"="south"
d"E"="east"
d"W"="west"
d"b"=" by "
d"-"="-"
d(x:y)=d[x]++d y
e(x:y)=x:tail(d$x:y)
k 'N'='S'
k 'S'='N'
k 'E'='W'
k x=x
r="N NbE N-NE NEbN NE NEbE E-NE EbN E EbS E-SE SEbE SE SEbS S-SE SbE "
p=words$r++(map k r)
g x=p!!mod(round$x/11.25)32
h x=e(g x)++(filter(/='-')$' ':g x)

Se han ido 3 caracteres más, gracias @shiona.

bazzargh
fuente
drop 1Es lo mismo que la cola. Además, si no me equivoco, puedes hacerlo e l@(x:_)=x:tail$d lpara afeitarte un poco más.
shiona
No puedo creer que me haya perdido eso. ¡Gracias!
bazzargh
0

Python 3.8 , 482 438 424 bytes

lambda h:' '.join([b(h),a(a(a(b(h)),1),d={' by ':'b','-':''})])
L=str.lower
c={'North':'N','East':'E','South':'S','West':'W'}
a=lambda t,l=0,d=c:[*(t:=t.replace([i,L(i)][l],d[i])for i in[*d])][-1]
b=lambda h,k=[*c]:a('W|W by x|W-z|Z by w|Z|Z by x|X-z|X by w'.split('|')[int((q:=h*4/45+.5)%8)],d={'W':(W:=[*k][(v:=int(q//8)%4)]),'X':(X:=[*k][(v+1)%4]),'w':(w:=L(W)),'x':(x:=L(X)),'Z':(Z:=[W+x,X+w][W in'EastWest']),'z':L(Z)})

Pruébalo en línea!

Esto es lo que obtuve después de jugar al golf con la respuesta de Tony Goodwin ; publicado en su propia respuesta debido a que el enlace TIO es demasiado largo para un comentario. Si elige actualizar su respuesta a lo anterior, eliminaré esta respuesta.

Supongo que es aceptable enviar una función como una solución en lugar de un programa completo. Si no, aquí hay un programa completo de 426 bytes.

Espero que todavía se pueda hacer mucho para acortar b.

Editar: Golfed 44 bytes, cortesía de la majestuosa morsa. Todavía no siento que bse haya terminado de jugar al golf.

Edit2: afeitó otro 14 por desembalar predice en vez de usar keys()y items().

calamar
fuente
-1

Python, 2103 1647 1103 1034 924 889 848 bytes

Muy tarde, lo sé. Gracias por el desafío, estoy configurando un magnetómetro para la dirección del viento con mi Pi, y quería una solución de 16 puntos de brújula como esta para alimentar los algoritmos de pronóstico del tiempo. Todo mi código está en Python, así que aquí hay una versión de la solución de JavaScript ya publicada en Python, pero con un giro adicional que puede especificar 32, 16 u 8 puntos de la brújula en la variable j, y he cambiado el desplazamiento de degHead en la declaración anterior, dependiendo del número de puntos. Utilicé un alogoritmo de cambio de nombre modificado (¡y utilicé variables que podía cambiar de nombre sin corromper las palabras!) Para asegurarme de que cumplía con los requisitos del caso de la pregunta.

Sé que esto no ganará, ya que Python es más prolijo, y yo también.

Version corta:

  def a(t,d,l):
    for i,j in d.items():
      if l:
        i=i.lower()
      t=t.replace(i,j)
    return t
  def b(h,q):
    p=32
    r=360
    h=(h+(r/q/2))/(r/p)
    j=int(int(int(h %8)%8/(p/q))*p/q)
    h=int(h/8)%4
    k=c.keys()
    u=['W','W by x','W-z','Z by w','Z','Z by x','X-z','X by w']
    d={}
    d['W']=list(k)[h]
    d['w']=d['W'].lower()
    d['X']=list(k)[(h+1)%4]
    d['x']=d['X'].lower()
    if(d['W']=='North' or d['W']=='South'):
      d['Z']=d['W']+d['x']
    else:
      d['Z']=d['X']+d['w']
    d['z']=d['Z'].lower()
    return a(u[j],d,0)
  def g(n):
    n=a(n,c,0)
    n=a(n,c,1)
    d={'by':'b',' ':'','-':''}
    return a(n,d,0)
  def v(m):
    while True:
      try:
        return float(input(m))
      except ValueError:
        print("?")
  c={'North':'N','East':'E','South':'S','West':'W'}
  while True:
    h=v("?")
    n=b(h,32)
    print(h,n,g(n))

Versión clara

            import math
            import sys

            def calcPoint(degHead, points):
                maxPoints=32
                if points not in(8,16,32):
                    sys.exit("not a good question")
                degHead=(degHead+(360/points/2))/(360/maxPoints)
                j =int(int( int(degHead  % 8)%8/(maxPoints/points))*maxPoints/points)
                degHead = int(degHead / 8) % 4
                cardinal = ['North', 'East', 'South', 'West']
                pointDesc = ['W', 'W by x', 'W-z', 'Z by w', 'Z', 'Z by x', 'X-z', 'X by w']#vars not compass points
                W = cardinal[degHead]
                X = cardinal[(degHead + 1) % 4]
                w=W.lower()
                x=X.lower()
                if (W == cardinal[0] or W == cardinal[2]) :
                    Z =W + x
                else:
                    Z =X + w
                z=Z.lower()
                return pointDesc[j].replace('W', W).replace('X', X).replace('w', w).replace('x', x).replace('Z', Z).replace('z', z);

            def getShortName(name): 
                return name.replace('North', 'N').replace('East', 'E').replace('South', 'S').replace('West', 'W').replace('north', 'N').replace('east', 'E').replace('south', 'S').replace('west', 'W').replace('by', 'b').replace(' ', '').replace('-', '')

            def input_number(msg, err_msg=None):
                while True:
                    try:
                        return float(input(msg))
                    except ValueError:
                        sys.exit("not a number")

            while True:
                headingCalib=input_number("input a number: ")
                print (headingCalib, end=' ')
                name = calcPoint(headingCalib,32) #degrees heading, points of compass 8,16 or 32)
                print (name, end=' ')
                shortName = getShortName(name)
                print (shortName)
Tony Goodwin
fuente
44
Esta respuesta muestra ningún intento de golf y, por tanto, está sujeto a eliminación no como un serio contendiente para el desafío
pppery
Punto justo: he publicado el intento de jugar al golf ahora.
Tony Goodwin
¿Por qué tienes tanta sangría en tu presentación? No parece ser parte de tu respuesta, así que no veo el punto. También puede jugar mucho más, simplemente eliminando todos los espacios en blanco adicionales, acortando los nombres y las declaraciones de variables, y eliminando las variables redundantes por completo
Jo King
Gracias Jo, he actualizado la versión nuevamente. ¿Lo tengo todo?
Tony Goodwin
reutilizó un diccionario para cardenales mucho mejor. Fuera de las ideas ahora. Con suerte lo suficiente como para calificar?
tony goodwin