Converta graus em um dos 32 pontos da bússola


13

A bússola de 32 pontos é ... interessante, para dizer o mínimo.

imagem

Por Denelson83 (Trabalho próprio) [ GFDL ou CC-BY-SA-3.0 ], via Wikimedia Commons

Seu desafio é tomar uma medida de grau e convertê-la em uma direção na bússola de 32 pontos.

Cada direção tem 11,25 (360/32) graus a mais que a anterior. Por exemplo, N (norte) é 0 graus, NbE (norte a leste) é 11,25 graus, NNE (norte-nordeste) é 22,5 graus, etc.

Quanto a como você deve obter as instruções,

  • 0 graus é N, 90 graus é E, 180 graus é S e 270 graus é W.

    • Essas são chamadas direções cardinais.
  • Os pontos intermediários entre as direções cardinais são simplesmente as direções cardinais entre as concatenadas. N ou S sempre são os primeiros e W ou E são os segundos.

    • Essas são chamadas direções ordinais.
  • Os pontos intermediários entre as direções cardinal e ordinal são as direções entre as quais são concatenadas, novamente, com um "-" no meio. As direções cardeais vão primeiro, segundo ordinal.

    • Estes são chamados de direções intercardinais secundárias.
  • Os pontos intermediários entre as direções secundário-intercardinal e outras direções são as outras direções "por" a direção cardinal mais próxima (diferente da diretamente ao lado delas, é claro).

    • Não faço ideia do que se chama: P

Se toda essa explicação machuca seu cérebro tanto quanto o meu, você pode consultar este gráfico:

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

Aqui está um gráfico mais detalhado e, possivelmente, uma melhor explicação dos pontos da bússola.

Seu desafio é obter entradas em graus e exibir o nome completo da direção da bússola a que corresponde, juntamente com sua abreviação.

Casos de teste:

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 capitalização deve ser preservada, como nos casos de teste. O número máximo de casas decimais é 2. Todos os números de entrada serão maiores ou iguais a 0 e menores que 360. Se houver um ponto decimal, haverá dígitos nos dois lados (você não precisa manipular .1ou 1.).

Isso é , então o código mais curto em bytes vence.


@WallyWest Hmm, este permite matrizes, tem letras maiúsculas diferentes e não tem "entre", mas eu não percebi isso (possivelmente por causa do ... título interessante: P). Vou ver o que posso fazer para torná-lo diferente o suficiente ...
Maçaneta da porta

3
@WallyWest Ali, agora você também deve exibir a abreviação. Juntamente com todas as outras diferenças, isso deve ser suficiente para torná-lo um não-dup. (oh, também este também tem traços) #
Maçaneta

@WallyWest Não há respostas em "R" para a sua pergunta anterior (não havia nenhuma em "C"!) Espero que desta vez possamos ver algumas, colegas de navio!
Level River St

Teria sido mais divertido se houvesse entrada de -360 a 360 graus (negativo significa anti-horário) e um bônus !.
Mukul Kumar 25/02

Para pessoas que não procuram um desafio, a solução mais fácil é encontrar a saída possível para a qual a distância é mínima do ângulo de entrada, usando um nome <-> do ângulo da tabela de pesquisa.
Rivenfall

Respostas:


4

Perl, 250 236 231 188 187

Edit: Alguns bytes de exploração de simetria (como já vi na solução @bazzargh)

+ Edit: E alguns truques do mal ...

+ Editar : Voltar para onde eu comecei (trabalhando com lista, não com string) e explorando mais simetria = 1 byte de folga e muito mais feio.

$_=((@_=(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

Pretty-impresso:

$_=(
    (@_=
        (
            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 necessário devido ao rmodificador.


Você tem um erro de digitação no seu código: Sourth deve ser sul (2ª declaração que começa com s / b / por ...
RononDex

Esses três primeiros regexps podem ser substituídos por y / NS / SN /; para 10 caracteres
bazzargh

@bazzargh, sim, e não só isso ;-)
user2846289

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)

Você pode copiar esse código no seu console e executá-lo. Ele solicita a entrada de graus e gera o resultado comalert();

Javascript não destruído pode ser encontrado neste violino: http://jsfiddle.net/AezL3/11


+1 Agradável, mas tenha cuidado: "Toda capitalização deve ser preservada, como nos casos de teste".

@BenH Qual caso de teste falha na verificação de maiúsculas? Obrigado por isso, btw. Isso foi útil para minha interface da web que estou escrevendo.
Steven Lu

By the way, isso morre por 355 graus a 360 graus. A correção é fácil. Basta fazer o calcPoint(32)que 0 faz, para que você possa fazer isso com %32ou similar.
Steven Lu

@StevenLu ele me levou um tempo para descobrir o que você quer dizer, mas esta linha var name = calcPoint(input % 32);faz o truque
Orwellophile

4

Haskell 415 372 347 330 317 304 301C

Acabou convergindo para uma solução como a do @ VadimR (e a simetria voltou!). Uso: h 219saídas"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)

Mais 3 caracteres desaparecidos, obrigado @shiona.


drop 1é o mesmo que cauda. Além disso, se não me engano, você pode fazer e l@(x:_)=x:tail$d lpara raspar ainda mais um char.
shiona

Não posso acreditar que senti falta disso. Obrigado!
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)})

Experimente online!

Foi isso que obtive depois de jogar a resposta de Tony Goodwin ; postado em sua própria resposta devido ao fato do link TIO ser muito longo para um comentário. Se ele optar por atualizar sua resposta para o acima, eu excluirei esta resposta.

Estou assumindo que é aceitável enviar uma função como uma solução e não como um programa completo. Caso contrário, aqui está um programa completo em 426 bytes.

Espero que muito ainda possa ser feito para diminuir b.

Edit: Golfed off 44 bytes, cortesia da morsa majestosa. Ainda não sinto que bestá terminando de jogar golfe.

Edit2: Raspou outros 14 descompactando dict em vez de usar keys()e items().


-1

Python, 2103 1647 1103 1034 924 889 848 bytes

Muito tarde, eu sei. Obrigado pelo desafio, estou configurando um magnetômetro para a direção do vento com o meu Pi e queria uma solução de bússola de 16 pontos como essa para alimentar os algoritmos de previsão do tempo. Todo o meu código está em Python, então aqui está a versão da solução javascript já publicada em Python, mas com um toque extra que você pode especificar 32, 16 ou 8 pontos da bússola na variável j, e eu mudei o deslocamento de degHead na declaração anterior, dependendo do número de pontos. Usei um alogoritmo de renomeação modificado (e usei variáveis ​​que eu poderia renomear sem corromper as palavras!) Para garantir que atendesse aos requisitos de caso da pergunta.

Eu sei que isso não vai ganhar, como Python é mais prolixo, e eu também.

Versão curta:

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

Versão 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)

4
Essa resposta mostra nenhuma tentativa de golfe e é, portanto, sujeitos a eliminação como não um candidato sério para o desafio
pppery

Ponto justo - afixei a tentativa de jogar golfe agora.
Goodwin tony

Por que você tem tanto recuo na sua inscrição? Parece que não faz parte da sua resposta, então não entendo o motivo. Você também pode golfe este muito mais, apenas removendo todo o espaço em branco extra, encurtando nomes e declarações de variáveis, e remoção de variáveis redundantes completamente
Jo rei

Obrigado Jo, atualizei a versão novamente. Eu entendi tudo?
Goodwin tony

reutilizou um dicionário para cardeais muito melhor. Fora de idéias agora. Esperançosamente o suficiente para se qualificar?
Goodwin tony
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.