├── .gitattributes ├── LICENSE ├── README.md └── python-challenge1 ├── Challenge_Dados_-_Fevereiro.pdf ├── nb_challenge1_python.ipynb └── script_solution1.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Bruno de Oliveira Feitosa 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Reúne os desafios lançados no Let's Code Pass 2 | Para mais informações, entre em nossa comunidade se inscrevendo em nosso [site](https://letscode.com.br/lets-code-pass) 3 | 4 | ## python-challenge1 5 | O primeiro desafio é aplicação do **Método Twist** para codificação e decodificação de mensagens. Mais informações em `Challenge_Dados_-_Fevereiro.pdf` 6 | 7 | `nb_challenge1_python.ipynb`: notebook com enunciado e solução passo a passo.
8 | `script_solution1.py`: script com a solução do problema. 9 | -------------------------------------------------------------------------------- /python-challenge1/Challenge_Dados_-_Fevereiro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Letscode-br/lc-challenges-python/f332881498919ab86a3651fd3d2f121615999d55/python-challenge1/Challenge_Dados_-_Fevereiro.pdf -------------------------------------------------------------------------------- /python-challenge1/nb_challenge1_python.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Challenge 1 - Python\n", 8 | "\n", 9 | "Fala, pessoal! Sejam muito bem-vindos ao 1º Challenge de Python disponibilizado no Let’s Code Pass! Você deve estar acompanhando as Short Classes de Web e, agora, é hora de colocar seus novos conhecimentos em prática! Vamos nessa?! 🚀\n", 10 | "\n", 11 | "Antes de tudo, é válido destacar que por se tratar de um desafio, é essencial que você troque uma ideia com outras pessoas, caso sinta dificuldades, ou mesmo possa utilizar do nosso servidor do Discord para enviar suas dúvidas. Ah, claro, você também pode ficar de olho nas dúvidas de outras pessoas para ajudá-las. Tudo isso vai te ajudar a avançar cada vez mais rumo ao seu objetivo!\n", 12 | "\n", 13 | "## Conhecendo o Challenge\n", 14 | "\n", 15 | "### Criptografia via método de substituição (Twist)\n", 16 | "\n", 17 | "Criptografia é uma área da Ciência da Computação que estuda os métodos de comunicação secreta que transformam uma mensagem (**textoplano**) em uma mensagem cifrada (**textocifrado**), de forma que apenas o real receptor da mensagem seja capaz de restaurar o seu conteúdo original.\n", 18 | "\n", 19 | "O ato de transformar uma mensagem em uma mensagem cifrada é chamado de **codificação** e o ato contrário é chamado de **decodificação**. Um método bastante simples de codificação é o **Método Twist**, que requer que ambos: remetente e receptor combinem uma **chave secreta k**, que deve ser um inteiro positivo (1, 2, 3, 4, ...).\n", 20 | "\n", 21 | "O **Método Twist** utiliza quatro listas: **textoplano**, **textocifrado**, **codigoplano** e **cifradocodigo**, sendo  **textoplano** e **textocifrado** listas de caracteres e **codigoplano** e **cifradocodigo** listas de inteiros. Todas as listas têm tamanho **n**, onde **n** é o tamanho da mensagem a ser codificada (as listas são iniciadas na posição zero de forma que seus elementos são numerados de 0 a n – 1). Para este problema, as mensagens apenas conterão letras minúsculas, pontos e “barra baixa” (underscore, representando espaço em branco).\n", 22 | "\n", 23 | "A mensagem a ser codificada é armazenada na lista **textoplano**. Dada a **chave k**, a codificação é feita da  seguinte forma: \n", 24 | "\n", 25 | "1. Primeiro as letras em **textoplano** são convertidas em códigos inteiros que são armazenados em **codigoplano**. A conversão é feita da seguinte forma:\n", 26 | "
\n", 27 | "'_' = 0, 'a' = 1, 'b' = 2, ..., 'z' = 26 e '.' = 27\n", 28 | "
\n", 29 | "2. Depois, cada código em **codigoplano** é convertido em um código codificado em **cifradocodigo** através da seguinte fórmula:\n", 30 | "\n", 31 | "Para todo i de 0 a n – 1,\n", 32 | "$$\n", 33 | "cifradocodigo[i] = (codigoplano[(k * i) mod n] – i) mod 28\n", 34 | "$$\n", 35 | "\n", 36 | "A decodificação é realizada de maneira análoga (usando-se um inverso multiplicativo modular), devendo-se fazer\n", 37 | "$$\n", 38 | "codigoplano[(k * i) mod n] = (cifradocodigo[i] + i) mod 28\n", 39 | "$$\n", 40 | "Aqui x mod y é o resto da divisão de x por y; por exemplo,\n", 41 | "
\n", 42 | "\n", 43 | "$3 mod 7 = 3$ \n", 44 | "\n", 45 | "$22 mod 8 = 6$ \n", 46 | "\n", 47 | "$-1 mod 28 = 27$\n", 48 | "
\n", 49 | "\n", 50 | "Você pode usar o operador `%` do Python como sendo $mod$.\n", 51 | "\n", 52 | "3. Por último, os códigos obtidos em **cifradocodigo** são convertidos novamente em letras (pela mesma regra descrita anteriormente e detalhada na dica 1 abaixo) e são armazenadas em **textocifrado**. Esse método funciona apenas quando **n** e **k** são primos entre si; essa propriedade é necessária para garantir que a mensagem decodificada corresponderá à mensagem original (não se preocupem em garantir que eles sejam primos).\n", 53 | "\n", 54 | "A codificação pelo métodos Twist das mensagens `'ola'` e `'wxyz'`, ambas usando a chave 5, são ilustradas na tabela a seguir:\n", 55 | "\n", 56 | "- **exemplo 1 : 'ola'**\n", 57 | "\n", 58 | "| Vetor | [0] | [1] | [2] |\n", 59 | "| --- | --- | --- | --- |\n", 60 | "| textoplano | 'o' | 'l' | 'a' |\n", 61 | "| codigoplano | 15 | 12 | 1 |\n", 62 | "| cifradocodigo | 15 | 0 | 10 |\n", 63 | "| textocifrado | 'o' | '_' | 'j' |\n", 64 | "\n", 65 | "- **exemplo 2 : 'wxyz'**\n", 66 | "\n", 67 | "| Vetor | [0] | [1] | [2] | [3] |\n", 68 | "| --- | --- | --- | --- | --- |\n", 69 | "| textoplano | 'w' | 'x' | 'y' | 'z' |\n", 70 | "| codigoplano | 23 | 24 | 25 | 26 |\n", 71 | "| cifradocodigo | 23 | 23 | 23 | 23 |\n", 72 | "| textocifrado | 'w'| 'w' | 'w' | 'w' |\n", 73 | "\n", 74 | "**Dicas sobre manipulação de caracteres**\n", 75 | "\n", 76 | "Em Python pode-se utilizar duas funções pré-definidas para manipular caracteres e seu código numérico correspondente.\n", 77 | "\n", 78 | "Por exemplo, o caractere/dígito ‘0’ tem código 48, o caractere/dígito ‘1’ tem código 49 e assim por diante (esses valores vêm do “velho” sistema de codificação [ASCII](https://www.asciitable.com/) – American Standard Code for Interchange, que usava 8 bits). \n", 79 | "\n", 80 | "Então pode-se usar as funções `ord(char)` e `chr(int)`, a primeira, dado o caractere **C**, devolve seu código e a segunda, dada um inteiro **N** devolve o caractere cujo código é **N**. Experimente o seguinte código em Python:\n", 81 | "\n", 82 | "```python\n", 83 | "def converteInt2Char(k): # k deve ser inteiro`\n", 84 | "\n", 85 | " return chr(k) # devolve o caractere associado a k`\n", 86 | "\n", 87 | "def converteChar2Int(c): # c deve ser caractere`\n", 88 | "\n", 89 | " return ord(c) # devolve o código inteiro associado ao caractere c`\n", 90 | "\n", 91 | "print(f\"N | converteInt2Char(N)\\n48 | {converteInt2Char(48)}\\n49 | {converteInt2Char(49)}\\nC | converteChar2Int(C)\\n'0'| {converteChar2Int('0')}\\n'1'| {converteChar2Int('1')}\")\n", 92 | "```\n", 93 | "\n", 94 | "\n", 95 | "> 💡 Você pode solucionar o Challenge sem uso das funções `ord()` e `chr()`, se preferir.\n", 96 | "\n", 97 | "\n", 98 | "## Requisitos Funcionais\n", 99 | "\n", 100 | "Sua tarefa é escrever um programa que codifica e decodifica uma mensagem usando **Método Twist**. Inicialmente o usuário escolhe a opção 0 (codifica) ou 1 (decodifica), sendo:\n", 101 | "\n", 102 | "- Para a opção 0: o usuário deve, em seguida, digitar o valor **k** da chave e depois uma frase (que será codificada);\n", 103 | "- Para a opção 1: o usuário deve, em seguida, digitar o valor **k** da chave e depois uma frase (que será decodificada).\n", 104 | "\n", 105 | "Por exemplo, se o usuário digitar:\n", 106 | "\n", 107 | "`1`\n", 108 | "\n", 109 | "`5` \n", 110 | "\n", 111 | "`'o_j'`\n", 112 | "\n", 113 | "Seu programa deve invocar a função de decodificação (com os parâmetros adequados e devolver `'ola'` (correspondendo ao texto decodificado). Então o programa deve imprimir o texto original (decodificando) `'ola'`. Se, por outro lado, o usuário digitar:\n", 114 | "\n", 115 | " > `0`\n", 116 | "\n", 117 | " > `5`\n", 118 | "\n", 119 | " > `'wxyz'`\n", 120 | "\n", 121 | " o programa deve imprimir `'wwww'`.\n", 122 | "\n", 123 | "## Entrada e Saída de Dados\n", 124 | "\n", 125 | "A entrada será via teclado. Primeiramente deve-se digitar a opção (0 ou 1), depois digita-se a chave **k** e por último a mensagem (a ser codificada ou decodificada).\n", 126 | "\n", 127 | " Pode-se supor que o tamanho da mensagem **n** esteja entre 1 e 70 caracteres. A chave **k** será um inteiro positivo menor ou igual a 300 que seja primo com o tamanho **n**, ou seja, mdc(k, n) = 1. Abaixo apresentamos 3 exemplos de codificações/decodificações, para as chaves 5, 11 e 29.\n", 128 | "\n", 129 | "| Chave | Frase original | Frase codificada |\n", 130 | "| --- | --- | --- |\n", 131 | "| 11 | cachorro. | cbmowxbkg |\n", 132 | "| 29 | espero_que_funcione. | edcnkjyzmjrpianvbyzo |\n", 133 | "\n", 134 | "
\n", 135 | "\n", 136 | "> 💡 Os códigos dos caracteres são sequências, sendo `97` o código do `‘a’`, `98` o código do `‘b’` e > assim por diante. Neste Challenge pode-se supor que serão digitados apenas letras minúsculas (logo > entre `'a'` e `'z`), ponto `'.'` ou “barra baixa” `'_'`.\n", 137 | "\n", 138 | "\n", 139 | "Abaixo ilustraremos como seriam as mensagens de seu programa para o primeiro exemplo da tabela acima. Atenção, tente copiar precisamente as mensagens como aparecem, pois caracteres errados podem produzir erros.\n", 140 | "\n", 141 | "**1. Exemplo de codificação.**\n", 142 | "```python\n", 143 | "Digite 0 para codificar e 1 para decodificar: 0\n", 144 | "Digite a chave: 29\n", 145 | "Digite a mensagem: espero_que_funcione.\n", 146 | "Frase final: edcnkjyzmjrpianvbyzo\n", 147 | "```\n", 148 | "\n", 149 | "**2. Exemplo de decodificação.**\n", 150 | "```python\n", 151 | "Digite 0 para codificar e 1 para decodificar: 1\n", 152 | "Digite a chave: 29\n", 153 | "Digite a mensagem: edcnkjyzmjrpianvbyzo\n", 154 | "Frase final: espero_que_funcione.\n", 155 | "```\n", 156 | "\n", 157 | "## Referência\n", 158 | "\n", 159 | "Baseado em um trabalho pedido em cursos da USP pelo Departamento de Ciência da Computação (DCC)." 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": 4, 165 | "metadata": {}, 166 | "outputs": [], 167 | "source": [ 168 | "# Imprimir todos valores da célula, não somente o último\n", 169 | "from IPython.core.interactiveshell import InteractiveShell\n", 170 | "\n", 171 | "InteractiveShell.ast_node_interactivity = \"all\"" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "# Solução - uso de chr() e ord()" 179 | ] 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "metadata": {}, 184 | "source": [ 185 | "Entendendo o uso das funções `ord()` e `chr()`." 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": 1, 191 | "metadata": {}, 192 | "outputs": [], 193 | "source": [ 194 | "def converteInt2Char(k): # k deve ser inteiro`\n", 195 | "\n", 196 | " return chr(k) # devolve o caractere associado a k`\n", 197 | "\n", 198 | "def converteChar2Int(c): # c deve ser caractere`\n", 199 | "\n", 200 | " return ord(c) # devolve o código inteiro associado ao caractere c`" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": 6, 206 | "metadata": {}, 207 | "outputs": [ 208 | { 209 | "name": "stdout", 210 | "output_type": "stream", 211 | "text": [ 212 | "_ = 95\n", 213 | ". = 46\n", 214 | "a = 97\n", 215 | "b = 98\n", 216 | "c = 99\n", 217 | "z = 122\n" 218 | ] 219 | } 220 | ], 221 | "source": [ 222 | "print(f\"_ = {converteChar2Int('_')}\")\n", 223 | "print(f\". = {converteChar2Int('.')}\")\n", 224 | "print(f\"a = {converteChar2Int('a')}\")\n", 225 | "print(f\"b = {converteChar2Int('b')}\")\n", 226 | "print(f\"c = {converteChar2Int('c')}\")\n", 227 | "print('...')\n", 228 | "print(f\"z = {converteChar2Int('z')}\")\n" 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": 27, 234 | "metadata": {}, 235 | "outputs": [ 236 | { 237 | "name": "stdout", 238 | "output_type": "stream", 239 | "text": [ 240 | "95 = _\n", 241 | "46 = .\n", 242 | "97 = a\n", 243 | "98 = b\n", 244 | "99 = c\n", 245 | "...\n", 246 | "122 = z\n" 247 | ] 248 | } 249 | ], 250 | "source": [ 251 | "def converteInt2Char(numero): # numero deve ser inteiro`\n", 252 | "\n", 253 | " return chr(numero) # devolve o caractere associado ao numero`\n", 254 | "\n", 255 | "print(f\"95 = {converteInt2Char(95)}\")\n", 256 | "print(f\"46 = {converteInt2Char(46)}\")\n", 257 | "print(f\"97 = {converteInt2Char(97)}\")\n", 258 | "print(f\"98 = {converteInt2Char(98)}\")\n", 259 | "print(f\"99 = {converteInt2Char(99)}\")\n", 260 | "print('...')\n", 261 | "print(f\"122 = {converteInt2Char(122)}\")" 262 | ] 263 | }, 264 | { 265 | "cell_type": "markdown", 266 | "metadata": {}, 267 | "source": [ 268 | "Mas segundo o enunciado, a correspondência deve ser:\n", 269 | "\n", 270 | "
\n", 271 | "'_' = 0, 'a' = 1, 'b' = 2, ..., 'z' = 26 e '.' = 27\n", 272 | "
\n", 273 | "\n", 274 | "Então é preciso fazer uma correção do valor retornado:" 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": 11, 280 | "metadata": {}, 281 | "outputs": [ 282 | { 283 | "name": "stdout", 284 | "output_type": "stream", 285 | "text": [ 286 | "_ = 0\n", 287 | ". = 27\n", 288 | "a = 1\n", 289 | "b = 2\n", 290 | "c = 3\n", 291 | "...\n", 292 | "z = 26\n" 293 | ] 294 | } 295 | ], 296 | "source": [ 297 | "def converte_char_int(char):\n", 298 | " if char == '.':\n", 299 | " return 27\n", 300 | " elif char == '_':\n", 301 | " return 0\n", 302 | " return ord(char) - 96\n", 303 | "\n", 304 | "print(f\"_ = {converte_char_int('_')}\")\n", 305 | "print(f\". = {converte_char_int('.')}\")\n", 306 | "print(f\"a = {converte_char_int('a')}\")\n", 307 | "print(f\"b = {converte_char_int('b')}\")\n", 308 | "print(f\"c = {converte_char_int('c')}\")\n", 309 | "print('...')\n", 310 | "print(f\"z = {converte_char_int('z')}\")" 311 | ] 312 | }, 313 | { 314 | "cell_type": "code", 315 | "execution_count": 29, 316 | "metadata": {}, 317 | "outputs": [ 318 | { 319 | "name": "stdout", 320 | "output_type": "stream", 321 | "text": [ 322 | "0 = _\n", 323 | "27 = .\n", 324 | "1 = a\n", 325 | "2 = b\n", 326 | "3 = c\n", 327 | "...\n", 328 | "26 = z\n" 329 | ] 330 | } 331 | ], 332 | "source": [ 333 | "def converte_int_char(inteiro):\n", 334 | " if inteiro == 27:\n", 335 | " return '.'\n", 336 | " elif inteiro == 0:\n", 337 | " return '_'\n", 338 | " return chr(inteiro + 96) \n", 339 | "\n", 340 | "print(f\"0 = {converte_int_char(0)}\")\n", 341 | "print(f\"27 = {converte_int_char(27)}\")\n", 342 | "print(f\"1 = {converte_int_char(1)}\")\n", 343 | "print(f\"2 = {converte_int_char(2)}\")\n", 344 | "print(f\"3 = {converte_int_char(3)}\")\n", 345 | "print('...')\n", 346 | "print(f\"26 = {converte_int_char(26)}\")" 347 | ] 348 | }, 349 | { 350 | "cell_type": "markdown", 351 | "metadata": {}, 352 | "source": [ 353 | "## Codificação" 354 | ] 355 | }, 356 | { 357 | "cell_type": "markdown", 358 | "metadata": {}, 359 | "source": [ 360 | "**Exemplo k = 5**\n", 361 | "\n", 362 | "| Vetor | [0] | [1] | [2] |\n", 363 | "| --- | --- | --- | --- |\n", 364 | "| textoplano | 'o' | 'l' | 'a' |\n", 365 | "| codigoplano | 15 | 12 | 1 |\n", 366 | "| cifradocodigo | 15 | 0 | 10 |\n", 367 | "| textocifrado | 'o' | '_' | 'j' |\n" 368 | ] 369 | }, 370 | { 371 | "cell_type": "code", 372 | "execution_count": null, 373 | "metadata": {}, 374 | "outputs": [], 375 | "source": [ 376 | "textoplano = 'ola'\n", 377 | "chave_k = 5" 378 | ] 379 | }, 380 | { 381 | "cell_type": "markdown", 382 | "metadata": {}, 383 | "source": [ 384 | "Montar a lista `textoplano`" 385 | ] 386 | }, 387 | { 388 | "cell_type": "code", 389 | "execution_count": 48, 390 | "metadata": {}, 391 | "outputs": [ 392 | { 393 | "data": { 394 | "text/plain": [ 395 | "['o', 'l', 'a']" 396 | ] 397 | }, 398 | "execution_count": 48, 399 | "metadata": {}, 400 | "output_type": "execute_result" 401 | } 402 | ], 403 | "source": [ 404 | "lista_textoplano = list('ola')\n", 405 | "lista_textoplano" 406 | ] 407 | }, 408 | { 409 | "cell_type": "markdown", 410 | "metadata": {}, 411 | "source": [ 412 | "Codificar cada caractere de textoplano em código" 413 | ] 414 | }, 415 | { 416 | "cell_type": "code", 417 | "execution_count": 46, 418 | "metadata": {}, 419 | "outputs": [ 420 | { 421 | "data": { 422 | "text/plain": [ 423 | "[15, 12, 1]" 424 | ] 425 | }, 426 | "execution_count": 46, 427 | "metadata": {}, 428 | "output_type": "execute_result" 429 | } 430 | ], 431 | "source": [ 432 | "# versão 1 com uso de loop for\n", 433 | "codigoplano = []\n", 434 | "for caractere in lista_textoplano:\n", 435 | " codigoplano.append(converte_char_int(caractere))\n", 436 | " \n", 437 | "codigoplano" 438 | ] 439 | }, 440 | { 441 | "cell_type": "code", 442 | "execution_count": 47, 443 | "metadata": {}, 444 | "outputs": [ 445 | { 446 | "data": { 447 | "text/plain": [ 448 | "[15, 12, 1]" 449 | ] 450 | }, 451 | "execution_count": 47, 452 | "metadata": {}, 453 | "output_type": "execute_result" 454 | } 455 | ], 456 | "source": [ 457 | "# versão 2 com uso de list comprehension\n", 458 | "codigoplano = [converte_char_int(caractere) for caractere in lista_textoplano]\n", 459 | "codigoplano" 460 | ] 461 | }, 462 | { 463 | "cell_type": "markdown", 464 | "metadata": {}, 465 | "source": [ 466 | "Conversão de `codigoplano` em `cifradocodigo`" 467 | ] 468 | }, 469 | { 470 | "cell_type": "code", 471 | "execution_count": 24, 472 | "metadata": {}, 473 | "outputs": [ 474 | { 475 | "data": { 476 | "text/plain": [ 477 | "[None, None, None]" 478 | ] 479 | }, 480 | "execution_count": 24, 481 | "metadata": {}, 482 | "output_type": "execute_result" 483 | } 484 | ], 485 | "source": [ 486 | "# construção de lista com dimensão suficiente para guardar os valores de codigoplano\n", 487 | "n_tam_msg = len(codigoplano)\n", 488 | "cifradocodigo = [None]*n_tam_msg\n", 489 | "cifradocodigo[: 10]" 490 | ] 491 | }, 492 | { 493 | "cell_type": "code", 494 | "execution_count": 25, 495 | "metadata": {}, 496 | "outputs": [ 497 | { 498 | "data": { 499 | "text/plain": [ 500 | "[15, 0, 10]" 501 | ] 502 | }, 503 | "execution_count": 25, 504 | "metadata": {}, 505 | "output_type": "execute_result" 506 | } 507 | ], 508 | "source": [ 509 | "for i in range(n_tam_msg):\n", 510 | " cifradocodigo[i] = (codigoplano[(chave_k * i) % n_tam_msg] - i) % 28\n", 511 | " \n", 512 | "cifradocodigo" 513 | ] 514 | }, 515 | { 516 | "cell_type": "markdown", 517 | "metadata": {}, 518 | "source": [ 519 | "Conversão de `cifradocodigo` em `textocifrado`" 520 | ] 521 | }, 522 | { 523 | "cell_type": "code", 524 | "execution_count": 31, 525 | "metadata": {}, 526 | "outputs": [ 527 | { 528 | "data": { 529 | "text/plain": [ 530 | "['o', '_', 'j']" 531 | ] 532 | }, 533 | "execution_count": 31, 534 | "metadata": {}, 535 | "output_type": "execute_result" 536 | }, 537 | { 538 | "data": { 539 | "text/plain": [ 540 | "'o_j'" 541 | ] 542 | }, 543 | "execution_count": 31, 544 | "metadata": {}, 545 | "output_type": "execute_result" 546 | } 547 | ], 548 | "source": [ 549 | "lista_textocifrado = [converte_int_char(cod) for cod in cifradocodigo]\n", 550 | "lista_textocifrado\n", 551 | "\n", 552 | "textocifrado = ''.join(lista_textocifrado)\n", 553 | "textocifrado" 554 | ] 555 | }, 556 | { 557 | "cell_type": "markdown", 558 | "metadata": {}, 559 | "source": [ 560 | "## Decodificação" 561 | ] 562 | }, 563 | { 564 | "cell_type": "markdown", 565 | "metadata": {}, 566 | "source": [ 567 | "**Exemplo k = 5**\n", 568 | "\n", 569 | "| Vetor | [0] | [1] | [2] |\n", 570 | "| --- | --- | --- | --- |\n", 571 | "| textoplano | 'o' | 'l' | 'a' |\n", 572 | "| codigoplano | 15 | 12 | 1 |\n", 573 | "| cifradocodigo | 15 | 0 | 10 |\n", 574 | "| textocifrado | 'o' | '_' | 'j' |" 575 | ] 576 | }, 577 | { 578 | "cell_type": "code", 579 | "execution_count": 37, 580 | "metadata": {}, 581 | "outputs": [], 582 | "source": [ 583 | "textocifrado = 'o_j'\n", 584 | "chave_k = 5" 585 | ] 586 | }, 587 | { 588 | "cell_type": "markdown", 589 | "metadata": {}, 590 | "source": [ 591 | "Converter `textocifrado` em lista" 592 | ] 593 | }, 594 | { 595 | "cell_type": "code", 596 | "execution_count": 38, 597 | "metadata": {}, 598 | "outputs": [ 599 | { 600 | "data": { 601 | "text/plain": [ 602 | "['o', '_', 'j']" 603 | ] 604 | }, 605 | "execution_count": 38, 606 | "metadata": {}, 607 | "output_type": "execute_result" 608 | } 609 | ], 610 | "source": [ 611 | "lista_textocifrado = list(textocifrado)\n", 612 | "lista_textocifrado" 613 | ] 614 | }, 615 | { 616 | "cell_type": "markdown", 617 | "metadata": {}, 618 | "source": [ 619 | "Converter `lista_textocifrado` em `cifradocodigo`" 620 | ] 621 | }, 622 | { 623 | "cell_type": "code", 624 | "execution_count": 39, 625 | "metadata": {}, 626 | "outputs": [ 627 | { 628 | "data": { 629 | "text/plain": [ 630 | "[15, 0, 10]" 631 | ] 632 | }, 633 | "execution_count": 39, 634 | "metadata": {}, 635 | "output_type": "execute_result" 636 | } 637 | ], 638 | "source": [ 639 | "# versão 2 com uso de list comprehension\n", 640 | "cifradocodigo = [converte_char_int(caractere) for caractere in lista_textocifrado]\n", 641 | "cifradocodigo" 642 | ] 643 | }, 644 | { 645 | "cell_type": "markdown", 646 | "metadata": {}, 647 | "source": [ 648 | "Converter `cifradocodigo` em `codigoplano`" 649 | ] 650 | }, 651 | { 652 | "cell_type": "code", 653 | "execution_count": 40, 654 | "metadata": {}, 655 | "outputs": [ 656 | { 657 | "data": { 658 | "text/plain": [ 659 | "[None, None, None]" 660 | ] 661 | }, 662 | "execution_count": 40, 663 | "metadata": {}, 664 | "output_type": "execute_result" 665 | } 666 | ], 667 | "source": [ 668 | "# construção de lista com dimensão suficiente para guardar os valores de cifradocodigo\n", 669 | "n_tam_msg = len(cifradocodigo)\n", 670 | "codigoplano = [None]*n_tam_msg\n", 671 | "codigoplano" 672 | ] 673 | }, 674 | { 675 | "cell_type": "code", 676 | "execution_count": 41, 677 | "metadata": {}, 678 | "outputs": [ 679 | { 680 | "data": { 681 | "text/plain": [ 682 | "[15, 12, 1]" 683 | ] 684 | }, 685 | "execution_count": 41, 686 | "metadata": {}, 687 | "output_type": "execute_result" 688 | } 689 | ], 690 | "source": [ 691 | "for i in range(n_tam_msg):\n", 692 | " codigoplano[(chave_k * i) % n_tam_msg] = (cifradocodigo[i] + i) % 28\n", 693 | " \n", 694 | "codigoplano" 695 | ] 696 | }, 697 | { 698 | "cell_type": "markdown", 699 | "metadata": {}, 700 | "source": [ 701 | "Converter `codigoplano` em `textoplano`" 702 | ] 703 | }, 704 | { 705 | "cell_type": "code", 706 | "execution_count": 43, 707 | "metadata": {}, 708 | "outputs": [ 709 | { 710 | "data": { 711 | "text/plain": [ 712 | "['o', 'l', 'a']" 713 | ] 714 | }, 715 | "execution_count": 43, 716 | "metadata": {}, 717 | "output_type": "execute_result" 718 | } 719 | ], 720 | "source": [ 721 | "lista_textoplano = [converte_int_char(cod) for cod in codigoplano]\n", 722 | "lista_textoplano" 723 | ] 724 | }, 725 | { 726 | "cell_type": "code", 727 | "execution_count": 44, 728 | "metadata": {}, 729 | "outputs": [ 730 | { 731 | "data": { 732 | "text/plain": [ 733 | "'ola'" 734 | ] 735 | }, 736 | "execution_count": 44, 737 | "metadata": {}, 738 | "output_type": "execute_result" 739 | } 740 | ], 741 | "source": [ 742 | "textoplano = ''.join(lista_textoplano)\n", 743 | "textoplano" 744 | ] 745 | } 746 | ], 747 | "metadata": { 748 | "interpreter": { 749 | "hash": "3d536ceee5838dd42851cf32b43d922eee13546d285c4374e489f5361fd15b8b" 750 | }, 751 | "kernelspec": { 752 | "display_name": "Python 3.6.13 ('lets-data')", 753 | "language": "python", 754 | "name": "python3" 755 | }, 756 | "language_info": { 757 | "codemirror_mode": { 758 | "name": "ipython", 759 | "version": 3 760 | }, 761 | "file_extension": ".py", 762 | "mimetype": "text/x-python", 763 | "name": "python", 764 | "nbconvert_exporter": "python", 765 | "pygments_lexer": "ipython3", 766 | "version": "3.6.13" 767 | }, 768 | "orig_nbformat": 4 769 | }, 770 | "nbformat": 4, 771 | "nbformat_minor": 2 772 | } 773 | -------------------------------------------------------------------------------- /python-challenge1/script_solution1.py: -------------------------------------------------------------------------------- 1 | ################ Funções Twist ################ 2 | 3 | def converte_char_int(caractere): 4 | """Converte um caractere para um inteiro segundo a tabela ASCII 5 | com correção do valor segundo enunciado e uso da função ord(), para que: 6 | 7 | '_' = 0, 'a' = 1, 'b' = 2, ..., 'z' = 26 e '.' = 27 8 | 9 | Args: 10 | caractere (str): caractere a ser convertido em inteiro 11 | 12 | Returns: 13 | [int]: inteiro correspondente ao caractere 14 | """ 15 | if caractere == '.': 16 | return 27 17 | 18 | elif caractere == '_': 19 | return 0 20 | 21 | return ord(caractere) - 96 22 | 23 | 24 | def converte_int_char(inteiro): 25 | 26 | """Converte um inteiro para um caractere segundo a tabela ASCII 27 | com correção do valor do inteiro, segundo enunciado e uso da função chr(), para que: 28 | 29 | 0 = '_' = , 1 = 'a' = , 2 = 'b', ..., 26 = 'z' e 27 = '.' 30 | 31 | Args: 32 | inteiro (int): inteiro a ser convertido em caractere 33 | 34 | Returns: 35 | [str]: caractere correspondente ao inteiro 36 | """ 37 | if inteiro == 27: 38 | return '.' 39 | 40 | elif inteiro == 0: 41 | return '_' 42 | 43 | return chr(inteiro + 96) 44 | 45 | 46 | def codifica(lista_codigoplano, chave_k): 47 | """A partir de codigoplano aplica a função de codificação segundo 48 | Método Twist 49 | 50 | Args: 51 | lista_codigoplano (list): lista com os códigos que representam codigoplano 52 | chave_k (int): chave para codificação 53 | 54 | Returns: 55 | [list]: lista que representa cifradocodigo 56 | """ 57 | n_tam_msg = len(lista_codigoplano) 58 | lista_cifradocodigo = monta_lista_base(lista_codigoplano) 59 | 60 | for i in range(n_tam_msg): 61 | lista_cifradocodigo[i] = (lista_codigoplano[(chave_k * i) % n_tam_msg] - i) % 28 62 | return lista_cifradocodigo 63 | 64 | 65 | def decodifica(lista_cifradocodigo, chave_k): 66 | """A partir de lista_cifradocodigo aplica a função de decodificação segundo 67 | Método Twist 68 | 69 | Args: 70 | lista_cifradocodigo (list): lista com elementos de cifradocodigo 71 | chave_k (int): chave para decoficação 72 | 73 | Returns: 74 | [list]: lista com elementos que representam codigoplano 75 | """ 76 | n_tam_msg = len(lista_cifradocodigo) 77 | lista_codigoplano = monta_lista_base(lista_cifradocodigo) 78 | 79 | for i in range(n_tam_msg): 80 | lista_codigoplano[(chave_k * i) % n_tam_msg] = (lista_cifradocodigo[i] + i) % 28 81 | 82 | return lista_codigoplano 83 | 84 | 85 | ################ Funções auxiliares ################ 86 | 87 | def aplica_conversao(funcao, lista_ref): 88 | """Aplica uma função de conversão em cada elemento da lista_ref 89 | construindo uma nova lista com os valores convertidos 90 | 91 | Args: 92 | funcao (function): função de conversão a ser aplicada 93 | lista_ref ([type]): lista de referência com os valores a serem convertidos pela funcao 94 | 95 | Returns: 96 | [list]: lista com elementos convertidos 97 | """ 98 | return [funcao(i) for i in lista_ref] 99 | 100 | 101 | def to_string(lista_ref): 102 | """ Constrói uma string a partir dos elementos de uma lista 103 | 104 | Args: 105 | lista_ref (list): lista de referência para construção da string 106 | 107 | Returns: 108 | [str]: string formada pelos elementos da lista_ref 109 | """ 110 | return ''.join(lista_ref) 111 | 112 | 113 | def monta_lista_base(lista_ref): 114 | 115 | """A partir de uma lista_ref constrói uma nova lista 116 | de mesmo tamanho e elementos None 117 | 118 | Args: 119 | lista_ref (list): lista de referência para o tamanho da nova lista 120 | 121 | Returns: 122 | [list]: lista com elementos None com mesmo tamanho de lista_ref 123 | """ 124 | return [None]*len(lista_ref) 125 | 126 | ################ MAIN ################ 127 | 128 | def main(): 129 | """Interface com o usuário para receber o texto a ser convertido, 130 | chave de conversão e opção selecionada 131 | """ 132 | 133 | opcao = input('Digite 0 para codificar e 1 para decodificar: ') 134 | chave_k = int(input('Digite a chave: ')) 135 | texto = input('Digite a mensagem: ') 136 | 137 | if opcao == '0': 138 | lista_textoplano = list(texto) 139 | codigoplano = aplica_conversao(converte_char_int, lista_textoplano) 140 | cifradocodigo = codifica(codigoplano, chave_k) 141 | lista_textocifrado = aplica_conversao(converte_int_char, cifradocodigo) 142 | textocifrado = to_string(lista_textocifrado) 143 | print(f'Frase final: {textocifrado}') 144 | 145 | else: 146 | lista_textocifrado = list(texto) 147 | cifradocodigo = aplica_conversao(converte_char_int, lista_textocifrado) 148 | codigoplano = decodifica(cifradocodigo, chave_k) 149 | lista_textoplano = aplica_conversao(converte_int_char, codigoplano) 150 | textoplano = to_string(lista_textoplano) 151 | print(f'Frase final: {textoplano}') 152 | 153 | if __name__ == '__main__': 154 | main() --------------------------------------------------------------------------------