Преобразовать градусы в одну из 32 точек компаса

13

32-точечный компас ... интересен, если не сказать больше.

образ

По Denelson83 (собственная работа) [ GFDL или CC-BY-SA-3.0 ], через Wikimedia Commons

Ваша задача - измерить градус и преобразовать его в направление на 32-точечном компасе.

Каждое направление на 11,25 (360/32) градуса дальше предыдущего. Например, N (север) составляет 0 градусов, NbE (север на восток) составляет 11,25 градуса, NNE (север-северо-восток) составляет 22,5 градуса и т. Д.

Что касается того, как вы должны получить указания,

  • 0 градусов - это N, 90 градусов - это E, 180 градусов - это S, а 270 градусов - это W.

    • Это так называемые кардинальные направления.
  • Точки на полпути между основными направлениями - это просто основные направления между сцепленными. N или S всегда идут первыми, а W или E всегда вторыми.

    • Это так называемые порядковые направления.
  • Точки на полпути между кардинальным и порядковым направлениями - это направления между конкатенацией, опять же, с «-» между ними. Кардинальные направления идут первыми, порядковые вторыми.

    • Это так называемые вторично-межкардинальные направления.
  • Точки на полпути между вторичными межкардинальными направлениями и другими направлениями являются другими направлениями «по» кардинальному направлению, к которому они ближе всего (конечно, кроме того, которое находится непосредственно рядом с ними).

    • Я понятия не имею, как они называются: P

Если все это объяснение вредит вашему мозгу так же, как моему, вы можете обратиться к этой таблице:

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

Вот более подробная таблица и, возможно, лучшее объяснение точек компаса.

Ваша задача состоит в том, чтобы взять ввод в градусах и вывести полное имя направления компаса, которому оно соответствует, вместе с его сокращением.

Тестовые случаи:

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

Вся заглавная буква должна быть сохранена, как в тестовых примерах. Максимальное количество десятичных знаков равно 2. Все входные числа будут больше или равны 0 и меньше 360. Если присутствует десятичная точка, с обеих сторон будут цифры (вам не нужно обрабатывать .1или 1.).

Это , поэтому выигрывает самый короткий код в байтах.

Дверная ручка
источник
@WallyWest Хм, этот разрешает массивы, имеет разную капитализацию и не имеет «между», но я этого не заметил (возможно, из-за ... интересного названия: P). Я посмотрю, что я могу сделать, чтобы сделать это достаточно по-другому ...
Дверная ручка
3
@WallyWest Там, теперь вы также должны вывести аббревиатуру. Наряду со всеми другими различиями, этого должно быть достаточно, чтобы сделать его недопустимым. (о, у этого также есть черточки)
Дверная ручка
@WallyWest В "R" нет ответов на ваш предыдущий вопрос (даже не было "C"!) Я надеюсь, что мы увидим некоторых на этот раз, товарищи по кораблю!
Уровень Ривер-Сент-
Было бы веселее, если бы вход был от -360 до 360 градусов (отрицательный означает против часовой стрелки) и бонус !.
Мукул Кумар
Для людей, не ищущих проблем, простое решение - найти возможный выход, для которого расстояние минимально от угла ввода, используя имя таблицы поиска <-> name.
Rivenfall

Ответы:

4

Perl, 250 236 231 188 187

Изменить: некоторые байты от использования симметрии (как я видел в решении @bazzargh)

+ Редактировать: И некоторые злые трюки ...

+ Редактировать : вернуться к тому, с чего я начал (работа со списком, а не со строкой), и использовать больше симметрии = 1 байт выключен и намного уродливее.

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

Довольно отпечатанный:

$_=(
    (@_=
        (
            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 требуется из-за rмодификатора.

user2846289
источник
В вашем коде есть опечатка: sourth должен быть южнее (2-е утверждение, начинающееся с s / b / by ...
RononDex
Эти первые 3 регулярных выражения можно заменить на y / NS / SN /; за 10 символов
bazzargh
@bazzargh, да, и не только это ;-)
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)

Вы можете скопировать этот код на консоль и выполнить его. Он запрашивает ввод градусов и выводит результат сalert();

Разоблаченный Javascript можно найти на этой скрипке: http://jsfiddle.net/AezL3/11

RononDex
источник
+1 Приятно, но будьте осторожны: «Все заглавные буквы должны быть сохранены, как в тестовых примерах».
@BenH Какой тестовый пример не проходит проверку на заглавные буквы? Спасибо за это, кстати. Это пригодилось для моего веб-интерфейса, который я пишу.
Стивен Лу
Кстати, это умирает на 355 градусов до 360 градусов. Исправить легко. Просто заставьте calcPoint(32)делать то, что делает 0, так что вы можете сделать это с %32или любым другим.
Стивен Лу
@ StevenLu мне потребовалось некоторое время, чтобы понять, что ты var name = calcPoint(input % 32);
свое дело
4

Haskell 415 372 347 330 317 304 301C

Закончилось сходом к решению, подобному @ VadimR (и обратно симметрии!). Использование: h 219выходы"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 символа исчезли, спасибо @shiona.

bazzargh
источник
drop 1такой же, как хвост. Также, если я не ошибаюсь, вы можете e l@(x:_)=x:tail$d lпобрить еще один символ.
Шион
не могу поверить, что я пропустил это. Благодарность!
Bazzargh
0

Python 3.8 , 482 438 424 байт

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

Попробуйте онлайн!

Это то, что я получил после игры в гольф от ответа Тони Гудвина ; размещен в своем собственном ответе из-за слишком длинной ссылки TIO для комментария. Если он решит обновить свой ответ выше, я удалю этот ответ.

Я предполагаю, что приемлемо представить функцию в качестве решения, а не полную программу. Если нет, то здесь полная программа на 426 байт.

Я ожидаю, что многое еще можно сделать, чтобы сократить b.

Изменить: Гольф от 44 байтов, любезность величественного моржа. Все еще не чувствую, что bзакончил быть гольфом.

Edit2: сбрил еще 14 путем распаковки диктов вместо использования keys()и items().

Кальмар
источник
-1

Питон, 2103 1647 1103 1034 924 889 848 байт

Очень поздно, я знаю. Спасибо за вызов, я настраиваю магнитометр для направления ветра с моим Pi, и хотел получить 16-точечное компасное решение, подобное этому, для включения в алгоритмы прогнозирования погоды. Весь мой код написан на Python, так что вот версия решения javascript, уже опубликованная на Python, но с дополнительным поворотом, в котором вы можете указать 32, 16 или 8 точек компаса для переменной j, и я изменил смещение degHead в заявлении перед ним, в зависимости от количества точек. Я использовал измененный алгоритм переименования (и использовал переменные, которые я мог переименовать, не повреждая слова!), Чтобы убедиться, что я отвечал требованиям к конкретному вопросу.

Я знаю, что это не победит, так как Python более многословен, и я тоже.

Укороченная версия:

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

Очистить версию

            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
Этот ответ не показывает попытки играть в гольф и поэтому может быть удален как несерьезный претендент на вызов
pppery
Справедливо: я опубликовал попытку игры в гольф сейчас.
Тони Гудвин
Почему у вас так много отступов в вашем представлении? Это не похоже на ваш ответ, поэтому я не вижу в этом смысла. Вы также можете использовать это намного больше, просто удалив все лишние пробелы, сократив имена и объявления переменных, а также удалив лишние переменные
Jo King
Спасибо Джо, я снова обновил версию. Я все понял?
Тони Гудвин
многократно использовать словарь для кардиналов. Из идей сейчас. Надеюсь, достаточно для квалификации?
Тони Гудвин