Niewłaściwe konto bankowe [zamknięte]

13

Pracujesz jako programista dla banku.
Twoim zadaniem jest napisanie programu obsługującego transakcje z jednego konta bankowego na drugie.

Program powinien wykonać następujące czynności:

  • Uruchom w nieskończonej pętli, czekając na dane wejściowe.
    Dane wejściowe składają się z 3 liczb:
    Numer konta 1, Numer konta 2 i x ilość pieniędzy.
    np. 999222 777333 500
  • Sprawdź, czy numery kont i x są prawidłowe.
    Dane wejściowe są prawidłowe, jeśli numery kont nie są takie same i istnieją w bazie danych, a x jest większe od zera,
  • Przelej pieniądze z konta 1 na konto 2, ale tylko wtedy, gdy konto 1 ma wystarczającą ilość pieniędzy.
    Konta nie mogą być przeczone.
  • Jeśli wszystko pójdzie dobrze, wydrukuj coś w stylu „Przeniesiono x $ z numeru 1 na numer 2”
  • jeśli coś pójdzie nie tak, na przykład dlatego, że numery kont są nieprawidłowe, wydrukuj komunikat o błędzie.
  • Zatrzymaj, jeśli wartością wejściową jest 0

Baza danych zawiera następujące konta bankowe:

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

Prosty przykład 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:
Twój numer konta bankowego to 123456.
Masz dokładnie 0,0 $ na koncie.
Chcesz to zmienić, manipulując swoim programem:
Program powinien zrobić dokładnie to, co powinien, ale także przelać trochę darmowych pieniędzy na twoje konto.

Musisz jednak uważać. Twój przełożony spojrzy na twój kod i nie będzie zadowolony, jeśli zobaczy coś podejrzanego. Wie o standardowych otworach pętli , więc nawet nie próbuj.
Ponadto pieniądze, które sam sobie przekażesz, nie powinny być zbyt duże. Byłoby podejrzane, gdyby twoje pieniądze rosły zbyt szybko. Nie bądź chciwy.

Twój kod powinien być tak prosty i przejrzysty, jak to możliwe, staraj się unikać dużego zaciemnienia.

To konkurs popularności, wygrywa odpowiedź z największą popularnością.

Uwaga: proszę podać saldo każdego konta na końcu programu, abyśmy mogli zobaczyć, ile pieniędzy zarobiłeś ciężką pracą (po prostu, aby pokazać, że Twój program rzeczywiście coś zrobił).

EDYCJA: Wyjaśnienie
Wyzwaniem nie jest napisanie programu, który poradziłby sobie z dużą bazą danych i dużą liczbą transakcji. Wyzwanie polega na tym, aby program wyglądał tak, jakby robił tylko to, co powinien, ale w rzeczywistości nie.

Na przykład, jeśli dane wejściowe to 999222 777333 500:
Następnie dodaj, jeśli to możliwe, 500 do konta 777333 i odejmij 500 od konta 999222. Nie musisz „kraść” pieniędzy z tych kont. Możesz „wygenerować” pieniądze na swoje konto, po prostu zwiększając je w kodzie.
Ile zależy od Ciebie, ale możesz założyć, że chcesz zarobić co najmniej 0,1 $ i maks. 10 $ za każde dane wejściowe. Byłoby podejrzane, gdybyś nagle miał na koncie miliony. Nie musisz się martwić niedokładnością zmiennoprzecinkową, ale możesz użyć jej do zwiększenia swoich pieniędzy.

Każdy użytkownik odgrywa rolę przełożonego.
Jeśli trik jest trudny do zauważenia, głosuj na odpowiedź.

Markuz
źródło
1
Co rozumiesz przez darmowe pieniądze?
Optymalizator
19
Myślę, że fakt, że używasz typów zmiennoprzecinkowych do przechowywania kwoty pieniędzy na każdym koncie, jest wystarczająco niedoceniany.
Martin Ender
2
Myślę, że działałoby to znacznie lepiej w przypadku znacznie większej początkowej bazy danych oraz zestawu przykładowych danych wejściowych testowych lub programu do generowania danych wejściowych testowych. Musimy także wiedzieć, co szef jest w stanie wykryć.
millinon
2
@millinon Uważam, że ostatecznym celem jest zdobycie pieniędzy dowolną metodą, ale zrobienie tego w taki sposób, aby nikt nie zauważył różnicy. „Nie musisz„ kraść ”pieniędzy z tych kont. Możesz„ wygenerować ”pieniądze na swoje konto, po prostu zwiększając je w kodzie.”
Xrylite,
3
Głosuję za zamknięciem tego pytania jako nie na temat, ponieważ słabe wyzwania nie są już na ten temat na tej stronie. meta.codegolf.stackexchange.com/a/8326/20469
kot

Odpowiedzi:

3

Próbowałem tutaj emulować funkcje dużych systemów w świecie rzeczywistym. Używam enkapsulacji i abstrakcji do obsługi różnych operacji w bazie danych, takich jak uzyskiwanie salda konta i przesyłanie pieniędzy. Kod ma również podstawowy zestaw testów dla tych funkcji. Jednak jeden programista wykorzystał ostatnie zmiany w wymaganiach projektu, aby dodać 1 USD do swojego konta przy każdym wejściu. Istnieje nawet prawdopodobna zaprzeczalność.

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

A oto przykładowy przebieg:

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
źródło
Nie patrząc nawet na resztę kodu, domyślam się, że ma to coś wspólnego z odb jest pustym słownikiem.
Joe Z.
OK, rozumiem Ponieważ odb jest pusty, ale nadal deklarowany, ostatni wiersz w teście testowym nie generuje błędu - po prostu aktualizuje odb po cichu zamiast przywracania wartości wstępnego testowania do ndb, tak jak powinien. Z tego powodu wszystkie zmiany testowe zostają przypisane do ndb, i dlatego konto 123456 (które jest skrótem jSWlMM) otrzymuje jeden dolar za każdym razem, gdy kod jest uruchamiany.
Joe Z.
A prawdopodobna zaprzeczalność wynika z komentarza z piątkowego popołudnia, w którym mógł przegapić finał, odbaby to zaryzykować db. Jednak poślizgnął się tam, że 20 października wcale nie był piątek - w rzeczywistości był poniedziałek i tydzień właśnie się zaczął. Jeśli o to chodzi, myślę, że ten gość z RJO potrzebowałby poważnego audytu kodu w celu uruchomienia testów w produkcyjnej bazie danych, nawet jeśli zaraz potem je odpisał.
Joe Z.
@Joe Z Haha, tak, przenoszenie pieniędzy na „tak jak test” to naprawdę zły pomysł w prawdziwym kodzie. Próbowałem wymyślić wiarygodny sposób db[hash('jSWlMM')] += 1. Zastanawiałem się nad nazwaniem zmiennej jSWlMMi „przypadkowym” jej zacytowaniem, ale w Pythonie jest to o wiele trudniejsze niż PHP (gdzie pominięcie $sigil zmienia zmienną w niezdefiniowaną stałą, która jest następnie traktowana jako dosłowny ciąg znaków).
Remy
Fajnie było przeglądać różne rzeczy, ale dam ci to.
Joe Z.
1

A co z tym ?

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
Alain Tésio
źródło
Traceback (ostatnie ostatnie wywołanie): plik „test.py”, wiersz 12, w liczeniu <module> [-1] + = 1 TypeError: nie można
połączyć
1
Tam też pojawia się błąd. Polega to na uporządkowaniu słownika, co jest (o ile wiem) niezdefiniowanym zachowaniem w Pythonie.
Emil