Yavaş Daktilo Clarence


35

Giriş

Clarence, bir internet servis sağlayıcısında çalışan bir veri girişi görevlisidir. Görevi, tüm ISS müşterilerinin IP adreslerini veri tabanına elle girmek. Bunu, aşağıdaki düzende olan bir tuş takımını kullanarak yapar:

123
456
789
.0

Yatay veya dikey olarak bitişik tuşların merkezi arasındaki mesafe tam olarak bir santimetredir. Örneğin, merkezleri arasındaki mesafe 3ve 9iki santimetre olacaktır. Merkezleri arasındaki mesafe 3ve 5√2cm olacaktır. Pisagor teoremi herhangi iki anahtar arasındaki mesafeyi hesaplamak için yeterlidir.

Bir ISS'de çalışan birinden bekleyebileceğiniz gibi Clarence, çok yavaş ve verimsiz bir yazma sistemi kullanıyor. Tek bir parmak kullanır ve anahtarı arar ve sonra parmağını tuşa taşır, sonra da basar ve sayıdaki tüm rakamlar için tekrar eder. Bu stili "kartal arama sistemi" olarak biliyor olabilirsiniz, çünkü parmak bir tuşa basmadan önce, klavyenin üstünde doğru tuş için arama yapar.

Örneğin, Clarence bu sayıyı nasıl yazacağını şöyle gösterir 7851:

  1. Parmağına başlıyor 7ve anahtarı itiyor.
  2. Parmağını sağa 1 cm hareket ettirir 8ve tuşa basar.
  3. Parmağını 1 cm yukarı doğru hareket ettirir 5ve tuşa basar.
  4. Parmağını çapraz olarak yukarı doğru hareket ettirir ve cm2 cm bırakarak tuşa basar 1.

Bu nedenle Clarence yazmak için parmağını hareket ettiği toplam mesafe 7851DİR 1 + 1 + √23.41cm hakkındadır.

Görevin, keyfi IP adreslerini yazmak için Clarence'ın parmağını oynatması gereken mesafeyi hesaplayan bir program yazmak.

Giriş açıklaması

Giriş, formda olacak bir dizedir

().().().()

her ()biri aralıktaki bir tam sayıdır 0- 999. Bu, Clarence’ın yazması gereken IP adresini gösterir. Örnek bir giriş olabilir:

219.45.143.143

Ayrıca , geçersiz IP adresleri olmasına rağmen, bu gibi girişlerin 0.42.42.42ya 999.999.999.999da hala geçerli girişler olduğunu belirtmek isterim. Bu nedenle, programınıza herhangi bir IP adresi doğrulama kodu dahil etmeniz gerekmez.

Çıkış açıklaması

Belirtilen IP adresini girmek için Clarence'in parmağını hareket ettirmesi gereken mesafeyi verin. Gerektiğinde iki ondalık basamağa yuvarlak cevaplar cmverin ve çıktınızdaki birimi kullanın . Örnek girişin çıkışı 27.38cm(1 + +8 + √5 + 2 + 1 + √5 + 3 + 1 + √5 + √13 + 3 + 1 + √5) şeklindedir.


29
Dostum, ISS’lerin garip klavyeleri var ...
Dennis,

1
@RetoKoradi Bir program bekliyorum, evet. stdin, komut satırı argümanları veya kullanıcı giriş fonksiyonları kabul edilebilir.
pelin otu

2
@dacapoaria - 'kartal araştırması' aynı zamanda daha fazla elle çalışan daktilolar için 'avlanma ve gagalama' ya da 'arama ve yok etme' olarak da bilinir.

12
@ArtofCode Clarence bir ISS'de çalışır ve bazen ISS ona veri tabanına yazması için geçersiz veri gönderir. Clarence yine de verileri yazıyor. Yine de kanonik sebep bu. Asıl sebep, spec yazarken bunu göz ardı etmem.
pelin otu

3
Yalnızca geçerli aralığı (0-255) IP Adresleri göz önüne alındığında, bu adresleri en kısa yola yazmak için klavyenin en iyi düzenlemesi hangisidir?
İsrail Morales

Yanıtlar:


16

CJam, 46 44 43 38 37 34 bayt

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

mh5 kullanıcı baytı kaydetmeyi mümkün kılan önerileri için @ user23013 sayesinde .

CJam tercümanında çevrimiçi olarak deneyin .

Nasıl çalışır

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: Teşekkürler. Varlığından mhbile haberim yoktu .
Dennis,

16

Pyth, 38 35 34 bayt

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

Gösteri.

@Dennis sayesinde bir kayan fikir dizisine indeksleme.

Sahte girişe ilişkin açıklama 15.0:

  • İlk önce girdiyi alıyoruz. Örtülü olarak depolanır z. '15 0,0'
  • Şöyle bu listeyi map: m.jF.Dx`ciUTT1k3z.

    • UT: Listeyi biz oluşturuyoruz [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
    • iUTT: Sonra, bu listeyi bize verilen 10 sayı olarak değerlendiriyoruz 123456789.
    • ciUTT1: Sonra, bu sayıyı bir kayan noktaya çevirerek kayan noktaya 1 ile bölerek veriyoruz 123456789.0.
    • `: Bir dizgiye dönüştür. '123456789.0'
    • x k: Girilen karakterin dizinini o dizgeye alın. [0, 4, 9, 10].
    • .D 3: .Ddivmod işlevi, ilk girişini bölüştüren ve ikinci girişte modüle edilen çıktı. İkinci giriş burada 3. Bu, sayısal tuş takımındaki karakterin fiziksel konumunu verir. [(0, 0), (1, 1), (3, 0), (3, 1)].
    • .jF: .jkarmaşık sayı kurucusudur. Fonu demetine uygular. [0j, (1+1j), (3+0j), (3+1j)].
  • .: 2: Şimdi, bu listenin 2 giriş alt dizinini alıyoruz, böylece ikili mesafeleri bulabiliriz. [[0j, (1+1j)], [(1+1j), (3+0j)], [(3+0j), (3+1j)]].
  • -M: İki karmaşık sayının farkını alır. [(-1-1j), (-2+1j), -1j].
  • .aM: Sonucun mutlak değerini alır. Bu tuş takımı konumları arasındaki mesafedir.[1.4142135623730951, 2.23606797749979, 1.0]
  • s: Mesafeleri toplayın. 4.650281539872885.
  • .R 2: 2 ondalık basamağa yuvarlak. 4.65.
  • + "cm: 'cm'Sonuna ekleyin ve yazdırın. 4.65cm.

7

PHP - 108 Bayt

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

Giriş stdin'den alınmıştır. Işleve -.987654321gönderilen bir dize bağlamında strposdeğerlendirir '-0.987654321'.


Örnek kullanım:

$ echo 219.45.143.143 | php isp.php
27.38cm

5

C, 192 177 159 bayt

Güncelleme sürümü, şimdi komut satırı argümanı kullanarak programı tamamlayın. Aynı zamanda, önceki sürümden daha kısa olması için geliştirildi:

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

Golf versiyonunda #define, tam sürümde tekrarlanan kodların bir kısmını kısaltmak için bir ön işlemci kullanılmaktadır .


2
1. Golf versiyonunuzda bir noktalı virgül yok. 2. Golf versiyonunuz hatalı sonuçlar veriyor, çünkü skontrol etmeden önce sıfırlı değilsiniz *s. 3. OP, programında yaptığı programı söyledi. Bir işlevin kabul edilip edilmediğinden emin değilim. 4. GCC ile içerme gerekmez. 5. sqrtdaha kısa sqrtf. 6. pow(u-p,2)daha kısa (u-p)*(u-p). 7. Emin değilim, ancak her iki koordinatı da tek bir dizgide ve ortamda saklamayı düşünüyorum u=x[c]/3ve v=x[c]%3daha kısa olmalıyım.
Dennis,

Doğruluk sorunu düzeltildi. İnce ayar yaparken önceki bir sürümü derlemeye devam ettiğimi ortaya koyuyor. Bunun için üzgünüm. 1, 2. Sabit. Onları uzaklaştırabilmeme şaşırdım. Bozuk testler bunu açıklardı ... 3. wiki / meta'da gördüklerime dayanarak, girdi açıkça belirtilmezse girdi işlev argümanları olarak kabul edilebilir bir seçenek olarak kabul edildi. Yorumum yanlışsa değiştireceğim. 4. Her zaman sadece geri dönen fonksiyonların intbildirilmemiş olarak kullanılabileceğini düşündüm . Ama gerçekten, clang da bir uyarı ile kabul eder, ondan kurtuldum.
Reto Koradi

Wiki, fonksiyonlara varsayılan olarak izin verildiğini belirtir, evet, ancak OP sizin görevinizi bir program yazmaktır p=u,q=v,G,r+=....
Dennis,

OP'den giriş gereklilikleriyle ilgili açıklama yapmasını istedim. Kodda, hatalı duruma getirmeden önce biraz eski bir sürüme döndürdüm. Yarın ayarlamada bir kez daha çekim yapacağım, ancak çok uzun süre kırık bir versiyonu bırakmak istemedim. İşaretçiler için teşekkürler.
Reto Koradi

@Dennis Tamam, güncellenmiş sürümü her şekilde daha iyi olmalıdır. Şimdi tam bir program ve bazı optimizasyonlar sayesinde hala daha kısa. İlk sürümdeki sorunlar hakkında bana bilgi verdiğiniz için tekrar teşekkür ederiz.
Reto Koradi

3

JavaScript ( ES6 ), 132

Pop-up üzerinden G / Ç. Test edilecek pasajı çalıştırın (yalnızca 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 bayt

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

Kuşkusuz çok iyi golf oynadım, ama en azından PHP ile bağları var.



2

Python 199 171 166

SP3000'de bunun için daha kısa bir Python kodu (108) var:

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

Örnek kullanım:

$ python isp.py 219.45.143.143
27.38cm

Çevrimiçi çalıştırın: http://codepad.org/h9CWCBNO

Yorumlanan kod

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
Bazı baytları iftek satırda cümle tanımlayarak kaydedebilirsiniz , örneğinif i<1:c=3,1
Zgarb

1
Bu yorumu, <!-- language: lang-python -->
Martin Ender
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.