[Question]
  [
## Background
Countless generations of children have wondered where they would end up if they dug a hole directly downwards. It turns out that this would, unsurprisingly, be [rather dangerous](https://what-if.xkcd.com/135/), but anyway...
Antipodes are points that are directly opposite each other on the Earth's surface. This means that if a line was drawn between the two points, it would pass through the centre of the Earth.
## Challenge
Write a program or function that, given a point, finds its antipode.
In this challenge, points are represented using the longitude-latitude system and degrees, arc minutes and arc seconds. To find the antipode, swap the directions of each ordinate (`N <-> S` and `W <-> E`) and subtract the longitude ordinate from `180` degrees.
Example:  
Take the point `N 50 26 23 W 4 18 29`. Swap the directions to give `S 50 26 23 E 4 18 29`. Subtract the longitude ordinate from `180 0 0` to give `175 41 31`, leaving the antipode coordinates as `S 50 26 23 E 175 41 31`.
## Rules
### Input
A set of latitude-longitude coordinates, **in any reasonable format**, where each ordinate contains a direction, a number of degrees, a number of arc minutes, and a number of arc seconds.
### Output
The latitude-longitude coordinates of the antipode, **in any reasonable format**, where each ordinate contains a direction, a number of degrees, a number of arc minutes, and a number of arc seconds.
**Take reasonable to mean that each part of the coordinate can be distinguished unambiguously.**
### Specs
* The direction for the latitude ordinate is `N` or `S`, and that for the longitude ordinate is `W` or `E`.
* All coordinate values are integers. The degree value will be between `0` and `90` for latitude, and between `0` and `180` for longitude. The arc minute and arc second values for both ordinates will be between `0` and `59`.
* If all the values for an ordinate are `0`, either direction is acceptable.
* There is no need to zero-pad any values.
* **No latitude ordinate will ever be larger than `90` degrees, and no longitude ordinate will ever be larger than `180` degrees.**
* [Standard loopholes](http://meta.codegolf.stackexchange.com/questions/1061/loopholes-that-are-forbidden-by-default) apply.
## Test cases
```
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
```
## Useful links
* [Latitude and longitude](https://en.wikipedia.org/wiki/Geographic_coordinate_system#Geographic_latitude_and_longitude)
* [Antipodes](https://en.wikipedia.org/wiki/Antipodes)
* [Arc minutes and arc seconds](https://en.wikipedia.org/wiki/Minute_and_second_of_arc)
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest answer in bytes wins!
  
[Answer]
## JavaScript (ES6), 88 bytes
```
(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]
```
Takes 8 parameters and returns an array as the result. Expects `a` to be one of `N` or `S` and similarly `e` to be one of `W` or `E`. Calculations:
* `f` needs to be subtracted from 179 if either `g` or `h` is nonzero but 180 if both `g` and `h` are zero (because there is no borrow), thus `!(g|h)` is added to the 179.
* `g` needs to be zero if both `g` and `h` are zero, thus `g|h&&`, otherwise it needs to be subtracted from 59 if `h` is nonzero but 60 if `h` is zero (because there is no borrow), thus `!h` is added to the 59.
* `h` needs to be zero if it was already zero, otherwise it is simply subtracted from 60.
Another way to look at this is to notice that subtracting in binary is achieved by adding the 1s complement plus an additional 1. Translated to this problem, we take `179-f`, `59-g` and `59-h` and add 1. `59-h` + 1 is `60-h`, but if this is 60 then it carries, so the desired result is zero if `h` was originally zero. We add 1 to `59-g` if there's a carry from `h`, i.e. if `h` was originally zero. Again we have to allow for a carry, which this time happens if both `g` and `h` are zero, and we add 1 to `179-f` in this case.
[Answer]
# [MATL](https://github.com/lmendo/MATL), 51 bytes
```
'NS'tPXEii'WE'tPXE648e3i60:qXJZA-JYAtn3-?2:&)wJZAwh
```
Input format:
```
'N'
[50 26 23]
'W'
[4 18 29]
```
Output format:
```
S
50 26 23
E
175  41  31
```
[**Try it online!**](http://matl.tryitonline.net/#code=J05TJ3RQWEVpaSdXRSd0UFhFNjQ4ZTNpNjA6cVhKWkEtSllBdG4zLT8yOiYpd0paQXdo&input=J04nCls1MCAyNiAyM10KJ1cnCls0IDE4IDI5XQ)
### Explanation
```
'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
```
[Answer]
# Racket, 199 bytes
```
(λ(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)))))
```
That's horribly long. There's probably some things I could do to shorten it further, but *shudders* I'm completely done.
Takes a `cons` pair of two `lists`: one for the latitude and one for the longitude. Each list has the direction (as a lowercase Racket symbol) as its first item and following it the degrees, arc-minutes, and arc-seconds. Outputs in the same format
Racket will interpret this pair of two lists as a single list with another list as its first element. This is perfectly fine, since you can still access both latitude and longitude as if they were two lists in a pair.
Usage:
```
>    (
     (λ(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)
```
Which can be interpreted by future code as `'((n 43 9 9) (w 179 59 55))`, two lists.
[Answer]
# Pyth, ~~41~~ ~~45~~ ~~43~~ 35 bytes
```
K60-"NS"ww-"EW"wA.D-*3^K3iEKK+.DGKH
```
Uses base-60 conversion to turn degrees and minutes into seconds.
I/O format:
```
N
[1,2,3]
E
[4,5,6]
```
It prints a line every time you input a line, so to have a good-looking format, you can either use the CLI and pipe the input, or more conveniently, [use the online Pyth implementation](http://pyth.herokuapp.com/?code=K60-%22NS%22ww-%22EW%22wA.D-%2a3%5EK3iEKK%2B.DGKH&input=N%0A%5B3%2C2%2C1%5D%0AE%0A%5B7%2C5%2C4%5D&test_suite=1&test_suite_input=N%0A%5B50%2C26%2C23%5D%0AW%0A%5B4%2C18%2C29%5D%0AS%0A%5B43%2C9%2C9%5D%0AE%0A%5B0%2C0%2C5%5D%0AN%0A%5B0%2C0%2C0%5D%0AE%0A%5B0%2C0%2C0%5D%0AS%0A%5B1%2C2%2C3%5D%0AW%0A%5B4%2C5%2C6%5D%0AS%0A%5B9%2C21%2C43%5D%0AW%0A%5B150%2C7%2C59%5D%0AS%0A%5B27%2C40%2C2%5D%0AW%0A%5B23%2C0%2C0%5D%0AN%0A%5B0%2C58%2C37%5D%0AW%0A%5B37%2C0%2C0%5D&debug=0&input_size=4).
In pseudocode:
```
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
```
[Answer]
## Python 2, ~~140~~ 122 bytes
Updated:
```
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])
```
This uses a slightly different approach: setting the values to subtract from the longitude based on the minutes and seconds. If there are 0 mins and seconds, it subtracts 180 from the degrees, and if there are >0 mins and secs, it subtracts 179, 59, and 60 from the d, m, s respectively.
Original:
```
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])
```
Takes input as a list: `f(['N', 0, 0, 0, 'E', 0, 0, 0])`, converts the longitude to decimal degrees, subtracts from 180, then converts back to degrees, minutes, seconds and re-constructs the list, flipping the directions in the process.
Un-golfed:
```
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])
```
[Try it](https://repl.it/C9Db/1)
[Answer]
# JavaScript, ~~138~~ ~~137~~ ~~129~~ ~~124~~ ~~112~~ 110
2 bytes improvement inspired by @Neil´s code
```
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 = array containing 2x(1 uppercase char and 3 int)
* tested in Firefox
**ungolfed**
```
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
);
```
**tests**
```
<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>
```
[Answer]
# Python 3, ~~131~~ 130 bytes
```
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"
```
Formats: angles are tuples of the form `(deg,min,sec)`, directions are of the form `N`. Outputs a quadruple of 2 angles, each followed by its direction.
Ungolfed version:
```
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"
```
[Answer]
# C#, ~~310~~ 269 bytes
```
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;}
```
The input is one string. You can try it on [.NetFiddle](https://dotnetfiddle.net/W3lEVs).
Code
```
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;
}
```
---
If I don't take a `string` as input but a `char, float[], char, float[]`, I can do:
# C#, ~~167~~ ~~166~~ ~~165~~ ~~163~~ ~~152~~ ~~148~~ ~~147~~ 139 bytes
```
(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;};
```
Code
```
(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;
};
```
Also I can remove the `3600` and use [`ฐ`](http://unicode-table.com/en/0E10/) instead to move to 164 characters and 166 bytes. Should I use it?
---
# C#, 150 bytes
```
(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}";};
```
Code
```
(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}";
};
```
A more .NET way! I delegate all the logic to the .NET `struct` `TimeSpan` and I ~~ab~~use the string formatting logic. Input is `char, int, int, int, char, int, int, int`. I share this one to give some ideas. Maybe someone will improve in a better way than me.
[Answer]
## 05AB1E, ~~37~~ 34 bytes
```
`60©3L<Rm*O3°648*s-®‰`s®‰s‚˜)'€ÃÂ‡
```
**Explained**
```
`                                      # 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
```
[Try it online](http://05ab1e.tryitonline.net/#code=YDYwwqkzTDxSbSpPM8KwNjQ4KnMtwq7igLBgc8Ku4oCwc-KAmsucKSfigqzDg8OC4oCh&input=WydzJyxbOSwgMjEsIDQzXSwndycsWzE1MCwgNywgNTldXQ)
**Edit:** Saved 3 bytes thanks to [Adnan](https://codegolf.stackexchange.com/users/34388/adnan).
[Answer]
# Java, ~~199~~ 177 or 151 or 134 Bytes
177 Bytes solution which prints result
```
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 Bytes solution which returns result as array
```
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 Bytes if we used lambda notation
```
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};}
```
[Answer]
# C, 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);}
```
Requires 8 program arguments, will fail otherwise. Pass arguments like `N 50 26 23 W 4 18 29`. Direction indicators `N`, `S`, `E`, `W`, must be capitalized.
[Answer]
# PostGIS, 123 bytes
The Tool-For-The-Job is disappointingly verbose, partly because of SQL wordiness and partly due to the need to cast to geometry and back:
```
CREATE FUNCTION f(p geography)
RETURNS geography
AS 'SELECT ST_Affine(p::geometry,1,0,0,-1,180,0)::geography' LANGUAGE sql;
```
On the other hand, this single function will transform points, collections of points, or more complex shapes (such as the entire coastline of Australia and New Zealand).
[Answer]
# PHP, 148 bytes
same approach as [my JavaScript answer](https://codegolf.stackexchange.com/questions/84560/dig-to-australia-antipodes/84603/#84603), look there for a breakdown
* +16 function overhead
* +17 for `$` signs
* +12 for parantheses (different operator precedence)
* +4 for `foreach` because PHP´s `array_map` has a huge overhead
* +1 for `(60-$v)%60` because `$v&&60-$v` casts to boolean in PHP
* -8 by working on the original
* -4 by using `chr`, `ord` and some arithmetics on the direction swap
```
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));}
```
* function works on original
* format: array with 2x (1 uppercase char, 3 int)
**tests**
```
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);
}
```
**abandoned ideas**
* no loop approach with carry flags: +5
* loop backwards with carry flags: +7
* I could turn this into a program for PHP<5.4, but never mind: -3
[Answer]
# Befunge, ~~122~~ ~~114~~ 111 Bytes (110 characters)
```
~"N"-v
 v"N"_"S"
v>,&.&.&.~"W"-
_"E"v"W"
+:v >,&"´"\-&"Z"*&
v\_\[[email protected]](/cdn-cgi/l/email-protection)\"<".-1\ <
>1-.:"Z"/"<"\-\"Z"%:#^_\..@
```
Input format:
```
N 50 26 23W 4 18 29
```
Notice the longitude direction and the arc seconds must be huddled together
You may test the code [here](http://www.quirkster.com/iano/js/befunge.html) 
]