Clarence the Slow Typist


35

pengantar

Clarence adalah petugas entri data yang bekerja di penyedia layanan internet. Tugasnya adalah secara manual memasukkan alamat IP semua pelanggan ISP ke dalam basis data. Dia melakukan ini menggunakan keypad yang memiliki tata letak berikut:

123
456
789
.0

Jarak antara pusat tombol yang berdekatan secara horizontal atau vertikal tepat satu sentimeter. Misalnya, jarak antara pusat 3dan 9akan menjadi dua sentimeter. Jarak antara pusat 3dan 5akan cm2cm. Teorema Pythagoras cukup untuk menghitung jarak antara dua kunci.

Clarence, seperti yang mungkin Anda harapkan dari orang yang bekerja di ISP, menggunakan sistem pengetikan yang sangat lambat dan tidak efisien. Dia menggunakan satu jari dan mencari kunci, lalu menggerakkan jarinya ke kunci, lalu menekannya, dan mengulangi untuk semua digit dalam angka. Anda mungkin tahu gaya ini sebagai "sistem pencarian elang" karena jari mencari di atas keyboard untuk tombol yang benar sebelum terjun untuk menekan tombol, seperti elang yang mencoba membunuh.

Misalnya, inilah cara Clarence mengetikkan nomor 7851:

  1. Dia mulai jarinya 7dan menekan tombol.
  2. Dia menggerakkan jarinya ke kanan 1cm ke 8dan menekan tombol.
  3. Dia menggerakkan jarinya ke atas 1 cm ke 5dan menekan tombol.
  4. Dia menggerakkan jarinya secara diagonal ke atas dan meninggalkan cm2cm ke 1dan menekan tombol.

Oleh karena itu total jarak yang Clarence pindah jarinya mengetikkan 7851yaitu 1 + 1 + √2yaitu sekitar 3.41cm.

Tugas Anda adalah menulis program yang menghitung jarak yang Clarence harus gerakkan jarinya untuk mengetik alamat IP yang berubah-ubah.

Deskripsi Input

Input adalah string yang akan di form

().().().()

di mana masing ()- masing bilangan bulat dalam kisaran 0- 999. Ini mewakili alamat IP yang harus diketik oleh Clarence. Contoh input mungkin:

219.45.143.143

Saya juga ingin menunjukkan bahwa input seperti 0.42.42.42atau 999.999.999.999masih input yang valid, terlepas dari kenyataan bahwa mereka adalah alamat IP yang tidak valid. Jadi Anda tidak perlu memasukkan kode verifikasi alamat IP dalam program Anda.

Deskripsi Output

Keluarkan jarak yang harus digerakkan Clarence untuk mengetik alamat IP yang ditentukan. Bulatkan jawaban ke dua tempat desimal di mana diperlukan, dan gunakan cmunit dalam hasil Anda. Output untuk input contoh adalah 27.38cm(1 + √8 + √5 + 2 + 1 + √5 + 3 + 1 + √5 + √13 + 3 + 1 + √5).


29
Sobat, ISP punya keyboard aneh ...
Dennis

1
@RetoKoradi Saya mengharapkan sebuah program, ya. stdin, argumen baris perintah, atau fungsi input pengguna dapat diterima.
absinthhe

2
@dacapoaria - 'pencarian elang' juga dikenal sebagai 'berburu dan mematuk' atau 'mencari dan menghancurkan' untuk pengetik yang lebih berat.

12
@ArtofCode Clarence bekerja di ISP, dan terkadang ISP mengiriminya data yang tidak valid untuk mengetik ke dalam basis data. Clarence mengetik data dengan cara apa pun. Itulah alasan kanonisnya. Alasan sebenarnya adalah karena saya mengabaikan hal itu ketika menulis spec.
absinthhe

3
Mempertimbangkan hanya kisaran IP (0-255) yang valid, yang harusnya merupakan pengaturan keyboard yang optimal untuk mengetik semua alamat di jalur terpendek?
Israel Morales

Jawaban:


16

CJam, 46 44 43 38 37 34 byte

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

Terima kasih kepada @ user23013 untuk menyarankan mh, yang memungkinkan untuk menghemat 5 byte.

Cobalah online di juru bahasa CJam .

Bagaimana itu bekerja

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: Terima kasih. Aku bahkan tidak tahu mh.
Dennis

16

Pyth, 38 35 34 byte

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

Demonstrasi.

Pengindeksan ke string ide mengambang berkat @ Dennis.

Penjelasan, pada input palsu 15.0:

  • Pertama, kami mengambil input. Secara implisit disimpan di z. '15 ,0 '
  • Kami memetakan daftar ini sebagai berikut: m.jF.Dx`ciUTT1k3z.

    • UT: Kami menghasilkan daftar [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
    • iUTT: Selanjutnya, kami memperlakukan daftar ini sebagai angka 10 basis yang memberi kami 123456789.
    • ciUTT1: Selanjutnya, kami mengonversi angka ini menjadi float dengan floating point yang membaginya dengan 1, memberi 123456789.0.
    • `: Konversikan ke string. '123456789.0'
    • x k: Ambil indeks karakter input dalam string itu. [0, 4, 9, 10].
    • .D 3: .Dadalah fungsi divmod, mengeluarkan input pertama dibagi dan modulo'd oleh input kedua. Input kedua adalah 3, di sini. Ini memberikan lokasi fisik karakter pada numpad. [(0, 0), (1, 1), (3, 0), (3, 1)].
    • .jF: .jadalah pembangun bilangan kompleks. Fmenerapkannya pada tuple. [0j, (1+1j), (3+0j), (3+1j)].
  • .: 2: Sekarang, kami mengambil 2 entri substring dari daftar ini sehingga kami dapat menemukan jarak berpasangan. [[0j, (1+1j)], [(1+1j), (3+0j)], [(3+0j), (3+1j)]].
  • -M: Mengambil perbedaan dari dua bilangan kompleks. [(-1-1j), (-2+1j), -1j].
  • .aM: Mengambil nilai absolut dari hasilnya. Ini adalah jarak antara lokasi keypad.[1.4142135623730951, 2.23606797749979, 1.0]
  • s: Jumlahkan jarak. 4.650281539872885.
  • .R 2: Membulatkan ke 2 tempat desimal. 4.65.
  • + "cm: Tambahkan 'cm'ke ujung dan cetak. 4.65cm.

7

PHP - 108 Bytes

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

Input diambil dari stdin. Yang -.987654321dikirim ke strposfungsi mengevaluasi '-0.987654321'dalam konteks string.


Penggunaan sampel:

$ echo 219.45.143.143 | php isp.php
27.38cm

5

C, 192 177 159 byte

Versi yang diperbarui, sekarang menyelesaikan program menggunakan argumen baris perintah. Pada saat yang sama, peningkatan menjadi lebih pendek dari versi sebelumnya:

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

Tidak Disatukan:

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

Versi golf menggunakan preprocessor #defineuntuk mempersingkat beberapa kode yang diulang dalam versi lengkap.


2
1. Versi golf Anda tidak memiliki titik koma di bagian akhir. 2. Versi golf Anda menghasilkan hasil yang salah, karena Anda menambah ssebelum memeriksa yang *stidak nol. 3. OP mengatakan program di posnya. Saya tidak yakin apakah suatu fungsi diterima. 4. Dengan GCC, Anda tidak perlu menyertakannya. 5. sqrtlebih pendek dari sqrtf. 6. pow(u-p,2)lebih pendek dari (u-p)*(u-p). 7. Saya tidak yakin, tapi saya pikir menyimpan kedua koordinat dalam satu string dan pengaturan u=x[c]/3dan v=x[c]%3harus lebih pendek.
Dennis

Memperbaiki masalah kebenaran. Ternyata saya terus mengkompilasi versi sebelumnya sambil melakukan fine tuning. Maaf soal itu. 1, 2. Diperbaiki. Saya benar-benar terkejut bahwa saya bisa meninggalkan mereka. Pengujian yang rusak akan menjelaskannya ... 3. Berdasarkan apa yang saya lihat di wiki / meta, itu terdengar seperti mengambil input karena argumen fungsi adalah opsi yang diperbolehkan jika input tidak ditentukan secara eksplisit. Saya akan mengubahnya jika interpretasi saya salah. 4. Saya selalu berpikir bahwa hanya fungsi yang kembali yang intdapat digunakan tidak dideklarasikan. Tapi memang, dentang juga menerimanya dengan peringatan, jadi aku menyingkirkannya.
Reto Koradi

Wiki menyatakan bahwa fungsi diizinkan secara default, ya, tetapi OP menulis tugas Anda untuk menulis sebuah program ... Anda tidak memerlukan tanda kurung yang Anda perkenalkan jika Anda menulis loop sebagai p=u,q=v,G,r+=....
Dennis

Saya meminta OP untuk klarifikasi tentang persyaratan input. Pada kode, saya mengembalikannya ke versi yang sedikit lebih tua sebelum saya mengoptimalkannya menjadi tidak benar. Saya akan mengambil gambar lain untuk menyetelnya besok, tapi saya tidak ingin membiarkan versi yang rusak berdiri terlalu lama. Terima kasih untuk petunjuknya.
Reto Koradi

@ Dennis Ok, versi yang diperbarui harus lebih baik dalam segala hal. Sekarang program yang lengkap, dan masih lebih pendek berkat beberapa optimasi. Sekali lagi terima kasih telah memberi tahu saya tentang masalah dengan versi awal.
Reto Koradi

3

JavaScript ( ES6 ), 132

I / O melalui sembulan. Jalankan cuplikan untuk menguji (khusus 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:])))

Memang golfnya tidak terlalu bagus, tapi setidaknya ada hubungannya dengan PHP.



2

Python 199 171 166

Ada kode Python yang lebih pendek (108) untuk ini oleh 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

Penggunaan sampel:

$ python isp.py 219.45.143.143
27.38cm

Jalankan online: http://codepad.org/h9CWCBNO

Kode yang dikomentari

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
Anda dapat menyimpan beberapa byte dengan mendefinisikan ifklausa pada satu baris, sepertiif i<1:c=3,1
Zgarb

1
Anda dapat menambahkan penyorotan sintaks dengan meletakkan komentar ini di bagian atas posting Anda:<!-- language: lang-python -->
Martin Ender
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.