クラレンス・ザ・スロー・タイピスト


35

前書き

Clarenceは、インターネットサービスプロバイダーで働くデータ入力担当者です。彼の仕事は、ISPのすべての顧客のIPアドレスをデータベースに手動で入力することです。彼は、次のレイアウトのキーパッドを使用してこれを行います。

123
456
789
.0

水平方向または垂直方向に隣接するキーの中心間の距離は、正確に1センチメートルです。例えば、中心間距離3とは、92センチメートルあろう。中心間の距離3とは5√2cmだろう。ピタゴラスの定理は、任意の2つのキー間の距離を計算するのに十分です。

Clarenceは、ISPで働いている人から期待されるように、非常に遅くて非効率的なタイピングシステムを使用しています。彼は1本の指を使用してキーを検索し、指をキーに移動し、それを押して、数字のすべての数字を繰り返します。このスタイルは「イーグル検索システム」として知っているかもしれません。指でキーボードを押して正しいキーを探してから、キープレスを押し下げる前に、イーグルが殺すために急降下するように。

たとえば、Clarenceが数値を入力する方法は次の7851とおりです。

  1. 彼は指を開始し7、キーを押します。
  2. 彼は指を右に1cm動かし8、キーを押します。
  3. 彼は指を1cm上に動かし5、キーを押します。
  4. 彼は指を斜め上方に動かし、√2cm離れ1てキーを押します。

したがって、クラレンスはを入力するように指を移動した総距離7851IS 1 + 1 + √23.41センチメートル程度です。

あなたの仕事は、クラレンスが指を動かして任意のIPアドレスを入力しなければならない距離を計算するプログラムを書くことです。

入力の説明

入力は次の形式の文字列です

().().().()

ここで、それぞれ()は範囲0-の整数999です。これは、Clarenceが入力する必要があるIPアドレスを表します。入力例は次のとおりです。

219.45.143.143

また、0.42.42.42やなどの999.999.999.999入力は、無効なIPアドレスであるにもかかわらず、依然として有効な入力であることを指摘したいと思います。そのため、プログラムにIPアドレス確認コードを含める必要はありません。

出力の説明

指定されたIPアドレスを入力するために、クラレンスが指を動かす必要がある距離を出力します。必要に応じて小数第2位まで答えを丸めcm、出力で単位を使用します。入力例の出力は27.38cm(1 +√8+√5+ 2 + 1 +√5+ 3 + 1 +√5+√13+ 3 + 1 +√5)です。


29
男、ISPには奇妙なキーボードがあります
デニス

1
@RetoKoradiはい、プログラムを期待しています。stdin、コマンドライン引数、またはユーザー入力関数は受け入れ可能です。
アブサン

2
@dacapoaria-「イーグルサーチ」は、より手強いタイピストのための「ハントアンドペック」または「サーチアンド破壊」としても知られています。

12
@ArtofCode ClarenceはISPで働き、時々ISPは彼に無効なデータを送信してデータベースに入力します。クラレンスはとにかくデータを入力します。とにかくそれが正統な理由です。実際の理由は、仕様を書くときにそれを見落としていたからです。
アブサン

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で割って、この数をfloatに変換し123456789.0ます。
    • `:文字列に変換します。 '123456789.0'
    • x k:その文字列の入力文字のインデックスを取得します。[0, 4, 9, 10]
    • .D 3.Ddivmod関数で、最初の入力を2番目の入力で除算およびモジュロ出力します。2番目の入力は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:2つの複素数の差を取ります。[(-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);

入力は標準入力から取得されます。-.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. ゼロ以外の値sをチェックする前に増分するため、ゴルフバージョンの結果が正しくありません*s。3. OPは彼のポストでプログラムを言った。関数が受け入れられるかどうかはわかりません。4. GCCでは、インクルードは不要です。5. sqrtは、よりも短いですsqrtf。6. pow(u-p,2)はより短いです(u-p)*(u-p)。7.私はわからないんだけど、私は単一の文字列の両方の座標を保存し、設定を考えるu=x[c]/3v=x[c]%3短くする必要があります。
デニス

正確性の問題を修正しました。微調整をしながら、以前のバージョンをコンパイルし続けていたことがわかりました。ごめんなさい 1、2。修正済み。私は彼らを置いていかなかったことに実際に驚いた。壊れたテストがそれを説明します... 3. wiki / metaで見たものに基づいて、入力が明示的に指定されていない場合、関数引数として入力を取ることは許可されたオプションであるように聞こえました。解釈が間違っている場合は変更します。4.返さintれる関数のみが宣言なしで使用できるといつも思っていました。しかし、確かに、clangは警告付きでそれを受け入れますので、私はそれを取り除きました。
レトコラディ

wikiには、デフォルトで機能が許可されていると書かれていますが、OPはあなたのタスクをプログラムの作成であると書いています...ループをとして記述した場合、導入した括弧は不要ですp=u,q=v,G,r+=...
デニス

入力要件の明確化をOPに依頼しました。コードでは、それを最適化する前に、少し古いバージョンにロールバックしました。明日、それを調整するために別のショットを撮りますが、壊れたバージョンをあまりにも長く放置したくありませんでした。ポインタをありがとう。
レトコラディ

@Dennis OK、更新されたバージョンはあらゆる点で優れているはずです。現在は完全なプログラムですが、最適化のおかげでさらに短くなりました。初期バージョンの問題について教えてくれてありがとう。
レトコラディ

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

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
ifif i<1:c=3,1
-Zgarb

1
あなたはあなたのポストの上部にこのコメントを置くことによって、構文の強調表示を追加することができます<!-- language: lang-python -->
マーティン・エンダー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.