คลาเรนซ์พิมพ์ช้า


35

บทนำ

Clarence เป็นพนักงานป้อนข้อมูลที่ทำงานกับผู้ให้บริการอินเทอร์เน็ต หน้าที่ของเขาคือป้อนที่อยู่ IP ของลูกค้า ISP ทั้งหมดลงในฐานข้อมูลด้วยตนเอง เขาทำสิ่งนี้โดยใช้แป้นพิมพ์ที่มีเค้าโครงดังต่อไปนี้:

123
456
789
.0

ระยะห่างระหว่างจุดศูนย์กลางของปุ่มในแนวนอนหรือแนวตั้งคือหนึ่งเซนติเมตร ตัวอย่างเช่นระยะห่างระหว่างศูนย์กลางของ3และ9จะเป็นสองเซนติเมตร ระยะห่างระหว่างศูนย์กลางของ3และ5จะเป็น√2cm ทฤษฎีบทพีทาโกรัสนั้นเพียงพอที่จะคำนวณระยะห่างระหว่างปุ่มสองปุ่มใด ๆ

Clarence ดังที่คุณคาดหวังจากผู้ที่ทำงานใน ISP ใช้ระบบการพิมพ์ที่ช้าและไม่มีประสิทธิภาพ เขาใช้นิ้วเดียวและค้นหากุญแจจากนั้นย้ายนิ้วของเขาไปที่คีย์จากนั้นกดมันและทำซ้ำตัวเลขทั้งหมดในตัวเลข คุณอาจรู้จักรูปแบบนี้ในฐานะ "ระบบค้นหานกอินทรี" เนื่องจากนิ้วค้นหาบนแป้นพิมพ์เพื่อหากุญแจที่ถูกต้องก่อนกดลงเพื่อกดปุ่มกดเช่นเดียวกับที่เหยี่ยวลงเพื่อฆ่า

ตัวอย่างเช่นนี่คือวิธีที่คลาเรนซ์จะพิมพ์หมายเลข7851:

  1. เขาเริ่มนิ้วของเขาที่7และกดปุ่ม
  2. เขาเลื่อนนิ้วของเขาไปทางขวา 1 ซม. 8และกดปุ่ม
  3. เขาเลื่อนนิ้วของเขาขึ้นไป 1 ซม. 5และกดปุ่ม
  4. เขาเลื่อนนิ้วของเขาขึ้นตามแนวทแยงมุมขึ้นไปและทิ้งไว้√2ซม. 1แล้วกดปุ่ม

ดังนั้นระยะทางทั้งหมดที่คลาเรนซ์ขยับนิ้วของเขาเพื่อพิมพ์7851นั้นอยู่1 + 1 + √2ที่ประมาณ 3.41 ซม.

งานของคุณคือการเขียนโปรแกรมที่คำนวณระยะทางคลาเรนซ์จะต้องเลื่อนนิ้วของเขาเพื่อพิมพ์ในที่อยู่ 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, อาร์กิวเมนต์บรรทัดคำสั่งหรือฟังก์ชั่นการป้อนข้อมูลของผู้ใช้เป็นที่ยอมรับ
absinthe

2
@dacapoaria - 'eagle search' หรือที่รู้จักกันในนาม 'Hunt and peck' หรือ 'search and destroy' สำหรับนักพิมพ์ดีดที่ถนัดมือมากขึ้น

12
@ArtofCode Clarence ทำงานที่ ISP และบางครั้ง ISP ส่งข้อมูลที่ไม่ถูกต้องให้เขาพิมพ์ลงในฐานข้อมูล คลาเรนซ์พิมพ์ข้อมูลลงไป นั่นคือเหตุผลที่ยอมรับอยู่แล้ว เหตุผลที่แท้จริงคือเพราะฉันมองข้ามว่าเมื่อเขียนสเป็ค
absinthe

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มีอยู่จริง
Dennis

16

Pyth, 38 35 34 ไบต์

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

สาธิต.

การจัดทำดัชนีลงในสตริงของแนวคิดแบบลอยตัวต้องขอบคุณ @Dennis

คำอธิบายเกี่ยวกับอินพุตปลอม15.0:

  • อันดับแรกเรารับอินพุต zจะถูกเก็บไว้โดยปริยายใน '15 .0'
  • เรา map 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 ซึ่งให้ผลลัพธ์อินพุตแรกที่ถูกหารและ modulo'd โดยอินพุตที่สอง อินพุตที่สองคือ 3 ที่นี่ สิ่งนี้ทำให้ตำแหน่งทางกายภาพของอักขระบน numpad [(0, 0), (1, 1), (3, 0), (3, 1)].
    • .jF: .jเป็นตัวสร้างจำนวนเชิงซ้อน Fนำไปใช้กับ tuple [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);}

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

เวอร์ชัน golfed ใช้ตัวประมวลผลล่วงหน้า#defineเพื่อย่อรหัสซ้ำบางส่วนในเวอร์ชันเต็ม


2
1. เวอร์ชันที่ตีกอล์ฟของคุณไม่มีเครื่องหมายอัฒภาคในตอนท้าย 2. เวอร์ชันที่ตีกอล์ฟของคุณกำลังสร้างผลลัพธ์ที่ไม่ถูกต้องเนื่องจากคุณเพิ่มขึ้นsก่อนที่จะตรวจสอบว่า*sไม่ใช่ศูนย์ 3. โปรแกรม OP กล่าวในโพสต์ของเขา ฉันไม่แน่ใจว่ายอมรับฟังก์ชั่นหรือไม่ 4. ด้วย GCC คุณไม่จำเป็นต้องมีการรวม 5. จะสั้นกว่าsqrt sqrtf6. จะสั้นกว่าpow(u-p,2) (u-p)*(u-p)7. ฉันไม่แน่ใจ แต่ฉันคิดว่าการเก็บพิกัดทั้งสองไว้ในสตริงและการตั้งค่าเดียวu=x[c]/3และv=x[c]%3ควรสั้นลง
Dennis

แก้ไขปัญหาความถูกต้อง ปรากฎว่าฉันยังคงรวบรวมรุ่นก่อนหน้าในขณะที่ทำการปรับจูน ขอโทษสำหรับเรื่องนั้น. 1, 2. แก้ไข จริง ๆ แล้วฉันประหลาดใจที่ฉันสามารถทิ้งพวกเขาไป การทดสอบที่เสียหายจะอธิบายได้ ... 3. จากสิ่งที่ฉันเห็นใน wiki / meta มันฟังดูเหมือนว่าจะรับอินพุตเนื่องจากอาร์กิวเมนต์ของฟังก์ชันเป็นตัวเลือกที่อนุญาตหากไม่มีการระบุอินพุตอย่างชัดเจน ฉันจะเปลี่ยนมันถ้าการตีความของฉันไม่ถูกต้อง 4. ฉันคิดเสมอว่ามีเพียงฟังก์ชั่นที่ส่งคืนเท่านั้นที่intไม่สามารถประกาศได้ แต่แน่นอนเสียงดังกราวก็ยอมรับมันด้วยการเตือนดังนั้นฉันจึงกำจัดมัน
Reto Koradi

รัฐวิกิพีเดียที่ฟังก์ชั่นที่ได้รับอนุญาตโดยเริ่มต้นใช่ แต่ OP เขียนงานของคุณคือการเขียนโปรแกรม ... p=u,q=v,G,r+=...คุณไม่จำเป็นต้องวงเล็บที่คุณแนะนำถ้าคุณเขียนห่วงเป็น
เดนนิส

ฉันขอ OP เพื่อชี้แจงเกี่ยวกับข้อกำหนดอินพุต ในรหัสฉันย้อนกลับไปเป็นรุ่นที่เก่ากว่าเล็กน้อยก่อนที่ฉันจะปรับปรุงให้เป็นความไม่ถูกต้อง ฉันจะถ่ายอีกนัดเพื่อปรับในวันพรุ่งนี้ แต่ฉันไม่ต้องการปล่อยให้รุ่นที่แตกหักยืนนานเกินไป ขอบคุณสำหรับคำแนะนำ
Reto Koradi

@Dennis Ok เวอร์ชั่นที่อัปเดตน่าจะดีกว่าในทุก ๆ ด้าน ตอนนี้เป็นโปรแกรมที่สมบูรณ์และยังสั้นลงด้วยการเพิ่มประสิทธิภาพบางอย่าง ขอขอบคุณอีกครั้งที่แจ้งให้ฉันทราบเกี่ยวกับปัญหาของรุ่นเริ่มต้น
Reto Koradi

3

JavaScript ( 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

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

Python 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 -->
Martin Ender
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.