Недостатній банківський рахунок [закрито]


13

Ви працюєте програмістом у банку.
Ваше завдання - написати програму, яка обробляє транзакції з одного банківського рахунку на інший.

Програма повинна робити наступне:

  • Виконати в нескінченному циклі, що чекає введення.
    Вхід складається з 3 чисел: номер
    рахунку1, номер рахунку2 та х сума грошей.
    наприклад 999222 777333 500
  • Перевірте, чи дійсні номери рахунків та х.
    Введення дійсне, якщо номери рахунків не однакові і існують у вашій базі даних, і якщо x більше нуля,
  • Перерахуйте гроші з рахунку1 на рахунок2, але тільки якщо на рахунку1 є достатньо грошей.
    Рахунки не можуть переходити в мінус.
  • Якщо все піде добре, надрукуйте щось на кшталт "Перенесено x $ з числа1 в число2"
  • якщо щось піде не так, наприклад, тому що номери рахунків недійсні, надрукуйте повідомлення про помилку.
  • Зупиніть, якщо вхід 0

База даних містить такі банківські рахунки:

  • 999222: 10000.56$
  • 888333: 335.13$
  • 555222: 56.0$
  • 222111: 123.55$
  • 123456: 0.0$

Простий приклад Python 2:

account_numbers = ["999222", "888333", "555222", "222111", "123456"]
account_money   = [10000.56,   335.13,     56.0,   123.55,      0.0]


while True:
    #input in the form of: 999222 777333 500
    input = raw_input()

    if input == "0": break

    number1, number2, x = input.split()

    x = float(x)
    if x <= 0:
        print "Invalid request!"
        continue

    if number1 in account_numbers and number2 in account_numbers and number1 != number2:
        index1 = account_numbers.index(number1)
        index2 = account_numbers.index(number2)

        if account_money[index1] >= x:
            account_money[index1] -= x
            account_money[index2] += x
            print "Transferred %.2f$ from %s to %s" % (x, number1, number2)
        else:
            print "Not enough money in account %s!" % (number1)

    else:
        print "Invalid account number(s)!"

TWIST:
Номер вашого банківського рахунку - 123456. У
вас на рахунку рівно 0,0 $.
Ви хочете змінити це, маніпулюючи програмою:
Програма повинна робити саме те, що вона повинна робити, але також повинна перерахувати кілька безкоштовних грошей на ваш рахунок.

Ти повинен бути обережним. Ваш керівник подивиться на ваш код, і він не буде задоволений, якщо побачить щось підозріле. Він знає про стандартні отвори петлі , тому навіть не намагайтеся.
Крім того, гроші, які ви даєте собі, не повинні бути занадто великими. Було б підозріло, якщо ваші гроші збільшуються занадто швидко. Не будь жадібним.

Ваш код повинен бути максимально простим і зрозумілим, намагайтеся уникати сильних омертвінь.

Це конкурс на популярність, виграє відповідь з найбільшою кількістю нагород.

Примітка. Будь ласка, виведіть залишки кожного рахунку в кінці програми, щоб ми могли бачити, скільки грошей ви заробили своєю наполегливою працею (просто щоб показати, що ваша програма насправді щось робила).

EDIT: Для уточнення
Завдання полягає в тому, щоб не написати програму, яка може обробляти велику базу даних і безліч транзакцій. Завдання полягає в тому, щоб зробити програму схожою лише на те, що вона повинна робити, але насправді це не так.

Наприклад, якщо вхід є 999222 777333 500:
Потім додайте, якщо можливо, 500 на рахунок 777333 і відніміть 500 з рахунку 999222. Вам не доведеться "красти" гроші з цих рахунків. Ви можете "генерувати" гроші для свого рахунку, просто збільшивши його якось у своєму коді.
Скільки залежить від вас, але ви можете припустити, що ви хочете заробити принаймні 0,1 $ і макс. 10 $ за кожен заданий вхід. Було б підозріло, якби у вас раптом на вашому рахунку були мільйони. Вам не доведеться турбуватися про неточність плаваючої точки, але ви можете використовувати її для збільшення своїх грошей.

Кожен користувач виконує роль супервізора.
Якщо хитрість важко помітити, відповідь не відповідає.


1
Що ви маєте на увазі під безкоштовними грошима?
Оптимізатор

19
Я думаю, що той факт, що ви використовуєте типи з плаваючою комою для зберігання кількості грошей на кожному рахунку, є недостатньо обґрунтованим.
Мартін Ендер

2
Я думаю, що це буде працювати набагато краще зі значно більшою початковою базою даних або набором прикладу тестового введення, або програмою для генерації тестових входів. Нам також потрібно знати, що бос здатний виявити.
мільйон

2
@millinon Я вважаю, що кінцева мета - взагалі отримати гроші будь-яким методом, але зробити це таким чином, щоб ніхто не помітив різниці. "Вам не доведеться" красти "гроші з цих рахунків. Ви можете" генерувати "гроші для свого рахунку, просто збільшивши їх якось у своєму коді".
Xrylite

3
Я голосую за те, щоб закрити це питання поза темою, оскільки обґрунтовані виклики більше не є темою на цьому сайті. meta.codegolf.stackexchange.com/a/8326/20469
кіт

Відповіді:


3

Я намагався наслідувати особливості великих реальних систем тут. Я використовую інкапсуляцію та абстракцію, щоб обробляти різні операції з базою даних, як-от отримання балансу на рахунку та переказ грошей. Код також має базовий тестовий набір для цих функцій. Однак один програміст скористався нещодавніми змінами в вимогах проекту, щоб додати 1 долар на свій рахунок при кожному вкладі. Існує навіть правдоподібне заперечення.

# {account number: balance in USD}
ndb = {
    999222: 10000.56,
    888333: 335.13,
    555222: 56.0,
    222111: 123.55,
    123456: 0.0
}

# {hashed account ID: balance in USD}
# (hash the IDs because integer-based hash tables are fast, and a
# bunch of strcmp's would be slow)
# 2014-10-20: phased out alphabetic account IDs for numeric ones
# keeping the old data here because Murphy's Law guarantees we'll
# need it right after it's deleted. -- RJO
odb = {
#   hash('mEYjxG'): 42.0,
#   hash('lDCIqp'): 1337.0,
#   hash('QDxkwD'): 123456.0,
#   hash('jSWlMM'): 0.0,
#   hash('siYWKC'): 20.14
}

def balance(a, db):
    try:
        return db[hash(a)]
    except:
        raise ValueError('no such account:', a)

def credit(a, n, db):
    if n <= 0:
        raise ValueError('invalid amount: ' + str(n))
    try:
        db[hash(a)] += n
    except:
        raise ValueError('no such account:', a)

# 2012-10-20: parameterizing the database ops to handle both
# old and new databases is a pain in the neck. -- RJO

def debit(a, n, db):
    if n <= 0:
        raise ValueError('invalid amount: ' + str(n))
    if balance(a, db) < n:
        raise ValueError('insufficient funds: below ' + str(n))
    try:
        db[hash(a)] -= n
    except:
        raise ValueError('no such account', a)

def transfer(a, b, n, db):
    if a == b:
        raise ValueError('same account', a)
    debit(a, n, db)
    credit(b, n, db)

# 2014-10-20: tests need to be updated with new account IDs, but
# it's Friday afternoon. -- RJO
def test(db):
    # back up database prior to changes
    bdb = db.copy()
    # test database functions
    try:
        # test 'balance'
        account = 'does not exist'
        try:
            bal = balance(account, db)
            assert(db[hash(account)] == bal)
        except ValueError:
            assert(hash(account) not in db)
        # test 'credit'
        account = 'jSWlMM'
        start = balance(account, db)
        delta = 1
        credit(account, delta, db)
        assert(balance(account, db) == start + delta)
        # test 'debit'
        account = 'lDCIqp'
        start = balance(account, db)
        delta = 1337
        try:
            debit(account, delta, db)
            assert(balance(account, db) == start - delta)
        except ValueError:
            assert(balance(account, db) < delta)
        # test 'transfer'
        account1 = 'mEYjxG'
        account2 = 'siYWKC'
        start1 = balance(account1, db)
        start2 = balance(account2, db)
        delta = 123
        try:
            transfer(account1, account2, delta, db)
            assert(balance(account1, db) == start - delta)
            assert(balance(account2, db) == start + delta)
        except ValueError:
            assert(balance(account1, db) < delta)
    except Exception as ex:
        # log errors
        print ex.message
    finally:
        # roll back all changes
        odb.update(bdb)

# interactive transfers
while True:
    # test everything
    test(ndb)
    # get input
    print 'Transfer $N from A to B:'
    line = raw_input('Enter "A B N" or 0: ')
    # check for exit
    if line == '0':
        print 'Exit'
        # print account balances
        for a in ndb:
            print 'Account', a, 'has', balance(a, ndb), '$'
        break
    # parse input
    try:
        a, b, n = line.split()
        a = int(a)
        b = int(b)
        n = float(n)
    except:
        print 'Bad input!'
        continue
    # make transfer
    try:
        transfer(a, b, n, ndb)
        print 'Transferred', n, '$ from account', a, 'to', b
    except ValueError as e:
        print e

Ось пробірка:

Transfer $N from A to B:
Enter "A B N" or 0: 999222 222111 500
Transferred 500.0 $ from account 999222 to 222111

Transfer $N from A to B:
Enter "A B N" or 0: 555222 888333 12
Transferred 12.0 $ from account 555222 to 888333

Transfer $N from A to B:
Enter "A B N" or 0: 222111 555222 14
Transferred 14.0 $ from account 222111 to 555222

Transfer $N from A to B:
Enter "A B N" or 0: 0
Exit
Account 555222 has 58.0 $
Account 123456 has 4.0 $
Account 888333 has 347.13 $
Account 999222 has 9500.56 $
Account 222111 has 609.55 $

Навіть не дивлячись на решту коду, я здогадуюсь, що це має щось спільне з тим, що odb є порожнім словником.
Джо З.

Гаразд, я зрозумів. Оскільки odb порожній, але все-таки задекларований, остаточний рядок у вашій процедурі тестування не видає помилку - він просто оновлює odb мовчки замість відновлення значень попереднього тестування до ndb, як слід. Через це всі тестові зміни приймаються на ndb, і таким чином рахунок 123456 (який є хеш jSWlMM) отримує один долар щоразу, коли код запускається.
Джо З.

І правдоподібне заперечення випливає з коментаря у другій половині дня п’ятниці, в якому він міг пропустити фінал, odbщоб шанс це зробити db. Однак він підсунувся туди, що 20 жовтня зовсім не була п'ятниця - насправді це був понеділок, а тиждень тільки почався. З цього приводу я думаю, що цьому співробітнику RJO потрібен був би серйозний аудит коду для запуску тестів на виробничій базі даних, навіть якщо він записував їх відразу після цього.
Джо Z.

@Joe Z Haha, так, переміщення грошей "як тест" - це дійсно погана ідея в реальному коді. Я намагався придумати правдоподібний спосіб зробити db[hash('jSWlMM')] += 1. Я розглядав можливість називати змінну jSWlMMі "випадково" цитувати її якось, але це зробити набагато важче в Python, ніж PHP (де відмова від $sigil перетворює змінну в невизначену константу, яка потім трактується як лінійна буква).
Ремі

Це було цікаво, намагаючись переглянути речі, однак, я вам це передам.
Джо З.

1

Як що до цього ?

account_numbers = ["999222", "888333", "555222", "222111", "123456"]
account_money   = [10000.56,   335.13,     56.0,   123.55,      0.0]

counting=locals()[locals().keys()[2]]

while True:
    #input in the form of: 999222 777333 500
    input = raw_input()

    if input == "0": break

    counting[-1]+=1
    number1, number2, x = input.split()

    x = float(x)
    if x <= 0:
        print "Invalid request!"
        continue

    if number1 in account_numbers and number2 in account_numbers and number1 != number2:
        index1 = account_numbers.index(number1)
        index2 = account_numbers.index(number2)

        if account_money[index1] >= x:
            account_money[index1] -= x
            account_money[index2] += x
            print "Transferred %.2f$ from %s to %s" % (x, number1, number2)
        else:
            print "Not enough money in account %s!" % (number1)

    else:
        print "Invalid account number(s)!"


for i in range(len(account_numbers)):
    print "Money in account '%s' is %s" % (account_numbers[i], account_money[i])

Тест:

999222 222111 500
Transferred 500.00$ from 999222 to 222111
555222 888333 12
Transferred 12.00$ from 555222 to 888333
222111 555222 14
Transferred 14.00$ from 222111 to 555222
0
Money in account '999222' is 9500.56
Money in account '888333' is 347.13
Money in account '555222' is 58.0
Money in account '222111' is 609.55
Money in account '123456' is 3.0

Traceback (останній виклик останній): Файл "test.py", рядок 12, у <module> counting [-1] + = 1 TypeError: не можна об'єднати об'єкти "str" ​​та "int"
ErlVolton

1
Я також отримую помилку там. Це спирається на впорядкування словника, що є (наскільки я знаю) невизначеною поведінкою в Python.
Еміль
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.