Кларенс повільний машиніст


35

Вступ

Кларенс - службовець з введення даних, який працює в Інтернет-провайдера. Його завдання полягає в ручному введенні IP-адреси всіх клієнтів провайдера в базу даних. Він робить це за допомогою клавіатури, яка має такий макет:

123
456
789
.0

Відстань між центром горизонтальних або вертикально сусідніх клавіш рівно один сантиметр. Наприклад, відстань між центрами 3і 9склало б два сантиметри. Відстань між центрами 3та 5складе would2см. Теореми Піфагора достатньо для обчислення відстані між будь-якими двома ключами.

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

Наприклад, ось як Кларенс набрав би номер 7851:

  1. Він заводить палець у 7та натискає на ключ.
  2. Він переміщує палець вправо на 1 см 8і натискає клавішу.
  3. Він рухає пальцем вгору на 1 см 5і натискає клавішу.
  4. Він рухає пальцем по діагоналі вгору і вліво на 2 см до 1і натискає клавішу.

Тому загальна відстань, Кларенс поворушив пальцем , щоб ввести 7851IS , 1 + 1 + √2який становить близько 3.41cm.

Ваше завдання - написати програму, яка обчислює відстань, яку Кларенс повинен перемістити пальцем, щоб ввести довільні IP-адреси.

Опис вводу

Введення - це рядок, який буде у формі

().().().()

де кожне ()ціле число в діапазоні 0- 999. Це відображає IP-адресу, в яку повинен ввести Clarence. Приклад введення може бути:

219.45.143.143

Я також хотів би зазначити, що входи, такі як 0.42.42.42або 999.999.999.999все ще є дійсними входами, незважаючи на те, що вони є невірними IP-адресами. Тому вам не потрібно включати в програму код підтвердження IP-адреси.

Опис виходу

Виведіть відстань, яку Кларенс повинен перемістити пальцем, щоб набрати вказану IP-адресу. Круглі відповіді на два десяткових знаки, де потрібно, і використовуйте cmодиницю у своєму висновку. Вихід для прикладу входу дорівнює 27.38cm(1 + √8 + √5 + 2 + 1 + √5 + 3 + 1 + √5 + √13 + 3 + 1 + √5).


29
Людина, у провайдерів є дивні клавіатури ...
Денніс,

1
@RetoKoradi Я очікую програми, так. stdin, аргументи командного рядка або функції введення користувача є прийнятними.
абсент

2
@dacapoaria - "пошук орлів" також відомий як "полювати і клювати" або "шукати і знищувати" для більш важких машиністів.

12
@ArtofCode Clarence працює в Інтернет-провайдері, і іноді провайдер надсилає йому недійсні дані для введення в базу даних. Clarence в будь-якому випадку вводить дані. Це все-таки канонічна причина. Фактична причина в тому, що я не помітив цього при написанні специфікації.
абсент

3
Враховуючи лише допустимий діапазон (0-255) IP-адреси, яким має бути оптимальне розташування клавіатури для введення всіх адрес, що знаходяться в найкоротшому шляху?
Ізраїль Моралес

Відповіді:


16

CJam, 46 44 43 38 38 37 34 байт

rA,sd`f#3fmd2/2ew::.-::mh:+2mO"cm"

Завдяки @ user23013 за пропозицію mh, яка дозволила зберегти 5 байт.

Спробуйте його в Інтернеті в інтерпретаторі CJam .

Як це працює

r     e# Read a token from STDIN.
A,    e# Push [0 1 2 3 4 5 6 7 8 9].
s     e# Stringify: [0 1 2 3 4 5 6 7 8 9] -> "0123456789"
d     e# Cast to Double: "0123456789" -> 123456789.0
`     e# Inspect: 123456789.0 -> "123456789.0"
f#    e# Push the index of each character from the input in "123456789.0".
3fmd  e# Push the quotient and residue of each index divided by 3.
2/    e# Split the resulting array into pairs.
2ew   e# Convert the array of pairs in the array of all overlapping pairs of pair.
::.-  e# Reduce each pair using vectorized difference: [[a b][c d]] -> [a-b c-d]
::mh  e# Reduce each reduced pair to its 2-norm distance: [a b] -> sqrt(aa + bb)
:+    e# Sum all distances.
2mO   e# Round to two decimal places.
"cm"  e# Push "cm".

2
{3fmd~@-@@-mh}%.
jimmy23013

@ user23013: Дякую У мене mhнавіть ідеї не було .
Денніс

16

Pyth, 38 35 34 байт

+.Rs.aM-M.:m.jF.Dx`ciUTT1b3z2 2"cm

Демонстрація.

Індексація в рядок плаваючої ідеї завдяки @Dennis.

Пояснення на фальшивому вході 15.0:

  • Спочатку беремо вхід. Він неявно зберігається в z. '15 .0 '
  • Ми відображаємо цей список виглядає наступним чином : m.jF.Dx`ciUTT1k3z.

    • UT: Ми формуємо список [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
    • iUTT: Далі ми розглядаємо цей список як базове число 10, яке дає нам 123456789.
    • ciUTT1: Далі ми перетворюємо це число в поплавок, розділяючи його з плаваючою точкою на 1, даючи 123456789.0.
    • `: Перетворити в рядок. '123456789.0'
    • x k: Візьміть індекс вхідного символу в цьому рядку. [0, 4, 9, 10].
    • .D 3: .D- функція divmod, що виводить перший вхід розділеним і модульованим другим входом. Другий вхід - 3. Це дає фізичне розташування персонажа на цифровій панелі. [(0, 0), (1, 1), (3, 0), (3, 1)].
    • .jF: .j- конструктор складних чисел. Fзастосовує його до кортежу. [0j, (1+1j), (3+0j), (3+1j)].
  • .: 2: Тепер ми беремо 2 вхідні підрядки цього списку, щоб ми могли знайти попарні відстані. [[0j, (1+1j)], [(1+1j), (3+0j)], [(3+0j), (3+1j)]].
  • -M: Бере різницю двох складних чисел. [(-1-1j), (-2+1j), -1j].
  • .aM: Приймає абсолютне значення результату. Це відстань між місцями розташування клавіатури.[1.4142135623730951, 2.23606797749979, 1.0]
  • s: Підсумовуйте відстані. 4.650281539872885.
  • .R 2: Округніть до 2 знаків після коми. 4.65.
  • + "cm: Додайте 'cm'до кінця та надрукуйте. 4.65cm.

7

PHP - 108 байт

<?for(;$v=strpos(-.987654321,fgetc(STDIN));$l=$v)$l&&$t+=hypot($l/3%4-$v/3%4,$l%3-$v%3);printf('%.2fcm',$t);

Введення взято з stdin. -.987654321Направлено в strposфункції приймає значення '-0.987654321'в контексті рядки.


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

$ echo 219.45.143.143 | php isp.php
27.38cm

5

C, 192 177 159 байт

Оновлена ​​версія, тепер повна програма, що використовує аргумент командного рядка. У той же час вдосконалено, щоб все-таки бути коротшим, ніж попередня версія:

#define G c=*a[1]++,c=c>48?c-49:c/2-14,u=c%3,v=c/3
float r;c,u,v,p,q;main(int n,char**a){for(G;*a[1];)p=u,q=v,G,p-=u,q-=v,r+=sqrt(p*p+q*q);printf("%.2fcm",r);}

Безголівки:

#include <stdio.h>
#include <math.h>

float r;
int c, u, v, p, q;

int main(int n, char** a) {
    c = *a[1]++;
    c = c > 48 ? c - 49 : c / 2 - 14;
    u = c % 3;
    v = c / 3;
    for ( ; *a[1]; ) {
        p = u;
        q = v;
        c = *a[1]++;
        c = c > 48 ? c - 49 : c / 2 - 14;
        u = c % 3;
        v = c / 3;
        p -= u;
        q -= v;
        r += sqrt(p * p + q * q);
    }

    printf("%.2fcm",r);

    return 0;
}

У версії для гольфу використовується препроцесор #defineдля скорочення деяких повторних кодів у повній версії.


2
1. У вашій версії для гольфу відсутня крапка з комою в кінці. 2. Ваша гольф-версія дає невірні результати, оскільки ви збільшуєте її sперед тим, як перевірити, що *sце не нульовий показник. 3. Програма згаданої програми в своїй посаді. Я не впевнений, чи прийнята функція. 4. З GCC вам не потрібно включати. 5. sqrtкоротше, ніж sqrtf. 6. pow(u-p,2)коротше, ніж (u-p)*(u-p). 7. Я не впевнений, але я думаю , зберігання обидві координати в одному рядку і установки u=x[c]/3і v=x[c]%3повинні бути коротше.
Денніс

Виправлена ​​проблема правильності. Виявляється, я продовжував компілювати попередню версію, роблячи точну настройку. Вибач за це. 1, 2. Виправлено. Я насправді був здивований, що можу залишити їх подалі. Розбитий тест пояснив би це ... 3. Виходячи з того, що я бачив у wiki / meta, це звучало як прийняття введення як функції аргументів - це дозволений варіант, якщо введення не вказано явно. Я його зміню, якщо моє тлумачення є невірним. 4. Я завжди вважав, що лише ті функції, що повертаються, intможуть використовуватися незадекларованими. Але дійсно, Кланг також приймає це з попередженням, тому я його позбувся.
Рето Коради

У wiki зазначено, що функції дозволені за замовчуванням, так, але ОП написав, що ваше завдання - написати програму ... Вам не потрібні введені дужки, якщо ви пишете цикл як p=u,q=v,G,r+=....
Денніс

Я попросив ОП роз'яснити вимоги щодо введення. Щодо коду, я повернув його до трохи старшої версії, перш ніж я оптимізував її до некоректності. Я сфотографую його настройку завтра, але зламану версію я не хотів стояти занадто довго. Дякую за покажчики
Рето Коради

@Dennis Ок, оновлена ​​версія повинна бути кращою в усіх відношеннях. Тепер повна програма, та ще коротша завдяки деяким оптимізаціям. Ще раз дякую, що повідомили мені про проблеми з початковою версією.
Рето Коради

3

JavaScript ( ES6 ), 132

Введення / виведення через спливаюче вікно. Запустіть фрагмент для тестування (лише Firefox)

[for(a of prompt(d=''))[p,q,d]=[x=(a=a<'0'?9:-a?a-1:10)%3,y=a/3|0,d!==''?d+Math.sqrt((p-=x)*p+(q-=y)*q):0]],alert(d.toFixed(2)+'cm')


3

Python 3, 108 байт

L=[x//3*1j+x%3for x in map("123456789.0".find,input())]
print("%.2fcm"%sum(abs(a-b)for a,b in zip(L,L[1:])))

Справді, не дуже добре гольф, але, принаймні, це пов'язано з PHP.



2

Пітон 199 171 166

Для SP3000 для цього існує коротший код Python (108):

https://codegolf.stackexchange.com/a/50854/41163

import sys
p=r=0
for i in sys.argv[1]:
 c=3,0
 if i!=".":c=divmod(int(i)-1,3)
 if i<1:c=3,1
 if p:r+=((p[1]-c[1])**2+(p[0]-c[0])**2)**0.5
 p=c
print"%.2fcm"%r

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

$ python isp.py 219.45.143.143
27.38cm

Запустити онлайн: http://codepad.org/h9CWCBNO

Коментований код

import sys

# p - last position as (y,x) tuple - initialized with 0, because "if 0" -> equals to "False"
p = 0
# r - result of adding all distances - ini with 0, because not moved any distances on start
r = 0

# Loop over chars
for char in sys.argv[1]:
   # c - current position of typist as (y,x) tuple

   # Always set c to position of "." key 
   c = 3,0 # lazy for c=(3,0)

   # Check if char is not the "." key
   if char !=".":

      # Get position of char on keypad
      c=divmod(int(char)-1,3)

      if char<1:
         c=3,1  

   # If this is the first char, 
   # then STORE_OPERATION has not been executed, 
   # so p is still p=0 from original initialization 
   # calling "if 0" evaluates to False,
   # so we jump this code block, for the first char
   if p:                           
      # calculate delta of x, y from current and last position, 
      # then add both deltas squared (**2),
      # then get square root of it (**0.5 = **1/2)
      # add to r (+=)
      r+=( (p[1]-c[1])**2 + (p[0]-c[0])**2 )**0.5

   # STORE_OPERATION - Store current position as last position
   p = c

# .2f returns r with 2 trailing digits
print"%.2fcm"%r

1
Ви можете зберегти кілька байтів, визначивши ifпропозиції в одному рядку, наприкладif i<1:c=3,1
Zgarb

1
Ви можете додати підсвічування синтаксису, поставивши цей коментар у верхній частині свого повідомлення:<!-- language: lang-python -->
Мартін Ендер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.