느린 타이피스트 클라렌스


35

소개

Clarence는 인터넷 서비스 제공 업체에서 근무하는 데이터 입력 담당자입니다. 그의 임무는 모든 ISP 고객의 IP 주소를 데이터베이스에 수동으로 입력하는 것입니다. 그는 다음과 같은 레이아웃의 키패드를 사용하여이 작업을 수행합니다.

123
456
789
.0

수평 또는 수직으로 인접한 키의 중심 사이의 거리는 정확히 1 센티미터입니다. 예를 들어 중심 3과 중심 사이의 거리는 92 센티미터입니다. 의 중심 사이의 거리 3와는 5√2cm 될 것이다. 피타고라스 정리는 두 키 사이의 거리를 계산하기에 충분합니다.

Clarence는 ISP에서 일하는 사람이 기대할 수 있듯이 매우 느리고 비효율적 인 타이핑 시스템을 사용합니다. 그는 한 손가락을 사용하여 키를 검색 한 다음 손가락을 키로 옮긴 다음 누른 다음 숫자의 모든 숫자에 대해 반복합니다. 이 스타일을 "이글 검색 시스템"이라고 생각할 수 있습니다. 손가락으로 키를 누르기 전에 키보드 위에서 올바른 키를 검색하기 때문입니다.

예를 들어, Clarence가 숫자를 입력하는 방법은 다음과 7851같습니다.

  1. 그는 손가락을 시작 7하고 열쇠를 밉니다.
  2. 손가락을 오른쪽으로 1cm 움직여 8키를 밉니다.
  3. 그는 손가락을 1cm 위로 움직여 5키를 밉니다.
  4. 그는 손가락을 대각선으로 위로 움직이고 √2cm 왼쪽으로 1키를 밉니다 .

따라서 클라렌스에 입력 그의 손가락을 이동 한 총 거리 7851IS 1 + 1 + √23.41cm 관한 것이다.

당신의 임무는 Clarence가 임의의 IP 주소를 입력하기 위해 손가락을 움직여야하는 거리를 계산하는 프로그램을 작성하는 것입니다.

입력 설명

입력은 형태가 될 문자열입니다

().().().()

여기서 각각 ()0- 범위의 정수입니다 999. 이는 Clarence가 입력해야하는 IP 주소를 나타냅니다. 입력 예는 다음과 같습니다.

219.45.143.143

또한 같은 입력 점을 지적하는 것처럼 0.42.42.42또는 999.999.999.999그들이 잘못된 IP 주소 있다는 사실에도 불구하고, 여전히 유효 입력합니다. 따라서 프로그램에 IP 주소 확인 코드를 포함시킬 필요가 없습니다.

출력 설명

지정된 IP 주소를 입력하기 위해 Clarence가 손가락을 움직여야하는 거리를 출력하십시오. 필요한 경우 소수점 이하 두 자리로 반올림하고 cm출력에 단위를 사용하십시오 . 예제 입력의 출력은 27.38cm(1 + √8 + √5 + 2 + 1 + √5 + 3 + 1 + √5 + √13 + 3 + 1 + √5)입니다.


29
사람, ISP는 이상한 키보드를 가지고 있습니다.
Dennis

1
@RetoKoradi 프로그램이 필요합니다. 예. stdin, 명령 행 인수 또는 사용자 입력 함수가 허용됩니다.
압생트

2
@dacapoaria- '독수리 검색'은 좀 더 엄격한 타이 포스트의 경우 '헌트 앤 펙'또는 '검색 및 파괴'라고도합니다.

12
@ArtofCode Clarence는 ISP에서 작동하며 때로는 ISP가 데이터베이스에 입력하기 위해 잘못된 데이터를 보냅니다. Clarence는 어쨌든 데이터를 입력합니다. 그것은 어쨌든 정식 이유입니다. 실제 이유는 사양을 작성할 때 간과했기 때문입니다.
압생트

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 '
  • 이 목록을 다음과 같이 매핑합니다 : 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: .Ddivmod 함수로, 첫 번째 입력을 두 번째 입력으로 나눈 모듈로 출력합니다. 두 번째 입력은 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. 골프 버전은 0이 아닌 값 s을 확인하기 전에 증가 시키기 때문에 잘못된 결과를 생성 *s합니다. 3. OP는 그의 직책에서 프로그램을 말했다. 기능이 허용되는지 확실하지 않습니다. 4. GCC를 사용하면 포함이 필요하지 않습니다. 5. sqrt보다 짧습니다 sqrtf. 6. pow(u-p,2)보다 짧습니다 (u-p)*(u-p). 7. 나는 모르겠지만, 하나의 문자열에서 두 좌표를 저장하고 설정을 생각 u=x[c]/3하고 v=x[c]%3짧게해야한다.
Dennis

정확성 문제를 해결했습니다. 미세 조정을 수행하면서 이전 버전을 계속 컴파일 한 것으로 나타났습니다. 미안합니다. 1, 2. 고정. 나는 내가 그들을 떠날 수 있다는 사실에 실제로 놀랐다. 깨진 테스트는 그것을 설명 할 것입니다 ... 3. 위키 / 메타에서 본 내용에 따르면 입력이 명시 적으로 지정되지 않은 경우 입력을 함수 인수로 사용하는 것이 허용되는 옵션처럼 들렸습니다. 해석이 틀리면 변경하겠습니다. 4. 항상 반환하는 함수 만 int선언되지 않은 상태로 사용할 수 있다고 생각했습니다 . 그러나 실제로, clang은 경고와 함께 그것을 받아들이므로 제거했습니다.
Reto Koradi

위키는 기본적으로 기능이 허용된다고 말하지만, OP는 당신의 작업이 프로그램을 작성하는 것이라고 썼다 ... 루프를로 쓰면 도입 한 괄호가 필요하지 않습니다 p=u,q=v,G,r+=....
Dennis

입력 요구 사항에 대한 설명을 OP에 요청했습니다. 코드에서 잘못된 것으로 최적화하기 전에 약간 오래된 버전으로 롤백했습니다. 내일 조정을 위해 다시 한 번 찍을 것이지만 깨진 버전을 너무 오래두고 싶지는 않았습니다. 포인터 주셔서 감사합니다.
Reto Koradi

@Dennis Ok, 모든면에서 업데이트 된 버전이 더 좋을 것입니다. 이제 완전한 프로그램이지만 일부 최적화 덕분에 여전히 짧습니다. 초기 버전의 문제에 대해 알려 주셔서 다시 한 번 감사드립니다.
Reto Koradi

3

자바 스크립트 ( ES6 ), 132

팝업을 통한 I / O 스 니펫을 실행하여 테스트 (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

파이썬 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 -->
Martin Ender
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.