# A bank for less Trustworthy Friends

## Introduction

Given the starting balance and all transactions, filter out all transactions where someone tries to overspend and block anyone who tries to overspend (this includes trying to overspend to a closed account) from ever using your bank again by filtering out future transactions to or from his/her bank account.

## Input/Output

Two lists A and B as input and a list C as output. A is the starting balance of each account with the format [["Alice", 5], ["Bob", 8], ["Charlie", 2], ...]. B is a list of transactions with the format [["Bob", "Alice", 3], ["Charlie", "Bob", 5], ...] where ["Bob", "Alice", 3] means that Bob wants to pay Alice 3 currency units. C should have the same format as B. A, B and C may be in any reasonable format.

## Test Cases

A: [["Alice", 5], ["Bob", 2]]
B: [["Alice", "Bob", 5], ["Bob", "Alice" 7]]
C: [["Alice", "Bob", 5], ["Bob", "Alice" 7]]

A: [["A", 2], ["B", 3], ["C", 5]]
B: [["C", "A", 2], ["B", "C", 4], ["A", "B", 2]]
C: [["C", "A", 2]]

A: [["A", 2], ["B", 3]]
B: [["A", "B", 2], ["A", "B", 2]]
C: [["A", "B", 2]]

A: [["A", 4], ["B", 0]]
B: [["A", "B", 1], ["A", "B", 5], ["A", "B", 2]]
C: [["A", "B", 1]]

A: [["A", 2], ["B", 3], ["C", 4]]
B: [["A", "B", 3], ["C", "B", 4]]
C: [["C", "B", 4]]

A: [["A", 2], ["B", 3], ["C", 4]]
B: [["A", "B", 3], ["B", "A", 4], ["C", "B" 2]]
C: []


## Scoring

This is , the shortest code in bytes in each language wins.

• How strict is the IO format? Could A also be a dictionary, or a list of tuples? Nov 25, 2017 at 14:40
• @Laikoni Or even just a list of the form ["A", 2, "B", 3, "C", 5]? Nov 25, 2017 at 14:41
• Suggested test case: A: [["A", 2], ["B", 3], ["C", 4]], B: [["A", "B", 3], ["C", "B", 4]], C: [["C", "B", 4]] (a valid transaction following an invalid one). Nov 25, 2017 at 16:16
• What happens if someone tries to overspend, and the intended recipient has already overspent? Nov 25, 2017 at 16:19
• There's no comma in ["B" 3] in the second and third test cases
– Jo King
Nov 26, 2017 at 3:53

# JavaScript (ES6), 9188 79 bytes

Saved 8 bytes thanks to @NahuelFouilleul

Takes input in currying syntax (a)(b).

a=>b=>b.filter(([x,y,z])=>(a[x]+=z)<0&a[y]<0?a[y]-=z:0,a.map(([x,y])=>a[x]=~y))


### Test cases

let f =

a=>b=>b.filter(([x,y,z])=>(a[x]+=z)<0&a[y]<0?a[y]-=z:0,a.map(([x,y])=>a[x]=~y))

console.log(JSON.stringify(f(
[["Alice", 5], ["Bob", 2]]
)(
[["Alice", "Bob", 5], ["Bob", "Alice", 7]]
)))

console.log(JSON.stringify(f(
[["A", 2], ["B", 3], ["C", 5]]
)(
[["C", "A", 2], ["B", "C", 4], ["A", "B", 2]]
)))

console.log(JSON.stringify(f(
[["A", 2], ["B", 3]]
)(
[["A", "B", 2], ["A", "B", 2]]
)))

console.log(JSON.stringify(f(
[["A", 4], ["B", 0]]
)(
[["A", "B", 1], ["A", "B", 5], ["A", "B", 2]]
)))

console.log(JSON.stringify(f(
[["A", 2], ["B", 3], ["C", 4]]
)(
[["A", "B", 3], ["C", "B", 4]]
)))

### Beautified and commented

a => b =>                 // given the two lists a and b
b.filter(([x, y, z]) => // for each (x = payer, y = payee, z = amount) in b:
(a[x] += z) < 0 &     //   update the payer's account; if it's still valid
a[y] < 0 ?            //   and the payee's account is also valid:
a[y] -= z           //     update the payee's account
:                     //   else:
0,                  //     do nothing
a.map(([x, y]) =>     //   initialization: for each (x = owner, y = amount) in a:
a[x] = ~y           //     set up this account (>= 0: closed, -1: $0, -2:$1, etc.)
)                     //   end of map()
)                       // end of filter()

• what about a=>b=>b.filter(([x,y,z])=>(a[x]-=z)>0&a[y]>0?a[y]+=z:0,a.map(([x,y])=>a[x]=y+1)) porting perl solution to javascript ? Nov 25, 2017 at 19:44
• @NahuelFouilleul Much better indeed. Thanks! Nov 25, 2017 at 20:46

# Perl 5, 72 + 2 (-ap) = 74 bytes

%h=@F;$_=<>;s/(\S+) (\S+) (\S+)/($h{$1}-=$3)<0||($h{$2}+=$3)<$3?"":\$&/ge


try it online

# Python 2, 103 bytes

A,B=input()
C=[]
for i in B:
N,P,M=i
if M>A[N]:A[N]=-1
if A[N]>-1<A[P]:A[N]-=M;A[P]+=M;C+=i,
print C


Try it online!

-12 thanks to ovs.

Longer due to output format restrictions:

C should have the same format as B.

Otherwise I could've done this for 92 bytes:

A,B=input()
for(N,P,M)in B:
if M>A[N]:A[N]=-1
if A[N]>-1<A[P]:A[N]-=M;A[P]+=M;print(N,P,M)

• 103 bytes
– ovs
Nov 25, 2017 at 16:04
• @ovs wow, that's clever Nov 25, 2017 at 16:09

# Ruby, 57 bytes

->a,b{b.select{|(s,r,x)|a[r]+=x if[a[s]-=x,a[r]].min>-1}}


Try it online!

Takes input A as a Hash in the format {"A"=>2, "B"=>3}. Input B and output C are in the suggested format.

## Explanation

->a,b{                      # lambda function taking arguments A and B
b.select{|(s,r,x)|              # select items in B that return truthy (s = sender, r = receiver, x = amount)
a[s]-=x,                # subtract amount from sender
if [         a[r]].min>-1   # check if the smaller of the balances is non-negative
# (true if both values are non-negative)

Input A as std::map, B as std::list.
#import<bits/stdc++.h>