2017-02-13 2 views
1

誰かが私にこのアルゴリズム上の質問をしてくれました。いつものように、私はこれに答えませんでした。 :)あなたは1つの番号を持っているとしましょう。数字の追加から予測する数字

504 

次回は、数字の最後の桁を削除します。

50 

次回は、その番号の最後の桁を削除します。

5 

ここで、3つの数字(a + b + c)のすべてを追加します。それは次のようになります:

504 + 50 + 5 = 559 

これまでに問題文をよく理解しているかもしれません。

質問:3つの数字a + b + c(この場合は559)を追加すると、元の番号(この場合は504)に戻ることはできますか?すべてのソリューションが評価されます。

+0

a + b + cが小さい場合(<= 10^6)、bruteforceを使用して1からa + b + cまでのすべての可能性を試すことができます。 – algojava

答えて

2

開始番号がxyzのようになっているとします。つまり、最後の(10進)桁はz、最後から2番目の桁はy、残りはxです。あなたの例では、504で始まった場合、x = 5、y = 0、z = 4です。元の番号の値は100x + 10y + zです。

最後の数字は、(100x + 10y + z)、(10x + y)、およびxの合計です。これは111x + 11y + zです。

私たちの制約は、0≦y≦9かつ0≦z≦9であったことに注意してください。最大値でも、11y + z≤11(9)+ 9 < 111です。したがって、変換を逆転できます。111の最大倍数を引き出し、残りの11の最大倍数を引き出します。残っているもの。

def transform(n): 
    return n + (n/10) + (n/100) 

def invert(m): 
    [x, y, z] = [m/111, (m%111)/11, (m%111)%11] 
    return 100*x + 10*y + z 

assert transform(504) == 559 
assert invert(559) == 504 

(Pythonシェルに上記試しxは1桁の数字でない場合でも、これが動作することに注意してください:。transform(12345)は13702を与え、そして予想通りinvert(13702)は、12345を与える)


を編集する:Paul Hankin's answer(考えてみてください)の考え方に基づいて、m*100/111を開始点として使用します。あなたは確かにその値を天性値として使って正確な答えを得るために1と2を加えようとするが、粗い答えから必要な "オフセット"をあらかじめ計算することもできる。

# Precomputation, to populate the "offset" dictionary 
def sane_mod(a, m): return ((a % m) + m) % m 
offset = {} 
for y in range(10): 
    for z in range(10): 
     add = 10*y + 11*z 
     offset[sane_mod(-add, 111)] = add 

# Actual function 
def invert2(m): 
    rough = m * 100 
    return (rough + offset[rough % 111])/111 
assert invert2(559) == 504 
+0

Python 3では、整数除算を行うには '/'の代わりに '/'を使う必要があります。 – ShreevatsaR

1

a + b + cは、a + a // 10 + a // 100(ここで、//は切り捨てを示す)である。これは、* 111/100 - 1.89とa * 111/100の間のどこかにあります。 (// 10から捨てられる最大分数が0.9であり、// 100から捨てられる最大分数が0.99であり、1.89 = 0.9 + 0.99であるため1.89)。

ので、+ B + Cを考えると、我々はそのような整数を探しています:X = CEIL((A + B + C)* 111分の100)させしたがって

a * 111/100 - 1.89 <= a + b + c <= a * 111/100 
a - 2.0979 <= (a + b + c) * 100/111 <= a 

、 x、x + 1またはx + 2のいずれかが解でなければなりません。

+0

いいアイデア、+1。 (n +⌊n/10⌋+⌊n/100⌋)の代わりに、床を取り除き、正確な除算を行うと、結果はn + n/10 + n/100 = 111n/100です(例:504→504 + 50.4 + 5.04 = 555.44)、丸めによって導入されたエラーを縛ります。これは、私がより頻繁に試してみるべき覚えがある一般的かつ強力なアイデアです。コンビナトリアル主義者ではなく、現実のアナリストのように考える。 :-) – ShreevatsaR

+0

あなたはm * 100/111を計算すると、正確に(10y + 11z)/ 111でnの正しい値に足りない、ここで* yz *は最後の2桁ですnであり、これらはすべて0≦y≦9,0≦z≦9で異なるため、m * 100/111の小数部から(10y + 11z)/ 111までのマップをx、x + 1、x + 2のどれかを直接把握して、3つすべてを試すのではなく、 – ShreevatsaR

関連する問題