Compte bancaire sournois [fermé]

13

Vous travaillez en tant que programmeur pour une banque.
Votre tâche consiste à écrire un programme qui gère les transactions d'un compte bancaire à un autre.

Le programme devrait faire ce qui suit:

  • Exécuter dans une boucle infinie en attente d'entrée.
    L'entrée se compose de 3 nombres:
    Accountnumber1, Accountnumber2 et x le montant d'argent.
    par exemple 999222 777333 500
  • Vérifiez si les numéros de compte et x sont valides.
    L'entrée est valide si les numéros de compte ne sont pas identiques et existent dans votre base de données et si x est supérieur à zéro,
  • Transférez l'argent du compte1 au compte2, mais uniquement si le compte1 a suffisamment d'argent.
    Les comptes ne sont pas autorisés à entrer dans le négatif.
  • Si tout se passe bien, imprimez quelque chose comme "Transféré x $ du numéro1 au numéro2"
  • en cas de problème, par exemple parce que les numéros de compte ne sont pas valides, imprimez un message d'erreur.
  • Arrêter si l'entrée est 0

La base de données contient les comptes bancaires suivants:

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

Exemple simple de 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)!"

TORSION:
Votre numéro de compte bancaire est 123456.
Vous avez exactement 0,0 $ dans votre compte.
Vous voulez changer cela en manipulant votre programme:
le programme doit faire exactement ce qu'il est censé faire, mais doit également transférer de l'argent gratuit sur votre compte.

Sois quand même prudent. Votre superviseur examinera votre code et il ne sera pas content s'il voit quelque chose de suspect. Il connaît la trous de boucle standard , alors n'essayez même pas.
De plus, l'argent que vous vous donnez ne devrait pas être trop. Il serait suspect que votre argent augmente trop rapidement. Ne soyez pas gourmand.

Votre code doit être aussi simple et clair que possible, essayez d'éviter les obstructions importantes.

Il s'agit d'un concours de popularité, la réponse avec le plus de votes positifs l'emporte.

Remarque: veuillez afficher le solde de chaque compte à la fin de votre programme, afin que nous puissions voir combien d'argent vous avez gagné avec votre travail acharné (simplement pour montrer que votre programme a réellement fait quelque chose).

EDIT: pour clarifier
Le défi n'est pas d'écrire un programme capable de gérer une grande base de données et beaucoup de transactions. Le défi est de donner l'impression que le programme ne fait que ce qu'il est censé faire, mais en réalité non.

Par exemple, si l'entrée est 999222 777333 500:
Ajoutez ensuite, si possible, 500 au compte 777333 et soustrayez 500 du compte 999222. Vous n'avez pas à "voler" l'argent de ces comptes. Vous pouvez "générer" de l'argent pour votre compte en l'augmentant simplement d'une manière ou d'une autre dans votre code.
Combien vous appartient, mais vous pouvez supposer que vous voulez gagner au moins 0,1 $ et max. 10 $ pour chaque entrée donnée. Il serait suspect que vous ayez soudainement des millions sur votre compte. Vous n'avez pas à vous soucier de l'imprécision en virgule flottante, mais vous pouvez l'utiliser pour augmenter votre argent.

Chaque utilisateur joue le rôle du superviseur.
Si l'astuce est difficile à repérer, votez la réponse.

Markuz
la source
1
Qu'entendez-vous par argent gratuit?
Optimizer
19
Je pense que le fait que vous utilisez des types à virgule flottante pour stocker le montant d'argent dans chaque compte est suffisamment sournois.
Martin Ender
2
Je pense que cela fonctionnerait beaucoup mieux avec une base de données initiale beaucoup plus grande et soit un ensemble d'exemples d'entrées de test ou un programme pour générer des entrées de test. Nous devons également savoir ce que le patron est capable de détecter.
millinon
2
@millinon Je crois que le but ultime est d'obtenir de l'argent par n'importe quelle méthode, mais de manière à ce que personne ne remarque la différence. "Vous n'avez pas à" voler "l'argent de ces comptes. Vous pouvez" générer "l'argent pour votre compte en l'augmentant simplement d'une manière ou d'une autre dans votre code."
Xrylite
3
Je vote pour fermer cette question comme hors sujet car les défis sournois ne sont plus sur le sujet sur ce site. meta.codegolf.stackexchange.com/a/8326/20469
cat

Réponses:

3

J'ai essayé d'émuler les fonctionnalités des grands systèmes du monde réel ici. J'utilise l'encapsulation et l'abstraction pour gérer les différentes opérations dans la base de données, comme obtenir un solde de compte et transférer de l'argent. Le code dispose également d'une suite de tests de base pour ces fonctions. Cependant, un programmeur a profité des récents changements dans les exigences du projet pour ajouter 1 $ à son compte à chaque entrée. Il y a même un déni plausible.

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

Et voici un exemple d'exécution:

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 $
Rémy
la source
Sans même regarder le reste du code, je suppose que cela a quelque chose à voir avec odb étant un dictionnaire vide.
Joe Z.
C'est bon je l'ai. Comme odb est vide mais toujours déclaré, la dernière ligne de votre procédure de test ne génère pas d'erreur - elle met simplement à jour odb en silence au lieu de restaurer les valeurs de pré-test sur ndb comme il se doit. Pour cette raison, toutes les modifications de test sont validées dans ndb, et en tant que tel, le compte 123456 (qui est le hachage de jSWlMM) est crédité d'un dollar chaque fois que le code est exécuté.
Joe Z.
Et le déni plausible vient du commentaire de vendredi après-midi dans lequel il aurait pu manquer la finale odbpour la chance db. Cependant, il a glissé là-haut en ce que le 20 octobre n'était pas du tout vendredi - en fait, c'était lundi et la semaine venait de commencer. D'ailleurs, je pense que ce boursier RJO aurait besoin d'un audit de code sérieux pour exécuter des tests sur une base de données de production en premier lieu, même s'il les a réécrits juste après.
Joe Z.
@Joe Z Haha, oui, déplacer de l'argent "juste comme un test" est une très mauvaise idée dans le vrai code. J'essayais de trouver une façon plausible de le faire db[hash('jSWlMM')] += 1. J'ai envisagé de nommer une variable jSWlMMet de la citer "accidentellement" d'une manière ou d'une autre, mais c'est beaucoup plus difficile à faire en Python qu'en PHP (où le fait de laisser le $sceau transforme la variable en une constante indéfinie, qui est ensuite traitée comme un littéral de chaîne).
Remy
C'était amusant d'essayer de regarder à travers les choses, cependant, je vais vous le donner.
Joe Z.
1

Et ça ?

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

Tester:

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
la source
Traceback (dernier appel le plus récent): fichier "test.py", ligne 12, dans <module> en comptant [-1] + = 1 TypeError: ne peut pas concaténer les objets 'str' et 'int'
ErlVolton
1
Je reçois également une erreur là-bas. Cela dépend de l'ordre d'un dictionnaire, qui est (pour autant que je sache) un comportement non défini en Python.
Emil