import%20marimo%0A%0A__generated_with%20%3D%20%220.9.3%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%20Administrando%20despesas%20em%20grupo%0A%0A%20%20%20%20%20%20%20%20O%20aplicativo%20%5BTricount%5D(https%3A%2F%2Fwww.tricount.com%2F)%20(e%20v%C3%A1rios%20outros%20concorrentes)%20gerencia%20gastos%20compartilhados%20de%20um%20grupo%20de%20pessoas.%20Cada%20pessoa%20pode%20adicionar%20gastos%20que%20tenha%20feito%20em%20nome%20do%20grupo%2C%20e%20o%20aplicativo%20calcula%20o%20quanto%20cada%20uma%20deve%20pagar%20ou%20receber%20para%20que%20todos%20fiquem%20quites.%20Por%20exemplo%2C%20imagine%20que%20alguns%20amigos%20fazem%20juntos%20uma%20viagem%2C%20e%20um%20deles%20reservou%20e%20pagou%20o%20hotel%2C%20uma%20outra%20alugou%20um%20ve%C3%ADculo%2C%20um%20outro%20contratou%20um%20guia%2C%20etc.%20A%20forma%20mais%20simples%20de%20um%20grupo%20ficar%20quite%20%C3%A9%20cada%20benefici%C3%A1rio%20de%20um%20gasto%20transferir%20a%20sua%20parte%20de%20cada%20despesa%20para%20a%20pessoa%20que%20efetivamente%20a%20pagou%2C%20mas%20isso%20demanda%20%24%5Csum_%7Bi%20%5Cin%20G%7Dn_i%24%20transfer%C3%AAncias%2C%20em%20que%20%24n_i%24%20%C3%A9%20n%C3%BAmero%20de%20benefici%C3%A1rios%20do%20gasto%20%24i%24%20diferentes%20do%20pagador%2C%20e%20%24G%24%20%C3%A9%20o%20conjunto%20de%20gastos.%20%C3%89%20poss%C3%ADvel%20tornar%20todos%20quites%20com%20menos%20transfer%C3%AAncias%2C%20e%20isso%20%C3%A9%20uma%20das%20coisas%20que%20exploraremos%20em%20um%20exerc%C3%ADcio.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%23%23%20Ex.%20calcula-balan%C3%A7o%0A%0A%20%20%20%20%20%20%20%20Implemente%20uma%20das%20funcionalidades%20principais%20do%20aplicativo%3A%20escreva%20a%20fun%C3%A7%C3%A3o%20%60calculate_balance%60%2C%20que%20dado%20o%20nome%20de%0A%20%20%20%20%20%20%20%20uma%20pessoa%20e%20uma%20lista%20de%20gastos%2C%20retorna%20o%20saldo%20da%20pessoa%20em%20rela%C3%A7%C3%A3o%20ao%20grupo.%20%0A%0A%20%20%20%20%20%20%20%20Se%20a%20pessoa%20pagou%20mais%20gastos%20do%20que%20%E2%80%98recebeu%E2%80%99%20gastos%20de%0A%20%20%20%20%20%20%20%20outras%20pessoas%2C%20seu%20saldo%20%C3%A9%20positivo%2C%20e%20caso%20contr%C3%A1rio%20seu%20saldo%20%C3%A9%0A%20%20%20%20%20%20%20%20negativo.%0A%0A%20%20%20%20%20%20%20%20O%20nome%20das%20pessoas%20do%20grupo%20%C3%A9%20sempre%20uma%20string%2C%20e%20o%20gasto%20ser%C3%A1%0A%20%20%20%20%20%20%20%20modelado%20como%20um%20dicion%C3%A1rio%20com%20chaves%20'description'%20(string%3A%20descri%C3%A7%C3%A3o%20da%20despesa)%2C%20'payer'%20(pagador%20da%20despesa)%2C%20'amount'%20(inteiro%3A%20valor%20da%20despesa%20em%20centavos)%20e%20'beneficiaries'%20(lista%20de%20strings%3A%20o%20nome%20das%20pessoas%20do%20grupo%20que%20se%20beneficiaram%20do%20gasto%20e%20que%20devem%20pagar%20por%20ele).%0A%0A%20%20%20%20%20%20%20%20Se%20voc%C3%AA%20implementar%20%60calculate_balance%60%20corretamente%2C%20%60calculate_balance(%22Frodo%22%2C%20example_expenses)%20%3D%3D%20-1140%60%2C%20j%C3%A1%20que%20Frodo%20n%C3%A3o%20pagou%20nada%20para%20ningu%C3%A9m%20e%20recebeu%20dois%20caf%C3%A9s%20da%20manh%C3%A3%20comprados%20por%20Sam%20e%20Pippin%20(nos%20valores%20totais%20de%201590%20e%201830%20cada%2C%20divididos%20por%20tr%C3%AAs%20pessoas%20isso%20significa%20que%20Frodo%20deveria%20ter%20pago%201140%20se%20cada%20um%20tivesse%20pago%20a%20sua%20parte%20de%20uma%20vez).%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22Como%20floats%20n%C3%A3o%20s%C3%A3o%20exatos%2C%20trabalhamos%20%3C!--com%20%5Bdecimais%5D(https%3A%2F%2Fdocs.python.org%2F3%2Flibrary%2Fdecimal.html).--%3E%20com%20inteiros%20(n%C3%BAmero%20de%20centavos).%20Cada%20benefici%C3%A1rio%20de%20um%20gasto%20%C3%A9%20respons%C3%A1vel%20pelo%20gasto%20dividido%20pelo%20n%C3%BAmero%20de%20benefici%C3%A1rios%2C%20e%20o%20resto%20(caso%20o%20gasto%20n%C3%A3o%20seja%20perfeitamente%20divis%C3%ADvel)%20%C3%A9%20de%20responsabilidade%20do%20pagador.%20Se%20preferir%2C%20voc%C3%AA%20tamb%C3%A9m%20pode%20distribuir%20o%20resto%20%24r%20%3C%20k%24%20igualmente%20entre%20%24r%24%20benefici%C3%A1rios.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%200.1%20%2B%200.1%20%2B%200.1%20-%200.3%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20example_expenses%20%3D%20%5B%0A%20%20%20%20%20%20%20%20dict(%0A%20%20%20%20%20%20%20%20%20%20%20%20description%3D%22Breakfast%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20payer%3D%22Sam%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20amount%3D15_90%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20beneficiaries%3D%5B%22Frodo%22%2C%20%22Sam%22%2C%20%22Pippin%22%5D%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20dict(%0A%20%20%20%20%20%20%20%20%20%20%20%20description%3D%22Breakfast%20(again)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20payer%3D%22Pippin%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20amount%3D18_30%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20beneficiaries%3D%5B%22Frodo%22%2C%20%22Sam%22%2C%20%22Pippin%22%5D%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%5D%0A%20%20%20%20example_expenses%0A%20%20%20%20return%20(example_expenses%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__()%3A%0A%20%20%20%20%23%20solu%C3%A7%C3%A3o%0A%20%20%20%20def%20calculate_balance(name%2C%20expenses)%3A%0A%20%20%20%20%20%20%20%20balance%20%3D%200%0A%20%20%20%20%20%20%20%20for%20expense%20in%20expenses%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20m%20%3D%20len(expense%5B%22beneficiaries%22%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20amount%20%3D%20expense%5B%22amount%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20expense%5B%22payer%22%5D%20%3D%3D%20name%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20balance%20%3D%20balance%20%2B%20amount%20-%20(amount%20%25%20m)%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20name%20in%20expense%5B%22beneficiaries%22%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20balance%20%3D%20balance%20-%20amount%20%2F%2F%20m%0A%20%20%20%20%20%20%20%20return%20balance%0A%20%20%20%20return%20(calculate_balance%2C)%0A%0A%0A%40app.cell%0Adef%20__(calculate_balance%2C%20example_expenses)%3A%0A%20%20%20%20calculate_balance(%22Frodo%22%2C%20example_expenses)%20%3D%3D%20-1140%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(calculate_balance)%3A%0A%20%20%20%20%23%20a%20soma%20dos%20balan%C3%A7os%20deve%20ser%20igual%20a%20zero%0A%20%20%20%20expense%20%3D%20%5B%0A%20%20%20%20%20%20%20%20dict(%0A%20%20%20%20%20%20%20%20%20%20%20%20description%3D%22Breakfast%20(again)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20payer%3D%22Pippin%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20amount%3D4%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20beneficiaries%3D%5B%22Frodo%22%2C%20%22Sam%22%2C%20%22Pippin%22%5D%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%5D%0A%20%20%20%20(%0A%20%20%20%20%20%20%20%20calculate_balance(%22Pippin%22%2C%20expense)%20%3D%3D%202%2C%0A%20%20%20%20%20%20%20%20sum(calculate_balance(p%2C%20expense)%20for%20p%20in%20%5B%22Frodo%22%2C%20%22Sam%22%2C%20%22Pippin%22%5D)%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(expense%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%23%23%20Ex.%20calcula-balan%C3%A7os%0A%0A%20%20%20%20%20%20%20%20Defina%20uma%20fun%C3%A7%C3%A3o%20semelhante%20a%20anterior%20que%20calcule%20o%20saldo%20de%20todas%20as%20pessoas%20do%20grupo%20de%20uma%20vez%20s%C3%B3%20(fazendo%20um%20%C3%BAnico%20loop%20sobre%20os%20gastos%20do%20grupo).%20A%20fun%C3%A7%C3%A3o%20%60calculate_balances%60%20tem%20um%20%C3%BAnico%20par%C3%A2metro%20(a%20lista%20de%20gastos%2C%20cada%20gasto%20sendo%20um%20dicion%C3%A1rio%20como%20acima)%2C%20e%20retornando%20um%20dicion%C3%A1rio%20cujas%20chaves%20s%C3%A3o%20os%20nomes%20dos%20participantes%20e%20os%20valores%20s%C3%A3o%20seus%20respectivos%20saldos%20(inteiro%3A%20n%C3%BAmero%20de%20centavos).%0A%0A%20%20%20%20%20%20%20%20Lembre-se%3A%20a%20soma%20dos%20saldos%20de%20todas%20as%20pessoas%20deve%20ser%20igual%20a%20zero%3B%20voc%C3%AA%20pode%20usar%20essa%20informa%C3%A7%C3%A3o%20para%20verificar%20sua%20solu%C3%A7%C3%A3o.%0A%0A%20%20%20%20%20%20%20%20**Aten%C3%A7%C3%A3o**%3A%20Voc%C3%AA%20*n%C3%A3o*%20deve%20usar%20a%20fun%C3%A7%C3%A3o%20%60calculate_balance%60%20definida%20anteriormente%20para%20definir%20%60calculate_balances%60%2C%20ou%20voc%C3%AA%0A%20%20%20%20%20%20%20%20n%C3%A3o%20estaria%20calculando%20os%20saldos%20com%20uma%20%C3%BAnica%20itera%C3%A7%C3%A3o%20sobre%20os%0A%20%20%20%20%20%20%20%20gastos%20do%20grupo%20(conforme%20o%20pedido).%20Voc%C3%AA%20pode%20no%20entanto%20usar%0A%20%20%20%20%20%20%20%20%60calculate_balance%60%20para%20verificar%20que%20os%20resultados%20das%20duas%20fun%C3%A7%C3%B5es%20concordam%20entre%20si%2C%20isto%20%C3%A9%2C%20que%20para%20cada%20pessoa%20%60p%60%20de%20um%20grupo%20com%20gastos%20%60expenses%60%2C%20vale%20que%20%60calculate_balance(person%2C%20expenses)%20%3D%3D%20calculate_balances(expenses)%5Bperson%5D%60.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__()%3A%0A%20%20%20%20def%20calculate_balances(expenses)%3A%0A%20%20%20%20%20%20%20%20balances%20%3D%20%7B%7D%0A%20%20%20%20%20%20%20%20for%20expense%20in%20expenses%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20payer%20%3D%20expense%5B'payer'%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20amount%20%3D%20expense%5B'amount'%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20beneficiaries%20%3D%20expense%5B'beneficiaries'%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20m%20%3D%20len(beneficiaries)%0A%20%20%20%20%20%20%20%20%20%20%20%20balances%5Bpayer%5D%20%3D%20balances.get(payer%2C%200)%20%2B%20amount%20%5C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20-%20(amount%20%25%20m)%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20name%20in%20beneficiaries%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20balances%5Bname%5D%20%3D%20balances.get(name%2C%200)%20-%20amount%20%2F%2F%20m%0A%20%20%20%20%20%20%20%20return%20balances%0A%20%20%20%20return%20(calculate_balances%2C)%0A%0A%0A%40app.cell%0Adef%20__(calculate_balances%2C%20example_expenses)%3A%0A%20%20%20%20calculate_balances(example_expenses)%20%3D%3D%20%7B'Sam'%3A%204_50%2C%20'Frodo'%3A%20-11_40%2C%20'Pippin'%3A%206_90%7D%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%23%23%20Ex.%20calcula-balan%C3%A7os-csv%0A%0A%20%20%20%20%20%20%20%20Escreva%20uma%20fun%C3%A7%C3%A3o%20%60calculate_balances_from_csv%60%20que%20l%C3%AA%20um%20arquivo%20CSV%20(invocando%20%60csv.reader%60)%20listando%20os%20gastos%20de%20um%20grupo%2C%20e%20calcula%20o%20saldo%20de%20todos%20os%20envolvidos%20no%20grupo%20usando%20a%20fun%C3%A7%C3%A3o%0A%20%20%20%20%20%20%20%20%60calculate_balances%60%20definida%20anteriormente.%0A%0A%20%20%20%20%20%20%20%20Neste%20%5Blink%5D(https%3A%2F%2Fwww.inf.puc-rio.br%2F~bclaro%2Fcourses%2Fpython-intro%2Fstatic%2Ftransactions.csv)%20h%C3%A1%20um%20arquivo%20que%20exemplifica%20o%20formato%20das%20listas%20de%20gastos%20em%20CSV.%20Cada%20linha%20do%20arquivo%20%C3%A9%20uma%20transa%C3%A7%C3%A3o%2C%20e%20cada%20transa%C3%A7%C3%A3o%20tem%20quatro%20campos%3A%20nome%2C%20pagador%2C%20montante%2Fvalor%2C%20e%20os%20benefici%C3%A1rios%20(uma%20lista%20de%20nomes%20separados%20por%20v%C3%ADrgulas).%20Segue%20um%20outro%20exemplo%20em%0A%20%20%20%20%20%20%20%20formato%20CSV%3A%0A%0A%20%20%20%20%20%20%20%20%60%60%60%0A%20%20%20%20%20%20%20%20Breakfast%2CSam%2C15.90%2C%22Frodo%2CSam%2CPippin%22%0A%20%20%20%20%20%20%20%20Breakfast%20(again)%2CPippin%2C18.30%2C%22Frodo%2CSam%2CPippin%22%0A%20%20%20%20%20%20%20%20%60%60%60%0A%0A%20%20%20%20%20%20%20%20**Aten%C3%A7%C3%A3o**%3A%20voc%C3%AA%20deve%20converter%20os%20valores%20dos%20gastos%20para%20centavos%20(do%20tipo%20%60int%60).%0A%0A%20%20%20%20%20%20%20%20Note%20tamb%C3%A9m%20que%20o%20%C3%BAltimo%20campo%20de%20cada%20linha%20est%C3%A1%20sempre%20envolto%20por%20aspas%2C%20para%20que%20n%C3%A3o%20se%20confundam%20as%20v%C3%ADrgulas%20que%20separam%20os%20nomes%20dos%20benefici%C3%A1rios%20de%20um%20gasto%20com%20as%20v%C3%ADrgulas%20que%20separam%20os%20campos%20do%20arquivo%20CSV.%20(No%20fundo%20voc%C3%AA%20n%C3%A3o%20precisa%20se%20preocupar%20com%20isso%2C%20neste%20caso%20o%20leitor%20de%20CSV%20do%20Python%20vai%20fazer%20a%20coisa%20certa%20por%20padr%C3%A3o).%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20csv%0A%20%20%20%20return%20(csv%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(calculate_balances%2C%20csv)%3A%0A%20%20%20%20def%20calculate_balances_from_csv(filepath)%3A%0A%20%20%20%20%20%20%20%20with%20open(filepath%2C%20'r')%20as%20csvfile%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20expenses%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20myreader%20%3D%20csv.reader(csvfile%2C%20delimiter%3D'%2C'%2C%20quotechar%3D'%22')%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20expense%20in%20myreader%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23print(expense)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Bname%2C%20payer%2C%20amount_str%2C%20beneficiaries_str%5D%20%3D%20expense%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20amount%20%3D%20int(100%20*%20float(amount_str))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20beneficiaries%20%3D%20beneficiaries_str.split('%2C')%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20new_expense%20%3D%20dict(description%3Dname%2C%20payer%3Dpayer%2C%20amount%3Damount%2C%20beneficiaries%3Dbeneficiaries)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20expenses.append(new_expense)%0A%20%20%20%20%20%20%20%20return%20calculate_balances(expenses)%0A%20%20%20%20return%20(calculate_balances_from_csv%2C)%0A%0A%0A%40app.cell%0Adef%20__(calculate_balances_from_csv)%3A%0A%20%20%20%20calculate_balances_from_csv('transactions.csv')%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%23%23%20Ex.%20gastos-par%0A%0A%20%20%20%20%20%20%20%20Defina%20uma%20fun%C3%A7%C3%A3o%20que%20dada%20uma%20lista%20de%20gastos%20e%20dois%20nomes%20retorna%20todos%20os%20gastos%20envolvendo%20os%20dois%20nomes.%20%0A%0A%20%20%20%20%20%20%20%20N%C3%B3s%20dizemos%20que%20um%20gasto%20envolve%20um%20par%20de%20pessoas%20se%20uma%20delas%20%C3%A9%20pagadora%20e%20a%20outra%20%C3%A9%20benefici%C3%A1ria%2C%20ou%20vice-versa.%20Dos%20gastos%20abaixo%2C%20s%C3%B3%20as%20duas%20primeiras%20envolvem%20Fulano%20e%20Cicrano%2C%20segundo%20nesta%20defini%C3%A7%C3%A3o.%0A%0A%20%20%20%20%20%20%20%20Essa%20defini%C3%A7%C3%A3o%20%C3%A9%20%C3%BAtil%20pois%20um%20gasto%20que%20n%C3%A3o%20envolve%20um%20par%20de%20pessoas%20n%C3%A3o%20altera%20o%20saldo%20entre%20esse%20par%20de%20pessoas.%20Por%20exemplo%2C%20o%20terceiro%20gasto%20n%C3%A3o%20altera%20o%20saldo%20do%20par%20(Fulano%2C%20Cicrano)%3A%20isto%20%C3%A9%2C%20depois%20dos%20primeiros%20dois%20gastos%20Fulano%20deve%20200%20reais%20para%20Cicrano%3B%20o%20fato%20de%20John%20ter%20pago%20sorvete%20para%20os%20tr%C3%AAs%20n%C3%A3o%20altera%20esse%20fato.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20ex1%20%3D%20dict(description%3D'Tour%20cachoeira'%2C%20payer%3D'Fulano'%2C%20amount%3D400_00%2C%20beneficiaries%3D%5B'Fulano'%2C%20'Cicrano'%5D)%0A%20%20%20%20ex2%20%3D%20dict(description%3D'Hotel'%2C%20payer%3D'Cicrano'%2C%20amount%3D800_00%2C%20beneficiaries%3D%5B'Fulano'%5D)%0A%20%20%20%20ex3%20%3D%20dict(description%3D'Sorvete'%2C%20payer%3D'John'%2C%20amount%3D60_00%2C%20beneficiaries%3D%5B'John'%2C%20'Fulano'%2C%20'Cicrano'%5D)%0A%20%20%20%20return%20ex1%2C%20ex2%2C%20ex3%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__()%3A%0A%20%20%20%20%23%20solu%C3%A7%C3%A3o%0A%20%20%20%20def%20get_pair_expenses(expenses%2C%20person1%2C%20person2)%3A%0A%20%20%20%20%20%20%20%20pair_expenses%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20for%20expense%20in%20expenses%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20payer%20%3D%20expense%5B'payer'%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20beneficiaries%20%3D%20expense%5B'beneficiaries'%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(person1%20%3D%3D%20payer%20and%20person2%20in%20beneficiaries)%20or%20(person2%20%3D%3D%20payer%20and%20person1%20in%20beneficiaries)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pair_expenses.append(expense)%0A%20%20%20%20%20%20%20%20return%20pair_expenses%0A%20%20%20%20return%20(get_pair_expenses%2C)%0A%0A%0A%40app.cell%0Adef%20__(ex1%2C%20ex2%2C%20ex3%2C%20get_pair_expenses)%3A%0A%20%20%20%20get_pair_expenses(%5Bex1%2C%20ex2%2C%20ex3%5D%2C%20%22Fulano%22%2C%20%22Cicrano%22)%20%3D%3D%20%5Bex1%2C%20ex2%5D%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%23%23%20Ex.%20balan%C3%A7o-par%0A%0A%20%20%20%20%20%20%20%20Defina%20a%20fun%C3%A7%C3%A3o%20%60get_pair_balance%60%2C%20que%20retorna%20o%20saldo%20entre%20duas%0A%20%20%20%20%20%20%20%20pessoas%20(passadas%20como%20argumentos)%20para%20uma%20s%C3%A9rie%20de%20gastos%20(tamb%C3%A9m%20passada%20como%20argumento).%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(get_pair_expenses)%3A%0A%20%20%20%20%23%20solu%C3%A7%C3%A3o%0A%20%20%20%20def%20get_pair_balance(expenses%2C%20person1%2C%20person2)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Calculate%20how%20much%20person1%20is%20owed%20by%20person2.%22%22%22%0A%20%20%20%20%20%20%20%20pair_balance%20%3D%200%0A%20%20%20%20%20%20%20%20pair_expenses%20%3D%20get_pair_expenses(expenses%2C%20person1%2C%20person2)%0A%20%20%20%20%20%20%20%20for%20expense%20in%20pair_expenses%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20payer%20%3D%20expense%5B'payer'%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20amount%20%3D%20expense%5B'amount'%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20m%20%3D%20len(expense%5B'beneficiaries'%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20amount_pp%20%3D%20amount%20%2F%2F%20m%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20payer%20%3D%3D%20person1%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pair_balance%20%2B%3D%20amount_pp%20-%20(amount%20%25%20m)%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20assert%20payer%20%3D%3D%20person2%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pair_balance%20-%3D%20amount_pp%0A%20%20%20%20%20%20%20%20return%20pair_balance%0A%20%20%20%20return%20(get_pair_balance%2C)%0A%0A%0A%40app.cell%0Adef%20__(ex1%2C%20ex2%2C%20ex3%2C%20get_pair_balance)%3A%0A%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20get_pair_balance(%5Bex1%2C%20ex2%2C%20ex3%5D%2C%20%22Cicrano%22%2C%20%22Fulano%22)%20%3D%3D%20600_00%2C%0A%20%20%20%20%20%20%20%20get_pair_balance(%5Bex1%2C%20ex2%2C%20ex3%5D%2C%20%22Fulano%22%2C%20%22Cicrano%22)%20%3D%3D%20-600_00%2C%0A%20%20%20%20%20%20%20%20get_pair_balance(%5Bex1%2C%20ex2%2C%20ex3%5D%2C%20%22Cicrano%22%2C%20%22John%22)%20%3D%3D%20-20_00%2C%0A%20%20%20%20%20%20%20%20get_pair_balance(%5Bex1%2C%20ex2%2C%20ex3%5D%2C%20%22John%22%2C%20%22Fulano%22)%20%3D%3D%2020_00%0A%20%20%20%20%5D%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%23%23%20Ex.%20calcula-quita%C3%A7%C3%B5es-simples%0A%0A%20%20%20%20%20%20%20%20Defina%20a%20fun%C3%A7%C3%A3o%20%60calculate_simple_settlements%60%2C%20que%20calcula%20as%0A%20%20%20%20%20%20%20%20transfer%C3%AAncias%20dois-a-dois%20que%20precisam%20ser%20feitas%20para%20que%20todos%20os%20membros%20de%20um%20grupo%20fiquem%20quites%20uns%20com%20os%20outros.%20O%20resultado%20%C3%A9%20um%20dicion%C3%A1rio%20cujas%20chaves%20s%C3%A3o%20pares%20de%20pessoas%20e%20os%20valores%20s%C3%A3o%20inteiros%20representando%20o%20montante%20em%20centavos%20que%20a%20primeira%20pessoa%20deve%20pagar%20%C3%A0%20segunda.%0A%0A%20%20%20%20%20%20%20%20Voc%C3%AA%20pode%20(e%20deve)%20usar%20a%20fun%C3%A7%C3%A3o%20%60get_pair_balance%60%20para%20responder%20%C3%A0%20esta%20quest%C3%A3o.%20%C3%89%20%C3%BAtil%20definir%20tamb%C3%A9m%3A%0A%0A%20%20%20%20%20%20%20%201.%20Defina%20uma%20fun%C3%A7%C3%A3o%20%60get_participants%60%20que%20retorna%20o%20conjunto%20de%20participantes%20de%20uma%20lista%20de%20gastos%3B%0A%20%20%20%20%20%20%20%202.%20Defina%20uma%20fun%C3%A7%C3%A3o%20que%20dado%20um%20conjunto%20de%20elementos%2C%20retorna%20as%20combina%C3%A7%C3%B5es%20%C3%BAnicas%20de%20dois%20elementos%20do%20conjunto%20(considere%20que%20%60(a%2C%20b)%20%3D%3D%20(b%2C%20a)%60).%0A%0A%20%20%20%20%20%20%20%20Ao%20usar%20a%20fun%C3%A7%C3%A3o%20%60get_pair_balance%60%2C%20j%C3%A1%20estamos%20reduzindo%20o%20n%C3%BAmero%20de%20transfer%C3%AAncias%20em%20rela%C3%A7%C3%A3o%20%C3%A0%20solu%C3%A7%C3%A3o%20trivial%20de%20%24%5Csum_%7Bi%20%5Cin%20G%7Dn_i%24%20transfer%C3%AAncias%2C%20em%20que%20%24n_i%24%20%C3%A9%20n%C3%BAmero%20de%20benefici%C3%A1rios%20do%20gasto%20%24i%24%20que%20n%C3%A3o%20s%C3%A3o%20o%20pagador%2C%20e%20%24G%24%20%C3%A9%20o%20conjunto%20de%20gastos.%20Se%20estiver%20com%20dificuldade%20para%20resolver%20essa%20quest%C3%A3o%2C%20tente%20fazer%20a%20solu%C3%A7%C3%A3o%20trivial%20primeiro%20(falamos%20um%20pouco%20mais%20dela%20na%20introdu%C3%A7%C3%A3o%2C%20pode%20ser%20%C3%BAtil%20rel%C3%AA-la).%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(get_pair_balance)%3A%0A%20%20%20%20%23%20solu%C3%A7%C3%A3o%0A%0A%20%20%20%20def%20get_participants(expenses)%3A%0A%20%20%20%20%20%20%20%20ps%20%3D%20set()%0A%20%20%20%20%20%20%20%20for%20e%20in%20expenses%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20ps.add(e%5B'payer'%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20p%20in%20e%5B'beneficiaries'%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ps.add(p)%0A%20%20%20%20%20%20%20%20return%20ps%0A%0A%20%20%20%20def%20calculate_simple_settlements(expenses)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Calculate%20how%20much%20everyone%20has%20to%20pay%20(and%20to%20whom)%20for%20the%20accounts%20to%20be%20settled%20(that%20is%2C%20no%20one%20owes%20anyone%20anymore).%0A%0A%20%20%20%20The%20answer%20is%20a%20dictionary%20whose%20keys%20are%20pairs%20of%20participant%20names%2C%20and%20whose%20values%20are%20integers%20representing%20how%20much%20the%20first%20person%20in%20the%20pair%20should%20reveive%20from%20the%20second%20person.%22%22%22%0A%20%20%20%20%20%20%20%20participants%20%3D%20get_participants(expenses)%0A%20%20%20%20%20%20%20%20all_pairs%20%3D%20%5B(p1%2C%20p2)%20for%20p1%20in%20participants%20for%20p2%20in%20participants%20if%20p1%20%3E%20p2%5D%0A%20%20%20%20%20%20%20%20settlements%20%3D%20%7B%7D%0A%20%20%20%20%20%20%20%20for%20(person1%2C%20person2)%20in%20all_pairs%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20pair_balance%20%3D%20get_pair_balance(expenses%2C%20person1%2C%20person2)%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20pair_balance%20%3E%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20settlements%5B(person2%2C%20person1)%5D%20%3D%20pair_balance%0A%20%20%20%20%20%20%20%20%20%20%20%20elif%20pair_balance%20%3C%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20settlements%5B(person1%2C%20person2)%5D%20%3D%20-pair_balance%0A%20%20%20%20%20%20%20%20return%20settlements%0A%20%20%20%20return%20calculate_simple_settlements%2C%20get_participants%0A%0A%0A%40app.cell%0Adef%20__(calculate_simple_settlements%2C%20ex1%2C%20ex2%2C%20ex3)%3A%0A%20%20%20%20calculate_simple_settlements(%5Bex1%2C%20ex2%2C%20ex3%5D)%20%3D%3D%20%7B(%22Fulano%22%2C%20%22John%22)%3A%2020_00%2C%20(%22Cicrano%22%2C%20%22John%22)%3A%2020_00%2C%20(%22Fulano%22%2C%20%22Cicrano%22)%3A%20600_00%7D%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%20%20%20%20%23%23%23%23%20Ex.%20calcula-quita%C3%A7%C3%B5es%0A%0A%20%20%20%20%20%20%20%20Defina%20a%20fun%C3%A7%C3%A3o%20%60calculate_settlements%60%2C%20que%20calcula%20as%0A%20%20%20%20%20%20%20%20transfer%C3%AAncias%20que%20precisam%20ser%20feitas%20para%20que%20todos%20os%20membros%20de%20um%20grupo%20fiquem%20quites%20uns%20com%20os%20outros%2C%20minimizando%20ainda%20mais%20o%20total%20de%20transfer%C3%AAncias%20em%20rela%C3%A7%C3%A3o%20ao%20exerc%C3%ADcio%20calcula-quita%C3%A7%C3%B5es-simples.%0A%0A%20%20%20%20%20%20%20%20No%20exemplo%20dado%2C%20a%20fun%C3%A7%C3%A3o%20%60calculate_simple_settlements%60%20nos%20d%C3%A1%20uma%20solu%C3%A7%C3%A3o%20com%20tr%C3%AAs%20transfer%C3%AAncias%2C%20mas%20%C3%A9%20poss%C3%ADvel%20reduzir%20esse%20n%C3%BAmero%20para%20duas%20(veja%20o%20exemplo%20abaixo).%0A%0A%20%20%20%20%20%20%20%20O%20resultado%20%C3%A9%20tamb%C3%A9m%20um%20dicion%C3%A1rio%20cujas%20chaves%20s%C3%A3o%20pares%20de%20pessoas%20e%20os%20valores%20s%C3%A3o%20inteiros%20representando%20o%20montante%20que%20a%20primeira%20pessoa%20deve%20pagar%20%C3%A0%20segunda.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20__(calculate_balances%2C%20get_participants)%3A%0A%20%20%20%20%23%20solu%C3%A7%C3%A3o%0A%20%20%20%20def%20calculate_settlements(expenses)%3A%0A%20%20%20%20%20%20%20%20participants%20%3D%20get_participants(expenses)%0A%20%20%20%20%20%20%20%20balances%20%3D%20calculate_balances(expenses)%0A%20%20%20%20%20%20%20%20to_pay_to%20%3D%20%7B%7D%0A%20%20%20%20%20%20%20%20def%20sort_balance_pairs(pairs)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20pairs.sort(key%3Dlambda%20x%3A%20x%5B1%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20owes%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20is_owed_to%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20for%20(participant%2C%20balance)%20in%20balances.items()%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20balance%20%3E%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20is_owed_to.append((participant%2C%20balance))%0A%20%20%20%20%20%20%20%20%20%20%20%20elif%20balance%20%3C%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20owes.append((participant%2C%20-balance))%0A%20%20%20%20%20%20%20%20sort_balance_pairs(owes)%0A%20%20%20%20%20%20%20%20sort_balance_pairs(is_owed_to)%0A%20%20%20%20%20%20%20%20while%20owes%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20(debtor%2C%20debt)%20%3D%20owes%5B-1%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20(creditor%2C%20credit)%20%3D%20is_owed_to%5B-1%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20difference%20%3D%20credit%20-%20debt%0A%20%20%20%20%20%20%20%20%20%20%20%20to_pay_to%5B(debtor%2C%20creditor)%5D%20%3D%20min(debt%2C%20credit)%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20difference%20%3E%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20owes.pop()%20%23%20debt%20is%20cleared%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20is_owed_to%5B-1%5D%20%3D%20(creditor%2C%20difference)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20TODO%3A%20it%20would%20be%20better%20to%20insert%20at%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20the%20appropriate%20position%20instead%20of%20re-sorting%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sort_balance_pairs(is_owed_to)%0A%20%20%20%20%20%20%20%20%20%20%20%20elif%20difference%20%3C%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20is_owed_to.pop()%20%23%20credit%20is%20cleared%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20owes%5B-1%5D%20%3D%20(debtor%2C%20-difference)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20sort_balance_pairs(owes)%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20owes.pop()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20is_owed_to.pop()%0A%20%20%20%20%20%20%20%20return%20to_pay_to%0A%20%20%20%20return%20(calculate_settlements%2C)%0A%0A%0A%40app.cell%0Adef%20__(calculate_settlements%2C%20ex1%2C%20ex2%2C%20ex3)%3A%0A%20%20%20%20calculate_settlements(%5Bex1%2C%20ex2%2C%20ex3%5D)%20%3D%3D%20%7B(%22Fulano%22%2C%20%22John%22)%3A%2040_00%2C%20(%22Fulano%22%2C%20%22Cicrano%22)%3A%20580_00%7D%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
213cfee77201595fd5266be15f9199aa95b15393d45ba81d6c86ea3877db8874