Копати до Австралії - антиподи


24

Фон

Незліченні покоління дітей замислювалися, де б вони опинилися, якби викопали яму прямо вниз. Виявляється, це не дивно було б досить небезпечно , але все одно ...

Антиподи - це точки, що знаходяться прямо навпроти один одного на поверхні Землі. Це означає, що якби між двома точками була проведена лінія, вона проходила б через центр Землі.

Виклик

Напишіть програму або функцію, яка, задавши крапку, знаходить свій антипод.

У цьому виклику точки представляються за допомогою системи довготи та широти, градусні хвилини дуги та дугові секунди. Щоб знайти антипод, поміняйте місцями напрямки кожної ординати ( N <-> Sі W <-> E) і відніміть ординату довготи від 180градусів.

Приклад:
Візьміть крапку N 50 26 23 W 4 18 29. Поміняйте місцями інструкції S 50 26 23 E 4 18 29. Відніміть ординату довготи від 180 0 0дати 175 41 31, залишивши координати антипода як S 50 26 23 E 175 41 31.

Правила

Вхідні дані

Набір координат широти-довготи у будь-якому розумному форматі , де кожна ордината містить напрямок, число градусів, кількість хвилин дуги та кількість дугових секунд.

Вихідні дані

Координати широти-довготи антипода в будь-якому розумному форматі , де кожна ордината містить напрямок, число градусів, кількість хвилин дуги та кількість дугових секунд.

Слід розуміти, що кожну частину координати можна розрізнити однозначно.

Технічні характеристики

  • Напрямок для ординати широти дорівнює Nабо S, а для ординати довготи - Wабо E.
  • Усі значення координат є цілими числами. Значення ступеня буде між 0і 90для широти, і між, 0і 180довготою. Значення хвилини дуги та секунди дуги для обох ординат будуть між 0та 59.
  • Якщо всі значення ординати є 0, будь-який напрямок є прийнятним.
  • Немає необхідності занижувати будь-які значення.
  • Жодна ординатна широта ніколи не буде більшою за 90градуси, і жодна ординатна широта ніколи не буде більше 180градусів.
  • Застосовуються стандартні лазівки .

Тестові справи

N 50 26 23 W 4 18 29 -> S 50 26 23 E 175 41 31

S 43 9 9 E 0 0 5     -> N 43 9 9 W 179 59 55

N 0 0 0 E 0 0 0      -> S/N 0 0 0 W/E 180 0 0 (either direction fine in each case)

S 1 2 3 W 4 5 6      -> N 1 2 3 E 175 54 54

S 9 21 43 W 150 7 59 -> N 9 21 43 E 29 52 1

S 27 40 2 W 23 0 0   -> N 27 40 2 E 157 0 0

N 0 58 37 W 37 0 0   -> S 0 58 37 E 143 0 0

Корисні посилання

Це , тому найкоротша відповідь у байтах виграє!


Це розумний формат? Чотири входи: масив з 3 чисел, char, масив з трьох чисел; розділені новими рядками
Луїс Мендо

@LuisMendo Якщо я не розумію вас, я бачу лише три входи; Я припускаю, що ви хочете отримати додатковий шар? Я б сказав, що це розумний формат. Під розумним я по суті маю на увазі, що кожну частину координати можна виділити однозначно.
TheBikingViking

Так, я забув перший чар. Спасибі!
Луїс Мендо

3
"Досить небезпечний"? Мате, справжня небезпека - коли ти потрапиш сюди .
Ендрю Грімм

1
@busukxuan Вибачте за те, що не відповів швидше. Я хотів би сказати , що обидва з цих форматів є необгрунтованими, оскільки специфікація вимагає N, S, Eабо Wв напрямку, в той час як надлишкові 0вводить неоднозначність щодо того , яке значення представляє , який компонент ординат.
TheBikingViking

Відповіді:


1

05AB1E, 37 34 байт

`60©3L<Rm*O3°648*s-®‰`s®‰s‚˜)'€Ã‡

Пояснив

`                                      # split input to 4 lines with longitude on top
 60©3L<Rm*O                            # convert longitude to seconds
            3°648*                     # longitude 180 0 0 in seconds
                  s-                   # subtract our longitude from this
                    ®‰`                # get seconds part
                       s®‰             # get minute and degrees part
                          s‚˜)         # join to list
                              '€Ã‡    # translate directions

Спробуйте в Інтернеті

Редагувати: Збережено 3 байти завдяки Аднану .


Ви можете стиснути "NEWS"до ‘€Ã‘або навіть '€Ãякщо в нижньому регістрі допускається.
Аднан

@Adnan: Приємно! Не думав стискати, оскільки струна вже була такою маленькою.
Емінья

6

JavaScript (ES6), 88 байт

(a,b,c,d,e,f,g,h)=>[a<'S'?'S':'N',b,c,d,e<'W'?'W':'E',!(g|h)+179-f,g|h&&!h+59-g,h&&60-h]

Бере 8 параметрів і повертає масив як результат. Очікує, aщо один із Nабо Sподібним чином eбуде одним із Wабо E. Розрахунки:

  • fпотрібно відняти від 179, якщо gабо hє нульовим, але 180, якщо обидва gі hє нульовими (оскільки позики немає), таким чином !(g|h)додається до 179.
  • gпотрібно дорівнювати нулю, якщо обидва gі hдорівнюють нулю, таким чином g|h&&, інакше його потрібно відняти від 59, якщо hце не нульове значення, але 60, якщо hдорівнює нулю (тому що позики немає), таким чином !hдодається до 59.
  • h потрібно дорівнювати нулю, якщо він уже був нуль, інакше його просто відняти від 60.

Інший спосіб дивитися на це помітити , що віднімання в двійковій системі досягається за рахунок додавання 1s доповнення плюс додатковий 1. Переклад цієї проблеми, ми приймаємо 179-f, 59-gі 59-hта додати 1 59-h+ 1 60-h, але якщо це 60 , то він несе , тому бажаний результат дорівнює нулю, якщо hспочатку дорівнював нулю. Додаємо 1, 59-gякщо є перенос h, тобто якщо hвін спочатку був нульовим. Знову ж таки, ми повинні дозволити перенесення, що цього разу трапляється, якщо обоє gі hдорівнюють нулю, і до 179-fцього додаємо 1 .


6

MATL , 51 байт

'NS'tPXEii'WE'tPXE648e3i60:qXJZA-JYAtn3-?2:&)wJZAwh

Формат введення:

'N'
[50 26 23]
'W'
[4 18 29]

Формат виводу:

S
50 26 23
E
175  41  31

Спробуйте в Інтернеті!

Пояснення

'NS'tPXE     % Take input (string) implicitly. Exchange 'N' and 'S'
i            % Take input (array)
i'WE'tPXE    % Take input (string). Exchange 'W' and 'E'
648e3        % Push 648000
i            % Take input (array)
60:qXJ       % Push [0 1 ... 59]. Copy into clipboard J
ZA           % Convert second input array from base 60 to decimal
-            % Subtract
JYA          % Convert to base 60
tn3-?        % If length exceeds 3
  2:&)       %   Split into first two elements and then the rest
  w          %   Swap
  JZA        %   Convert from base 60 to decimal
  wh         %   Swap, concatenate

Там помилка в вашому поясненні на другий до останнього рядка: bnase.
TheBikingViking

1
@TheBikingViking Дякую! Виправлено
Луїс Мендо

4

Ракетка, 199 байт

(λ(l)(cons(cons(if(eq?(caar l)'n)'s'n)(cdar l))(cons(if(eq?(cadr l)'e)'w'e)(list (- 180(+(caddr l)(sgn(foldl + 0(cdddr l)))))(modulo(- 60(+(fourth l)(sgn(fifth l))))60)(modulo(- 60(fifth l))60)))))

Це жахливо довго. Напевно, я можу щось зробити, щоб скоротити його далі, але я здригаюся повністю.

Бере consпару двох lists: одна для широти і одна для довготи. Кожен список має напрямок (як символ малої ракетки) як його перший пункт, а за ним - градуси, дугові хвилини та дуги-секунди. Виходи в тому ж форматі

Ракетка інтерпретуватиме цю пару з двох списків як єдиний список, а інший - як її перший елемент. Це абсолютно добре, оскільки ви все ще можете отримати доступ до широти та довготи, як якщо б вони були двома списками в парі.

Використання:

>    (
     (λ(l)(cons(cons(if(eq?(caar l)'n)'s'n)(cdar l))(cons(if(eq?(cadr l)'e)'w'e)(list (- 180(+(caddr l)(sgn(foldl + 0(cdddr l)))))(modulo(- 60(+(fourth l)(sgn(fifth l))))60)(modulo(- 60(fifth l))60)))))
     (cons (list 's 43 9 9) (list 'e 0 0 5)))
'((n 43 9 9) w 179 59 55)

Який може бути інтерпретований майбутнім кодом як '((n 43 9 9) (w 179 59 55))два списки.


4

Піта, 41 45 43 35 байт

K60-"NS"ww-"EW"wA.D-*3^K3iEKK+.DGKH

Використовує конверсію бази-60, щоб перетворити градуси і хвилини на секунди.

Формат вводу / виводу:

N
[1,2,3]
E
[4,5,6]

Він друкує рядок кожного разу, коли ви вводите рядок, щоб мати гарний формат, ви можете використовувати CLI та передавати вхід, або зручніше, передавати використовувати онлайн-реалізацію Pyth .

У псевдокоді:

K60                                              K = 60
   -"NS"w                                        "NS".remove(input())
         w                                       print(input())
          -"EW"w                                 "EW".remove(input())
                A.D                              G,H = divmod(
                   -*3^K3                          3*K**3 -
                         iEK                         baseToDec(input(),K)),
                            K                      K)
                             +.DGKH              divmod(G,K)+H

@LuisMendo такий же, як і ваш, але списки розділені комами, і жодних лапок
busukxuan

4

Пітон 2, 140 122 байт

Оновлено:

def f(c):x=([180,0,0],[179,59,60])[1<sum(c[6:8])];print['NS'['N'in c]]+c[1:4]+['EW'['E'in c]]+map(lambda x,y:x-y,x,c[5:8])

Для цього використовується дещо інший підхід: встановлення значень для віднімання довготи на основі хвилин і секунд. Якщо є 0 хвилин і секунд, це віднімає 180 градусів, а якщо є> 0 хвилин і секунд, віднімає відповідно 179, 59 і 60 від d, m, s.

Оригінал:

def f(c):v=divmod;m,s=v((180-(c[5]+c[6]/60.+c[7]/3600.))*3600,60);d,m=v(m,60);print['NS'['N'in c]]+c[1:4]+['EW'['E'in c]]+map(round,[d,m,s])

Приймає введення як список:, f(['N', 0, 0, 0, 'E', 0, 0, 0])перетворює довготу в десяткові градуси, віднімає від 180, потім перетворює назад на градуси, хвилини, секунди і відновлює список, гортаючи вказівки в процесі.

Без гольфу:

def f(c):
    minutes,seconds=divmod((180-(c[5]+c[6]/60.+c[7]/3600.))*3600,60)
    degrees,minutes=divmod(minutes,60)
    print ['NS'['N'in c]]+c[1:4]+['EW'['E'in c]]+map(round,[degrees,minutes,seconds])

Спробуй це


3

JavaScript, 138 137 129 124 112 110

Поліпшення на 2 байти, натхнене кодом @ Ніла

f=a=>a.map((v,i,a)=>i%4?i>6?v&&60-v:i>5?(59-v+!a[7])%60:i>4?179-v+!(a[7]|a[6]):v:'NEWS'[3-'NEWS'.indexOf(v)]);
  • input = output = масив, що містить 2x (1 велика величина та 3 int)
  • перевірено у Firefox

неозорий

f=a=>a.map((v,i,a)=>
i%4?
    i>6?v&&60-v              // 7: invert seconds - old: (60-v)%60
    :i>5?(59-v+!a[7])%60     // 6: invert minutes, increase if seconds are 0
    :i>4?179-v+!(a[7]|a[6])  // 5: invert degrees, increase if seconds and minutes are 0
    :v                       // 1,2,3: unchanged
:'NEWS'[3-'NEWS'.indexOf(v)] // 0,4: swap directions
);

тести

<table id=out border=1><tr><th>in</th><th>out<th>expected</th><th>ok?</th></tr></table>
<script>
addR=(r,s)=>{var d=document.createElement('td');d.appendChild(document.createTextNode(s));r.appendChild(d)}
test=(x,e,f)=>{var y,r=document.createElement('tr');addR(r,x);addR(r,y=('function'==typeof f)?f(x):f);addR(r,e);addR(r,e.toString()==y.toString()?'Y':'N');document.getElementById('out').appendChild(r)}

samples=[
'N',50,26,23,'W',4,18,29,   'S',50,26,23,'E',175,41,31,
'S',43,9,9,'E',0,0,5,       'N',43,9,9,'W',179,59,55,
'N',0,0,0,'E',0,0,0,        'S',0,0,0,'W',180,0,0,
'S',1,2,3,'W',4,5,6,        'N',1,2,3,'E',175,54,54,
'S',9,21,43,'W',150,7,59,   'N',9,21,43,'E',29,52,1,
'S',27,40,2,'W',23,0,0,     'N',27,40,2,'E',157,0,0,
'N',0,58,37,'W',37,0,0,     'S',0,58,37,'E',143,0,0,
];
while (samples.length)
{
    x=samples.splice(0,8);
    e=samples.splice(0,8);
    test(x,e,h);
    test(e,x,h);
}
</script>

ах, я просто бачу, що @Neil мав таку ж ідею, але кілька коротших параметрів
Titus

2

Python 3, 131 130 байт

def f(w,x,y,z):S=60;d=divmod;a,b,c=y;l,m=d(648e3-c-S*b-S*S*a,S);return w,"N" if x=="S" else "S",d(l,S)+(m,),"E" if z=="W" else "W"

Формати: кути - кортежі форми (deg,min,sec), напрями - формиN . Виводиться вчетверо з 2 кутів, кожен з яких слідує за його напрямком.

Негольована версія:

def f(latitude,NS,longitude,EW):
    degree,minute,second=longitude
    minute,second=divmod(648000-second-60*minute-60*60*degree,60)
    return latitude, "N" if NS=="S" else "S", divmod(minute,60)+(second,), "E" if EW=="W" else "W"

1
Ви можете звести це до 120 байтів, виконуючи def f(w,x,y,z):S=60;d=divmod;a,b,c=y;l,m=d(648e3-c-S*b-S*S*a,S);return w,["S","N"][x=="S"],d(l,S)+(m,),["W","E"][z=="W"]цю роботу, використовуючи той факт, що Trueі Falseможе бути інтерпретований як 1і 0, і, отже a if b else c, еквівалентний [c, a][b]. Зі сторони, я думаю, що ваш оригінальний код має помилку друку; повинно x=="W"бути z=="W"?
TheBikingViking

2

C #, 310 269 ​​байт

float[]t(string[]a,int n)=>a.Skip(n).Take(3).Select(float.Parse).ToArray();string A(string i){var s=i.Split(' ');var w=t(s,5);float a=180-(w[0]+w[1]/60+w[2]/3600),b=a%1*60;return(s[0][0]>82?"N":"S")+$" {string.Join(" ",t(s,1))} {(s[4][0]<70?'W':'E')} {a} {b} "+b%1*60;}

Вхід - один рядок. Ви можете спробувати .NetFiddle .

Код

float[]t(string[]a,int n)=>a.Skip(n).Take(3).Select(float.Parse).ToArray();
string A(string i) {
    var s=i.Split(' ');var w=t(s,5);float a=180-(w[0]+w[1]/60+w[2]/3600),b=a%1*60;
    return (s[0][0]>82?"N":"S")
        +$" {string.Join(" ",t(s,1))} {(s[4][0]<70?'W':'E')} {a} {b} "+b%1*60;
}

Якщо я не беру stringяк вхід, а а char, float[], char, float[], я можу зробити:

C #, 167 166 165 163 152 148 147 139 байт

(s,n,e,w)=>{float a=180-(w[0]+w[1]/60+w[2]/3600),b=a%1*60;return(s>82?"N":"S")+$" {string.Join(" ",n)} {(e<70?'W':'E')} {a} {b} "+b%1*60;};

Код

(s,n,e,w) => {
    float a=180-(w[0]+w[1]/60+w[2]/3600),b=a%1*60;
    return(s>82?"N":"S")+$" {string.Join(" ",n)} {(e<70?'W':'E')} {a} {b} "+b%1*60;
};

Також я можу видалити 3600та використовувати замість цього для переміщення до 164 символів та 166 байтів. Чи варто його використовувати?


C #, 150 байт

(s,n,m,p,e,w,x,y)=>{var t=new TimeSpan(180,0,0)-new TimeSpan(w,x,y);return(s>82?"N":"S")+$" {n} {m} {p} {(e<70?'W':'E')} {t.TotalHours} {t:%m\\ s}";};

Код

(s,n,m,p,e,w,x,y) => {
    var z=new TimeSpan(180,0,0)-new TimeSpan(w,x,y);
     return(s>82?"N":"S")+$" {n} {m} {p} {(e<70?'W':'E')} {z.TotalHours} {z:%m\\ s}";
};

Більше .NET спосіб! Я делегувати всю логіку в .NET , struct TimeSpanі я як-небудь використовувати рядок логіки форматування. Введення є char, int, int, int, char, int, int, int. Я ділюсь цим, щоб дати кілька ідей. Можливо, хтось покращиться краще, ніж я.


Це, на жаль, багатослівне.
Стівен Х.

@Fawful Я публікую іншу версію з різними аргументами. Менше багатослівного немає? Я все одно не можу позбутися string.Join()...
aloisdg каже, що повернеться Моніка

Зауважте, що це C # 6.0
Yytsi

@TuukkaX, оскільки це остання версія C #, я не вказував її. Я буду, якщо використовую якусь функцію розблокування, наприклад функцію C # 7.
aloisdg повідомляє про відновлення Моніки

1
Ну, я не бачуreturn , я повинен був додати це сам ... З допомогою тест a('N', new float[] { 50, 26, 23 }, 'W', new float[] { 4, 18, 29 })я отримую S 50 26 23 E 175.6919 41.51642 30.98511- Ви б це пропуск?
onedaywhen

0

Java, 199 177 або 151 або 134 байт

177 байт, який видає результат

void t(int...a){int i=648000-(a[5]*3600+a[6]*60+a[7]);System.out.println(a[0]=='N'?"S":"N"+" "+a[1]+" "+a[2]+" "+a[3]+" "+(a[4]=='E'?"W":"E")+" "+i/3600+" "+i/60%60+" "+i%60);}

151 байт рішення, яке повертає результат у вигляді масиву

Object[]y(int...a){int i=648000-(a[5]*3600+a[6]*60+a[7]);return new Object[]{a[0]=='N'?"S":"N",a[1],a[2],a[3],a[4]=='E'?"W":"E",i/3600,i/60%60,i%60};}

134 байт, якщо ми використовували позначення лямбда

a->{int i=648000-a[5]*3600-a[6]*60-a[7];return new Object[]{a[0]=='N'?"S":"N",a[1],a[2],a[3],a[4]=='E'?"W":"E",i/3600,i/60%60,i%60};}

0

С, 188

main(int c,char**v){int n=*v[1]==78?83:78,e=*v[5]==69?87:69,b=648000-(atoi(v[6])*3600+atoi(v[7])*60+atoi(v[8]));printf("%c %s %s %s %c %d %d %d\n",n,v[2],v[3],v[4],e,b/3600,b/60%60,b%60);}

Потрібно 8 програмних аргументів, інакше не вдасться. Передайте такі аргументи, як N 50 26 23 W 4 18 29. Покажчики повороту N, S, E, W, повинні бути капіталізовані.


0

PostGIS, 123 байти

Інструмент «Робота для роботи» розчаровує багатослівний вигляд, почасти через викладеність SQL, а частково через необхідність переходу на геометрію та назад:

CREATE FUNCTION f(p geography)
RETURNS geography
AS 'SELECT ST_Affine(p::geometry,1,0,0,-1,180,0)::geography' LANGUAGE sql;

З іншого боку, ця єдина функція перетворить точки, колекції точок або більш складні форми (наприклад, уся берегова лінія Австралії та Нової Зеландії).


0

PHP, 148 байт

такий же підхід, як і моя відповідь на JavaScript , шукайте там розрив

  • +16 функція накладних витрат
  • +17 для $знаків
  • +12 для парантезів (різний пріоритет оператора)
  • +4 foreachтому, що PHP array_mapмає величезні накладні витрати
  • +1 для, (60-$v)%60тому що він $v&&60-$vпередає булеве значення в PHP
  • -8, працюючи над оригіналом
  • -4 за допомогою chr, ordа також деякі арифметики на зміну напрямку

function f(&$a){foreach($a as$i=>$v)$a[$i]=$i%4?($i>6?(60-$v)%60:($i>5?(59-$v+!$a[7])%60:($i>4?179-$v+!($a[7]|$a[6]):$v))):chr(($i?156:161)-ord($v));}
  • функція працює на оригіналі
  • формат: масив з 2x (1 велика літера, 3 int)

тести

function out($a){if(!is_array($a))return$a;$r=[];foreach($a as$v)$r[]=out($v);return'['.join(',',$r).']';}
function cmp($a,$b){if(is_numeric($a)&&is_numeric($b))return 1e-2<abs($a-$b);if(is_array($a)&&is_array($b)&&count($a)==count($b)){foreach($a as $v){$w = array_shift($b);if(cmp($v,$w))return true;}return false;}return strcmp($a,$b);}
$samples=[
N,50,26,23,W,4,18,29,   S,50,26,23,E,175,41,31,
S,43,9,9,E,0,0,5,       N,43,9,9,W,179,59,55,
N,0,0,0,E,0,0,0,        S,0,0,0,W,180,0,0,
S,1,2,3,W,4,5,6,        N,1,2,3,E,175,54,54,
S,9,21,43,W,150,7,59,   N,9,21,43,E,29,52,1,
S,27,40,2,W,23,0,0,     N,27,40,2,E,157,0,0,
N,0,58,37,W,37,0,0,     S,0,58,37,E,143,0,0,
];
while ($samples)
{
    $xx=$x=array_splice($samples,0,8);
    $ee=$e=array_splice($samples,0,8);
    func($x); test($xx,$ee,$x);
    func($e); test($ee,$xx,$e);
}

занедбані ідеї

  • немає циклічного підходу з прапорцями: +5
  • петля назад з прапорцями: +7
  • Я міг би перетворити це на програму для PHP <5.4, але неважливо: -3

0

Befunge, 122 114 111 байт (110 символів)

~"N"-v
 v"N"_"S"
v>,&.&.&.~"W"-
_"E"v"W"
+:v >,&"´"\-&"Z"*&
v\_\.00..@.-\"<".-1\ <
>1-.:"Z"/"<"\-\"Z"%:#^_\..@

Формат введення:

N 50 26 23W 4 18 29

Зауважте напрямок довготи і дуги секунди повинні бути збиті між собою

Ви можете протестувати код тут

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.