Учитывая названия двух планет, дайте расстояние

25

Используя следующую таблицу ( источник ), напишите некоторый код, который берет имена двух планет и возвращает расстояние между ними:

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

Примеры, ввод, затем вывод:

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

Обратите внимание на отрицательный знак, поскольку Юпитер стоит перед Нептуном. Они также являются целыми числами.

Плутон не должен быть включен (в основном из-за странной орбиты, из-за которой трудно определить расстояние - данное расстояние - мой собственный расчет, но поскольку Плутон теперь всем известен ...).

Под расстояниями между планетами я подразумеваю орбиты - я не ожидаю даты и не знаю, где они находятся.

Это код гольф, самый короткий код выигрывает.

Тим
источник
10
+1 за не "потому что Плутон не планета"
Оптимизатор
@Optimizer Я делаю проект, который нуждается в расстояниях, и никто не может согласиться! Я прибег к использованию его орбитального периода и орбитальной скорости ...
Тим
Может ли наша функция / программа вернуть число с плавающей точкой? то есть Mercury, Mars -> 170030000.0?
Каде
8
Это подразумевается, но предполагаем ли мы святой момент во времени, когда все планеты находятся на одной прямой, а расстояние между любыми двумя несмежными планетами является суммой расстояний между ними?
Sp3000 15.07.15
3
Есть ли штраф за включение Плутона (помимо байтов)? Я чувствую себя немного плохо из-за этого, просто у него был большой день и все ...
DeadChex

Ответы:

24

CJam, 54 51 44 байта

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

Попробуйте онлайн в интерпретаторе CJam .

идея

Мы используем простую функцию хеширования, чтобы идентифицировать все восемь планет. Рассматривая каждое имя как массив его кодовых точек, преобразовывая их из базы 26 в целое число и получая результат по модулю 93, а затем по модулю 8, Меркурий , Венера , Земля и т. Д. Отображаются в 2 , 4 , 0 , 1 , 3 , 5. , 6 и 7 .

Теперь мы выбираем точку, которая находится на 320 000 км позади Нептуна, и рассчитываем расстояния всех восьми планет до этой точки. После отбрасывания четырех конечных нулей и изменения порядка планет, чтобы они соответствовали 8 индексам сверху, мы получаем массив

[435172 427338 444341 372299 439312 307672 162777 32]

который, если мы закодируем каждое целое число в базе 70, даст следующее:

[
   [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]
]

Помня, что две соседние цифры (A B)могут быть заменены на ((A-1) (B+70)), мы можем изменить массив сверху, чтобы все целые числа могли быть закодированы как печатные символы ASCII:

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

Код

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.
Деннис
источник
10

Python 2, 149 147 142 138 128 123 119 байт

Просто используйте простой поиск, чтобы выяснить, какие расстояния использовать :) Это определяет анонимную функцию, поэтому для ее использования вам нужно дать ей имя.

Спасибо Sp3000 за идеи, которые сэкономили кучу байтов!

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

Отступы правильно и немного загнут для удобства чтения:

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

Звоните так:

f("Mercury","Mars")    -> 170030000
f("Neptune","Jupiter") -> -3722670000L
Када
источник
В вашем выводе отсутствует 0, но вы, похоже, умножаете на нужную сумму.
Тим
@Tim Я запутался в примере вызова, у него есть четвертый 0 в конце: P
Kade
Ты забыл Плутон?
Будет
@ Вилл Плутон не должен быть включен ...
Каде
(Вы сохраните как минимум два байта, если скопируете этот трюк, возвращающий -1, из моей записи, и тогда вы опередите меня :)
Уилл
8

Пролог, 190 174 151 байт

Спасибо Fatalize за руководство.

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
источник
Почему бы вам не вернуть этот результат напрямую, s(A, B, R)а не писать R? Для выходных данных ничего не указано, поэтому предикатный возврат должен быть в порядке.
Роковая
Вы также можете сбрить 22 байта, изменив предикат gдля 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]).и удаления всех фактов для планет. Это менее круто, чем, =..но короче получить сопоставление ключ-значение
Fatalize
7

JavaScript (ES6), 115 110 байт

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

Это анонимная функция, поэтому вам нужно будет сохранить ее в переменной ( f=...; f("Earth", "Mercury")) или использовать в качестве выражения в скобках ( (...)("Earth", "Mercury").

Эта грязная строка - это первые две буквы каждой планеты, за которыми следует расстояние от планеты до Меркурия (деленное на 10000 для экономии места). Внутренняя функция gделает следующее:

  1. берет имя ( k),
  2. уменьшает его до первых двух букв ( k[0]+k[1]),
  3. использует совпадение с регулярным выражением, чтобы найти соответствующее расстояние от Меркурия, разделенное на 10000 (например, регулярное выражение "Земля" выглядит так Ea(\d*)),
  4. умножает значение на 10000 ( 1e4) и возвращает результат.

Вычитая одно расстояние Меркурия из другого, мы получаем расстояние между планетами.

apsillers
источник
@ vihan1086 Ага, я сделал классическую ошибку, путая значение точки кода с фактическим представлением байтов :(
apsillers
1
UTF-8 - просто неправильная кодировка для этого трюка. Все возвращаемые символы btoaимеют кодовые точки ниже 256, поэтому ISO 8859-1 будет кодировать каждый символ, используя один байт.
Деннис
7

Java, 274 272 264 байта (включая Плутон!)

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

Ввод, вывод:

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

Размещено и с вкладками:

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
источник
1
Вы могли бы много отрезать, разделив все числа на 1000
Тим
Просто собираюсь сделать это!
DeadChex
1
Вы также можете поместить объявления intи и int[]в одну строку, если массив идет последним: Likeint i=0,j=1,k[]={};
Geobits
1
Вы можете сбрить два байта, заменив 10000на 1e4.
Анубиан Нуб
1
поскольку мы знаем, что e > wвы можете обрезать символ, используя оператор while(e-->w)for(;e--!=w;)
Go
6

Python, 118 байт

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 это функция, которая возвращает расстояние от Меркурия.

Строка "VeEaMaJuSaUrNe"- это первые два символа всех названий планет, кроме Меркурия . findне может найти Меркурий, поэтому вернет -1. -1/2 по-прежнему равно -1, так что это последний элемент в кортеже, который равен 0.

Простой тестовый код:

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)
Будет
источник
Хороший трюк там.
Анубиан Нуб
6

APL, 97 95 85 байт

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

Это создает безымянную двоичную функцию, которая принимает исходную планету в качестве левого аргумента и целевую планету в качестве правой.

Вы можете попробовать это онлайн !

Алекс А.
источник
4

J-- , 226 байт

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 = т; т = -1;} @ F (; е - ^^ ш;) H + = д [е] * 10000; эхо (ч * м);}

Я не думаю, что это считается, так как я создавал язык, пока вопрос был задан, но это был в основном тест на то, насколько маленьким я мог сжать код Java. Это полностью и полностью основано на ответе DeadChex .

Вот как это использовать:

$ j-- planets.j-- Меркурий Марс
170030000
фаза
источник
4

Pyth - 59 53 байта

Кодирует расстояние в кодовых точках Юникода.

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

Поиск имени довольно крутой, потому что он зацикливается. Спасибо @Dennis за предложение индекс 14 в качестве поиска без столкновений!

Попробуйте здесь онлайн .

Maltysen
источник
Я использовал индекс 14 в моей первой ревизии. Это без столкновений.
Деннис
3

Баш, 140 байт

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
источник
3

CoffeeScript, 183 180 байт

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

Unminified:

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
источник
3

Рубин, 168 байт

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}

Он разработан как скрипт для запуска из командной строки, поэтому использует ARGV. Беги как

$ 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
Карстен С.
источник
3

Haskell, 160 158 157 байт

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

Пример использования:

*Main> Neptune # Jupiter
-3722670000

*Main> Mercury # Mars
170030000

Как это работает: я определяю новый тип данных, Pгде имена конструктора - это имена планет. Я также поместил его в Enumкласс, то есть я получаю сопоставление с целыми числами через fromEnum(в порядке определения, начиная с Mercury-> 0). Это целое число может использоваться в качестве индекса для списка расстояний.

Изменить: @Kritzefitz нашел два байта для сохранения и @Alchymist еще один. Благодарность!

Ними
источник
Вы можете убрать круглые скобки fromEnum xи сохранить два байта.
Kritzefitz
Можете ли вы использовать 10 ^ 4 вместо 10000 или это повлияет на результат?
Алхимик
@ Алхимик: да, это возможно. Благодарность!
Ними
2

Юлия, 206 203 190 байтов

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

Это создает безымянную функцию, которая принимает две строки и возвращает целое число. Чтобы назвать это, дать ему имя.

Ungolfed + объяснение:

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
Алекс А.
источник
2

Джава, 257 228 байт

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){...}решает проблему. Ввод требует, чтобы имена планет точно совпадали с именами констант перечисления. Мне нравится, как Java предоставляет метод преобразования строк в enum для меня <3

Использование:

Z.d("Mercury","Pluto") возвращается 5848470000

Z.d("Pluto","Mercury") возвращается -5848470000

Z.d("Uranus","Neptune") возвращается 1627450000

Z.d("Mars","Pluto") возвращается 5678440000

Джек Боеприпасы
источник