数値省略表現を使用した式の評価


10

あなたはユーザーフレンドリーな計算機を作りたいと思っている会社で働いているので、ユーザーに「数値の省略形」、つまりkforのような数値を表す文字を使用する機能を追加する必要があります1000。あなたの会社は、計算機でストレージのコストを節約したいので、ストレージのコストを削減するために、コードをできるだけ最小限に抑える必要があります。


あなたのタスク

STDINから入力として式を読み取るか、式をパラメーターとして受け取り、その評価を返すか、STDOUTに出力する関数を作成します。

いくつかの明確化

いくつか定義をさせてください。最初に、式と呼ぶ入力があります。これは次のようになります。

x + y / z

:この式の中で、我々は3つの数字を持っているx、yとz、オペレータ(区切っ+と/)。これらの数値は、必ずしも正の整数(または整数)である必要はありません。複雑なのは、数値に含まれる省略形を評価する必要がある場合です。たとえば、

2k15

:評価の目的のために、我々は3つの数字にこれを分割2、1000(であるk)、および15。次に、ルールに従って、それらを組み合わせて

2*1000 + 15 = 2015

うまくいけば、次のルールを理解するのが少し簡単になります。

ルール

注意特に明記されていない限り、「数字」という単語またはその同義語を解釈して、省略形を含めることができます。

  1. 以下は、関数が処理できなければならない数値の省略形ですk, m, b, t, and e。それぞれk, m, b, and t値1000, 1000000, 1000000000, and 1000000000000(1,000、100万、10億、1兆)に対応します。e速記は常に、別の番号が続くn、と表しています10^n。数値の省略形が存在するn前に存在することを許可する必要がありますe。たとえば、はにkek評価され1000*10^1000ます。

  2. 簡単にするために、数字に省略形がある場合、その数字はe1回だけ使用されます。

  3. 省略形の前に任意の数(省略形を含む)が掛けられます。たとえば120kk、として評価され120 * 1000 * 1000ます。その前に数値がない場合は、数値が1であると想定する必要があります(数学では、変数をx暗黙的にとして扱う方法と同様1x)。たとえば、にe10評価され10^10ます。別の例:に2m2k評価されます2*1000000*2*1000(何も追加されません)。

  4. 省略形を含む数の最後の省略形に続く任意の数(省略形は適用されません)が追加されます。たとえば2k12、として評価され2*1000 + 12ます。これの例外は、省略形eが使用される場合です。その場合、後続の数(含まれる省略形)は次のeように扱われn、評価されます10^n(最初のルールを参照)。

  5. 関数は+, -, *, and /、それぞれ加算、減算、乗算、および除算である演算子を処理できる必要があります。必要に応じて、さらに処理する場合があります。

  6. 操作は操作の順序に従って評価されます。

  7. 省略表記の数値は整数だけではありません。3.5b1.2有効であり、次のように評価されます3.5*1000000000 + 1.2 = 3500000001.2

  8. この種のものが存在する場合、組み込みは許可されません。私が追加する例外は、言語が自動的に大きな数を科学表記に変換する場合です。その場合、それは出力で許容されます。

  9. バイト単位の最短コードが優先され、標準の抜け穴が適用されます。

入力

入力は、各数値と演算子がスペースで区切られた式になります。数字には省略形が含まれる場合と含まれない場合があります。以下にサンプルを示します。

10 + 1b - 2k

出力

関数は、式の評価を数値として出力する必要があります。出力が大きすぎて表示できない場合は、科学表記法を使用できます。数値が整数でない場合は、少なくとも小数点以下3桁が必要です。数値が整数の場合、これらの小数点以下の桁数を保持することは許容されます。

テストケース

入力

t

出力

1000000000000

入力

1 + 4b / 10k11

出力

399561.483

入力

e2 + k2ke-1 - b12

出力

-999799912

または

-999799912.000

入力

142ek12

出力

142e1012

または

142.000e1012

入力:

1.2m5.25

出力:

1200005.25

最終メモ

これは投稿された私の最初のチャレンジです(サンドボックスのユーザーからの助けを借りて)何か不明な点がある場合は、私に知らせてください。明確にするために最善を尽くします。


1
良い最初の課題
— デジタルトラウマ2015

@DigitalTraumaありがとうございます!お返事を楽しみにしています。
— cole 2015

2番目の例が理解できません。中期はと解釈されたの1000 + 2000 * 10 ^ -1ではないかと思ったが、最終的にはと答えた-999998712。(また、私の解釈は、ルール4の「最後の省略表現」には当てはまらないようですが、他にシーケンスを理解する方法がわかりませんk2k。)評価の手順を説明できますか?
— DLosc

@trichoplaxはい、それは数字でなければなりません。良いキャッチ。
— cole 2015

1
サンドボックスの投稿のコメントを見て、次のような例2m2kをルール3の説明に追加する必要があると思います。また、123そのようなリテラル数には、別の用語(おそらく「整数」)を使用するのが最善かもしれません。速記ではありません。「数」という言葉には、現在のところ、3つの異なる定義があります。
— DLosc

回答:


4

Python 2、553バイト

import sys
a=lambda i:lambda j:j*10**i
d={'k':a(3),'m':a(6),'b':a(9),'t':a(12)}
e='e'
o={'+':lambda i,j:i+j,'-':lambda i,j:i-j,'*':lambda i,j:i*j,'/':lambda i,j:i/j,e:lambda i,j:i*10**j}
r=[e,'*','/','+','-']
x=0
y=k=b=''
z=[]
q=lambda i,j:float(i or j)
for l in ''.join(sys.argv[1:]):
 if l in d:x,y=d[l](q(x,1)*q(y,1)),b
 elif l==e:z.extend([q(x+q(y,0),1),l]);x,y=0,b
 elif k==e:y+=l
 elif l in o:z.extend([x+q(y,0),l]);x,y=0,b
 else:y+=l
 k=l
z.append(x+q(y,0))
for m in r:
 while m in z:n=z.index(m);z[n-1:n+2]=[o[m](z[n-1],z[n+1])]
print repr(z[0])

この質問は少し愛されておらず、面白そうだったので、試してみました。私はコードゴルフをしたことがないので、改善できることはおそらくたくさんありますが、言語の知識に基づいて最善を尽くしました。同等のソリューションは、1つの余分バイトのコストではPython 3で可能です:print repr(z[0])- > print(repr(z[0]))。

使い方は次のとおりです

python2 ShorthandMath.py <equation>

すなわち

python2 ShorthandMath.py e2 + k2ke-1 - b12

出力

-999799912.0

これを改善する方法についてのご意見をいただければ幸いです。十分な関心があれば、私はプログラムをアンゴルフしてコメントすることができますが、そのほとんどはすでにかなり読みやすいです(コードゴルフの懸念事項)。

この例では142ek12、その値が途方もなく大きく、プログラムがオーバーフローするため、プログラムが壊れることに注意してください。

これを補うために、以下は少し長くなりますが、組み込みの任意精度ライブラリを使用するため、理論的にはスローされたものはすべて処理できます。構文は同じです。

Python 2、589 588バイト(任意の精度)

import sys
from decimal import*
a=lambda i:lambda j:j*10**i
d={'k':a(3),'m':a(6),'b':a(9),'t':a(12)}
e='e'
o={'+':lambda i,j:i+j,'-':lambda i,j:i-j,'*':lambda i,j:i*j,'/':lambda i,j:i/j,e:lambda i,j:i*10**j}
r=[e,'*','/','+','-']
x=c=Decimal(0)
y=k=b=''
z=[]
q=lambda i,j:Decimal(float(i or j))
for l in ''.join(sys.argv[1:]):
 if l in d:x,y=d[l](q(x,1)*q(y,1)),b
 elif l==e:z.extend([q(x+q(y,0),1),l]);x,y=c,b
 elif k==e:y+=l
 elif l in o:z.extend([x+q(y,0),l]);x,y=c,b
 else:y+=l
 k=l
z.append(x+q(y,0))
for m in r:
 while m in z:n=z.index(m);z[n-1:n+2]=[o[m](z[n-1],z[n+1])]
print z[0]

最初のバージョンは問題ないはずですが、何か問題がある場合は折り返しご連絡いたします(今は慎重に見たり考えたりすることはできません)。
— cole 2015年

@Cole Awesome、ありがとう。私は与えられたすべての例でそれを試しました、そしてそれはそれらのすべてを少なくとも正しくします。
— BobChao87 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.