Conta bancária secreta [fechada]

13

Você está trabalhando como programador de um banco.
Sua tarefa é escrever um programa que lida com as transações de uma conta bancária para outra.

O programa deve fazer o seguinte:

  • Execute um loop infinito aguardando entrada.
    A entrada consiste em 3 números: Número da
    conta1, Número da conta2 e x a quantia em dinheiro.
    por exemplo, 999222 777333 500
  • Verifique se os números de conta ex são válidos.
    A entrada é válida se os números da conta não forem os mesmos e existirem no seu banco de dados e se x for maior que zero,
  • Transfira o dinheiro da conta1 para a conta2, mas apenas se a conta1 tiver dinheiro suficiente.
    As contas não têm permissão para entrar no negativo.
  • Se tudo correr bem, imprima algo como "Transferido x $ do número1 para o número2"
  • se algo der errado, por exemplo, porque os números da conta são inválidos, imprima uma mensagem de erro.
  • Pare se a entrada for 0

O banco de dados contém as seguintes contas bancárias:

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

Exemplo simples 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: O
número da sua conta bancária é 123456.
Você tem exatamente 0,0 $ na sua conta.
Você deseja alterar isso manipulando seu programa:
O programa deve fazer exatamente o que deve ser feito, mas também deve transferir algum dinheiro grátis para sua conta.

Você tem que ter cuidado, porém. Seu supervisor examinará seu código e não ficará satisfeito se vir algo suspeito. Ele conhece os furos de loop padrão , então nem tente.
Além disso, o dinheiro que você dá a si mesmo não deve ser demais. Seria suspeito se seu dinheiro aumentar muito rapidamente. Não seja ganancioso.

Seu código deve ser o mais simples e claro possível, tente evitar ofuscação pesada.

Este é um concurso de popularidade, a resposta com mais vitórias positivas.

Nota: forneça o saldo de cada conta no final do seu programa, para que possamos ver quanto você ganhou com seu trabalho duro (simplesmente para mostrar que seu programa realmente fez alguma coisa).

EDIT: Para esclarecer
O desafio não é escrever um programa que possa lidar com um banco de dados grande e com muitas transações. O desafio é fazer com que o programa pareça apenas fazer o que deveria, mas na realidade não.

Por exemplo, se a entrada for 999222 777333 500:
Em seguida, adicione, se possível, 500 à conta 777333 e subtraia 500 da conta 999222. Você não precisa "roubar" o dinheiro dessas contas. Você pode "gerar" o dinheiro da sua conta, simplesmente aumentando de alguma forma no seu código.
Quanto depende de você, mas você pode supor que deseja ganhar pelo menos 0,1 $ e no máximo. 10 $ para cada entrada fornecida. Seria suspeito se de repente você tivesse milhões em sua conta. Você não precisa se preocupar com a imprecisão de ponto flutuante, mas pode usá-lo para aumentar seu dinheiro.

Todo usuário desempenha o papel de supervisor.
Se o truque é difícil de identificar, a resposta é positiva.

Markuz
fonte
1
O que você quer dizer com dinheiro grátis?
Optimizer
19
Eu acho que o fato de você estar usando tipos de ponto flutuante para armazenar a quantidade de dinheiro em cada conta é insuficiente.
Martin Ender
2
Eu acho que isso funcionaria muito melhor com um banco de dados inicial muito maior e um conjunto de exemplos de entrada de teste ou um programa para gerar entradas de teste. Também precisamos saber o que o chefe é capaz de detectar.
millinon 17/09/14
2
@millinon Creio que o objetivo final é obter dinheiro através de qualquer método, mas fazê-lo de maneira que ninguém perceba a diferença. "Você não precisa" roubar "o dinheiro dessas contas. Você pode" gerar "o dinheiro para sua conta, simplesmente aumentando de alguma forma em seu código."
Xrylite
3
Estou votando para encerrar esta questão como fora de tópico, porque os desafios secretos não estão mais no tópico neste site. meta.codegolf.stackexchange.com/a/8326/20469
cat

Respostas:

3

Tentei emular recursos de sistemas grandes do mundo real aqui. Uso encapsulamento e abstração para lidar com as diferentes operações do banco de dados, como obter um saldo da conta e transferir dinheiro. O código também possui um conjunto de testes básico para essas funções. No entanto, um programador aproveitou as alterações recentes nos requisitos do projeto para adicionar US $ 1 à sua conta a cada entrada. Existe até negação plausível.

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

E aqui está uma amostra:

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
fonte
Sem sequer olhar para o restante do código, acho que tem algo a ver com odb ser um dicionário vazio.
911 Joe Z.
OK eu entendi. Como o odb está vazio, mas ainda é declarado, a linha final no seu procedimento de teste não gera um erro - apenas atualiza o odb silenciosamente em vez de restaurar os valores de pré-teste para o ndb como deveria. Por esse motivo, todas as alterações de teste são confirmadas no ndb e, como tal, a conta 123456 (que é o hash de jSWlMM) recebe um dólar cada vez que o código é executado.
911 Joe Z.
E a negação plausível vem do comentário da tarde de sexta-feira no qual ele poderia ter perdido a final odbpor acaso db. No entanto, ele chegou lá naquele dia 20 de outubro não era sexta-feira - na verdade, era segunda-feira e a semana estava apenas começando. Por falar nisso, acho que esse colega do RJO precisaria de uma auditoria de código séria para executar testes em um banco de dados de produção, mesmo que os escrevesse logo depois.
Joe Z.
@ Joe Z Haha, sim, transferir dinheiro "apenas como teste" é uma péssima idéia em código real. Eu estava tentando encontrar uma maneira plausível de fazer db[hash('jSWlMM')] += 1. Eu considerei nomear uma variável jSWlMMe "acidentalmente" citá-la de alguma forma, mas isso é muito mais difícil de fazer em Python do que PHP (onde deixar o $sigilo transforma a variável em uma constante indefinida, que é então tratada como uma string literal).
Remy
Foi divertido tentar analisar as coisas, porém, eu vou lhe dar isso.
Joe Z.
1

Que tal isso?

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

Teste:

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
fonte
Traceback (última chamada mais recente): arquivo "test.py", linha 12, em <module> contando [-1] + = 1 TypeError: não é possível concatenar os objetos 'str' e 'int'
ErlVolton
1
Eu também recebo um erro lá. Isso depende da ordem de um dicionário, que é (até onde eu sei) um comportamento indefinido no Python.
Emil