Кларенс Медленная машинистка


35

Введение

Кларенс - клерк ввода данных, работающий в интернет-провайдере. Его задача - вручную вводить IP-адреса всех клиентов интернет-провайдера в базу данных. Он делает это с помощью клавиатуры, которая имеет следующую раскладку:

123
456
789
.0

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

Кларенс, как и следовало ожидать от того, кто работает в ISP, использует очень медленную и неэффективную систему набора текста. Он использует один палец и ищет клавишу, затем перемещает палец к клавише, затем нажимает ее и повторяет все цифры в числе. Возможно, вы знаете об этом стиле как «поисковая система орла», так как палец ищет над клавиатурой правильную клавишу, а затем нажимает на нажатие клавиши, как орел, опускающийся вниз для убийства.

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

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

Поэтому общее расстояние, Кларенс пошевелил пальцем , чтобы ввести 7851IS , 1 + 1 + √2который составляет около 3.41cm.

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

Описание входа

Ввод - это строка, которая будет иметь вид

().().().()

где каждый ()является целым числом в диапазоне 0- 999. Это представляет IP-адрес, который должен ввести Кларенс. Пример ввода может быть:

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 Я ожидаю программу, да. Стандартные аргументы, аргументы командной строки или пользовательские функции ввода являются приемлемыми.
абсент

2
@dacapoaria - «поиск орла» также известен как «охота и клевка» или «поиск и уничтожение» для более жестких машинисток.

12
@ArtofCode Кларенс работает на провайдера, и иногда провайдер отправляет ему неверные данные для ввода в базу данных. Кларенс вводит данные в любом случае. В любом случае, это каноническая причина. Фактическая причина в том, что я упустил это из виду при написании спецификации.
абсент

3
Учитывая только допустимый диапазон (0-255) IP-адресов, какой должна быть оптимальная компоновка клавиатуры для ввода всех адресов в кратчайшем пути?
Израиль Моралес

Ответы:


16

CJam, 46 44 43 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,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);

Ввод взят из стандартного ввода. -.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);}

Ungolfed:

#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. Исходя из того, что я видел в вики / мета, это звучало так, будто входные данные в качестве аргументов функции - это допустимая опция, если входные данные не указаны явно. Я изменю это, если моя интерпретация неправильна. 4. Я всегда думал, что только функции, которые возвращают, intмогут быть использованы без объявления. Но действительно, Clang также принимает это с предупреждением, поэтому я избавился от этого.
Рето Коради

Вики утверждают, что функции разрешены по умолчанию, да, но ОП написал, что ваша задача - написать программу ... Вам не нужны введенные вами скобки, если вы пишете цикл как 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

Для этого есть более короткий код Python (108) для SP3000:

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.