Làm rõ máy đánh chữ chậm


35

Giới thiệu

Clarence là một nhân viên nhập dữ liệu làm việc tại một nhà cung cấp dịch vụ internet. Công việc của anh là nhập thủ công địa chỉ IP của tất cả các khách hàng của ISP vào cơ sở dữ liệu. Anh ta làm điều này bằng cách sử dụng một bàn phím có bố cục sau:

123
456
789
.0

Khoảng cách giữa tâm của các phím liền kề theo chiều ngang hoặc chiều dọc chính xác là một centimet. Chẳng hạn, khoảng cách giữa tâm 39sẽ là hai centimet. Khoảng cách giữa tâm 35sẽ là √2cm. Định lý Pythagoras là đủ để tính khoảng cách giữa hai khóa bất kỳ.

Clarence, như bạn có thể mong đợi từ một người làm việc trong một ISP, sử dụng một hệ thống gõ rất chậm và không hiệu quả. Anh ta sử dụng một ngón tay và tìm kiếm phím, sau đó di chuyển ngón tay đến phím, sau đó nhấn nó và lặp lại cho tất cả các chữ số trong số. Bạn có thể biết phong cách này là "hệ thống tìm kiếm đại bàng" vì ngón tay tìm kiếm trên bàn phím để tìm phím chính xác trước khi lao xuống nhấn phím, giống như một con đại bàng lao xuống để giết.

Ví dụ, đây là cách Clarence sẽ gõ số 7851:

  1. Anh ta bắt đầu ngón tay của mình tại 7và nhấn phím.
  2. Anh di chuyển ngón tay sang phải 1cm 8và ấn phím.
  3. Anh di chuyển ngón tay của mình lên 1cm 5và nhấn phím.
  4. Anh ta di chuyển ngón tay theo đường chéo lên trên và để lại √2cm 1và nhấn phím.

Do đó tổng khoảng cách mà Clarence chuyển ngón tay của mình để gõ vào 78511 + 1 + √2đó là khoảng 3.41cm.

Nhiệm vụ của bạn là viết chương trình tính khoảng cách Clarence phải di chuyển ngón tay để gõ địa chỉ IP tùy ý.

Mô tả đầu vào

Đầu vào là một chuỗi sẽ ở dạng

().().().()

trong đó mỗi số ()là một số nguyên trong phạm vi 0- 999. Điều này thể hiện địa chỉ IP mà Clarence phải nhập. Một ví dụ đầu vào có thể là:

219.45.143.143

Tôi cũng muốn chỉ ra rằng các đầu vào như 0.42.42.42hoặc 999.999.999.999vẫn là đầu vào hợp lệ, mặc dù thực tế chúng là các địa chỉ IP không hợp lệ. Vì vậy, bạn không cần đưa bất kỳ mã xác minh địa chỉ IP nào vào chương trình của mình.

Mô tả đầu ra

Xuất khoảng cách mà Clarence phải di chuyển ngón tay của mình để nhập địa chỉ IP được chỉ định. Làm tròn câu trả lời đến hai vị trí thập phân khi cần và sử dụng cmđơn vị trong đầu ra của bạn. Đầu ra cho đầu vào ví dụ là 27.38cm(1 + 8 + 5 + 2 + 1 + 5 + 3 + 1 + 5 + 13 + 3 + 1 + 5).


29
Man, ISP có bàn phím kỳ lạ ...
Dennis

1
@RetoKoradi Tôi mong đợi một chương trình, vâng. stdin, đối số dòng lệnh hoặc chức năng nhập của người dùng đều được chấp nhận.
absinthe

2
@dacapoaria - 'tìm kiếm đại bàng' còn được gọi là 'săn và mổ' hoặc 'tìm kiếm và tiêu diệt' đối với những người đánh máy nặng tay hơn.

12
@ArtofCode Clarence hoạt động tại một ISP và đôi khi ISP gửi cho anh ta dữ liệu không hợp lệ để nhập vào cơ sở dữ liệu. Clarence gõ dữ liệu trong anyway. Dù sao đó cũng là lý do kinh điển. Lý do thực sự là vì tôi đã bỏ qua điều đó khi viết thông số kỹ thuật.
absinthe

3
Chỉ xem xét các Địa chỉ IP phạm vi hợp lệ (0-255), đó có phải là sự sắp xếp tối ưu của bàn phím để nhập tất cả các địa chỉ đó trong đường dẫn ngắn nhất không?
Israel Morales

Câu trả lời:


16

CJam, 46 44 43 38 37 34 byte

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

Cảm ơn @ user23013 đã gợi ý mh, giúp lưu 5 byte.

Hãy thử trực tuyến trong trình thông dịch CJam .

Làm thế nào nó hoạt động

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: Cảm ơn. Tôi mhthậm chí không có ý tưởng nào tồn tại.
Dennis

16

Pyth, 38 35 34 byte

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

Trình diễn.

Lập chỉ mục vào chuỗi ý tưởng nổi nhờ @Dennis.

Giải thích, về đầu vào giả mạo 15.0:

  • Đầu tiên, chúng tôi lấy đầu vào. Nó được lưu trữ ngầm trong z. '15 .0 '
  • Chúng tôi ánh xạ danh sách này như sau : m.jF.Dx`ciUTT1k3z.

    • UT: Chúng tôi tạo danh sách [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
    • iUTT: Tiếp theo, chúng tôi coi danh sách này là số 10 cơ sở cho chúng tôi 123456789.
    • ciUTT1: Tiếp theo, chúng tôi chuyển đổi số này thành số float bằng cách thả nổi chia cho 1, cho 123456789.0.
    • `: Chuyển đổi thành một chuỗi. '123456789.0'
    • x k: Lấy chỉ mục của ký tự đầu vào trong chuỗi đó. [0, 4, 9, 10].
    • .D 3: .Dlà hàm divmod, xuất ra đầu vào đầu tiên được chia và modulo'd cho đầu vào thứ hai. Đầu vào thứ hai là 3, ở đây. Điều này cho vị trí vật lý của nhân vật trên bàn phím số. [(0, 0), (1, 1), (3, 0), (3, 1)].
    • .jF: .jlà hàm tạo số phức. Fáp dụng nó cho tuple. [0j, (1+1j), (3+0j), (3+1j)].
  • .: 2: Bây giờ, chúng tôi lấy 2 chuỗi con của danh sách này để chúng tôi có thể tìm thấy khoảng cách theo cặp. [[0j, (1+1j)], [(1+1j), (3+0j)], [(3+0j), (3+1j)]].
  • -M: Lấy sự khác biệt của hai số phức. [(-1-1j), (-2+1j), -1j].
  • .aM: Lấy giá trị tuyệt đối của kết quả. Đây là khoảng cách giữa các vị trí bàn phím.[1.4142135623730951, 2.23606797749979, 1.0]
  • s: Tính tổng khoảng cách. 4.650281539872885.
  • .R 2: Làm tròn đến 2 chữ số thập phân. 4.65.
  • + "cm: Thêm 'cm'vào cuối và in. 4.65cm.

7

PHP - 108 byte

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

Đầu vào được lấy từ stdin. Việc -.987654321gửi đến strposhàm ước tính '-0.987654321'trong ngữ cảnh chuỗi.


Sử dụng mẫu:

$ echo 219.45.143.143 | php isp.php
27.38cm

5

C, 192 177 159 byte

Phiên bản cập nhật, bây giờ hoàn thành chương trình bằng cách sử dụng đối số dòng lệnh. Đồng thời, cải tiến để vẫn ngắn hơn phiên bản trước:

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

Ung dung:

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

Phiên bản golf sử dụng bộ tiền xử lý #defineđể rút ngắn một số mã lặp lại trong phiên bản đầy đủ.


2
1. Phiên bản chơi gôn của bạn bị thiếu dấu chấm phẩy ở cuối. 2. Phiên bản chơi gôn của bạn đang tạo ra kết quả không chính xác, vì bạn tăng strước khi kiểm tra đó *slà khác không. 3. OP cho biết chương trình trong bài viết của mình. Tôi không chắc chắn nếu một chức năng được chấp nhận. 4. Với GCC, bạn không cần bao gồm. 5. sqrtngắn hơn sqrtf. 6. pow(u-p,2)ngắn hơn (u-p)*(u-p). 7. Tôi không chắc chắn, nhưng tôi nghĩ việc lưu trữ cả hai tọa độ trong một chuỗi và cài đặt u=x[c]/3v=x[c]%3nên ngắn hơn.
Dennis

Đã sửa lỗi chính xác. Hóa ra tôi tiếp tục biên dịch một phiên bản trước đó trong khi điều chỉnh tốt. Xin lỗi vì điều đó. 1, 2. Đã sửa. Tôi thực sự ngạc nhiên rằng tôi có thể bỏ chúng đi. Thử nghiệm bị hỏng sẽ giải thích điều đó ... 3. Dựa trên những gì tôi thấy trên wiki / meta, có vẻ như lấy đầu vào làm đối số chức năng là một tùy chọn được phép nếu đầu vào không được chỉ định rõ ràng. Tôi sẽ thay đổi nó nếu cách giải thích của tôi không chính xác. 4. Tôi luôn nghĩ rằng chỉ các hàm trả về intcó thể được sử dụng không được khai báo. Nhưng thực sự, clang cũng chấp nhận nó với một cảnh báo, vì vậy tôi đã thoát khỏi nó.
Reto Koradi

Wiki nói rằng các chức năng được cho phép theo mặc định, vâng, nhưng OP đã viết nhiệm vụ của bạn là viết chương trình ... Bạn không cần dấu ngoặc bạn đã giới thiệu nếu bạn viết vòng lặp như p=u,q=v,G,r+=....
Dennis

Tôi yêu cầu OP làm rõ về các yêu cầu đầu vào. Về mã, tôi đã đưa nó trở lại phiên bản cũ hơn một chút trước khi tôi tối ưu hóa nó thành không chính xác. Tôi sẽ thực hiện một cảnh quay khác để điều chỉnh nó vào ngày mai, nhưng tôi không muốn để một phiên bản bị hỏng đứng quá lâu. Cảm ơn các con trỏ.
Reto Koradi

@Dennis Ok, phiên bản cập nhật sẽ tốt hơn về mọi mặt. Bây giờ là một chương trình hoàn chỉnh, và vẫn còn ngắn hơn nhờ một số tối ưu hóa. Cảm ơn một lần nữa vì đã cho tôi biết về các vấn đề với phiên bản ban đầu.
Reto Koradi

3

JavaScript ( ES6 ), 132

I / O thông qua cửa sổ bật lên. Chạy đoạn mã để kiểm tra (chỉ dành cho 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 byte

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:])))

Phải thừa nhận rằng chơi golf không tốt lắm, nhưng ít nhất nó có quan hệ với PHP.



2

Con trăn 199 171 166

Có mã Python ngắn hơn (108) cho điều này bằng 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

Sử dụng mẫu:

$ python isp.py 219.45.143.143
27.38cm

Chạy trực tuyến: http://codepad.org/h9CWCBNO

Mã nhận xét

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
Bạn có thể lưu một số byte bằng cách xác định ifmệnh đề trên một dòng, nhưif i<1:c=3,1
Zgarb

1
Bạn có thể thêm đánh dấu cú pháp bằng cách đặt nhận xét này ở đầu bài đăng của bạn:<!-- language: lang-python -->
Martin Ender
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.