Dados los nombres de dos planetas, da la distancia

25

Usando la siguiente tabla ( fuente ) escriba un código que tome los nombres de dos planetas y devuelva la distancia entre ellos:

+-------------------+---------------+
|      Planets      | Distance (km) |
+-------------------+---------------+
| Mercury -> Venus  |      50290000 |
| Venus -> Earth    |      41400000 |
| Earth -> Mars     |      78340000 |
| Mars -> Jupiter   |     550390000 |
| Jupiter -> Saturn |     646270000 |
| Saturn -> Uranus  |    1448950000 |
| Uranus -> Neptune |    1627450000 |
| Neptune -> Pluto  |    1405380000 |
+-------------------+---------------+

Ejemplos, entrada y salida:

Mercury, Mars
170030000
Neptune, Jupiter
-3722670000
Earth, Earth
0

Observe el signo negativo allí, ya que Júpiter viene antes que Neptuno. También son todos enteros.

Plutón no tiene que ser incluido (principalmente debido a una órbita extraña que hace que sea difícil calcular la distancia; esa distancia dada es mi propio cálculo, pero como Plutón es famoso ahora ...).

Por distancias entre planetas me refiero a órbitas: no espero una fecha y averiguar dónde están.

Este es el código de golf, el código más corto gana.

Tim
fuente
10
+1 por no "porque Plutón no es un planeta"
Optimizer
@Optimizer ¡Estoy haciendo un proyecto que necesita las distancias y nadie puede estar de acuerdo! Recurrí a usar su período orbital y su velocidad orbital ...
Tim
¿Puede nuestra función / programa devolver un flotador? es decir Mercury, Mars -> 170030000.0?
Kade
8
Está implícito, pero ¿estamos asumiendo el momento sagrado en el tiempo donde los planetas están todos en línea recta y la distancia entre dos planetas no adyacentes es la suma de las distancias intermedias?
Sp3000
3
¿Hay una penalización por incluir a Plutón (además de los bytes)? Me siento un poco mal por eso, solo tuvo un gran día y todo ...
DeadChex

Respuestas:

24

CJam, 54 51 44 bytes

2{"X84VT:Z/3KD'Y->>6\ Ta "3/r26b93%=70be4}*-

Pruébelo en línea en el intérprete de CJam .

Idea

Utilizamos una función de hashing simple para identificar los ocho planetas. Al considerar cada nombre como la matriz de sus puntos de código, convertirlos de la base 26 a un número entero y tomar el resultado módulo 93 y luego módulo 8, Mercurio , Venus , Tierra , etc., mapa a 2 , 4 , 0 , 1 , 3 , 5 , 6 y 7 .

Ahora, elegimos un punto que se encuentra 320,000 km detrás de Neptuno y calculamos las distancias de los ocho planetas a ese punto. Después de soltar cuatro ceros finales y reordenar los planetas para que se ajusten a los 8 índices desde arriba, obtenemos la matriz

[435172 427338 444341 372299 439312 307672 162777 32]

que, si codificamos cada número entero en la base 70, produce lo siguiente:

[
   [1 18 56 52] [1 17 14 58] [1 20 47 51] [1 5 68 39]
   [1 19 45 62] [  62 55 22] [  33 15 27] [       32]
]

Recordando que (A B)se pueden reemplazar dos dígitos adyacentes ((A-1) (B+70)), podemos modificar la matriz desde arriba para que todos los enteros se puedan codificar como caracteres ASCII imprimibles:

["X84" "VT:" "Z/3" "KD'" "Y->" ">6\\" " Ta" " "]

Código

2{                         e# Do twice:   
  "X84VT:Z/3KD'Y->>6\ Ta " e#   Push that string.
  3/                       e#   Chop it into chunks of length 3.
  r                        e#   Read a token from STDIN.
  26b                      e#   Convert from base 26 to integer.
  93%                      e#   Take the result modulo 93.
  =                        e#   Retrieve the chunk at that index.
  70b                      e#   Convert from base 70 to integer.
  e4                       e#   Multiply by 10,000.
}*                         e#
-                          e# Subtract the two results.
Dennis
fuente
10

Python 2, 149 147 142 138 128 123 119 Bytes

Solo usa una búsqueda simple para determinar qué distancias usar :) Esto define una función anónima, por lo que para usarla deberá darle un nombre.

¡Gracias a Sp3000 por las ideas que ahorraron un montón de bytes!

lambda*x:int.__sub__(*[[0,5029,9169,17003,72042,136669,281564,444309]['MeVeEaMaJuSaUr'.find(k[:2])/2]for k in x])*~9999

Sangrado correctamente y sin golf un poco para facilitar la lectura:

def f(*x):
 d=0,5029,9169,17003,72042,136669,281564,444309
 a,b=[d['MeVeEaMaJuSaUr'.find(k[:2])/2]for k in x]
 print(b-a)*10000

Llame así:

f("Mercury","Mars")    -> 170030000
f("Neptune","Jupiter") -> -3722670000L
Kade
fuente
A su salida le falta un 0, pero parece que se multiplica por la cantidad correcta.
Tim
@Tim Me equivoqué en la llamada de ejemplo, tiene un cuarto 0 al final: P
Kade
¿Te estás olvidando de Plutón?
Will
@Will Plutón no tiene que ser incluido ...
Kade
(Ahorrará al menos dos bytes si copia ese truco de devolución -1 de mi entrada, y luego se adelantará a mí :)
Será el
8

Prólogo, 190 174 151 bytes

Gracias a Fatalize por tu orientación.

g(A,X):-sub_atom(A,2,2,_,B),member(B:X,[rc:0,nu:5029,rt:9169,rs:17003,pi:72042,tu:136669,an:281564,pt:444309]).
s(A,B,R):-g(A,X),g(B,Y),R is(Y-X)*10^4.

$ gprolog --consult-file src.pro 
| ?- s('Mercury','Mars',R).   
R = 170030000 ? 
yes
| ?- s('Neptune','Jupiter',R).
R = -3722670000 ? 
yes
| ?- s('Earth','Earth',R).    
R = 0 ? 
yes
SteelRaven
fuente
¿Por qué no devuelve este resultado directamente así en s(A, B, R)lugar de escribir R? No se especifica nada para las salidas, por lo que un retorno de predicado debería estar bien.
Fatalize
También puede afeitarse 22 bytes modificando predicado ga g(A,X):-sub_atom(A,2,2,_,B),member(B:X,[rc:0,nu:5029,rt:9169,rs:17003,pi:72042,tu:136669,an:281564,pt:444309]).y la eliminación de todos los hechos de planetas. Es menos interesante =..pero es más corto obtener un mapeo de valores clave
Fatalize
7

JavaScript (ES6), 115 110 bytes

(x,y,g=k=>"Me0Ve5029Ea9169Ma17003Ju72042Sa136669Ur281564Ne444309".match(k[0]+k[1]+"(\\d*)")[1]*1e4)=>g(y)-g(x)

Esta es una función anónima, por lo que deberá almacenarla en una variable ( f=...; f("Earth", "Mercury")) o usarla como una expresión entre paréntesis ((...)("Earth", "Mercury") .

Esa cadena desordenada son las dos primeras letras de cada planeta, seguidas de la distancia de ese planeta a Mercurio (dividido por 10000, para ahorrar espacio). La función interna ghace lo siguiente:

  1. toma un nombre (k ),
  2. lo reduce a las dos primeras letras (k[0]+k[1] ),
  3. usa una coincidencia de expresiones regulares para encontrar la distancia correspondiente de Mercurio, dividida por 10000 (p. ej., la expresión regular de "Tierra" parece Ea(\d*) ),
  4. multiplica el valor por 10000 ( 1e4) y devuelve el resultado.

Al restar una distancia de Mercurio de la otra, obtenemos la distancia entre los planetas.

apsillers
fuente
@ vihan1086 Ajá, he cometido el clásico error de confundir el valor del punto de código con la representación de bytes real :(
apsillers
1
UTF-8 es la codificación incorrecta para este truco. Todos los caracteres devueltos por btoatienen puntos de código por debajo de 256, por lo que ISO 8859-1 codificará cada carácter utilizando un solo byte.
Dennis
7

Java, 274 272 264 bytes (¡incluye Plutón!)

  void p(String p,String l){String q="MeVeEaMaJuSaUrNePl";int w=q.indexOf(p.substring(0,2))/2,e=q.indexOf(l.substring(0,2))/2,m=1,t=e,d[]={5029,4140,7834,55039,64627,144895,162745,140538};long h=0;if(w>e){e=w;w=t;m=-1;}for(;e-->w;)h+=d[e]*1e4;System.out.print(h*m);}

De entrada y salida:

p("Mercury","Mars") --> 170030000
p("Mars","Mercury") --> -170030000
p("Earth","Earth")  --> 0

Espaciado y con pestañas:

void p(String p,String l){
    String q="MeVeEaMaJuSaUrNePl";
    int w=q.indexOf(p.substring(0,2))/2,
      e=q.indexOf(l.substring(0,2))/2,
      m=1,
      t=e,
      d[]={5029,4140,7834,55039,64627,144895,162745,140538};
    long h=0;
    if(w>e){
        e=w;
        w=t;
        m=-1;
    }
    for(;e-->w;)
        h+=d[e]*1e4;
    System.out.print(h*m);
}
DeadChex
fuente
1
Podría cortar mucho dividiendo todos los números entre 1000
Tim
¡A punto de hacer eso!
DeadChex
1
También puede poner las declaraciones inty int[]en una línea si la matriz es la última: Me gustaint i=0,j=1,k[]={};
Geobits
1
Puede eliminar dos bytes reemplazando 10000con 1e4.
Anubian Noob
1
ya que sabemos e > wque puede recortar un personaje usando el operador va a: while(e-->w)que es de 12 caracteres, en lugar de for(;e--!=w;)lo que es 13.
corsiKa
6

Python, 118 bytes

n=lambda x:(5029,9169,17003,72042,136669,281564,444309,0)["VeEaMaJuSaUrNe".find(x[:2])/2]*10000
f=lambda a,b:n(b)-n(a)

n es una función que devuelve la distancia de Mercurio.

La cadena "VeEaMaJuSaUrNe"son los dos primeros caracteres de todos los nombres de los planetas, excepto Mercurio . findno puede encontrar Mercurio, por lo que devolverá -1. -1/2 sigue siendo -1, así que este es el último elemento de la tupla, que es 0.

Código de prueba simple:

test = (
    ("Mercury","Venus",50290000),
    ("Venus","Earth",41400000),
    ("Earth","Mars",78340000),
    ("Mars","Jupiter",550390000),
    ("Jupiter","Saturn",646270000),
    ("Saturn","Uranus",1448950000),
    ("Uranus","Neptune",1627450000),
    #("Neptune","Pluto",1405380000),
    ("Mercury","Mars",170030000),
    ("Neptune","Jupiter",-3722670000),
    ("Earth","Earth",0))

for a, b, expect in test:
    print a, "->", b, "=", expect
    assert f(a, b) == expect, f(a, b)
Será
fuente
Buen truco allí.
Anubian Noob
6

APL, 97 95 85 bytes

{1E4×-/(0 5029 9169 17003 72042 136669 281564 444309[{⍵≡'Mars':4⋄'MVEmJSUN'⍳⊃⍵}¨⍵⍺])}

Esto crea una función diádica sin nombre que toma el planeta de origen como argumento izquierdo y el planeta de destino como el derecho.

¡Puedes probarlo en línea !

Alex A.
fuente
4

J-- , 226 bytes

main {str q = "MeVeEaMaJuSaUrNePl"; int w = q.indexOf (a [0] .subs (0,2)) / 2, e = q.indexOf (a [1] .subs (0,2)) / 2, m = 1, t = e, d [] = {5029,4140,7834,55039,64627,144895,162745,140538}; lg h = 0; @i (w> e) {e = w; w = t; m = -1;} @ f (; e - ^^ w;) h + = d [e] * 10000; echo (h * m);}

No creo que esto cuente porque estaba haciendo el lenguaje mientras la pregunta estaba fuera, pero fue principalmente una prueba de cuán pequeño podía comprimir el código Java. Esto se basa total y completamente en la respuesta de DeadChex .

Aquí se explica cómo usarlo:

$ j-- planetas.j-- Mercurio Marte
170030000
fase
fuente
4

Pyth - 59 53 bytes

Codifica la distancia en puntos de código unicode.

-Fm*^T4s<CM"Ꭵာẚ훿ﱳ𣗿𧮹"x"MshrJtaN"@d14_Q

La búsqueda de nombres es genial porque se repite. ¡Gracias a @Dennis por sugerir el índice 14 como una búsqueda sin colisiones!

Pruébalo aquí en línea .

Maltysen
fuente
Usé el índice 14 en mi primera revisión. Está libre de colisiones.
Dennis
3

Bash, 140 bytes

bc<<<"(-`sed -e 's/,/+/;s/[abd-z]//g;s/Mc/0/g;s/V/5029/g;s/E/9169/g;s/M/17003/g;s/J/72042/g;s/S/136669/g;s/U/281564/g;s/N/444309/g'`)*10^4"

$ bash script.sh 
Mercury, Mars
170030000
$ bash script.sh 
Neptune, Jupiter
-3722670000
$ bash script.sh 
Earth, Earth
0
SteelRaven
fuente
3

CoffeeScript, 183 180 bytes

f=(a,b)->t=[d=0,5029,4140,7834,55039,64627,144895,162745];n='MeVeEaMaJuSaUrNe';t=(x=n[q='indexOf'](a[..1])/2)<(y=n[q](b[..1])/2)&&t[x+1..y]||t[y+1..x];d+=c*1e4for c in t;x>y&&-d||d

No minificado:

f = (a,b) ->
 t = [d = 0, 5029, 4140, 7834, 55039, 64627, 144895, 162745]
 n = 'MeVeEaMaJuSaUrNe'
 t = if (x = n[q='indexOf'](a[..1]) / 2) < (y = n[q](b[..1]) / 2) then t[x+1..y] else t[y+1..x];
 d += c * 1e4 for c in t
 if x > y then -d else d
rink.attendant.6
fuente
3

Ruby, 168 bytes

a=ARGV.map{|e|e=='Mars'?3:%w(M V E m J S U N P).index(e[0])}
p 10000*(a[1]<=>a[0])*[5029,4140,7834,55039,64627,144895,162745,140538][a.min..a.max-1].inject(0){|r,e|r+e}

Está diseñado como un script para ejecutarse desde la línea de comandos, por lo tanto, utiliza ARGV. Correr como

$ ruby planets.rb Mercury Mars
170030000
$ ruby planets.rb Neptune Jupiter
-3722670000
$ ruby planets.rb Earth Earth
0
$ ruby planets.rb Mercury Venus
50290000
$ ruby planets.rb Venus Earth
41400000
$ ruby planets.rb Mercury Mercury
0
$ ruby planets.rb Pluto Pluto
0
$ ruby planets.rb Mercury Pluto
5848470000
$ ruby planets.rb Pluto Mercury
-5848470000
Karsten S.
fuente
3

Haskell, 160 158 157 bytes

data P=Mercury|Venus|Earth|Mars|Jupiter|Saturn|Uranus|Neptune deriving Enum
d x=[0,5029,9169,17003,72042,136669,281564,444309]!!fromEnum x
x#y=(d y-d x)*10^4

Ejemplo de uso:

*Main> Neptune # Jupiter
-3722670000

*Main> Mercury # Mars
170030000

Cómo funciona: defino un nuevo tipo de datos Pdonde los nombres de los constructores son los nombres de los planetas. También lo puse en elEnum clase, es decir, obtengo una asignación a enteros vía fromEnum(en orden de definición, comenzando con Mercury-> 0). Este entero puede usarse como índice para la lista de distancia.

Editar: @Kritzefitz encontró dos bytes para guardar y @Alchymist otro. ¡Gracias!

nimi
fuente
Puede eliminar los paréntesis fromEnum xy guardar dos bytes.
Kritzefitz
¿Puedes usar 10 ^ 4 en lugar de 10000 o eso afectará la salida?
Alchymist
@Alchymist: sí, es posible. ¡Gracias!
nimi
2

Julia, 206 203 190 bytes

(f,t)->t==f?0:(M(p)=p=="Mars"?4:findin("MVEmJSUN",p[1])[1];T=M(t);F=M(f);(T>F?1:-1)*sum([get(Dict(zip(1:8,[5029,4140,7834,55039,64627,144895,162745,0])),i,0)for i=T>F?(F:T-1):(T:F+1)])*1000)

Esto crea una función sin nombre que acepta dos cadenas y devuelve un entero. Para llamarlo, dale un nombre.

Ungolfed + explicación:

function planet_distance(p_from, p_to)
    if p_from == p_to
        # Return 0 right away if we aren't going anywhere
        0
    else
        # Define a function to get the planet's order in the solar system
        M(p) = p == "Mars" ? 4 : findin("MVEmJSUN", p[1])[1]

        # Get indices for origin and destination
        ind_from = M(p_from)
        ind_to = M(p_to)

        # Define a dictionary to look up distances by index
        D = Dict(zip(1:8,[5029,4140,7834,55039,64627,144895,162745,0])

        # Determine whether the distance will be positive or negative
        # and the range over which we'll sum distances
        if ind_to > ind_from
            coef = 1
            range = ind_from:ind_to-1
        else
            coef = -1
            range = ind_to:ind_from+1
        end

        # Sum the distances between points
        coef * sum([get(D, i, 0) for i in range]) * 1000
    end
end
Alex A.
fuente
2

Java, 257 228 bytes

enum Z{Mercury(0),Venus(5029),Earth(9169),Mars(17003),Jupiter(72042),Saturn(136669),Uranus(281564),Neptune(444309),Pluto(584847);long r;Z(long x){r=x*10000;}static long d(String...s){return Z.valueOf(s[1]).r-Z.valueOf(s[0]).r;}}

static long d(String...s){...}resuelve el desafío La entrada requiere nombres de planetas para que coincidan exactamente con los nombres de las constantes de la enumeración. Me encanta cómo Java proporciona un método de conversión de cadena a enumeración para mí <3

Uso:

Z.d("Mercury","Pluto") devoluciones 5848470000

Z.d("Pluto","Mercury") devoluciones -5848470000

Z.d("Uranus","Neptune") devoluciones 1627450000

Z.d("Mars","Pluto") devoluciones 5678440000

Jack munición
fuente
1

Macro de preprocesador C (gcc) , 146 bytes

char*p="(3$,?2'+";D[]={0,5029,9169,17003,72042,136669,281564,444309,584847};	
#define E(x)D[strchr(p,*x^x[1])-p]
#define f(s,t)(E(t)-E(s))*10000LL

Pruébalo en línea!

gastropner
fuente