From 5e5713d5d86267adf153064bc74c87a8d556133d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Thu, 13 Oct 2022 20:09:25 +0100 Subject: [PATCH] Import FP --- .gitattributes | 3 + .github/workflows/deploy.yml | 14 + FP/.gitignore | 1 + FP/aula00/aula00.norg | 317 +++++ FP/aula00/res/graph00.png | Bin 0 -> 32055 bytes FP/aula00/res/graph01.png | Bin 0 -> 29436 bytes FP/aula00/res/graph02.png | Bin 0 -> 27324 bytes FP/aula00/res/plot.py | 22 + FP/aula00/res/retangulo.py | 10 + FP/aula00/res/solution.py | 11 + FP/aula00/res/welcome.py | 11 + "FP/aula00/te\303\263rico/README.md" | 14 + "FP/aula00/te\303\263rico/aula00.pdf" | Bin 0 -> 131 bytes "FP/aula00/te\303\263rico/plot.py" | 20 + "FP/aula00/te\303\263rico/solution.py" | 11 + "FP/aula00/te\303\263rico/welcome.py" | 12 + FP/aula01/aula01.norg | 264 ++++ FP/aula01/res/aula01e01.py | 13 + FP/aula01/res/aula01e02.py | 15 + FP/aula01/res/aula01e03.py | 27 + FP/aula01/res/aula01e04.py | 15 + FP/aula01/res/aula01e05.py | 17 + FP/aula01/res/aula01e07.py | 30 + FP/aula01/res/aula01e08.py | 26 + FP/aula01/res/aula01e09.py | 29 + FP/aula01/res/points.py | 19 + "FP/aula01/te\303\263rico/README.md" | 16 + "FP/aula01/te\303\263rico/aula01.pdf" | Bin 0 -> 131 bytes "FP/aula01/te\303\263rico/idade.py" | 1 + "FP/aula01/te\303\263rico/points.py" | 17 + "FP/aula01/te\303\263rico/pointsg.py" | 20 + "FP/aula01/te\303\263rico/tp00-computers.pdf" | Bin 0 -> 132 bytes "FP/aula01/te\303\263rico/tp01-intro.pdf" | Bin 0 -> 131 bytes FP/aula02/aula02.norg | 355 ++++++ FP/aula02/res/age.py | 18 + FP/aula02/res/aula02e04.py | 8 + FP/aula02/res/aula02e05.py | 12 + FP/aula02/res/aula02e09.py | 24 + FP/aula02/res/darts.py | 61 + FP/aula02/res/imc.py | 22 + FP/aula02/res/kryptonite.py | 18 + FP/aula02/res/max2.py | 16 + FP/aula02/res/max3.py | 17 + FP/aula02/res/max4.py | 17 + "FP/aula02/te\303\263rico/README.md" | 22 + "FP/aula02/te\303\263rico/age.py" | 26 + "FP/aula02/te\303\263rico/aula02.pdf" | Bin 0 -> 131 bytes "FP/aula02/te\303\263rico/darts.py" | 18 + "FP/aula02/te\303\263rico/examples/ex1if.py" | 19 + .../te\303\263rico/examples/ex1ifelse.py" | 18 + .../te\303\263rico/examples/ex1raining.py" | 15 + .../te\303\263rico/examples/ex2classifier.py" | 18 + .../te\303\263rico/examples/ex2ifelifelse.py" | 13 + .../te\303\263rico/examples/ex2piecewise.py" | 12 + .../te\303\263rico/examples/ex3grades.py" | 23 + "FP/aula02/te\303\263rico/examplesformat.py" | 52 + "FP/aula02/te\303\263rico/examplesfstring.py" | 51 + "FP/aula02/te\303\263rico/imc.py" | 23 + "FP/aula02/te\303\263rico/kryptonite.py" | 28 + "FP/aula02/te\303\263rico/max2.py" | 13 + .../te\303\263rico/plotPhaseDiagram.py" | 44 + "FP/aula02/te\303\263rico/tp02-selection.pdf" | Bin 0 -> 131 bytes "FP/aula03/te\303\263rico/README.md" | 22 + "FP/aula03/te\303\263rico/aula03.pdf" | Bin 0 -> 131 bytes "FP/aula03/te\303\263rico/bmi.py" | 44 + "FP/aula03/te\303\263rico/dates.py" | 47 + "FP/aula03/te\303\263rico/examples/args.py" | 3 + "FP/aula03/te\303\263rico/examples/funcs1.py" | 58 + "FP/aula03/te\303\263rico/examples/funcs2.py" | 26 + "FP/aula03/te\303\263rico/tp03-functions.pdf" | Bin 0 -> 131 bytes FP/build.sh | 20 + FP/fp.norg | 9 + FP/templates/eisvogel.latex | 1090 +++++++++++++++++ FP/templates/elegant_bootstrap_menu.html | 118 ++ flake.lock | 58 + flake.nix | 53 + nix/neorg-pandoc.nix | 78 ++ nix/neorg-pandoc.patch | 22 + 78 files changed, 3566 insertions(+) create mode 100644 .gitattributes create mode 100644 .github/workflows/deploy.yml create mode 100644 FP/.gitignore create mode 100644 FP/aula00/aula00.norg create mode 100644 FP/aula00/res/graph00.png create mode 100644 FP/aula00/res/graph01.png create mode 100644 FP/aula00/res/graph02.png create mode 100644 FP/aula00/res/plot.py create mode 100644 FP/aula00/res/retangulo.py create mode 100644 FP/aula00/res/solution.py create mode 100644 FP/aula00/res/welcome.py create mode 100644 "FP/aula00/te\303\263rico/README.md" create mode 100644 "FP/aula00/te\303\263rico/aula00.pdf" create mode 100644 "FP/aula00/te\303\263rico/plot.py" create mode 100644 "FP/aula00/te\303\263rico/solution.py" create mode 100644 "FP/aula00/te\303\263rico/welcome.py" create mode 100644 FP/aula01/aula01.norg create mode 100755 FP/aula01/res/aula01e01.py create mode 100755 FP/aula01/res/aula01e02.py create mode 100644 FP/aula01/res/aula01e03.py create mode 100644 FP/aula01/res/aula01e04.py create mode 100644 FP/aula01/res/aula01e05.py create mode 100644 FP/aula01/res/aula01e07.py create mode 100644 FP/aula01/res/aula01e08.py create mode 100644 FP/aula01/res/aula01e09.py create mode 100644 FP/aula01/res/points.py create mode 100644 "FP/aula01/te\303\263rico/README.md" create mode 100644 "FP/aula01/te\303\263rico/aula01.pdf" create mode 100644 "FP/aula01/te\303\263rico/idade.py" create mode 100644 "FP/aula01/te\303\263rico/points.py" create mode 100644 "FP/aula01/te\303\263rico/pointsg.py" create mode 100644 "FP/aula01/te\303\263rico/tp00-computers.pdf" create mode 100644 "FP/aula01/te\303\263rico/tp01-intro.pdf" create mode 100644 FP/aula02/aula02.norg create mode 100644 FP/aula02/res/age.py create mode 100644 FP/aula02/res/aula02e04.py create mode 100644 FP/aula02/res/aula02e05.py create mode 100644 FP/aula02/res/aula02e09.py create mode 100644 FP/aula02/res/darts.py create mode 100644 FP/aula02/res/imc.py create mode 100644 FP/aula02/res/kryptonite.py create mode 100644 FP/aula02/res/max2.py create mode 100644 FP/aula02/res/max3.py create mode 100644 FP/aula02/res/max4.py create mode 100644 "FP/aula02/te\303\263rico/README.md" create mode 100644 "FP/aula02/te\303\263rico/age.py" create mode 100644 "FP/aula02/te\303\263rico/aula02.pdf" create mode 100644 "FP/aula02/te\303\263rico/darts.py" create mode 100644 "FP/aula02/te\303\263rico/examples/ex1if.py" create mode 100644 "FP/aula02/te\303\263rico/examples/ex1ifelse.py" create mode 100644 "FP/aula02/te\303\263rico/examples/ex1raining.py" create mode 100644 "FP/aula02/te\303\263rico/examples/ex2classifier.py" create mode 100644 "FP/aula02/te\303\263rico/examples/ex2ifelifelse.py" create mode 100644 "FP/aula02/te\303\263rico/examples/ex2piecewise.py" create mode 100644 "FP/aula02/te\303\263rico/examples/ex3grades.py" create mode 100644 "FP/aula02/te\303\263rico/examplesformat.py" create mode 100644 "FP/aula02/te\303\263rico/examplesfstring.py" create mode 100644 "FP/aula02/te\303\263rico/imc.py" create mode 100644 "FP/aula02/te\303\263rico/kryptonite.py" create mode 100644 "FP/aula02/te\303\263rico/max2.py" create mode 100644 "FP/aula02/te\303\263rico/plotPhaseDiagram.py" create mode 100644 "FP/aula02/te\303\263rico/tp02-selection.pdf" create mode 100644 "FP/aula03/te\303\263rico/README.md" create mode 100644 "FP/aula03/te\303\263rico/aula03.pdf" create mode 100644 "FP/aula03/te\303\263rico/bmi.py" create mode 100644 "FP/aula03/te\303\263rico/dates.py" create mode 100644 "FP/aula03/te\303\263rico/examples/args.py" create mode 100644 "FP/aula03/te\303\263rico/examples/funcs1.py" create mode 100644 "FP/aula03/te\303\263rico/examples/funcs2.py" create mode 100644 "FP/aula03/te\303\263rico/tp03-functions.pdf" create mode 100755 FP/build.sh create mode 100644 FP/fp.norg create mode 100644 FP/templates/eisvogel.latex create mode 100644 FP/templates/elegant_bootstrap_menu.html create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/neorg-pandoc.nix create mode 100644 nix/neorg-pandoc.patch diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c0a0942 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.pdf filter=lfs diff=lfs merge=lfs -text +*.vpp filter=lfs diff=lfs merge=lfs -text +*.odt filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..848a862 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,14 @@ +name: "Deploy" +on: + pull_request: + push: +jobs: + tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v18 + with: + nix_path: nixpkgs=channel:nixos-unstable + - run: nix build + - run: nix flake check diff --git a/FP/.gitignore b/FP/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/FP/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/FP/aula00/aula00.norg b/FP/aula00/aula00.norg new file mode 100644 index 0000000..87cb7ca --- /dev/null +++ b/FP/aula00/aula00.norg @@ -0,0 +1,317 @@ +@document.meta + title: Aula 00 + description: The beggining of the journey + author: João Capucho +@end + +* Fundamento de Programação, Aula 00 + +** Exercício 1 + + > Antes de começar, confirme que criou uma pasta (diretório) chamada FP (ou + > FundamentosProgramacao) para guardar os materiais desta disciplina. E deve ter + > extraído a pasta da aula dentro de FP, para manter os materiais bem organizados. + + @code bash + $ tree + FP + ├── aula00 + │ ├── aula00.pdf + │ ├── plot.py + │ ├── README.md + │ ├── solution.py + │ └── welcome.py + ├── aula01 + │ ├── aula01.pdf + │ ├── points.py + │ ├── README.md + │ ├── tp00-computers.pdf + │ └── tp01-intro.pdf + @end + +** Exercício 2 + + > No seu computador, siga as instruções para instalar Python que encontra + > na página da cadeira. + + @code bash + $ python3 --version + Python 3.10.6 + @end + +** Exercício 3 + + > Abra uma janela de terminal (ver como aqui) e, na linha de comandos, + > introduza o comando python3 para executar o Python em modo interativo. + + @code bash + $ python3 + Python 3.10.6 (main, Aug 1 2022, 20:38:21) [GCC 11.3.0] on linux + Type "help", "copyright", "credits" or "license" for more information. + >>> + @end + +** Exercício 4 + + > Usando o Python em modo interativo, execute as seguintes instruções: + + @code python + >>> 20-3 + 17 + >>> type(17) + + >>> 1+2.3 + 3.3 + >>> type(1+2.3) + + >>> 'Paris' + 'Paris' + >>> type('Paris') + + >>> 'Paris'/2 + Traceback (most recent call last): + File "", line 1, in + TypeError: unsupported operand type(s) for /: 'str' and 'int' + @end + + > A função type(x) permite determinar o tipo de dados do valor x. Para cada uma das + > expressões abaixo, tente prever o valor e tipo de dados (int, float, str, ...) do + > resultado, ou se dá erro. Depois confirme no Python. + + @table + Expressão | Valor | Tipo + 1 + 2 * 5 | 11 | int + 17 / 3.0 | 5.666666666666667 | float + 17 / 3 | 5.666666666666667 | float + 17 // 3 | 5 | int + 17 % 3.0 | 2.0 | float + 5.0 / 0.75 | 6.666666666666667 | float + 5.0 // 0.75 | 6.0 | float + 'tau' + 'rus' | 'taurus' | str + 'tau' + 2 | erro | N/A + 'tau' * 2 | 'tautau' | str + @end + +** Exercício 5 + + > Em Python podemos guardar valores em variáveis para depois os reutilizar. Por + > exemplo, para guardar as dimensões de um retângulo pode usar as seguintes instruções. + + @code python + >>> largura = 21.0 + >>> altura = 29.7 + @end + + > Agora pode calcular a área do retângulo, guardá-la numa variável e mostrar o seu valor: + + @code python + >>> area = largura * altura + >>> area + 623.6999999999999 + @end + + > Consegue calcular, guardar e mostrar o perímetro? Dê um nome sugestivo à nova variável. + + @code python + >>> perimetro = 2 * largura + 2 * altura + >>> perimetro + 101.4 + @end + +** Exercício 6 + + > Abra um editor de texto (por exemplo, o “Bloco de notas”/Notepad do Windows, “Text + > editor”/gedit no Linux), reescreva as instruções que usou no exercício anterior e + > grave num ficheiro com o nome retangulo.py, dentro da pasta aula00. + + @code python + # retangulo.py + largura = 21.0 + altura = 29.7 + + area = largura * altura + area + + perimetro = 2 * largura + 2 * altura + perimetro + @end + + > Acabou de criar um programa (script) em Python. Para o executar o programa, + > regresse ao terminal e introduza o comando: + + @code bash + $ python3 retangulo.py + $ + @end + + > No editor, corrija o programa para mostrar os resultados explicitamente usando + > a função print, grave e volte a executar o programa. Repita o processo até o + > programa funcionar. + + @code python + # retangulo.py + largura = 21.0 + altura = 29.7 + + area = largura * altura + print(f"area = {area}") + + perimetro = 2 * largura + 2 * altura + print(f"perimetro = {perimetro}") + @end + + @code bash + $ python3 retangulo.py + area = 623.6999999999999 + perimetro = 101.4 + $ + @end + +** Exercício 7 + + > Altere o programa anterior para pedir ao utilizador as dimensões do retângulo + > (usando a função input). + + @code python + # Pede ao utilizador para inserir a largura + larguraStr = input("Insira a largura do retângulo: ") + # Tenta transformar de uma string para um int + largura = float(larguraStr) + # Pede ao utilizador para inserir a altura + alturaStr = input("Insira a altura do retângulo: ") + # Tenta transformar de uma string para um int + altura = float(alturaStr) + + # Calcula a area + area = largura * altura + print(f"area = {area}") + + # Calcula o perimetro + perimetro = 2 * largura + 2 * altura + print(f"perimetro = {perimetro}") + @end + +** Exercício 8 + + > Execute o programa welcome.py para ver o que acontece. Modifique o programa + > para que o X seja substituído pelo curso indicado pelo utilizador. + + @code bash + $ python3 welcome.py + Primeiro nome? João + Apelido? Capucho + Curso? LEI + Olá João Capucho! + Bem vindo ao curso de X! + @end + + @code python + # welcome.py + # coding: utf-8 + + # Execute the program and see what happens. + # Then modify the program so that X is replaced by the course input. + # Hint: see what we did with the name and surname. + + name = input("Primeiro nome? ") + surname = input("Apelido? ") + course = input("Curso? ") + + print("Olá {} {}!\nBem vindo ao curso de {}!".format(name, surname, course)) + @end + + @code bash + $ python3 welcome.py + Primeiro nome? João + Apelido? Capucho + Curso? LEI + Olá João Capucho! + Bem vindo ao curso de LEI! + @end + +** Exercício 9 + + > O programa plot.py traça os gráficos de duas funções. Experimente executá-lo. + + @code bash + $ python3 plot.py + @end + + @embed image + ./res/graph00.png + @end + + > Experimente colocar uma instrução print para imprimir o valor de alguma + > variável ou modifique um parâmetro de alguma expressão. Depois grave + > e volte a executar o para ver o que acontece. + + @code python + # plot.py + # Try running this program. + # Then change it to generate another subplot with the product of y1 and y2. + + import numpy as np + import matplotlib.pyplot as plt + + plt.figure(1) + + t = np.arange(0.0, 5.0, 0.1) # try printing t + + print(t) + + plt.subplot(2, 1, 1) + y1 = np.exp(-t) + plt.plot(t, y1, "k+") # try 'g' or 'bo' or 'k+' + + plt.subplot(2, 1, 2) + y2 = np.cos(2 * np.pi * t) + plt.plot(t, y2, "ro-") + + plt.show() + @end + + @code bash + $ python3 plot.py + [0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. 1.1 1.2 1.3 1.4 1.5 1.6 1.7 + 1.8 1.9 2. 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3. 3.1 3.2 3.3 3.4 3.5 + 3.6 3.7 3.8 3.9 4. 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9] + @end + + @embed image + ./res/graph01.png + @end + +** Exercício 10 + + > Altere o programa anterior para gerar um terceiro gráfico com o produto + > das funções y1 e y2. Trace o gráfico com linhas e bolas verdes. + + @code python + # plot.py + # Try running this program. + # Then change it to generate another subplot with the product of y1 and y2. + + import numpy as np + import matplotlib.pyplot as plt + + plt.figure(1) + + t = np.arange(0.0, 5.0, 0.1) # try printing t + + plt.subplot(3, 1, 1) + y1 = np.exp(-t) + plt.plot(t, y1, "b") # try 'g' or 'bo' or 'k+' + + plt.subplot(3, 1, 2) + y2 = np.cos(2 * np.pi * t) + plt.plot(t, y2, "ro-") + + plt.subplot(3, 1, 3) + plt.plot(t, y1 * y2, "go-") + + plt.show() + @end + + @embed image + ./res/graph02.png + @end diff --git a/FP/aula00/res/graph00.png b/FP/aula00/res/graph00.png new file mode 100644 index 0000000000000000000000000000000000000000..5bc03cfe495904caa45acf723e748c228363d3c8 GIT binary patch literal 32055 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 literal 0 HcmV?d00001 diff --git a/FP/aula00/res/graph02.png b/FP/aula00/res/graph02.png new file mode 100644 index 0000000000000000000000000000000000000000..e2267973646e1c60671efb54ea55c93cb820df68 GIT binary patch literal 27324 zcmeEuby$?$*X|4{($bA|iini7v?PI{%%&j@R{GFY`RlUc1&_d+mGOYsYG7suEwNzY2jsh}G4UbRZBc7z6^H zy@Cgxhz?IJg8xbSC>#0cy4(BsTYK3-G^~9*T-<$J9^0_`*?Dq zkB9diAtBd)KDgoT_5O}B=dqW_k)|mgGMRJ9YArL2CbtMJ8fOnhI!De~~ zjdI(A5UeD;J38_RP{&WqfoV*^=TN`< z_%Uy8Ztm=g!}m`&yIK7<#;;F@?DgwBdX$eNZ_*mpGMU}o*Y^^Sgpmgq7gycW)ARd$ zM|_4)-}!k60Yuzws@`+qn?|&0Sl9)X0n@2NI(6IbuGjwh80pcpKZ{$_rWpK;Maqw8 zp)V1Bv-qR-N=x8g4V+975L@5AO#Iu{g+Wt|j z3$(H5$V5pAr=+x0+stfZ-+_;x-@49Z-4(Gt`?M{JxGhl}3l~>b5(lHs>5mEJbF4=y zIn*^R;rAatR1F9S*rcYQSa?xC6M!8Pj~#YKOe=a-B6NZ~`Z`AMZ@EIpt8G=^-SI7% zaaLAVzH;S?{NyLs%!|HvlHOW6Iyy~DD=TLlpH>}bODkdNw6lfTu;IK8S8L3wkxc&t z0mGrBqN36=_Q`cJO5rKqd*d2=&2TOro+7`t=t}%BpWke8ZACn@(JU}wTbSI%_OCh2 z`cneq_bM&zy0|z^Lqh|k{k9PJU)R~7TAZZ!^6X47s(kwLeKhkIRO@9@ZS8GF*$`S3 z;_Svu;0lxU;kd2SGt`fthS-*21U{>f#bqqpPAu6qKg<&5vPs9fDJ8{#jYrf5gJMG< zj~_p#y=eu>3Ojuak+-(Cb``z?0opR&94K;2L}a)%JY4$nd@o=jQCvC;ONDpLj6JUH zlWRoi8SEuxPT7OaBG6p5L4nlJMQqVGVEzLFB<|h27a~hKdx5sm+dkQAiy?1w$c74< z9Pd8|4T#ELJTNUK8o_e(!N!ARhm$;u!g}*Y-ic33`@NqY_#j_Z0OGsYxDG2fjd)JR z%8s2bO;=Q+BgF?s^g9DJ?2d>}Q9XLHxgp@4^c%qlP~yjJP+~QT0hY)Rk;6Ls;vsBj zA>zAET^?oUa0zeZzoYZft4 z0UdeFL@1wmUk&o{WBaaWG%5DiD5z@EU$5v0<+1CR>8-|Y8bG&4pv0?6XzOp0IwZC3KFhTKj!C|4SO zor-1FeC0tpq|BoH&jH{RfDjic6Iy-6v+ALo{m!{_JRc7+4CMk1hvDW}KjqDn}<<4 zEw6MyRk{eq%=g9O=BOty5r&{e$!PEyWv+5?VbRe!sVal^Iaxs+*<^yTkRjM+;VtQ0 zT%5Q@%|?Gt_hTTgAT)TkS12MFh3g_VI~N^cTmxHks$*vd?f6gyx&0nY1o|j~#)8bU zbqCL*SFnvGyojC}3^4CAP^qzijZ=EE9Nt@T{7)`WJQ5r)uOCSXph+Q#xH;V#SpuU( zh&8_1V^6D9tzn_(FH|VV$?0ea<-fq7xl2N#R7EA%&{!x00}sEh)GbiuE-p0;N51TO zvm4WP55LX#)nr+$iYAid9o0XZ)KCq{H=!onzPw<0{)RwFIkr2uvW40RVYb-?Dpk`I zfD}hqe}$pXB8KxK2x(x&x)H4xR7FKve@IWoCY1LoQN*`eH<*3npwv5?%4q}Z5^61C zq5~ZY1Y2ptB8s#xlmF^xzfGl5tILbF*2{kFFJKshzF|F|x~J(kbqx_fo-V0dCK$4t zKam284X0T_)tF2wN6Vd5Re*pjAls0G6%ugz*a~H# zO-4gv%OeH^e&Ign}8@w2!$X2=>=-Lr#kuJwd}#oI&Nz{TbMM zE7+DHP@msei%U=nF31aR@BEwKHFY(F<5vPbF5?{>>5KYRhI&6iG8WQv)FqZ!#>6m2 z09Zn)`tj6l@j`KvUlgMtA3n5&qhALg!dw4%Pu_<0JS5-U((1^~YR86Enz3tu8jU;h zT|(^{myTkc8ESedMgaxnQ0o2I}HfD(*bci!rzToABQBB~D$kNael$jB@%n0Dc zF0Nq1r|}XPdEKahnxuRr(udqIsl5WM*cB2ImAiMbK7RaYww3Yb4MBXzcdN7Ch1rw| z<7PTK?W`%67w*;XrjnTEKW*>-mRE@QqkV6pt*^G}ml{|fZu|;ZD=w@GzYOEx}VK@-TJ9O?Oajgg9GD(u7k2)Ak2N*4AFGcBpR zV5$~G9zc&LoGa%p&QP6}7rQj=ot?H|GmMFi{R}o`26O`n)14gK&ZN4G*4Ea$K#O4`RVdqhKd_*Eedt3nt9j#g;vyw@{>DqW)+c^mR4m_ejv6xF#Fl2cDpA{er2F7mZI%PvCTxf%GNAquxN<1 zA=ET9U+rtaewRD54yI4SckSg!c5FgIdn)JsD!)yWGE+E-OwfK?k#=5{_loB0PWAun zob2m?>1iEoDg>AN6wk9T#{BFM3d||kagbr9e$POQzuBa4pdWtI*3yD$X5O(L%#u-i z@SrRdoqc)EEqgqRos94IApItkIvzJe%+>1@-P3bV&%j_b%(c#hoPy$MYU;ITk&%J^ z*Ywu+AA3q2XZiy}vop~z9xwX@8?T6gft>tz_8%KheQ_l+$`R@^R>5?RMl;kNQc+Qf zI#RjxJ-@E#vDiia8cBNf>Rlrvqn5-)8ggj!NdYa-tc!SqDYw5cFs1Ctt?=Wy`ohOS4&D^M>7-@>PX+$_4>_j znMQVt15(Nnm|4D8JpPS{Ly7Oz#k)saHtpM=pSCS_+pMLh@pr_r z9nJ7BQ)9gLLEIuHm|4MtH&1FD2Im`AvJ|bYuLm7%CH7~C=XtLTKwv;igS@c}^!4Ye zJDIp&wK>|+#IovgWaeC-^tg%C#J=5s(ZugrMGuS$X5`bb)|68jLQ_c;u)TJ_Tp z(`a%6kev zn*%EM_;K5Co(=sQu=B=Uot^fNc!mS^4dIe>cyw$`R~beaE?!)0e(M>@c-{Rzrtz{j ztK0#DGV%|Iwtwj6c7VOG>j6fVu|V6w7&gBFBrvdTZ!q5Ui^D*S={NI6$O|s0=_d%r zzJX)W2{WPmt+XVj2w**gtsZTfSS_mM6yO=PGSkX2$0Sl=tB0K^Z>oWlQb;r|>l+<; znB&3O8h>?aS2&tx=#!w97V9$g#;{^7JpwIeRae3!2>Q|t>i>PPK_FlRc_+=gOx66G zOE`8vOQsE*G{)d7*k(Vu)09U7)e7oNlW%T&)1Fvbr6nK?G^p*NoTNo^62??+)hj0O zEPwP?Qab&*E>0+4xsClOBo!xQFOdhwu%awns@~a9Rd~EfJYE5KMzaSQxH*Q$&|9zL zt_te}EZxJnPVqEM$n{^kluvXEAk$5yH0)sdJO7qtVQ1G?m>p;1(Mz3E(zDYNhKBvn zvzk{DCJ;5ni;by`9CN3JST!$i9D5%z*L<1vl2$==j*8*cdhQ z=CB&b{#7}7pN4sx*_uHZF#~K+t};BMUY}q1OTfI6)s#f_BPQT0B>ydt-g}2_yMrc| z_I#0|dN;%$9Bj96En1BsL6I!1jXJFtS6!z0K5b5dEuRs&w})NPq)GWKPX+oEA3Gvq zt>d23quYNsl_NUtDscR?iNY=^ zk(8GZ8?*7ZTs2ow(cDN6u)Pj4?;KCM6CbS)LF*4EPEF4adphqc<>UU{t9<1`P06^= z(@ha51ojPcr+Ukkfh3!4;C)A6L&FkcyNLdgNqWNqhlCMwxasX8hh7XpR+x93cKE_I zGXu`jV-o(E`Tdf7oUZO-OUmUXNhI9WRQn1EEo6V4`;^AQo0yET%&|*J>EqmAn#aa2 z8EjBXxrHQMT#nn^wyuurUIJTxX(e@sRi(vzwZA)XvK25CBG2j$`;xDGpY3(YRybzrrBi-YnU z<_=v*-ypd{tiQz=)5Z8t5oui=wz$uYk#m);agu}#&Z0Q&tS@hvw^P%s1h^sZ-VI@r zA*Um*L<&G!zL1io_;aY2`JPX@Cq3C7vt*iF>Yb4s`Bd(xkPz$X;@g@OH{V9dR`QSX zcfrdHFvktsPS`?chr!XwQtzzf!V1362G6ocLY&jFWB5!7)ru6yEkcXd2uK|^E1MUm z0MY7*s>{GTIiY2tzCnL!3xs(i4kcwwx$x)DxmsmS%1XCG$`$c*lnH-5Op8&|2GEWg z+@$WBDH1WzYN^ZaCY&uX$Ak4StL)MU7%cg+B9B^u#*y4e9vmqjGG{)^i)M4F>N;0` zW<|wcjbMtt0O*LQH|z{<+xhLNvZbt2~Oi%53z6D$BV-D;V&68<7_qhbfmLBJzORUQWnaA)J-W^zYIQhDy( zsi;phDH_9NZ}QSc5Or?mm+RXeoz&FJ0k!Uo5JjZ{44Ae1yknlHtO7AnlilE!EDqAYmp~= zE9|_y-AflzejD;8CiK7&d{$J%bH2cG*``P;lW*0oq(p2ikaV|%H`3Pp^^MrcpNF|s zwLf<1(1FwaPPje29qm&CpGx>T&n5^TTJ9eCQ$E}Jl#>&cQ96c=JuP=<5({gb&l8cMWQ*<(uRMgHw=RyQNbKCAxZ*}mI zoAmkiS4Sj527?Dt4Zvd5Wc%Mr;=Sm4UviJ~$bgNoUWt z`uQoo?QC0wQFDOjrt{9uj+%ysa!^pvQ#4EXxu?rSEkQIXOGW4=2J(o&#@{{|vkdlm zpvj@G#F71$KIh{{Yi%R{(z3G4gO2!l(X;i#l>tOW8D*r4Z88|Ml|$->H8nUy?z#mr8k)^v4EeZ!xzqvkvD|AdS?}H@$OIospx;!sUeI@UcOO_V zNcjn1&=s>rAAOi4KW_s7C9&f-`};o9XB#!UxSC2zZy!}lxQ#_UD`HASsio%8 z*3v|aiXOx(Ib?)pH=bEsm`tl0B46Z3otYyzIf^nlZEq<-9UU6VYMyYY6I*!0TWiKP zm;2s4t*xz{s4O?&x2dR&76VR6j{vo5>*pNSy1eV0bh(iK&9h#rSs$;?8$n}ZVGVt9 zH7%5*prm}pdckrRcqw;)1Nb}D@3W}X>?(84It^iDpPc+AJ6i}k`z?_H zgMI$?=p7t<-NHOfs8|cZYJ176>v6bYEPXWP%_AV7gqmro4&1Z%*_xt*Xc-yBG&eU- zpcm%ntH49))78A=qt?qruu7YEzAuSZnx=BReD#WrkFTe5`0;D&W$11C0quN&WmDrm_{Vg2yFWg!Ovs*q z{(;qh{0|17c=hVlFCv4|UmrVAe)&Tj^;LSSFC*^1orsr?p#$|_J z7;jb)Iq%GOtWLs(z`+853Q_ItN-n=XDsNUjV3(0$0!KJ-5HXOVRD3Jte?x%!eoHwx z)jCCg;1__1+W#!kPnQW6%L-cK#hjwl)z#J1)r;W?Ox=ae&5Y>NgRfsA34fAwYy&Vm zf=1JN;pZ4d$;6aMV;MpYaN(|jfp3Z8GcmCg-1Fev

cm zaCW%)6&zZJ;O>@nio&%PEkWkV4x7)X2kR+s z-)-%n4 ztH@Tl<-zPqKcgrS|1C3@@hT|5Y@MQWOgog#?U&Epf4PVOUB9-pv;+>vdQyyv8N#-BZjHaW5}0L7HnoUQT`BA_adCIe%ow)- z48$lCq__Fphf{tN()GT+o>nY_7@X4%ERthl+JLFhi;GhWOXavOC`kM@idYd0BxrvX z3A1zzm@qv(y&SvVS4OR2GC_wM#h|@)UQ72v0Pa5ych3eLo0&JTxy*|MR})6-)r z%$sa}fB&F%|Guv9Ei|a)`sPI4)7IATr=tjI?Al^3u}Ndj|eZjJb$0_-#$aMiSEGe*Adt z;^Kl&#nI*Z_3Nu6g``Q0lDU37jh|&<^w(%NIH4t$4N%Hl%N+NyaQ+!f3adEgG!)-^hEyS7I;_~vx zbmA)0<3wXJTefTJFy%Wz5`>K3RMLR+Pen z2SoSo->(L9`pDkiW*tC+K<4}R?}<-qqMkj=0b{?hvWA^3b4bheARRV7ZbV5%g;8LD z6{U;0zMXjg8;?*v@y#u}s{>gw@he%uB$1JktJ6*5V(v2u1DR5#OmDB-IXKuZcBRx= zPM#$_$Pgn2laIKkP4^R5L|KM+e5!h$5nU(h_{MYw`={9sUsEe}Z55kAYGA{ftAM zM^I2%Pml8ayzdvozz;!~l>b(HuTX2kyLXI~)YM{u*JhtQ!D?@BKfZyni@R??z-xp= zMZ_2CXoK;>UA1?s-Z=nu^VgL?d>Xx!XyV&+G zODkRmc10T-r^*HUcGI>?PtIPLak;^>=;*xse5EWbkLf#ByN_mf!>^rfE{QtB)L%5q zkr4dLtote-uER;HA?Kt&3FR}0SHI&*cz)4`$@|>)*r09ujnmxuugd(5AYROET)@Y8 z_S2~x-p$3|dmuzAf3E)~Tj-D-^{;J(i^&E$j`REX?<=IFmD7)yAUZ}osIVUr|JqaX z6$Ky}7_^Cpm$!I&cW-Yg*!!V_(2BsyuGQb06ZM|PokwfhZ5mWy2hYi2MK%ZOq^`1i z?LPXd+3qJSY$La8VGDQONOwPZC%YNOvTQ2b(Xn-8jabsvnFl{JZhr$a0ra-cSqv-5 z4uleSUy^=9vKUp#OZ$r!`*_`wBI})7NRDXae^}phlqh}+=>_a#{h3?mSjDbPh{T>? z^g}t^t;XJ+y3!EfoPytja`Du<;KJXLT z)_xN2O_!tv0KcT~;mTS|k*tH{=^8)lA0dfA%eo$4#8??LD|`kcxGx2z?$ZInVH^-0 zb@kY0cQbQA^-1{s?{QS~JKs6gPtTB?>Qjub@}pT^<*zz+j=_$DHcbK-hHC1Z8J3I8 zrPOziXa-RYs*A>{?^e!=3mN5(##(P7x9WTR6B-Zn_Lx zo@8=3aYI_9z7?eydFX5}MtO;q|ezLGq@X!GtiMtOFp_lUnz zB5W%wINja<-ID1tF%&U%KPb`L;J*8-4Qh(&1k|Qd&C}hT_dX@KPWWC*0SD7+90NF|5*^;`8?FH zpfBAj(=S9+`{2RaX7+f5=-{y|^b zQkOBp6mE}L589GME;s4(FE>>*?i~vw5l5BbCt^TP`~1x-5qy>i^V!=sQ`@QKW!~Oa ze;`#A+GIq8(zrXOJeDU9~3zh0jb@sjPwppW!pDZ}i{I4|s5I zR~ET=?FvTe~fAi?rAAA+OV*QvN+nv*@_H}RYqmfP+@fVM*uAAOK%0_?le6u$Wt?c~ zlGoO|08|N|)n!;tc=*YTX=O=CyTkT|u~jcMzzI)gnzm3S?g%Kr?hr?#r64vSb-4f7 zYJ|(`3r;qp3dNXvS~ac~%EpF~21Y8YB~D##RHJf!cXL?r!m=nOrER=={^XMf~EZWfG3>)~GIR*{C-Iq-ta+?a(j~CeU6-1;Zb+oAg7MC%0+_!9zNN z1Uhz9aCD@k$wj*R+}@z_&KRPlxkF5}4QuF1!9$wl`>*e?NZN^^T7{SkAG(kKG9ft( z5i;d6!Rj9fn|mwP4?nR$nAMV`XQKB)Q7y1+(y++MJ@i~OusFM|tuy0$GQK75cr4?4 z=wVfPyAS86O7X)Gq&MkM*_)F0v`p^MUr;+c**oTqUEv9h@L4f;JRO}yxhM;O3mII#rJsFm33HoX zlv9~D^`_A3O?i+%2$sSP;!2HZ|H`A}mAAM*J#FrD)azxL3d@pF$EgujS)ut0F|?%*NQ zWsodkJaMh>6+?B;q4M$&kE3bKhb=adJQsMxyP$N8K}WG}hj-0N@J~MN^Mm!3k@;jC zYM6?3YhqQ9sK?xslJ`Xg1>bfEe`JwbR<~YG)FoCHIz39&yF9EE0+OtsItGfetCt{K zKEK|$%*qa7GqLEu_dCS>*B^frhfqMMVc&#Z(rKY)CRfWWEB$V-b@f~u;Rk_*;$no% zC48_ugqD4IxV;mz64_r&3*sz%vWtL+7(vV<*@}6#J*tvGC{A6MHZWthHp(A~(XQ&R>F8h9%)YkT9bwz{9xn}h*CH_h}^ghM*COj8+VrKrKYzNj5&-po{ zcfp$ju_x$e_f{sy;VqWXy}l{!R+tWqK_=uIn}UVBy34TvAW%l!q(1r7OvD?Wn2} zJ`gNcA}li=cd;?adxAAwt`b3zE$WXpfSN)Q7eOd&?yIuG$B>4JVV+)D8uPIV5J}

&EOvnzu5husFlIuK8pDv*- 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

&PaMGEjEF~m25-fUpIkL zRoUQrbTX~AuPPR_hJ9@hg@D8)W6Xgakg}2|-mi|eMc628&sup_H#gHlm9jHG-deI1 z$pwig2}HxYMrG)53|t33y3PAhu( z4zl93R(r%}ookngn#;s0bICLn)+WDX%dQMi1CBQw95I&T6-EMW8^4;>dOn1Qd-8v$ zS~j%+Ntswfm_K%anll=vy9fHBZZvMye+glrCv4*?`irIW#=?NwV>w|R<^3uk(9TX& z)+_ns70q6GS((5v>JLGE@M5|W$h$wOk$I+meuq@8;eTUC>FKm|d1Jf-*DC)_2rZz_ z@q>81mGtJ?@)$9$yZ`!z;rWI4a-V{Ui3x^#oTkj`5Nr5185F}J)fLf$j#rpV)jE$2 zIG|YmuY!!xU&{D&yf`|RYC|J72-7zMlgz7q1nKjA+9nc>dkzk8j_)*UX&Oi8%ba4;agjZ2r02 zB1Z+(H220KYp(g}RqKB^A(*Y?tjB}w3ZPnoi!*Tl4>x5LDF7NWhN$`E>C=?w&tX6T zFqGO%DSw+U&j>J$14Pp(Vul|i-BsU5Mm#s`#@KG(rewO~Bk$zI7j|*tQ1|s#Sw}og zo;wmz=bgvN#bwj`O3*3Vjvf%bs*D5xi}n+sX?~w-@V2ftT61NR^3#(NFbDUG2$vd^ zf7$p|v-3muq4nhjTJ7GwyZ7#01$3+*B>m5OdV7Z}E#(Bv>a_r))V(u_DIJhZ54Wb{ z6B3B@3=P>OCFuYG6+;&s9v%+Z>7Yr;%uL+aaG3(>|LGE*Y#=)U0BBKgcciR<@kbm$ zwbaM3J%5(cTqPuQh6DCv2~%o?2W8baB4%k?Y^- zT4|a5tf}ps1i3(>8=TQF{9N*SWdz|6uGt)YSZzB@+y&uwCK+ z2!X`pJ`3r!ud!b0N#hX`Qnj(kotUGYNT3t(7|{^7-d`Pdina+*O=464_N zX91_&DLS9ujL=9Cgb%E1egO`mHtHZI<_fqG;@*d%m_=^&Yaq+>rpx%v{jF(JKxkbD z>QHTmQcd$2y1=P;NBCeMi9u%g``85#|St(Ylpju;FPm{vt_tA^+4{^Pz3 zaZ)f49q$#RF=YC>uOlF(o&FJ+-%vpeE*!J(0+8WjkV0JTJaz-aZf2GVVg;*pWiY#Q zqRv^^b>jBMc=c1|9MZ*=728n|ssH5408|h#WVgXZ6;9b;pTUofja{9n<9~I-JPv@Q zRO}<9ppx&vTpXXBi92rc^YJ+i@u}q-CQI*L5p$h*29%cV&K(obFF}wFYiJoN3b7i> zQ2<0?7HR<_z_Sawztok$4aOW?j-jTeRutL~h8R%Fjp{wF17hqP3RP+I>>Ks9YfofD zPiFy%8N-0xz%IHT5fK5tm;d8#43S&6Fa+bYT(;C`4)t_k?MBN@qbm`oS3wT9Q}m-d zsT}V=e$?5#N%Z(fk+wv@HY;GoI>W(r8gpAsC>3C(;^kOC`bRrRvL&aZE5;CcspS*Z z@8AClt_Tr!9Af1FYp6Sw^FJtX6i6|SvJ6Mp9j*h4I>zd`PSh&6xRe1R_#jYrd7fHzwwI1PBKjx)^-J;QW^FCNOqzI;gu2⩔wUl5^mF(@g0HL)6Lr$lspU9DO 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 literal 0 HcmV?d00001 diff --git a/FP/aula00/res/plot.py b/FP/aula00/res/plot.py new file mode 100644 index 0000000..45ba682 --- /dev/null +++ b/FP/aula00/res/plot.py @@ -0,0 +1,22 @@ +# Try running this program. +# Then change it to generate another subplot with the product of y1 and y2. + +import numpy as np +import matplotlib.pyplot as plt + +plt.figure(1) + +t = np.arange(0.0, 5.0, 0.1) # try printing t + +plt.subplot(3, 1, 1) +y1 = np.exp(-t) +plt.plot(t, y1, "b") # try 'g' or 'bo' or 'k+' + +plt.subplot(3, 1, 2) +y2 = np.cos(2 * np.pi * t) +plt.plot(t, y2, "ro-") + +plt.subplot(3, 1, 3) +plt.plot(t, y1 * y2, "go-") + +plt.show() diff --git a/FP/aula00/res/retangulo.py b/FP/aula00/res/retangulo.py new file mode 100644 index 0000000..5848f10 --- /dev/null +++ b/FP/aula00/res/retangulo.py @@ -0,0 +1,10 @@ +larguraStr = input("Insira a largura do retângulo: ") +largura = float(larguraStr) +alturaStr = input("Insira a altura do retângulo: ") +altura = float(alturaStr) + +area = largura * altura +print(f"area = {area}") + +perimetro = 2 * largura + 2 * altura +print(f"perimetro = {perimetro}") diff --git a/FP/aula00/res/solution.py b/FP/aula00/res/solution.py new file mode 100644 index 0000000..f02bebf --- /dev/null +++ b/FP/aula00/res/solution.py @@ -0,0 +1,11 @@ +# Este programa é a solução de um dos exercícios da aula. + +largura = float(input('Largura? ')) +altura = float(input('Altura? ')) + +area = largura * altura +perimetro = largura*2 + altura*2 + +print('Area:', area) +print('Perimetro:', perimetro) + diff --git a/FP/aula00/res/welcome.py b/FP/aula00/res/welcome.py new file mode 100644 index 0000000..7f2906d --- /dev/null +++ b/FP/aula00/res/welcome.py @@ -0,0 +1,11 @@ +# coding: utf-8 + +# Execute the program and see what happens. +# Then modify the program so that X is replaced by the course input. +# Hint: see what we did with the name and surname. + +name = input("Primeiro nome? ") +surname = input("Apelido? ") +course = input("Curso? ") + +print("Olá {} {}!\nBem vindo ao curso de {}!".format(name, surname, course)) diff --git "a/FP/aula00/te\303\263rico/README.md" "b/FP/aula00/te\303\263rico/README.md" new file mode 100644 index 0000000..988fafc --- /dev/null +++ "b/FP/aula00/te\303\263rico/README.md" @@ -0,0 +1,14 @@ +# Bibliografia para aula 01. + +* Slides e guião disponibilizados nesta pasta. +* [1, capítulo 1](https://elearning.ua.pt/mod/lti/view.php?id=1139979) +(Semelhante a [2, capítulo 1]). + +# Trabalho para casa (Homework) + +Ler e resolver os exercícios referentes a esta aula do livro recomendado [1]. + +[1] [Python for Everybody - Interactive] + +[2] [Think Python 2e](http://greenteapress.com/wp/think-python-2e/) + diff --git "a/FP/aula00/te\303\263rico/aula00.pdf" "b/FP/aula00/te\303\263rico/aula00.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..e9503ec07233c958028d0c2ec3af852f6fe38002 GIT binary patch literal 131 zcmWN_K@P$o5CFhCuiyg~*204Q4GW8qs5CC^!Pnc+d>f?L&&&7biqgW NSe5i2YY5&Ws6RYJC*uGB literal 0 HcmV?d00001 diff --git "a/FP/aula00/te\303\263rico/plot.py" "b/FP/aula00/te\303\263rico/plot.py" new file mode 100644 index 0000000..83bd3e5 --- /dev/null +++ "b/FP/aula00/te\303\263rico/plot.py" @@ -0,0 +1,20 @@ +# Try running this program. +# Then change it to generate another subplot with the product of y1 and y2. + +import numpy as np +import matplotlib.pyplot as plt + +plt.figure(1) + +t = np.arange(0.0, 5.0, 0.1) # try printing t + +plt.subplot(2, 1, 1) +y1 = np.exp(-t) +plt.plot(t, y1, 'b') # try 'g' or 'bo' or 'k+' + +plt.subplot(2, 1, 2) +y2 = np.cos(2*np.pi*t) +plt.plot(t, y2, 'ro-') + +plt.show() + diff --git "a/FP/aula00/te\303\263rico/solution.py" "b/FP/aula00/te\303\263rico/solution.py" new file mode 100644 index 0000000..f02bebf --- /dev/null +++ "b/FP/aula00/te\303\263rico/solution.py" @@ -0,0 +1,11 @@ +# Este programa é a solução de um dos exercícios da aula. + +largura = float(input('Largura? ')) +altura = float(input('Altura? ')) + +area = largura * altura +perimetro = largura*2 + altura*2 + +print('Area:', area) +print('Perimetro:', perimetro) + diff --git "a/FP/aula00/te\303\263rico/welcome.py" "b/FP/aula00/te\303\263rico/welcome.py" new file mode 100644 index 0000000..faf236c --- /dev/null +++ "b/FP/aula00/te\303\263rico/welcome.py" @@ -0,0 +1,12 @@ +# coding: utf-8 + +# Execute the program and see what happens. +# Then modify the program so that X is replaced by the course input. +# Hint: see what we did with the name and surname. + +name = input("Primeiro nome? ") +surname = input("Apelido? ") +course = input("Curso? ") + +print("Olá {} {}!\nBem vindo ao curso de X!".format(name, surname)) + diff --git a/FP/aula01/aula01.norg b/FP/aula01/aula01.norg new file mode 100644 index 0000000..e809949 --- /dev/null +++ b/FP/aula01/aula01.norg @@ -0,0 +1,264 @@ +* Fundamento de Programação, Aula 01 + +** Exercício 1 + + > Escreva um programa que lê um valor de temperatura em graus Celsius, + > converte-o para graus Fahrenheit e imprime o resultado na forma "XX ºC = YY ºF". + > A fórmula de conversão de graus Celsius (C) para graus Fahrenheit (F) + > é a seguinte: F = 1.8∙C + 32. + + @code python + # Pede ao utilizador para inserir a temperatura em celsius + valorStr = input("Temperature (ºC)? ") + + # Tenta transformar de uma string para um float + valor = float(valorStr) + + # Converte de celsius para fahrenheit + valorFahrenheit = 1.8 * valor + 32 + + # Mostra ao utilizador o resultado + print(f"{valor} ºC = {valorFahrenheit} ºF") + @end + +** Exercício 2 + + > Repare no seguinte exemplo de interação com um programa em Python. + > O texto à frente dos pontos de interrogação foi introduzido pela + > utilizadora. Consegue fazer um programa semelhante? + + @code python + # Pede ao utilizador para inserir o nome + nome = input("Como te chamas? ") + + # Pede ao utilizador para inserir o ano em que nasceu + anoStr = input("Como te chamas? ") + + # Tenta transformar de uma string para um int + ano = int(anoStr) + + # Calcula a idade do utilizador em 2020 + idade2020 = 2020 - ano + + print(f"{nome}, em 2020 farás 33 anos.") + @end + +** Exercício 3 + + > Um automóvel faz uma viagem entre duas cidades com velocidade média v1 + > e regressa pelo mesmo percurso com velocidade média v2. Escreva um programa + > que peça os dois valores, v1 e v2, e calcule e imprima a velocidade média + > da viagem completa. + + @code python + # Pede ao utilizador para inserir a primeira velocidade + v1Str = input("Insira a primeira velocidade (v1): ") + # Tenta transformar a string inserida num float + v1 = float(v1Str) + + # Pede ao utilizador para inserir a segunda velocidade + v2Str = input("Insira a segunda velocidade (v2): ") + # Tenta transformar a string inserida num float + v2 = float(v2Str) + + # Note que a velocidade média é calculada pela distância percorrida + # a dividir pelo tempo total: v=d/t. + # + # Como nós temos duas velocidades, v1 e v2, e a distância percorrida + # é a mesma nas duas, as velocidades são definidas por v1=d/t1 e v2=d/t2, + # logo queremos calcular v=2d/(t1 + t2) ou seja + # v=2d/(d/v1 + d/v2) + # <=> v = 2d/((dv2 + dv1)/v1v2) + # <=> v = 2d/(d(v1 + v2)/v1v2) + # <=> v = 2dv1v2/(d(v1 + v2) + # <=> v = 2v1v2/(v1 + v2) + v = 2 * v1 * v2 / (v1 + v2) + + # Formata e imprime os resultados + print("A velocidade média é", v) + @end + +** Exercício 4 + + > Escreva um programa que dado um tempo em segundos lido do teclado, mostre + > na consola o tempo com o formato hh:mm:ss. + + @code python + # Pede ao utilizador para inserir o tempo em segundos + secsStr = input("Segundos (s)? ") + + # Tenta transformar de uma string para um int + rawSecs = int(secsStr) + + # Calculate the time components + secs = rawSecs % 60 + mins = (rawSecs // 60) % 60 + hours = rawSecs // 3600 + + # Formata e imprime os resultados + print(f"{hours:02d}:{mins:02d}:{secs:02d}") + @end + +** Exercício 5 + + > Um triângulo retângulo tem catetos A e B e hipotenusa C. Escreva um programa + > que leia os comprimentos dos catetos e determine a hipotenusa, bem como o + > valor do ângulo (em graus) entre o lado A e a hipotenusa. + + @code python + import math + + # Pede ao utilizador para inserir o comprimento dos catetos + catetoA = float(input("Comprimento do cateto A (m)? ")) + catetoB = float(input("Comprimento do cateto B (m)? ")) + + # Calcula a hipotenusa + hipo = math.sqrt(catetoA**2 + catetoB**2) + + # Calcula o ângulo em radianos entre a hipotenusa e o cateto A + angleRad = math.acos(catetoA / hipo) + # Transforma de radianos para graus + angle = angleRad * 180 / math.pi + + # Formata e imprime os resultados + print(f"A hipotenusa têm {hipo} m e faz um ângulo de {angle} graus com o cateto A") + @end + +** Exercício 6 + + > O programa points.py lê as coordenadas cartesianas de dois pontos, (x1, y1) e + > (x2, y2). Complete-o para calcular e imprimir a distância entre os pontos. + + @code python + import math + + # This program reads the coordinates of two points (x1,y1) and (x2,y2). + + x1 = float(input("x1? ")) + y1 = float(input("y1? ")) + x2 = float(input("x2? ")) + y2 = float(input("y2? ")) + + # Find and print the distance between the points! + # + # The distance between two points is given by the square root + # of the squares of the difference between the components of the + # two points + distance = math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2) + + # Format and print + print(f"A distância entre os dois pontos é {distance}") + @end + +** Exercício 7 + + > Num prédio com R/C e 3 andares e 2 moradores por andar, cada morador sobe e + > desce 2 vezes por dia no elevador (entre o R/C e o seu andar). Se cada andar + > tem uma altura de 3m, quantos km percorre o elevador por ano? Admitindo que o + > elevador viaja à velocidade constante de 1 m/s, quantas horas está o elevador + > em funcionamento num ano? Generalize o programa para um prédio de A andares e + > M moradores por piso. + + @code python + # Número de andares no prédio e a sua altura em metros + andares = int(input("Quantos andares? ")) + aAltura = 3 + # Número de moradores por andar + aMorador = int(input("Quantos moradores por andar? ")) + # Número de viagens por dia por morador + mViagens = 2 + # velocidade em metros por segundo + velocidade = 1 + + # Tempo em segundos gastos num andar por n° do andar (s/i) por dia + andarTempo = mViagens * aMorador * aAltura / velocidade + + # sum(andares, 1, \a -> andarTempo * a) + # <=> andarTempo * (andares * (1 + andares)) / 2 + # <=> andarTempo * (andares + andares^2) / 2 + + # Tempo gasto por dia em segundos + tempoDia = andarTempo * (andares + andares**2) / 2 + + # Tempo gasto por ano + tempo = tempoDia * 365 + tempoMinutos = int(tempo / 60 % 60) + tempoHoras = int(tempo // 3600) + + print( + f"O elevador está em funcionamento {tempoHoras:d} horas e {tempoMinutos:d} minutos por ano" + ) + @end + +** Exercício 8 + + > Um livro custa 20€ a fabricar (PF). Suponha que o preço de capa de um livro é + > 24,95€ (PC) e que o mesmo paga uma taxa de IVA de 23% (IMP). Acresce sobre o + > valor do livro uma taxa para compensar os autores pelas cópias de 0,20€ fixos + > (SPA). + > PC = (PF + Lucro) * (100% + IMP) + SPA + > Para uma tiragem de 500 exemplares: qual o lucro da livraria? Qual o total + > de impostos? + + @code python + # Preço de fabrico + PF = 20 + # Preço de capa + PC = 24.95 + # taxa de IVA + IMP = 0.23 + # Taxa fixa a pagar aos autores + SPA = 0.20 + + # Lucro por exemplar + # + # PC = (PF + Lucro) * (1 + IMP) + SPA + # <=> PC = PF * (1 + IMP) + Lucro * (1 + IMP) + SPA + # <=> PC = PF * (1 + IMP) + Lucro * (1 + IMP) + SPA + # <=> PC - PF * (1 + IMP) - SPA = Lucro * (1 + IMP) + # <=> PC / (1 + IMP) - PF - SPA / (1 + IMP) = Lucro + custoAcrescido = 1 + IMP + lucro = PC / custoAcrescido - PF - SPA / custoAcrescido + + # Calcula o lucro total + exemplares = int(input("Quantos exemplares? ")) + lucroTotal = exemplares * lucro + + print(f"O lucro para {exemplares} é de {lucroTotal} euros") + @end + +** Exercício 9 + + > Se sair de casa às 6:52 e percorrer 1 km a andar (fazendo 10 min por km), depois + > correr 3 km ao ritmo de 6 min por km e depois voltar a casa a andar, a que + > horas chego a casa para o pequeno almoço? + + @code python + # Minutos por km a andar + vAndar = 10 + # Minutos por km a correr + vCorrer = 6 + + # Minutos de saída de casa 6:52 + minutosSaida = 6 * 60 + 52 + + # Distâncias a andar e a correr + distanciaAndar = float(input("Quanto andou (km)? ")) + distanciaCorrer = float(input("Quanto correu (km)? ")) + + # Distância total percorrida após sair de casa e antes de começar regressar + distanciaTotal = distanciaAndar + distanciaCorrer + # Tempo gasto após sair de casa e antes de começar regressar + tempoFora = distanciaAndar * vAndar + distanciaCorrer * vCorrer + + # Tempo gasto a regressar + tempoDentro = distanciaTotal * vAndar + + # Tempo total + minutosChegada = minutosSaida + tempoFora + tempoDentro + # Formatar + horas = int(minutosChegada // 60) + minutos = int(minutosChegada % 60) + + print(f"Chego a casa as {horas:02d}:{minutos:02d}") + @end diff --git a/FP/aula01/res/aula01e01.py b/FP/aula01/res/aula01e01.py new file mode 100755 index 0000000..b25af8e --- /dev/null +++ b/FP/aula01/res/aula01e01.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +# Pede ao utilizador para inserir a temperatura em celsius +valorStr = input("Temperature (ºC)? ") + +# Tenta transformar de uma string para um float +valor = float(valorStr) + +# Converte de celsius para fahrenheit +valorFahrenheit = 1.8 * valor + 32 + +# Mostra ao utilizador o resultado +print(f"{valor} ºC = {valorFahrenheit} ºF") diff --git a/FP/aula01/res/aula01e02.py b/FP/aula01/res/aula01e02.py new file mode 100755 index 0000000..4db69ad --- /dev/null +++ b/FP/aula01/res/aula01e02.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +# Pede ao utilizador para inserir o nome +nome = input("Como te chamas? ") + +# Pede ao utilizador para inserir o ano em que nasceu +anoStr = input("Como te chamas? ") + +# Tenta transformar de uma string para um int +ano = int(anoStr) + +# Calcula a idade do utilizador em 2020 +idade2020 = 2020 - ano + +print(f"{nome}, em 2020 farás 33 anos.") diff --git a/FP/aula01/res/aula01e03.py b/FP/aula01/res/aula01e03.py new file mode 100644 index 0000000..535b5ab --- /dev/null +++ b/FP/aula01/res/aula01e03.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + +# Pede ao utilizador para inserir a primeira velocidade +v1Str = input("Insira a primeira velocidade (v1): ") +# Tenta transformar a string inserida num float +v1 = float(v1Str) + +# Pede ao utilizador para inserir a segunda velocidade +v2Str = input("Insira a segunda velocidade (v2): ") +# Tenta transformar a string inserida num float +v2 = float(v2Str) + +# Note que a velocidade média é calculada pela distância percorrida +# a dividir pelo tempo total: v=d/t. +# +# Como nós temos duas velocidades, v1 e v2, e a distância percorrida +# é a mesma nas duas, as velocidades são definidas por v1=d/t1 e v2=d/t2, +# logo queremos calcular v=2d/(t1 + t2) ou seja +# v=2d/(d/v1 + d/v2) +# <=> v = 2d/((dv2 + dv1)/v1v2) +# <=> v = 2d/(d(v1 + v2)/v1v2) +# <=> v = 2dv1v2/(d(v1 + v2) +# <=> v = 2v1v2/(v1 + v2) +v = 2 * v1 * v2 / (v1 + v2) + +# Formata e imprime os resultados +print("A velocidade média é", v) diff --git a/FP/aula01/res/aula01e04.py b/FP/aula01/res/aula01e04.py new file mode 100644 index 0000000..f076b08 --- /dev/null +++ b/FP/aula01/res/aula01e04.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +# Pede ao utilizador para inserir o tempo em segundos +secsStr = input("Segundos (s)? ") + +# Tenta transformar de uma string para um int +rawSecs = int(secsStr) + +# Calculate the time components +secs = rawSecs % 60 +mins = (rawSecs // 60) % 60 +hours = rawSecs // 3600 + +# Formata e imprime os resultados +print(f"{hours:02d}:{mins:02d}:{secs:02d}") diff --git a/FP/aula01/res/aula01e05.py b/FP/aula01/res/aula01e05.py new file mode 100644 index 0000000..241e358 --- /dev/null +++ b/FP/aula01/res/aula01e05.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +import math + +# Pede ao utilizador para inserir o comprimento dos catetos +catetoA = float(input("Comprimento do cateto A (m)? ")) +catetoB = float(input("Comprimento do cateto B (m)? ")) + +# Calcula a hipotenusa +hipo = math.sqrt(catetoA**2 + catetoB**2) + +# Calcula o ângulo em radianos entre a hipotenusa e o cateto A +angleRad = math.acos(catetoA / hipo) +# Transforma de radianos para graus +angle = angleRad * 180 / math.pi + +# Formata e imprime os resultados +print(f"A hipotenusa têm {hipo} m e faz um ângulo de {angle} graus com o cateto A") diff --git a/FP/aula01/res/aula01e07.py b/FP/aula01/res/aula01e07.py new file mode 100644 index 0000000..302f09c --- /dev/null +++ b/FP/aula01/res/aula01e07.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +# Número de andares no prédio e a sua altura em metros +andares = int(input("Quantos andares? ")) +aAltura = 3 +# Número de moradores por andar +aMorador = int(input("Quantos moradores por andar? ")) +# Número de viagens por dia por morador +mViagens = 2 +# velocidade em metros por segundo +velocidade = 1 + +# Tempo em segundos gastos num andar por n° do andar (s/i) por dia +andarTempo = mViagens * aMorador * aAltura / velocidade + +# sum(andares, 1, \a -> andarTempo * a) +# <=> andarTempo * (andares * (1 + andares)) / 2 +# <=> andarTempo * (andares + andares^2) / 2 + +# Tempo gasto por dia em segundos +tempoDia = andarTempo * (andares + andares**2) / 2 + +# Tempo gasto por ano +tempo = tempoDia * 365 +tempoMinutos = int(tempo / 60 % 60) +tempoHoras = int(tempo // 3600) + +print( + f"O elevador está em funcionamento {tempoHoras:d} horas e {tempoMinutos:d} minutos por ano" +) diff --git a/FP/aula01/res/aula01e08.py b/FP/aula01/res/aula01e08.py new file mode 100644 index 0000000..a9effc1 --- /dev/null +++ b/FP/aula01/res/aula01e08.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 + +# Preço de fabrico +PF = 20 +# Preço de capa +PC = 24.95 +# taxa de IVA +IMP = 0.23 +# Taxa fixa a pagar aos autores +SPA = 0.20 + +# Lucro por exemplar +# +# PC = (PF + Lucro) * (1 + IMP) + SPA +# <=> PC = PF * (1 + IMP) + Lucro * (1 + IMP) + SPA +# <=> PC = PF * (1 + IMP) + Lucro * (1 + IMP) + SPA +# <=> PC - PF * (1 + IMP) - SPA = Lucro * (1 + IMP) +# <=> PC / (1 + IMP) - PF - SPA / (1 + IMP) = Lucro +custoAcrescido = 1 + IMP +lucro = PC / custoAcrescido - PF - SPA / custoAcrescido + +# Calcula o lucro total +exemplares = int(input("Quantos exemplares? ")) +lucroTotal = exemplares * lucro + +print(f"O lucro para {exemplares} é de {lucroTotal} euros") diff --git a/FP/aula01/res/aula01e09.py b/FP/aula01/res/aula01e09.py new file mode 100644 index 0000000..a290f00 --- /dev/null +++ b/FP/aula01/res/aula01e09.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +# Minutos por km a andar +vAndar = 10 +# Minutos por km a correr +vCorrer = 6 + +# Minutos de saída de casa 6:52 +minutosSaida = 6 * 60 + 52 + +# Distâncias a andar e a correr +distanciaAndar = float(input("Quanto andou (km)? ")) +distanciaCorrer = float(input("Quanto correu (km)? ")) + +# Distância total percorrida após sair de casa e antes de começar regressar +distanciaTotal = distanciaAndar + distanciaCorrer +# Tempo gasto após sair de casa e antes de começar regressar +tempoFora = distanciaAndar * vAndar + distanciaCorrer * vCorrer + +# Tempo gasto a regressar +tempoDentro = distanciaTotal * vAndar + +# Tempo total +minutosChegada = minutosSaida + tempoFora + tempoDentro +# Formatar +horas = int(minutosChegada // 60) +minutos = int(minutosChegada % 60) + +print(f"Chego a casa as {horas:02d}:{minutos:02d}") diff --git a/FP/aula01/res/points.py b/FP/aula01/res/points.py new file mode 100644 index 0000000..3925e25 --- /dev/null +++ b/FP/aula01/res/points.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +import math + +# This program reads the coordinates of two points (x1,y1) and (x2,y2). + +x1 = float(input("x1? ")) +y1 = float(input("y1? ")) +x2 = float(input("x2? ")) +y2 = float(input("y2? ")) + +# Find and print the distance between the points! +# +# The distance between two points is given by the square root +# of the squares of the difference between the components of the +# two points +distance = math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2) + +# Format and print +print(f"A distância entre os dois pontos é {distance}") diff --git "a/FP/aula01/te\303\263rico/README.md" "b/FP/aula01/te\303\263rico/README.md" new file mode 100644 index 0000000..671fbf5 --- /dev/null +++ "b/FP/aula01/te\303\263rico/README.md" @@ -0,0 +1,16 @@ +# Bibliografia para aula 02. + +* Slides e guião disponibilizados nesta pasta. +* [1, capítulo 2](https://elearning.ua.pt/mod/lti/view.php?id=1142043) + (Semelhante a [2, capítulo 2]). +* Extra: para aprender um pouco mais sobre erros e debugging, + recomenda-se [1, cap. 3]. + +# Trabalho para casa (Homework) + +Ler e resolver os exercícios referentes a esta aula do livro recomendado [1]. + +[1] [Python for Everybody - Interactive] + +[2] [Think Python 2e](http://greenteapress.com/wp/think-python-2e/) + diff --git "a/FP/aula01/te\303\263rico/aula01.pdf" "b/FP/aula01/te\303\263rico/aula01.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..897ea182592dd889aeaba54fe8f6b1c499c053a2 GIT binary patch literal 131 zcmWN^K@x)?3;@78ukZtvB*Y;81_Kmk+UgYb(AU?~&R+T3+x8jiaqNAu_SufdtMu`< zp6jUF+x9)Hz0hne4ZTL1WFZQ%KxDw#Q(^XwQNs*nitGJ^3dovNJOy-Rav&13!~`6O NA)DTQc|i6gV*cZSCd2>$ literal 0 HcmV?d00001 diff --git "a/FP/aula01/te\303\263rico/idade.py" "b/FP/aula01/te\303\263rico/idade.py" new file mode 100644 index 0000000..c56ee8e --- /dev/null +++ "b/FP/aula01/te\303\263rico/idade.py" @@ -0,0 +1 @@ +# Complete o programa. diff --git "a/FP/aula01/te\303\263rico/points.py" "b/FP/aula01/te\303\263rico/points.py" new file mode 100644 index 0000000..5623ee7 --- /dev/null +++ "b/FP/aula01/te\303\263rico/points.py" @@ -0,0 +1,17 @@ +# This program reads the coordinates of two points (x1,y1) and (x2,y2). + +x1 = float(input("x1? ")) +y1 = float(input("y1? ")) +x2 = float(input("x2? ")) +y2 = float(input("y2? ")) + +# create tuples from coordinates +p1 = (x1, y1) +p2 = (x2, y2) + +print("Point1:", p1) +print("Point2:", p2) + +# Compute and print the distance between the points! +# ... + diff --git "a/FP/aula01/te\303\263rico/pointsg.py" "b/FP/aula01/te\303\263rico/pointsg.py" new file mode 100644 index 0000000..d8fc81e --- /dev/null +++ "b/FP/aula01/te\303\263rico/pointsg.py" @@ -0,0 +1,20 @@ +# This program uses matplotlib to graphically get two points. + +import matplotlib.pyplot as plt + +plt.axis([-4, 4, -3, 3]) +plt.axis("equal") +plt.grid("on") +plt.title("Choose 2 points!") +p1, p2 = plt.ginput(2) + +# extract coords from points +x1, y1 = p1 +x2, y2 = p2 + +print("Point1:", p1) +print("Point2:", p2) + +# Compute and print the distance between the points! +# ... + diff --git "a/FP/aula01/te\303\263rico/tp00-computers.pdf" "b/FP/aula01/te\303\263rico/tp00-computers.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..2810f311a9b170c4ba53452db69d40d7d5c73350 GIT binary patch literal 132 zcmWN|OA^8$5CG9Vr{DsH3+AmA6xbor;Ji8~4 literal 0 HcmV?d00001 diff --git "a/FP/aula01/te\303\263rico/tp01-intro.pdf" "b/FP/aula01/te\303\263rico/tp01-intro.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..7db732ccd8fd1b28b9c689d65d7035baeffc8da6 GIT binary patch literal 131 zcmWN}O%lQ&3_#&Mr{Dq>Nm8J_4L?DcQR$f4g{PO*TYNL`;*a$4*6lnG*^PPh^Y*N= z%(ib@@^~3JIGf9=(TkQAVRd`OJ0Uv25MxM*JcS%XEz^KX2I~omOUZ3)x%i4c0->wk QV%}h7CH==5EX;%Y1Nqk{Hvj+t literal 0 HcmV?d00001 diff --git a/FP/aula02/aula02.norg b/FP/aula02/aula02.norg new file mode 100644 index 0000000..33d6fa4 --- /dev/null +++ b/FP/aula02/aula02.norg @@ -0,0 +1,355 @@ +* Fundamento de Programação, Aula 01 + +** Exercício 1 + ID: `zuxa-esel-qese-pave` + + @comment + https://codecheck.io/private/resume/21102308566qx6cbh5dm4i6bezvgwbnobot/zuxa-esel-qese-pave/15KMZ9PQ030ROC6VKIE354URC + @end + +** Exercício 2 + + > O programa max2.py lê dois números e mostra o maior deles. Teste-o e analise-o. + > Altere o programa para fazer o mesmo, mas usando uma instrução condicional + > em vez da função pré-definida max. + + @code python + # This program finds the maximum of two numbers. + # It used the built-in max function. + # Can you do it with a conditional statement (if / if-else) instead? + # Sure can :) + + x1 = float(input("number? ")) + x2 = float(input("number? ")) + + mx = x1 + + if x2 > x1: + mx = x2 + + print("Maximum:", mx) + @end + +** Exercício 3 + + > Copie o programa anterior para max3.py e modifique esta cópia para achar o maior + > de três números, sem usar a função max. Consegue fazê-lo só com duas + > comparações? + + @code python + x1 = float(input("number? ")) + x2 = float(input("number? ")) + x3 = float(input("number? ")) + + mx = x1 + + if x2 > mx: + mx = x2 + if x3 > mx: + mx = x3 + + print("Maximum:", mx) + @end + + > E consegue achar o maior de quatro números só com três comparações? + + @code python + x1 = float(input("number? ")) + x2 = float(input("number? ")) + x3 = float(input("number? ")) + x4 = float(input("number? ")) + + mx = x1 + + if x2 > mx: + mx = x2 + if x3 > mx: + mx = x3 + if x4 > mx: + mx = x4 + + print("Maximum:", mx) + @end + +** Exercício 4 + + > Escreva um programa que leia um número inteiro e mostre uma mensagem indicando + > se o número é par ou ímpar. + + @code python + x1 = int(input("number? ")) + + if x1 % 2 == 0: + print(x1, "is even") + else: + print(x1, "is odd") + @end + +** Exercício 5 + + > Um certo tarifário de telefone cobra 0.12 € por minuto, cobrado ao segundo após + > o primeiro minuto. Por exemplo, chamadas de 10 s, de 30 s ou de 60 s custam + > 0.12 €. Uma chamada de 90 s custa 0.18 €. Faça um programa que calcule o + > custo de uma chamada sabendo a duração em segundos. + + @code python + secs = int(input("seconds? ")) + + rate = 0.12 + cost = rate + + if secs > 60: + remainingSecs = secs - 60 + cost += remainingSecs / 60 * rate + + print("The cost of the call is", cost, "euros") + @end + +** Exercício 6 + + > Execute o programa age.py e teste-o com vários valores de entrada. Analise o + > código-fonte para perceber como funciona. Consegue detetar o erro semântico? + + O problema com o programa é que considera pessoas com a idade de 13 anos como + "grown-up", enquanto que estas deviam ser consideradas como "teenager". + + > Que valores de age produzem a categoria "grown-up"? + + Idealmente deviam ser todos os valores maiores que 19 (exclusivo), max com o + atual erro semântico são considerados "grown-up" aqueles maiores que 19 e os + que tem 13 anos. + + > Corrija o erro. Consegue reescrever o código com uma instrução if-elif-else? + > Tente simplificar o código para eliminar condições redundantes. + + @code python + age = int(input("Age? ")) + + if age < 0: + print("ERROR: invalid age!") + exit(1) + + print("Age:", age) + + if age < 13: + cat = "child" + elif age < 20: + cat = "teenager" + else: + cat = "grown-up" + + print("Category:", cat) + @end + +** Exercício 7 + + > O índice de massa corporal (IMC) é uma medida usada para avaliar se uma pessoa + > tem um peso saudável para a sua estatura. O programa imc.py determina o IMC + > do utilizador e classifica-o apenas em duas categorias. Experimente o + > programa e analise-o. Modifique-o para dar uma de 4 categorias de acordo com + > a tabela abaixo. Evite testar condições redundantes no programa. + + @table + IMC (kg/m^2): | <18.5 | [18.5, 25[ | [25,30[ | 30 ou mais + Categoria: | Magro | Saudável | Forte | Obseo + @end + + @code python + print("Índice de Massa Corporal") + + altura = float(input("Altura (m)? ")) + peso = float(input("Peso (kg)? ")) + + imc = peso / altura**2 + + print("IMC:", imc, "kg/m2") + + # Determinar a categoria de IMC: + if imc < 18.5: + categoria = "Magro" + elif imc < 25: + categoria = "Saudável" + elif imc < 30: + categoria = "Forte" + else: + categoria = "Obeso" + + print("Categoria:", categoria) + @end + +** Exercício 8 + + > O diagrama de fases da Kryptonite (substância fictícia) é muito invulgar (ver + > figura ao lado). Diz-nos que em condições normais de temperatura e pressão + > (ponto assinalado na figura), a Kryptonite é sólida, mas se a temperatura for + > superior a 400 Kelvin e a pressão estiver acima de 50 kPa, passa à fase + > líquida. Também pode passar à fase gasosa se a pressão for baixa e a + > temperatura suficientemente elevada. O programa kryptonite.py pede a + > temperatura e a pressão e deveria indicar a fase correspondente, mas tem + > vários erros. + + > Execute o programa e veja o erro sintático reportado. Detete-o e corrija-o. + + @code diff + -print("At {} K and {} kPa, Kryptonite is in the {} phase.".format(T, P, phase) + +print("At {} K and {} kPa, Kryptonite is in the {} phase.".format(T, P, phase)) + @end + + > Volte a executar. Ocorre um TypeError? Porquê? Corrija. + + @code diff + -T = input("Temperature (K)? ") + -P = input("Pressure (kPa)? ") + +T = float(input("Temperature (K)? ")) + +P = float(input("Pressure (kPa)? ")) + @end + + > Agora deve conseguir executar o programa, mas ainda tem erros semânticos. Por + > exemplo, a 300 K e 100 kPa a fase devia ser SOLID. Modifique as instruções + > condicionais para determinar a fase corretamente. + + @code python + print("Kryptonite phase classifier") + + T = float(input("Temperature (K)? ")) + P = float(input("Pressure (kPa)? ")) + + # Define the line that divides the GAS and SOLID forms, this can be calculated + # by using (y2 - y1)/(x2 - x1) to get the slope, replacing with the known + # points we get (50 - 0)/(400 - 0) = 50/400 = 1/8 + line = 1 / 8 * T + + if P > 50.0 and T > 400: + phase = "LIQUID" + elif P < line: + phase = "GAS" + else: + phase = "SOLID" + + print("At {} K and {} kPa, Kryptonite is in the {} phase.".format(T, P, phase)) + @end + + > Ajuste a string de formato do resultado para a temperatura aparecer com 1 casa + > decimal e a pressão com 3. + + @code python + print("Kryptonite phase classifier") + + T = float(input("Temperature (K)? ")) + P = float(input("Pressure (kPa)? ")) + + # Define the line that divides the GAS and SOLID forms, this can be calculated + # by using (y2 - y1)/(x2 - x1) to get the slope, replacing with the known + # points we get (50 - 0)/(400 - 0) = 50/400 = 1/8 + line = 1 / 8 * T + + if P > 50.0 and T > 400: + phase = "LIQUID" + elif P < line: + phase = "GAS" + else: + phase = "SOLID" + + print("At {:.1f} K and {:.3f} kPa, Kryptonite is in the {} phase.".format(T, P, phase)) + @end + +** Exercício 9 + + > Escreva um programa que peça as notas de duas componentes de avaliação, CTP e CP, e + > calcule a nota final (inteira) de um aluno de Fundamentos de Programação. Se alguma + > componente for inferior à nota mínima, a nota final deve ser 66 (significa Reprovado por + > Nota Mínima). Se o aluno reprovar por nota mínima ou nota inferior a 10, o programa + > deve pedir as notas de recurso, ATPR e APR, e calcular a nova nota final. + + @code python + ctp = float(input("Nota CTP? ")) + cp = float(input("Nota CP? ")) + + NOTA_MIN = 6.5 + WEIGHT_CTP = 0.3 + WEIGHT_CP = 0.7 + + reprovado = False + final = WEIGHT_CP * cp + WEIGHT_CTP * ctp + + reprovado = ctp < NOTA_MIN or cp < NOTA_MIN or final < 10 + + if reprovado: + atpr = float(input("Nota ATPR? ")) + apr = float(input("Nota APR? ")) + + final = WEIGHT_CP * apr + WEIGHT_CTP * atpr + + if atpr < NOTA_MIN or apr < NOTA_MIN or final < 10: + final = 66 + + print(f"A sua nota final é {final:.5g}") + @end + +** Exercício 10 + + > Desafio: Um dardo atinge o alvo nas coordenadas (x, y). Complete o programa + > darts.py para mostrar a pontuação obtida. + + @code python + import math + + print("Enter the coordinates in mm from the center of the board.") + x = float(input("x? ")) + y = float(input("y? ")) + + # Points of the sectors, clockwise from the top + # Example: the sector right from the center is POINTS[5] == 6. + POINTS = (20, 1, 18, 4, 13, 6, 10, 15, 2, 17, 3, 19, 7, 16, 8, 11, 14, 9, 12, 5) + + TARGET_RADIUS = 170 + OUTER_RING_END = TARGET_RADIUS - 8 + INNER_RING_START = 107 + INNER_RING_END = INNER_RING_START - 8 + + CENTRAL_OUTER_RING_START = 16 + CENTRAL_INNER_RING_START = 6.35 + + SECTOR_SIZE = math.pi * 2 / len(POINTS) + + distance = math.sqrt(x**2 + y**2) + + # Now for some math tricks, the coordinates are provided in cartesian + # coordinates, but if we convert them to polar coordinates then we can easily + # get the sector that the coordinates belong to + # + # The cartesian to polar coordinates is as follows: + # r = sqrt(x^2 + y^2) + # theta = atan2(y, x) + # where r is the distance, theta is the angle and atan2 is the 2-argument + # arctangent. + # + # But we need to do some more transformations to fit our problem, first we must + # swap x and y in the atan2 function, this is because the atan2 is + # counter-clockwise and starts from the x-axis and our problem assumes that the + # sectors are in clockwise order and start from the y-axis. + # + # Furthermore we need to rotate the result by half the sector angle, because in + # the dart board is symmetrical along the y-axis. + angle = math.atan2(x, y) + SECTOR_SIZE / 2 + if angle < 0: + angle += 2 * math.pi + + # Now that we know the angle we can just divide it by the sector angle and get + # the non-decimal part. + sector = int(angle // SECTOR_SIZE) + score = POINTS[sector] + + if distance <= CENTRAL_INNER_RING_START: + score = 50 + elif distance <= CENTRAL_OUTER_RING_START: + score = 25 + elif INNER_RING_END <= distance and distance <= INNER_RING_START: + score *= 3 + elif OUTER_RING_END <= distance and distance <= TARGET_RADIUS: + score *= 2 + elif distance > TARGET_RADIUS: + score = 0 + + print(score) + @end diff --git a/FP/aula02/res/age.py b/FP/aula02/res/age.py new file mode 100644 index 0000000..4bda3da --- /dev/null +++ b/FP/aula02/res/age.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +age = int(input("Age? ")) + +if age < 0: + print("ERROR: invalid age!") + exit(1) + +print("Age:", age) + +if age < 13: + cat = "child" +elif age < 20: + cat = "teenager" +else: + cat = "grown-up" + +print("Category:", cat) diff --git a/FP/aula02/res/aula02e04.py b/FP/aula02/res/aula02e04.py new file mode 100644 index 0000000..16a01e8 --- /dev/null +++ b/FP/aula02/res/aula02e04.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +x1 = int(input("number? ")) + +if x1 % 2 == 0: + print(x1, "is even") +else: + print(x1, "is odd") diff --git a/FP/aula02/res/aula02e05.py b/FP/aula02/res/aula02e05.py new file mode 100644 index 0000000..0558bc1 --- /dev/null +++ b/FP/aula02/res/aula02e05.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +secs = int(input("seconds? ")) + +rate = 0.12 +cost = rate + +if secs > 60: + remainingSecs = secs - 60 + cost += remainingSecs / 60 * rate + +print("The cost of the call is", cost, "euros") diff --git a/FP/aula02/res/aula02e09.py b/FP/aula02/res/aula02e09.py new file mode 100644 index 0000000..dd059ac --- /dev/null +++ b/FP/aula02/res/aula02e09.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 + +ctp = float(input("Nota CTP? ")) +cp = float(input("Nota CP? ")) + +NOTA_MIN = 6.5 +WEIGHT_CTP = 0.3 +WEIGHT_CP = 0.7 + +reprovado = False +final = WEIGHT_CP * cp + WEIGHT_CTP * ctp + +reprovado = ctp < NOTA_MIN or cp < NOTA_MIN or final < 10 + +if reprovado: + atpr = float(input("Nota ATPR? ")) + apr = float(input("Nota APR? ")) + + final = WEIGHT_CP * apr + WEIGHT_CTP * atpr + + if atpr < NOTA_MIN or apr < NOTA_MIN or final < 10: + final = 66 + +print(f"A sua nota final é {final:.5g}") diff --git a/FP/aula02/res/darts.py b/FP/aula02/res/darts.py new file mode 100644 index 0000000..ebeb3f2 --- /dev/null +++ b/FP/aula02/res/darts.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +import math + +print("Enter the coordinates in mm from the center of the board.") +x = float(input("x? ")) +y = float(input("y? ")) + +# Points of the sectors, clockwise from the top +# Example: the sector right from the center is POINTS[5] == 6. +POINTS = (20, 1, 18, 4, 13, 6, 10, 15, 2, 17, 3, 19, 7, 16, 8, 11, 14, 9, 12, 5) + +TARGET_RADIUS = 170 +OUTER_RING_END = TARGET_RADIUS - 8 +INNER_RING_START = 107 +INNER_RING_END = INNER_RING_START - 8 + +CENTRAL_OUTER_RING_START = 16 +CENTRAL_INNER_RING_START = 6.35 + +SECTOR_SIZE = math.pi * 2 / len(POINTS) + +distance = math.sqrt(x**2 + y**2) + +# Now for some math tricks, the coordinates are provided in cartesian +# coordinates, but if we convert them to polar coordinates then we can easily +# get the sector that the coordinates belong to +# +# The cartesian to polar coordinates is as follows: +# r = sqrt(x^2 + y^2) +# theta = atan2(y, x) +# where r is the distance, theta is the angle and atan2 is the 2-argument +# arctangent. +# +# But we need to do some more transformations to fit our problem, first we must +# swap x and y in the atan2 function, this is because the atan2 is +# counter-clockwise and starts from the x-axis and our problem assumes that the +# sectors are in clockwise order and start from the y-axis. +# +# Furthermore we need to rotate the result by half the sector angle, because in +# the dart board is symmetrical along the y-axis. +angle = math.atan2(x, y) + SECTOR_SIZE / 2 +if angle < 0: + angle += 2 * math.pi + +# Now that we know the angle we can just divide it by the sector angle and get +# the non-decimal part. +sector = int(angle // SECTOR_SIZE) +score = POINTS[sector] + +if distance <= CENTRAL_INNER_RING_START: + score = 50 +elif distance <= CENTRAL_OUTER_RING_START: + score = 25 +elif INNER_RING_END <= distance and distance <= INNER_RING_START: + score *= 3 +elif OUTER_RING_END <= distance and distance <= TARGET_RADIUS: + score *= 2 +elif distance > TARGET_RADIUS: + score = 0 + +print(score) diff --git a/FP/aula02/res/imc.py b/FP/aula02/res/imc.py new file mode 100644 index 0000000..7375d7a --- /dev/null +++ b/FP/aula02/res/imc.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 + +print("Índice de Massa Corporal") + +altura = float(input("Altura (m)? ")) +peso = float(input("Peso (kg)? ")) + +imc = peso / altura**2 + +print("IMC:", imc, "kg/m2") + +# Determinar a categoria de IMC: +if imc < 18.5: + categoria = "Magro" +elif imc < 25: + categoria = "Saudável" +elif imc < 30: + categoria = "Forte" +else: + categoria = "Obeso" + +print("Categoria:", categoria) diff --git a/FP/aula02/res/kryptonite.py b/FP/aula02/res/kryptonite.py new file mode 100644 index 0000000..9e199d6 --- /dev/null +++ b/FP/aula02/res/kryptonite.py @@ -0,0 +1,18 @@ +print("Kryptonite phase classifier") + +T = float(input("Temperature (K)? ")) +P = float(input("Pressure (kPa)? ")) + +# Define the line that divides the GAS and SOLID forms, this can be calculated +# by using (y2 - y1)/(x2 - x1) to get the slope, replacing with the known +# points we get (50 - 0)/(400 - 0) = 50/400 = 1/8 +line = 1 / 8 * T + +if P > 50.0 and T > 400: + phase = "LIQUID" +elif P < line: + phase = "GAS" +else: + phase = "SOLID" + +print("At {:.1f} K and {:.3f} kPa, Kryptonite is in the {} phase.".format(T, P, phase)) diff --git a/FP/aula02/res/max2.py b/FP/aula02/res/max2.py new file mode 100644 index 0000000..75c03b4 --- /dev/null +++ b/FP/aula02/res/max2.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# coding: utf-8 +# This program finds the maximum of two numbers. +# It used the built-in max function. +# Can you do it with a conditional statement (if / if-else) instead? +# Sure can :) + +x1 = float(input("number? ")) +x2 = float(input("number? ")) + +mx = x1 + +if x2 > x1: + mx = x2 + +print("Maximum:", mx) diff --git a/FP/aula02/res/max3.py b/FP/aula02/res/max3.py new file mode 100644 index 0000000..35aacec --- /dev/null +++ b/FP/aula02/res/max3.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +x1 = float(input("number? ")) +x2 = float(input("number? ")) +x3 = float(input("number? ")) +x4 = float(input("number? ")) + +mx = x1 + +if x2 > mx: + mx = x2 +if x3 > mx: + mx = x3 +if x4 > mx: + mx = x4 + +print("Maximum:", mx) diff --git a/FP/aula02/res/max4.py b/FP/aula02/res/max4.py new file mode 100644 index 0000000..e4bebc0 --- /dev/null +++ b/FP/aula02/res/max4.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +# coding: utf-8 +# This program finds the maximum of two numbers. +# It uses the built-in max function. +# Can you do it with a conditional statement (if / if-else) instead? +# Sure can :) + +x1 = float(input("number? ")) +x2 = float(input("number? ")) + +# Use a conditional statement instead of max function! +mx = x1 + +if x2 > x1: + mx = x2 + +print("Maximum:", mx) diff --git "a/FP/aula02/te\303\263rico/README.md" "b/FP/aula02/te\303\263rico/README.md" new file mode 100644 index 0000000..3ae7ea3 --- /dev/null +++ "b/FP/aula02/te\303\263rico/README.md" @@ -0,0 +1,22 @@ +# Bibliografia para aula 02. + +* Slides e guião disponibilizados nesta pasta. +* [py4e] cap. 4 +* Ou [1] cap. 7 +* Ou [2] cap. 5--5.7 + +[py4e] [Python for Everybody: Interactive](https://elearning.ua.pt/mod/lti/view.php?id=1137743) + +[1] [How to Think Like a Computer Scientist: Interactive Edition](https://runestone.academy/runestone/static/thinkcspy/index.html) + +[2] [Think Python 2e](http://greenteapress.com/wp/think-python-2e/) + +Nos livros interativos, recomenda-se: + +* Ler cada capítulo até à secção "Glossary". +* Responder às questões no texto. +* Estudar exemplos que estão em caixas "Codelens". + Estas caixas permitem executar as instruções passo-a-passo e visualizar a + evolução das variáveis na memória à medida que o programa é executado. +* Para aprofundar, pode fazer alguns exercícios que aparecem no fim do capítulo. + diff --git "a/FP/aula02/te\303\263rico/age.py" "b/FP/aula02/te\303\263rico/age.py" new file mode 100644 index 0000000..d84dd43 --- /dev/null +++ "b/FP/aula02/te\303\263rico/age.py" @@ -0,0 +1,26 @@ +# A teenager is a person between 13 and 19 years old, inclusive. +# A child is under 13. A grown-up is 20 or more. +# This program outputs the age category for a given input age. +# It has a semantic error. Can you find it? +# Which values of age produce the output "grown-up"? +# Correct the error. +# Can you simplify the code to avoid redundant conditions? + +age = int(input("Age? ")) + +if age < 0: + print("ERROR: invalid age!") + exit(1) # this terminates the program + +print("Age:", age) + +if age < 13 : + cat = "child" +else: + if 13 < age < 20: + cat = "teenager" + else: + cat = "grown-up" + +print("Category:", cat) + diff --git "a/FP/aula02/te\303\263rico/aula02.pdf" "b/FP/aula02/te\303\263rico/aula02.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..1a69d5f25297edbcb6bc7da9ec29448760585855 GIT binary patch literal 131 zcmWN|OAf;z3;@wRr{Dq&F<&RQAz%tpTcVm|(bJdJNKcxZzTEmp)-g`rm3p@Ecokk| z>vb%tzZIX9)D5DyEV)MQ{2mJE;4>H~tFr;U)3~AyF@Y`-GNRka`9!b`DpP6);A`( literal 0 HcmV?d00001 diff --git "a/FP/aula02/te\303\263rico/darts.py" "b/FP/aula02/te\303\263rico/darts.py" new file mode 100644 index 0000000..787905e --- /dev/null +++ "b/FP/aula02/te\303\263rico/darts.py" @@ -0,0 +1,18 @@ +# You throw a dart that hits coordinates (x, y) on a dartboard. +# Create a program that gives you the score. +# See: +# https://en.wikipedia.org/wiki/Darts#Dartboard +# https://www.dimensions.com/element/dartboard + +print("Enter the coordinates in mm from the center of the board.") +x = float(input("x? ")) +y = float(input("y? ")) + +# Points of the sectors, clockwise from the top +# Example: the sector right from the center is POINTS[5] == 6. +POINTS = (20, 1, 18, 4, 13, 6, 10, 15, 2, 17, 3, 19, 7, 16, 8, 11, 14, 9, 12, 5) + +# COMPLETE... + + +print(score) diff --git "a/FP/aula02/te\303\263rico/examples/ex1if.py" "b/FP/aula02/te\303\263rico/examples/ex1if.py" new file mode 100644 index 0000000..59196ef --- /dev/null +++ "b/FP/aula02/te\303\263rico/examples/ex1if.py" @@ -0,0 +1,19 @@ +# Example: if statements. + +N = int(input("N? ")) + +if N > 10: + print("A") + +if N % 2 == 0: + print("B") + +print("END") + +# Think and answer: +# Which values of N make the program print A? +# Which values of N make the program print B? +# Does the program always print END? +# Can the program print both A and B? +# Can the program print B then A then END? + diff --git "a/FP/aula02/te\303\263rico/examples/ex1ifelse.py" "b/FP/aula02/te\303\263rico/examples/ex1ifelse.py" new file mode 100644 index 0000000..9aa002c --- /dev/null +++ "b/FP/aula02/te\303\263rico/examples/ex1ifelse.py" @@ -0,0 +1,18 @@ +# Example: # Does the program always print END? +. + +idade = int(input("idade? ")) + +print(idade) + +if idade >= 18: + res = "OK" + print("MAIOR") +else: + res = "KO" + +print(res) +print("FIM") + +# Think and answer: +# Which are the possible outputs of the program? OK/MAIOR/FIM OK/MAIOR/KO/FIM MAIOR/OK/FIM MAIOR/KO/FIM KO/FIM diff --git "a/FP/aula02/te\303\263rico/examples/ex1raining.py" "b/FP/aula02/te\303\263rico/examples/ex1raining.py" new file mode 100644 index 0000000..e82e759 --- /dev/null +++ "b/FP/aula02/te\303\263rico/examples/ex1raining.py" @@ -0,0 +1,15 @@ +# Example: using a boolean variable (a flag) + +response = input("Is it raining? ") +isRaining = response == "yes" +print(isRaining) + +if isRaining : + whatToDo = "take an umbrella" + print("too bad!") +else: + whatToDo = "enjoy!" + print("good!") + +print(whatToDo) + diff --git "a/FP/aula02/te\303\263rico/examples/ex2classifier.py" "b/FP/aula02/te\303\263rico/examples/ex2classifier.py" new file mode 100644 index 0000000..29b3acd --- /dev/null +++ "b/FP/aula02/te\303\263rico/examples/ex2classifier.py" @@ -0,0 +1,18 @@ +# Example: a classifier + +x = float(input("Altura (m)? ")) + +#print(x) + +if x > 1.9: + cl = "alto" +elif x < 1.9 and x > 1.6: + cl = "medio" +else: + cl = "baixo" + +print("És", cl) + +# One specific value of X is wrongly classified in the program. Can you spot it? +# What kind of error is this? Syntax error? Runtime error? Semantic error? + diff --git "a/FP/aula02/te\303\263rico/examples/ex2ifelifelse.py" "b/FP/aula02/te\303\263rico/examples/ex2ifelifelse.py" new file mode 100644 index 0000000..be4a5ee --- /dev/null +++ "b/FP/aula02/te\303\263rico/examples/ex2ifelifelse.py" @@ -0,0 +1,13 @@ +# Example: if-elif-else statement + +x = float(input("X? ")) +y = float(input("Y? ")) + +if x > y: + print('x is greater than y') +elif x < y: + print('x is less than y') +else: + print('x and y are equal') + +print("END") diff --git "a/FP/aula02/te\303\263rico/examples/ex2piecewise.py" "b/FP/aula02/te\303\263rico/examples/ex2piecewise.py" new file mode 100644 index 0000000..b8c8002 --- /dev/null +++ "b/FP/aula02/te\303\263rico/examples/ex2piecewise.py" @@ -0,0 +1,12 @@ +# Example: compute a piecewise function (pt: função definida por ramos) + +x = float(input("x? ")) + +if x < 10: + f = 3 +elif x < 20: + f = 1+x +else: + f = 1+2*x + +print(f) diff --git "a/FP/aula02/te\303\263rico/examples/ex3grades.py" "b/FP/aula02/te\303\263rico/examples/ex3grades.py" new file mode 100644 index 0000000..c53ce38 --- /dev/null +++ "b/FP/aula02/te\303\263rico/examples/ex3grades.py" @@ -0,0 +1,23 @@ +# Example: grade and classify + +nt = float(input("nota T?" )) +np = float(input("nota P?" )) + +nfinal = 0.3*nt + 0.7*np + +if nfinal < 9.5: + nfinal = float(input("nota ER?" )) + +print(nfinal) + +if nfinal < 9.5: + cl = "Reprovado" +elif nfinal < 14: + cl = "Suf" +elif nfinal < 17: + cl = "Bom" +else: + cl = "MB" + +print(cl) + diff --git "a/FP/aula02/te\303\263rico/examplesformat.py" "b/FP/aula02/te\303\263rico/examplesformat.py" new file mode 100644 index 0000000..b0943bf --- /dev/null +++ "b/FP/aula02/te\303\263rico/examplesformat.py" @@ -0,0 +1,52 @@ +# Examples showing how to use str.format method. +# jmr@ua.pt 2022 +# +# You may also like: +# https://www.digitalocean.com/community/tutorials/how-to-use-string-formatters-in-python-3 +# https://docs.python.org/3.6/library/string.html#format-string-syntax + +s = "Text" # a string +m = 23 # an integer +n = 764 # another integer +x = 2.3456 # a real +y = 5.67891e+2 # another real + +# Allignment +print( "({})".format("Text") ) +print( "({:20})".format("Text") ) +print( "({:>20})".format("Text") ) +print( "({:^20})".format("Text") ) +print( "({:<20})".format("Text") ) +print() + +# Formatting ints +print( "m=({:6d})".format(m) ) +print( "n=({:6d})".format(n) ) +print( "n=({:06d})".format(n) ) +print( "n=({:<6d})".format(n) ) +print( "m=({:6x})".format(m) ) +print( "m=({:6b})".format(m) ) +print() + +# Formatting floats +print( "x=({:f})".format(x) ) +print( "x=({:.1f})".format(x) ) +print( "x=({:.2f})".format(x) ) +print( "x=({:10f})".format(x) ) +print( "x=({:10.2f})".format(x) ) +print( "y=({:10.2f})".format(y) ) +print() + +# Formatting floats in scientific notation +print( "x=({:10.2e})".format(x) ) +print( "y=({:10.2e})".format(y) ) +print() + +# Floats in general format +print( "x=({:10.3g})".format(x) ) +print( "y=({:10.3g})".format(y) ) +print() + +# Multiple values and formats +print( "The values are:\ns:_{:^10s}_n:_{:<10d}_x: {:10.2e}_".format(s, n, x) ) + diff --git "a/FP/aula02/te\303\263rico/examplesfstring.py" "b/FP/aula02/te\303\263rico/examplesfstring.py" new file mode 100644 index 0000000..a1ab420 --- /dev/null +++ "b/FP/aula02/te\303\263rico/examplesfstring.py" @@ -0,0 +1,51 @@ +# Examples showing how to use f-strings instead of str.format. +# jmr@ua.pt 2022 +# +# You may also like: +# https://docs.python.org/3/reference/lexical_analysis.html#formatted-string-literals + +s = "Text" # a string +m = 23 # an integer +n = 764 # another integer +x = 2.3456 # a real +y = 5.67891e+2 # another real + +# Allignment +print( f"({s})" ) +print( f"({s:20})" ) +print( f"({s:>20})" ) +print( f"({s:^20})" ) +print( f"({s:<20})" ) +print() + +# Formatting ints +print( f"m=({m:6d})" ) +print( f"n=({n:6d})" ) +print( f"n=({n:06d})" ) +print( f"n=({n:<6d})" ) +print( f"m=({m:6x})" ) +print( f"m=({m:6b})" ) +print() + +# Formatting floats +print( f"x=({x:f})" ) +print( f"x=({x:.1f})" ) +print( f"x=({x:.2f})" ) +print( f"x=({x:10f})" ) +print( f"x=({x:10.2f})" ) +print( f"y=({y:10.2f})" ) +print() + +# Formatting floats in scientific notation +print( f"x=({x:10.2e})" ) +print( f"y=({y:10.2e})" ) +print() + +# Floats in general format +print( f"x=({x:10.3g})" ) +print( f"y=({y:10.3g})" ) +print() + +# Multiple values and formats +print( f"The values are:\ns:_{s:^10s}_n:_{n:<10d}_x: {x:10.2e}_" ) + diff --git "a/FP/aula02/te\303\263rico/imc.py" "b/FP/aula02/te\303\263rico/imc.py" new file mode 100644 index 0000000..5b998ec --- /dev/null +++ "b/FP/aula02/te\303\263rico/imc.py" @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +# Modifique o programa para indicar a categoria de IMC de acordo com a tabela: +# IMC: <18.5 [18.5, 25[ [25, 30[ 30 ou mais +# Categoria: Magro Saudável Forte Obeso + +print("Índice de Massa Corporal") + +altura = float(input("Altura (m)? ")) +peso = float(input("Peso (kg)? ")) + +imc = peso / altura**2 + +print("IMC:", imc, "kg/m2") + +# Determinar a categoria de IMC: +if imc < 20: + categoria = "Magro" +else: + categoria = "Obeso" + +print("Categoria:", categoria) + diff --git "a/FP/aula02/te\303\263rico/kryptonite.py" "b/FP/aula02/te\303\263rico/kryptonite.py" new file mode 100644 index 0000000..ecdfee6 --- /dev/null +++ "b/FP/aula02/te\303\263rico/kryptonite.py" @@ -0,0 +1,28 @@ +# This program should find the phase of a fictional substance +# for given temperature and pressure conditions, but it has several bugs. +# +# a) Try to run the program with Python3 and see what happens. +# There's a syntax error near the end. Fix it. +# b) Try again. It'll crash with a runtime error. Find the cause and fix it. +# c) There is also a semantic error: for T=300 and P=100, +# the phase should be SOLID. +# Fix it to agree with the phase diagram. Test in several conditions. +# d) Adjust the format string to output the temperature with 1 decimal place +# and the pressure with 3. + +print("Kryptonite phase classifier") + +# Input. (You can fix the runtime error by changing something here.) +T = input("Temperature (K)? ") +P = input("Pressure (kPa)? ") + +# Determine the phase. (This is wrong. Fix to match the phase diagram.) +if P > 50.0: + phase = "SOLID" +if T > 400.0: + phase = "LIQUID" +else: + phase = "GAS" + +# Output. (There's a subtle syntax error here!) +print("At {} K and {} kPa, Kryptonite is in the {} phase.".format(T, P, phase) diff --git "a/FP/aula02/te\303\263rico/max2.py" "b/FP/aula02/te\303\263rico/max2.py" new file mode 100644 index 0000000..8c1c6ab --- /dev/null +++ "b/FP/aula02/te\303\263rico/max2.py" @@ -0,0 +1,13 @@ +# coding: utf-8 +# This program finds the maximum of two numbers. +# It uses the built-in max function. +# Can you do it with a conditional statement (if / if-else) instead? + +x1 = float(input("number? ")) +x2 = float(input("number? ")) + +# Use a conditional statement instead of max function! +mx = max(x1, x2) + +print("Maximum:", mx) + diff --git "a/FP/aula02/te\303\263rico/plotPhaseDiagram.py" "b/FP/aula02/te\303\263rico/plotPhaseDiagram.py" new file mode 100644 index 0000000..11f7eca --- /dev/null +++ "b/FP/aula02/te\303\263rico/plotPhaseDiagram.py" @@ -0,0 +1,44 @@ +# Create a phase diagram of a hypothetical substance. +# +# FP students _are not required_ to know this. +# Curious students may learn something, anyway. :) +# +# JMR@ua.pt 2017 + +import numpy as np +import matplotlib.pyplot as plt + +# temperature and pressure of triple-point: +t = 400.0 # in Kelvin +p = 50.0 # in kPa + +# axis limits: +t0, t1 = 0.0, 1000.0 +p0, p1 = 0.0, 200.0 + +plt.figure(1, figsize=(3, 2.5), dpi=200, constrained_layout=True) +# Solid +plt.fill([t0, t, t, t0], [p0, p, p1, p1], 'g', alpha=0.2) +plt.text(0.5*t0 + 0.5*t, 0.5*p + 0.5*p1, "Solid", + horizontalalignment='center', verticalalignment='center') +# Liquid +plt.fill([t, t1, t1, t], [p, p, p1, p1], 'b', alpha=0.2) +plt.text(0.5*t + 0.5*t1, 0.5*p + 0.5*p1, "Liquid", + horizontalalignment='center', verticalalignment='center') +# Gas +plt.fill([t0, t1, t1, t], [p0, p0, p, p], 'c', alpha=0.1) +plt.text(0.5*t0 + 0.5*t1, 0.5*p0 + 0.5*p, "Gas", + horizontalalignment='center', verticalalignment='center') + +# The "Normal Temperature and Pressure" point: +plt.plot([293.15],[101.325], 'ko') + +plt.title("Phase Diagram of Kryptonite") +plt.xlabel("Temperature (K)") +plt.ylabel("Pressure (kPa)") +plt.axis([t0, t1, p0, p1]) +plt.grid() + +plt.show() +plt.savefig("kryptonite.png") + diff --git "a/FP/aula02/te\303\263rico/tp02-selection.pdf" "b/FP/aula02/te\303\263rico/tp02-selection.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..c3b55ff363db6854d8f8872869a3d06128b908e0 GIT binary patch literal 131 zcmWl~OAf*y5CG79Pr(H&%yJd!M&QmGyT! z^IFDJ%fUrou#CPdX@ov(jKy*VPlk6yEgp3^uvt3n1$!)c^nh literal 0 HcmV?d00001 diff --git "a/FP/aula03/te\303\263rico/README.md" "b/FP/aula03/te\303\263rico/README.md" new file mode 100644 index 0000000..a5c5743 --- /dev/null +++ "b/FP/aula03/te\303\263rico/README.md" @@ -0,0 +1,22 @@ +# Bibliografia para aula 03. + +* Slides e guião disponibilizados nesta pasta. +* [py4e] cap. 5 +* Ou [1] ch. 6 +* Ou [2] ch. 3 + +[py4e] [Python for Everybody: Interactive](https://elearning.ua.pt/mod/lti/view.php?id=1137743) + +[1] [How to Think Like a Computer Scientist: Interactive Edition](https://runestone.academy/runestone/static/thinkcspy/index.html) + +[2] [Think Python 2e](http://greenteapress.com/wp/think-python-2e/) + +Nos livros interativos, recomenda-se: + +* Ler cada capítulo até à secção "Glossary". +* Responder às questões no texto. +* Estudar exemplos que estão em caixas "Codelens". + Estas caixas permitem executar as instruções passo-a-passo e visualizar a + evolução das variáveis na memória à medida que o programa é executado. +* Para aprofundar, pode fazer alguns exercícios que aparecem no fim do capítulo. + diff --git "a/FP/aula03/te\303\263rico/aula03.pdf" "b/FP/aula03/te\303\263rico/aula03.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..f787c983ea32ebac9e6b64fd9799eaa15bb680c2 GIT binary patch literal 131 zcmWN?K@!3s3;@78uiyigNeK}88%l^UqtY?82Vbvy*{i*E%$M!wdFbZceVn(4=<>gR z_NC6J)1y^)ftiD?_Ogb!3DUY_iX}ysP`#vFLO>R1E#`=c00=8rs?3>^XY_0 + # Complete the function definition... + ... + + +# This is the main function +def main(): + print("Índice de Massa Corporal") + + altura = float(input("Altura (m)? ")) + if altura < 0: + print("ERRO: altura inválida!") + exit(1) + + peso = float(input("Peso (kg)? ")) + if peso < 0: + print("ERRO: peso inválido!") + exit(1) + + # Complete the function calls... + imc = bodyMassIndex( ... ) + cat = bmiCategory(...) + + print("BMI:", imc, "kg/m2") + print("BMI category:", cat) + + +# Program starts executing here +main() + diff --git "a/FP/aula03/te\303\263rico/dates.py" "b/FP/aula03/te\303\263rico/dates.py" new file mode 100644 index 0000000..612ea23 --- /dev/null +++ "b/FP/aula03/te\303\263rico/dates.py" @@ -0,0 +1,47 @@ + +# This function checks if year is a leap year. +# It is wrong: 1900 was a common year! +def isLeapYear(year): + return year%4 == 0 + +# This function has a semantic error: February in a leap year should return 29! +# Correct it. +def monthDays(year, month): + MONTHDAYS = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) + # This tuple contains the days in each month (on a common year). + # For example: MONTHDAYS[3] is the number of days in March. + days = MONTHDAYS[month] + return days + +# This is wrong, too. +def nextDay(year, month, day): + day += 1 + return year, month, day + + +# This is the main function +def main(): + print("Was", 2017, "a leap year?", isLeapYear(2017)) # False? + print("Was", 2016, "a leap year?", isLeapYear(2016)) # True? + print("Was", 2000, "a leap year?", isLeapYear(2000)) # True? + print("Was", 1900, "a leap year?", isLeapYear(1900)) # False? + + print("January 2017 had", monthDays(2017, 1), "days") # 31? + print("February 2017 had", monthDays(2017, 2), "days") # 28? + print("February 2016 had", monthDays(2016, 2), "days") # 29? + print("February 2000 had", monthDays(2000, 2), "days") # 29? + print("February 1900 had", monthDays(1900, 2), "days") # 28? + + y, m, d = nextDay(2017, 1, 30) + print(y, m, d) # 2017 1 31 ? + y, m, d = nextDay(2017, 1, 31) + print(y, m, d) # 2017 2 1 ? + y, m, d = nextDay(2017, 2, 28) + print(y, m, d) # 2017 3 1 ? + y, m, d = nextDay(2016, 2, 29) + print(y, m, d) # 2016 3 1 ? + y, m, d = nextDay(2017, 12, 31) + print(y, m, d) # 2018 1 1 ? + +# call the main function +main() diff --git "a/FP/aula03/te\303\263rico/examples/args.py" "b/FP/aula03/te\303\263rico/examples/args.py" new file mode 100644 index 0000000..a049f62 --- /dev/null +++ "b/FP/aula03/te\303\263rico/examples/args.py" @@ -0,0 +1,3 @@ +def func(a, b, c): + print(a, b, c) + diff --git "a/FP/aula03/te\303\263rico/examples/funcs1.py" "b/FP/aula03/te\303\263rico/examples/funcs1.py" new file mode 100644 index 0000000..2dc66f8 --- /dev/null +++ "b/FP/aula03/te\303\263rico/examples/funcs1.py" @@ -0,0 +1,58 @@ +# Example functions created in TP lesson #3. +# jmr@ua.pt 2018 + +## Example 1: A simple function to compute a square number + +def sqr(x): + y = x**2 + return y + +print("3 ao quadrado é", sqr(3)) + + +## Example 2: A BAD example of using a global variable + +def power(x): + y = x**exp # exp is not local! + # x and y are local because they are assigned values inside the function! + return y + +# define some global variables +x = 99 +y = 33 +exp = 3 +z = 10 + power(2) +print("z:", z) # 18 (= 10 + 2**3) +print(x, y) # still 99 33 (x and y inside power are local) +exp = 10 +z = power(2) +print("z:", z) # 1024 (2**10) +print(x, y) # still 99 33 (x and y inside power are local) + + +## Example 3: A nicer way would use exp as parameter + +def power(x, exp): + return x**exp + +print(power(2, 3)) +print(power(2, 10)) + + +## Example 4: Functions can take any type of argument +def fullname(first, last): + first = first.title() # title makes the first letter uppercase! + last = last.title() + return first + " " + last + +print( fullname("maria", "costa") ) +print( fullname("fernando", "pessoa") ) + + +## Example 5: Functions can return several values (as a tuple) +def divRem(a, b): + return a//b, a%b + +q, r = divRem(13, 4) +print(q, r) # 3 1 + diff --git "a/FP/aula03/te\303\263rico/examples/funcs2.py" "b/FP/aula03/te\303\263rico/examples/funcs2.py" new file mode 100644 index 0000000..56eb469 --- /dev/null +++ "b/FP/aula03/te\303\263rico/examples/funcs2.py" @@ -0,0 +1,26 @@ +# Example functions created in TP lesson #3. +# jmr@ua.pt 2018 + +# A function to print a message twice +def printTwice(msg): + print(msg) + print(msg) + +# A function to print a message three times +def print3times(msg): + print(msg) # print once + printTwice(msg) # call previous fcn to print twice more... + +# A function to print a message four times +def print4times(msg): + print(msg) + print3times(msg) + +# A generalization to print a message any number of times +def printNtimes(msg, n): + if n > 0: + print(msg) + printNtimes(msg, n-1) # It calls itself! Wow! + + +printNtimes("bla", 3) diff --git "a/FP/aula03/te\303\263rico/tp03-functions.pdf" "b/FP/aula03/te\303\263rico/tp03-functions.pdf" new file mode 100644 index 0000000000000000000000000000000000000000..66853db59c5843ae848e67df40383dc4816cf296 GIT binary patch literal 131 zcmWN?K@!3s3;@7;U%>|~0);?-6G9MXR62(C;OliSd+|s5c&j$&A-mR(K5x$|>;HD< zmBvfU!K5#\linewidth\linewidth\else\Gin@nat@width\fi} +\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi} +\makeatother +% Scale images if necessary, so that they will not overflow the page +% margins by default, and it is still possible to overwrite the defaults +% using explicit options in \includegraphics[width, height, ...]{} +\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio} +% Set default figure placement to htbp +\makeatletter +\def\fps@figure{htbp} +\makeatother +$endif$ +$if(links-as-notes)$ +% Make links footnotes instead of hotlinks: +\DeclareRobustCommand{\href}[2]{#2\footnote{\url{#1}}} +$endif$ +$if(strikeout)$ +\usepackage[normalem]{ulem} +% Avoid problems with \sout in headers with hyperref +\pdfstringdefDisableCommands{\renewcommand{\sout}{}} +$endif$ +\setlength{\emergencystretch}{3em} % prevent overfull lines +\providecommand{\tightlist}{% + \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} +$if(numbersections)$ +\setcounter{secnumdepth}{$if(secnumdepth)$$secnumdepth$$else$5$endif$} +$else$ +\setcounter{secnumdepth}{-\maxdimen} % remove section numbering +$endif$ +$if(beamer)$ +$else$ +$if(block-headings)$ +% Make \paragraph and \subparagraph free-standing +\ifx\paragraph\undefined\else + \let\oldparagraph\paragraph + \renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}} +\fi +\ifx\subparagraph\undefined\else + \let\oldsubparagraph\subparagraph + \renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}} +\fi +$endif$ +$endif$ +$if(pagestyle)$ +\pagestyle{$pagestyle$} +$endif$ + +% Make use of float-package and set default placement for figures to H. +% The option H means 'PUT IT HERE' (as opposed to the standard h option which means 'You may put it here if you like'). +\usepackage{float} +\floatplacement{figure}{$if(float-placement-figure)$$float-placement-figure$$else$H$endif$} + +$for(header-includes)$ +$header-includes$ +$endfor$ +$if(lang)$ +\ifxetex + $if(mainfont)$ + $else$ + % See issue https://github.com/reutenauer/polyglossia/issues/127 + \renewcommand*\familydefault{\sfdefault} + $endif$ + % Load polyglossia as late as possible: uses bidi with RTL langages (e.g. Hebrew, Arabic) + \usepackage{polyglossia} + \setmainlanguage[$for(polyglossia-lang.options)$$polyglossia-lang.options$$sep$,$endfor$]{$polyglossia-lang.name$} +$for(polyglossia-otherlangs)$ + \setotherlanguage[$for(polyglossia-otherlangs.options)$$polyglossia-otherlangs.options$$sep$,$endfor$]{$polyglossia-otherlangs.name$} +$endfor$ +\else + \usepackage[$for(babel-otherlangs)$$babel-otherlangs$,$endfor$main=$babel-lang$]{babel} +% get rid of language-specific shorthands (see #6817): +\let\LanguageShortHands\languageshorthands +\def\languageshorthands#1{} +$if(babel-newcommands)$ + $babel-newcommands$ +$endif$ +\fi +$endif$ +\ifluatex + \usepackage{selnolig} % disable illegal ligatures +\fi +$if(dir)$ +\ifxetex + % Load bidi as late as possible as it modifies e.g. graphicx + \usepackage{bidi} +\fi +\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex + \TeXXeTstate=1 + \newcommand{\RL}[1]{\beginR #1\endR} + \newcommand{\LR}[1]{\beginL #1\endL} + \newenvironment{RTL}{\beginR}{\endR} + \newenvironment{LTR}{\beginL}{\endL} +\fi +$endif$ +$if(natbib)$ +\usepackage[$natbiboptions$]{natbib} +\bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$} +$endif$ +$if(biblatex)$ +\usepackage[$if(biblio-style)$style=$biblio-style$,$endif$$for(biblatexoptions)$$biblatexoptions$$sep$,$endfor$]{biblatex} +$for(bibliography)$ +\addbibresource{$bibliography$} +$endfor$ +$endif$ +$if(csl-refs)$ +\newlength{\cslhangindent} +\setlength{\cslhangindent}{1.5em} +\newlength{\csllabelwidth} +\setlength{\csllabelwidth}{3em} +\newenvironment{CSLReferences}[2] % #1 hanging-ident, #2 entry spacing + {% don't indent paragraphs + \setlength{\parindent}{0pt} + % turn on hanging indent if param 1 is 1 + \ifodd #1 \everypar{\setlength{\hangindent}{\cslhangindent}}\ignorespaces\fi + % set entry spacing + \ifnum #2 > 0 + \setlength{\parskip}{#2\baselineskip} + \fi + }% + {} +\usepackage{calc} +\newcommand{\CSLBlock}[1]{#1\hfill\break} +\newcommand{\CSLLeftMargin}[1]{\parbox[t]{\csllabelwidth}{#1}} +\newcommand{\CSLRightInline}[1]{\parbox[t]{\linewidth - \csllabelwidth}{#1}\break} +\newcommand{\CSLIndent}[1]{\hspace{\cslhangindent}#1} +$endif$ +$if(csquotes)$ +\usepackage{csquotes} +$endif$ + +$if(title)$ +\title{$title$$if(thanks)$\thanks{$thanks$}$endif$} +$endif$ +$if(subtitle)$ +$if(beamer)$ +$else$ +\usepackage{etoolbox} +\makeatletter +\providecommand{\subtitle}[1]{% add subtitle to \maketitle + \apptocmd{\@title}{\par {\large #1 \par}}{}{} +} +\makeatother +$endif$ +\subtitle{$subtitle$} +$endif$ +\author{$for(author)$$author$$sep$ \and $endfor$} +\date{$date$} +$if(beamer)$ +$if(institute)$ +\institute{$for(institute)$$institute$$sep$ \and $endfor$} +$endif$ +$if(titlegraphic)$ +\titlegraphic{\includegraphics{$titlegraphic$}} +$endif$ +$if(logo)$ +\logo{\includegraphics{$logo$}} +$endif$ +$endif$ + + + +%% +%% added +%% + +% +% language specification +% +% If no language is specified, use English as the default main document language. +% +$if(lang)$$else$ +\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex + \usepackage[shorthands=off,$for(babel-otherlangs)$$babel-otherlangs$,$endfor$main=english]{babel} +$if(babel-newcommands)$ + $babel-newcommands$ +$endif$ +\else + $if(mainfont)$ + $else$ + % Workaround for bug in Polyglossia that breaks `\familydefault` when `\setmainlanguage` is used. + % See https://github.com/Wandmalfarbe/pandoc-latex-template/issues/8 + % See https://github.com/reutenauer/polyglossia/issues/186 + % See https://github.com/reutenauer/polyglossia/issues/127 + \renewcommand*\familydefault{\sfdefault} + $endif$ + % load polyglossia as late as possible as it *could* call bidi if RTL lang (e.g. Hebrew or Arabic) + \usepackage{polyglossia} + \setmainlanguage[]{english} +$for(polyglossia-otherlangs)$ + \setotherlanguage[$polyglossia-otherlangs.options$]{$polyglossia-otherlangs.name$} +$endfor$ +\fi +$endif$ + +$if(page-background)$ +\usepackage[pages=all]{background} +$endif$ + +% +% for the background color of the title page +% +$if(titlepage)$ +\usepackage{pagecolor} +\usepackage{afterpage} +$if(titlepage-background)$ +\usepackage{tikz} +$endif$ +$if(geometry)$ +$else$ +\usepackage[margin=2.5cm,includehead=true,includefoot=true,centering]{geometry} +$endif$ +$endif$ + +% +% break urls +% +\PassOptionsToPackage{hyphens}{url} + +% +% When using babel or polyglossia with biblatex, loading csquotes is recommended +% to ensure that quoted texts are typeset according to the rules of your main language. +% +\usepackage{csquotes} + +% +% captions +% +\definecolor{caption-color}{HTML}{777777} +$if(beamer)$ +$else$ +\usepackage[font={stretch=1.2}, textfont={color=caption-color}, position=top, skip=4mm, labelfont=bf, singlelinecheck=false, justification=$if(caption-justification)$$caption-justification$$else$raggedright$endif$]{caption} +\setcapindent{0em} +$endif$ + +% +% blockquote +% +\definecolor{blockquote-border}{RGB}{221,221,221} +\definecolor{blockquote-text}{RGB}{119,119,119} +\usepackage{mdframed} +\newmdenv[rightline=false,bottomline=false,topline=false,linewidth=3pt,linecolor=blockquote-border,skipabove=\parskip]{customblockquote} +\renewenvironment{quote}{\begin{customblockquote}\list{}{\rightmargin=0em\leftmargin=0em}% +\item\relax\color{blockquote-text}\ignorespaces}{\unskip\unskip\endlist\end{customblockquote}} + +% +% Source Sans Pro as the de­fault font fam­ily +% Source Code Pro for monospace text +% +% 'default' option sets the default +% font family to Source Sans Pro, not \sfdefault. +% +\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex + $if(fontfamily)$ + $else$ + \usepackage[default]{sourcesanspro} + \usepackage{sourcecodepro} + $endif$ +\else % if not pdftex + $if(mainfont)$ + $else$ + \usepackage[default]{sourcesanspro} + \usepackage{sourcecodepro} + + % XeLaTeX specific adjustments for straight quotes: https://tex.stackexchange.com/a/354887 + % This issue is already fixed (see https://github.com/silkeh/latex-sourcecodepro/pull/5) but the + % fix is still unreleased. + % TODO: Remove this workaround when the new version of sourcecodepro is released on CTAN. + \ifxetex + \makeatletter + \defaultfontfeatures[\ttfamily] + { Numbers = \sourcecodepro@figurestyle, + Scale = \SourceCodePro@scale, + Extension = .otf } + \setmonofont + [ UprightFont = *-\sourcecodepro@regstyle, + ItalicFont = *-\sourcecodepro@regstyle It, + BoldFont = *-\sourcecodepro@boldstyle, + BoldItalicFont = *-\sourcecodepro@boldstyle It ] + {SourceCodePro} + \makeatother + \fi + $endif$ +\fi + +% +% heading color +% +\definecolor{heading-color}{RGB}{40,40,40} +$if(beamer)$ +$else$ +\addtokomafont{section}{\color{heading-color}} +$endif$ +% When using the classes report, scrreprt, book, +% scrbook or memoir, uncomment the following line. +%\addtokomafont{chapter}{\color{heading-color}} + +% +% variables for title, author and date +% +$if(beamer)$ +$else$ +\usepackage{titling} +\title{$title$} +\author{$for(author)$$author$$sep$, $endfor$} +\date{$date$} +$endif$ + +% +% tables +% +$if(tables)$ + +\definecolor{table-row-color}{HTML}{F5F5F5} +\definecolor{table-rule-color}{HTML}{999999} + +%\arrayrulecolor{black!40} +\arrayrulecolor{table-rule-color} % color of \toprule, \midrule, \bottomrule +\setlength\heavyrulewidth{0.3ex} % thickness of \toprule, \bottomrule +\renewcommand{\arraystretch}{1.3} % spacing (padding) + +$if(table-use-row-colors)$ +% TODO: This doesn't work anymore. I don't know why. +% Reset rownum counter so that each table +% starts with the same row colors. +% https://tex.stackexchange.com/questions/170637/restarting-rowcolors +% +% Unfortunately the colored cells extend beyond the edge of the +% table because pandoc uses @-expressions (@{}) like so: +% +% \begin{longtable}[]{@{}ll@{}} +% \end{longtable} +% +% https://en.wikibooks.org/wiki/LaTeX/Tables#.40-expressions +\let\oldlongtable\longtable +\let\endoldlongtable\endlongtable +\renewenvironment{longtable}{ +\rowcolors{3}{}{table-row-color!100} % row color +\oldlongtable} { +\endoldlongtable +\global\rownum=0\relax} +$endif$ +$endif$ + +% +% remove paragraph indention +% +\setlength{\parindent}{0pt} +\setlength{\parskip}{6pt plus 2pt minus 1pt} +\setlength{\emergencystretch}{3em} % prevent overfull lines + +% +% +% Listings +% +% + +$if(listings)$ + +% +% general listing colors +% +\definecolor{listing-background}{HTML}{F7F7F7} +\definecolor{listing-rule}{HTML}{B3B2B3} +\definecolor{listing-numbers}{HTML}{B3B2B3} +\definecolor{listing-text-color}{HTML}{000000} +\definecolor{listing-keyword}{HTML}{435489} +\definecolor{listing-keyword-2}{HTML}{1284CA} % additional keywords +\definecolor{listing-keyword-3}{HTML}{9137CB} % additional keywords +\definecolor{listing-identifier}{HTML}{435489} +\definecolor{listing-string}{HTML}{00999A} +\definecolor{listing-comment}{HTML}{8E8E8E} + +\lstdefinestyle{eisvogel_listing_style}{ + language = java, +$if(listings-disable-line-numbers)$ + xleftmargin = 0.6em, + framexleftmargin = 0.4em, +$else$ + numbers = left, + xleftmargin = 2.7em, + framexleftmargin = 2.5em, +$endif$ + backgroundcolor = \color{listing-background}, + basicstyle = \color{listing-text-color}\linespread{1.0}$if(code-block-font-size)$$code-block-font-size$$else$\small$endif$\ttfamily{}, + breaklines = true, + frame = single, + framesep = 0.19em, + rulecolor = \color{listing-rule}, + frameround = ffff, + tabsize = 4, + numberstyle = \color{listing-numbers}, + aboveskip = 1.0em, + belowskip = 0.1em, + abovecaptionskip = 0em, + belowcaptionskip = 1.0em, + keywordstyle = {\color{listing-keyword}\bfseries}, + keywordstyle = {[2]\color{listing-keyword-2}\bfseries}, + keywordstyle = {[3]\color{listing-keyword-3}\bfseries\itshape}, + sensitive = true, + identifierstyle = \color{listing-identifier}, + commentstyle = \color{listing-comment}, + stringstyle = \color{listing-string}, + showstringspaces = false, + escapeinside = {/*@}{@*/}, % Allow LaTeX inside these special comments + literate = + {á}{{\'a}}1 {é}{{\'e}}1 {í}{{\'i}}1 {ó}{{\'o}}1 {ú}{{\'u}}1 + {Á}{{\'A}}1 {É}{{\'E}}1 {Í}{{\'I}}1 {Ó}{{\'O}}1 {Ú}{{\'U}}1 + {à}{{\`a}}1 {è}{{\'e}}1 {ì}{{\`i}}1 {ò}{{\`o}}1 {ù}{{\`u}}1 + {À}{{\`A}}1 {È}{{\'E}}1 {Ì}{{\`I}}1 {Ò}{{\`O}}1 {Ù}{{\`U}}1 + {ä}{{\"a}}1 {ë}{{\"e}}1 {ï}{{\"i}}1 {ö}{{\"o}}1 {ü}{{\"u}}1 + {Ä}{{\"A}}1 {Ë}{{\"E}}1 {Ï}{{\"I}}1 {Ö}{{\"O}}1 {Ü}{{\"U}}1 + {â}{{\^a}}1 {ê}{{\^e}}1 {î}{{\^i}}1 {ô}{{\^o}}1 {û}{{\^u}}1 + {Â}{{\^A}}1 {Ê}{{\^E}}1 {Î}{{\^I}}1 {Ô}{{\^O}}1 {Û}{{\^U}}1 + {œ}{{\oe}}1 {Œ}{{\OE}}1 {æ}{{\ae}}1 {Æ}{{\AE}}1 {ß}{{\ss}}1 + {ç}{{\c c}}1 {Ç}{{\c C}}1 {ø}{{\o}}1 {å}{{\r a}}1 {Å}{{\r A}}1 + {€}{{\EUR}}1 {£}{{\pounds}}1 {«}{{\guillemotleft}}1 + {»}{{\guillemotright}}1 {ñ}{{\~n}}1 {Ñ}{{\~N}}1 {¿}{{?`}}1 + {…}{{\ldots}}1 {≥}{{>=}}1 {≤}{{<=}}1 {„}{{\glqq}}1 {“}{{\grqq}}1 + {”}{{''}}1 + {ã}{{\~a}}1 + {┐}{{\textSFiii}}1 + {└}{{\textSFii}}1 + {┴}{{\textSFvii}}1 + {┬}{{\textSFvi}}1 + {├}{{\textSFviii}}1 + {─}{{\textSFx}}1 + {┼}{{\textSFv}}1 + {│}{{\textSFxi}}1 + {º}{{\ensuremath{^\circ}}}1 + % this is a different symbol from the one above + {°}{{\ensuremath{^\circ}}}1 +} +\lstset{style=eisvogel_listing_style} + +% +% Java (Java SE 12, 2019-06-22) +% +\lstdefinelanguage{Java}{ + morekeywords={ + % normal keywords (without data types) + abstract,assert,break,case,catch,class,continue,default, + do,else,enum,exports,extends,final,finally,for,if,implements, + import,instanceof,interface,module,native,new,package,private, + protected,public,requires,return,static,strictfp,super,switch, + synchronized,this,throw,throws,transient,try,volatile,while, + % var is an identifier + var + }, + morekeywords={[2] % data types + % primitive data types + boolean,byte,char,double,float,int,long,short, + % String + String, + % primitive wrapper types + Boolean,Byte,Character,Double,Float,Integer,Long,Short + % number types + Number,AtomicInteger,AtomicLong,BigDecimal,BigInteger,DoubleAccumulator,DoubleAdder,LongAccumulator,LongAdder,Short, + % other + Object,Void,void + }, + morekeywords={[3] % literals + % reserved words for literal values + null,true,false, + }, + sensitive, + morecomment = [l]//, + morecomment = [s]{/*}{*/}, + morecomment = [s]{/**}{*/}, + morestring = [b]", + morestring = [b]', +} + +\lstdefinelanguage{XML}{ + morestring = [b]", + moredelim = [s][\bfseries\color{listing-keyword}]{<}{\ }, + moredelim = [s][\bfseries\color{listing-keyword}]{}, + moredelim = [l][\bfseries\color{listing-keyword}]{/>}, + moredelim = [l][\bfseries\color{listing-keyword}]{>}, + morecomment = [s]{}, + morecomment = [s]{}, + commentstyle = \color{listing-comment}, + stringstyle = \color{listing-string}, + identifierstyle = \color{listing-identifier} +} + +\lstdefinelanguage{diff}{ + basicstyle=\ttfamily\small, + morecomment=[f][\color{diffstart}]{@@}, + morecomment=[f][\color{diffincl}]{+\ }, + morecomment=[f][\color{diffrem}]{-\ }, +} +$endif$ + +\usepackage{newunicodechar} +\newunicodechar{∙}{\ensuremath{\cdot}} + +% +% header and footer +% +$if(beamer)$ +$else$ +$if(disable-header-and-footer)$ +$else$ +\usepackage{fancyhdr} + +\fancypagestyle{eisvogel-header-footer}{ + \fancyhead{} + \fancyfoot{} + \lhead[$if(header-right)$$header-right$$else$$date$$endif$]{$if(header-left)$$header-left$$else$$title$$endif$} + \chead[$if(header-center)$$header-center$$else$$endif$]{$if(header-center)$$header-center$$else$$endif$} + \rhead[$if(header-left)$$header-left$$else$$title$$endif$]{$if(header-right)$$header-right$$else$$date$$endif$} + \lfoot[$if(footer-right)$$footer-right$$else$\thepage$endif$]{$if(footer-left)$$footer-left$$else$$for(author)$$author$$sep$, $endfor$$endif$} + \cfoot[$if(footer-center)$$footer-center$$else$$endif$]{$if(footer-center)$$footer-center$$else$$endif$} + \rfoot[$if(footer-left)$$footer-left$$else$$for(author)$$author$$sep$, $endfor$$endif$]{$if(footer-right)$$footer-right$$else$\thepage$endif$} + \renewcommand{\headrulewidth}{0.4pt} + \renewcommand{\footrulewidth}{0.4pt} +} +\pagestyle{eisvogel-header-footer} +$if(page-background)$ +\backgroundsetup{ +scale=1, +color=black, +opacity=$if(page-background-opacity)$$page-background-opacity$$else$0.2$endif$, +angle=0, +contents={% + \includegraphics[width=\paperwidth,height=\paperheight]{$page-background$} + }% +} +$endif$ +$endif$ +$endif$ + +%% +%% end added +%% + +\begin{document} + +%% +%% begin titlepage +%% +$if(beamer)$ +$else$ +$if(titlepage)$ +\begin{titlepage} +$if(titlepage-background)$ +\newgeometry{top=2cm, right=4cm, bottom=3cm, left=4cm} +$else$ +\newgeometry{left=6cm} +$endif$ +$if(titlepage-color)$ +\definecolor{titlepage-color}{HTML}{$titlepage-color$} +\newpagecolor{titlepage-color}\afterpage{\restorepagecolor} +$endif$ +$if(titlepage-background)$ +\tikz[remember picture,overlay] \node[inner sep=0pt] at (current page.center){\includegraphics[width=\paperwidth,height=\paperheight]{$titlepage-background$}}; +$endif$ +\newcommand{\colorRule}[3][black]{\textcolor[HTML]{#1}{\rule{#2}{#3}}} +\begin{flushleft} +\noindent +\\[-1em] +\color[HTML]{$if(titlepage-text-color)$$titlepage-text-color$$else$5F5F5F$endif$} +\makebox[0pt][l]{\colorRule[$if(titlepage-rule-color)$$titlepage-rule-color$$else$435488$endif$]{1.3\textwidth}{$if(titlepage-rule-height)$$titlepage-rule-height$$else$4$endif$pt}} +\par +\noindent + +$if(titlepage-background)$ +% The titlepage with a background image has other text spacing and text size +{ + \setstretch{2} + \vfill + \vskip -8em + \noindent {\huge \textbf{\textsf{$title$}}} + $if(subtitle)$ + \vskip 1em + {\Large \textsf{$subtitle$}} + $endif$ + \vskip 2em + \noindent {\Large \textsf{$for(author)$$author$$sep$, $endfor$} \vskip 0.6em \textsf{$date$}} + \vfill +} +$else$ +{ + \setstretch{1.4} + \vfill + \noindent {\huge \textbf{\textsf{$title$}}} + $if(subtitle)$ + \vskip 1em + {\Large \textsf{$subtitle$}} + $endif$ + \vskip 2em + \noindent {\Large \textsf{$for(author)$$author$$sep$, $endfor$}} + \vfill +} +$endif$ + +$if(logo)$ +\noindent +\includegraphics[width=$if(logo-width)$$logo-width$$else$35mm$endif$, left]{$logo$} +$endif$ + +$if(titlepage-background)$ +$else$ +\textsf{$date$} +$endif$ +\end{flushleft} +\end{titlepage} +\restoregeometry +$endif$ +$endif$ + +%% +%% end titlepage +%% + +$if(has-frontmatter)$ +\frontmatter +$endif$ +$if(title)$ +$if(beamer)$ +\frame{\titlepage} +$endif$ +$if(abstract)$ +\begin{abstract} +$abstract$ +\end{abstract} +$endif$ +$endif$ + +$if(first-chapter)$ +\setcounter{chapter}{$first-chapter$} +\addtocounter{chapter}{-1} +$endif$ + +$for(include-before)$ +$include-before$ + +$endfor$ +$if(toc)$ +$if(toc-title)$ +\renewcommand*\contentsname{$toc-title$} +$endif$ +$if(beamer)$ +\begin{frame}[allowframebreaks] +$if(toc-title)$ + \frametitle{$toc-title$} +$endif$ + \tableofcontents[hideallsubsections] +\end{frame} +$if(toc-own-page)$ +\newpage +$endif$ +$else$ +{ +$if(colorlinks)$ +\hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$$endif$} +$endif$ +\setcounter{tocdepth}{$toc-depth$} +\tableofcontents +$if(toc-own-page)$ +\newpage +$endif$ +} +$endif$ +$endif$ +$if(lot)$ +\listoftables +$endif$ +$if(lof)$ +\listoffigures +$endif$ +$if(linestretch)$ +\setstretch{$linestretch$} +$endif$ +$if(has-frontmatter)$ +\mainmatter +$endif$ +$body$ + +$if(has-frontmatter)$ +\backmatter +$endif$ +$if(natbib)$ +$if(bibliography)$ +$if(biblio-title)$ +$if(has-chapters)$ +\renewcommand\bibname{$biblio-title$} +$else$ +\renewcommand\refname{$biblio-title$} +$endif$ +$endif$ +$if(beamer)$ +\begin{frame}[allowframebreaks]{$biblio-title$} + \bibliographytrue +$endif$ + \bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$} +$if(beamer)$ +\end{frame} +$endif$ + +$endif$ +$endif$ +$if(biblatex)$ +$if(beamer)$ +\begin{frame}[allowframebreaks]{$biblio-title$} + \bibliographytrue + \printbibliography[heading=none] +\end{frame} +$else$ +\printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$ +$endif$ + +$endif$ +$for(include-after)$ +$include-after$ + +$endfor$ +\end{document} diff --git a/FP/templates/elegant_bootstrap_menu.html b/FP/templates/elegant_bootstrap_menu.html new file mode 100644 index 0000000..7b2b989 --- /dev/null +++ b/FP/templates/elegant_bootstrap_menu.html @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +$for(author-meta)$ + +$endfor$ +$if(date-meta)$ + +$endif$ + $if(title-prefix)$$title-prefix$ - $endif$$pagetitle$ + +$if(quotes)$ + +$endif$ +$if(highlighting-css)$ + +$endif$ +$for(css)$ + +$endfor$ +$if(math)$ + $math$ +$endif$ +$for(header-includes)$ + $header-includes$ +$endfor$ + + + + + $if(title)$ +

+ $endif$ +
+
+ $if(toc)$ +
+
+ + $toc$ + +
+
+ $endif$ +
+ $for(include-before)$ + $include-before$ + $endfor$ +$body$ + $for(include-after)$ + $include-after$ + $endfor$ +
+
+
+ + + + diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..ad7bacb --- /dev/null +++ b/flake.lock @@ -0,0 +1,58 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "neorg-pandoc-src": { + "flake": false, + "locked": { + "lastModified": 1664988615, + "narHash": "sha256-jKBk1PPctIQhqbKGcFr4AnuX+bWRJEUVEh8FlDLcFO8=", + "owner": "JCapucho", + "repo": "neorg-haskell-parser", + "rev": "791afc59c945e0a90908e5d53c43fd26c0d6b26b", + "type": "github" + }, + "original": { + "owner": "JCapucho", + "repo": "neorg-haskell-parser", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1663264531, + "narHash": "sha256-2ncO5chPXlTxaebDlhx7MhL0gOEIWxzSyfsl0r0hxQk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "454887a35de6317a30be284e8adc2d2f6d8a07c4", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "neorg-pandoc-src": "neorg-pandoc-src", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..27256c8 --- /dev/null +++ b/flake.nix @@ -0,0 +1,53 @@ +{ + inputs = { + flake-utils.url = "github:numtide/flake-utils"; + + neorg-pandoc-src.url = "github:JCapucho/neorg-haskell-parser"; + # neorg-pandoc-src.url = "path:///home/capucho/programming/neorg-haskell-parser"; + neorg-pandoc-src.flake = false; + }; + outputs = { + nixpkgs, + flake-utils, + neorg-pandoc-src, + ... + }: + flake-utils.lib.eachDefaultSystem (system: let + pkgs = nixpkgs.legacyPackages.${system}; + hCallPackage = pkgs.haskellPackages.callPackage; + neorg-pandoc = hCallPackage ./nix/neorg-pandoc.nix { + inherit neorg-pandoc-src; + }; + in { + # packages.default = pkgs.mkDerivation { + # pname = "export"; + # version = "0.1"; + # + # buildInputs = [ + # pandoc + # neorg-pandoc + # ]; + # + # buildPhase = '' + # mkdir -p $out + # ./build.sh + # ''; + # + # src = ./.; + # }; + devShell = pkgs.mkShell { + buildInputs = with pkgs; [ + black + ghostscript + imagemagick + python3Packages.python-lsp-server + python3Packages.matplotlib + pandoc + neorg-pandoc + dotnet-sdk + nodePackages.prettier + jdk + ]; + }; + }); +} diff --git a/nix/neorg-pandoc.nix b/nix/neorg-pandoc.nix new file mode 100644 index 0000000..544bb64 --- /dev/null +++ b/nix/neorg-pandoc.nix @@ -0,0 +1,78 @@ +{ + mkDerivation, + aeson, + base, + bytestring, + cleff, + containers, + data-default, + fetchgit, + lib, + megaparsec, + optics-core, + optics-th, + pandoc-types, + tasty, + tasty-hunit, + text, + text-builder, + time, + transformers, + vector, + applyPatches, + neorg-pandoc-src, +}: +mkDerivation { + pname = "neorg"; + version = "0.1.0.0"; + src = applyPatches { + name = "neorg-pandoc-src"; + src = neorg-pandoc-src; + patches = [./neorg-pandoc.patch]; + }; + isLibrary = true; + isExecutable = true; + + doCheck = false; + + libraryHaskellDepends = [ + base + cleff + containers + data-default + megaparsec + optics-core + optics-th + text + text-builder + time + transformers + vector + ]; + executableHaskellDepends = [ + aeson + base + bytestring + cleff + containers + optics-core + pandoc-types + text + transformers + vector + ]; + testHaskellDepends = [ + base + cleff + megaparsec + optics-core + tasty + tasty-hunit + text + time + transformers + vector + ]; + license = "unknown"; + mainProgram = "neorg-pandoc"; +} diff --git a/nix/neorg-pandoc.patch b/nix/neorg-pandoc.patch new file mode 100644 index 0000000..cfca667 --- /dev/null +++ b/nix/neorg-pandoc.patch @@ -0,0 +1,22 @@ +diff --git a/neorg.cabal b/neorg.cabal +index 17eb38a..0e15979 100644 +--- a/neorg.cabal ++++ b/neorg.cabal +@@ -56,7 +56,7 @@ library + + -- LANGUAGE extensions used by modules in this package. + -- other-extensions: +- build-depends: base ^>=4.14.2.0, text, vector, containers, megaparsec, time, transformers, optics-core, optics-th, data-default, cleff, cleff, text-builder ++ build-depends: base >=4.14.2.0 && <4.16, text, vector, containers, megaparsec, time, transformers, optics-core, optics-th, data-default, cleff, cleff, text-builder + hs-source-dirs: src + -- include-dirs: tree-sitter-norg/src + -- c-sources: tree-sitter-norg/src/parser.c, tree-sitter-norg/src/scanner.cc +@@ -66,7 +66,7 @@ library + executable neorg-pandoc + import: common + main-is: Main.hs +- build-depends: base ^>=4.14.2.0, text, vector, containers, bytestring, aeson, pandoc-types, optics-core, neorg, transformers, cleff ++ build-depends: base >=4.14.2.0 && <4.16, text, vector, containers, bytestring, aeson, pandoc-types, optics-core, neorg, transformers, cleff + hs-source-dirs: pandoc + + test-suite test