Underhanded Bank Account [geschlossen]

13

Sie arbeiten als Programmierer für eine Bank.
Ihre Aufgabe ist es, ein Programm zu schreiben, das die Transaktionen von einem Bankkonto auf ein anderes verwaltet.

Das Programm sollte Folgendes ausführen:

  • Führen Sie eine Endlosschleife aus, die auf Eingabe wartet.
    Die Eingabe besteht aus 3 Zahlen:
    Kontonummer1, Kontonummer2 und x dem Geldbetrag.
    zB 999222 777333 500
  • Überprüfen Sie, ob die Kontonummern und x gültig sind.
    Die Eingabe ist gültig, wenn die Kontonummern nicht identisch sind und in Ihrer Datenbank vorhanden sind und wenn x größer als Null ist.
  • Überweisen Sie das Geld von Konto1 auf Konto2, jedoch nur, wenn Konto1 über genügend Geld verfügt.
    Konten dürfen nicht ins Negative gehen.
  • Wenn alles gut geht, drucken Sie so etwas wie "Übertragene x $ von Nummer1 zu Nummer2"
  • Wenn etwas schief geht, z. B. weil die Kontonummern ungültig sind, drucken Sie eine Fehlermeldung.
  • Stoppen, wenn die Eingabe 0 ist

Die Datenbank enthält die folgenden Bankkonten:

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

Einfaches Python 2 Beispiel:

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:
Ihre Bankkontonummer lautet 123456.
Sie haben genau 0,0 $ auf Ihrem Konto.
Sie möchten das ändern, indem Sie Ihr Programm manipulieren:
Das Programm sollte genau das tun, was es tun soll, aber auch etwas kostenloses Geld auf Ihr Konto überweisen.

Sie müssen jedoch vorsichtig sein. Ihr Vorgesetzter wird sich Ihren Code ansehen und es wird ihn nicht freuen, wenn er etwas Verdächtiges sieht. Er kennt sich mit den Standard-Loop-Löchern aus , versuchen Sie es also nicht einmal.
Auch das Geld, das Sie sich selbst geben, sollte nicht zu viel sein. Es wäre verdächtig, wenn Ihr Geld zu schnell steigt. Sei nicht gierig.

Ihr Code sollte so einfach und klar wie möglich sein. Vermeiden Sie starke Verschleierung.

Dies ist ein Beliebtheitswettbewerb, bei dem die Antwort mit den meisten positiven Stimmen gewinnt.

Hinweis: Bitte geben Sie den Saldo jedes Kontos am Ende Ihres Programms aus, damit wir sehen können, wie viel Geld Sie mit Ihrer harten Arbeit verdient haben (nur um zu zeigen, dass Ihr Programm tatsächlich etwas getan hat).

BEARBEITEN: Zur Klärung
Die Herausforderung besteht nicht darin, ein Programm zu schreiben, das eine große Datenbank und viele Transaktionen verarbeiten kann. Die Herausforderung besteht darin, das Programm so aussehen zu lassen, als würde es nur das tun, was es tun soll, in Wirklichkeit aber nicht.

Wenn die Eingabe beispielsweise lautet 999222 777333 500:
Addieren Sie nach Möglichkeit 500 zu Konto 777333 und subtrahieren Sie 500 von Konto 999222. Sie müssen das Geld nicht von diesen Konten "stehlen". Sie können das Geld für Ihr Konto "generieren", indem Sie es einfach in Ihrem Code erhöhen.
Wie viel liegt bei Ihnen, aber Sie können davon ausgehen, dass Sie mindestens 0,1 $ und max verdienen möchten. 10 $ für jeden gegebenen Eingang. Es wäre verdächtig, wenn Sie plötzlich Millionen auf Ihrem Konto hätten. Sie müssen sich keine Gedanken über Gleitkomma-Ungenauigkeiten machen, aber Sie können damit Ihr Geld erhöhen.

Jeder Benutzer spielt die Rolle des Supervisors.
Wenn der Trick schwer zu erkennen ist, stimme der Antwort zu.

Markuz
quelle
1
Was meinst du mit kostenlosem Geld?
Optimierer
19
Ich denke, die Tatsache, dass Sie Gleitkommatypen verwenden, um den Geldbetrag auf jedem Konto zu speichern, ist nicht ausreichend belegt.
Martin Ender
2
Ich denke, dass dies mit einer viel größeren anfänglichen Datenbank und entweder einer Reihe von Testeingaben oder einem Programm zum Generieren von Testeingaben viel besser funktionieren würde. Wir müssen auch wissen, was der Chef erkennen kann.
Millinon
2
@millinon Ich glaube, das ultimative Ziel ist es, Geld mit einer beliebigen Methode reinzuholen, aber so, dass niemand den Unterschied bemerkt. "Sie müssen das Geld nicht von diesen Konten" stehlen ". Sie können das Geld für Ihr Konto" generieren ", indem Sie es einfach in Ihrem Code irgendwie erhöhen."
Xrylite
3
Ich stimme dafür, diese Frage als "Off-Topic" zu schließen, da hinterhältige Herausforderungen auf dieser Site nicht mehr zum Thema gehören. meta.codegolf.stackexchange.com/a/8326/20469
cat

Antworten:

3

Ich habe hier versucht, Features von realen großen Systemen zu emulieren. Ich verwende Kapselung und Abstraktion, um die verschiedenen Vorgänge in der Datenbank zu erledigen, wie das Abrufen eines Kontostands und das Überweisen von Geld. Der Code enthält auch eine grundlegende Testsuite für diese Funktionen. Ein Programmierer hat jedoch die jüngsten Änderungen der Projektanforderungen genutzt, um seinem Konto bei jeder Eingabe 1 US-Dollar hinzuzufügen. Es gibt sogar eine plausible Verleugnung.

# {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

Und hier ist ein Probelauf:

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 $
Remy
quelle
Ohne auf den Rest des Codes zu schauen, hat es vermutlich etwas damit zu tun, dass odb ein leeres Wörterbuch ist.
Joe Z.
Ich hab es verstanden. Da odb leer, aber immer noch deklariert ist, wird in der letzten Zeile Ihres Testverfahrens kein Fehler ausgegeben. Statt die Werte vor dem Test auf ndb zurückzusetzen, wird odb nur stillschweigend aktualisiert. Aus diesem Grund werden alle Änderungen an den Tests für ndb festgeschrieben, und dem Konto 123456 (dessen Hashwert jSWlMM) wird jedes Mal, wenn der Code ausgeführt wird, ein Dollar gutgeschrieben.
Joe Z.
Und die plausible Verleugnung ergibt sich aus dem Freitagnachmittagskommentar, in dem er das Finale verpasst haben könnte, um es odbzu versuchen db. Allerdings rutschte er dort hoch, als der 20. Oktober überhaupt nicht Freitag war - tatsächlich war es Montag und die Woche hatte gerade erst begonnen. Ich denke, dieser RJO-Mitarbeiter würde in erster Linie ein ernstes Code-Audit benötigen, um Tests in einer Produktionsdatenbank durchzuführen, selbst wenn er sie direkt danach zurückschreibt.
Joe Z.
@ Joe Z Haha, ja, Geld "nur als Test" zu bewegen, ist eine wirklich schlechte Idee in echtem Code. Ich habe versucht, einen plausiblen Weg zu finden db[hash('jSWlMM')] += 1. Ich habe überlegt, eine Variable zu benennen jSWlMMund sie "versehentlich" in Anführungszeichen zu setzen, aber das ist in Python viel schwieriger als in PHP (wobei das $Weglassen des Siegels die Variable in eine undefinierte Konstante verwandelt, die dann als String-Literal behandelt wird).
Remy
Es hat Spaß gemacht, durch die Dinge zu schauen, das gebe ich dir.
Joe Z.
1

Was ist damit?

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

Prüfung:

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
Alain Tésio
quelle
Traceback (letzter Aufruf zuletzt): Datei "test.py", Zeile 12, in <module> counting [-1] + = 1 TypeError: Objekte 'str' und 'int' können nicht verkettet werden
ErlVolton 31.10.14
1
Ich bekomme dort auch einen Fehler. Dies hängt von der Bestellung eines Wörterbuchs ab, was (soweit ich weiß) undefiniertes Verhalten in Python ist.
Emil