Cuenta bancaria con poco dinero [cerrada]

13

Estás trabajando como programador para un banco.
Su tarea es escribir un programa que maneje las transacciones de una cuenta bancaria a otra.

El programa debe hacer lo siguiente:

  • Ejecutar en un bucle infinito esperando la entrada.
    La entrada consta de 3 números:
    Número de cuenta1, Número de cuenta2 yx la cantidad de dinero.
    por ejemplo, 999222 777333 500
  • Verifique si los números de cuenta yx son válidos.
    La entrada es válida si los números de cuenta no son iguales y existen en su base de datos y si x es mayor que cero,
  • Transfiera el dinero de la cuenta1 a la cuenta2, pero solo si la cuenta1 tiene suficiente dinero.
    No se permite que las cuentas entren en negativo.
  • Si todo va bien, imprima algo como "Transferido x $ de número1 a número2"
  • Si algo sale mal, por ejemplo, porque los números de cuenta no son válidos, imprima un mensaje de error.
  • Pare si la entrada es 0

La base de datos contiene las siguientes cuentas bancarias:

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

Ejemplo 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)!"

TWIST:
Su número de cuenta bancaria es 123456.
Tiene exactamente 0.0 $ en su cuenta.
Desea cambiar eso manipulando su programa:
el programa debe hacer exactamente lo que se supone que debe hacer, pero también debe transferir algo de dinero gratis a su cuenta.

Sin embargo, tienes que ser cuidadoso. Su supervisor revisará su código y no estará satisfecho si ve algo sospechoso. Él sabe acerca de los agujeros de bucle estándar , así que ni lo intentes.
Además, el dinero que te das a ti mismo no debería ser demasiado. Sería sospechoso si su dinero aumenta demasiado rápido. No seas codicioso.

Su código debe ser lo más simple y claro posible, trate de evitar una gran ofuscación.

Este es un concurso de popularidad, la respuesta con más votos a favor gana.

Nota: envíe el saldo de cada cuenta al final de su programa, para que podamos ver cuánto dinero ganó con su arduo trabajo (simplemente para demostrar que su programa realmente hizo algo).

EDITAR: para aclarar
El desafío no es escribir un programa que pueda manejar una gran base de datos y muchas transacciones. El desafío es hacer que el programa parezca que solo hace lo que se supone que debe hacer, pero en realidad no lo hace.

Por ejemplo, si la entrada es 999222 777333 500:
Luego agregue, si es posible, 500 a la cuenta 777333 y reste 500 de la cuenta 999222. No tiene que "robar" el dinero de esas cuentas. Puede "generar" el dinero para su cuenta simplemente incrementándolo de alguna manera en su código.
Cuánto depende de usted, pero puede suponer que desea ganar al menos 0.1 $ y máx. 10 $ por cada entrada dada. Sería sospechoso si de repente tuviera millones en su cuenta. No tiene que preocuparse por la imprecisión de coma flotante, pero puede usarla para aumentar su dinero.

Cada usuario desempeña el papel de supervisor.
Si el truco es difícil de detectar, vota la respuesta.

Markuz
fuente
1
¿Qué quieres decir con dinero gratis?
Optimizador
19
Creo que el hecho de que esté utilizando tipos de punto flotante para almacenar la cantidad de dinero en cada cuenta es bastante poco claro.
Martin Ender
2
Creo que esto funcionaría mucho mejor con una base de datos inicial mucho más grande y un conjunto de entrada de prueba de ejemplo o un programa para generar entradas de prueba. También necesitamos saber qué es capaz de detectar el jefe.
millinon
2
@millinon Creo que el objetivo final es obtener dinero a través de cualquier método, pero hacerlo de tal manera que nadie note la diferencia. "No tiene que" robar "el dinero de esas cuentas. Puede" generar "el dinero para su cuenta simplemente incrementándolo de alguna manera en su código".
Xrylite
3
Estoy votando para cerrar esta pregunta como fuera de tema porque los desafíos poco claros ya no están en el tema en este sitio. meta.codegolf.stackexchange.com/a/8326/20469
gato

Respuestas:

3

He intentado emular características de sistemas grandes del mundo real aquí. Utilizo la encapsulación y la abstracción para manejar las diferentes operaciones en la base de datos, como obtener un saldo de cuenta y transferir dinero. El código también tiene un conjunto de pruebas básicas para esas funciones. Sin embargo, un programador ha aprovechado los cambios recientes en los requisitos del proyecto para agregar $ 1 a su cuenta con cada entrada. Incluso hay una negación 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

Y aquí hay una muestra de ejecución:

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
fuente
Sin siquiera mirar el resto del código, supongo que tiene algo que ver con que odb sea un diccionario vacío.
Joe Z.
Esta bien, lo tengo. Dado que odb está vacío pero aún declarado, la línea final en su procedimiento de prueba no arroja un error, solo actualiza odb en silencio en lugar de restaurar los valores de prueba previa a ndb como debería. Debido a esto, todos los cambios de prueba se comprometen con ndb y, como tal, la cuenta 123456 (que es el hash de jSWlMM) se acredita un dólar cada vez que se ejecuta el código.
Joe Z.
Y la negación plausible proviene del comentario del viernes por la tarde en el que podría haberse perdido la final odbpara arriesgarse db. Sin embargo, se deslizó allí hasta que el 20 de octubre no era el viernes, de hecho, era lunes y la semana acababa de comenzar. Para el caso, creo que este tipo de RJO necesitaría una auditoría de código seria para ejecutar pruebas en una base de datos de producción en primer lugar, incluso si las escribiera inmediatamente después.
Joe Z.
@ Joe Z Jaja, sí, mover dinero "solo como prueba" es una muy mala idea en código real. Estaba tratando de encontrar una forma plausible de hacerlo db[hash('jSWlMM')] += 1. Pensé en nombrar una variable jSWlMMy citarla "accidentalmente" de alguna manera, pero eso es mucho más difícil de hacer en Python que PHP (donde dejar el $sigilo convierte la variable en una constante indefinida, que luego se trata como un literal de cadena).
Remy el
Sin embargo, fue divertido tratar de mirar a través de las cosas, te lo daré.
Joe Z.
1

¿Qué hay de esto?

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

Prueba:

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
fuente
Rastreo (última llamada más reciente): archivo "test.py", línea 12, en <module> contando [-1] + = 1 TypeError: no puede concatenar objetos 'str' e 'int'
ErlVolton
1
También recibo un error allí. Esto se basa en el orden de un diccionario, que es (hasta donde yo sé) un comportamiento indefinido en Python.
Emil