Conto bancario underhanded [chiuso]


13

Stai lavorando come programmatore per una banca.
Il tuo compito è scrivere un programma che gestisca le transazioni da un conto bancario a un altro.

Il programma dovrebbe effettuare le seguenti operazioni:

  • Esegui in un ciclo infinito in attesa di input.
    L'input è composto da 3 numeri:
    Accountnumber1, Accountnumber2 e x la quantità di denaro.
    ad es. 999222 777333 500
  • Controlla se i numeri di conto e x sono validi.
    L'input è valido se i numeri di conto non sono uguali ed esistono nel database e se x è maggiore di zero,
  • Trasferisci i soldi dal conto1 al conto2, ma solo se il conto1 ha abbastanza soldi.
    Gli account non possono andare in negativo.
  • Se tutto va bene, stampa qualcosa del tipo "Trasferito x $ da numero1 a numero2"
  • se qualcosa va storto, ad esempio perché i numeri di conto non sono validi, stampare un messaggio di errore.
  • Arresta se l'ingresso è 0

Il database contiene i seguenti conti bancari:

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

Esempio di Python 2 semplice:

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: il
tuo numero di conto bancario è 123456.
Hai esattamente 0,0 $ nel tuo conto.
Vuoi cambiarlo manipolando il tuo programma:
il programma dovrebbe fare esattamente quello che dovrebbe fare, ma dovrebbe anche trasferire un po 'di denaro gratuito sul tuo account.

Devi stare attento però. Il tuo supervisore esaminerà il tuo codice e non sarà contento se vede qualcosa di sospetto. Conosce gli Standard Loop Holes , quindi non provarci nemmeno.
Inoltre, i soldi che ti dai non dovrebbero essere troppo. Sarebbe sospetto se il tuo denaro aumenta troppo rapidamente. Non essere avido.

Il tuo codice dovrebbe essere il più semplice e chiaro possibile, cerca di evitare pesanti offuscamenti.

Questo è un concorso di popolarità, la risposta con il maggior numero di voti vince.

Nota: si prega di generare il saldo di ciascun account alla fine del programma, in modo che possiamo vedere quanti soldi hai guadagnato con il tuo duro lavoro (semplicemente per dimostrare che il tuo programma ha effettivamente fatto qualcosa).

EDIT: per chiarire
La sfida non è quella di scrivere un programma in grado di gestire un database di grandi dimensioni e molte transazioni. La sfida è far sembrare che il programma faccia solo quello che dovrebbe fare, ma in realtà no.

Ad esempio, se l'input è 999222 777333 500:
Quindi aggiungere, se possibile, 500 all'account 777333 e sottrarre 500 dall'account 999222. Non è necessario "rubare" il denaro da tali account. Puoi "generare" il denaro per il tuo account semplicemente aumentandolo in qualche modo nel tuo codice.
Quanto dipende da te, ma puoi presumere che vuoi guadagnare almeno 0,1 $ e max. 10 $ per ogni dato input. Sarebbe sospetto se all'improvviso ne avessi milioni sul tuo account. Non devi preoccuparti dell'imprecisione in virgola mobile, ma puoi usarla per aumentare i tuoi soldi.

Ogni utente svolge il ruolo di supervisore.
Se il trucco è difficile da individuare, vota la risposta.


1
Cosa intendi con denaro gratis?
Ottimizzatore,

19
Penso che il fatto che tu stia usando tipi a virgola mobile per archiviare la quantità di denaro in ciascun conto è abbastanza subdolo.
Martin Ender,

2
Penso che funzionerebbe molto meglio con un database iniziale molto più ampio e un insieme di input di test di esempio o un programma per generare input di test. Dobbiamo anche sapere cosa è in grado di rilevare il capo.
millinon

2
@millinon Credo che l'obiettivo finale sia quello di ottenere denaro con qualsiasi metodo, ma farlo in modo tale che nessuno si accorga della differenza. "Non devi" rubare "i soldi da quei conti. Puoi" generare "i soldi per il tuo conto semplicemente aumentandoli in qualche modo nel tuo codice."
Xrylite,

3
Sto votando per chiudere questa domanda come fuori tema perché le sfide subdole non sono più in argomento su questo sito. meta.codegolf.stackexchange.com/a/8326/20469
cat

Risposte:


3

Ho cercato di emulare le caratteristiche dei grandi sistemi del mondo reale qui. Uso l'incapsulamento e l'astrazione per gestire le diverse operazioni nel database, come ottenere un saldo del conto e trasferire denaro. Il codice ha anche una suite di test di base per tali funzioni. Tuttavia, un programmatore ha approfittato delle recenti modifiche ai requisiti del progetto per aggiungere $ 1 al proprio account ad ogni input. C'è persino una negabilità plausibile.

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

Ed ecco un esempio:

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 $

Senza nemmeno guardare il resto del codice, immagino abbia a che fare con odb che è un dizionario vuoto.
Joe Z.

Okay ho capito. Poiché odb è vuoto ma ancora dichiarato, la riga finale della procedura di test non genera un errore, ma aggiorna odb in silenzio invece di ripristinare i valori pre-test su ndb come dovrebbe. Per questo motivo, tutte le modifiche ai test vengono impegnate in ndb e, come tale, all'account 123456 (che è l'hash jSWlMM) viene accreditato un dollaro ogni volta che viene eseguito il codice.
Joe Z.

E la plausibile negabilità viene dal commento del venerdì pomeriggio in cui avrebbe potuto perdere la finale odbper tentarselo db. Tuttavia, è scivolato lassù in quel 20 ottobre non era affatto venerdì - in effetti, era lunedì e la settimana era appena iniziata. In ogni caso, penso che questo collega RJO avrebbe bisogno di un serio controllo del codice per eseguire i test su un database di produzione, anche se li ha riscritti subito dopo.
Joe Z.

@Joe Z Haha, sì, spostare i soldi "proprio come un test" è una pessima idea in codice reale. Stavo cercando di trovare un modo plausibile per farlo db[hash('jSWlMM')] += 1. Ho preso in considerazione l'idea di nominare una variabile jSWlMMe di "casualmente" citarla in qualche modo, ma è molto più difficile da fare in Python rispetto a PHP (dove lasciare il $sigillo trasforma la variabile in una costante indefinita, che viene quindi trattata come una stringa letterale).
Remy,

È stato divertente cercare di guardare attraverso le cose, però, te lo darò.
Joe Z.

1

Che dire di questo ?

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

Test:

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 (ultima chiamata più recente): file "test.py", riga 12, nel <modulo> conteggio [-1] + = 1 TypeError: impossibile concatenare gli oggetti 'str' e 'int'
ErlVolton

1
Ho anche ricevuto un errore lì. Ciò si basa sull'ordinamento di un dizionario, che è (per quanto ne so) un comportamento indefinito in Python.
Emil,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.