挖掘到澳大利亚-对映体


24

背景

无数代的孩子想知道,如果他们直接向下挖一个洞,他们会到哪里去。事实证明,这无疑是相当危险的,但无论如何...

对映体是在地球表面上彼此直接相对的点。这意味着,如果在两点之间画一条线,它将穿过地球的中心。

挑战

编写一个程序或函数,找到要解决的问题。

在此挑战中,使用经度-纬度系统以及度,弧分和弧秒来表示点。要找到对映体,请交换每个纵坐标(N <-> SW <-> E)的方向,然后从180度数中减去经度坐标。

示例:
抓住重点N 50 26 23 W 4 18 29。交换指示即可S 50 26 23 E 4 18 29。从中减去经度坐标180 0 0175 41 31,将对映体的坐标保留为S 50 26 23 E 175 41 31

规则

输入项

一组任意合理格式的纬度-经度坐标,其中每个坐标包含一个方向,一个度数,一个弧分和一个弧秒。

输出量

对映体的纬度-经度坐标,采用任何合理的格式,其中每个坐标包含一个方向,一个度数,一个弧分和一个弧秒。

合理地表示可以清楚地区分坐标的每个部分。

眼镜

  • 纬度坐标的方向是NS,经度坐标的方向是WE
  • 所有坐标值都是整数。度值将与090纬度之间,以及0180经度。两个坐标的弧分和弧秒值都在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,3个数字的数组;用换行符分隔
Luis Mendo

@LuisMendo除非我对您有误解,否则我只能看到三个输入。我想你会想要一个额外的字符吗?我会说这是一种合理的格式。合理地说,我实质上是指可以清楚地区分坐标的每个部分。
TheBikingViking '16

是的,我忘记了第一个字符。谢谢!
Luis Mendo

3
“比较危险”?伴侣,真正的危险是一旦你到达这里
Andrew Grimm

1
@busukxuan很抱歉没有尽快回复。我要说的是两者的那些格式不能合理的,因为该规范要求NSE,或W作为一个方向,而冗余0介绍歧义哪个值表示纵坐标的哪个组件。
TheBikingViking

Answers:


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

在线尝试

编辑:感谢Adnan节省了3个字节。


您可以压缩"NEWS"‘€Ã‘,甚至'€Ã允许小写。
阿德南

@Adnan:太好了!因为字符串已经很小,所以没有考虑压缩。
Emigna '16

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个参数并返回一个数组作为结果。期望aN或之一,S并且类似e地是W或之一E。计算:

  • f如果其中一个gh不是零,则需要从179中减去;如果两个gh都为零,则需要从180中减去(因为没有借位),因此!(g|h)将其添加到179。
  • g需要是零,如果两者gh是零,因此g|h&&,否则它需要如果待从59中减去h非零但如果60 h是零(因为没有借位),从而!h被添加到59。
  • h 如果已经为零,则必须为零;否则,只需将其减去60。

另一种方式来看待,这是要注意到,在二进制减去通过将1的补加翻译这个问题,我们需要一个额外的1实现179-f59-g59-h添加1 59-h+ 1 60-h,但如果这是60那么它承载,因此,如果h原本为零,则预期结果为零。59-g如果从中有一个进位h,则将1加,即如果h原本为零。同样,我们必须允许进位,这一次如果同时gh都为零,则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 '16

1
@TheBikingViking谢谢!已纠正
Luis Mendo

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:一个用于纬度,一个用于经度。每个列表的第一项都有方向(作为小写的球拍符号),其后是度,弧分和弧秒。以相同格式输出

Racket会将这对两个列表解释为一个列表,并将另一个列表作为其第一个元素。这非常好,因为您仍然可以访问纬度和经度,就好像它们是成对的两个列表一样。

用法:

>    (
     (λ(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

Pyth,41 45 43 35字节

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

使用以60为基数的转换将度和分转换为秒。

I / O格式:

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

Python 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分钟和秒,则分别从d,m和s中减去179、59和60。

原版的:

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

@Neil的代码启发了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)]);
  • 输入=输出=包含2x(1个大写字符和3个整数)的数组
  • 在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"]使用的事实,这个作品TrueFalse可以解释为10,因此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输入a而是a 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。我分享这一观点以提出一些想法。也许有人会以比我更好的方式改善自己。


不幸的是,这很冗长。
史蒂文H.

@Fawful我发布了另一个带有不同参数的版本。不太冗长,不是吗?我仍然无法摆脱string.Join()……
aloisdg说莫妮卡

请注意,这是C#6.0
Yttsi'7

@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-你会认为这是一通?
一天,2016年

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

如果使用lambda表示法,则为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

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

需要8个程序参数,否则将失败。传递参数,例如N 50 26 23 W 4 18 29。方向指示器NSEW,必须大写。


0

PostGIS,123字节

Job-For-The-Job令人失望地冗长,部分是由于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通过使用chrord并且在方向交换一些算术

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个整数)

测试

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

请注意,经度方向和弧秒必须紧缩在一起

您可以在此处测试代码

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.