Convertissez les degrés en l'un des 32 points de la boussole

13

La boussole à 32 points est ... intéressante, c'est le moins qu'on puisse dire.

image

Par Denelson83 (Travail personnel) [ GFDL ou CC-BY-SA-3.0 ], via Wikimedia Commons

Votre défi est de prendre une mesure de degré et de la convertir dans une direction sur la boussole à 32 points.

Chaque direction est plus éloignée de 11,25 (360/32) que la précédente. Par exemple, N (nord) est de 0 degré, NbE (nord par est) est de 11,25 degrés, NNE (nord-nord-est) est de 22,5 degrés, etc.

Quant à la façon dont vous êtes censé obtenir les directions,

  • 0 degré est N, 90 degrés E, 180 degrés S et 270 degrés W.

    • Celles-ci sont appelées directions cardinales.
  • Les points à mi-chemin entre les directions cardinales sont simplement les directions cardinales entre lesquelles ils sont concaténés. N ou S vont toujours en premier, et W ou E sont toujours en deuxième position.

    • Celles-ci sont appelées directions ordinales.
  • Les points à mi-chemin entre les directions cardinales et ordinales sont les directions entre lesquelles ils sont concaténés, encore une fois, avec un «-» entre les deux. Les directions cardinales vont en premier, les secondes ordinales.

    • Celles-ci sont appelées directions intercardinales secondaires.
  • Les points à mi-chemin entre les directions secondaire-intercardinales et les autres directions sont les autres directions "par" la direction cardinale dont ils sont les plus proches (autre que celle directement à côté d'eux, bien sûr).

    • Je ne sais pas comment on les appelle: P

Si toute cette explication blesse autant votre cerveau que le mien, vous pouvez vous référer à ce tableau:

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

Voici un tableau plus détaillé et éventuellement une meilleure explication des points cardinaux.

Votre défi consiste à saisir les données en degrés et à afficher le nom complet de la direction de la boussole à laquelle il correspond, ainsi que son abréviation.

Cas de test:

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

Toute la capitalisation doit être préservée, comme dans les cas de test. Le nombre maximum de décimales est 2. Tous les nombres en entrée seront supérieurs ou égaux à 0 et inférieurs à 360. Si un séparateur décimal est présent, il y aura des chiffres des deux côtés (vous n'avez pas à gérer .1ou 1.).

Il s'agit de , donc le code le plus court en octets l'emporte.

Poignée de porte
la source
@WallyWest Hmm, celui-ci autorise les tableaux, a une capitalisation différente et n'a pas de "entre", mais je ne l'ai pas remarqué (peut-être à cause du ... titre intéressant: P). Je vais voir ce que je peux faire pour le rendre suffisamment différent ...
Poignée de porte
3
@WallyWest Là, vous devez maintenant également sortir l'abréviation. Avec toutes les autres différences, cela devrait suffire à en faire un non-dup. (oh, aussi celui-ci a des tirets aussi)
Poignée de porte
@WallyWest Il n'y a pas de réponse en "R" à votre question précédente (il n'y en avait même pas en "C"!) J'espère que nous en verrons cette fois, mes coéquipiers!
Level River St
Cela aurait été plus amusant s'il y avait une entrée de -360 à 360 degrés (négatif signifie dans le sens inverse des aiguilles d'une montre) et un bonus!.
Mukul Kumar
Pour les personnes ne recherchant pas un défi, la solution la plus simple consiste à trouver la sortie possible pour laquelle la distance est minimale par rapport à l'angle d'entrée, en utilisant un angle de table de recherche <-> nom.
Rivenfall

Réponses:

4

Perl, 250 236 231 188 187

Edit: Quelques octets hors exploitation de la symétrie (comme je l'ai vu dans la solution @bazzargh)

+ Edit: Et quelques trucs diaboliques ...

+ Edit : Retour à l'endroit où j'ai commencé (travailler avec la liste, pas la chaîne), et exploiter plus de symétrie = 1 octet de moins et beaucoup plus laid.

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

Assez imprimé:

$_=(
    (@_=
        (
            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 requis en raison du rmodificateur.

user2846289
la source
Vous avez une faute de frappe dans votre code: sourth devrait être sud (2ème déclaration qui commence par s / b / by ...
RononDex
Ces 3 premières expressions régulières peuvent être remplacées par y / NS / SN /; pour 10 caractères
bazzargh
@bazzargh, oui, et pas seulement ;-)
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)

Vous pouvez copier ce code sur votre console et l'exécuter. Il vous invite à entrer les degrés et à sortir le résultat avecalert();

Javascript non golfé se trouve sur ce violon: http://jsfiddle.net/AezL3/11

RononDex
la source
+1 Sympa mais attention: "Toutes les majuscules doivent être préservées, comme dans les cas de test."
@BenH Quel cas de test échoue au contrôle de capitalisation? Merci pour cela, btw. Cela m'a été utile pour mon interface Web que j'écris.
Steven Lu
Soit dit en passant, cela meurt de 355 degrés à 360 degrés. La solution est simple. Faites calcPoint(32)simplement ce que 0 fait, donc vous pouvez le faire avec %32ou similaire.
Steven Lu
@StevenLu il m'a fallu un certain temps pour comprendre ce que vous voulez dire, mais cette ligne var name = calcPoint(input % 32);fait l'affaire
Orwellophile
4

Haskell 415 372 347 330 317 304 301C

A fini par converger vers une solution comme @ VadimR (et le dos de la symétrie!). Utilisation: h 219sorties"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)

3 autres caractères disparus, merci @shiona.

bazzargh
la source
drop 1est identique à la queue. Aussi, si je ne me trompe pas, vous pouvez faire e l@(x:_)=x:tail$d lpour raser encore un autre caractère.
shiona
ne peux pas croire que j'ai raté ça. Merci!
bazzargh
0

Python 3.8 , 482 438 424 octets

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

Essayez-le en ligne!

C'est ce que j'ai obtenu après avoir joué au golf de la réponse de Tony Goodwin ; affiché à sa propre réponse en raison du lien TIO étant trop long pour un commentaire. S'il choisit de mettre à jour sa réponse à ce qui précède, je supprimerai cette réponse.

Je suppose qu'il est acceptable de soumettre une fonction comme solution plutôt que comme programme complet. Sinon, voici un programme complet à 426 octets.

J'espère que beaucoup peut encore être fait pour raccourcir b.

Edit: golfé de 44 octets, gracieuseté du majestueux morse. Je n'ai toujours pas l'impression d' bavoir fini de jouer au golf.

Edit2: rasé 14 autres en déballant les dict au lieu d'utiliser keys()et items().

calamar
la source
-1

Python, 2103 1647 1103 1034 924 889 848 octets

Très tard, je sais. Merci pour le défi, je mets en place un magnétomètre pour la direction du vent avec mon Pi, et je voulais une solution à 16 points de boussole comme celle-ci pour alimenter les algorithmes de prévisions météorologiques. Tout mon code est en Python, alors voici la version de la solution javascript déjà publiée en Python, mais avec une touche supplémentaire que vous pouvez spécifier soit 32, 16 ou 8 points de la boussole à la variable j, et j'ai changé le décalage de degHead dans l'instruction qui précède, en fonction du nombre de points. J'ai utilisé un alogorithme de changement de nom modifié (et utilisé des variables que je pouvais renommer sans corrompre les mots!) Pour m'assurer de répondre aux exigences de cas de la question.

Je sais que cela ne gagnera pas, car Python est plus verbeux, et moi aussi.

Version courte:

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

Version claire

            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
la source
4
Cette réponse ne montre aucune tentative de golf et est donc susceptible d'être supprimée car elle n'est pas un concurrent sérieux pour le défi
pppery
Bon point - j'ai publié la tentative de golf maintenant.
tony goodwin
Pourquoi avez-vous autant d'indentation dans votre soumission? Cela ne semble pas faire partie de votre réponse, donc je n'en vois pas l'intérêt. Vous pouvez également jouer au golf beaucoup plus, simplement en supprimant tous les espaces supplémentaires, en raccourcissant les noms et les déclarations de variables, et en supprimant complètement les variables redondantes
Jo King
Merci Jo, j'ai à nouveau mis à jour la version. Ai-je tout compris?
tony goodwin
réutilisé un dictionnaire pour les cardinaux beaucoup mieux. À court d'idées maintenant. Si tout va bien assez pour se qualifier?
tony goodwin