├── Introduction-to-Functional-Programming.md ├── LICENSE ├── LICENSE.md ├── README.md ├── classes_tools └── elixir │ └── livebook │ ├── Dockerfile │ ├── README.md │ └── notebooks │ ├── 06-17-2021 │ └── functions.livemd │ ├── 10-24-2023 │ └── state.md │ └── 2023_10_17.livemd ├── examples ├── adventofcode2019 │ ├── advent01.exs │ └── advent02.exs ├── center.exs ├── comunicacao.exs ├── erlang │ ├── jokenpo.beam │ └── jokenpo.erl ├── estatistica.exs ├── fatorial.exs ├── geometria.exs ├── lean │ ├── README.md │ ├── examples_1.lean │ ├── examples_1_5.lean │ ├── examples_1_6.lean │ ├── functional_programming_lean_notes.md │ ├── independent_programs │ │ ├── Hello.lean │ │ └── HelloName.lean │ └── scripts │ │ └── Hello.lean ├── macros.exs ├── maffetone.exs ├── map_coloring │ ├── .formatter.exs │ ├── .gitignore │ ├── README.md │ ├── lib │ │ └── map_coloring.ex │ ├── mix.exs │ └── test │ │ ├── map_coloring_test.exs │ │ └── test_helper.exs ├── send_receive.exs ├── truth_table.exs └── truth_table_streams.exs ├── exercises ├── maffetone.md ├── maps_keywordlists_sets.md └── random.md ├── historico ├── oferecimentos.md └── trabalhos.md ├── languages ├── ocaml.md └── pt │ └── ocaml.md ├── links.md ├── minicursos └── semana_formacao_docente_2020.md ├── offerings ├── 2019 │ ├── aulas_2019.md │ └── class_of_2019.md ├── 2020 │ ├── classes │ │ └── class01.md │ ├── students.md │ └── videos.md ├── 2021 │ └── 2021.md ├── 2022 │ ├── 01_01_presentation.md │ ├── 01_introduction.md │ └── projects │ │ ├── README.md │ │ ├── guess │ │ ├── .formatter.exs │ │ ├── .gitignore │ │ ├── README.md │ │ ├── lib │ │ │ ├── guess.ex │ │ │ ├── guess │ │ │ │ └── cli │ │ │ │ │ └── main.ex │ │ │ └── mix │ │ │ │ └── tasks │ │ │ │ └── start.ex │ │ ├── mix.exs │ │ └── test │ │ │ ├── guess_test.exs │ │ │ └── test_helper.exs │ │ └── tic_tac_toe │ │ ├── .formatter.exs │ │ ├── .gitignore │ │ ├── README.md │ │ ├── lib │ │ ├── mix │ │ │ └── tasks │ │ │ │ └── start.ex │ │ ├── tic_tac_toe.ex │ │ └── tic_tac_toe │ │ │ └── cli │ │ │ └── main.ex │ │ ├── mix.exs │ │ ├── mix.lock │ │ └── test │ │ ├── test_helper.exs │ │ └── tic_tac_toe_test.exs ├── 2023 │ ├── README.md │ ├── livebooks │ │ ├── 2023_10_17.livemd │ │ ├── 2023_10_24.livemd │ │ ├── 2023_10_31 │ │ │ ├── README.md │ │ │ ├── oct31_part1.livemd │ │ │ ├── oct31_part2.livemd │ │ │ └── oct31_part3.livemd │ │ ├── 2023_11_14.livemd │ │ ├── 2023_12_05.livemd │ │ ├── 2023_12_05_2.livemd │ │ ├── 2023_12_08_1.livemd │ │ ├── 2023_12_12_2.livemd │ │ └── digraphs.livemd │ ├── notes │ │ ├── 2023_11_21.md │ │ ├── 2023_11_28.md │ │ └── knowldege_items.md │ ├── projects │ │ ├── aoc2017_day01 │ │ │ ├── .formatter.exs │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── lib │ │ │ │ └── aoc2017_day01.ex │ │ │ ├── mix.exs │ │ │ └── test │ │ │ │ ├── aoc2017_day01_test.exs │ │ │ │ └── test_helper.exs │ │ ├── factorial │ │ │ ├── .formatter.exs │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── factorial │ │ │ ├── lib │ │ │ │ ├── calculator.ex │ │ │ │ └── factorial.ex │ │ │ ├── mix.exs │ │ │ └── test │ │ │ │ ├── factorial_test.exs │ │ │ │ └── test_helper.exs │ │ ├── pbt │ │ │ ├── .formatter.exs │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── lib │ │ │ │ └── pbt.ex │ │ │ ├── mix.exs │ │ │ ├── mix.lock │ │ │ └── test │ │ │ │ ├── pbt_props_test.exs │ │ │ │ ├── pbt_test.exs │ │ │ │ └── test_helper.exs │ │ ├── tasks │ │ │ ├── .formatter.exs │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── lib │ │ │ │ ├── mix │ │ │ │ │ └── tasks │ │ │ │ │ │ └── play.ex │ │ │ │ └── tasks.ex │ │ │ ├── mix.exs │ │ │ └── test │ │ │ │ ├── tasks_test.exs │ │ │ │ └── test_helper.exs │ │ └── tictactoe │ │ │ ├── .formatter.exs │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── lib │ │ │ └── tictactoe.ex │ │ │ ├── mix.exs │ │ │ └── test │ │ │ ├── test_helper.exs │ │ │ └── tictactoe_test.exs │ ├── scripts │ │ ├── 01_simple │ │ │ ├── 01.exs │ │ │ ├── 02.exs │ │ │ ├── 03.exs │ │ │ └── 04.exs │ │ ├── 02_factorial │ │ │ ├── 01.exs │ │ │ ├── 02.exs │ │ │ ├── 03.exs │ │ │ ├── 04.exs │ │ │ └── 05.exs │ │ └── 03_mix_install │ │ │ ├── 01.exs │ │ │ └── 02.exs │ └── tasks │ │ ├── exercism_task.md │ │ ├── game_task.md │ │ ├── image.png │ │ ├── knowledge_items.md │ │ ├── languages_task.md │ │ └── paper_task.md ├── 2024 │ ├── Livebook │ │ ├── 20241009 │ │ │ ├── Dockerfile │ │ │ ├── receiver.livemd │ │ │ └── sender.livemd │ │ ├── 20241023 │ │ │ ├── aniversario.livemd │ │ │ ├── app.livemd │ │ │ ├── funcoes.livemd │ │ │ ├── funcoes_claude.livemd │ │ │ ├── funcoes_claude_v2.livemd │ │ │ └── funcoes_claude_v3.livemd │ │ ├── 20241108 │ │ │ └── nx_tensors.livemd │ │ ├── 20241114 │ │ │ └── estruturas_de_controle.livemd │ │ ├── 20241205 │ │ │ └── aula-dezembro-05.livemd │ │ └── help │ │ │ ├── app │ │ │ └── start │ ├── README.md │ ├── currying │ │ ├── currying.hs │ │ └── firstclass.pas │ ├── desafio_dos_tres │ │ └── README.md │ ├── elixir_projects │ │ ├── deffunc │ │ │ ├── .formatter.exs │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── lib │ │ │ │ └── deffunc.ex │ │ │ ├── mix.exs │ │ │ └── test │ │ │ │ ├── deffunc_test.exs │ │ │ │ └── test_helper.exs │ │ └── megasena │ │ │ ├── .formatter.exs │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── chama.txt │ │ │ ├── lib │ │ │ ├── megasena.ex │ │ │ └── megasena │ │ │ │ ├── application.ex │ │ │ │ ├── player.ex │ │ │ │ ├── server.ex │ │ │ │ └── supervisor.ex │ │ │ ├── mix.exs │ │ │ └── test │ │ │ ├── megasena_test.exs │ │ │ └── test_helper.exs │ ├── lazy │ │ ├── lazyeval │ │ ├── lazyeval.hi │ │ ├── lazyeval.hs │ │ ├── lazyeval.o │ │ └── lazyfib.exs │ ├── lua │ │ ├── alo_mundo.lua │ │ ├── array.lua │ │ ├── eight_queens.lua │ │ ├── eight_queens_chatgpt.lua │ │ ├── funcao_cidada.lua │ │ ├── maior.lua │ │ └── maior_fatorial.lua │ ├── macros │ │ ├── .formatter.exs │ │ ├── .gitignore │ │ ├── README.md │ │ ├── lib │ │ │ ├── calculator.ex │ │ │ └── macros.ex │ │ ├── mix.exs │ │ └── test │ │ │ ├── calculator_test.exs │ │ │ ├── macros_test.exs │ │ │ └── test_helper.exs │ └── monad │ │ ├── monad │ │ ├── monad.hi │ │ ├── monad.hs │ │ └── monad.o └── 2025 │ ├── livebooks │ └── luaelixir.livemd │ └── sample_projects │ └── distributed_hello_world │ ├── .formatter.exs │ ├── .gitignore │ ├── README.md │ ├── lib │ ├── distributed_hello_world.ex │ └── distributed_hello_world │ │ └── application.ex │ ├── mix.exs │ └── test │ ├── distributed_hello_world_test.exs │ └── test_helper.exs ├── other_courses ├── elixir_erlang_beam.md ├── material.md ├── software_verification.md ├── temp.md └── types_etc.md ├── stech2019 ├── resumo.md ├── stech_2019.md ├── stech_slides.md └── stech_slides.pdf └── topics ├── README.md ├── control_flow.md ├── mix_task.md ├── pt ├── macros.md ├── mix.md ├── mix1.png ├── phoenix.md └── processos.md ├── sample_projects.md ├── strings_binaries_and_charlists_1.md └── strings_binaries_and_charlists_2.md /Introduction-to-Functional-Programming.md: -------------------------------------------------------------------------------- 1 | # Introduction to Functional Programming 2 | 3 | 4 | A 45-hour course for graduate and undergraduate students at UTFPR Curitiba. 5 | 6 | ## Syllabus 7 | 8 | - Functional Programming: Concepts and main languages. 9 | - Functions: functions as first class citizens, named functions and anonymous functions, Currying, modules. 10 | - Pattern Matching. 11 | - Data structures and immutability. 12 | - Recursion. 13 | - Collection processing. 14 | - Lazy evaluation. 15 | - Control Flow. 16 | - Implementation of projects using a functional language. 17 | - Overview of functional languages for concurrency. 18 | 19 | 20 | ### Suggested Additions 21 | 22 | - [Higher-order functions](https://twitter.com/ramalhoorg/status/1148778652655640579?s=20) 23 | - [Layers](https://twitter.com/redrapids/status/1148670656374091776?s=20) 24 | - [Purity, ie, separating effectful code](https://twitter.com/ktec/status/1148748154709446656?s=20) 25 | - [Why functional data structures are different from OOP or procedural data structures](https://twitter.com/redrapids/status/1148670656374091776?s=20) 26 | - [Why functional programming became interesting](https://twitter.com/renanranelli/status/1148793119946575875?s=20) 27 | - [Other paradigms](https://twitter.com/SWI_Prolog/status/1148905678758535169?s=20) 28 | - [Parametric polymorphism?](https://twitter.com/rodinhart/status/1148975522833027078?s=20) 29 | - [Lambda calculus, call-by-value, call-by-name](https://twitter.com/Kakadu18/status/1149567470635642881?s=20). See also [this](https://pdfs.semanticscholar.org/9e1c/0bf9c3c2e0a293f7eb5a38a9253551dc2e1f.pdf). 30 | 31 | ## References 32 | 33 | - Thomas, Dave. **[Programming Elixir 1.6: Functional |> Concurrent |> Pragmatic |> Fun.](https://pragprog.com/book/elixir16/programming-elixir-1-6)** Pragmatic Programmers, 2018. 34 | - Almeida, Ulisses. **[Learn Functional Programming with Elixir: New Foundations for a New World.](https://pragprog.com/book/cdc-elixir/learn-functional-programming-with-elixir)** Pragmatic Programmers, 2018. 35 | - Davi, Tiago. **[Elixir: Do zero à concorrência.](https://www.casadocodigo.com.br/products/livro-elixir)** Casa do Código, 2017. 36 | - Sebesta, Robert W. **[Concepts of Programming Languages.](https://www.amazon.com/Concepts-Programming-Languages-Robert-Sebesta/dp/013394302X/)** 11th Edition, Pearson, 2015. 37 | - Scientific papers and gray literature (blog posts, podcast episodes, videos, etc.) 38 | 39 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Adolfo Neto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /classes_tools/elixir/livebook/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM hexpm/elixir:1.12.0-erlang-24.0-alpine-3.13.3 2 | 3 | # we need to git if anyone try to install a git Mix dep 4 | RUN apk add --no-cache build-base openssl ncurses-libs 5 | 6 | RUN adduser caes005-introduction-to-functional-programming intro_functional -D 7 | 8 | USER caes005-introduction-to-functional-programming 9 | 10 | WORKDIR /home/caes005-introduction-to-functional-programming 11 | 12 | # Install hex and rebar 13 | RUN mix local.hex --force && \ 14 | mix local.rebar --force 15 | 16 | # install livebook itself 17 | RUN yes | mix escript.install hex livebook 18 | 19 | COPY ./notebooks /home/caes005-introduction-to-functional-programming/notebooks 20 | 21 | # Override the default 127.0.0.1 address, so that the app 22 | # can be accessed outside the container by binding ports 23 | ENV LIVEBOOK_IP 0.0.0.0 24 | ENV LIVEBOOK_PASSWORD xxxxxxxxxxxxxxx 25 | 26 | CMD [ "./.mix/escripts/livebook", "server" ] 27 | -------------------------------------------------------------------------------- /classes_tools/elixir/livebook/README.md: -------------------------------------------------------------------------------- 1 | # LiveBook 2 | 3 | From 06/17/2021 class we started to use [livebook](https://github.com/elixir-nx/livebook) to all students be able to collaborative write and test `Elixir` code! 4 | 5 | ## Setting up 6 | 7 | Remember to set `LIVEBOOK_PASSWORD` env in [Dockerfile](./Dockerfile)!!! 8 | 9 | You nee to create an account at [fly.io](fly.io), install thier cli tool `flyctl` and then: 10 | 11 | 1. Run `flyctl auth login` 12 | 2. In this folder, run `flyctl launch` 13 | 14 | After that you will be prompted for the new app config. 15 | 16 | To open the new app, run `flyctl open`. 17 | -------------------------------------------------------------------------------- /classes_tools/elixir/livebook/notebooks/06-17-2021/functions.livemd: -------------------------------------------------------------------------------- 1 | # Functions 2 | 3 | ## Named Functions 4 | 5 | ```elixir 6 | defmodule BMI do 7 | def calculate(weight, height) do 8 | weight / (height * height) 9 | end 10 | 11 | def obese?(weight, height) do 12 | calculate(weight, height) > 30 13 | end 14 | end 15 | ``` 16 | 17 | ```elixir 18 | BMI.calculate(100, 1.8) 19 | ``` 20 | 21 | ```elixir 22 | BMI.calculate(70, 1.8) 23 | ``` 24 | 25 | ```elixir 26 | BMI.obese?(90, 1.80) 27 | ``` 28 | 29 | ## Anonymous Functions 30 | 31 | ```elixir 32 | fn x -> x + 1 end 33 | ``` 34 | 35 | ```elixir 36 | (fn x -> x + 1 end).(3) 37 | ``` 38 | 39 | ```elixir 40 | fn weight, height -> weight / (height * height) end 41 | ``` 42 | 43 | ```elixir 44 | (fn weight, height -> weight / (height * height) end).(100, 1.80) 45 | ``` 46 | 47 | ## Functions as First-Class Citizens 48 | 49 | An anonymous function assigned to a variable 50 | 51 | ```elixir 52 | f = fn weight, height -> weight / (height * height) end 53 | f.(100, 1.80) 54 | ``` 55 | 56 | A function that, when applied, returns another function 57 | 58 | ```elixir 59 | g = fn x -> fn y -> x + y + 1 end end 60 | h = g.(4) 61 | h.(10) 62 | ``` 63 | 64 | A function received as a parameter 65 | 66 | ```elixir 67 | f = fn x -> x + 1 end 68 | g = fn y -> y.(4) end 69 | h = g.(f) 70 | ``` 71 | 72 | ## A different syntax for anonymous functions 73 | 74 | ```elixir 75 | &(&1 + 1) 76 | 77 | fn x -> x + 1 end 78 | 79 | h = &(&2 * &3 + &1) 80 | h.(1, 2, 3) 81 | ``` -------------------------------------------------------------------------------- /classes_tools/elixir/livebook/notebooks/10-24-2023/state.md: -------------------------------------------------------------------------------- 1 | - EXERCISM 2 | 3 | 1 Alessandro Bueno 4 | VM499:2 2 Derli Machado 5 | VM499:2 3 Diogo Dias 6 | OK VM499:2 4 Gabriel Magalhaes 7 | VM499:2 5 Gabriel Shimosaka 8 | OK VM499:2 6 GERALDO SAMIR SILVEIRA VARRIALE 9 | VM499:2 7 Igor Vinícius 10 | (INTERNET NOT GOOD) VM499:2 8 LETICIA D SANTI MOREIRA 11 | VM499:2 9 Lucas Kemp de Oliveira 12 | VM499:2 10 LUCIANO ANTONICHEN DE CAMPOS 13 | ?? VM499:2 11 Maike Cristian 14 | VM499:2 12 Michelangelo Cali 15 | ?? VM499:2 13 RAUL SCARMOCIN DE FREITAS 16 | VM499:2 14 Ricardo Dos S. Alvares 17 | VM499:2 15 Ricardo Serathiuk 18 | VM499:2 16 VITOR OLIVEIRA DOS SANTOS 19 | 20 | document.querySelectorAll('.zWGUib').forEach(function(element, k) { 21 | console.log(k + ' ' + element.innerHTML); 22 | }); 23 | 24 | Rodando no console do browser pra pegar todos os que contém os nomes dos participantes. Todos tem uma classe em comum mas o nome 'zWGUib'. Aparentemente ela não muda mas é um ponto de atenção. 25 | 26 | Daí usa o https://www.random.org/lists/ pra selecionar um felizardo pra responder. 27 | 28 | Sugestão só =D 29 | 30 | https://huggingface.co/spaces/adolfont/learn4elixir 31 | 32 | Transcribing an audio file into a .srt file 33 | https://gist.github.com/adolfont/6452374069e7a5cb4b9bf52febdffe00 34 | 35 | - State 36 | 37 | 38 | LISTEN WITH THE STUDENTS AND THEN DRAW 39 | 40 | - [Teaching Functional Programming, Software Unscripted](https://open.spotify.com/episode/0RhRifMc0XzigROlXRQPDM) 41 | 42 | - [Transcription](https://sites.google.com/noredink.com/podcast-transcriptions/1-2-teaching-functional-programming?authuser=0) 43 | 44 | - How do you define functional programming? 45 | - art 46 | - pure functions 47 | - inputs, arguments, information, output 48 | - no side effects 49 | - nothing goes to the console 50 | - no other impact in the world 51 | 52 | 53 | - Functional programming style 54 | - avoiding mutation and side effects 55 | - pure function 56 | - Functional programming languages 57 | 58 | 59 | - Programming withou state 60 | - Cherry notebook https://dev.to/cherryramatis/handling-state-between-multiple-instances-with-elixir-4jm1 61 | 62 | - Memory 63 | - Storage 64 | - Variables as storage address vs name for value 65 | - Mutation 66 | 67 | 68 | MY VIDEO 69 | 70 | 71 | EXERCISE: smallest largest -------------------------------------------------------------------------------- /examples/adventofcode2019/advent01.exs: -------------------------------------------------------------------------------- 1 | defmodule Advent01 do 2 | @moduledoc """ 3 | Documentation for Advent01. 4 | """ 5 | 6 | def fuel(x) do 7 | div(x, 3) - 2 8 | end 9 | 10 | def mass(y) when y<=0, do: 0 11 | 12 | def mass(x) do 13 | (if (fuel(x)<0), do: 0, else: fuel(x)) + mass(fuel(x)) 14 | end 15 | 16 | end 17 | 18 | # Part 1 19 | File.read!("input.txt") 20 | |> String.split("\n") 21 | |> Enum.map(&String.to_integer/1) 22 | |> Enum.map(&Advent01.fuel/1) 23 | |> Enum.sum() 24 | |> IO.inspect() 25 | 26 | # Part 2 27 | File.read!("input.txt") 28 | |> String.split("\n") 29 | |> Enum.map(&String.to_integer/1) 30 | |> Enum.map(&Advent01.mass/1) 31 | |> Enum.sum() 32 | |> IO.inspect() 33 | -------------------------------------------------------------------------------- /examples/adventofcode2019/advent02.exs: -------------------------------------------------------------------------------- 1 | defmodule Advent02 do 2 | def readFile(filename) do 3 | File.read(filename) 4 | end 5 | 6 | def process(string) do 7 | String.split(string, ",") 8 | |> Enum.map(&String.to_integer/1) 9 | |> process_options(0) 10 | |> Enum.join(",") 11 | end 12 | 13 | defp process_options(all, cursor) when cursor < length(all) do 14 | case Enum.at(all, cursor) do 15 | 1 -> do_operation(all, cursor, &Kernel.+/2) 16 | 2 -> do_operation(all, cursor, &Kernel.*/2) 17 | 99 -> all 18 | end 19 | end 20 | 21 | defp do_operation(all, cursor, operation) do 22 | op1_pos = Enum.at(all, cursor + 1) 23 | op2_pos = Enum.at(all, cursor + 2) 24 | result_pos = Enum.at(all, cursor + 3) 25 | 26 | value1 = Enum.at(all, op1_pos) 27 | value2 = Enum.at(all, op2_pos) 28 | 29 | List.replace_at(all, result_pos, operation.(value1, value2)) 30 | |> process_options(cursor + 4) 31 | end 32 | 33 | def trim_and_replace(input, {pos1, value1}, {pos2, value2}) do 34 | input 35 | |> String.trim() 36 | |> String.split(",") 37 | |> Enum.map(&String.to_integer/1) 38 | |> List.replace_at(pos1, value1) 39 | |> List.replace_at(pos2, value2) 40 | |> Enum.join(",") 41 | end 42 | end 43 | 44 | ExUnit.start() 45 | 46 | defmodule Advent02Test do 47 | use ExUnit.Case 48 | 49 | test "Tries to reads file and it works" do 50 | assert {:ok, _} = Advent02.readFile("input02.txt") 51 | end 52 | 53 | test "Processes examples" do 54 | inputs = [ 55 | "1,9,10,3,2,3,11,0,99,30,40,50", 56 | "1,0,0,0,99", 57 | "2,3,0,3,99", 58 | "2,4,4,5,99,0", 59 | "1,1,1,4,99,5,6,0,99" 60 | ] 61 | 62 | outputs = [ 63 | "3500,9,10,70,2,3,11,0,99,30,40,50", 64 | "2,0,0,0,99", 65 | "2,3,0,6,99", 66 | "2,4,4,5,99,9801", 67 | "30,1,1,4,2,5,6,0,99" 68 | ] 69 | 70 | for {x, y} <- Enum.zip(inputs, outputs) do 71 | assert Advent02.process(x) == y 72 | end 73 | end 74 | 75 | # part 1 76 | test "Processing AdventOfCode input with my file - Part 1" do 77 | {:ok, input} = Advent02.readFile("input02.txt") 78 | 79 | new_input = Advent02.trim_and_replace(input, {1, 12}, {2, 2}) 80 | 81 | assert String.starts_with?(Advent02.process(new_input), "5290681,") 82 | end 83 | 84 | # part 2 85 | test "Processing AdventOfCode input with my file - Part 2" do 86 | {:ok, input} = Advent02.readFile("input02.txt") 87 | 88 | for noun <- 0..99, verb <- 0..99 do 89 | new_input = Advent02.trim_and_replace(input, {1, noun}, {2, verb}) 90 | 91 | if String.starts_with?(Advent02.process(new_input), "19690720,") do 92 | # IO.puts("noun = #{noun}") 93 | # IO.puts("verb = #{verb}") 94 | # IO.puts("100 * noun + verb = #{100 * noun + verb}") 95 | assert 100 * noun + verb == 5741 96 | end 97 | end 98 | end 99 | end 100 | -------------------------------------------------------------------------------- /examples/center.exs: -------------------------------------------------------------------------------- 1 | defmodule Center do 2 | require Integer 3 | 4 | def center(string_list) do 5 | size_max = string_list |> Enum.max_by(&String.length/1) |> String.length() 6 | 7 | Enum.map(string_list, fn x -> show(x, size_max) end) 8 | end 9 | 10 | defp show(string, size_max) do 11 | length = String.length(string) 12 | left = div(size_max - length, 2) 13 | # if (Integer.is_odd(size_max-length)), do: left = left - 1 14 | string |> String.pad_leading(length + left) |> String.pad_trailing(size_max) |> IO.puts() 15 | end 16 | end 17 | 18 | Center.center(["cat", "zebra", "elephant", "elepahnt", "lephan"]) 19 | IO.puts("") 20 | Center.center(["cat", "zebra", "elephant"]) 21 | IO.puts("") 22 | Center.center(["cat", "zebra", "lephan"]) 23 | IO.puts("") 24 | Center.center(["cat", "zebra", "elephant", "lephan"]) 25 | -------------------------------------------------------------------------------- /examples/comunicacao.exs: -------------------------------------------------------------------------------- 1 | 2 | defmodule Comunicacao do 3 | def cumprimenta do 4 | receive do 5 | {remetente, mensagem} -> 6 | send remetente, { :ok, "Olá, #{mensagem}" } 7 | end 8 | end 9 | end 10 | 11 | pid = spawn(Comunicacao, :cumprimenta, []) 12 | send pid, {self(), "Mundo!"} 13 | 14 | receive do 15 | {:ok, mensagem} -> 16 | IO.puts mensagem 17 | end 18 | 19 | receive do 20 | {:ok, mensagem} -> 21 | IO.puts mensagem 22 | after 23 | 1_000 -> "Nada!" 24 | end 25 | -------------------------------------------------------------------------------- /examples/erlang/jokenpo.beam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adolfont/caes005-introduction-to-functional-programming/a9b6de4534585a632113a1d960a9102c0715fb5c/examples/erlang/jokenpo.beam -------------------------------------------------------------------------------- /examples/erlang/jokenpo.erl: -------------------------------------------------------------------------------- 1 | -module(jokenpo). 2 | -export([play/2]). 3 | 4 | play(X,X) -> 5 | case lists:member(X, [rock, paper, scissors]) of 6 | true -> 7 | {tie, X}; 8 | false -> 9 | {"Error: invalid options!", {X, X}} 10 | end; 11 | play(rock,paper) -> {win, paper}; 12 | play(paper,rock) -> {win, paper}; 13 | play(rock,scissors) -> {win, rock}; 14 | play(scissors,rock) -> {win, rock}; 15 | play(scissors,paper) -> {win, scissors}; 16 | play(paper,scissors) -> {win, scissors}; 17 | play(X,Y) -> {error, "Error: invalid options!", {X, Y}}. 18 | 19 | % c("jokenpo.erl"). 20 | % jokenpo:play(paper, scissors). 21 | % will return {win,scissors} 22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/estatistica.exs: -------------------------------------------------------------------------------- 1 | defmodule Estatistica do 2 | # http://dojopuzzles.com/problemas/exibe/calculando-estatisticas-simples/ 3 | 4 | def mostra(lista) do 5 | IO.puts("Valor mínimo: #{valorMinimo(lista)}") 6 | IO.puts("Valor máximo: #{valorMaximo(lista)}") 7 | IO.puts("Número de elementos na sequência: #{tamanho(lista)}") 8 | IO.puts("Valor médio: #{valorMedio(lista)}") 9 | end 10 | 11 | def valorMinimo([head|tail]) do 12 | limite(head,tail, &(&1 < &2)) 13 | end 14 | 15 | def valorMaximo([head|tail]) do 16 | limite(head,tail, &(&1 > &2)) 17 | end 18 | 19 | def tamanho([]), do: 0 20 | 21 | def tamanho([_|tail]) do 22 | 1 + tamanho(tail) 23 | end 24 | 25 | def valorMedio(lista) do 26 | soma(lista)/tamanho(lista) 27 | end 28 | 29 | defp soma([]), do: 0 30 | 31 | defp soma([head|tail]) do 32 | head + soma(tail) 33 | end 34 | 35 | defp limite(limite_ate_agora,[], _) do 36 | limite_ate_agora 37 | end 38 | 39 | defp limite(limite_ate_agora,[head|tail], f) do 40 | if f.(head, limite_ate_agora) do 41 | limite(head,tail,f) 42 | else 43 | limite(limite_ate_agora,tail,f) 44 | end 45 | end 46 | 47 | 48 | end 49 | -------------------------------------------------------------------------------- /examples/fatorial.exs: -------------------------------------------------------------------------------- 1 | defmodule Fatorial do 2 | def fat(1), do: 1 3 | def fat(n), do: n * fat(n-1) 4 | 5 | # https://inquisitivedeveloper.com/lwm-elixir-35/ 6 | def of(n), do: of(n, 1) 7 | defp of(0, current_factorial), do: current_factorial 8 | defp of(n, current_factorial) when n > 0, do: of(n - 1, current_factorial * n) 9 | 10 | def of_2(0), do: 1 11 | def of_2(n) when n > 0 do 12 | Enum.reduce(1..n, fn (x, fact) -> fact * x end) 13 | end 14 | 15 | def measure(function) do 16 | function 17 | |> :timer.tc 18 | |> elem(0) 19 | |> Kernel./(1_000_000) 20 | end 21 | end 22 | 23 | # testar com 400000 24 | entrada = IO.gets("Digite um número: ") 25 | numero = entrada |> String.trim() |> String.to_integer() 26 | 27 | # IO.puts("O fatorial de #{numero} é #{Fatorial.of_2(numero)}") 28 | # IO.puts("O fatorial de #{numero} é #{Fatorial.of(numero)}") 29 | # IO.puts("O fatorial de #{numero} é #{Fatorial.fat(numero)}") 30 | 31 | IO.puts("O tempo para calcular o fatorial de #{numero} é #{Fatorial.measure(fn -> Fatorial.of_2(numero) end)}") 32 | IO.puts("O tempo para calcular o fatorial de #{numero} é #{Fatorial.measure(fn -> Fatorial.of(numero) end)}") 33 | IO.puts("O tempo para calcular o fatorial de #{numero} é #{Fatorial.measure(fn -> Fatorial.fat(numero) end)}") 34 | -------------------------------------------------------------------------------- /examples/geometria.exs: -------------------------------------------------------------------------------- 1 | defmodule Geometria do 2 | def pi do 3 | 3.1415 4 | end 5 | 6 | def circunferencia(raio) do 7 | 2 * pi() * raio 8 | end 9 | 10 | def area_circulo(raio) do 11 | pi() * raio * raio 12 | end 13 | 14 | def perimetro_quadrado(lado) do 15 | 4 * lado 16 | end 17 | 18 | def area_quadrado(lado) do 19 | lado * lado 20 | end 21 | 22 | def perimetro_triangulo(lado1, lado2, lado3) do 23 | lado1 + lado2 + lado3 24 | end 25 | 26 | def area_triangulo(base, altura) do 27 | (base * altura) / 2 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /examples/lean/README.md: -------------------------------------------------------------------------------- 1 | # Learning material for Lean 2 | 3 | ## Books 4 | - [Functional Programming in Lean by David Thrane Christiansen](https://bit.ly/3tFnHoJ) 5 | 6 | ### Examples (some adapted by me) from "Functional Programming in Lean" 7 | 8 | - [Chapter 1](./examples_1.lean) 9 | 10 | ## Videos 11 | 12 | - [Machine-Checked Proofs and the Rise of Formal Methods in Mathematics | Theoretically Speaking](https://www.youtube.com/watch?v=ekYeqvMcaWQ) 13 | -------------------------------------------------------------------------------- /examples/lean/examples_1_5.lean: -------------------------------------------------------------------------------- 1 | -- Learn more about lean at: 2 | -- https://lean-lang.org/ 3 | -- Functional Programming in Lean, by David Thrane Christiansen https://lean-lang.org/functional_programming_in_lean/ 4 | -- You can use Lean in your browser at https://live.lean-lang.org/ 5 | 6 | -- Language version: 7 | -- Lean (version 4.0.0-nightly-2023-03-10, commit 0477276f66b0, Release) 8 | 9 | -- VS Code plugin version: 10 | -- lean4 v0.0.113 11 | -- Lean 4 language support for VS Code 12 | 13 | -- 1.5 Datatypes and Patterns 14 | -- https://lean-lang.org/functional_programming_in_lean/getting-to-know/datatypes-and-patterns.html 15 | 16 | -- "Lean constructors correspond to objects in JavaScript or TypeScript that include a tag that identifies the contents." 17 | 18 | -- Pattern Matching 19 | 20 | def isZero (n : Nat) : Bool := 21 | match n with 22 | | Nat.zero => true 23 | | Nat.succ k => false 24 | 25 | 26 | #eval isZero Nat.zero 27 | #eval isZero 5 28 | 29 | def pred (n : Nat) : Nat := 30 | match n with 31 | | Nat.zero => Nat.zero 32 | | Nat.succ k => k 33 | 34 | #eval pred 5 35 | 36 | 37 | structure Point3D where 38 | x : Float 39 | y : Float 40 | z : Float 41 | deriving Repr 42 | 43 | -- "In this case, it would have been much simpler to just use the z accessor, but structure patterns are occasionally the simplest way to write a function." 44 | def depth (p : Point3D) : Float := 45 | match p with 46 | | { x:= h, y := w, z := d } => d 47 | 48 | -- Recursive Functions 49 | -- https://lean-lang.org/functional_programming_in_lean/getting-to-know/datatypes-and-patterns.html#recursive-functio 50 | 51 | #eval "Definitions that refer to the name being defined are called recursive definitions." 52 | 53 | -- Recursive datatypes are nicely complemented by recursive functions. 54 | 55 | #eval "structural recursion" 56 | def even (n : Nat) : Bool := 57 | match n with 58 | | Nat.zero => true 59 | | Nat.succ k => not (even k) 60 | 61 | #eval "Unlike many languages, Lean ensures by default that every recursive function will eventually reach a base case. " 62 | 63 | -- error 64 | -- def evenLoops (n : Nat) : Bool := 65 | -- match n with 66 | -- | Nat.zero => true 67 | -- | Nat.succ k => not (evenLoops n) 68 | 69 | def plus (n : Nat) (k : Nat) : Nat := 70 | match k with 71 | | Nat.zero => n 72 | | Nat.succ k' 73 | 74 | => Nat.succ (plus n k') 75 | 76 | def times (n : Nat) (k : Nat) : Nat := 77 | match k with 78 | | Nat.zero => Nat.zero 79 | | Nat.succ k' => plus n (times n k') 80 | 81 | def minus (n : Nat) (k : Nat) : Nat := 82 | match k with 83 | | Nat.zero => n 84 | | Nat.succ k' => pred (minus n k') 85 | 86 | #eval plus 3 2 87 | 88 | #eval times 3 5 89 | 90 | #eval minus 10 5 91 | 92 | #eval "Not every function can be easily written using structural recursion. " 93 | 94 | 95 | -- def div (n : Nat) (k : Nat) : Nat := 96 | -- if n < k then 97 | -- 0 98 | -- else Nat.succ (div (n - k) k) 99 | 100 | -- "it is not structurally recursive, 101 | -- because it doesn't follow the pattern of 102 | -- finding a result for zero and transforming 103 | -- a result for a smaller Nat into a result for its successor." 104 | -- "In particular, the recursive invocation of the function 105 | -- is applied to the result of another function call, rather 106 | -- than to an input constructor's argument." 107 | 108 | def factorial (n : Nat) : Nat := 109 | match n with 110 | | Nat.zero => 1 111 | | Nat.succ k => n * (factorial k) 112 | 113 | #eval factorial 10 114 | 115 | -- 1.6 Polymorphism https://lean-lang.org/functional_programming_in_lean/getting-to-know/polymorphism.html 116 | -------------------------------------------------------------------------------- /examples/lean/functional_programming_lean_notes.md: -------------------------------------------------------------------------------- 1 | # 1.6 Polymorphism 2 | 3 | 4 | 5 | - Types in Lean can take arguments 6 | - List Nat 7 | -------------------------------------------------------------------------------- /examples/lean/independent_programs/Hello.lean: -------------------------------------------------------------------------------- 1 | def main : IO Unit := IO.println "Hello, world!" 2 | -------------------------------------------------------------------------------- /examples/lean/independent_programs/HelloName.lean: -------------------------------------------------------------------------------- 1 | def main : IO Unit := do 2 | let stdin ← IO.getStdin 3 | let stdout ← IO.getStdout 4 | 5 | stdout.putStrLn "How would you like to be addressed?" 6 | let input ← stdin.getLine 7 | let name := input.dropRightWhile Char.isWhitespace 8 | 9 | stdout.putStrLn s!"Hello, {name}!" 10 | -------------------------------------------------------------------------------- /examples/lean/scripts/Hello.lean: -------------------------------------------------------------------------------- 1 | def main : IO Unit := IO.println "Hello, world!" 2 | -------------------------------------------------------------------------------- /examples/macros.exs: -------------------------------------------------------------------------------- 1 | defmodule AMenosQue do 2 | def funcao_amenosque(clausula, do: expressao) do 3 | if(!clausula, do: expressao) 4 | end 5 | 6 | defmacro macro_amenosque(clausula, do: expressao) do 7 | quote do 8 | if(!unquote(clausula), do: unquote(expressao)) 9 | end 10 | end 11 | end 12 | 13 | -------------------------------------------------------------------------------- /examples/maffetone.exs: -------------------------------------------------------------------------------- 1 | defmodule Maffetone do 2 | def limite_superior(idade) do 3 | 180 - idade 4 | end 5 | 6 | def limite_superior(idade, true) do 7 | limite_superior(idade) - 10 8 | end 9 | 10 | def limite_superior(idade, false) do 11 | limite_superior(idade) 12 | end 13 | 14 | def limite_inferior(idade) do 15 | limite_superior(idade) - 10 16 | end 17 | 18 | def limite_inferior(idade, true) do 19 | limite_inferior(idade) - 10 20 | end 21 | 22 | def limite_inferior(idade, false) do 23 | limite_inferior(idade) 24 | end 25 | 26 | def intervalo(idade) do 27 | {limite_inferior(idade), limite_superior(idade)} 28 | end 29 | end 30 | 31 | IO.puts("Cálculo da Fórmula Maffetone") 32 | idade = 40 33 | IO.puts("Limite inferior para #{idade} anos: #{Maffetone.limite_inferior(idade)}") 34 | IO.puts("Limite superior para #{idade} anos: #{Maffetone.limite_superior(idade)}") 35 | IO.puts("Intervalo para #{idade} anos: ") 36 | IO.inspect(Maffetone.intervalo(idade)) 37 | 38 | condicao = true 39 | 40 | IO.puts( 41 | "Limite inferior para #{idade} anos: #{Maffetone.limite_inferior(idade, condicao)} para condicao a sendo #{ 42 | condicao 43 | }" 44 | ) 45 | 46 | IO.puts( 47 | "Limite superior para #{idade} anos: #{Maffetone.limite_superior(idade, condicao)} para condicao a sendo #{ 48 | condicao 49 | }" 50 | ) 51 | 52 | condicao = false 53 | 54 | IO.puts( 55 | "Limite inferior para #{idade} anos: #{Maffetone.limite_inferior(idade, condicao)} para condicao a sendo #{ 56 | condicao 57 | }" 58 | ) 59 | 60 | IO.puts( 61 | "Limite superior para #{idade} anos: #{Maffetone.limite_superior(idade, condicao)} para condicao a sendo #{ 62 | condicao 63 | }" 64 | ) 65 | -------------------------------------------------------------------------------- /examples/map_coloring/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /examples/map_coloring/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | map_coloring-*.tar 24 | 25 | -------------------------------------------------------------------------------- /examples/map_coloring/README.md: -------------------------------------------------------------------------------- 1 | # MapColoring 2 | 3 | **TODO: Add description** 4 | 5 | ## Installation 6 | 7 | If [available in Hex](https://hex.pm/docs/publish), the package can be installed 8 | by adding `map_coloring` to your list of dependencies in `mix.exs`: 9 | 10 | ```elixir 11 | def deps do 12 | [ 13 | {:map_coloring, "~> 0.1.0"} 14 | ] 15 | end 16 | ``` 17 | 18 | Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) 19 | and published on [HexDocs](https://hexdocs.pm). Once published, the docs can 20 | be found at [https://hexdocs.pm/map_coloring](https://hexdocs.pm/map_coloring). 21 | 22 | -------------------------------------------------------------------------------- /examples/map_coloring/lib/map_coloring.ex: -------------------------------------------------------------------------------- 1 | defmodule MapColoring do 2 | @moduledoc """ 3 | This module implements two functions (color_first/0 and color_all/0) to solve 4 | the map coloring problem as presented in 5 | page 11 of https://media.pragprog.com/titles/btlang/prolog.pdf 6 | (Seven Languages in Seven Weeks by Bruce Tate). 7 | 8 | As described there: 9 | "We want to color a map of the southeastern United States. 10 | We’ll cover the states shown in Figure 4, Map of some south-eastern states, 11 | on page 12. We do not want two states of the same color to touch." 12 | 13 | [First version](https://github.com/adolfont/introducao-a-programacao-funcional/blob/9f92ce102b85088a58e941b468892e0e929617a5/examples/map_coloring.exs) 14 | 15 | 16 | 17 | """ 18 | 19 | @colors [:red, :green, :blue] 20 | 21 | defp generate_all_colorings() do 22 | for( 23 | alabama <- @colors, 24 | missisipi <- @colors, 25 | georgia <- @colors, 26 | tennesse <- @colors, 27 | florida <- @colors, 28 | do: {alabama, missisipi, georgia, tennesse, florida} 29 | ) 30 | end 31 | 32 | defp _valid_coloring_accumulator(true, coloring, accumulator) do 33 | {:halt, accumulator ++ [coloring]} 34 | end 35 | 36 | defp _valid_coloring_accumulator(false, _, accumulator) do 37 | {:cont, accumulator} 38 | end 39 | 40 | defp valid_coloring_accumulator( 41 | {alabama, missisipi, georgia, tennesse, florida} = coloring, 42 | accumulator 43 | ) do 44 | _valid_coloring_accumulator( 45 | all_neighbourin_states_have_different_coloring?( 46 | alabama, 47 | missisipi, 48 | georgia, 49 | tennesse, 50 | florida 51 | ), 52 | coloring, 53 | accumulator 54 | ) 55 | end 56 | 57 | defp valid_coloring_filter(coloring) do 58 | {alabama, missisipi, georgia, tennesse, florida} = coloring 59 | 60 | all_neighbourin_states_have_different_coloring?( 61 | alabama, 62 | missisipi, 63 | georgia, 64 | tennesse, 65 | florida 66 | ) 67 | end 68 | 69 | defp all_neighbourin_states_have_different_coloring?( 70 | alabama, 71 | missisipi, 72 | georgia, 73 | tennesse, 74 | florida 75 | ) do 76 | missisipi != tennesse and 77 | missisipi != alabama and 78 | alabama != tennesse and 79 | alabama != georgia and 80 | alabama != florida and 81 | georgia != florida and 82 | georgia != tennesse 83 | end 84 | 85 | @doc """ 86 | Returns the first valid coloring for the map of the southeastern United States 87 | """ 88 | def color_first() do 89 | generate_all_colorings() 90 | |> find_first_valid_coloring() 91 | end 92 | 93 | defp find_first_valid_coloring(colorings) do 94 | Enum.reduce_while( 95 | colorings, 96 | [], 97 | &valid_coloring_accumulator/2 98 | ) 99 | |> Enum.at(0) 100 | end 101 | 102 | @doc """ 103 | Returns all valid colorings for the map of the southeastern United States 104 | """ 105 | def color_all() do 106 | generate_all_colorings() 107 | |> filter_valid_colorings() 108 | end 109 | 110 | defp filter_valid_colorings(colorings) do 111 | Enum.filter(colorings, &valid_coloring_filter/1) 112 | end 113 | 114 | @doc """ 115 | Shows a map coloring as a string. 116 | """ 117 | def show_coloring({alabama, missisipi, georgia, tennesse, florida}) do 118 | """ 119 | Alabama = #{alabama} 120 | Missisipi = #{missisipi} 121 | Georgia = #{georgia} 122 | Tennesse = #{tennesse} 123 | Florida = #{florida} 124 | """ 125 | end 126 | end 127 | -------------------------------------------------------------------------------- /examples/map_coloring/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule MapColoring.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :map_coloring, 7 | version: "0.1.0", 8 | elixir: "~> 1.9", 9 | start_permanent: Mix.env() == :prod, 10 | deps: deps() 11 | ] 12 | end 13 | 14 | # Run "mix help compile.app" to learn about applications. 15 | def application do 16 | [ 17 | extra_applications: [:logger] 18 | ] 19 | end 20 | 21 | # Run "mix help deps" to learn about dependencies. 22 | defp deps do 23 | [ 24 | # {:dep_from_hexpm, "~> 0.3.0"}, 25 | # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} 26 | ] 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /examples/map_coloring/test/map_coloring_test.exs: -------------------------------------------------------------------------------- 1 | defmodule MapColoringTest do 2 | use ExUnit.Case 3 | doctest MapColoring 4 | 5 | test "First Valid Coloring" do 6 | assert MapColoring.color_first() == {:red, :green, :green, :blue, :blue} 7 | end 8 | 9 | test "All Valid Colorings" do 10 | assert MapColoring.color_all() == [ 11 | {:red, :green, :green, :blue, :blue}, 12 | {:red, :blue, :blue, :green, :green}, 13 | {:green, :red, :red, :blue, :blue}, 14 | {:green, :blue, :blue, :red, :red}, 15 | {:blue, :red, :red, :green, :green}, 16 | {:blue, :green, :green, :red, :red} 17 | ] 18 | end 19 | 20 | test "Show Coloring" do 21 | assert MapColoring.show_coloring(MapColoring.color_first()) == 22 | """ 23 | Alabama = red 24 | Missisipi = green 25 | Georgia = green 26 | Tennesse = blue 27 | Florida = blue 28 | """ 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /examples/map_coloring/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /examples/send_receive.exs: -------------------------------------------------------------------------------- 1 | # Copie e cole o texto abaixo no iex - vai mostrar duas mensagens 2 | send self(), {:hello, "world"} 3 | send self(), {:world, "world"} 4 | 5 | 6 | receive do 7 | {:hello, msg} -> msg 8 | {:world, _msg} -> "won't match" 9 | end 10 | 11 | receive do 12 | {:hello, msg} -> msg 13 | {:world, _msg} -> "won't match" 14 | end 15 | 16 | # Faça novamente - Vai travar o terminal 17 | send self(), {:ola, "world"} 18 | receive do 19 | {:hello, msg} -> msg 20 | {:world, _msg} -> "won't match" 21 | end 22 | -------------------------------------------------------------------------------- /examples/truth_table.exs: -------------------------------------------------------------------------------- 1 | defmodule TruthTable do 2 | @values [0, 1] 3 | 4 | def values(n) when n > 1 do 5 | for z <- @values, l <- values(n - 1), do: [z | l] 6 | end 7 | 8 | def values(1) do 9 | for x <- @values, do: [x] 10 | end 11 | end 12 | 13 | for x <- 1..4 do 14 | IO.puts("Number of atoms: #{x}") 15 | IO.inspect(TruthTable.values(x)) 16 | IO.puts("") 17 | end 18 | -------------------------------------------------------------------------------- /examples/truth_table_streams.exs: -------------------------------------------------------------------------------- 1 | defmodule TruthTable do 2 | @values [0, 1] 3 | 4 | def values(n) when n > 1 do 5 | # for z <- @values, l <- values(n - 1), do: [z | l] 6 | for z <- @values, l <- values(n - 1), do: Stream.concat([z], l) 7 | end 8 | 9 | def values(1) do 10 | # for x <- @values, do: [x] 11 | for x <- @values, do: Stream.concat([], [x]) 12 | end 13 | 14 | def print_max_lines(number_atoms, max_lines) do 15 | tt = TruthTable.values(number_atoms) 16 | 17 | for i <- 0..max_lines, i < :math.pow(2, number_atoms) do 18 | tt 19 | |> Enum.at(i) 20 | |> Enum.to_list() 21 | |> IO.inspect() 22 | end 23 | end 24 | 25 | def show() do 26 | max_atoms_answer = IO.gets("Type max number of atoms: ") 27 | 28 | max_atoms = String.to_integer(String.trim(max_atoms_answer)) 29 | 30 | lines_answer = IO.gets("Type max number of lines: ") 31 | 32 | lines = String.to_integer(String.trim(lines_answer)) 33 | 34 | for x <- 1..max_atoms do 35 | IO.puts("Number of atoms: #{x}") 36 | 37 | IO.puts("The first #{lines} lines of the truth table for #{x} atoms") 38 | 39 | TruthTable.print_max_lines(x, lines) 40 | 41 | IO.puts("") 42 | end 43 | end 44 | end 45 | 46 | TruthTable.show() 47 | -------------------------------------------------------------------------------- /exercises/maffetone.md: -------------------------------------------------------------------------------- 1 | # Maffetone 2 | 3 | Inspiração: https://philmaffetone.com/180-formula/ 4 | 5 | 1. Crie uma função chamada limite_superior/1 que recebe como entrada uma idade e retorna (180 - idade) 6 | 2. Crie uma função chamada limite_inferior/1 que recebe como entrada uma idade e retorna (limite_superior(idade)- 10) 7 | 3. Crie uma função chamada intervalo_maffetone/1 que recebe como entrada uma idade e retorna o par (limite_inferior(idade), limite_superior(idade)). 8 | -------------------------------------------------------------------------------- /exercises/maps_keywordlists_sets.md: -------------------------------------------------------------------------------- 1 | # Exercises on Elixir Maps, Keyword Lists, Sets, and Structs 2 | 3 | https://medium.com/@adolfont/exercises-on-elixir-maps-keyword-lists-sets-and-structs-4cba2d00e9b3 4 | -------------------------------------------------------------------------------- /exercises/random.md: -------------------------------------------------------------------------------- 1 | # Funcionamento do motor de um carro 2 | 3 | Vamos pensar num exercício de programação aqui pra trabalhar a cabeça de pessoas iniciantes (ou não) 4 | 5 | É um exercício que passei pra um aluno 6 | 7 | #dev #pratica #exercise 8 | 9 | É o seguinte: pensa no funcionamento do motor de um carro (ele gosta de carro), como você faria pra simular esse comportamento utilizando programação? 10 | 11 | O exercício é aberto. A pessoa que vai resolver pode simplificar ou complicar a resposta o quanto quiser. O importante é utilizar seus conhecimentos em programação pra simular o comportamento do motor ♥️ 12 | 13 | Se você quiser fazer, codifica isso e sobe num GitHub, Codepen ou algum lugar pra gente ver e manda aqui na thread pra fazermos Code Review 14 | (https://twitter.com/w_oliveiras/status/1199638233593864192?s=03) -------------------------------------------------------------------------------- /historico/oferecimentos.md: -------------------------------------------------------------------------------- 1 | # Disciplinas na Pós 2 | 3 | - 2018 4 | - 2019 5 | 6 | # Minicursos 7 | 8 | - 2019 9 | 10 | # Palestras 11 | 12 | - 2017 13 | 14 | # Coding Dojos 15 | -------------------------------------------------------------------------------- /historico/trabalhos.md: -------------------------------------------------------------------------------- 1 | # 2019 2 | 3 | - Doglas André Finco 4 | - LISP e Clojure https://speakerdeck.com/doglas/lisp-clojure 5 | - Entrevistas com alunos https://anchor.fm/a-g-s-s-n/episodes/Introduo--Programao-Funcional-2019-e97nds 6 | 7 | # 2018 8 | 9 | - Elixir Forum Survey https://elixirforum.com/t/survey-about-the-use-of-the-elixir-forum/18319 10 | - Results http://www.dainf.ct.utfpr.edu.br/~adolfo/dokuwiki/doku.php?id=2018:elixir_forum_survey_2018_results 11 | -------------------------------------------------------------------------------- /languages/ocaml.md: -------------------------------------------------------------------------------- 1 | # OCaml 2 | 3 | Speaker: Adolfo Neto 4 | 5 | Site: https://ocaml.org/ 6 | 7 | Wikipedia entry: https://en.wikipedia.org/wiki/OCaml 8 | 9 | OCaml creators: Xavier Leroy, Jérôme Vouillon, Damien Doligez, Didier Rémy, Ascánder Suárez 10 | 11 | Creation year: 1996 12 | 13 | Formerly Objective Caml. 14 | 15 | "The main implementation of the Caml programming language." (Wikipedia) 16 | 17 | "The acronym CAML originally stood for Categorical Abstract Machine Language, but OCaml omits this abstract machine." (Wikipedia) 18 | 19 | 20 | How to install: https://ocaml.org/docs/install.html 21 | 22 | REPL: `ocaml` 23 | 24 | # Characteristics 25 | 26 | 27 | 28 | 29 | # References 30 | 31 | ## In Portuguese 32 | 33 | - FORMIGA, Andrei de Araújo. **OCaml: Programação funcional na prática**. Casa do Código, 2015. 34 | - Link: https://twitter.com/andreiformiga/status/553171431190978560 35 | - Code: https://github.com/tautologico/opfp 36 | - Amazon link: https://www.amazon.com.br/dp/B019P9OPOI/ 37 | -------------------------------------------------------------------------------- /languages/pt/ocaml.md: -------------------------------------------------------------------------------- 1 | # OCaml 2 | 3 | Palestrante: Adolfo Neto 4 | 5 | Site: https://ocaml.org/ 6 | 7 | Entrada na Wikipédia: https://pt.wikipedia.org/wiki/OCaml 8 | 9 | Criadrores de OCaml: Xavier Leroy, Jérôme Vouillon, Damien Doligez, Didier Rémy, Ascánder Suárez 10 | 11 | Ano de criação: 1996 12 | 13 | Nome anterior: Objective Caml. 14 | 15 | ## Wikipédia 16 | 17 | Uma linguagem de programação funcional da família ML 18 | 19 | Desenvolvida pelo INRIA em 1996. 20 | 21 | Linguagem Caml com a adição de suporte de técnicas de orientação a objetos e algumas alterações e extensões de sintaxe. 22 | 23 | 24 | A sigla CAML originalmente significava "Categorical Abstract Machine Language", mas OCaml omite esta máquina abstrata. 25 | 26 | Como instalar: https://ocaml.org/docs/install.html 27 | 28 | REPL: `ocaml` 29 | 30 | ## Livro Andrei Formiga 31 | 32 | O compilador de [Hack](https://hacklang.org/) é escrito em OCaml. 33 | 34 | F# foi criada para ser uma versão de OCaml para .Net. 35 | 36 | OCaml não é apenas fincional. 37 | 38 | Estaticamente tipada. 39 | 40 | Inferência de tipos que pode fazer você pensar que é dinamicamente tipada. 41 | 42 | Orientada a expressões. 43 | 44 | Compilação nativa (`ocamlopt`) ou para *bytecode* (`ocamlc`). 45 | 46 | Uso interativo ou em *batch*. 47 | 48 | 49 | ## Breve histórico da linguagem: criadores, razão de ter sido criada, ano em que foi criada, popularidade hoje em dia, principais aplicações 50 | 51 | ## Tipos de dados 52 | 53 | ## Como definir funções 54 | 55 | ```ocaml 56 | let mult x y = x * y;; 57 | ``` 58 | 59 | ```ocaml 60 | mult 2 4 61 | ``` 62 | 63 | ## Tipagem estática ou dinâmica? 64 | 65 | ## Currying? 66 | 67 | Currificação 68 | https://github.com/tautologico/opfp/blob/master/capitulos/c05-progfun.ml 69 | 70 | ## Roda em máquina virtual (se sim, qual?), é compilada, é interpretada? 71 | 72 | ## Características peculiares da linguagem 73 | 74 | OO + Funcional! 75 | 76 | ## Exemplos 77 | 78 | https://github.com/tautologico/opfp/tree/master/capitulos 79 | 80 | ## Tipos básicos na REPL 81 | 82 | https://github.com/tautologico/opfp/blob/master/capitulos/c02-basico.ml 83 | 84 | 85 | ### Fatorial recursivo 86 | 87 | https://pt.wikipedia.org/wiki/OCaml#Factorial_recursivo 88 | 89 | 90 | 91 | 92 | 93 | # Referências 94 | 95 | - FORMIGA, Andrei de Araújo. **OCaml: Programação funcional na prática**. Casa do Código, 2015. 96 | - Link: https://twitter.com/andreiformiga/status/553171431190978560 97 | - Código: https://github.com/tautologico/opfp 98 | - Na Amazon: https://www.amazon.com.br/dp/B019P9OPOI/ 99 | -------------------------------------------------------------------------------- /links.md: -------------------------------------------------------------------------------- 1 | # Links 2 | 3 | [History of Lisp, John McCarthy](http://jmc.stanford.edu/articles/lisp.html) 4 | 5 | [Who Cares About Functional Programming?, Thomas Bandt](https://thomasbandt.com/who-cares-about-functional-programming) 6 | 7 | [Suitability of functional programming for the development of mobile applications: A comparison of F# and C# involving Xamarin](https://thomasbandt.com/upload/thesis.pdf) 8 | 9 | [Which companies are using Elixir, and why? #MyTopdogStatus](https://www.erlang-solutions.com/blog/which-companies-are-using-elixir-and-why-mytopdogstatus.html?utm_source=facebook&utm_medium=social&utm_campaign=19Q3.Mark.Underdog.MRBlog) 10 | 11 | [Functional Programming Essentials with Elixir - Slides Ulisses](https://speakerdeck.com/ulissesalmeida/functional-programming-essentials-with-elixir) 12 | 13 | [Think in Erlang! #Code BEAM STO 2019](https://codesync.global/media/think-in-erlang-viktoria-fordos-code-beam-sto) 14 | 15 | [Why am I interested in Elixir? (underjord.io)](https://news.ycombinator.com/item?id=20357055) 16 | 17 | [Thinking Elixir](https://thinkingelixir.com/) 18 | 19 | [Podcast ElixirMix 57 - The Elixir Community with Adolfo Neto](https://www.reddit.com/r/elixir/comments/c5b475/podcast_elixirmix_57_the_elixir_community_with/) 20 | 21 | [The Erlang Rationale, Robert Virding](https://drive.google.com/file/d/1zKsOgwZJ_YZ1bY3b3gNRjAxpn6VneR8b/view) 22 | 23 | [Programação Concorrente, Luciano Ramalho](https://www.youtube.com/watch?v=FYKNHk3Ze8A) 24 | 25 | [Curso de Python](https://www.youtube.com/playlist?list=PLlrxD0HtieHhS8VzuMCfQD4uJ9yne1mE6) 26 | 27 | [An Introduction to the basic principles of Functional Programming](https://www.freecodecamp.org/news/an-introduction-to-the-basic-principles-of-functional-programming-a2c2a15c84/) 28 | 29 | [Spreadsheets: Functional Programming for the Masses](https://www.slideshare.net/kfrdbs/peyton-jones) 30 | 31 | 32 | ## In Portuguese 33 | 34 | - [Curso de Clojure e Programação Funcional](https://cursos.segunda.tech) 35 | -------------------------------------------------------------------------------- /minicursos/semana_formacao_docente_2020.md: -------------------------------------------------------------------------------- 1 | # Proposta 2 | 3 | - Evento: X JORNADA DE FORMAÇÃO DOCENTE UTFPR/CT - APERFEIÇOAMENTO DA DOCÊNCIA NO ENSINO SUPERIOR 4 | - Duração: 4 horas 5 | 6 | # Ementa 7 | 8 | Elixir é uma linguagem de programação funcional concorrente criada pelo brasileiro José Valim. Atualmente está entre as linguagens mais utilizadas no mundo. Ao final deste minicurso, você deverá ser capaz de: 9 | - Responder as seguintes questões: 10 | - O que é Programação Funcional? 11 | - O que é a linguagem Elixir? 12 | - Conceituar e utilizar Casamento de Padrões em Elixir. 13 | - Criar de funções e módulos em Elixir. 14 | - Resolver exercícios simples de programação com Elixir. 15 | 16 | # Materiais 17 | 18 | O material está online em https://elixirschool.com/pt/ e em https://github.com/adolfont/introducao-a-programacao-funcional 19 | -------------------------------------------------------------------------------- /offerings/2019/aulas_2019.md: -------------------------------------------------------------------------------- 1 | # Introdução à Programação Funcional 2 | 3 | Professor: [Adolfo Neto (DAINF-UTFPR)](http://www2.dainf.ct.utfpr.edu.br/Members/adolfo) 4 | 5 | [Ementa](http://ppgca.dainf.ct.utfpr.edu.br/doku.php?id=caes005)/[Syllabus](Introduction-to-Functional-Programming.md) 6 | 7 | ## Aluno(a)s Matriculado(a)s 8 | 9 | - Doglas Andre Finco 10 | - Jean Carlos Rodrigues 11 | - Laura Keity Shibukawa 12 | - Mattheus Rodrigo Marzola Leite 13 | - Yanaiara Graziele De Oliveira 14 | 15 | 16 | 17 | ## Datas das Aulas 18 | 19 | [Calendário UTFPR 2019](http://portal.utfpr.edu.br/alunos/calendario/ct/calendario-utfpr-ct-2019) 20 | 21 | - 24/09 22 | - 01/10 23 | - Não haverá em 08/10 24 | - 15/10 25 | - 22/10 26 | - 29/10 27 | - 05/11 28 | - 12/11 29 | - 19/11 30 | - 26/11 31 | - 03/12 32 | - 10/12 33 | 34 | ## Avaliação 35 | 36 | - Apresentações de linguagens 37 | - Vídeos 38 | - Pesquisa Elixir Forum, Slack, Telegram 39 | 40 | ## Assuntos 41 | 42 | - Introdução rápida sobre a necessidade/utilidade de PF 43 | 44 | ### Elixir 45 | 46 | - IEx 47 | - Alguns tipos básicos 48 | - Casamento de padrões 49 | - Chamada de funções Módulo.nome 50 | - Alguns módulos que já vêm com Elixir: 51 | - Kernel https://hexdocs.pm/elixir/Kernel.html 52 | - No iex, Kernel. e TAB 53 | - funções do Módulo Kernel não precisam do nome do Módulo antes 54 | - h Kernel.trunc round abs is_integer 55 | - h Kernel 56 | - https://hexdocs.pm/elixir/Atom.html#summary 57 | - Atom.to_string 58 | - Também não precisa do nome do Módulo 59 | - https://hexdocs.pm/elixir/String.html#summary 60 | - String.replace("a,b,c", ",", "-") 61 | - precisa do nome do Módulo 62 | 63 | ### Depois 64 | 65 | - mais detalhes sobre as aplicações de Elixir e a importãncia da Erlang VM 66 | - como contribuir? 67 | - pacotes de brasileiros 68 | - https://github.com/elixir-validation/validation 69 | -------------------------------------------------------------------------------- /offerings/2019/class_of_2019.md: -------------------------------------------------------------------------------- 1 | # Introduction to Functional Programming 2 | 3 | [Syllabus](Introduction-to-Functional-Programming.md) 4 | 5 | This is a course I am offering this semester (2019/2) at [UTFPR Curitiba](http://portal.utfpr.edu.br/campus/curitiba). 6 | 7 | ## Professor 8 | 9 | [Adolfo Neto (DAINF - UTFPR Curitiba)](https://twitter.com/adolfont) 10 | 11 | ## Students 12 | 13 | - Doglas Andre Finco 14 | - Jean Carlos Rodrigues 15 | - Laura Keity Shibukawa 16 | - Mattheus Rodrigo Marzola Leite 17 | - Yanaiara Graziele De Oliveira 18 | 19 | 20 | ## Calendar 21 | 22 | - 24/09 - IEx, Variables, Values, Types 23 | - 01/10 - Pattern Matching, Named Functions 24 | - 08/10 - No class 25 | - 15/10 - Ada Lovelace Day 26 | - 22/10 27 | - 29/10 28 | - 05/11 29 | - 12/11 30 | - 19/11 31 | - 26/11 32 | - 03/12 33 | - 10/12 34 | -------------------------------------------------------------------------------- /offerings/2020/classes/class01.md: -------------------------------------------------------------------------------- 1 | 2 | # Introduction to Functional Programming 3 | - Class Notes October 1st, 2020 4 | - Adolfo Neto 5 | - Video: https://youtu.be/X6XcAARZgn4 6 | 7 | I am not the "owner of truth", as we say in Portuguese. You can know more than me about many things. I like that! 8 | 9 | I have my passions and my pet peeves. 10 | 11 | You can disagree with me, it is OK! 12 | 13 | --- 14 | 15 | 16 | # Declarative languages 17 | 18 | A little bit of history 19 | 20 | ## Functional 21 | 22 | Relatively random choices... 23 | 24 | Functional programming https://en.wikipedia.org/wiki/Functional_programming 25 | 26 | 27 | - 1958 LISP https://en.wikipedia.org/wiki/Lisp_(programming_language) 28 | - 1973 ML https://en.wikipedia.org/wiki/ML_(programming_language) 29 | - 1975 Scheme https://en.wikipedia.org/wiki/Scheme_(programming_language) 30 | - 1983 Erlang https://en.wikipedia.org/wiki/Erlang_(programming_language) 31 | - 1985 Miranda https://en.wikipedia.org/wiki/Miranda_(programming_language) 32 | - 1990 Haskell https://en.wikipedia.org/wiki/Haskell_(programming_language) 33 | - 1995 Racket https://en.wikipedia.org/wiki/Racket_(programming_language) 34 | - 2007 Clojure https://en.wikipedia.org/wiki/Clojure 35 | - 2007 Idris https://en.wikipedia.org/wiki/Idris_(programming_language) 36 | - 2011 Elixir https://en.wikipedia.org/wiki/Elixir_(programming_language) 37 | 38 | ### Not well-known enough yet 39 | 40 | - 2012 ? Elm https://en.wikipedia.org/wiki/Elm_(programming_language) 41 | - 2013 ? PureScript https://en.wikipedia.org/wiki/PureScript 42 | 43 | [Are these the main functional programming languages?](https://twitter.com/adolfont/status/1311426261684834306?s=20) 44 | 45 | ## Logic 46 | 47 | - 1972 Prolog https://en.wikipedia.org/wiki/Prolog 48 | 49 | ## Dialects 50 | 51 | - Common LISP 52 | - 1983 Standard ML https://en.wikipedia.org/wiki/Standard_ML 53 | 54 | 55 | ## Multi-paradigm 56 | 57 | - 1996 OCaml https://en.wikipedia.org/wiki/OCaml 58 | - 2004 Scala https://en.wikipedia.org/wiki/Scala_(programming_language) 59 | - 2005 ? F# https://en.wikipedia.org/wiki/F_Sharp_(programming_language) 60 | - 2014 Swift https://en.wikipedia.org/wiki/Swift_(programming_language) 61 | - 2010 Rust https://en.wikipedia.org/wiki/Rust_(programming_language) 62 | 63 | ## Languages that implemented features from functional programming 64 | 65 | - "C++11, Kotlin, Perl, PHP, Python, and Scala." https://en.wikipedia.org/wiki/Functional_programming 66 | 67 | ## Links 68 | 69 | https://github.com/adolfont/caes005-introduction-to-functional-programming/blob/master/links.md 70 | 71 | https://github.com/adolfont/caes005-introduction-to-functional-programming/blob/master/README.md 72 | 73 | https://github.com/adolfont/caes005-introduction-to-functional-programming/blob/master/Introduction-to-Functional-Programming.md 74 | 75 | # Functions as First Class Citizens 76 | 77 | What does it mean? 78 | 79 | But first, let us make it clear what are functions. 80 | 81 | --- 82 | 83 | # Functions 84 | 85 | - In mathematics 86 | - In programming 87 | 88 | # Sets 89 | 90 | # Elements 91 | 92 | --- 93 | 94 | # Research 95 | 96 | https://www.cambridge.org/core/journals/journal-of-functional-programming 97 | 98 | # Random 99 | 100 | https://ramdajs.com/ 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /offerings/2020/students.md: -------------------------------------------------------------------------------- 1 | # Students 2 | 3 | - Andre Luis Santos Pereira - MSc. (special) student at UTFPR 4 | - Evandro Sestrem - MSc. student at UTFPR 5 | - [Felipe Rodolfo do Nascimento](https://github.com/felipedotcom) - Industrial Mechanical Engineer - FATEC SJC-SP 6 | - Gabriel de Andrade Torelli - Ph.D. student at UTFPR - CPGEI 7 | - [Gustavo Brunholi Chierici](https://github.com/GustavoChierici/) - undergraduate student at UTFPR - Computer Engineering 8 | - Matheus Vinicius Barcaro Turatti - undergraduate student at UTFPR - Computer Engineering 9 | - [Gabriel Henrique de Oliveira](https://github.com/oliveigah) - Bachelor of Information Systems - EACH USP 10 | - [Lucas de Alencar Barbosa](https://github.com/alencarlucas) - Bachelor of Science and Technology at ICT-UNIFESP 11 | 12 | 13 | # Listeners 14 | 15 | - Cristine Guadalupe 16 | 17 | -------------------------------------------------------------------------------- /offerings/2020/videos.md: -------------------------------------------------------------------------------- 1 | 2 | # Patten Matching 3 | 4 | * Pattern Matching in Elixir https://youtu.be/o54RI03n-tA - very basic 5 | * Pattern Matching in Elixir https://youtu.be/48X5aGwBnzQ - more advanced 6 | * The Beauty of Pattern Matching in Elixir https://youtu.be/jbuSdZH-14w - more advanced 7 | * Understanding Pattern Matching | Zero to Hero in Elixir #6 https://youtu.be/79WCxJ9TM1o - more advanced 8 | * Pattern Matching in Elixir https://www.youtube.com/watch?v=nEUHb7RJspQ - much more advanced 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /offerings/2021/2021.md: -------------------------------------------------------------------------------- 1 | # Important Dates 2 | 3 | [Academic calendar](http://www.utfpr.edu.br/documentos/pesquisa-e-pos-graduacao/proppg/stricto-sensu/documentos-stricto-sensu/calendarios-2021/CalendrioPsGraduao2021.pdf) 4 | 5 | - Start: 17/June/2021 6 | - End: 02/September/2021 7 | -------------------------------------------------------------------------------- /offerings/2022/01_01_presentation.md: -------------------------------------------------------------------------------- 1 | # Who is each one of us? 2 | 3 | - Name 4 | - Profession 5 | - City 6 | 7 | # Ice-breaker question 8 | -------------------------------------------------------------------------------- /offerings/2022/01_introduction.md: -------------------------------------------------------------------------------- 1 | # Basic concepts for functional programming 2 | 3 | Video https://youtu.be/wTPfqpbFPQk 4 | 5 | ## Values 6 | 7 | - Numbers 8 | - Integers 9 | - Reals 10 | - Words 11 | - Phrases 12 | - Logical values (booleans) 13 | 14 | ## Sets 15 | 16 | - Empty set 17 | - Infinite sets 18 | - Finite sets 19 | - The ones we are interested in have one or more elements 20 | - \{1958, 1962, 1970, 1994, 2002\} 21 | 22 | ### Basic properties of sets 23 | 24 | - The order is not important. 25 | - There is no repetition 26 | 27 | ### "Famous" sets 28 | - Natural Numbers https://en.wikipedia.org/wiki/Natural_number 29 | - Integers https://en.wikipedia.org/wiki/Integer 30 | - Reals https://en.wikipedia.org/wiki/Real_number 31 | 32 | ## Relations 33 | 34 | - A relation is also a set. 35 | - Pair, Tuple 36 | 37 | - [Relation (mathematics)](https://en.wikipedia.org/wiki/Relation_(mathematics)) 38 | 39 | ## Mathematical Functions 40 | 41 | - [Several ways to see a function (Carnielli- Epstein)](https://drive.google.com/file/d/1hV1CMonW-o8p5vayXo_MRVTTI3LoHn8-/view?usp=sharing) 42 | - Black-boxes 43 | - Domains and ranges 44 | - As rules 45 | - As collections of ordered pairs 46 | 47 | 48 | When two functions are the same function? 49 | 50 | ### Some functions 51 | 52 | - Identity 53 | - Increment 54 | - Decrement 55 | 56 | 57 | ## Functions in Programming 58 | 59 | - Pure function = mathematical function 60 | - Impure function = relation (i.e., not a function) 61 | 62 | - State!!! 63 | 64 | ### 65 | 66 | - Arity 67 | - Types 68 | 69 | ### 70 | 71 | - Anonymous functions 72 | - Function composition 73 | 74 | 75 | 76 | 77 | ## Other materials 78 | 79 | - "A mathematical function is a rule that gives value of a dependent variable that corresponds to specified values of one or more independent variables. A function can be represented in several ways, such as by a table, a formula, or a graph. Except for isolated points, the mathematical functions found in physical chemistry are single-valued. " Chapter 2 - Mathematical Functions. Robert G.Mortimer https://www.sciencedirect.com/science/article/pii/B9780124158092000021 80 | 81 | - What is a function? | Functions and their graphs | Algebra II | Khan Academy https://youtu.be/kvGsIo1TmsM 82 | 83 | - What is a Function? | Don't Memorise https://youtu.be/g1FqhHpnBdw 84 | 85 | 86 | # Practice 87 | 88 | Using [Elixir](https://elixir-lang.org/)'s [Livebook](https://livebook.dev/) 89 | -------------------------------------------------------------------------------- /offerings/2022/projects/README.md: -------------------------------------------------------------------------------- 1 | Nothing right now 2 | -------------------------------------------------------------------------------- /offerings/2022/projects/guess/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /offerings/2022/projects/guess/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | guess-*.tar 24 | 25 | # Temporary files, for example, from tests. 26 | /tmp/ 27 | -------------------------------------------------------------------------------- /offerings/2022/projects/guess/README.md: -------------------------------------------------------------------------------- 1 | # Guess 2 | 3 | **TODO: Add description** 4 | 5 | ## Installation 6 | 7 | If [available in Hex](https://hex.pm/docs/publish), the package can be installed 8 | by adding `guess` to your list of dependencies in `mix.exs`: 9 | 10 | ```elixir 11 | def deps do 12 | [ 13 | {:guess, "~> 0.1.0"} 14 | ] 15 | end 16 | ``` 17 | 18 | Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) 19 | and published on [HexDocs](https://hexdocs.pm). Once published, the docs can 20 | be found at . 21 | 22 | -------------------------------------------------------------------------------- /offerings/2022/projects/guess/lib/guess.ex: -------------------------------------------------------------------------------- 1 | defmodule Guess do 2 | @moduledoc """ 3 | Documentation for `Guess`. 4 | """ 5 | 6 | @doc """ 7 | Hello world. 8 | 9 | ## Examples 10 | 11 | iex> Guess.hello() 12 | :world 13 | 14 | """ 15 | def hello do 16 | :world 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /offerings/2022/projects/guess/lib/guess/cli/main.ex: -------------------------------------------------------------------------------- 1 | defmodule Guess.CLI.Main do 2 | alias Mix.Shell.IO, as: Shell 3 | 4 | @max 10 5 | 6 | def start_game do 7 | Shell.cmd("clear") 8 | welcome_message() 9 | play_game(Enum.random(1..@max)) 10 | end 11 | 12 | def play_game(sorted_number) do 13 | choice = get_number() 14 | 15 | cond do 16 | choice == -1 -> 17 | Shell.info("Bye bye! See you next time!") 18 | 19 | choice == sorted_number -> 20 | Shell.info("You won!") 21 | Shell.info("") 22 | play_game(Enum.random(1..@max)) 23 | 24 | choice == :error -> 25 | Shell.info("You must type an integer number!") 26 | Shell.info("") 27 | play_game(Enum.random(1..@max)) 28 | 29 | true -> 30 | try_again(sorted_number) 31 | end 32 | end 33 | 34 | defp welcome_message do 35 | Shell.info("== Guess Game ==") 36 | Shell.info("Guess the right number.") 37 | end 38 | 39 | defp get_number() do 40 | try do 41 | Shell.prompt("Type an integer number between 1 and 100 (-1 to quit): ") 42 | |> String.trim() 43 | |> String.to_integer() 44 | rescue 45 | ArgumentError -> :error 46 | end 47 | end 48 | 49 | defp try_again(sorted_number) do 50 | Shell.info("You lost! Try again!") 51 | Shell.info("") 52 | play_game(sorted_number) 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /offerings/2022/projects/guess/lib/mix/tasks/start.ex: -------------------------------------------------------------------------------- 1 | defmodule Mix.Tasks.Start do 2 | use Mix.Task 3 | 4 | def run(_), do: Guess.CLI.Main.start_game() 5 | end 6 | -------------------------------------------------------------------------------- /offerings/2022/projects/guess/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Guess.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :guess, 7 | version: "0.1.0", 8 | elixir: "~> 1.14", 9 | start_permanent: Mix.env() == :prod, 10 | deps: deps() 11 | ] 12 | end 13 | 14 | # Run "mix help compile.app" to learn about applications. 15 | def application do 16 | [ 17 | extra_applications: [:logger] 18 | ] 19 | end 20 | 21 | # Run "mix help deps" to learn about dependencies. 22 | defp deps do 23 | [ 24 | # {:dep_from_hexpm, "~> 0.3.0"}, 25 | # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} 26 | ] 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /offerings/2022/projects/guess/test/guess_test.exs: -------------------------------------------------------------------------------- 1 | defmodule GuessTest do 2 | use ExUnit.Case 3 | doctest Guess 4 | 5 | test "greets the world" do 6 | assert Guess.hello() == :world 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /offerings/2022/projects/guess/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /offerings/2022/projects/tic_tac_toe/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /offerings/2022/projects/tic_tac_toe/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | tic_tac_toe-*.tar 24 | 25 | # Temporary files, for example, from tests. 26 | /tmp/ 27 | -------------------------------------------------------------------------------- /offerings/2022/projects/tic_tac_toe/README.md: -------------------------------------------------------------------------------- 1 | # TicTacToe 2 | 3 | TicTacToe is a text-based implementation of the [Tic-tac-toe game](https://en.wikipedia.org/wiki/Tic-tac-toe) where the user plays against the computer that chooses its move using a pseudorandom number generator. 4 | 5 | To run it, clone this repository and do the following: 6 | 7 | 8 | ``` 9 | $ git clone https://github.com/adolfont/caes005-introduction-to-functional-programming.git 10 | 11 | Cloning into 'caes005-introduction-to-functional-programming'... 12 | remote: Enumerating objects: 1150, done. 13 | remote: Counting objects: 100% (515/515), done. 14 | remote: Compressing objects: 100% (311/311), done. 15 | remote: Total 1150 (delta 253), reused 366 (delta 155), pack-reused 635 16 | Receiving objects: 100% (1150/1150), 313.28 KiB | 3.52 MiB/s, done. 17 | Resolving deltas: 100% (590/590), done. 18 | 19 | $ cd caes005-introduction-to-functional-programming/2022/projects/tic_tac_toe/ 20 | 21 | $ mix deps.get 22 | 23 | Resolving Hex dependencies... 24 | Resolution completed in 0.023s 25 | Unchanged: 26 | earmark_parser 1.4.29 27 | ex_doc 0.29.1 28 | makeup 1.1.0 29 | makeup_elixir 0.16.0 30 | makeup_erlang 0.1.1 31 | nimble_parsec 1.2.3 32 | * Getting ex_doc (Hex package) 33 | * Getting earmark_parser (Hex package) 34 | * Getting makeup_elixir (Hex package) 35 | * Getting makeup_erlang (Hex package) 36 | * Getting makeup (Hex package) 37 | * Getting nimble_parsec (Hex package) 38 | 39 | $ mix start 40 | 41 | ==> earmark_parser 42 | Compiling 1 file (.yrl) 43 | Compiling 2 files (.xrl) 44 | Compiling 3 files (.erl) 45 | Compiling 46 files (.ex) 46 | Generated earmark_parser app 47 | ==> nimble_parsec 48 | Compiling 4 files (.ex) 49 | Generated nimble_parsec app 50 | ==> makeup 51 | Compiling 44 files (.ex) 52 | Generated makeup app 53 | ==> makeup_elixir 54 | Compiling 6 files (.ex) 55 | Generated makeup_elixir app 56 | ==> makeup_erlang 57 | Compiling 3 files (.ex) 58 | warning: Application.get_env/3 is discouraged in the module body, use Application.compile_env/3 instead 59 | lib/makeup/lexers/erlang_lexer.ex:250: Makeup.Lexers.ErlangLexer 60 | 61 | Generated makeup_erlang app 62 | ==> ex_doc 63 | Compiling 25 files (.ex) 64 | Generated ex_doc app 65 | ==> tic_tac_toe 66 | Compiling 3 files (.ex) 67 | Generated tic_tac_toe app 68 | == Tic-tac-toe Game == 69 | Do you want a random game? (yes/no)? 70 | 71 | 72 | ``` 73 | 74 | 75 | ## Example 76 | 77 | ``` 78 | $ mix start 79 | == Tic-tac-toe Game == 80 | Do you want a random game? (yes/no)? yes 81 | OK, random game chosen! 82 | The first move is yours! 83 | Current board 84 | _ _ _ 85 | _ _ _ 86 | _ _ _ 87 | 88 | Type line and column of your move 89 | (two numbers, line and column, between 1 and 3 separated by a blank space, or -1 to quit): 1 1 90 | You chose line=1, column=1! 91 | Current board 92 | X _ O 93 | _ _ _ 94 | _ _ _ 95 | 96 | Type line and column of your move 97 | (two numbers, line and column, between 1 and 3 separated by a blank space, or -1 to quit): 2 2 98 | You chose line=2, column=2! 99 | Current board 100 | X _ O 101 | _ X _ 102 | _ O _ 103 | 104 | Type line and column of your move 105 | (two numbers, line and column, between 1 and 3 separated by a blank space, or -1 to quit): 3 3 106 | You chose line=3, column=3! 107 | Current board 108 | X _ O 109 | _ X _ 110 | _ O X 111 | 112 | Congrats! You won! 113 | ``` 114 | 115 | 116 | -------------------------------------------------------------------------------- /offerings/2022/projects/tic_tac_toe/lib/mix/tasks/start.ex: -------------------------------------------------------------------------------- 1 | defmodule Mix.Tasks.Start do 2 | use Mix.Task 3 | 4 | def run(_), do: TicTacToe.CLI.Main.start_game() 5 | end 6 | -------------------------------------------------------------------------------- /offerings/2022/projects/tic_tac_toe/lib/tic_tac_toe/cli/main.ex: -------------------------------------------------------------------------------- 1 | defmodule TicTacToe.CLI.Main do 2 | alias Mix.Shell.IO, as: Shell 3 | 4 | def start_game do 5 | Shell.info("== Tic-tac-toe Game ==") 6 | type = ask_type_of_game() 7 | Shell.info("The first move is yours!") 8 | play_game(type) 9 | end 10 | 11 | defp ask_type_of_game() do 12 | answer = 13 | Shell.prompt("Do you want a random game? (yes/no)?") 14 | |> String.trim() 15 | 16 | if answer == "yes" do 17 | Shell.info("OK, random game chosen!") 18 | true 19 | else 20 | Shell.info("OK, my moves will be predictable!") 21 | false 22 | end 23 | end 24 | 25 | def play_game(pseudo_random) do 26 | if pseudo_random do 27 | :rand.seed(:exsss) 28 | else 29 | :rand.seed(:exsss, {100, 101, 102}) 30 | end 31 | 32 | keep_playing(TicTacToe.new_board()) 33 | end 34 | 35 | def parse_choice(string) do 36 | string 37 | |> String.split() 38 | |> Enum.map(&String.to_integer/1) 39 | end 40 | 41 | defp keep_playing(board) do 42 | show_board(board) 43 | 44 | case parse_choice(choose_position()) do 45 | [-1] -> 46 | Shell.info("Bye bye! See you next time!") 47 | 48 | [line, column] when line in 1..3 and column in 1..3 -> 49 | Shell.info("You chose line=#{line}, column=#{column}!") 50 | apply_move(board, line, column) 51 | 52 | _ -> 53 | Shell.info("Wrong input! Your input should be two numbers between 1 and 3!") 54 | keep_playing(board) 55 | end 56 | end 57 | 58 | defp choose_position() do 59 | Shell.prompt( 60 | "Type line and column of your move\n(two numbers, line and column, between 1 and 3 separated by a blank space, or -1 to quit): " 61 | ) 62 | |> String.trim() 63 | end 64 | 65 | defp show_board([p11, p12, p13, p21, p22, p23, p31, p32, p33]) do 66 | Shell.info("Current board") 67 | Shell.info("#{p11} #{p12} #{p13}") 68 | Shell.info("#{p21} #{p22} #{p23}") 69 | Shell.info("#{p31} #{p32} #{p33}") 70 | Shell.info("") 71 | end 72 | 73 | defp apply_move(board, line, column) do 74 | if TicTacToe.allowed_play?(board, line, column) do 75 | board_after_the_human_played = TicTacToe.play(board, 1, line, column) 76 | 77 | if winner?(board_after_the_human_played) do 78 | show_board(board_after_the_human_played) 79 | Shell.info("Congrats! You won!") 80 | start_game() 81 | else 82 | board_after_the_computer_played = computer_plays(board_after_the_human_played) 83 | 84 | if winner?(board_after_the_computer_played) do 85 | show_board(board_after_the_computer_played) 86 | Shell.info("Sorry, the computer won!") 87 | start_game() 88 | else 89 | keep_playing(board_after_the_computer_played) 90 | end 91 | end 92 | else 93 | Shell.info("Wrong input! The position you chose is not empty!") 94 | keep_playing(board) 95 | end 96 | end 97 | 98 | defp winner?(board) do 99 | {_, result} = TicTacToe.finished?(board) 100 | result 101 | end 102 | 103 | def computer_plays(board) do 104 | TicTacToe.play_random(board, 2) 105 | end 106 | end 107 | -------------------------------------------------------------------------------- /offerings/2022/projects/tic_tac_toe/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule TicTacToe.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :tic_tac_toe, 7 | version: "0.1.0", 8 | elixir: "~> 1.14", 9 | start_permanent: Mix.env() == :prod, 10 | deps: deps() 11 | ] 12 | end 13 | 14 | # Run "mix help compile.app" to learn about applications. 15 | def application do 16 | [ 17 | extra_applications: [:logger] 18 | ] 19 | end 20 | 21 | # Run "mix help deps" to learn about dependencies. 22 | defp deps do 23 | [ 24 | {:ex_doc, "~> 0.27", only: :dev, runtime: false} 25 | 26 | # {:dep_from_hexpm, "~> 0.3.0"}, 27 | # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} 28 | ] 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /offerings/2022/projects/tic_tac_toe/mix.lock: -------------------------------------------------------------------------------- 1 | %{ 2 | "earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"}, 3 | "ex_doc": {:hex, :ex_doc, "0.29.1", "b1c652fa5f92ee9cf15c75271168027f92039b3877094290a75abcaac82a9f77", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "b7745fa6374a36daf484e2a2012274950e084815b936b1319aeebcf7809574f6"}, 4 | "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, 5 | "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, 6 | "makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"}, 7 | "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, 8 | "mix_test_watch": {:hex, :mix_test_watch, "1.1.0", "330bb91c8ed271fe408c42d07e0773340a7938d8a0d281d57a14243eae9dc8c3", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "52b6b1c476cbb70fd899ca5394506482f12e5f6b0d6acff9df95c7f1e0812ec3"}, 9 | "nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"}, 10 | } 11 | -------------------------------------------------------------------------------- /offerings/2022/projects/tic_tac_toe/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /offerings/2022/projects/tic_tac_toe/test/tic_tac_toe_test.exs: -------------------------------------------------------------------------------- 1 | defmodule TicTacToeTest do 2 | use ExUnit.Case 3 | doctest TicTacToe 4 | 5 | test "Create an empty board" do 6 | assert TicTacToe.new_board() == List.duplicate(TicTacToe.empty_symbol(), 9) 7 | end 8 | 9 | test "Player 1 puts an X on line 3, column 1" do 10 | board_after_play = 11 | TicTacToe.new_board() 12 | |> TicTacToe.play(1, 3, 1) 13 | 14 | assert board_after_play == ["_", "_", "_", "_", "_", "_", "X", "_", "_"] 15 | end 16 | 17 | test "Player 1 puts an X on line 1, column 1" do 18 | board_after_play = 19 | TicTacToe.new_board() 20 | |> TicTacToe.play(1, 1, 1) 21 | 22 | assert board_after_play == ["X", "_", "_", "_", "_", "_", "_", "_", "_"] 23 | end 24 | 25 | test "Player can be only 1 or 2" do 26 | assert_raise FunctionClauseError, 27 | "no function clause matching in TicTacToe.player_symbol/1", 28 | fn -> 29 | TicTacToe.new_board() 30 | |> TicTacToe.play(3, 1, 1) 31 | end 32 | end 33 | 34 | test "Player 1 puts an X on line 1, column 1 and then" <> 35 | "Player 2 puts an O on line 1, column 2" do 36 | board_after_play = 37 | TicTacToe.new_board() 38 | |> TicTacToe.play(1, 1, 1) 39 | |> TicTacToe.play(2, 1, 2) 40 | 41 | assert board_after_play == ["X", "O", "_", "_", "_", "_", "_", "_", "_"] 42 | end 43 | 44 | test "Plays: 1 1 1, 2 1 2, 1 2 1, 2 2 2, 1 3 1" do 45 | board_after_play = 46 | TicTacToe.new_board() 47 | |> TicTacToe.play(1, 1, 1) 48 | |> TicTacToe.play(2, 1, 2) 49 | |> TicTacToe.play(1, 2, 1) 50 | |> TicTacToe.play(2, 2, 2) 51 | |> TicTacToe.play(1, 3, 1) 52 | 53 | assert board_after_play == [ 54 | "X", 55 | "O", 56 | "_", 57 | "X", 58 | "O", 59 | "_", 60 | "X", 61 | "_", 62 | "_" 63 | ] 64 | 65 | assert TicTacToe.finished?(board_after_play) == {"X", true} 66 | end 67 | 68 | test "XXX 69 | O_O 70 | _O_ is a finished board" do 71 | assert TicTacToe.finished?([ 72 | "X", 73 | "X", 74 | "X", 75 | "O", 76 | "_", 77 | "O", 78 | "X", 79 | "O", 80 | "_" 81 | ]) == {"X", true} 82 | end 83 | 84 | test "X_XOXO_OX is a finished board" do 85 | assert TicTacToe.finished?([ 86 | "X", 87 | "_", 88 | "X", 89 | "O", 90 | "X", 91 | "O", 92 | "_", 93 | "O", 94 | "X" 95 | ]) == {"X", true} 96 | end 97 | 98 | test "XOX 99 | XOO 100 | OXX 101 | is a finished board" do 102 | assert TicTacToe.finished?([ 103 | "X", 104 | "O", 105 | "X", 106 | "X", 107 | "O", 108 | "O", 109 | "O", 110 | "X", 111 | "X" 112 | ]) == {nil, true} 113 | end 114 | 115 | test "XOX 116 | XOO 117 | OX_ 118 | is a finished board" do 119 | assert TicTacToe.finished?([ 120 | "X", 121 | "O", 122 | "X", 123 | "X", 124 | "O", 125 | "O", 126 | "O", 127 | "X", 128 | "_" 129 | ]) == {nil, false} 130 | end 131 | end 132 | -------------------------------------------------------------------------------- /offerings/2023/README.md: -------------------------------------------------------------------------------- 1 | # CAES005 - Introduction to Functional Programming (2023) 2 | 3 | ## Blog posts 4 | 5 | - [Why I think the dot is not a problem in Elixir](https://dev.to/adolfont/why-i-think-the-dot-is-not-a-problem-in-elixir-1nia) 6 | - [Why the dot (when calling anonymous functions)?](https://dashbit.co/blog/why-the-dot) 7 | 8 | ## Books 9 | 10 | - [Programming Elixir 1.6](https://pragprog.com/titles/elixir16/programming-elixir-1-6/) 11 | - [Learn Functional Programming with Elixir](https://pragprog.com/titles/cdc-elixir/learn-functional-programming-with-elixir/) 12 | -------------------------------------------------------------------------------- /offerings/2023/livebooks/2023_10_24.livemd: -------------------------------------------------------------------------------- 1 | # October 24th, 2023 2 | 3 | ## Side effects 4 | 5 | ```elixir 6 | defmodule M do 7 | def f(x) do 8 | 2 * x 9 | end 10 | end 11 | ``` 12 | 13 | ```elixir 14 | x = 30 15 | ``` 16 | 17 | ```elixir 18 | M.f(x) 19 | ``` 20 | 21 | ```elixir 22 | x 23 | ``` 24 | 25 | ```elixir 26 | x = 6000 27 | ``` 28 | 29 | ```elixir 30 | M.f(x) 31 | ``` 32 | 33 | ```elixir 34 | x = M.f(x) 35 | ``` 36 | 37 | ```elixir 38 | x 39 | ``` 40 | 41 | ```elixir 42 | IO.puts("1200") 43 | 2300 44 | ``` 45 | 46 | ```elixir 47 | IO.puts("1200") 48 | IO.puts("10") 49 | IO.puts("200") 50 | IO.puts("13200") 51 | IO.puts("124400") 52 | x = 10 53 | y = 20 54 | z = 30 55 | x * y * z 56 | ``` 57 | 58 | ```elixir 59 | IO.puts("2742893749") 60 | ``` 61 | 62 | ```elixir 63 | x = IO.puts("x") 64 | ``` 65 | 66 | ```elixir 67 | x 68 | ``` 69 | 70 | ## Immutability in lists 71 | 72 | ```elixir 73 | # range 74 | 1..100 75 | ``` 76 | 77 | ```elixir 78 | 100..1 79 | ``` 80 | 81 | ```elixir 82 | 1..100//2 83 | ``` 84 | 85 | ```elixir 86 | even = Enum.to_list(10..50//2) 87 | ``` 88 | 89 | ```elixir 90 | newlist = List.replace_at(even, 2, 13) 91 | ``` 92 | 93 | ```elixir 94 | even 95 | ``` 96 | 97 | ```elixir 98 | newlist 99 | ``` 100 | 101 | ## Function with side effects 102 | 103 | ```elixir 104 | defmodule SideEffects do 105 | def f(x) do 106 | IO.inspect(x) 107 | x 108 | end 109 | end 110 | ``` 111 | 112 | ```elixir 113 | SideEffects.f(10) 114 | ``` 115 | 116 | ```elixir 117 | SideEffects.f({7_632_746, 234_234, :ok}) 118 | ``` 119 | 120 | ```elixir 121 | # IO.gets("Type a number: ") 122 | # only on an elixir program or on iex 123 | ``` 124 | 125 | ## This is not a mathematical function! 126 | 127 | ```elixir 128 | Enum.random(even) 129 | ``` 130 | 131 | ## Exercise: Smallest and largest 132 | 133 | ```elixir 134 | defmodule Math do 135 | def smallest_largest([head | tail] = a_list) when is_list(a_list) do 136 | smallest_largest(tail, {head, head}) 137 | end 138 | 139 | def smallest_largest(_), 140 | do: {:error, "!!! Wrong Argument !!! It should be a non-empty list !!!"} 141 | 142 | defp smallest_largest([], {smallest_so_far, largest_so_far}), 143 | do: {smallest_so_far, largest_so_far} 144 | 145 | defp smallest_largest([head | tail], {smallest_so_far, largest_so_far}) 146 | when head > largest_so_far, 147 | do: smallest_largest(tail, {smallest_so_far, head}) 148 | 149 | defp smallest_largest([head | tail], {smallest_so_far, largest_so_far}) 150 | when head < smallest_so_far, 151 | do: smallest_largest(tail, {head, largest_so_far}) 152 | 153 | defp smallest_largest([_head | tail], {smallest_so_far, largest_so_far}), 154 | do: smallest_largest(tail, {smallest_so_far, largest_so_far}) 155 | end 156 | ``` 157 | 158 | ```elixir 159 | Math.smallest_largest([12, 34, 48, 48, 3]) 160 | ``` 161 | 162 | ```elixir 163 | Math.smallest_largest([1, -1, 100, 48, 3]) 164 | ``` 165 | -------------------------------------------------------------------------------- /offerings/2023/livebooks/2023_10_31/README.md: -------------------------------------------------------------------------------- 1 | # 3 notebooks from October 31st, 2023 2 | 3 | - [Part 1 - previous exercises](./oct31_part1.livemd) 4 | - [Part 2 - TDD](./oct31_part2.livemd) 5 | - [Part 3](./oct31_part3.livemd) 6 | -------------------------------------------------------------------------------- /offerings/2023/livebooks/2023_10_31/oct31_part2.livemd: -------------------------------------------------------------------------------- 1 | # October 31st, 2023 - TDD with Livebook 2 | 3 | ## Tests 4 | 5 | TDD = Test Driven Development 6 | 7 | ```elixir 8 | ExUnit.start(auto_run: false) 9 | 10 | defmodule CalculatorTest do 11 | use ExUnit.Case, async: false 12 | 13 | describe "Testing the addition function" do 14 | test "2 plus 3 is 5" do 15 | assert Calculator.add(2, 3) == 5 16 | end 17 | 18 | test "2 plus 2 is 4" do 19 | assert Calculator.add(2, 2) == 4 20 | end 21 | end 22 | 23 | describe "Testing the multiplication function" do 24 | test "2 times 3 is 6" do 25 | assert Calculator.multiply(2, 3) == 6 26 | end 27 | 28 | test "2 times 20 is 40" do 29 | assert Calculator.multiply(2, 20) == 40 30 | end 31 | end 32 | end 33 | 34 | ExUnit.run() 35 | ``` 36 | 37 | ## Code 38 | 39 | ```elixir 40 | defmodule Calculator do 41 | def add(a, b) do 42 | a + b 43 | end 44 | 45 | def multiply(a, b) do 46 | a * b 47 | end 48 | end 49 | ``` 50 | 51 | ## Second example 52 | 53 | ## Tests 54 | 55 | ```elixir 56 | ExUnit.start(auto_run: false) 57 | 58 | defmodule MethodTest do 59 | use ExUnit.Case, async: false 60 | 61 | describe "Testing the square root function" do 62 | test "the square root of 9 is 3.0" do 63 | assert Method.sqrt(9) == 3.0 64 | end 65 | 66 | test "the square root of 16 is 4.00..." do 67 | assert Method.sqrt(16) == 4.0 68 | end 69 | end 70 | 71 | describe "Testing the power function" do 72 | test "3 raised to the power of 2 is 9" do 73 | assert Method.pow(3, 2) == 9.0 74 | end 75 | end 76 | 77 | describe "Testing the cubic root function" do 78 | test "the cubic root of 27 is 3.0" do 79 | assert Method.cbcrt(27) == 3.0 80 | end 81 | 82 | test "the cubic root of 64 is 4.0" do 83 | assert_in_delta Method.cbcrt(64), 4.0, 0.00000000000001 84 | end 85 | end 86 | end 87 | 88 | ExUnit.run() 89 | ``` 90 | 91 | ## Code 92 | 93 | ```elixir 94 | defmodule Method do 95 | def sqrt(x) do 96 | x ** (1 / 2) 97 | end 98 | 99 | def pow(base, exponent) do 100 | base ** exponent 101 | end 102 | 103 | def cbcrt(x) do 104 | x ** (1 / 3) 105 | end 106 | end 107 | ``` 108 | 109 | ```elixir 110 | Method.sqrt(16) 111 | ``` 112 | -------------------------------------------------------------------------------- /offerings/2023/livebooks/2023_10_31/oct31_part3.livemd: -------------------------------------------------------------------------------- 1 | # October 31st, 2023 2 | 3 | ## 1. Review 4 | 5 | ```elixir 6 | 7 | ``` 8 | 9 | ## 1.1 Doing two things at the same time 10 | 11 | ## 1.1.1 Math.smallest_largest/1 12 | 13 | ## 1.2 Exercism topics 14 | 15 | * Basics (Modules and functions) 16 | * Anonymous functions 17 | * Bit Manipulation 18 | * Booleans 19 | * Floating Point Numbers 20 | * Integers 21 | * Lists 22 | * Atoms 23 | * Cond 24 | * ... 25 | 26 | So, it is basically: 27 | 28 | * Functions 29 | * Types 30 | * Conditional expressions 31 | 32 | ## 2. Visitors 33 | 34 | ```elixir 35 | visitors = ["Danilo Gazzoli", "Gabriel Aquino"] 36 | ``` 37 | -------------------------------------------------------------------------------- /offerings/2023/livebooks/2023_11_14.livemd: -------------------------------------------------------------------------------- 1 | # November 14th, 2023 2 | 3 | ## Case 4 | 5 | ```elixir 6 | # structure = [1, 2, 3] 7 | # structure = {1, 2, 3} 8 | # structure = %{"one" => :two, 3 => "four"} 9 | magic_number = 42 10 | structure = 42 11 | 12 | case structure do 13 | [head | _tail] -> head 14 | {element, _, _} -> element 15 | %{"one" => value} -> value 16 | ^magic_number -> "It is the magic number" 17 | _ -> :error 18 | end 19 | ``` 20 | -------------------------------------------------------------------------------- /offerings/2023/livebooks/2023_12_05.livemd: -------------------------------------------------------------------------------- 1 | # A small task 2 | 3 | ## Section 4 | 5 | ```elixir 6 | f = fn x -> x end 7 | 8 | f.([{2, 1, 3}, {4, 5, 1}, {5, 2, 1}]) == {5, 5, 3} 9 | ``` 10 | 11 | ```elixir 12 | f.([{2, 1, 3}, {4, 5, 1}]) == {4, 5, 3} 13 | ``` 14 | 15 | ```elixir 16 | f.([{2, 1, 3}, {4, 5, 10}, {2, 10, 3}, {40, 5, 1}]) == {40, 10, 10} 17 | ``` 18 | 19 | ```elixir 20 | Enum.max([10, 2, 3]) 21 | ``` 22 | 23 | ```elixir 24 | max_first = 25 | [{2, 1, 3}, {4, 5, 10}, {2, 10, 3}, {40, 5, 1}] 26 | |> Enum.map(fn {x, _, _} -> x end) 27 | |> Enum.max() 28 | ``` 29 | 30 | ```elixir 31 | max_second = 32 | [{2, 1, 3}, {4, 5, 10}, {2, 10, 3}, {40, 5, 1}] 33 | |> Enum.map(fn {_, x, _} -> x end) 34 | |> Enum.max() 35 | ``` 36 | 37 | ```elixir 38 | max_third = 39 | [{2, 1, 3}, {4, 5, 10}, {2, 10, 3}, {40, 5, 1}] 40 | |> Enum.map(fn {_, _, x} -> x end) 41 | |> Enum.max() 42 | ``` 43 | 44 | ```elixir 45 | defmodule SimpleTask do 46 | def max_tuple(list) do 47 | { 48 | max_in(list, fn {x, _, _} -> x end), 49 | max_in(list, fn {_, x, _} -> x end), 50 | max_in(list, fn {_, _, x} -> x end) 51 | } 52 | end 53 | 54 | defp max_in(list, function) do 55 | list 56 | |> Enum.map(function) 57 | |> Enum.max() 58 | end 59 | end 60 | ``` 61 | 62 | ```elixir 63 | SimpleTask.max_tuple([{2, 1, 3}, {4, 5, 1}, {5, 2, 1}]) == {5, 5, 3} 64 | ``` 65 | 66 | ```elixir 67 | SimpleTask.max_tuple([{2, 1, 3}, {4, 5, 10}, {2, 10, 3}, {40, 5, 1}]) == {40, 10, 10} 68 | ``` 69 | 70 | ```elixir 71 | [{2, 1, 3}, {4, 5, 10}, {2, 10, 3}, {40, 5, 1}] 72 | |> Enum.reduce(fn {x, y, z}, {maxx, maxy, maxz} -> 73 | {max(x, maxx), max(y, maxy), max(z, maxz)} 74 | end) 75 | ``` 76 | 77 | ## Second sub-task 78 | 79 | ```elixir 80 | f = fn {x, y, z} -> x * y * z end 81 | f.({4, 5, 10}) == 4 * 5 * 10 82 | ``` 83 | -------------------------------------------------------------------------------- /offerings/2023/livebooks/2023_12_05_2.livemd: -------------------------------------------------------------------------------- 1 | # 2023 - 12 -05 2 | 3 | ## Section 4 | 5 | ```elixir 6 | defmodule Moves do 7 | def new() do 8 | [] 9 | end 10 | 11 | def add([m1, m2, m3, _m4] = moves, x, y) when length(moves) == 4 do 12 | [{x, y} | [m1, m2, m3]] 13 | end 14 | 15 | def add(moves, x, y) do 16 | [{x, y} | moves] 17 | end 18 | 19 | # def add(moves, x, y) do 20 | # new_moves = [{x, y} | moves] 21 | 22 | # if length(new_moves) == 5 do 23 | # new_moves 24 | # |> Enum.reverse() 25 | # |> tl() 26 | # |> Enum.reverse() 27 | # else 28 | # new_moves 29 | # end 30 | # end 31 | 32 | def add_v2(moves, x, y) do 33 | new_moves = moves ++ [{x, y}] 34 | 35 | if length(new_moves) == 5 do 36 | tl(new_moves) 37 | else 38 | new_moves 39 | end 40 | end 41 | end 42 | ``` 43 | 44 | ```elixir 45 | Moves.new() 46 | |> Moves.add(1, 1) 47 | |> Moves.add(2, 2) 48 | |> Moves.add(3, 3) 49 | |> Moves.add(3, 2) 50 | |> Moves.add(1, 3) 51 | |> Moves.add(1, 1) 52 | ``` 53 | 54 | ```elixir 55 | Moves.new() 56 | |> Moves.add_v2(1, 1) 57 | |> Moves.add_v2(2, 2) 58 | |> Moves.add_v2(3, 3) 59 | |> Moves.add_v2(3, 2) 60 | |> Moves.add_v2(1, 3) 61 | |> Moves.add_v2(1, 1) 62 | ``` 63 | 64 | ## Queue 65 | 66 | ```elixir 67 | :queue.from_list([1, 2, 3, 4, 5]) 68 | ``` 69 | -------------------------------------------------------------------------------- /offerings/2023/livebooks/2023_12_08_1.livemd: -------------------------------------------------------------------------------- 1 | # Function as first-class citizen 2 | 3 | ## Function as an argument 4 | 5 | ```elixir 6 | Enum.map([1, 2, 3], fn x -> x ** 3 end) 7 | ``` 8 | 9 | ## Function as a return value 10 | 11 | ```elixir 12 | defmodule Power do 13 | def of_three(list) do 14 | Enum.map(list, pow(3)) 15 | end 16 | 17 | def of_two(list) do 18 | Enum.map(list, pow(2)) 19 | end 20 | 21 | def pow(n) do 22 | fn x -> x ** n end 23 | end 24 | end 25 | ``` 26 | 27 | ```elixir 28 | Power.of_three([1, 2, 3]) 29 | ``` 30 | 31 | ```elixir 32 | Power.of_two([2, 4, 78]) 33 | ``` 34 | 35 | ## Assign a function to a variable 36 | 37 | ```elixir 38 | power_of_four = Power.pow(4) 39 | ``` 40 | 41 | ```elixir 42 | power_of_four 43 | ``` 44 | 45 | ```elixir 46 | power_of_four.(3) 47 | ``` 48 | 49 | ```elixir 50 | defmodule X do 51 | def f(y) do 52 | y * 3 53 | end 54 | end 55 | ``` 56 | -------------------------------------------------------------------------------- /offerings/2023/livebooks/2023_12_12_2.livemd: -------------------------------------------------------------------------------- 1 | # Collections 2 | 3 | ## Lists 4 | 5 | ```elixir 6 | [1, 3, 4] 7 | ``` 8 | 9 | ```elixir 10 | [1, 3, "a"] 11 | ``` 12 | 13 | ## Tuples 14 | 15 | ```elixir 16 | {1, 3, 4} 17 | ``` 18 | 19 | ## Maps 20 | 21 | ```elixir 22 | %{} 23 | ``` 24 | 25 | ```elixir 26 | %{:A => 1} 27 | ``` 28 | 29 | ```elixir 30 | %{"A" => 1} 31 | ``` 32 | 33 | ```elixir 34 | %{:A => 1, :B => 3, :C => 45} 35 | ``` 36 | 37 | ```elixir 38 | map = %{:A => 1, :B => 3, :C => 3, :A => 90} 39 | ``` 40 | 41 | ```elixir 42 | Enum.map(map, fn x -> x end) 43 | ``` 44 | 45 | ```elixir 46 | Enum.map(map, fn {x, _y} -> x end) 47 | ``` 48 | 49 | ```elixir 50 | Enum.map(map, fn {_x, y} -> y end) 51 | ``` 52 | 53 | ```elixir 54 | Enum.map(map, fn {key, value} -> {key, value * 2} end) 55 | ``` 56 | 57 | ```elixir 58 | map 59 | |> Enum.reduce( 60 | Map.new(), 61 | fn {key, value}, acc -> 62 | Map.put(acc, key, value * 2) 63 | end 64 | ) 65 | ``` 66 | 67 | ```elixir 68 | [1, 2, 30] 69 | |> Enum.reduce(1, fn x, acc -> acc * x end) 70 | ``` 71 | 72 | ## Keyword list 73 | 74 | ```elixir 75 | [{:A, 90}, {:B, 3}, {:C, 45}] 76 | ``` 77 | 78 | ```elixir 79 | x = 3 80 | ``` 81 | 82 | ```elixir 83 | x = 4 84 | ``` 85 | 86 | ```elixir 87 | x 88 | ``` 89 | 90 | ```elixir 91 | Integer.parse("10") 92 | ``` 93 | 94 | ```elixir 95 | Integer.parse("10AAA") 96 | ``` 97 | 98 | ```elixir 99 | Integer.parse("AA") 100 | ``` 101 | 102 | ```elixir 103 | input = "a" 104 | 105 | case Integer.parse(input) do 106 | :error -> "This '#{input}' is not a number" 107 | {number, ""} -> "Your number is #{number}" 108 | _ -> "This '#{input}' is not only a number" 109 | end 110 | ``` 111 | 112 | ```elixir 113 | x = [1, 2] 114 | ``` 115 | 116 | ```elixir 117 | List.replace_at(x, 1, 300) 118 | ``` 119 | 120 | ```elixir 121 | x 122 | ``` 123 | 124 | ```elixir 125 | Enum.reduce_while(1..100, 0, fn x, acc -> 126 | if x < 5 do 127 | {:cont, acc + x} 128 | else 129 | {:halt, acc} 130 | end 131 | end) 132 | ``` 133 | 134 | ```elixir 135 | Enum.reduce_while(100..1, 0, fn x, acc -> 136 | if x > 95 do 137 | {:cont, acc + x} 138 | else 139 | {:halt, acc} 140 | end 141 | end) 142 | ``` 143 | 144 | ```elixir 145 | 100 + 99 + 98 + 97 + 96 146 | ``` 147 | 148 | ```elixir 149 | with {m, ""} <- Integer.parse("10"), 150 | {n, ""} <- Integer.parse("BB20") do 151 | m * n 152 | end 153 | ``` 154 | -------------------------------------------------------------------------------- /offerings/2023/livebooks/digraphs.livemd: -------------------------------------------------------------------------------- 1 | # Digraphs 2 | 3 | ## Example 4 | 5 | ```elixir 6 | graph = :digraph.new() 7 | ``` 8 | 9 | ```elixir 10 | vertex1 = :digraph.add_vertex(graph, "Node 1") 11 | vertex2 = :digraph.add_vertex(graph, "Node 2") 12 | vertex3 = :digraph.add_vertex(graph, "Node 3") 13 | ``` 14 | 15 | ```elixir 16 | :digraph.add_edge(graph, vertex1, vertex2) 17 | :digraph.add_edge(graph, vertex2, vertex3) 18 | ``` 19 | 20 | ```elixir 21 | graph 22 | ``` 23 | 24 | ```elixir 25 | :digraph.vertices(graph) 26 | ``` 27 | 28 | ```elixir 29 | :digraph.edges(graph) 30 | ``` 31 | 32 | ```elixir 33 | :digraph.get_path(graph, vertex1, vertex3) 34 | ``` 35 | 36 | ```elixir 37 | :digraph.get_path(graph, vertex1, vertex2) 38 | ``` 39 | 40 | ```elixir 41 | :digraph.get_path(graph, vertex2, vertex3) 42 | ``` 43 | -------------------------------------------------------------------------------- /offerings/2023/notes/2023_11_21.md: -------------------------------------------------------------------------------- 1 | # 2023-11-21 2 | 3 | - More interaction - more coding - breakout rooms? 4 | - Results from form 5 | - [Choose Your Language](https://docs.google.com/forms/d/1yEeNhhS3XtQ3nw7es7zKR6VcowH95h-TPG1HR5f-fIo/edit) 6 | - Advent of Code 2017 - Day 1 7 | - Enum 8 | -------------------------------------------------------------------------------- /offerings/2023/notes/2023_11_28.md: -------------------------------------------------------------------------------- 1 | # 28/11/2023 2 | 3 | 4 | 5 | 6 | - **Task 1** (30%) https://github.com/adolfont/caes005-introduction-to-functional-programming/blob/main/offerings/2023/tasks/languages_task.md 7 | - on Dec 19th 8 | 9 | 10 | - Task 2 (15%) review 3 knowledge exchange items 11 | - video 12 | - podcast episode 13 | - blog post 14 | - Task 3 (15%) review one scientific paper from: 15 | - [Journal of Functional Programming](https://scholar.google.com/citations?hl=en&view_op=list_hcore&venue=yzdEqktbJzoJ.2023) 16 | - [ICFP: International Conference on Functional Programming](https://dl.acm.org/conference/icfp/proceedings) - Not from the workshops 17 | - [Journal of Computer Languages](https://www.sciencedirect.com/journal/journal-of-computer-languages) 18 | - [The Programming Journal](https://programming-journal.org/) 19 | - Task 4 (40%) implement a game 20 | - Task 5 (5%) Exercism 21 | - [Type Systems](https://kmicinski.com/cis352-f23/assets/slides/types.pdf) 22 | - Intuitionistic Propositional Logic (IPL) and natural deduction 23 | - These type systems rule out programs containing possible type errors 24 | - No well-typed program will crash due to a runtime type error 25 | - Curry-Howard Isomorphism: well-typed programs correspond to valid proofs of theorems in constructive logic 26 | - compile time vs. runtime (contracts are checked at runtime) --> Guards 27 | - "sometimes we want to know our program won’t break before it runs!" 28 | - "A type system assigns each source fragment with a given type: a specification of how it will behave" 29 | 30 | - Aoc 2017 Day 1 in Lean?? 31 | 32 | 33 | - Bruce Tate (probably next week) 34 | 35 | 36 | - [Lazy evaluation](https://chat.openai.com/share/62fcb401-501f-4f7c-b595-fcd6c018483c) 37 | - https://wiki.haskell.org/Lazy_evaluation 38 | - https://wiki.haskell.org/Haskell/Lazy_evaluation 39 | - https://hexdocs.pm/elixir/Stream.html 40 | -------------------------------------------------------------------------------- /offerings/2023/notes/knowldege_items.md: -------------------------------------------------------------------------------- 1 | Good evening Professor, 2 | 3 | I have chosen the following videos for the Knowledge Exchange Review task of our Introduction to Functional Programming class: 4 | 5 | The purest coding style, where bugs are near impossible 6 | https://www.youtube.com/watch?v=HlgG395PQWw 7 | An interesting visual introduction to functional programming. 8 | 9 | Functional Programming in 40 Minutes • Russ Olsen • GOTO 2018 10 | https://www.youtube.com/watch?v=HlgG395PQWw 11 | A talk about Functional Programming on the GOTO Berlin 2018 convention. 12 | 13 | ABSTRACT - Functional programming has finally escaped from academia. These days developers are building real systems in functional programming languages like Clojure, Scala, Elixir and F#. Functional techniques are also seeping into more traditional languages like Java and Ruby. Unfortunately somewhere along the way functional programming has also developed a reputation for being deep and mysterious: Good programs achieve the Zen-like state of being functional which somehow involves immutability, higher order functions [...] 14 | 15 | The Absolute Best Intro to Monads For Software Engineers 16 | https://www.youtube.com/watch?v=C2w45qRc3aU 17 | An interesting video that talks about a design pattern spawned from functional programming principles called Monads. 18 | 19 | Hope you find them interesting! 20 | - Paulo Sérgio Ávila Júnior 21 | -------------------------------------------------------------------------------- /offerings/2023/projects/aoc2017_day01/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /offerings/2023/projects/aoc2017_day01/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | aoc2017_day01-*.tar 24 | 25 | # Temporary files, for example, from tests. 26 | /tmp/ 27 | -------------------------------------------------------------------------------- /offerings/2023/projects/aoc2017_day01/README.md: -------------------------------------------------------------------------------- 1 | # Aoc2017Day01 2 | 3 | **TODO: Add description** 4 | 5 | ## Installation 6 | 7 | If [available in Hex](https://hex.pm/docs/publish), the package can be installed 8 | by adding `aoc2017_day01` to your list of dependencies in `mix.exs`: 9 | 10 | ```elixir 11 | def deps do 12 | [ 13 | {:aoc2017_day01, "~> 0.1.0"} 14 | ] 15 | end 16 | ``` 17 | 18 | Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) 19 | and published on [HexDocs](https://hexdocs.pm). Once published, the docs can 20 | be found at . 21 | 22 | -------------------------------------------------------------------------------- /offerings/2023/projects/aoc2017_day01/lib/aoc2017_day01.ex: -------------------------------------------------------------------------------- 1 | defmodule Aoc2017Day01 do 2 | def task1(input) do 3 | input 4 | |> creates_a_list_of_integers() 5 | |> Enum.chunk_every(2, 1) 6 | |> Enum.reverse() 7 | |> tl 8 | |> Enum.reverse() 9 | |> Enum.reduce(0, fn element, acc -> acc + check_pairs(element) end) 10 | end 11 | 12 | defp creates_a_list_of_integers(input) do 13 | list = String.codepoints(input) 14 | 15 | new_list = list ++ [hd(list)] 16 | 17 | new_list 18 | |> Enum.map(&String.to_integer/1) 19 | end 20 | 21 | defp creates_a_list_of_integers_task2(input) do 22 | input 23 | |> String.codepoints() 24 | |> Enum.map(&String.to_integer/1) 25 | end 26 | 27 | @doc """ 28 | An auxiliary function that returns zero when the arguments are different 29 | And that returns the number when the two arguments are that number. 30 | """ 31 | def check_pairs([n, n]), do: n 32 | def check_pairs([_, _]), do: 0 33 | 34 | def task2(input) do 35 | map = 36 | input 37 | |> creates_a_list_of_integers_task2() 38 | |> create_a_map() 39 | 40 | len = length(Map.keys(map)) 41 | 42 | map 43 | |> Enum.reduce( 44 | 0, 45 | fn {index, value}, acc -> acc + check_pairs([value, map[rem(index + div(len, 2), len)]]) end 46 | ) 47 | end 48 | 49 | defp create_a_map(list) do 50 | list 51 | |> Enum.with_index() 52 | |> Enum.map(fn {x, y} -> {y, x} end) 53 | |> Map.new() 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /offerings/2023/projects/aoc2017_day01/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Aoc2017Day01.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :aoc2017_day01, 7 | version: "0.1.0", 8 | elixir: "~> 1.15", 9 | start_permanent: Mix.env() == :prod, 10 | deps: deps() 11 | ] 12 | end 13 | 14 | # Run "mix help compile.app" to learn about applications. 15 | def application do 16 | [ 17 | extra_applications: [:logger] 18 | ] 19 | end 20 | 21 | # Run "mix help deps" to learn about dependencies. 22 | defp deps do 23 | [ 24 | # {:dep_from_hexpm, "~> 0.3.0"}, 25 | # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} 26 | ] 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /offerings/2023/projects/aoc2017_day01/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /offerings/2023/projects/factorial/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /offerings/2023/projects/factorial/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | factorial-*.tar 24 | 25 | # Temporary files, for example, from tests. 26 | /tmp/ 27 | -------------------------------------------------------------------------------- /offerings/2023/projects/factorial/README.md: -------------------------------------------------------------------------------- 1 | # Factorial 2 | 3 | **TODO: Add description** 4 | 5 | ## Installation 6 | 7 | If [available in Hex](https://hex.pm/docs/publish), the package can be installed 8 | by adding `factorial` to your list of dependencies in `mix.exs`: 9 | 10 | ```elixir 11 | def deps do 12 | [ 13 | {:factorial, "~> 0.1.0"} 14 | ] 15 | end 16 | ``` 17 | 18 | Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) 19 | and published on [HexDocs](https://hexdocs.pm). Once published, the docs can 20 | be found at . 21 | 22 | -------------------------------------------------------------------------------- /offerings/2023/projects/factorial/factorial: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adolfont/caes005-introduction-to-functional-programming/a9b6de4534585a632113a1d960a9102c0715fb5c/offerings/2023/projects/factorial/factorial -------------------------------------------------------------------------------- /offerings/2023/projects/factorial/lib/calculator.ex: -------------------------------------------------------------------------------- 1 | defmodule Calculator do 2 | def fac(0), do: 1 3 | def fac(n), do: n * fac(n - 1) 4 | end 5 | -------------------------------------------------------------------------------- /offerings/2023/projects/factorial/lib/factorial.ex: -------------------------------------------------------------------------------- 1 | defmodule Factorial do 2 | def main([string]) do 3 | case Integer.parse(string) do 4 | {number, ""} when number >= 0 -> 5 | IO.puts("factorial #{number} = #{Calculator.fac(number)}") 6 | possible_loop() 7 | 8 | :error -> 9 | IO.puts("Your input must be an integer number larger or equal to zero!") 10 | possible_loop() 11 | 12 | _ -> 13 | IO.puts("Your input must be an integer number larger or equal to zero!") 14 | possible_loop() 15 | end 16 | end 17 | 18 | def main(_) do 19 | usage() 20 | end 21 | 22 | defp usage() do 23 | IO.puts("usage: factorial integer") 24 | end 25 | 26 | defp possible_loop() do 27 | choice = String.trim(IO.gets("Do you want to continue? (Y/N): ")) 28 | 29 | case choice do 30 | "Y" -> 31 | another_factorial() 32 | 33 | _ -> 34 | IO.puts("Bye!") 35 | exit(:normal) 36 | end 37 | end 38 | 39 | defp another_factorial() do 40 | possible_number = String.trim(IO.gets("Type another number: ")) 41 | main([possible_number]) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /offerings/2023/projects/factorial/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Factorial.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :factorial, 7 | version: "0.1.0", 8 | elixir: "~> 1.15", 9 | start_permanent: Mix.env() == :prod, 10 | deps: deps(), 11 | ## THIS LINE WAS ADDED 12 | escript: escript() 13 | ] 14 | end 15 | 16 | defp escript do 17 | ## THIS LINE (and the Factorial module) were ADDED 18 | [main_module: Factorial] 19 | end 20 | 21 | # Run "mix help compile.app" to learn about applications. 22 | def application do 23 | [ 24 | extra_applications: [:logger] 25 | ] 26 | end 27 | 28 | # Run "mix help deps" to learn about dependencies. 29 | defp deps do 30 | [ 31 | # {:dep_from_hexpm, "~> 0.3.0"}, 32 | # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} 33 | ] 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /offerings/2023/projects/factorial/test/factorial_test.exs: -------------------------------------------------------------------------------- 1 | defmodule FactorialTest do 2 | use ExUnit.Case 3 | end 4 | -------------------------------------------------------------------------------- /offerings/2023/projects/factorial/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /offerings/2023/projects/pbt/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /offerings/2023/projects/pbt/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | pbt-*.tar 24 | 25 | # Temporary files, for example, from tests. 26 | /tmp/ 27 | -------------------------------------------------------------------------------- /offerings/2023/projects/pbt/README.md: -------------------------------------------------------------------------------- 1 | # Pbt 2 | 3 | **TODO: Add description** 4 | 5 | ## Installation 6 | 7 | If [available in Hex](https://hex.pm/docs/publish), the package can be installed 8 | by adding `pbt` to your list of dependencies in `mix.exs`: 9 | 10 | ```elixir 11 | def deps do 12 | [ 13 | {:pbt, "~> 0.1.0"} 14 | ] 15 | end 16 | ``` 17 | 18 | Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) 19 | and published on [HexDocs](https://hexdocs.pm). Once published, the docs can 20 | be found at . 21 | 22 | -------------------------------------------------------------------------------- /offerings/2023/projects/pbt/lib/pbt.ex: -------------------------------------------------------------------------------- 1 | defmodule Pbt do 2 | @moduledoc """ 3 | Documentation for `Pbt`. 4 | """ 5 | 6 | # @doc """ 7 | # Hello world. 8 | 9 | # ## Examples 10 | 11 | # iex> Pbt.hello() 12 | # :world 13 | 14 | # """ 15 | def hello(start, ending) do 16 | hd(Enum.shuffle(start..ending)) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /offerings/2023/projects/pbt/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Pbt.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :pbt, 7 | version: "0.1.0", 8 | elixir: "~> 1.15", 9 | start_permanent: Mix.env() == :prod, 10 | deps: deps() 11 | ] 12 | end 13 | 14 | # Run "mix help compile.app" to learn about applications. 15 | def application do 16 | [ 17 | extra_applications: [:logger] 18 | ] 19 | end 20 | 21 | # Run "mix help deps" to learn about dependencies. 22 | defp deps do 23 | [ 24 | {:propcheck, "~> 1.4", only: [:test, :dev]} 25 | 26 | # {:dep_from_hexpm, "~> 0.3.0"}, 27 | # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} 28 | ] 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /offerings/2023/projects/pbt/mix.lock: -------------------------------------------------------------------------------- 1 | %{ 2 | "libgraph": {:hex, :libgraph, "0.16.0", "3936f3eca6ef826e08880230f806bfea13193e49bf153f93edcf0239d4fd1d07", [:mix], [], "hexpm", "41ca92240e8a4138c30a7e06466acc709b0cbb795c643e9e17174a178982d6bf"}, 3 | "propcheck": {:hex, :propcheck, "1.4.1", "c12908dbe6f572032928548089b34ff9d40672d5d70f1562e3a9e9058d226cc9", [:mix], [{:libgraph, "~> 0.13", [hex: :libgraph, repo: "hexpm", optional: false]}, {:proper, "~> 1.4", [hex: :proper, repo: "hexpm", optional: false]}], "hexpm", "e1b088f574785c3c7e864da16f39082d5599b3aaf89086d3f9be6adb54464b19"}, 4 | "proper": {:hex, :proper, "1.4.0", "89a44b8c39d28bb9b4be8e4d715d534905b325470f2e0ec5e004d12484a79434", [:rebar3], [], "hexpm", "18285842185bd33efbda97d134a5cb5a0884384db36119fee0e3cfa488568cbb"}, 5 | } 6 | -------------------------------------------------------------------------------- /offerings/2023/projects/pbt/test/pbt_props_test.exs: -------------------------------------------------------------------------------- 1 | defmodule PbtPropsTest do 2 | use ExUnit.Case 3 | use PropCheck 4 | 5 | 6 | # doctest Pbt 7 | 8 | # test "greets the world" do 9 | # assert Pbt.hello() == :world 10 | # end 11 | 12 | property "Hello is between two numbers", [:verbose, numtests: 1000] do 13 | forall p <- integer() do 14 | IO.puts "p is #{p}" 15 | Pbt.hello(p,p+1000) > p 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /offerings/2023/projects/pbt/test/pbt_test.exs: -------------------------------------------------------------------------------- 1 | defmodule PbtTest do 2 | use ExUnit.Case 3 | doctest Pbt 4 | 5 | test "Sorts a number between 1 and 100" do 6 | number = Pbt.hello(1, 100) 7 | assert (number > 0) and (number < 101) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /offerings/2023/projects/pbt/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /offerings/2023/projects/tasks/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /offerings/2023/projects/tasks/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | tasks-*.tar 24 | 25 | # Temporary files, for example, from tests. 26 | /tmp/ 27 | -------------------------------------------------------------------------------- /offerings/2023/projects/tasks/README.md: -------------------------------------------------------------------------------- 1 | # Tasks 2 | 3 | In order to play, go to the folder (having Elixir installed) and do: 4 | 5 | $ mix play 6 | 7 | -------------------------------------------------------------------------------- /offerings/2023/projects/tasks/lib/mix/tasks/play.ex: -------------------------------------------------------------------------------- 1 | defmodule Mix.Tasks.Play do 2 | @moduledoc "The hello mix task: `mix help hello`" 3 | use Mix.Task 4 | 5 | @shortdoc "Simply calls the Tasks.play/0 function." 6 | def run(_) do 7 | # calling our Hello.say() function from earlier 8 | Tasks.play() 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /offerings/2023/projects/tasks/lib/tasks.ex: -------------------------------------------------------------------------------- 1 | defmodule Tasks do 2 | def play do 3 | IO.puts("Starting a game") 4 | 5 | player_1_name = String.trim(IO.gets("Tell me you name: ")) 6 | 7 | IO.puts("Welcome, #{player_1_name}!") 8 | 9 | play("10", player_1_name) 10 | end 11 | 12 | defp play(number, name) do 13 | choice = String.trim(IO.gets("What's the number: ")) 14 | 15 | if choice == number do 16 | IO.puts("Congrats, #{name}! That's the right number!") 17 | exit(:normal) 18 | else 19 | IO.puts("Sorry, #{name}! Please try again!") 20 | IO.puts "X___\n" <> "____\n" <> "____\n" <> "___O" 21 | play(number, name) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /offerings/2023/projects/tasks/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Tasks.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :tasks, 7 | version: "0.1.0", 8 | elixir: "~> 1.15", 9 | start_permanent: Mix.env() == :prod, 10 | deps: deps() 11 | ] 12 | end 13 | 14 | # Run "mix help compile.app" to learn about applications. 15 | def application do 16 | [ 17 | extra_applications: [:logger] 18 | ] 19 | end 20 | 21 | # Run "mix help deps" to learn about dependencies. 22 | defp deps do 23 | [ 24 | # {:dep_from_hexpm, "~> 0.3.0"}, 25 | # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} 26 | ] 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /offerings/2023/projects/tasks/test/tasks_test.exs: -------------------------------------------------------------------------------- 1 | defmodule TasksTest do 2 | use ExUnit.Case 3 | doctest Tasks 4 | 5 | 6 | end 7 | -------------------------------------------------------------------------------- /offerings/2023/projects/tasks/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /offerings/2023/projects/tictactoe/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /offerings/2023/projects/tictactoe/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | tictactoe-*.tar 24 | 25 | # Temporary files, for example, from tests. 26 | /tmp/ 27 | -------------------------------------------------------------------------------- /offerings/2023/projects/tictactoe/README.md: -------------------------------------------------------------------------------- 1 | # Tictactoe 2 | 3 | ["Tic-tac-toe (American English), noughts and crosses (Commonwealth English), or Xs and Os (Canadian or Irish English) is a paper-and-pencil game for two players who take turns marking the spaces in a three-by-three grid with X or O."](https://en.wikipedia.org/wiki/Tic-tac-toe) 4 | 5 | ## Installation 6 | 7 | If [available in Hex](https://hex.pm/docs/publish), the package can be installed 8 | by adding `tictactoe` to your list of dependencies in `mix.exs`: 9 | 10 | ```elixir 11 | def deps do 12 | [ 13 | {:tictactoe, "~> 0.1.0"} 14 | ] 15 | end 16 | ``` 17 | 18 | Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) 19 | and published on [HexDocs](https://hexdocs.pm). Once published, the docs can 20 | be found at . 21 | 22 | -------------------------------------------------------------------------------- /offerings/2023/projects/tictactoe/lib/tictactoe.ex: -------------------------------------------------------------------------------- 1 | defmodule TicTacToe do 2 | @moduledoc """ 3 | Documentation for `TicTacToe`. 4 | """ 5 | 6 | defstruct symbols: [:x, :o], board: [:e, :e, :e, :e, :e, :e, :e, :e, :e] 7 | 8 | @doc """ 9 | The symbols of tic-tac-toe are :x and :o 10 | 11 | ## Examples 12 | 13 | iex> TicTacToe.new() 14 | %TicTacToe{symbols: [:x, :o]} 15 | 16 | """ 17 | 18 | # CRC pattern - constructor(s), reducer(s), converter(s) 19 | 20 | def new() do 21 | %__MODULE__{} 22 | end 23 | 24 | def play(game = %TicTacToe{board: _b}, symbol, _line, _column) do 25 | new_board = [symbol, :e, :e, :e, :e, :e, :e, :e, :e] 26 | 27 | # https://hexdocs.pm/elixir/1.15.7/List.html#replace_at/3 28 | 29 | %{game | board: new_board} 30 | end 31 | 32 | end 33 | -------------------------------------------------------------------------------- /offerings/2023/projects/tictactoe/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Tictactoe.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :tictactoe, 7 | version: "0.1.0", 8 | elixir: "~> 1.15", 9 | start_permanent: Mix.env() == :prod, 10 | deps: deps() 11 | ] 12 | end 13 | 14 | # Run "mix help compile.app" to learn about applications. 15 | def application do 16 | [ 17 | extra_applications: [:logger] 18 | ] 19 | end 20 | 21 | # Run "mix help deps" to learn about dependencies. 22 | defp deps do 23 | [ 24 | # {:dep_from_hexpm, "~> 0.3.0"}, 25 | # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} 26 | ] 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /offerings/2023/projects/tictactoe/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /offerings/2023/projects/tictactoe/test/tictactoe_test.exs: -------------------------------------------------------------------------------- 1 | defmodule TicTacToeTest do 2 | use ExUnit.Case 3 | doctest TicTacToe 4 | 5 | test "Put an x on position 1,1" do 6 | game = TicTacToe.new() 7 | 8 | assert TicTacToe.play(game, :x, 1, 1) == 9 | %TicTacToe{board: [:x, :e, :e, 10 | :e, :e, :e, 11 | :e, :e, :e]} 12 | end 13 | test "Put an o on position 1,1" do 14 | game = TicTacToe.new() 15 | 16 | assert TicTacToe.play(game, :o, 1, 1) == 17 | %TicTacToe{board: [:o, :e, :e, 18 | :e, :e, :e, 19 | :e, :e, :e]} 20 | end 21 | test "Put an x on position 2,2" do 22 | game = TicTacToe.new() 23 | 24 | assert TicTacToe.play(game, :x, 2, 2) == 25 | %TicTacToe{board: [:e, :e, :e, 26 | :e, :x, :e, 27 | :e, :e, :e]} 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /offerings/2023/scripts/01_simple/01.exs: -------------------------------------------------------------------------------- 1 | # Running an Elixir File as a Script https://thinkingelixir.com/2019-04-running-an-elixir-file-as-a-script/ 2 | 3 | # elixir 01.exs 4 | 5 | "Hello, world!" 6 | -------------------------------------------------------------------------------- /offerings/2023/scripts/01_simple/02.exs: -------------------------------------------------------------------------------- 1 | IO.puts "Hello, world!" 2 | -------------------------------------------------------------------------------- /offerings/2023/scripts/01_simple/03.exs: -------------------------------------------------------------------------------- 1 | name = IO.gets("What's your name? ") 2 | 3 | IO.puts "Hello, #{name}!" 4 | -------------------------------------------------------------------------------- /offerings/2023/scripts/01_simple/04.exs: -------------------------------------------------------------------------------- 1 | name = IO.gets("What's your name? ") 2 | 3 | trimmed_name = String.trim(name) 4 | 5 | IO.puts "Hello, #{trimmed_name}!" 6 | -------------------------------------------------------------------------------- /offerings/2023/scripts/02_factorial/01.exs: -------------------------------------------------------------------------------- 1 | # Recursive anonymous function 2 | # https://chat.openai.com/c/ffec3ccf-61e3-423e-be8c-aaff49471d83 3 | # https://sharno.medium.com/an-anonymous-recursive-function-in-elixir-2fe1e5e89e59 4 | # https://levelup.gitconnected.com/implementing-recursion-with-the-y-combinator-in-any-language-9e83fa369ca 5 | 6 | factorial_aux = fn 7 | 0, _ -> 1 8 | n, f when is_integer(n) and n > 0 -> n * f.(n - 1, f) 9 | _, _ -> "Input must be a non-negative integer" 10 | end 11 | 12 | factorial = fn n -> 13 | factorial_aux.(n, factorial_aux) 14 | end 15 | 16 | IO.write("Type an integer number: ") 17 | input = IO.gets("") 18 | 19 | IO.puts("You entered: #{input}") 20 | 21 | case Integer.parse(String.trim(input)) do 22 | {integer_result, ""} -> 23 | IO.puts("The factorial of #{integer_result} is #{factorial.(integer_result)}") 24 | 25 | _ -> 26 | IO.puts("Invalid integer format.") 27 | end 28 | -------------------------------------------------------------------------------- /offerings/2023/scripts/02_factorial/02.exs: -------------------------------------------------------------------------------- 1 | # Fixed-point combinator https://en.wikipedia.org/wiki/Fixed-point_combinator 2 | 3 | 4 | y = fn f -> 5 | (fn x -> f.(fn v -> x.(x).(v) end) end) 6 | .(fn x -> f.(fn v -> x.(x).(v) end) end) 7 | end 8 | 9 | factorial = y.(fn f -> 10 | fn 11 | 0 -> 1 12 | n -> n * f.(n - 1) 13 | end 14 | end) 15 | 16 | 17 | 18 | IO.write("Type an integer number: ") 19 | input = IO.gets("") 20 | 21 | IO.puts("You entered: #{input}") 22 | 23 | case Integer.parse(String.trim(input)) do 24 | {integer_result, ""} -> 25 | IO.puts("The factorial of #{integer_result} is #{factorial.(integer_result)}") 26 | 27 | _ -> 28 | IO.puts("Invalid integer format.") 29 | end 30 | -------------------------------------------------------------------------------- /offerings/2023/scripts/02_factorial/03.exs: -------------------------------------------------------------------------------- 1 | defmodule Factorial do 2 | 3 | def of(0), do: 1 4 | def of(1), do: 1 5 | def of(n) when is_integer(n) and n>1 do 6 | n * of(n-1) 7 | end 8 | end 9 | 10 | # defmodule AnotherModule do 11 | # def f(), do: 5 12 | # end 13 | 14 | 15 | 16 | 17 | IO.write("Type an integer number: ") 18 | input = IO.gets("") 19 | 20 | IO.puts("You entered: #{input}") 21 | 22 | case Integer.parse(String.trim(input)) do 23 | {integer_result, ""} -> 24 | IO.puts("The factorial of #{integer_result} is #{Factorial.of(integer_result)}") 25 | 26 | _ -> 27 | IO.puts("Invalid integer format.") 28 | end 29 | 30 | # IO.puts AnotherModule.f() 31 | -------------------------------------------------------------------------------- /offerings/2023/scripts/02_factorial/04.exs: -------------------------------------------------------------------------------- 1 | defmodule Factorial do 2 | def of(0), do: 1 3 | def of(1), do: 1 4 | 5 | def of(n) when is_integer(n) and n > 1 do 6 | n * of(n - 1) 7 | end 8 | 9 | def interact() do 10 | IO.write("Type an integer number: ") 11 | input = IO.gets("") 12 | 13 | IO.puts("You entered: #{input}") 14 | 15 | case Integer.parse(String.trim(input)) do 16 | {integer_result, ""} -> 17 | IO.puts("The factorial of #{integer_result} is #{Factorial.of(integer_result)}") 18 | 19 | _ -> 20 | IO.puts("Invalid integer format.") 21 | end 22 | end 23 | end 24 | 25 | Factorial.interact() 26 | -------------------------------------------------------------------------------- /offerings/2023/scripts/02_factorial/05.exs: -------------------------------------------------------------------------------- 1 | defmodule Factorial do 2 | def of(0), do: 1 3 | def of(1), do: 1 4 | 5 | def of(n) when is_integer(n) and n > 1 do 6 | n * of(n - 1) 7 | end 8 | 9 | def interface() do 10 | IO.write("Type an integer and non-negative number: ") 11 | input = IO.gets("") 12 | 13 | IO.puts("You entered: #{input}") 14 | 15 | case Integer.parse(String.trim(input)) do 16 | {integer_result, ""} -> 17 | show_message(integer_result) 18 | 19 | :error -> 20 | IO.puts("Invalid integer format.\n") 21 | end 22 | 23 | interface() 24 | end 25 | 26 | def show_message(value) when value >= 0 do 27 | IO.puts("The factorial of #{value} is #{Factorial.of(value)}. \n") 28 | end 29 | 30 | def show_message(-1) do 31 | IO.puts("Bye. \n") 32 | exit(:normal) 33 | end 34 | 35 | def show_message(_) do 36 | IO.puts("Error! It should have been an integer and non-negative number.\n") 37 | end 38 | end 39 | 40 | Factorial.interface() 41 | -------------------------------------------------------------------------------- /offerings/2023/scripts/03_mix_install/01.exs: -------------------------------------------------------------------------------- 1 | # https://tmr08c.github.io/2021/05/using-mix-install/ 2 | Mix.install([:jason]) 3 | 4 | 5 | IO.puts(Jason.encode!(%{hello: :world})) 6 | -------------------------------------------------------------------------------- /offerings/2023/scripts/03_mix_install/02.exs: -------------------------------------------------------------------------------- 1 | Mix.install([:propcheck]) 2 | 3 | 4 | IO.puts("Hi") 5 | -------------------------------------------------------------------------------- /offerings/2023/tasks/exercism_task.md: -------------------------------------------------------------------------------- 1 | # Exercism task 2 | 3 | Add to your private repo shared with me the code for all the Exercism exercises you solved and also a screenshot like this one: 4 | 5 | ![screenshot of Elixir track](image.png) 6 | 7 | The screenshot should have your photo (to right side) and a checkmark for all the problems you solved. 8 | 9 | You should solve at least 5 Exercism exercises. -------------------------------------------------------------------------------- /offerings/2023/tasks/game_task.md: -------------------------------------------------------------------------------- 1 | # Game Task 2 | 3 | You will implement a game called ["TIC-TAC-TOE: 4 IN A ROW!"](https://emu.edu/gaming-hub/tic-tac-toe). 4 | 5 | 6 | ## Description 7 | 8 | "TIC-TAC-TOE: 4 IN A ROW!" is a unique twist on the classic Tic-Tac-Toe game. In this version, players are challenged to achieve a victory by connecting four of their pieces in a row. The game provides an engaging and strategic experience, where players must carefully plan their moves to outsmart their opponent and form a winning combination. 9 | 10 | One distinctive feature of this version is the limitation of only four pieces for each player. Once a player places their fifth piece on the board, the oldest piece will disappear. This introduces an additional layer of strategy, requiring players to not only focus on their current moves but also to consider the consequences of their earlier placements. 11 | 12 | The objective remains the same – be the first to connect four pieces horizontally, vertically, or diagonally. With the dynamic element of disappearing pieces, players must think ahead and adapt their tactics throughout the game. This variation adds a fresh and exciting dimension to the traditional Tic-Tac-Toe, making it a compelling and fast-paced challenge for players of all ages. 13 | 14 | 15 | ## Instructions 16 | 17 | Your project should be inside your private repo shared with me. 18 | 19 | You can create a [Mix Task](https://elixirschool.com/en/lessons/intermediate/mix_tasks) or an [escript](https://elixirschool.com/en/lessons/intermediate/escripts) so that the game can be played on a terminal. See my sample [tasks] project(https://github.com/adolfont/caes005-introduction-to-functional-programming/tree/main/offerings/2023/projects/tasks) or my [factorial](https://github.com/adolfont/caes005-introduction-to-functional-programming/tree/main/offerings/2023/projects/factorial) project. 20 | 21 | You do not have to implement the "computer plays". You can play like this: 22 | 23 | ``` 24 | $ mix play // or ./name_of_the_escript 25 | What's Player 1 name? 26 | Adolfo // you type 27 | What's Player 2 name? 28 | Gustavo // you type 29 | OK, let's start the game! 30 | The current board is: 31 | _ _ _ _ 32 | _ _ _ _ 33 | _ _ _ _ 34 | _ _ _ _ 35 | Adolfo, choose an empty position between (1,1) and (4,4): 36 | (1,2) // you type 37 | The current board is: 38 | _ X _ _ 39 | _ _ _ _ 40 | _ _ _ _ 41 | _ _ _ _ 42 | Gustavo, choose an empty position between (1,1) and (4,4): 43 | (1,2) // you type 44 | Gustavo, you should have chosen an empty position! Position (1,2) is not empty. 45 | Gustavo, choose an empty position between (1,1) and (4,4): 46 | (5,5) // you type 47 | Gustavo, you should have chosen a position between (1,1) and (4,4)! Position (5,5) is out of bounds. 48 | Gustavo, choose an empty position between (1,1) and (4,4): 49 | (2,2) // you type 50 | The current board is: 51 | _ X _ _ 52 | _ O _ _ 53 | _ _ _ _ 54 | _ _ _ _ 55 | Adolfo, choose an empty position between (1,1) and (4,4): 56 | (maria,joaquina) // you type 57 | Adolfo, you should have chosen a position between (1,1) and (4,4)! Position (maria,joaquina) is not a valid position. 58 | Adolfo, choose an empty position between (1,1) and (4,4): 59 | (1,1) // you type 60 | The current board is: 61 | X X _ _ 62 | _ O _ _ 63 | _ _ _ _ 64 | _ _ _ _ 65 | ``` 66 | 67 | and so on. 68 | 69 | After Adolfo has played, in this order: 70 | ``` 71 | ... 72 | (3,1) 73 | (1,1) 74 | (1,2) 75 | (1,3) 76 | ``` 77 | 78 | it is time for Adolfo to play again. 79 | 80 | ``` 81 | The current board is: 82 | X X X _ 83 | _ O O _ 84 | X O O _ 85 | _ _ _ _ 86 | Adolfo, choose an empty position between (1,1) and (4,4): 87 | (1,4) // you type 88 | Congrats, Adolfo! You won! 89 | // end of the game 90 | ``` 91 | 92 | 93 | -------------------------------------------------------------------------------- /offerings/2023/tasks/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adolfont/caes005-introduction-to-functional-programming/a9b6de4534585a632113a1d960a9102c0715fb5c/offerings/2023/tasks/image.png -------------------------------------------------------------------------------- /offerings/2023/tasks/knowledge_items.md: -------------------------------------------------------------------------------- 1 | # Task: Knowledge Exchange Review 2 | 3 | ## Objective: 4 | This task aims to enhance your understanding of functional programming concepts through reviewing and analyzing knowledge exchange items. 5 | 6 | ## Instructions: 7 | 8 | 1. **Selection of Items:** 9 | - Choose three knowledge exchange items related to functional programming. Examples include a YouTube video (minimum 10 minutes), a podcast episode (minimum 30 minutes), or a blog post (minimum 500 words). 10 | - Email the selected items to me (adolfo at utfpr.edu.br) for approval before proceeding. 11 | 12 | 2. **Approval Process:** 13 | - I will review the proposed items and provide feedback on their relevance to the course. 14 | - If approved, you will receive confirmation to proceed with the review. 15 | 16 | 3. **Review and Analysis:** 17 | - For each approved item, write a paragraph summarizing the key concepts discussed. 18 | - Analyze how the content contributes to understanding functional programming principles. 19 | - Identify any practical examples or applications mentioned. 20 | 21 | 4. **Reflection:** 22 | - Share your personal insights gained from each knowledge exchange item. 23 | - Reflect on how the content aligns with or challenges concepts learned in the Introduction to Functional Programming class. 24 | 25 | 5. **Submission:** 26 | - Compile the paragraphs into a document and submit it by the specified deadline. 27 | 28 | ## How to submit? 29 | 30 | - Add a markdown file to your private repo shared with me. 31 | 32 | ## Grading Criteria: 33 | - Relevance of selected items to functional programming. 34 | - Quality of summarization and analysis. 35 | - Demonstration of understanding and application of functional programming concepts. 36 | - Thoughtful reflection on the content. 37 | 38 | ## Submission Deadline: 39 | 40 | - December 19th, 2023 -------------------------------------------------------------------------------- /offerings/2023/tasks/paper_task.md: -------------------------------------------------------------------------------- 1 | # Paper task 2 | 3 | // para 2024, colocar no repositório 4 | 5 | ## Subtask 1 6 | 7 | 8 | Choose a paper related to functional programming from one of the following sources: 9 | 10 | - [Journal of Functional Programming](https://scholar.google.com/citations?hl=en&view_op=list_hcore&venue=yzdEqktbJzoJ.2023) 11 | - [ICFP: International Conference on Functional Programming](https://dl.acm.org/conference/icfp/proceedings) - Not from the workshops 12 | - [Journal of Computer Languages](https://www.sciencedirect.com/journal/journal-of-computer-languages) 13 | - [The Programming Journal](https://programming-journal.org/) 14 | 15 | ## Subtask 2 16 | 17 | Send an e-mail to adolfo @ utfpr.edu.br asking if you can use that paper. 18 | 19 | ## Subtask 3 20 | 21 | If the paper you chose was approved by me, fill [this form](https://forms.gle/BFEPnrNNpXUaeYf6A). 22 | -------------------------------------------------------------------------------- /offerings/2024/Livebook/20241009/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/livebook-dev/livebook:0.14.4 2 | 3 | # Apps configuration 4 | ENV LIVEBOOK_APPS_PATH "/apps" 5 | ENV LIVEBOOK_APPS_PATH_WARMUP "manual" 6 | ENV LIVEBOOK_APPS_PATH_HUB_ID "personal-hub" 7 | 8 | # Notebook 9 | COPY app.livemd /apps/ 10 | 11 | # Cache apps setup at build time 12 | RUN /app/bin/warmup_apps 13 | -------------------------------------------------------------------------------- /offerings/2024/Livebook/20241009/receiver.livemd: -------------------------------------------------------------------------------- 1 | # Commmunicating Processes - The Receiver 2 | 3 | ## 1. What is the name of this node? 4 | 5 | ```elixir 6 | Node.self() 7 | 8 | ``` 9 | 10 | You will have to add the name of this node to the other notebook. 11 | 12 | ## 4. Identifying the Sender Node 13 | 14 | ```elixir 15 | # sender_node = "" 16 | 17 | sender_node = :"livebook_7louvomv--3732fjg3@127.0.0.1" 18 | 19 | 20 | ``` 21 | 22 | ## 5. Connecting to other node 23 | 24 | ```elixir 25 | Node.connect(sender_node) 26 | ``` 27 | 28 | ## 6. Creating a process 29 | 30 | ```elixir 31 | pid = spawn(fn -> receive do msg -> IO.inspect(msg) end end) 32 | ``` 33 | 34 | ## 7. Registering a process 35 | 36 | ```elixir 37 | Process.register(pid, :receiver) 38 | ``` 39 | 40 | ## 8. Receiving a message 41 | 42 | ```elixir 43 | IO.puts "Waiting" 44 | ``` 45 | -------------------------------------------------------------------------------- /offerings/2024/Livebook/20241009/sender.livemd: -------------------------------------------------------------------------------- 1 | # Commmunicating Processes - The Sender 2 | 3 | ## 2. What is the name of this node? 4 | 5 | ```elixir 6 | Node.self() 7 | ``` 8 | 9 | You will have to add the name of this node to the other notebook. 10 | 11 | ## 3. Identifying the Receiver Node 12 | 13 | ```elixir 14 | # receiver_node = "" 15 | 16 | receiver_node = :"livebook_7louvomv--255mv4r6@127.0.0.1" 17 | 18 | ``` 19 | 20 | ## 9. Sending a message 21 | 22 | ```elixir 23 | send {:receiver, receiver_node}, :"Hi, this is the message from the sender!" 24 | ``` 25 | -------------------------------------------------------------------------------- /offerings/2024/Livebook/20241023/aniversario.livemd: -------------------------------------------------------------------------------- 1 | # Aniversário 2 | 3 | ```elixir 4 | Mix.install([ 5 | {:kino, "~> 0.11.0"}, 6 | {:jason, "~> 1.4"} 7 | ]) 8 | ``` 9 | 10 | ## Módulo Aniversario 11 | 12 | ```elixir 13 | defmodule Aniversario do 14 | def celebrar(nome) do 15 | fogos = "🎆" 16 | bolo = "🎂" 17 | festa = "🎉" 18 | presente = "🎁" 19 | estrelas = "✨" 20 | baloes = "🎈" 21 | 22 | mensagem = """ 23 | #{String.duplicate(fogos, 3)}#{String.duplicate(baloes, 2)} FELIZ ANIVERSÁRIO #{nome}! #{String.duplicate(baloes, 2)}#{String.duplicate(fogos, 3)} 24 | 25 | #{estrelas} Que seu dia seja tão especial quanto você! #{estrelas} 26 | #{bolo} Muita saúde, paz e realizações! #{bolo} 27 | #{presente} Que todos os seus sonhos se realizem! #{presente} 28 | #{festa} Aproveite seu dia ao máximo! #{festa} 29 | """ 30 | 31 | IO.puts mensagem 32 | 33 | # Função para gerar fogos de artifício animados 34 | 1..5 35 | |> Enum.each(fn _ -> 36 | IO.puts String.duplicate("#{fogos}#{estrelas}", 5) 37 | Process.sleep(500) 38 | end) 39 | end 40 | end 41 | 42 | ``` 43 | 44 | ```elixir 45 | 46 | nome = "(Nome da Pessoa aqui)" 47 | 48 | # Executando a celebração 49 | Aniversario.celebrar(nome) 50 | ``` 51 | -------------------------------------------------------------------------------- /offerings/2024/Livebook/20241023/app.livemd: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Meu primeiro aplicativo 4 | 5 | ```elixir 6 | Mix.install([ 7 | {:kino, "~> 0.10.0"} 8 | ]) 9 | ``` 10 | 11 | ## Frame 12 | 13 | ```elixir 14 | frame = Kino.Frame.new() 15 | ``` 16 | 17 | ```elixir 18 | name = Kino.Input.text("Nome") 19 | message = Kino.Input.textarea("Mensagem") 20 | 21 | form = 22 | Kino.Control.form( 23 | [name: name, message: message], 24 | submit: "Envie", 25 | reset_on_submit: [:message] 26 | ) 27 | ``` 28 | 29 | ```elixir 30 | Kino.listen( 31 | form, 32 | fn %{data: %{name: name, message: message}, origin: origin} -> 33 | if name != "" and message != "" do 34 | content = Kino.Markdown.new("**#{name}:** #{message}") 35 | Kino.Frame.append(frame, content) 36 | else 37 | content = Kino.Markdown.new("**Nome e mensagem são obrigatórios!**") 38 | Kino.Frame.append(frame, content, to: origin) 39 | end 40 | end 41 | ) 42 | ``` 43 | -------------------------------------------------------------------------------- /offerings/2024/Livebook/20241108/nx_tensors.livemd: -------------------------------------------------------------------------------- 1 | # Nx Tensors 2 | 3 | ```elixir 4 | Mix.install([ 5 | {:nx, "~> 0.9.1"} 6 | ]) 7 | ``` 8 | 9 | ## Creating a tensor 10 | 11 | ```elixir 12 | tensor = Nx.tensor([1, 2, 3, 4]) 13 | 14 | ``` 15 | 16 | ## Applying a transformation that updates the tensor 17 | 18 | ```elixir 19 | updated_tensor = Nx.add(tensor, 10) 20 | 21 | ``` 22 | 23 | ## Showing the updated tensor 24 | 25 | ```elixir 26 | IO.inspect(updated_tensor) # Updated tensor 27 | 28 | ``` 29 | 30 | ## Showing the original tensor 31 | 32 | ```elixir 33 | IO.inspect(tensor) # Original tensor 34 | 35 | ``` 36 | 37 | ## Another tensor 38 | 39 | ```elixir 40 | another_tensor = Nx.tensor([[1, 2, 3], [4,5,6], [7,8,9]]) 41 | 42 | ``` 43 | 44 | ```elixir 45 | Nx.add(another_tensor, 3) 46 | ``` 47 | 48 | ```elixir 49 | [[0,1], [2, 3]] 50 | |> Nx.tensor() 51 | |> Nx.all() 52 | ``` 53 | -------------------------------------------------------------------------------- /offerings/2024/Livebook/20241114/estruturas_de_controle.livemd: -------------------------------------------------------------------------------- 1 | # Estruturas de Controle 2 | 3 | ## if 4 | 5 | ```elixir 6 | if true do 7 | "A" 8 | end 9 | ``` 10 | 11 | ```elixir 12 | if false do 13 | "A" 14 | end 15 | ``` 16 | 17 | ```elixir 18 | if true do 19 | "A" 20 | else 21 | "B" 22 | end 23 | ``` 24 | 25 | ```elixir 26 | if false do 27 | "A" 28 | else 29 | "B" 30 | end 31 | ``` 32 | 33 | ```elixir 34 | if true, do: "A", else: "B" 35 | ``` 36 | 37 | ```elixir 38 | if false, do: "A", else: "B" 39 | ``` 40 | 41 | ```elixir 42 | if nil, do: "A", else: "B" 43 | ``` 44 | 45 | ```elixir 46 | if 0, do: "A", else: "B" 47 | ``` 48 | 49 | ```elixir 50 | x = 10 51 | y = 11 52 | 53 | if x > y do 54 | "x é o maior" 55 | else 56 | "y é o maior" 57 | end 58 | ``` 59 | 60 | ```elixir 61 | x = 12 62 | y = 11 63 | 64 | if x > y do 65 | "x é o maior" 66 | else 67 | "y é o maior" 68 | end 69 | ``` 70 | 71 | ```elixir 72 | x = 10 73 | y = 11 74 | z = "Adolfo" 75 | w = :maria 76 | 77 | if (x == 10 and w == "Adolfo") do 78 | "Adolfo é o maior" 79 | else 80 | if z > 35 do 81 | "Adolfo perdeu" 82 | else 83 | if is_atom(w) do 84 | "w é um átomo" 85 | end 86 | end 87 | end 88 | ``` 89 | 90 | ## case 91 | 92 | ```elixir 93 | # {:ok, 35} ou {:error, :not_a_number} 94 | 95 | defmodule M do 96 | def divide(x, y) when is_number(x) and is_number(y) do 97 | if y != 0 do 98 | {:ok, x/y} 99 | else 100 | {:error, :not_a_number} 101 | end 102 | end 103 | def divide(_x, _y), do: {:error, :argument_not_number} 104 | end 105 | ``` 106 | 107 | ```elixir 108 | M.divide(2,0) 109 | ``` 110 | 111 | ```elixir 112 | M.divide(234, 33) 113 | ``` 114 | 115 | ```elixir 116 | M.divide("Adolfo", :gustavo) 117 | ``` 118 | 119 | ```elixir 120 | x = 100 121 | y = 1 122 | 123 | case M.divide(x,y) do 124 | {:ok, result} -> result 125 | end 126 | ``` 127 | 128 | ```elixir 129 | x = 100 130 | y = 0 131 | 132 | case M.divide(x,y) do 133 | {:ok, result} -> result 134 | {:error, :not_a_number} -> "Erro na divisão!" 135 | end 136 | ``` 137 | 138 | ```elixir 139 | x = "100" 140 | y = "1" 141 | 142 | case M.divide(x,y) do 143 | {:ok, result} -> result 144 | {:error, :not_a_number} -> "Erro divisão por zero!" 145 | {:error, :argument_not_number} -> "Ao menos um dos argumentos não é um número!" 146 | end 147 | ``` 148 | 149 | ```elixir 150 | x = 100 151 | y = :A10 152 | 153 | case M.divide(x,y) do 154 | {:ok, result} -> "O resultado da divisão é #{result}" 155 | {:error, :not_a_number} -> "Erro divisão por zero!" 156 | _anything_else -> "Não sei o que aconteceu" 157 | end 158 | ``` 159 | 160 | ## Cond 161 | 162 | ```elixir 163 | x = 1 164 | y = 24 165 | z = 25 166 | 167 | cond do 168 | x > 1 -> "x é maior do que 1" 169 | y > 2 -> "y é maior do que 2" 170 | z > 20 -> "z é maior do que 20" 171 | true -> "nenhuma das condições é verdadeira" 172 | end 173 | ``` 174 | 175 | ## with 176 | 177 | ```elixir 178 | 179 | with {:ok, value} <- M.divide(100, 3), 180 | {:error, atom} <- M.divide("Adolfo", "Neto"), 181 | {:error, atom2} <- M.divide(100, 2) do 182 | IO.puts "O value é #{value}" 183 | IO.puts "O atom é #{atom}" 184 | IO.puts "O atom2 é #{atom2}" 185 | else 186 | x -> IO.puts "#{inspect(x)} não deu certo" 187 | end 188 | 189 | ``` 190 | -------------------------------------------------------------------------------- /offerings/2024/Livebook/20241205/aula-dezembro-05.livemd: -------------------------------------------------------------------------------- 1 | # Aula dezembro 05 2 | 3 | ## Descrição 4 | 5 | ```elixir 6 | %{{1,1} => "1"} 7 | ``` 8 | 9 | Escreva um programa que converta 10 | 11 | 12 | 13 | ```elixir 14 | """ 15 | ABC 16 | DEF 17 | GHI 18 | """ 19 | ``` 20 | 21 | em 22 | um mapa que imita uma matriz 23 | 24 | 25 | 26 | ```elixir 27 | %{{1,1} => "A" ... {3,3}=>"I"} 28 | ``` 29 | 30 | ```elixir 31 | input = """ 32 | ABC 33 | DEF 34 | GHI 35 | """ 36 | ``` 37 | 38 | ```elixir 39 | Enum.map(String.split(input), fn x -> String.graphemes(x) end) 40 | ``` 41 | 42 | ```elixir 43 | parsedInput = 44 | input 45 | |> String.split() 46 | |> Enum.map(&String.graphemes/1) 47 | ``` 48 | 49 | ```elixir 50 | String.graphemes("abc") 51 | ``` 52 | 53 | ```elixir 54 | for l <- parsedInput do 55 | for r <- l do 56 | IO.inspect(r) 57 | end 58 | end 59 | ``` 60 | 61 | ```elixir 62 | for {line, i} <- Enum.with_index(parsedInput) do 63 | for {letter, j} <- Enum.with_index(line) do 64 | {letter, i, j} 65 | end 66 | end 67 | |> List.flatten() 68 | |> Enum.reduce(%{}, fn {letter, row, columm}, acc -> 69 | Map.put(acc, {row + 1, columm + 1}, letter) 70 | end) 71 | ``` 72 | 73 | ```elixir 74 | """ 75 | ABC 76 | DEF 77 | GHI 78 | """ 79 | |> String.split() 80 | |> Enum.map(&String.graphemes/1) 81 | |> Enum.with_index() 82 | |> Enum.flat_map(fn {line, i} -> 83 | Enum.with_index(line) 84 | |> Enum.map(fn {letter, j} -> {letter, i, j} end) 85 | end) 86 | |> Enum.reduce(%{}, fn {letter, row, columm}, acc -> 87 | Map.put(acc, {row + 1, columm + 1}, letter) 88 | end) 89 | ``` 90 | 91 | ```elixir 92 | Enum.with_index(parsedInput) 93 | ``` 94 | 95 | ```elixir 96 | 97 | Enum.reduce([1, 11145, 674, 1000], 0, 98 | fn x, acc -> 99 | x+acc 100 | end 101 | ) 102 | ``` 103 | 104 | ## Verificação da Existência de Padrões 105 | 106 | ```elixir 107 | [ 108 | [{1,1},{2,2},{3,3}], 109 | [{3,1},{2,2},{3,3}], 110 | [{1,1},{1,2},{2,1},{2,2}] 111 | ] 112 | ``` 113 | 114 | ```elixir 115 | """ 116 | X.. 117 | .X. 118 | ..X 119 | """ 120 | 121 | """ 122 | ..X 123 | .X. 124 | X.. 125 | """ 126 | 127 | """ 128 | XX. 129 | XX. 130 | ... 131 | """ 132 | 133 | """ 134 | .XX 135 | .XX 136 | ... 137 | """ 138 | 139 | """ 140 | ... 141 | XX. 142 | XX. 143 | """ 144 | 145 | """ 146 | ... 147 | .XX 148 | .XX 149 | """ 150 | ``` 151 | 152 | ```elixir 153 | tabuleiro = 154 | """ 155 | X.. 156 | XX. 157 | ... 158 | """ 159 | 160 | padrao = [{1, 1}, {1, 2}, {2, 1}, {2, 2}] 161 | 162 | defmodule Jogo do 163 | def cria_mapa(tabuleiro) do 164 | tabuleiro 165 | |> String.split() 166 | |> Enum.map(&String.graphemes/1) 167 | |> aux() 168 | end 169 | 170 | defp aux(parsed_input) do 171 | for {line, i} <- Enum.with_index(parsed_input) do 172 | for {letter, j} <- Enum.with_index(line) do 173 | {letter, i, j} 174 | end 175 | end 176 | |> List.flatten() 177 | |> Enum.reduce(%{}, fn {letter, row, columm}, acc -> 178 | Map.put(acc, {row + 1, columm + 1}, letter) 179 | end) 180 | end 181 | 182 | def satisfaz(tabuleiro, padrao) do 183 | mapa = Jogo.cria_mapa(tabuleiro) 184 | Enum.all?(padrao, fn x -> mapa[x] == "X" end) 185 | end 186 | end 187 | 188 | Jogo.satisfaz(tabuleiro, padrao) == true 189 | 190 | # Jogo.cria_mapa(tabuleiro) 191 | ``` 192 | 193 | ```elixir 194 | # Refactored by ElixirSparq 195 | tabuleiro = """ 196 | XX. 197 | XX. 198 | ... 199 | """ 200 | 201 | padrao = [{1, 1}, {1, 2}, {2, 1}, {2, 2}] 202 | 203 | defmodule Jogo2 do 204 | def cria_mapa(tabuleiro) do 205 | tabuleiro 206 | |> String.split() 207 | |> Enum.map(&String.graphemes/1) 208 | |> aux() 209 | end 210 | 211 | defp aux(parsed_input) do 212 | parsed_input 213 | |> Enum.with_index() 214 | |> Enum.reduce(%{}, fn {line, i}, acc -> 215 | line 216 | |> Enum.with_index() 217 | |> Enum.reduce(acc, fn {letter, j}, acc_inner -> 218 | Map.put(acc_inner, {i + 1, j + 1}, letter) 219 | end) 220 | end) 221 | end 222 | 223 | def satisfaz(tabuleiro, padrao) do 224 | mapa = cria_mapa(tabuleiro) 225 | Enum.all?(padrao, fn x -> mapa[x] == "X" end) 226 | end 227 | end 228 | 229 | Jogo2.satisfaz(tabuleiro, padrao) 230 | 231 | 232 | ``` 233 | -------------------------------------------------------------------------------- /offerings/2024/Livebook/help/app: -------------------------------------------------------------------------------- 1 | docker build -t my-app . 2 | docker run --rm -p 8080:8080 -p 8081:8081 my-app 3 | 4 | 5 | 6 | 7 | Funcionou em 23/10 8 | 9 | Abri o Livebook com 10 | sudo docker run -p 8090:8090 -p 8091:8091 --pull always -e LIVEBOOK_PORT=8090 -e LIVEBOOK_IFRAME_PORT=8091 -u $(id -u):$(id -g) -e LIVEBOOK_PASSWORD="adolfontcaes0052024" -v .:/data ghcr.io/livebook-dev/livebook 11 | 12 | Abri https://gist.github.com/adolfont/1e0675a0b7e7ed77d677ccd4d3395a52 13 | 14 | Criei o app pra Docker 15 | 16 | Salvei o Dockerfile 17 | 18 | Chamei 19 | sudo docker build -t my-app . 20 | sudo docker run --rm -p 8080:8080 -p 8081:8081 my-app 21 | 22 | pois as portas são diferentes quando abri o Livebook 23 | 24 | Ele me deu este link 25 | http://localhost:8080/?token=7mixtcuqkq3xxapo3uchwgrnanaosloj 26 | 27 | Abri janela anônima 28 | Fui em Local apps 29 | Cliquei na URL do Meu primeiro aplicativo: http://localhost:8080/apps/meu-aplicativo-de-chat 30 | 31 | Ele mostrou janela com 32 | Meu primeiro aplicativo 33 | This is a multi-session app, pick an existing session or create a new one. 34 | 35 | + New session 36 | 37 | Cliquei em + New session 38 | 39 | Mostrou a tela do app em 40 | http://localhost:8080/apps/meu-aplicativo-de-chat/sessions/ewrrf6d244kqtjrgsck4szwmttoegvv7z5ob3s6p6tf6ds3x 41 | 42 | 43 | Abri o Chrome com outro perfil 44 | Fui em http://localhost:8080/apps/meu-aplicativo-de-chat 45 | 46 | Aparece 47 | Meu primeiro aplicativo 48 | This is a multi-session app, pick an existing session or create a new one. 49 | 50 | New session 51 | Started less than a minute ago 52 | 53 | Cliquei em "Started less than a minute ago" 54 | 55 | Pronto. Agora o chat funciona. 56 | -------------------------------------------------------------------------------- /offerings/2024/Livebook/help/start: -------------------------------------------------------------------------------- 1 | # You can configure Livebook using environment variables, 2 | # for all options see the dedicated "Environment variables" section below 3 | 4 | 5 | docker run -p 8080:8080 -p 8081:8081 --pull always -u $(id -u):$(id -g) -e LIVEBOOK_PASSWORD="adolfontcaes0052024" -v .:/data ghcr.io/livebook-dev/livebook 6 | latest: Pulling from livebook-dev/livebook 7 | 8 | # It did work on October 23rd 9 | sudo docker run -p 8080:8080 -p 8081:8081 --pull always -u $(id -u):$(id -g) -e LIVEBOOK_PASSWORD="adolfontcaes0052024" -v .:/data ghcr.io/livebook-dev/livebook 10 | 11 | # It did work on October 23rd 12 | sudo docker run -p 8090:8090 -p 8091:8091 --pull always -e LIVEBOOK_PORT=8090 -e LIVEBOOK_IFRAME_PORT=8091 -u $(id -u):$(id -g) -e LIVEBOOK_PASSWORD="adolfontcaes0052024" -v .:/data ghcr.io/livebook-dev/livebook 13 | 14 | adolfontcaes0052024 15 | -------------------------------------------------------------------------------- /offerings/2024/README.md: -------------------------------------------------------------------------------- 1 | # CAES005 - Introduction to Functional Programming (2024) 2 | 3 | - Instructor: [Adolfo Neto](http://adolfont.github.io) 4 | 5 | 6 | ## Numbers 7 | 8 | - 52 students (7 PPGCA students and 45 external participants) enrolled 9 | - Of these, 24 (6 PPGCA students and 18 external participants) completed the course without failing due to absence 10 | - And 17 were present in the final class 11 | 12 | 13 | ![last class](https://github.com/user-attachments/assets/37c3a9b4-0b2c-4239-8583-4d39a9f8e727) 14 | 15 | 16 | 17 | ## Invited talks 18 | 19 | - [Unsafe Impedance, Lee Barney (BYU-Idaho)](https://youtu.be/HEhOYitn2ZU) 20 | - [Introdução à linguagem Haskell, Zoey Pessanha](https://majestic-brisket-0c6.notion.site/Introdu-o-linguagem-Haskell-145f9e92597480dc9625dfdf8fe32c5e?pvs=4) 21 | - Ulf Riehm and Bas Wegh - [Herrmann Ultrasonics](https://www.herrmannultrasonics.com/en-us/) 22 | - [Além das Terras de Java - Uma Introdução ao Lisp da JVM para Programação Funcional, Eduardo Lemos](https://www.youtube.com/watch?v=UyN1Sw1nBbo) 23 | 24 | 25 | ## Evaluation 26 | 27 | - A paper 28 | - A project 29 | -------------------------------------------------------------------------------- /offerings/2024/currying/currying.hs: -------------------------------------------------------------------------------- 1 | -- ChatGPT helped me create these examples https://chatgpt.com/share/672cd10e-29c4-8002-96df-56cf62c2f611 2 | 3 | 4 | -- A curried function that takes two arguments 5 | add :: Int -> Int -> Int 6 | add x y = x + y 7 | -- Actually, it is a function that returns another function! 8 | 9 | ---------------------- 10 | 11 | add 3 5 12 | 13 | resultCurried = add 3 5 -- This will give 8 14 | 15 | add3 = add 3 -- This will return a function such as add3 x = 3 + y 16 | 17 | add3 10 18 | resultAdd3 = add3 10 -- This will give 13 19 | 20 | ---------------------- 21 | 22 | -- The uncurried version of add 23 | -- Actually, it is a function that receives a tuple as an argument 24 | 25 | add' :: (Int, Int) -> Int 26 | add' (x, y) = x + y 27 | 28 | 29 | ---------------------- 30 | add' (3, 5) 31 | 32 | resultUncurried = add' (3, 5) -- This will also give 8 33 | 34 | add3B = add'(3) -- This does not work 35 | 36 | ---------------------- 37 | 38 | -- Using curry to convert add' (uncurried) to a curried form 39 | curriedAdd = curry add' 40 | 41 | -- Using uncurry to convert add (curried) to an uncurried form 42 | uncurriedAdd = uncurry add 43 | 44 | ---------------------- 45 | curriedAdd 3 5 46 | resultFromCurriedAdd = curriedAdd 3 5 -- Gives 8 47 | uncurriedAdd (3,5) 48 | resultFromUncurriedAdd = uncurriedAdd (3,5) -- Gives 8 49 | 50 | -------------------------------------------------------------------------------- /offerings/2024/currying/firstclass.pas: -------------------------------------------------------------------------------- 1 | program ExponentCalculation; 2 | uses Math; 3 | 4 | function PowerSum(x, y, z: Real): Real; 5 | begin 6 | PowerSum := Power(x, y + z); 7 | end; 8 | 9 | var 10 | x, y, z, result: Real; 11 | 12 | begin 13 | writeln('Enter values for x, y, and z:'); 14 | readln(x); 15 | readln(y); 16 | readln(z); 17 | 18 | result := PowerSum(x, y, z); 19 | writeln('Result of ', x:0:2, ' ^ (', y:0:2, ' + ', z:0:2, ') is ', result:0:2); 20 | end. 21 | -------------------------------------------------------------------------------- /offerings/2024/desafio_dos_tres/README.md: -------------------------------------------------------------------------------- 1 | # Desafio dos Três 2 | 3 | Um jogo parecido com o Jogo da velha, mas que envolve 3 pessoas, 3 símbolos e a possibilidade de uma pessoa apagar o símbolo da outra (escrever por cima). O tabuleiro é 4x4. Criado com a ajuda do ChatGPT. 4 | 5 | 6 | ## Objetivo 7 | 8 | Ser o primeiro jogador a alinhar 4 símbolos consecutivos (horizontal, vertical ou diagonal) no tabuleiro 4x4. 9 | 10 | ## Regras 11 | 12 | 13 | 1. **Número de Jogadores:** 3 jogadores. 14 | 2. **Símbolos:** Cada jogador escolhe um símbolo único (ex.: `X`, `O`, `#`). 15 | 3. **Tabuleiro:** Um grid de 4x4, inicialmente vazio. 16 | 17 | 4. **Turnos:** 18 | - O jogo é jogado em turnos rotativos: Jogador 1 → Jogador 2 → Jogador 3 → volta ao Jogador 1. 19 | - No turno, o jogador pode: 20 | - Colocar seu símbolo em uma célula vazia. 21 | - Apagar o símbolo de um oponente escrevendo por cima (substituir o símbolo). 22 | 23 | 5. **Vencedor:** 24 | - O primeiro jogador a alinhar 4 de seus símbolos consecutivos (horizontalmente, verticalmente ou diagonalmente) vence. 25 | - Se o tabuleiro for preenchido sem um vencedor, o jogo termina em empate. 26 | 27 | 6. **Regra contra a Vingança:** 28 | - Um jogador não pode apagar o símbolo que acabou de ser jogado no turno imediatamente anterior por outro jogador que apagou seu símbolo. Isso evita "vinganças instantâneas." 29 | 7. **Regra de Apagar Símbolos:** 30 | - Um jogador pode apagar o símbolo de outro jogador ao escrever por cima dele. 31 | - **Limitação:** Um jogador **não pode apagar símbolos em dois turnos consecutivos**. 32 | - Se no turno anterior o jogador apagou o símbolo de outro, ele deve **obrigatoriamente jogar em uma célula vazia** no turno atual. 33 | 34 | --- 35 | 36 | ### **Exemplo de Representação do Tabuleiro Inicial:** 37 | ``` 38 | . . . . 39 | . . . . 40 | . . . . 41 | . . . . 42 | ``` 43 | 44 | Onde `.` representa células vazias. 45 | 46 | 47 | 48 | 49 | ### Exemplo 1 50 | 51 | 1. Jogador 1 coloca `X` em uma célula. 52 | 2. Jogador 2 coloca `O` em outra célula. 53 | 3. Jogador 3 pode: 54 | - Colocar `#` em uma célula vazia. 55 | - Substituir o `X` ou o `O` por `#` (seguindo as regras). 56 | 57 | 58 | 59 | ### Exemplo 2 60 | 61 | - **Turno 1:** Jogador 1 coloca `X` no tabuleiro. 62 | - **Turno 2:** Jogador 2 coloca `O`. 63 | - **Turno 3:** Jogador 3 apaga o `X` e coloca `#`. 64 | - **Turno 4:** Jogador 1 **não pode apagar o `#` do Jogador 3** porque apagou no turno anterior. Ele deve jogar em uma célula vazia. 65 | 66 | ## Para implementar 67 | 68 | - Você pode usar escript ou [mix task](https://github.com/adolfont/caes005-introduction-to-functional-programming/tree/main/offerings/2023/projects/tasks) -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/deffunc/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/deffunc/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | deffunc-*.tar 24 | 25 | # Temporary files, for example, from tests. 26 | /tmp/ 27 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/deffunc/README.md: -------------------------------------------------------------------------------- 1 | # Deffunc 2 | 3 | **TODO: Add description** 4 | 5 | ## Installation 6 | 7 | If [available in Hex](https://hex.pm/docs/publish), the package can be installed 8 | by adding `deffunc` to your list of dependencies in `mix.exs`: 9 | 10 | ```elixir 11 | def deps do 12 | [ 13 | {:deffunc, "~> 0.1.0"} 14 | ] 15 | end 16 | ``` 17 | 18 | Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) 19 | and published on [HexDocs](https://hexdocs.pm). Once published, the docs can 20 | be found at . 21 | 22 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/deffunc/lib/deffunc.ex: -------------------------------------------------------------------------------- 1 | defmodule Deffunc do 2 | @moduledoc """ 3 | Documentation for `Deffunc`. 4 | """ 5 | 6 | @doc """ 7 | Hello world. 8 | 9 | ## Examples 10 | 11 | iex> Deffunc.hello() 12 | :world 13 | 14 | """ 15 | def hello() do 16 | :world 17 | end 18 | 19 | def imprime_nome(keyword_list) do 20 | meio = 21 | if keyword_list[:nomes_do_meio] != nil do 22 | keyword_list[:nomes_do_meio] <> " " 23 | else 24 | "" 25 | end 26 | 27 | keyword_list[:nome] <> " " <> meio <> keyword_list[:sobrenome] 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/deffunc/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Deffunc.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :deffunc, 7 | version: "0.1.0", 8 | elixir: "~> 1.17", 9 | start_permanent: Mix.env() == :prod, 10 | deps: deps() 11 | ] 12 | end 13 | 14 | # Run "mix help compile.app" to learn about applications. 15 | def application do 16 | [ 17 | extra_applications: [:logger] 18 | ] 19 | end 20 | 21 | # Run "mix help deps" to learn about dependencies. 22 | defp deps do 23 | [ 24 | # {:dep_from_hexpm, "~> 0.3.0"}, 25 | # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} 26 | ] 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/deffunc/test/deffunc_test.exs: -------------------------------------------------------------------------------- 1 | defmodule DeffuncTest do 2 | use ExUnit.Case 3 | doctest Deffunc 4 | 5 | test "Imprime Nome e Sobrenome" do 6 | assert Deffunc.imprime_nome(nome: "Adolfo", sobrenome: "Neto") == "Adolfo Neto" 7 | end 8 | 9 | test "Imprime Nome, Nomes do Meio e Sobrenome" do 10 | assert Deffunc.imprime_nome( 11 | sobrenome: "Neto", 12 | nome: "Adolfo", 13 | nomes_do_meio: "Gustavo Serra Seca" 14 | ) == "Adolfo Gustavo Serra Seca Neto" 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/deffunc/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/megasena/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/megasena/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | megasena-*.tar 24 | 25 | # Temporary files, for example, from tests. 26 | /tmp/ 27 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/megasena/README.md: -------------------------------------------------------------------------------- 1 | # MegaSena 2 | 3 | By using MegaSena, I hope you get convinced that bets are not a good idea. 4 | 5 | 6 | Download the project and, if you have Elixir installed, just do: 7 | 8 | $ mix run --no-halt 9 | 10 | 11 | 12 | 31 | 32 | ## Uses of OTPSparq 33 | 34 | 1. 35 | 2. -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/megasena/chama.txt: -------------------------------------------------------------------------------- 1 | mix run -e "MegaSena.main(100000)" 2 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/megasena/lib/megasena.ex: -------------------------------------------------------------------------------- 1 | defmodule MegaSena do 2 | def main(tries) do 3 | # Start the game by calling the `play` function in `MegaSena.Player` 4 | MegaSena.Player.play(tries) 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/megasena/lib/megasena/application.ex: -------------------------------------------------------------------------------- 1 | defmodule MegaSena.Application do 2 | use Application 3 | 4 | def start(_type, _args) do 5 | # Start the supervisor 6 | numbers = 6 7 | guesses = 10 8 | result = MegaSena.Supervisor.start_link({numbers, guesses}) 9 | 10 | # Start a game with a set number of tries 11 | MegaSena.main(100000) 12 | 13 | result 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/megasena/lib/megasena/player.ex: -------------------------------------------------------------------------------- 1 | defmodule MegaSena.Player do 2 | use GenServer 3 | 4 | def start_link({guesses, numbers}) do 5 | GenServer.start_link(__MODULE__, {guesses, numbers}, name: __MODULE__) 6 | end 7 | 8 | # Server (GenServer) Callbacks 9 | def init({guesses, numbers}) do 10 | # Ensure MegaSena.Server is started 11 | server = 12 | case MegaSena.Server.start_link(numbers) do 13 | {:ok, pid} -> pid 14 | {:error, {:already_started, pid}} -> pid 15 | end 16 | 17 | # Initialize state with server pid and other data 18 | {:ok, %{server: server, plays: 0, wins: 0, guesses: guesses, numbers: numbers}} 19 | end 20 | 21 | # Play a single round, calling the server with a guess and updating state 22 | def handle_call( 23 | {:play, guess}, 24 | _from, 25 | state = %{server: server, plays: plays, wins: wins, guesses: _guesses, numbers: numbers} 26 | ) do 27 | correct_guesses = GenServer.call(server, {:play, guess}) 28 | 29 | new_wins = if correct_guesses == numbers, do: wins + 1, else: wins 30 | 31 | response = 32 | "Your play #{inspect(guess, charlists: :as_lists)} guessed #{correct_guesses} numbers correctly!" 33 | 34 | # IO.puts("numbers: #{numbers}") 35 | # IO.puts("wins: #{wins}") 36 | # IO.puts("new_wins: #{new_wins}") 37 | {:reply, response, %{state | plays: plays + 1, wins: new_wins}} 38 | end 39 | 40 | # Retrieve the current state 41 | def handle_call(:get_state, _from, state) do 42 | {:reply, state, state} 43 | end 44 | 45 | # Public API to play a specified number of times with a generated guess 46 | def play(n) do 47 | %{guesses: guesses} = get_state() 48 | 49 | Enum.each(1..n, fn _ -> 50 | guess = 1..60 |> Enum.to_list() |> Enum.shuffle() |> Enum.take(guesses) |> Enum.sort() 51 | IO.inspect(GenServer.call(__MODULE__, {:play, guess}), label: "Play result") 52 | end) 53 | 54 | IO.inspect(get_state()) 55 | end 56 | 57 | # Public API to get the current state 58 | def get_state() do 59 | GenServer.call(__MODULE__, :get_state) 60 | end 61 | 62 | # Optional helper function to start the player and check the state 63 | def new(guesses, numbers) do 64 | {:ok, pid} = MegaSena.Player.start_link({guesses, numbers}) 65 | IO.inspect(MegaSena.Player.get_state(), label: "Initial Player State") 66 | pid 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/megasena/lib/megasena/server.ex: -------------------------------------------------------------------------------- 1 | defmodule MegaSena.Server do 2 | use GenServer 3 | 4 | # Client API 5 | def start_link(numbers) do 6 | GenServer.start_link(__MODULE__, numbers, name: __MODULE__) 7 | end 8 | 9 | # Server (GenServer) Callbacks 10 | 11 | # Called when the GenServer is first started 12 | def init(numbers) do 13 | all_numbers = 1..60 |> Enum.shuffle() |> Enum.take(numbers) |> Enum.sort() 14 | 15 | dbg(all_numbers) 16 | 17 | {:ok, all_numbers} 18 | end 19 | 20 | def handle_call({:play, guess}, _from, state) do 21 | state_set = MapSet.new(state) 22 | guess_set = MapSet.new(guess) 23 | 24 | correct_guesses = 25 | state_set 26 | |> MapSet.intersection(guess_set) 27 | |> Enum.count() 28 | 29 | {:reply, correct_guesses, state} 30 | end 31 | 32 | def handle_call(:get_numbers, _from, state) do 33 | {:reply, state, state} 34 | end 35 | 36 | def get_numbers() do 37 | GenServer.call(__MODULE__, :get_numbers) 38 | end 39 | 40 | def guess_numbers(guess) do 41 | GenServer.call(__MODULE__, {:play, guess}) 42 | end 43 | 44 | # Convenience function to start a new instance and inspect the numbers 45 | def new(numbers) do 46 | {:ok, pid} = MegaSena.Server.start_link(numbers) 47 | IO.inspect(MegaSena.Server.get_numbers(), label: "Generated numbers") 48 | pid 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/megasena/lib/megasena/supervisor.ex: -------------------------------------------------------------------------------- 1 | defmodule MegaSena.Supervisor do 2 | use Supervisor 3 | 4 | # Accept numbers and guesses as arguments 5 | def start_link({numbers, guesses}) do 6 | Supervisor.start_link(__MODULE__, {numbers, guesses}, name: __MODULE__) 7 | end 8 | 9 | def init({numbers, guesses}) do 10 | children = [ 11 | # Pass numbers to MegaSena.Server 12 | {MegaSena.Server, numbers}, 13 | # Pass guesses and numbers to MegaSena.Player 14 | {MegaSena.Player, {guesses, numbers}} 15 | ] 16 | 17 | # Supervisor with :one_for_one strategy 18 | Supervisor.init(children, strategy: :one_for_one) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/megasena/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Megasena.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :megasena, 7 | version: "0.1.0", 8 | elixir: "~> 1.17", 9 | start_permanent: Mix.env() == :prod, 10 | deps: deps() 11 | ] 12 | end 13 | 14 | # Run "mix help compile.app" to learn about applications. 15 | def application do 16 | [ 17 | extra_applications: [:logger], 18 | # This specifies the application module 19 | mod: {MegaSena.Application, []} 20 | ] 21 | end 22 | 23 | # Run "mix help deps" to learn about dependencies. 24 | defp deps do 25 | [ 26 | # {:dep_from_hexpm, "~> 0.3.0"}, 27 | # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} 28 | ] 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/megasena/test/megasena_test.exs: -------------------------------------------------------------------------------- 1 | defmodule MegasenaTest do 2 | use ExUnit.Case 3 | doctest Megasena 4 | 5 | test "greets the world" do 6 | assert Megasena.hello() == :world 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /offerings/2024/elixir_projects/megasena/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /offerings/2024/lazy/lazyeval: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adolfont/caes005-introduction-to-functional-programming/a9b6de4534585a632113a1d960a9102c0715fb5c/offerings/2024/lazy/lazyeval -------------------------------------------------------------------------------- /offerings/2024/lazy/lazyeval.hi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adolfont/caes005-introduction-to-functional-programming/a9b6de4534585a632113a1d960a9102c0715fb5c/offerings/2024/lazy/lazyeval.hi -------------------------------------------------------------------------------- /offerings/2024/lazy/lazyeval.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE InstanceSigs #-} 2 | 3 | -- Private link https://claude.ai/chat/87e8d68e-5414-45b3-b74b-c99a3247e70a 4 | 5 | import Data.List (take, drop) 6 | 7 | -- Define an infinite list of Fibonacci numbers 8 | fibs :: [Integer] 9 | fibs = 1 : 1 : zipWith (+) fibs (drop 1 fibs) 10 | 11 | -- Define a function that takes the first n Fibonacci numbers 12 | takeFibs :: Int -> [Integer] 13 | takeFibs n = take n fibs 14 | 15 | main :: IO () 16 | main = do 17 | let first10Fibs = takeFibs 12 18 | print first10Fibs 19 | -- Output: [1,1,2,3,5,8,13,21,34,55] 20 | 21 | -- Now, let's try taking the first 1000 Fibonacci numbers 22 | let first1000Fibs = takeFibs 1000 23 | print (length first1000Fibs) 24 | -- Output: 1000 25 | -- Notice that the program doesn't hang or use an excessive amount of memory, even though we're working with an infinite list. -------------------------------------------------------------------------------- /offerings/2024/lazy/lazyeval.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adolfont/caes005-introduction-to-functional-programming/a9b6de4534585a632113a1d960a9102c0715fb5c/offerings/2024/lazy/lazyeval.o -------------------------------------------------------------------------------- /offerings/2024/lazy/lazyfib.exs: -------------------------------------------------------------------------------- 1 | # Private link https://claude.ai/chat/87e8d68e-5414-45b3-b74b-c99a3247e70a 2 | defmodule LazyFib do 3 | def fibonacci_stream do 4 | Stream.unfold({1, 1}, fn {a, b} -> {a, {b, a + b}} end) 5 | end 6 | 7 | def main do 8 | # Get first 10 Fibonacci numbers 9 | first_10 = 10 | fibonacci_stream() 11 | |> Stream.take(10) 12 | |> Enum.to_list() 13 | 14 | IO.puts("First 10 Fibonacci numbers:") 15 | IO.inspect(first_10) 16 | 17 | # Get first 1000 Fibonacci numbers 18 | first_1000_length = 19 | fibonacci_stream() 20 | |> Stream.take(1000) 21 | |> Enum.to_list() 22 | |> length() 23 | 24 | IO.puts("\nLength of first 1000 Fibonacci numbers:") 25 | IO.puts(first_1000_length) 26 | end 27 | end 28 | 29 | # Run the program 30 | LazyFib.main() 31 | -------------------------------------------------------------------------------- /offerings/2024/lua/alo_mundo.lua: -------------------------------------------------------------------------------- 1 | print("Alo Mundo") 2 | 3 | -------------------------------------------------------------------------------- /offerings/2024/lua/array.lua: -------------------------------------------------------------------------------- 1 | -- Declara um array de 10 posições 2 | local array = {} 3 | 4 | -- Coloca 0.1 no primeiro elemento 5 | array[1] = 0.1 6 | 7 | -- Preenche as posições subsequentes com 1.1 elevado ao valor anterior 8 | for i = 2, 10 do 9 | array[i] = 1.1 ^ array[i - 1] 10 | end 11 | 12 | -- Lista todos os elementos e calcula a soma 13 | local soma = 0 14 | for i = 1, 10 do 15 | print("Elemento " .. i .. ": " .. array[i]) 16 | soma = soma + array[i] 17 | end 18 | 19 | -- Exibe a soma total dos elementos 20 | print("Soma de todos os elementos: " .. soma) 21 | 22 | 23 | -------------------------------------------------------------------------------- /offerings/2024/lua/eight_queens.lua: -------------------------------------------------------------------------------- 1 | -- Solution for the Eigth Queens Problem 2 | -- Adapted from Roberto Ierusalismchy's Programming in Lua, Fourth Edition https://amzn.to/3CccLTZ 3 | 4 | N = 8 -- board size 5 | 6 | -- check whether position (line, column) is free from attacks 7 | local function is_place_ok(board, line, column) 8 | for i = 1, line - 1 do -- for each queen already placed 9 | if (board[i] == column) or -- same column? 10 | (board[i] - i == column - line) or -- same diagonal? 11 | (board[i] + i == column + line) then -- same diagonal? 12 | return false -- place can be attacked 13 | end 14 | end 15 | return true -- no attacks; place is OK 16 | end 17 | 18 | local function print_board(board) 19 | for i = 1, N do -- for each row 20 | for j = 1, N do -- and for each column 21 | -- write "X" or "-" plus a space 22 | io.write(board[i] == j and "X" or "-", " ") 23 | end 24 | io.write("\n") 25 | end 26 | io.write("\n") 27 | end 28 | 29 | 30 | local function add_queen(board, line) 31 | if line > N then -- all queens have been placed? 32 | print_board(board) 33 | else -- try to place line-th queen 34 | for column = 1, N do 35 | if is_place_ok(board, line, column) then 36 | board[line] = column -- place line-th queen at 'column' 37 | add_queen(board, line + 1) 38 | end 39 | end 40 | end 41 | end 42 | 43 | -- run the program 44 | 45 | add_queen({}, 1) 46 | -------------------------------------------------------------------------------- /offerings/2024/lua/eight_queens_chatgpt.lua: -------------------------------------------------------------------------------- 1 | -- Solution for the Eight Queens Problem 2 | -- Adapted from Roberto Ierusalimchy's Programming in Lua, Fourth Edition https://amzn.to/3CccLTZ 3 | 4 | N = 8 -- board size 5 | 6 | -- check whether position (line, column) is free from attacks 7 | local function is_place_ok(board, line, column) 8 | for i = 1, line - 1 do -- for each queen already placed 9 | if (board[i] == column) or -- same column? 10 | (board[i] - i == column - line) or -- same diagonal? 11 | (board[i] + i == column + line) then -- same diagonal? 12 | return false -- place can be attacked 13 | end 14 | end 15 | return true -- no attacks; place is OK 16 | end 17 | 18 | local function print_board(board) 19 | for i = 1, N do -- for each row 20 | for j = 1, N do -- and for each column 21 | -- write "X" or "-" plus a space 22 | io.write(board[i] == j and "X" or "-", " ") 23 | end 24 | io.write("\n") 25 | end 26 | io.write("\n") 27 | end 28 | 29 | local function add_queen(board, line) 30 | if line > N then -- all queens have been placed? 31 | print_board(board) 32 | else -- try to place line-th queen 33 | for column = 1, N do 34 | if is_place_ok(board, line, column) then 35 | board[line] = column -- place line-th queen at 'column' 36 | add_queen(board, line + 1) 37 | board[line] = nil -- backtrack: remove queen 38 | end 39 | end 40 | end 41 | end 42 | 43 | -- run the program 44 | add_queen({}, 1) 45 | -------------------------------------------------------------------------------- /offerings/2024/lua/funcao_cidada.lua: -------------------------------------------------------------------------------- 1 | function reduce (table, fun, start) 2 | local accum = start 3 | for i = 1, #table do 4 | accum = fun(accum, table[i]) 5 | end 6 | return accum 7 | end 8 | 9 | function add(a, b) 10 | return a + b 11 | end 12 | 13 | 14 | function multiply(a, b) 15 | return a * b 16 | end 17 | 18 | my_table = {1, 3, 5, 4, 2} 19 | 20 | for key, value in pairs(my_table) do 21 | print("my_table[".. key.. "] = ".. value) 22 | end 23 | 24 | 25 | print("Soma dos valores de my_table: ".. reduce(my_table, add, 0)) 26 | 27 | print("Produto dos valores de my_table: ".. reduce(my_table, multiply, 1)) 28 | -------------------------------------------------------------------------------- /offerings/2024/lua/maior.lua: -------------------------------------------------------------------------------- 1 | -- Solicita os três números ao usuário 2 | print("Digite o primeiro número:") 3 | local num1 = io.read("*n") 4 | 5 | print("Digite o segundo número:") 6 | local num2 = io.read("*n") 7 | 8 | print("Digite o terceiro número:") 9 | local num3 = io.read("*n") 10 | 11 | -- Calcula o maior número 12 | local maior = num1 13 | 14 | if num2 > maior then 15 | maior = num2 16 | end 17 | 18 | if num3 > maior then 19 | maior = num3 20 | end 21 | 22 | -- Imprime o maior número 23 | print("O maior número é:", maior) 24 | -------------------------------------------------------------------------------- /offerings/2024/lua/maior_fatorial.lua: -------------------------------------------------------------------------------- 1 | -- Solicita os três números ao usuário 2 | io.write("Digite o primeiro número: ") 3 | local num1 = tonumber(io.read()) 4 | 5 | io.write("Digite o segundo número: ") 6 | local num2 = tonumber(io.read()) 7 | 8 | io.write("Digite o terceiro número: ") 9 | local num3 = tonumber(io.read()) 10 | -- Calcula o maior número 11 | local maior = num1 12 | 13 | if num2 > maior then 14 | maior = num2 15 | end 16 | 17 | if num3 > maior then 18 | maior = num3 19 | end 20 | 21 | -- Função para calcular o fatorial de um número 22 | local function fatorial(n) 23 | local resultado = 1 24 | for i = 2, n do 25 | resultado = resultado * i 26 | end 27 | return resultado 28 | end 29 | 30 | -- Calcula o fatorial do maior número 31 | local fatorial_maior = fatorial(maior) 32 | 33 | -- Imprime o maior número e seu fatorial 34 | print("O maior número é:", maior) 35 | print("O fatorial de", maior, "é:", fatorial_maior) 36 | -------------------------------------------------------------------------------- /offerings/2024/macros/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /offerings/2024/macros/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | macros-*.tar 24 | 25 | # Temporary files, for example, from tests. 26 | /tmp/ 27 | -------------------------------------------------------------------------------- /offerings/2024/macros/README.md: -------------------------------------------------------------------------------- 1 | # Macros 2 | 3 | **TODO: Add description** 4 | 5 | ## Installation 6 | 7 | If [available in Hex](https://hex.pm/docs/publish), the package can be installed 8 | by adding `macros` to your list of dependencies in `mix.exs`: 9 | 10 | ```elixir 11 | def deps do 12 | [ 13 | {:macros, "~> 0.1.0"} 14 | ] 15 | end 16 | ``` 17 | 18 | Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) 19 | and published on [HexDocs](https://hexdocs.pm). Once published, the docs can 20 | be found at . 21 | 22 | -------------------------------------------------------------------------------- /offerings/2024/macros/lib/calculator.ex: -------------------------------------------------------------------------------- 1 | defmodule Calculator do 2 | require Macros 3 | 4 | Macros.defmath([:add, :subtract, :multiply, :divide]) 5 | end 6 | -------------------------------------------------------------------------------- /offerings/2024/macros/lib/macros.ex: -------------------------------------------------------------------------------- 1 | defmodule Macros do 2 | defmacro hello(expr, complement: block) do 3 | quote do 4 | if unquote(expr), do: "Hello, " <> unquote(block) 5 | end 6 | end 7 | 8 | defmacro defmath(operations) do 9 | operations 10 | |> Enum.map(fn op -> 11 | case op do 12 | :add -> 13 | quote do 14 | def add(a, b), do: a + b 15 | end 16 | 17 | :subtract -> 18 | quote do 19 | def subtract(a, b), do: a - b 20 | end 21 | 22 | :multiply -> 23 | quote do 24 | def multiply(a, b), do: a * b 25 | end 26 | 27 | :divide -> 28 | quote do 29 | def divide(a, b) when b != 0, do: a / b 30 | def divide(_, 0), do: raise(ArgumentError, "Cannot divide by zero") 31 | end 32 | 33 | _ -> 34 | raise ArgumentError, "Unsupported operation: #{op}" 35 | end 36 | end) 37 | |> Enum.reduce(fn quoted_expr, acc -> 38 | quote do 39 | unquote(acc) 40 | unquote(quoted_expr) 41 | end 42 | end) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /offerings/2024/macros/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Macros.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :macros, 7 | version: "0.1.0", 8 | elixir: "~> 1.17", 9 | start_permanent: Mix.env() == :prod, 10 | deps: deps() 11 | ] 12 | end 13 | 14 | # Run "mix help compile.app" to learn about applications. 15 | def application do 16 | [ 17 | extra_applications: [:logger] 18 | ] 19 | end 20 | 21 | # Run "mix help deps" to learn about dependencies. 22 | defp deps do 23 | [ 24 | # {:dep_from_hexpm, "~> 0.3.0"}, 25 | # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} 26 | ] 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /offerings/2024/macros/test/calculator_test.exs: -------------------------------------------------------------------------------- 1 | defmodule CalculatorTest do 2 | use ExUnit.Case, async: true 3 | 4 | test "add/2 function adds two numbers" do 5 | assert Calculator.add(3, 5) == 8 6 | end 7 | 8 | test "subtract/2 function subtracts two numbers" do 9 | assert Calculator.subtract(10, 4) == 6 10 | end 11 | 12 | test "multiply/2 function multiplies two numbers" do 13 | assert Calculator.multiply(6, 7) == 42 14 | end 15 | 16 | test "divide/2 function divides two numbers" do 17 | assert Calculator.divide(20, 4) == 5.0 18 | end 19 | 20 | test "divide/2 raises ArgumentError when dividing by zero" do 21 | assert_raise ArgumentError, "Cannot divide by zero", fn -> 22 | Calculator.divide(10, 0) 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /offerings/2024/macros/test/macros_test.exs: -------------------------------------------------------------------------------- 1 | defmodule MacrosTest do 2 | use ExUnit.Case 3 | 4 | require Macros 5 | 6 | test "Macro that returns 'Hello, World!'" do 7 | result = 8 | Macros.hello(true, complement: "Wor" <> "ld!") 9 | 10 | assert result == "Hello, World!" 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /offerings/2024/macros/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /offerings/2024/monad/monad: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adolfont/caes005-introduction-to-functional-programming/a9b6de4534585a632113a1d960a9102c0715fb5c/offerings/2024/monad/monad -------------------------------------------------------------------------------- /offerings/2024/monad/monad.hi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adolfont/caes005-introduction-to-functional-programming/a9b6de4534585a632113a1d960a9102c0715fb5c/offerings/2024/monad/monad.hi -------------------------------------------------------------------------------- /offerings/2024/monad/monad.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad.State 2 | 3 | -- Define a type alias for the State monad that carries an `Int` as state 4 | type Counter = State Int 5 | 6 | -- Increment the counter by 1 7 | increment :: Counter Int 8 | increment = do 9 | current <- get -- Get the current state 10 | let next = current + 1 11 | put next -- Update the state 12 | return next -- Return the updated value 13 | 14 | -- Run a sequence of increments 15 | runCounter :: Counter [Int] 16 | runCounter = do 17 | val1 <- increment 18 | val2 <- increment 19 | val3 <- increment 20 | return [val1, val2, val3] 21 | 22 | -- Main function to execute 23 | main :: IO () 24 | main = do 25 | let initialState = 0 26 | (result, finalState) = runState runCounter initialState 27 | putStrLn $ "Sequence of results: " ++ show result 28 | putStrLn $ "Final state: " ++ show finalState 29 | 30 | -------------------------------------------------------------------------------- /offerings/2024/monad/monad.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adolfont/caes005-introduction-to-functional-programming/a9b6de4534585a632113a1d960a9102c0715fb5c/offerings/2024/monad/monad.o -------------------------------------------------------------------------------- /offerings/2025/livebooks/luaelixir.livemd: -------------------------------------------------------------------------------- 1 | # Lua and Elixir 2 | 3 | ```elixir 4 | Mix.install([ 5 | {:lua, "~> 0.2.1"} 6 | ]) 7 | ``` 8 | 9 | ## Example 10 | 11 | ```elixir 12 | defmodule MyAPI do 13 | use Lua.API 14 | 15 | deflua double(v), do: 2 * v 16 | end 17 | ``` 18 | 19 | ```elixir 20 | import Lua, only: [sigil_LUA: 2] 21 | 22 | ``` 23 | 24 | ```elixir 25 | lua = Lua.new() |> Lua.load_api(MyAPI) 26 | 27 | ``` 28 | 29 | ```elixir 30 | {[10], _} = Lua.eval!(lua, ~LUA[return double(5)]) 31 | 32 | ``` 33 | 34 | ```elixir 35 | Lua.eval!(lua, ~LUA[return double(5)]) 36 | ``` 37 | 38 | ## Factorial in Lua 39 | 40 | ```elixir 41 | code = ~LUA""" 42 | function factorial(n) 43 | if n == 0 then 44 | return 1 45 | else 46 | return n * factorial(n - 1) 47 | end 48 | end 49 | 50 | return factorial(10) 51 | """ 52 | ``` 53 | 54 | ```elixir 55 | Lua.eval!(code) 56 | 57 | 58 | ``` 59 | -------------------------------------------------------------------------------- /offerings/2025/sample_projects/distributed_hello_world/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /offerings/2025/sample_projects/distributed_hello_world/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where third-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # If the VM crashes, it generates a dump, let's ignore it too. 14 | erl_crash.dump 15 | 16 | # Also ignore archive artifacts (built via "mix archive.build"). 17 | *.ez 18 | 19 | # Ignore package tarball (built via "mix hex.build"). 20 | distributed_hello_world-*.tar 21 | 22 | # Temporary files, for example, from tests. 23 | /tmp/ 24 | -------------------------------------------------------------------------------- /offerings/2025/sample_projects/distributed_hello_world/README.md: -------------------------------------------------------------------------------- 1 | # DistributedHelloWorld 2 | 3 | 4 | 5 | ## Installation 6 | 7 | If [available in Hex](https://hex.pm/docs/publish), the package can be installed 8 | by adding `distributed_hello_world` to your list of dependencies in `mix.exs`: 9 | 10 | ```elixir 11 | def deps do 12 | [ 13 | {:distributed_hello_world, "~> 0.1.0"} 14 | ] 15 | end 16 | ``` 17 | 18 | Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) 19 | and published on [HexDocs](https://hexdocs.pm). Once published, the docs can 20 | be found at . 21 | 22 | -------------------------------------------------------------------------------- /offerings/2025/sample_projects/distributed_hello_world/lib/distributed_hello_world.ex: -------------------------------------------------------------------------------- 1 | defmodule DistributedHelloWorld do 2 | @moduledoc """ 3 | Documentation for `DistributedHelloWorld`. 4 | """ 5 | 6 | @doc """ 7 | Hello world. 8 | 9 | ## Examples 10 | 11 | iex> DistributedHelloWorld.hello() 12 | :world 13 | 14 | """ 15 | def hello do 16 | :world 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /offerings/2025/sample_projects/distributed_hello_world/lib/distributed_hello_world/application.ex: -------------------------------------------------------------------------------- 1 | defmodule DistributedHelloWorld.Application do 2 | # See https://hexdocs.pm/elixir/Application.html 3 | # for more information on OTP Applications 4 | @moduledoc false 5 | 6 | use Application 7 | 8 | @impl true 9 | def start(_type, _args) do 10 | children = [ 11 | # Starts a worker by calling: DistributedHelloWorld.Worker.start_link(arg) 12 | # {DistributedHelloWorld.Worker, arg} 13 | ] 14 | 15 | # See https://hexdocs.pm/elixir/Supervisor.html 16 | # for other strategies and supported options 17 | opts = [strategy: :one_for_one, name: DistributedHelloWorld.Supervisor] 18 | Supervisor.start_link(children, opts) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /offerings/2025/sample_projects/distributed_hello_world/mix.exs: -------------------------------------------------------------------------------- 1 | defmodule DistributedHelloWorld.MixProject do 2 | use Mix.Project 3 | 4 | def project do 5 | [ 6 | app: :distributed_hello_world, 7 | version: "0.1.0", 8 | elixir: "~> 1.18", 9 | start_permanent: Mix.env() == :prod, 10 | deps: deps() 11 | ] 12 | end 13 | 14 | # Run "mix help compile.app" to learn about applications. 15 | def application do 16 | [ 17 | extra_applications: [:logger], 18 | mod: {DistributedHelloWorld.Application, []} 19 | ] 20 | end 21 | 22 | # Run "mix help deps" to learn about dependencies. 23 | defp deps do 24 | [ 25 | # {:dep_from_hexpm, "~> 0.3.0"}, 26 | # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} 27 | ] 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /offerings/2025/sample_projects/distributed_hello_world/test/distributed_hello_world_test.exs: -------------------------------------------------------------------------------- 1 | defmodule DistributedHelloWorldTest do 2 | use ExUnit.Case 3 | doctest DistributedHelloWorld 4 | 5 | test "greets the world" do 6 | assert DistributedHelloWorld.hello() == :world 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /offerings/2025/sample_projects/distributed_hello_world/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /other_courses/elixir_erlang_beam.md: -------------------------------------------------------------------------------- 1 | # Universities teaching BEAM languages 2 | 3 | **The latest version of this document is now on https://github.com/adolfont/elixir_cop/blob/master/university_courses.md** 4 | 5 | Source: https://docs.google.com/spreadsheets/d/18zSqsCDOmIc4c5J1VsbLMiUPdRSZnPpS8nvOTu7osOY/edit#gid=0 6 | 7 | Elixir Forum post: https://elixirforum.com/t/universities-teaching-beam-related-languages/26267 8 | 9 | Twitter thread: https://twitter.com/adolfont/status/1182310375909400576?s=20 10 | 11 | Below I will list in text format some information about the university courses that teach BEAM languages. 12 | 13 | ## Federal University of Technology, Paraná 14 | 15 | - Course name: Introduction to Functional Programming 16 | - Language(s): Elixir 17 | - Instructor: Adolfo Neto https://twitter.com/adolfont 18 | - Hours: 45 19 | - Link: https://github.com/adolfont/introducao-a-programacao-funcional 20 | - Offered in: 2019 21 | - Campus: Curitiba 22 | 23 | --- 24 | 25 | - Course name: Concurrent Functional Programming 26 | - Language(s): Elixir 27 | - Instructor: Adolfo Neto https://twitter.com/adolfont 28 | - Hours: 45 29 | - Link: http://ppgca.dainf.ct.utfpr.edu.br/doku.php?id=caes004 30 | - Offered in: 2018 31 | - Campus: Curitiba 32 | 33 | ## University of São Paulo 34 | 35 | - Course name: Contemporary Functional Programming 36 | - Language(s): Erlang (and Scala) 37 | - Instructor: Francisco Reverbel 38 | - Hours: 60 39 | - Links: [2012](https://www.ime.usp.br/~reverbel/PFC-12/), [2011](https://www.ime.usp.br/~reverbel/PFC-11/) [2010](https://www.ime.usp.br/~reverbel/PFC-10/) [2009](https://www.ime.usp.br/~reverbel/PFC-09/) 40 | - Offered in: 2009-2012 41 | - Campus: São Paulo 42 | 43 | --- 44 | 45 | - Course name: Computational Logic (PCS3556 - Lógica Computacional) 46 | - Language(s): Elixir 47 | - Observation: It is not a course about Elixir or Functional Programming. 48 | - Instructor: Ricardo Luis de Azevedo da Rocha https://twitter.com/rcephas 49 | - Hours: 60 50 | - Links: [Syllabus](https://uspdigital.usp.br/jupiterweb/obterDisciplina?sgldis=PCS3556&codcur=3032&codhab=5060) [2018](https://edisciplinas.usp.br/course/view.php?id=60568) [2019](https://edisciplinas.usp.br/enrol/index.php?id=66248) 51 | - Offered in: 2018, 2019 52 | - Campus: São Paulo 53 | 54 | -------------------------------------------------------------------------------- /other_courses/material.md: -------------------------------------------------------------------------------- 1 | # Learning Resources 2 | 3 | 4 | - Teaching Functional Programming with Elixir - Adolfo Neto - Elixir Meetup #21 https://www.youtube.com/watch?v=1l1_rHC3lSo 5 | - ElixirConf 2023 - José Valim - The foundations of the Elixir type system https://www.youtube.com/watch?v=giYbq4HmfGA 6 | - C9 Lectures: Erik Meijer (Microsoft) https://learn.microsoft.com/en-us/shows/c9-lectures-erik-meijer-functional-programming-fundamentals/lecture-series-erik-meijer-functional-programming-fundamentals-chapter-1 7 | - An Introduction to Functional Programming through Lambda Calculus, Greg Michaelson https://www.amazon.com/Introduction-Functional-Programming-Calculus-Mathematics/dp/0486478831 8 | - OCaml Programming: Correct + Efficient + Beautiful https://cs3110.github.io/textbook/cover.html 9 | - Programming Languages - University of Washington. A: ML https://www.coursera.org/learn/programming-languages, B: Racket https://www.coursera.org/learn/programming-languages-part-b 10 | - Functional Programming in 40 Minutes • Russ Olsen • GOTO 2018 https://www.youtube.com/watch?v=0if71HOyVjY 11 | - Haskell - 2023/2 https://www.youtube.com/playlist?list=PLfdR3_dt2rbctdMHwZG2h4aKGROujEG3j 12 | - Functional programming books, comparison https://alvinalexander.com/photos/functional-programming-books-comparison-2023/ 13 | - Haskell Programming https://haskellbook.com/ 14 | - Learn Haskell by building a blog generator https://learn-haskell.blog/ 15 | - Learn you Some Haskell http://learnyouahaskell.com/ 16 | - Algoritmos funcionais: introdução minimalista à lógica de programação funcional pura aplicada à teoria dos conjuntos https://www.amazon.com.br/dp/8550814474 17 | - Awesome Funcional Programming Studies https://web.archive.org/web/20220108200614/https://github.com/lambda-study-group/awesome-functional-studies 18 | - Haskell for Imperative Programmers https://www.youtube.com/playlist?list=PLe7Ei6viL6jGp1Rfu0dil1JH1SHk9bgDV 19 | - Functional Programming in Scala https://www.manning.com/books/functional-programming-in-scala 20 | - Programación funcional con Haskell https://jaalonso.github.io/materias/PFconHaskell/ 21 | 22 | ## Disciplinas em português 23 | 24 | - BCC222 - Programação Funcional (UFOP). Professor: Rodrigo Geraldo Ribeiro https://github.com/rodrigogribeiro/bcc222-material 25 | - GRUPO DE ESTUDOS EM HASKELL DA UFABC https://haskell.pesquisa.ufabc.edu.br/ 26 | - Programação Funcional, André Rauber Du Bois (UFPEL) https://youtube.com/playlist?list=PLT3QeyTkGXU5jGOQxmNUM3schl_oB0lfy&si=GYUhTwq1DZTm6roo 27 | - Programação em Haskell (UFMG) https://homepages.dcc.ufmg.br/~camarao/haskell/ 28 | - Curso Introdução à Programação Funcional usando a Linguagem Elixir - prof. André Rauber Du Bois - Computação - Universidade Federal de Pelotas https://ardubois.github.io/elixir/ 29 | 30 | 31 | -------------------------------------------------------------------------------- /other_courses/software_verification.md: -------------------------------------------------------------------------------- 1 | # Software Verification courses 2 | 3 | Jan de Muijnck-Hughes asked on Twitter: 4 | ["Looking for existing University courses *all levels* that use #Dafny, #Coq, #Agda, #Idris et cetera for software verification, computer-aided verification, et cetera.... Asking for a Friend...we need context for proposing a course... 5 | I should be explicit, as 'et cetera' is not suitably fudgable: #Lean and other ITPs are fine. Courses on them are fine, courses that use them as the vehicle for teaching even better. 6 | I know about the channel on the Lean zulip, this ain't the only hive mind that I have asked the question ;-) and I have done some research already..."](https://x.com/jfdm/status/1714006851245732253?s=20) 7 | 8 | - Rob Lewis's "Formal Proof and Verification": https://browncs1951x.github.io 9 | - one automated-bounded-verification based, "Logic for Systems": https://csci1710.github.io/2023/ 10 | - Software Fiável https://fenix.ciencias.ulisboa.pt/courses/sfia-2536354281948960/pagina-inicial 11 | - Construction and Verification of Software (2021/2022) http://ctp.di.fct.unl.pt/~btoninho/teaching/cvs-22/ 12 | - Robert Rand teaches program verification at the undergrad level at UChicago: https://rand.cs.uchicago.edu/cmsc224/winter22/ 13 | - More Programming Than Programming: Teaching Formal Methods in a Software Engineering Programme https://link.springer.com/chapter/10.1007/978-3-031-06773-0_23 14 | - PROOF AUTOMATION https://dependenttyp.es/classes/598fa2022.html 15 | - Tobias Nipkow's courses on programming language semantics and functional data structures, both taught with Isabelle/HOL: 16 | - Semantics of Programming Languages https://www21.in.tum.de/teaching/semantics/WS23/index.html 17 | - Functional Data Structures https://www21.in.tum.de/teaching/fds/SS23/index.html 18 | - Practical Course ‘Specification and Verification’ https://www21.in.tum.de/teaching/psv/WS23/index.html 19 | - 10 years ago there was also a course at TUM on verifying C programs with Isabelle/HOL, taught by an external lecturer: https://www21.in.tum.de/teaching/isv/SS13/ 20 | - Formal Methods (UFMG) https://hanielb.github.io/2023.2-fm/ 21 | - Master Course on Advanced Functional Programming https://www.cs.uu.nl/docs/vakken/afp/ 22 | - CS6225 Programs and Proofs @ IITM (Coq + F*) https://www.youtube.com/playlist?list=PLt0HgEXFOHdkfd7phdKKmTIuwHEvPX0qb 23 | - CS5232: Formal Specification and Design Techniques https://ilyasergey.net/CS5232/index.html 24 | - CMSC631: Program Analysis and Understanding https://www.cs.umd.edu/class/fall2022/cmsc631/index.html 25 | 26 | 27 | -------------------------------------------------------------------------------- /other_courses/temp.md: -------------------------------------------------------------------------------- 1 | # University of Kitakyushu, Japan 2 | 3 | https://elixirforum.com/t/universities-teaching-beam-related-languages/26267/5 4 | 5 | https://speakerdeck.com/zacky1972/hastega-challenge-for-gpgpu-on-elixir-at-lonestar-elixirconf-2019?slide=5 6 | 7 | https://medium.com/@zacky1972/hastega-challenge-for-gpgpu-on-elixir-intend-to-apply-it-to-machine-learning-691c3560d179 8 | 9 | https://www.youtube.com/watch?v=lypqlGlK1So&feature=youtu.be 10 | 11 | 12 | # Sofia 13 | 14 | https://github.com/ElixirCourse 15 | 16 | https://twitter.com/valentinmihov/status/1182578371600871424?s=03 17 | 18 | # Japan 19 | 20 | 21 | 22 | adolfont: 23 | 24 | Is “Computer Systems, Digital System Design and Software for Embedded Systems” the name of the course? 25 | 26 | These are three courses: “Computer Systems”, “Digital System Design” and “Software for Embedded Systems” 27 | 28 | adolfont: 29 | 30 | Do you have a page in English for this course? 31 | 32 | I’m sorry because pages in English for these course are unavailable now but I’d like to create them as soon as possible. 33 | 34 | adolfont: 35 | 36 | Do you know the name of the professor? 37 | 38 | Prof. Akio Nakata, Dr. Yoshihiro Murata and Mr. Yasuomi Sato. 39 | -------------------------------------------------------------------------------- /other_courses/types_etc.md: -------------------------------------------------------------------------------- 1 | # Types and etc. 2 | 3 | - Introduction to Homotopy Type Theory, Egbert Rijke https://arxiv.org/abs/2212.11082 4 | - Categorical Logic and Type Theory https://www.cs.ru.nl/B.Jacobs/CLT/bookinfo.html 5 | - When Computers Write Proofs, What's the Point of Mathematicians? https://www.youtube.com/watch?v=3l1RMiGeTfU 6 | - Towards a Semantic Language of Mathematics https://www.youtube.com/watch?v=psSyM1zp82k 7 | - 22:30 4.1. Set theory, type theory, homotypy type theory, constructivism, and all that 8 | - 30:17 4.2. Typesystems for mathematics and propositions as types 9 | - Comment on Simply Easy! (An Implementation of a Dependently Typed Lambda Calculus) https://augustss.blogspot.com/2007/10/simpler-easier-in-recent-paper-simply.html 10 | - The Xena project https://www.ma.imperial.ac.uk/~buzzard/xena/ 11 | - [Types and Programming Languages, Benjamin C. Pierce](https://www.amazon.com.br/Types-Programming-Languages-Benjamin-Pierce/dp/0262162091/) 12 | - [Types and Programming Languages: The Next Generation (slides)](https://d1wqtxts1xzle7.cloudfront.net/42906352/tng-lics2003-slides-libre.pdf?1456077802=&response-content-disposition=inline%3B+filename%3DTypes_and_Programming_Languages_The_Next.pdf&Expires=1698698309&Signature=AGUDpeUYl6TEXAt-Hb~q1AzGfHEw1a3VerPD3Vg8znr9qVVl2Y9UY0umeQtQ78COx0nZ1NfIcVL6pp1i3mi9eYj366nKXWLcwnj4Us4SR2zaLhff0XKnXuMLQIq1fJIbfTWOohg4V8ABc37JO8czajqcRSJldSD9pBTu9TO4m9ljcmStGe2xnXk6LQprvvW5iAjpQdTo8gd26qMd0vCOolX5IBsff8srphLfgKJLBnfGlLtEfR4k8pO6h-u~yo5twbo7fDcinsGa~G23dg8P57eg-HdsSCX3HFZf26rWR6FVNYDioufT9guFIwtL~XvM8QZNu2uhJA7Gw9OIXu0crQ__&Key-Pair-Id=APKAJLOHF5GGSLRBV4ZA) 13 | - [The calculus of constructions, T. Coquand, Gérard Huet](https://inria.hal.science/inria-00076024/document) [via...](https://twitter.com/andreiformiga/status/1719064507786600618) 14 | -------------------------------------------------------------------------------- /stech2019/resumo.md: -------------------------------------------------------------------------------- 1 | # Elixir 2 | 3 | Linguagem brasileira conhecida no mundo todo 4 | 5 | Criador: José Valim 6 | - https://elixirforum.com/u/josevalim/summary 7 | - https://twitter.com/josevalim 8 | - https://github.com/josevalim 9 | 10 | Erlang 11 | 12 | Seven Languages in Sevem Weeks https://pragprog.com/book/btlang/seven-languages-in-seven-weeks 13 | 14 | Seven More Languages, inclui Elixir e Lua! https://pragprog.com/book/7lang/seven-more-languages-in-seven-weeks 15 | 16 | Ruby, Rails, Clojure 17 | 18 | Palestra do Hugo Baraúna https://www.infoq.com/br/presentations/como-uma-empresa-brasileira-criou-uma-linguagem-que-e-usada-no-mundo-inteiro/ 19 | 20 | BEAM e Erlang VM 21 | 22 | Livro grátis para quem tem email de universidade: https://pragprog.com/book/elixir16/programming-elixir-1-6 23 | 24 | Site de notícas sobre esportes que usa Elixir https://bleacherreport.com/ 25 | 26 | # Como aprender mais? 27 | 28 | ## Sites 29 | 30 | Elixir School em português https://elixirschool.com/pt/ 31 | 32 | ## Livros 33 | 34 | ### Em português 35 | 36 | Elixir: do zero à concorrência, Tiago Davi https://www.casadocodigo.com.br/products/livro-elixir?_pos=1&_sid=9a1f5238b&_ss=r 37 | 38 | ### Em inglês 39 | 40 | Programming Elixir 1.6, Dave Thomas https://pragprog.com/book/elixir16/programming-elixir-1-6. Grátis para quem tem email de universidade. 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /stech2019/stech_2019.md: -------------------------------------------------------------------------------- 1 | # Curso de Elixir na Semana Technológica 2 | 3 | ## O que é Elixir? 4 | 5 | - José Valim 6 | - Erlang, BEAM, multicore e concorrência 7 | - Programação Funcional 8 | 9 | ## Básico do Básico 10 | 11 | - iex 12 | - elixir arquivo.exs 13 | - Valores e Tipos 14 | - Variáveis e Casamento de Padrões 15 | - Funções e Módulos 16 | - Recursividade 17 | - Listas, Mapas 18 | - Enum 19 | 20 | ## Code Katas 21 | 22 | - [Maffetone](https://github.com/adolfont/introducao-a-programacao-funcional/blob/master/maffetone.md) 23 | 24 | - http://dojopuzzles.com/ 25 | - http://dojopuzzles.com/problemas/exibe/calculando-estatisticas-simples/ 26 | - http://dojopuzzles.com/problemas/exibe/fizzbuzz/ 27 | - http://dojopuzzles.com/problemas/exibe/numeros-romanos/ 28 | 29 | ## Pequeno Projeto 30 | 31 | - Link da Pyettra 32 | 33 | 34 | ## Links 35 | 36 | - Site da Semana Technológica http://semanatechnologica.dainf.ct.utfpr.edu.br/ 37 | - Página de minicursos http://semanatechnologica.dainf.ct.utfpr.edu.br/#minicursos 38 | - Versão da página em 08/11/2019 http://archive.is/yydFR 39 | -------------------------------------------------------------------------------- /stech2019/stech_slides.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | - Introdução a Elixir 4 | subtitle: 5 | - Linguagem brasileira utilizada em todo o mundo 6 | date: 7 | - 20 de novembro de 2019 8 | author: 9 | - Adolfo Neto 10 | theme: Copenhagen 11 | theme: Madrid 12 | colortheme: dolphin 13 | fontfamily: noto-sans 14 | aspectratio: 169 15 | header-includes: 16 | - \usepackage{cmbright} 17 | fontsize: 20pt 18 | --- 19 | 20 | # Exemplo de código 21 | 22 | ```elixir 23 | defmodule Matematica do 24 | def fatorial(1), do: 1 25 | def fatorial(x) when x>1 do 26 | x * fatorial(x-1) 27 | end 28 | end 29 | ``` 30 | 31 | # Instalação 32 | 33 | 34 | ## Linux 35 | 36 | Algumas distribuições têm pacotes atualizados. 37 | Eu uso Mint com [asdf](https://elixirschool.com/blog/asdf-version-management/). 38 | 39 | ## Windows 40 | 41 | [Instalação direta](https://repo.hex.pm/elixir-websetup.exe) ou usando [Chocolatey](https://chocolatey.org/). 42 | 43 | # Instalação 44 | 45 | ## MacOS 46 | 47 | [Brew or Macports](https://elixir-lang.org/install.html#macos) 48 | 49 | ## Outros 50 | 51 | Ver [Instalando Elixir](https://elixir-lang.org/install.html) 52 | 53 | # Verificando a versão instalada 54 | 55 | ``` 56 | elixir --version 57 | elixir -v 58 | ``` 59 | 60 | # Testando 61 | 62 | \small 63 | ``` 64 | > iex 65 | 66 | iex(1)> 4 + 5 67 | 9 68 | iex(2)> div(7,3) 69 | 2 70 | iex(3)> rem(7,3) 71 | 1 72 | ``` 73 | 74 | # Variáveis e Tipos Básicos 75 | 76 | - Inteiros 77 | - Números de Ponto Flutuante 78 | - Strings 79 | - Átomos 80 | 81 | # Casamento de Padrões 82 | 83 | 84 | 85 | # Funções predefinidas 86 | 87 | - Chamada de funções `Módulo.nome` 88 | 89 | - Kernel 90 | 91 | - (h)elp 92 | 93 | - Atom 94 | 95 | - String 96 | 97 | 111 | 112 | 113 | 114 | 115 | # Agradecimentos 116 | 117 | ## Projeto Emílias 118 | 119 | 120 | 121 | ## Elixir Forum 122 | 123 | 124 | 125 | ## Elixir Brasil no Telegram 126 | 127 | -------------------------------------------------------------------------------- /stech2019/stech_slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adolfont/caes005-introduction-to-functional-programming/a9b6de4534585a632113a1d960a9102c0715fb5c/stech2019/stech_slides.pdf -------------------------------------------------------------------------------- /topics/README.md: -------------------------------------------------------------------------------- 1 | # Functional Programming 2 | 3 | ## What is a mathematical function? 4 | 5 | ## What is a function in Computer Science? 6 | 7 | ## Which are teh features of functiona that are important for programming? 8 | 9 | ## What are types? 10 | 11 | ## What is the arity of a function? 12 | 13 | ## What is a module? 14 | 15 | ## What is functional programming? 16 | 17 | ## What is a recursive function? 18 | 19 | 20 | ## What is currying? 21 | 22 | ## What are higher-order functions? 23 | -------------------------------------------------------------------------------- /topics/control_flow.md: -------------------------------------------------------------------------------- 1 | # Control Flow 2 | 3 | - You should try not to use control flow constructs 4 | - Instead, write functions using guard clauses and pattern matching of parameters whenever possible. 5 | 6 | ## if and unless 7 | 8 | ## cond 9 | 10 | - list a series of conditions 11 | 12 | - FizzBuzz examples (Thomas, 2018) 13 | 14 | ## case 15 | 16 | - First pattern that matches 17 | - May include guard clauses 18 | 19 | ## raise 20 | 21 | - "exceptions in Elixir are not control-flow structures." (Thomas, 2018) 22 | 23 | - "The trailing exclamation point in the method name is an Elixir convention—if you see it, you know the function will raise an exception on error, and that exception will be meaningful." (Thomas, 2018) 24 | 25 | ## Examples 26 | 27 | - Philip Sampaio's Floki 28 | - https://github.com/philss/floki 29 | 30 | - Ulisses Almeida's CPF 31 | - https://github.com/ulissesalmeida/cpf/ 32 | - https://ulisses.dev/elixir/2019/10/31/annoucing-cpf-1-0-0.html 33 | 34 | - Matheus Gontijo's Validation 35 | - https://github.com/elixir-validation/validation 36 | 37 | 38 | # References 39 | 40 | [Programming Elixir 1.6: Functional |> Concurrent |> Pragmatic |> Fun, by Dave Thomas (2018)](http://bit.ly/2rqD9VF) 41 | -------------------------------------------------------------------------------- /topics/mix_task.md: -------------------------------------------------------------------------------- 1 | # Creating an Interactive command-line application using Mix Task 2 | 3 | ## Creating the Start task 4 | 5 | - [lib/mix/tasks/start.ex](https://media.pragprog.com/titles/cdc-elixir/code/design_your_application/tutorial/0/dungeon_crawl/lib/mix/tasks/start.ex) 6 | - [Using Mix.Shell.IO.info/1](http://media.pragprog.com/titles/cdc-elixir/code/design_your_application/tutorial/0/dungeon_crawl/lib/dungeon_crawl/cli/main.ex) 7 | - [Using Mix.Shell.IO.prompt/1](http://media.pragprog.com/titles/cdc-elixir/code/design_your_application/tutorial/1/dungeon_crawl/lib/dungeon_crawl/cli/main.ex) 8 | 9 | 10 | # References 11 | - CHAPTER 6 (Designing Your Elixir Applications) of Ulisses Almeida's book called [Learn Functional Programming with Elixir: New Foundations for a New World](http://bit.ly/ulisseslearningelixir). 12 | -------------------------------------------------------------------------------- /topics/pt/macros.md: -------------------------------------------------------------------------------- 1 | # Macros em Elixir 2 | 3 | Links: 4 | - https://elixir-lang.org/getting-started/meta/macros.html 5 | - https://elixirschool.com/pt/lessons/advanced/metaprogramming/ 6 | 7 | Macros devem ser usadas apenas em último caso! 8 | 9 | Vamos salvar o código em [macros.exs](https://github.com/adolfont/introducao-a-programacao-funcional/blob/master/examples/macros.exs) e executá-lo com `elixir macros.exs` 10 | ou com `iex macros.exs`. 11 | 12 | # Primeiro Teste 13 | 14 | ~~~ 15 | iex 16 | 17 | require AMenosQue 18 | 19 | AMenosQue.macro_amenosque true, do: IO.puts "Isto nunca deveria ser impresso!" 20 | 21 | AMenosQue.funcao_amenosque true, do: IO.puts "Isto nunca deveria ser impresso!" 22 | ~~~ 23 | 24 | ## Por que isto acontece? 25 | 26 | ~~~ 27 | iex(3)> AMenosQue.funcao_amenosque true, do: IO.puts "Isto nunca deveria ser impresso!" 28 | Isto nunca deveria ser impresso! 29 | nil 30 | 31 | 32 | ~~~ 33 | 34 | ## Veja o que está acontecendo 35 | 36 | ~~~ 37 | iex> 38 | 39 | expr = quote do: AMenosQue.macro_amenosque true, do: IO.puts "Isto nunca deveria ser impresso!" 40 | 41 | res = Macro.expand_once(expr, __ENV__) 42 | 43 | IO.puts Macro.to_string(res) 44 | ~~~ 45 | 46 | `unless/2` é implementado em Elixir como uma macro. 47 | 48 | `defmacro/2`, `def/2`, `defprotocol/2`, e muitos outros são implementados em Elixir puro, frequentemente como uma macro. 49 | 50 | -------------------------------------------------------------------------------- /topics/pt/mix1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adolfont/caes005-introduction-to-functional-programming/a9b6de4534585a632113a1d960a9102c0715fb5c/topics/pt/mix1.png -------------------------------------------------------------------------------- /topics/pt/phoenix.md: -------------------------------------------------------------------------------- 1 | # Phoenix 2 | 3 | Instalação 4 | https://hexdocs.pm/phoenix/installation.html#content 5 | 6 | Meetup Elixir CWB #4 7 | https://github.com/cwbelixir/meetup-4 8 | 9 | Aplicação exemplo 10 | https://github.com/cwbelixir/socker 11 | 12 | Pheonix Forum 13 | https://elixirforum.com/c/phoenix-forum 14 | 15 | ## Comandos 16 | 17 | mix archive.install hex phx_new 1.4.11 18 | 19 | sudo apt install nodejs 20 | 21 | mix phx.new hello 22 | 23 | cd hello 24 | 25 | mix ecto.create 26 | 27 | mix phx.server 28 | 29 | Access HelloWeb.Endpoint at http://localhost:4000 30 | 31 | -------------------------------------------------------------------------------- /topics/pt/processos.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Atores 4 | 5 | - Cada ator é um processo 6 | - Cada ator é um processo. 7 | - Cada processo executa uma tarefa específica. 8 | - Para instruir um processo a fazer algo, você precisa enviar uma mensagem para ele. 9 | O processo pode responder enviando de volta outra mensagem. 10 | - Os tipos de mensagens nas quais o processo pode atuar são específicos ao próprio processo. 11 | Em outras palavras, as mensagens passam por casamento de padrões. 12 | - Fora isso, os processos não compartilham nenhuma informação com outros processos. 13 | 14 | Fonte: The Little Elixir & OTP Guidebook https://www.goodreads.com/book/show/25563811-the-little-elixir-otp-guidebook 15 | 16 | 17 | # Processos 18 | 19 | - A unidade básica de concorrência em Elixir é o processo. 20 | - Não são processos nativos do sistema operacional. 21 | - `spawn/1` 22 | - `spawn/3` 23 | - `Process.info/2` 24 | 25 | ~~~elixir 26 | spawn(fn -> IO.puts("Hello, Alpha Centauri!") end) 27 | 28 | spawn(IO, :puts, ["Hello, Alpha Centauri!"]) 29 | 30 | spawn(fn -> IO.puts "Hello, World!" end) |> Process.info(:memory) 31 | ~~~ 32 | 33 | - PID: número de identificação do processo 34 | 35 | # Referências 36 | 37 | - Elixir Processes: Spawn, Send, and Receive https://samuelmullen.com/articles/elixir-processes-send-and-receive 38 | -------------------------------------------------------------------------------- /topics/sample_projects.md: -------------------------------------------------------------------------------- 1 | # Sample Projects 2 | 3 | ## Elixir 4 | 5 | - Leprechaun https://github.com/altenwald/leprechaun 6 | - Mine https://github.com/altenwald/mine https://mine.altenwald.com/ 7 | -------------------------------------------------------------------------------- /topics/strings_binaries_and_charlists_1.md: -------------------------------------------------------------------------------- 1 | # Strings, Binaries and Character Lists - part 1 2 | 3 | ## String Literals 4 | 5 | - Single-quoted and double-quoted 6 | - [UTF-8](https://en.wikipedia.org/wiki/UTF-8) 7 | - Escape sequences 8 | - #{...} syntax 9 | 10 | ### Exercise 11 | 12 | On iex: 13 | 14 | ```elixir 15 | IO.puts "\u00A9" 16 | name = "Adolfo" 17 | "Hello, #{String.capitalize name}\u2757" 18 | ``` 19 | 20 | ## Heredocs 21 | 22 | - """ 23 | - "Heredocs are used extensively to add documentation to functions and modules." (Thomas, 2018) 24 | 25 | - Run this with elixir https://gist.github.com/adolfont/f803d6014136bb94bf0daa8c5c2c9a47 26 | 27 | ## Sigils 28 | 29 | - Tilde 30 | - Upper- or lowercase letter 31 | - Delimited dontent ( <...> , {...} , [...] , (...) , |...| , /.../ , "..." , and '...') 32 | - optional options 33 | 34 | ```elixir 35 | ~C[1\n2#{1+2}] 36 | ~W[the c#{'a'}t sat on the mat] 37 | ~N{1999-12-31 23:59:59} 38 | ~w[the c#{'a'}t sat on the mat]s 39 | ``` 40 | 41 | - You can use heredocs 42 | - You can define your own sigils 43 | 44 | ## Strings vs. character lists 45 | 46 | - "In Elixir, the convention is that we call only double-quoted strings “strings.” The single-quoted form is a character list." (Thomas, 2018) 47 | 48 | ### Single-Quoted Strings—Lists of Character Codes 49 | 50 | - "IEx says it is a list, but it shows the value as a string" (Thomas, 2018) 51 | 52 | ```elixir 53 | [ 67, 65, 84 ] 54 | ``` 55 | 56 | - "The notation ?c returns the integer code for the character c" (Thomas, 2018) 57 | 58 | - "Because a character list is a list, we can use the usual pattern matching and List functions" (Thomas, 2018). See [parse.exs](http://media.pragprog.com/titles/elixir16/code/strings/parse.exs) 59 | 60 | 61 | # References 62 | 63 | [Programming Elixir 1.6: Functional |> Concurrent |> Pragmatic |> Fun, by Dave Thomas (2018)](http://bit.ly/2rqD9VF) 64 | -------------------------------------------------------------------------------- /topics/strings_binaries_and_charlists_2.md: -------------------------------------------------------------------------------- 1 | # Strings, Binaries and Character Lists - part 2 2 | 3 | [Strings, Binaries and Character Lists - part 1](https://github.com/adolfont/introducao-a-programacao-funcional/blob/master/topics/strings_binaries_and_charlists_1.md) 4 | 5 | ## Binaries 6 | 7 | - A sequence of bits 8 | - << term,... >> 9 | - "The simplest term is just a number from 0 to 255" (Thomas, 2018) 10 | - byte_size, bit_syze 11 | 12 | ```elixir 13 | b = << 1, 2, 3 >> 14 | {byte_size(b), bit_size(b)} 15 | b = << 1::size(2), 1::size(3) >> 16 | {byte_size(b), bit_size(b)} 17 | ``` 18 | 19 | ```elixir 20 | int = << 1 >> 21 | float = << 2.5 :: float >> 22 | mix = << int :: binary, float :: binary >> 23 | ``` 24 | 25 | - [IEEE 754: IEEE Standard for Floating-Point Arithmetic](https://en.wikipedia.org/wiki/IEEE_754) 26 | - "An IEEE 754 float has a sign bit, 11 bits of exponent, and 52 bits of mantissa. The exponent is biased by 1023, and the mantissa is a fraction with the top bit assumed to be 1." (Thomas, 2018) 27 | 28 | ```elixir 29 | << sign::size(1), exp::size(11), mantissa::size(52) >> = << 3.14159::float >> 30 | {sign, exp, mantissa} 31 | (1 + mantissa / :math.pow(2, 52)) * :math.pow(2, exp-1023) * (1 - 2*sign) 32 | ``` 33 | 34 | ## Double-Quoted Strings Are Binaries 35 | 36 | - a consecutive sequence of bytes in UTF-8 encoding 37 | 38 | ```elixir 39 | formula = "∀x,∃y(p(x,y))" 40 | String.length formula 41 | byte_size formula 42 | String.at(formula, 0) 43 | String.codepoints(formula) 44 | String.split(formula, "(") 45 | String.split(formula, ["(",")"]) 46 | ``` 47 | 48 | ## Strings and Elixir Libraries 49 | 50 | - "When Elixir library documentation uses the word string (and most of the time it uses the word binary), it means double-quoted strings." (Thomas, 2018) 51 | - [String module: double-quoted strings](https://hexdocs.pm/elixir/String.html) 52 | 53 | ```elixir 54 | String.ends_with? "adolfo", ["olfo", "ad", "elf"] 55 | String.jaro_distance("adolfo", "rodolfo") 56 | String.myers_difference("brasil", "brazil") 57 | ``` 58 | 59 | ## Binaries and Pattern Matching 60 | 61 | - "The first rule of binaries is “if in doubt, specify the type of each field.”" (Thomas, 2018) 62 | 63 | - Types: binary, bits, bitstring, bytes, float, integer, utf8, utf16, utf32. 64 | - Qualifiers: 65 | - size(n) 66 | - signed or unsigned 67 | - endianness 68 | - Hyphens 69 | 70 | ### String Processing with Binaries 71 | 72 | - << head :: utf8, tail :: binary >> 73 | - [utf-iterate.ex](http://media.pragprog.com/titles/elixir16/code/strings/utf-iterate.ex) 74 | 75 | ## Strings and Erlang 76 | 77 | - "String handling in Elixir is the result of a long evolutionary process in the underlying Erlang environment." (Thomas, 2018) 78 | 79 | # References 80 | 81 | [Programming Elixir 1.6: Functional |> Concurrent |> Pragmatic |> Fun, by Dave Thomas (2018)](http://bit.ly/2rqD9VF) 82 | --------------------------------------------------------------------------------