Golf en el banco

11

Nuestro nuevo banco necesita un sistema de transacciones de cajero, pero hay un problema. Solo quedan unos pocos cientos de bytes de espacio en nuestro servidor, por lo que tendrá que escribir un código muy compacto.

Base de datos

Afortunadamente, nuestra base de datos es muy simple (fue construida por el hijo del alumno de nuestro presidente del banco), y hasta ahora solo tenemos unos pocos clientes.

el archivo Bank.dataes:

Account Firstname Lastname Balance Date
123 Maree Jones 346.22 2014-12-13
035 Thomas Breakbone 3422.02 2015-01-03
422 Henrietta Throsby-Borashenko 277847.74 2014-11-21
501 Timmy Bongo 7.95 2014-11-04
105 William Greene 893.00 2015-01-06
300 Mary Galoway 1228.73 2014-12-28
203 Samantha Richardson 2055.44 2014-11-01
151 Bruce Wayne 956119.66 2014-10-09
166 Chip Stonesmith 266.71 2014-12-15
888 Alexandria Cooper 1299.82 2014-12-30

Especificación de la aplicación

Nuestra aplicación bancaria debe implementar los siguientes comandos:

open <firstname> <lastname> Crea (abre) una nueva cuenta que imprime un número de cuenta único de 3 dígitos.

withdraw <account> <amount> Retirar el monto de una cuenta.

deposit <account> <amount> Deposite la cantidad en una cuenta.

close <account> Cerrar cuenta si está vacía.

report <fieldname> Imprima un informe de la base de datos ordenado por nombre de campo. Mueva la columna de nombre de campo a la primera posición. El ancho de cada columna será el máximo de los datos más amplios y el ancho del nombre del campo, separados por un espacio. La primera línea serán los títulos de campo. Los saldos solo deben justificarse correctamente con un $signo inicial.

print <account> Imprima los nombres de campo y registre para esta cuenta formateada como el informe.

Cada vez que se cambia un registro, el Datecampo en el registro debe actualizarse a la fecha actual.

La aplicación mostrará un mensaje "#" al esperar un comando. Si falla un comando (como una operación en una cuenta desconocida o fondos insuficientes), la aplicación debe imprimir el mensaje de error informativo "fallido". El programa debe volver a escribir los cambios en el archivo después de cada cambio, y leer el archivo en cada comando, ya que hay muchos programas de cajeros en todo el mundo que operan en el archivo simultáneamente (no necesitamos bloqueo de archivo, eso puede reducir el rendimiento).

EDITAR: Los campos de cadena son ASCII simples (az, AZ, -) sin espacios en blanco y la cantidad siempre estará entre 0.00 y 1000000000.00 (1,000 millones) de dólares con 2 decimales que indican centavos. La fecha será en hora local en cada sucursal (una solución simple, pero puede dar lugar a algunos problemas más adelante ...).

Salida

Las respuestas deberán demostrar que cumplen con la especificación. Adjunte la salida de su programa después de procesar los siguientes comandos:

report Balance
open Clark Kent
print 001
deposit 001 4530
withdraw 105 893
close 105
report Date

Asegúrese de utilizar una copia original del Bank.dataarchivo proporcionado anteriormente.

Puntuación

Este es el código de golf, por lo que su puntaje será el recuento de bytes de su código. Las lagunas estándar están prohibidas.

Caballero Lógico
fuente
¿Debería ser una forma de salir del programa?
bacchusbeale
No queremos incluir demasiadas funciones en esta aplicación ;-) Una salida de tipo control-C está bien.
Logic Knight el
¿Qué restricciones se pueden asumir sobre los caracteres en <firstname>y <lastname>y el rango y precisión de <amount>? (Por ejemplo, puede haber algunas optimizaciones que son posibles si <amount>siempre tiene exactamente dos decimales, o es posible que desee que el programa sea utilizable por la rama del Medio Oriente, donde la mayoría de las monedas usan tres decimales).
Peter Taylor
Gracias Peter He agregado algunas cláusulas sobre el tipo de cadena y el rango de cantidad como se sugiere.
Logic Knight
Tal vez debería haber sido más explícito en mi pregunta sobre los nombres. La restricción más útil sería eso <firstname>y <lastname>ambos solo se usan a-zA-Z, pero incluso una simple declaración de que nunca contienen caracteres de tabulación permite usar TSV. Si pudieran ser cualquier secuencia de caracteres ASCII, es necesaria alguna forma de escape o delimitación que no sea con un delimitador de un carácter.
Peter Taylor

Respuestas:

1

Rubí, 918

Esta pregunta es bastante larga para el golf, ya que consta de muchas partes pequeñas. Por un momento, casi quise definir algunas clases adicionales para hacer las cosas más ordenadas con polimorfismo, etc. (pero al final no lo hice).

l=->a,i{a.map{|x|x[i].to_s.size}.max}
y=1..-1
d=File.open(f="bank.data").each.map(&:split)
j=[k=%w{Account Firstname Lastname Balance Date}]
_=->{puts"Failure"}
q=->t,v=0{z=-1;puts t.map{|r|([v]+((0..4).to_a-[v])).map{|c|b=l[t,c];c!=3?r[c].ljust(b):(?$*(z+=z<1?1:0)+r[c]).rjust(b>7?b+1:b)}*' '}}
w=->d{File.open(f,?w).write(d.map{|x|x*' '}*?\n)}
s=->i,m=!0{o=d.select{|r|r[0]==i};o==[]?_[]:m ?q[[k]+o]:1}
u=->{Time.now.to_s[0..9]}
($><<"# ";i=gets.split;o=i.size;("report"==h=i[0])?((v=k.index i[1])?q[j+d[y].sort_by{|x|v!=3?x[v]:x[v].to_f},v]:_[]):h=="print"?s[i[1],0]:h=="close"?(s[m=i[1]]?w[d=j+d[y].select{|r|r[0]!=m}]:0):h=="open"?((o==3&&t=((1..999).map{|x|'%03d'%x}-d.map{|x|x[0]})[0])?(w[d=d+[[t,i[1],i[2],'0.00',u[]]]];puts t):_[]):h=="withdraw"||h=="deposit"?(o==3&&s[i[1]]?w[d=j+d[y].map{|r|i[1]==r[0]?(b=(c=r[3].to_f)+i[2].to_f*(i[0][0]==?w?-1:1);0>b&&(b=c;_[]);r[0..2]+["%.2f"%b,u[]]):r}]:_[]):_[])while 1

Probablemente se pueda jugar más al golf. Pero a partir de ahora, ni siquiera puedo seguir lo que hice en la última línea.

Salida:

# report Balance
   Balance Account Firstname  Lastname           Date      
     $7.95 501     Timmy      Bongo              2014-11-04
   $266.71 166     Chip       Stonesmith         2014-12-15
   $346.22 123     Maree      Jones              2014-12-13
   $893.00 105     William    Greene             2015-01-06
  $1228.73 300     Mary       Galoway            2014-12-28
  $1299.82 888     Alexandria Cooper             2014-12-30
  $2055.44 203     Samantha   Richardson         2014-11-01
  $3422.02 035     Thomas     Breakbone          2015-01-03
$277847.74 422     Henrietta  Throsby-Borashenko 2014-11-21
$956119.66 151     Bruce      Wayne              2014-10-09
# open Clark Kent
001
# print 001
Account Firstname Lastname Balance Date      
001     Clark     Kent       $0.00 2015-02-01
# deposit 001 4530
# withdraw 105 893
# close 105
# report Date
Date       Account Firstname  Lastname              Balance
2014-10-09 151     Bruce      Wayne              $956119.66
2014-11-01 203     Samantha   Richardson           $2055.44
2014-11-04 501     Timmy      Bongo                   $7.95
2014-11-21 422     Henrietta  Throsby-Borashenko $277847.74
2014-12-13 123     Maree      Jones                 $346.22
2014-12-15 166     Chip       Stonesmith            $266.71
2014-12-28 300     Mary       Galoway              $1228.73
2014-12-30 888     Alexandria Cooper               $1299.82
2015-01-03 035     Thomas     Breakbone            $3422.02
2015-02-01 001     Clark      Kent                 $4530.00
#
Vectorizado
fuente
Sería muy útil si pudiera agregar una muestra de la salida del programa (vea la pregunta actualizada). Gracias.
Logic Knight
Sé que esto es un subproducto del resaltado de sintaxis mal aplicado, pero las cantidades en dólares se ven muy bien con los números enteros en negro y los centavos en rojo pálido.
Joe Z.
2

T-SQL 1919

Llamado con "exec q 'Su comando aquí'" No creo que T-SQL pueda realmente obtener la entrada del usuario, por lo que creo que esto es lo más cercano posible.

Utiliza la utilidad bcp para E / S que no he probado antes porque viene con SQL Server 2014.

No estoy seguro de si sería mejor o peor usar solo el procedimiento almacenado principal y poner el resto del código allí.

CREATE PROC q @ CHAR(99)AS
CREATE TABLE ##(A CHAR(3),F CHAR(99),L CHAR(99),B MONEY,D DATE)bcp ## in Bank.data -t " " -T
DECLARE @g INT,@w MONEY,@z CHAR(9),@y CHAR(99),@x CHAR(99)SET @g=patindex('% %',@)SET @z=substring(@,1,@g-1)SET @=substring(@,@g+1,99)SET @g=patindex('% %',@)SET @y=substring(@,1,@g-1)SET @=substring(@,@g+1,99)SET @g=patindex('% %',@)SET @x=substring(@,1,@g-1)SET @w=CONVERT(MONEY,@x)*2*(LEN(@z)-7.5)IF @z='open'exec o @y,@x
IF @z='close'exec c @y
IF @z='withdraw'exec w @y,@w
IF @z='deposit'exec w @y,@w
IF @z='print'exec p @y
IF @z='report'exec r @y
bcp ## out Bank.data -t " " -T
SELECT'#'
CREATE PROC r @q CHAR(9)AS
DECLARE @a char(9)='A Account',@f char(11)='F Firstname',@l char(10)='L Lastname',@b char(45)='CONCAT(''$'',SPACE(9-LEN(B)),B) Balance',@d char(6)='D Date',@ varchar(999)='SELECT '
IF @q='Account'SET @+=@a+','+@f+','+@l+','+@b+','+@d
IF @q='Balance'SET @+=@b+','+@a+','+@f+','+@l+','+@d
IF @q='Date'SET @+=@d+','+@a+','+@f+','+@l+','+@b
IF @q='Lastname'SET @+=@l+','+@a+','+@f+','+@b+','+@d
IF @q='Firstname'SET @+=@f+','+@a+','+@l+','+@b+','+@d
IF LEN(@)<9
BEGIN
SELECT'failed'RETURN
END
SET @+=' FROM ## ORDER BY '+@q
exec(@)CREATE PROC p @ CHAR(3)AS
DECLARE @r CHAR(9)=(SELECT 1 FROM ## WHERE A=@)IF @r IS NULL SELECT'failed'ELSE SELECT*FROM ## WHERE A=@
CREATE Proc o @f CHAR(99),@l CHAR(99)AS
DECLARE @ INT=0,@r CHAR(9)=(SELECT 1 FROM # WHERE A='000')WHILE @r IS NOT NULL
BEGIN

SET @+=1
SET @r=(SELECT 1 FROM # WHERE CONVERT(INT,A)=@)END
IF @>999 SELECT'failed'ELSE INSERT INTO # OUTPUT Inserted.A VALUES(REPLICATE('0',3-LEN(@))+CONVERT(CHAR(3),@),@f,@l,0,GETDATE())CREATE PROC w @ CHAR(3),@b MONEY AS
DECLARE @r CHAR(9)=(SELECT 1 FROM ## WHERE A=@ AND B>@b)IF @r IS NULL SELECT'failed'ELSE UPDATE ## SET B=B-@b,D=GETDATE()WHERE A=@
CREATE Proc c @q CHAR(3)AS
DECLARE @r CHAR(9)=(SELECT 1 FROM ## WHERE A=@q AND B=0)IF @r IS NULL SELECT'failed'ELSE DELETE FROM ## WHERE A=@q
comentarios
fuente
Sería muy útil si pudiera agregar una muestra de la salida del programa (vea la pregunta actualizada). Gracias.
Logic Knight
2

Cobra - 1505

class P
    var m='Account Firstname Lastname Balance Date'
    def main
        while[d=DateTime.now.toString('yyyy-MM-dd'),z='0.00']
            print'#'stop
            try,branch (c=Console.readLine.split)[r=0]
                on'open'
                    post while u in for x in.f get x[0],u=(r+=1).toString('000')
                    print u
                    .f=.f.toList+[@[u,c[1],c[2],z,d]]
                on'deposit'or 'withdraw'
                    n=.z(if(c[0]>'deposit','-','')+c[2])
                    assert.z(.i(c[1])[3])+n>=0
                    .f=for x in.f get if(x[0]==c[1],@[x[:3].join(' '),'[(.z(x[3])+n).toString(z)]',d],x)
                on'close'
                    assert.i(c[1])[3]==z
                    .f=for x in.f where.i(c[1])<>x
                on'report',.a(.f,c[1])
                on'print',.a([.i(c[1])])
                else,assert 0
            catch
                print'failed'
    def z(s='')as float
        return float.parse(s)
    pro f as String[]?*
        get
            return for x in File.readAllLines('Bank.data')[1:]get x.split
        set
            File.writeAllLines('Bank.data',[.m]+for x in value get x.join(' '))
    def a(f as String[]?*,c='Account')
        i,l=(m=.m.split).toList.indexOf(c),[7,9,8,8,4]
        assert c in m
        print (for q in (for z in (for x in[m]+f.toList.sorted(do(a as String[],b as String[]))get for y in 5 get[t=try' '.repeat(l[y]-x[y].length)catch get'',if(y-3,x[y]+t,t+if(x==m,' ','$')+x[y])][1])get[z[i]]+for p in z where p<>z[i])get q.join(' ')).join('\n')
            for v in[a,b],for k in 5,if (u=v[k].length)>l[k],l[k]=u
            return[d=a[i].compareTo(b[i]),d,d,.z(a[3]).compareTo(.z(b[3])),DateTime.parse(a[4]).compareTo(DateTime.parse(b[4]))][i]
    def i(s='')as String[]?
        return (for x in.f where x[0]==s)[0]

Salida:

#report Balance
   Balance Account Firstname  Lastname           Date      
     $7.95 501     Timmy      Bongo              2014-11-04
   $266.71 166     Chip       Stonesmith         2014-12-15
   $346.22 123     Maree      Jones              2014-12-13
   $893.00 105     William    Greene             2015-01-06
  $1228.73 300     Mary       Galoway            2014-12-28
  $1299.82 888     Alexandria Cooper             2014-12-30
  $2055.44 203     Samantha   Richardson         2014-11-01
  $3422.02 035     Thomas     Breakbone          2015-01-03
$277847.74 422     Henrietta  Throsby-Borashenko 2014-11-21
$956119.66 151     Bruce      Wayne              2014-10-09
#open Clark Kent
001
#print 001
Account Firstname Lastname   Balance Date
001     Clark     Kent         $0.00 2015-02-04
#deposit 001 4530
#withdraw 105 893
#close 105
#report Date
Date       Account Firstname  Lastname              Balance
2014-10-09 151     Bruce      Wayne              $956119.66
2014-11-01 203     Samantha   Richardson           $2055.44
2014-11-04 501     Timmy      Bongo                   $7.95
2014-11-21 422     Henrietta  Throsby-Borashenko $277847.74
2014-12-13 123     Maree      Jones                 $346.22
2014-12-15 166     Chip       Stonesmith            $266.71
2014-12-28 300     Mary       Galoway              $1228.73
2014-12-30 888     Alexandria Cooper               $1299.82
2015-01-03 035     Thomas     Breakbone            $3422.02
2015-02-04 001     Clark      Kent                 $4530.00
Οurous
fuente
Gracias por tu entrada. Tuve que buscar a Cobra para ver qué era. Tal vez sea hora de que aprenda otro idioma.
Logic Knight el
Sería muy útil si pudiera agregar una muestra de la salida del programa (vea la pregunta actualizada). Gracias.
Logic Knight
@CarpetPython se realizará esta tarde.
Οurous
1

Python 2 - 2205 bytes

Aquí hay un intento bastante detallado de encontrar una solución.

import sys, time, re
def db(recs):
    text = '\n'.join(' '.join(row) for row in [titles]+recs)
    open('Bank.data', 'wt').write(text+'\n')
def wid(col, recs):
    w = max(len(r[col]) for r in [titles]+recs)
    return w if col == 3 else -w
while 1:
    inp=raw_input('# ').split()
    try:
        cmd = inp.pop(0)
        data = [d.split() for d in open('Bank.data', 'rt').readlines()]
        titles = data.pop(0)
        today = '-'.join('%02u' % v for v in time.localtime()[:3])
        alist = set(int(r[0]) for r in data)
        if cmd == 'open':
            assert re.match(r'[-a-zA-Z]{2,}', inp[0]+inp[1])
            acct = '%03u'%([n for n in range(1, 1000) if n not in alist][0])
            rec = [acct] + inp + ['0.00', today]
            db(data+[rec])
            print acct
        elif cmd == 'withdraw':
            a, m = inp[0], float(inp[1])
            rec = [r for r in data if r[0] == a][0]
            b = float(rec[3])
            assert b >= m
            rec[3] = '%.2f' % (b-m)
            rec[4] = today
            db(data)
        elif cmd == 'deposit':
            a, m = inp[0], float(inp[1])
            rec=[r for r in data if r[0]==a][0]
            rec[3]='%.2f'%(float(rec[3])+m)
            rec[4]=today
            db(data)
        elif cmd=='close':
            rec=[r for r in data if r[0]==inp[0]][0]
            assert int(rec[3])==0
            data=[r for r in data if r!=rec]
            db(data)
        elif cmd=='report':
            for r in data: r[3]='$'+r[3]
            fmtlist=['%'+str(wid(c,data))+'s' for c in range(5)]
            loc=titles.index(inp[0])
            for r in data: r.insert(0,r.pop(loc))
            data.sort(key=lambda x: float(x[0][1:]) if loc==3 else x[0])
            titles.insert(0,titles.pop(loc))
            fmtlist.insert(0,fmtlist.pop(loc))
            for r in [titles]+data: print ' '.join(fmtlist)%tuple(r)
        elif cmd=='print':
            for r in data: r[3]='$'+r[3]
            rec=[r for r in data if r[0]==inp[0]][0]
            fmt=' '.join('%'+str(wid(c,[rec]))+'s' for c in range(5))
            for r in [titles,rec]: print fmt%tuple(r)
        else: raise()
    except:
        print 'failed'

Aquí hay una muestra de la aplicación en uso:

# report Balance
   Balance Account Firstname  Lastname           Date      
     $7.95 501     Timmy      Bongo              2014-11-04
   $266.71 166     Chip       Stonesmith         2014-12-15
   $346.22 123     Maree      Jones              2014-12-13
   $893.00 105     William    Greene             2015-01-06
  $1228.73 300     Mary       Galoway            2014-12-28
  $1299.82 888     Alexandria Cooper             2014-12-30
  $2055.44 203     Samantha   Richardson         2014-11-01
  $3422.02 035     Thomas     Breakbone          2015-01-03
$277847.74 422     Henrietta  Throsby-Borashenko 2014-11-21
$956119.66 151     Bruce      Wayne              2014-10-09
# open Clark Kent
001
# print 001
Account Firstname Lastname Balance Date      
001     Clark     Kent       $0.00 2015-01-13
# deposit 001 4530
# withdraw 105 893
# close 105
# report Date
Date       Account Firstname  Lastname              Balance
2014-10-09 151     Bruce      Wayne              $956119.66
2014-11-01 203     Samantha   Richardson           $2055.44
2014-11-04 501     Timmy      Bongo                   $7.95
2014-11-21 422     Henrietta  Throsby-Borashenko $277847.74
2014-12-13 123     Maree      Jones                 $346.22
2014-12-15 166     Chip       Stonesmith            $266.71
2014-12-28 300     Mary       Galoway              $1228.73
2014-12-30 888     Alexandria Cooper               $1299.82
2015-01-03 035     Thomas     Breakbone            $3422.02
2015-01-13 001     Clark      Kent                 $4530.00
# 
Caballero Lógico
fuente
1

Lote - 1827

Batch no está diseñado para este tipo de cosas.

@echo off&setLocal enableDelayedExpansion&set B=Bank.data&echo wscript.echo eval(wscript.arguments(0))>%temp%\eval1.vbs&set Z=goto :EOF&set V=call&set F=for /l %%a in (1,1,
:m
set C=-1&set D=%date:~-4%-%date:~-7,2%-%date:~-10,2%
for /f "tokens=1-5" %%a in (%B%)do set/aC+=1 &set !C!=%%a %%b %%c %%d %%e&set !C!n=%%a&set !C!f=%%b&set !C!s=%%c&set !C!b=%%d&set !C!d=%%e&set A=%%a&set/aA+=1
set/pI="#"
%V% :%I% 2>nul||echo failed&goto m
goto m
:open
echo %A% %1 %2 0.00 %D%>>%B%&echo %A%&%Z%
:close
echo !0!>%B%&%F%!C!)do if "!%%an!" NEQ "%1" (echo !%%a!>>%B%)else if !%%ab! GTR 0.00 echo failed & echo !%%a!>>%B%
%Z%
:deposit
%F%!C!)do if "!%%an!"=="%1" set p=%%a
%V% :c "!%p%b!+%2"
set %p%b=%r%&set %p%d=%D%&%V% :u
%Z%
:withdraw
%F%!C!)do if "!%%an!"=="%1" set p=%%a
%V% :c "!%p%b!-%2"&if "%r:~0,1%"=="-" echo failed&%Z%
set %p%b=%r%&set %p%d=%D%&%V% :u
%Z%
:report
for /l %%a in (1,1,50)do set H= !H!
for /l %%a in (0,1,!C!)do (
%V% :l !%%an!&set %%anl=!l!&if !l! GTR !tn! set/atn=!l!
%V% :l !%%af!&set %%afl=!l!&if !l! GTR !tf! set/atf=!l!
%V% :l !%%as!&set %%asl=!l!&if !l! GTR !ts! set/ats=!l!
%V% :l !%%ab!&set %%abl=!l!&if !l! GTR !tb! set/atb=!l!
)
for /l %%a in (0,1,!C!)do %V% :c "%tn%-!%%anl!"&set sn=!r:~0,-3!&%V% :t !sn!&set pn=!x!&%V% :c "%tf%-!%%afl!"&set sf=!r:~0,-3!&%V% :t !sf!&set pf=!x!&%V% :c "%ts%-!%%asl!"&set ss=!r:~0,-3!&%V% :t !ss!&set ps=!x!&%V% :c "%tb%-!%%abl!"&set sb=!r:~0,-3!&%V% :t !sb!&set pb=!x!&echo !%%an!!pn! !%%af!!pf! !%%as!!ps! !pb!$!%%ab! !%%ad!
%Z%
:l
set S=%1&for /f usebackq %%a in (`Powershell "'!S!'.Length"`)do set l=%%a
%Z%
:t
set x=!H:~0,%1!
%Z%
:u
echo !0!>%B%&%F%!C!)do echo !%%an! !%%af! !%%as! !%%ab! !%%ad!>>%B%&%Z%
:c
for /f %%a in ('cscript //nologo %temp%\eval1.vbs "round(%1,2)"')do set r=%%a
if "%r:~-3,1%" NEQ "." set r=%r%.00

Sin embargo, implementar las funciones Ordenar (dentro del informe) e Imprimir.

carne sin carne
fuente
Sería muy útil si pudiera agregar una muestra de la salida del programa (vea la pregunta actualizada). Gracias.
Logic Knight
1

STATA 1506

No traté de jugar al golf demasiado. Pensé que un lenguaje estadístico sería mejor para esto, pero aparentemente.

set more off
while 1<2{
qui insheet using Bank.data,delim(" ")clear case
form A %-03.0f
form B %10.2f
form D %-10s
form F %-50s
form L %-50s
g K="$"+string(B,"%10.2f")
di"#",_r(q)
loc s: di %tdCCYY-NN-DD date(c(current_date),"DMY")
if word("$q",1)=="open"{
forv x=0/999{
egen c=anymatch(A),v(`x')
if c<1{
egen m=min(A)
cap expand 2 if A==m,gen(z)
replace A=`x' if A==m&z>0
replace B=0 if A==`x'
replace F=word("$q",2) if A==`x'
replace L=word("$q",3) if A==`x'
replace D="`s'" if A==`x'
di"`x'"
outsheet A-D using Bank.data,delim(" ")replace
continue, br
}
if `x'==999{
di"failed"
}
drop c
}
continue
}
if word("$q",1)=="report"{
ren B R
ren K Balance
if word("$q",2)=="Account"{
so A
l A-L B D,clean noo
}
else if word("$q",2)=="Date"{
so D
l D A-L B,clean noo
}
else if word("$q",2)=="Lastname"{
so L
l L A F B D,clean noo
}
else if word("$q",2)=="Balance"{
so R
l B A-L D,clean noo
}
else if word("$q",2)=="Firstname"{
so F
l F A L B D,clean noo
}
else{
di"failed"
}
continue
}
gen i=real(word("$q",2))
egen p=min(abs(A-i))
if p>0{
di"failed"
continue
}
if word("$q",1)=="close"{
egen c=count(i)
drop if A==i&B==0
qui cou
if c==r(N){
di"failed"
continue
}
}
if word("$q",1)=="print"{
drop Balance
ren K Balance
l A-L B D if A==i,noo clean ab(9)
continue
}
gen j=real(word("$q",3))
if word("$q",1)=="withdraw"{
replace B=B-j if A==i
egen c=min(B)
if c<0{
di"failed"
continue
}
}
if word("$q",1)=="deposit"{
replace B=B+j if A==i
}
replace D="`s'" if A==i
outsheet A-D using Bank.data,delim(" ")replace
}
comentarios
fuente
Sería muy útil si pudiera agregar una muestra de la salida del programa (vea la pregunta actualizada). Gracias.
Logic Knight
1

C # - 1952 1883

Mostraré algo de salida cuando llegue mañana. Por ahora, aquí está la presentación:

using System;using System.Collections.Generic;using System.IO;using System.Linq;using S=System.String;using O=System.Func<dynamic,string,string>;class I{char[]c={' '};Action<string>w;Func<S,S,S,S,S,dynamic>n;Func<string>N;List<dynamic>T;private static void Main(string[]a){while(true){Console.Write("# ");new I().Parse(Console.ReadLine());}}I(){w=Console.WriteLine;n=(g,h,i,j,k)=>new{a=g,f=h,l=i,b=j,d=k};N=()=>DateTime.Now.ToString("yyyy-MM-dd");}List<dynamic>G(){return File.ReadAllLines("test.data").Select(l=>l.Split(c)).Select(ac=>n(ac[0],ac[1],ac[2],ac[3],ac[4])).ToList();}void W(){File.WriteAllLines("test.data",T.Select(a=>(S)(a.a+" "+a.f+" "+a.l+" "+a.b+" "+a.d)));}void Parse(string inp){var C=true;try{Func<object,float>v=Convert.ToSingle;Func<string,bool>s=string.IsNullOrEmpty;var i=inp.Split(c);T=G();Func<S,int>F=m=>T.IndexOf(T.FirstOrDefault(a=>a.a==m));C=!s(i[1]);var g=F(i[1]);switch(i[0]){case"open":if(C){int an=0;var cs="000";while(T.Any(A=>cs==A.a)){an++;cs=an.ToString("D3");}T.Add(n(cs,i[1],i[2],"0.00",N()));w(cs);}break;case"withdraw":case"deposit":var D=i[0]=="deposit";C=(D||v(T[g].b)>=v(i[2]));var ba=(v(T[g].b)+v(i[2])*(D?1:-1)).ToString("F");if(C)T[g]=n(T[g].a,T[g].f,T[g].l,ba,N());break;case"close":C=g>-1&&v(T[g].b)<=0;if(C)T.RemoveAt(g);break;case"report":case"print":var X=i[0]=="print";var B=1;O o=(x,p)=>((Type)x.GetType()).GetProperty(p).GetValue(x);O K=(k,j)=>{var r=(j=="b"?"$":"");var P=T.Max(_=>(o(_,j)).Length);return r==""?(o(k,j)).PadRight(P):((B<1?r:"")+(o(k,j))).PadLeft(P+1);};var q=i[1];Action<dynamic,S>U=(u,t)=>{S l=""; foreach(var h in t)l+=K(u,h.ToString())+" "; w(l);};q=q=="Account"?"a":q=="Firstname"?"f":q=="Lastname"?"l":q=="Balance"?"b":q=="Date"?"d":"a"; var V=(q+"afldb".Replace(q,""));U(T.First(),V);B=0;foreach(var M in(X?T.Skip(1).Take(1):T.Skip(1).OrderBy(df=>o(df,q))))U(M,V);break;}W();}catch{}if(!C)w("Failed");}}
Brandon
fuente
Sería muy útil si pudiera agregar una muestra de la salida del programa (vea la pregunta actualizada). Gracias.
Logic Knight
1

C # - 1870 1881 Bytes

El abuso de usingalias, Action, Func, excepciones para el control de flujo y más. Estaba considerando explotar ese "informe" que no especificaba cómo deberían clasificarse las cosas. Bank.data debe usar saltos de línea de Unix o este código se romperá.

Editado para solucionar un posible problema de clasificación por campos que no sean Fecha y Saldo.

using System;using System.Collections.Generic;using System.IO;using System.Linq;using Ac=System.Action;using Cn=System.Console;using F1=System.Func<string,int>;using F2=System.Func<string>;using S=System.String;class P{static void Main(S[] args){S fn="Bank.data";List<S>ad=null;F1 L=(s)=>s.Length;F2 dt=()=>S.Format("{0:yyyy-MM-dd}",DateTime.Now);Func<S,S[]>sp=(s)=>s.Split(' ');Action<S,S>wl=(s,fm)=>Cn.WriteLine(S.Format(fm,sp(s)));Func<S,S>rs=(s)=>{var t=sp(s);t[3]="$"+t[3];return S.Join(" ",t);};F2 fs=()=>{int[]sz={7,9,8,7};ad.Skip(1).ToList().ForEach(b=>{for(int c=0;c<4;c++){sz[c]=Math.Max(sz[c],L(sp(rs(b))[c]));}});return"{0,-"+sz[0]+"} {1,-"+sz[1]+"} {2,-"+sz[2]+"} {3,"+sz[3]+"} {4,-10}";};F1 k=(s)=>sp(ad[0]).ToList().FindIndex(a=>a==s);Ac Sv=()=>File.WriteAllText(fn,S.Join("\n",ad));Ac Ld=()=>ad=File.ReadAllText(fn).Split('\n').ToList();Action<int,S>R=(r,a)=>{var s=sp(ad[r]);s[3]=S.Format("{0:#.00}",Convert.ToDouble(s[3])+Convert.ToDouble(a));s[4]=dt();ad[r]=S.Join(" ",s);};Ac f=()=>wl("failure","{0}");F1 ri=(n)=>{for(int w=1;w < ad.Count;w++){if(ad[w].StartsWith(n))return w;}return -1;};F2 nm=()=>{var s="";for(int i=1;i<1000;i++){s=S.Format("{0:000}",i);if (ri(s)<0)break;}return s;};for(;;){Cn.Write("# ");S i=Cn.ReadLine();var it=sp(i+" ");Ld();var n=ri(it[1]);it=sp(i);var a=new Dictionary<S,Ac>(){{"deposit",()=>R(n,it[2])},{"withdraw",()=>R(n,"-"+it[2])},{"close",()=>(sp(ad[n])[3]==".00"?()=>ad.RemoveAt(n):f)()},{"open",()=>{var nn=nm();ad.Add(S.Format("{0} {1} {2} .00 {3}",nn,it[1],it[2],dt()));wl(nn,"{0}");}},{"print",()=>{wl(ad[0],fs());wl(rs(ad[n]),fs());}},{"report",()=>{var ks=sp(fs()).ToList();var ki=k(it[1]);ks.Insert(0,ks[ki]);ks.RemoveAt(ki+1);var kf=S.Join(" ",ks);wl(ad[0],kf);ad.Skip(1).OrderBy(b=>(ki==3?new S('0',11-L(sp(b)[ki])):"")+sp(b)[ki]).ToList().ForEach(b=>wl(rs(b),kf));}}};try{a[it[0]]();Sv();}catch(Exception){f();}}}}

Salida:

# report Balance
   Balance Account Firstname  Lastname           Date
     $7.95 501     Timmy      Bongo              2014-11-04
   $266.71 166     Chip       Stonesmith         2014-12-15
   $346.22 123     Maree      Jones              2014-12-13
   $893.00 105     William    Greene             2015-01-06
  $1228.73 300     Mary       Galoway            2014-12-28
  $1299.82 888     Alexandria Cooper             2014-12-30
  $2055.44 203     Samantha   Richardson         2014-11-01
  $3422.02 035     Thomas     Breakbone          2015-01-03
$277847.74 422     Henrietta  Throsby-Borashenko 2014-11-21
$956119.66 151     Bruce      Wayne              2014-10-09
# open Clark Kent
001
# print 001
Account Firstname  Lastname              Balance Date
001     Clark      Kent                     $.00 2015-02-03
# deposit 001 4530
# withdraw 105 893
# close 105
# report Date
Date       Account Firstname  Lastname              Balance
2014-10-09 151     Bruce      Wayne              $956119.66
2014-11-01 203     Samantha   Richardson           $2055.44
2014-11-04 501     Timmy      Bongo                   $7.95
2014-11-21 422     Henrietta  Throsby-Borashenko $277847.74
2014-12-13 123     Maree      Jones                 $346.22
2014-12-15 166     Chip       Stonesmith            $266.71
2014-12-28 300     Mary       Galoway              $1228.73
2014-12-30 888     Alexandria Cooper               $1299.82
2015-01-03 035     Thomas     Breakbone            $3422.02
2015-02-03 001     Clark      Kent                 $4530.00
#
RomSteady
fuente