A generalização é uma m.

> “Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” – Martin Fowler

Vira e mexe e eu vejo essa citação como sendo a máxima das máximas. Penso que o cara que postou está se achando ou quer que os outros achem que ele é o máximo. Eu acho que é uma generalização mais para fazer com que o programador escreva um código simples em uma linguagem mainstream. Assim, fica mais fácil trocar de programador sem muito custo. É mais uma citação para empresas e não para programadores.

Mesmo trocando "humans" por "programmers", as coisas podem não ser tão simples assim. Quer radicalizar? Computador só entende binário e, tirando um ou dois, duvido que qualquer humano programador ou não entenda o código. Vou entender que é código para um compilador ou interpretador.

Vou usar como exemplo o problema #3 do projeto Euler

> The prime factors of 13195 are 5, 7, 13 and 29. > What is the largest prime factor of the number 600851475143 ?

O código que utilizei para resolver o problema foi:

>./q:13195

Basta executar para me retornar

29

Pronto. A resposta como o exemplo do problema. É só trocar o 13195 por 600851475143 para que o problema seja resolvido.

Ei? Você é um idiota pois eu não entendi o código que você escreveu. Não! Eu sou um idiota pois o código não é o melhor nem o mais rápido. Para eu não ser um idiota deveria ter escrito:

{:q:13195

Agora sim. Além de ser mais rápido, eliminei um advérbio ( / ) e ele ficou ainda menor (usa apenas 4 caracteres :P). Mas vamos deixar claro algumas coisas:

  • não sou idiota por ter escolhido uma linguagem que resolve o problema de uma forma concisa;
  • não sou idiota por ter escrito um código que você não entendeu;
  • você não é idiota por não ter entendido o código.

Só para entender um pouco do que foi feito anteriormente, usamos o

  • Prime Factors q: y : retornar a lista dos fatores primos no número informado
  • Larger of (Max) x >. y : retorna o maior de dois valores
  • Insert / para retornar o maior elemento da lista.

Como q: retorna a lista dos fatores primos em ordem ascendente, é perda de tempo verificarmos todos os itens da lista procurando o maior. Mais prático pegar diretamente o último que é obtido com Tail {: utilizado na segunda solução.

Se quiser escrever um código que seja entendido por humanos, utilize COBOL. Um dos propósitos foi este, mas duvido que todos os "humanos" consigam entender um programa em COBOL.

O livro Thinkin Forth tem um trecho interessante no prefácio.

> Programming computers can be crazy-making. Other professions give you the luxury of seeing tangible proof of your efforts. A watchmaker can watch the cogs and wheels; a seamstress can watch the seams come together with each stitch. But programmers design, build, and repair the stuff of imagination, ghostly mechanisms that escape the senses. Our work takes place not in RAM, not in an editor, but within our own minds.

Entender um programa significa entender o que o outro pensou. Como o outro pensou na resolução. O exemplo dado em J é muito simples e nem precisa nada a não ser conhecer a linguagem. É como somar 2 + 2. Não necessita explicação.

Teste a expressão 2 + 2 * 3 + 2 em diversas linguagens e verá que pode ter resultados como 12, 18 ou 10.

Mais ainda. Conforme o estilo de programação, o programa pode ficar mais legível para uns e menos para outros. Os programadores de APL também escrevem em C e, muito provavelmente, você não entenderá/gostará do formato utilizado.

Veja o código em C que deu origem ao J. Posso garantir que o Ken Iverson e o Arthur Whitney não eram idiotas. Muito pelo contrário.

Programação é mais do que só escrever código que os outros entendam. É mais do que ter apenas um martelo e achar que todos os problemas são pregos. Aproveite e de uma olhadinha em J quando não estiver fazendo nada na pademia.

J ou K?

Introdução

Depois que eu postei algumas formas de calcular o fatorial usando K , alguns amigos do Facebook queriam desesperadamente saber qual das duas linguagens eu preferia. Na realidade, não era desesperadamente. Apenas uma curiosidade. E também não eram todos os meu amigos, apenas os que trabalhavam com TI. Bem, nem todos que trabalhavam com TI. Só um pouquinho. Vou lá no face para saber quantos amigos queria a minha opinião. Tec, tec, tec…. Pô, nenhum. Acho que foi um sonho.

Então tá. Como ninguém queria saber, vou escrever mesmo assim. Quem sabe …. algum dia ….

Bem, K é comercializado pela Kx Systems  e foi feita uma versão aberta de K conhecida como kona. Mas é só uma parte do todo. A empresa Kx permite baixar a versão de 32bits do sistema que não pode ser utilizada em sistemas comerciais. Baseado apenas nisso, já posso dizer que a minha preferência é por J, que é uma versão completa, foi desenvolvida por Kenneth E. Iverson (desenvolvedor da APL), tem a versão GPL (inclusive é possível baixar os fontes).

A linguagem

Existem diferenças entre uma e outra linguagens, mas nada de muito anormal. No exemplo do fatorial em K foram usados dois exemplos para gerar a lista. Um era 1+!5 (gera a lista 0 1 2 3 4) e adiciona 1 e o exemplo 1_!6 (gera a lista 0 1 2 3 4 5 6), retira o primeiro elemento e fica com os restantes. Em J, os equivalentes seriam 1+i.5 (1 + 0 1 2 3 4 = 1 2 3 4 5) e }.i.6 (0 1 2 3 4 5 = 1 2 3 4 5). Existem outras variantes possíveis como, por exemplo, >:i.5 (gera a lista e incrementa os elementos). Em qualquer caso de J, precede-se */ para inserir a multiplicação entre os elementos da lista (*/>:i.5 => 0 1 2 3 4 5 => 1 2 3 4 5 => 1 * 2 * 3 * 4 * 5).

Já vem com diversas bibliotecas para facilitar o trabalho e ainda podemos instalar outras tantas, facilitando tarefas como a geração dos mais diversos tipos de gráficos, trabalhar com web, arquivos, sgbds, etc..

Ambiente.

Existem três ambientes onde podemos trabalhar com J.

Console

É o mais básico e é possível fazer de tudo mas, provavelmente, não será utilizado para muita coisa. Só para executar algum programa em J ou pequenos testes. Para não causar conflito com o jconsole do java, uma opção é criar um link simbólico. Aqui, /usr/bin/jc aponta para /home/zilog/j64-804/bin/jconsole. Não é necessário ser administrador para instalar o J.

jqt

Muito bom para você fazer testes, administrar o sistema e criar projetos. Inicialmente apresenta uma janela como o do terminal (jconsole) porém, existem diversos programas e funções que podem ser acessadas pelo menu para facilitar o desenvolvimento e consulta. É uma janela mais ou menos assim:

jqt

Em Tools/Package Manager, existe um utilitário para gerenciar os pacotes. Você poderá instalar/atualizar os diversos pacotes existentes para a linguagem. Como não ocupam muito espaço, pode instalar todos (até porque alguns exemplos necessitam).

package

Em File, além de outras coisas como imprimir, é possível editar arquivos. Com Ctrl+N ou File/New Temp, você pode digitar e executar linhas, blocos ou todo o arquivo e salvar para uso posterior.

qeditNo menu Help, temos toda uma gama de informações para auxiliar o usuário no desenvolvimento e ainda uma série de exemplos que podem servir de base para outros programas. Em Help/Studio/Labs, existe uma série de tutoriais interativos. O usuário pode selecionar um assunto e, ao executar, os diversos capítulos e seções serão executados no terminal. Após mostrar uma seção, o usuário deverá pressionar Ctrl+J para prosseguir depois de ler e entender (bem, não é necessário nem possível entender tudo). Antes de pressionar Ctrl+J, é possível entrar com comandos com valores diferentes para melhorar o entendimento. A janela para escolher entre oa diversos tutoriais:

lab1

Exemplo da execução do tutorial (note que também é possível avançar utilizando o menu mas Ctrl+j é muito mais simples).

lab2Outra opção interessante é Help/Studio/Showcase…, que possui diversos programas que podem ser executados e podem ser vistos os fontes para análise.

demojO programa plot é um bom começo para mostrar a grande quantidade de gráficos bi e tri dimensionais que o J permite.

demoj1Também temos a opção Help/Studio/Qt Demos… que possui exemplos de como utilizar os diversos controles do QT com os programas, entregando uma interface gráfica para facilitar a vida do usuário.

demoqt

jhs

É um servidor que possibilita a interação com J por um navegador. Vem configurado para aceitar apenas conexões de localhost (127.0.0.1) mas é possível editar o arquivo j64-804/addons/ide/jhs/config/jhs_default.ijs (troque o j64-804 pelo caminho da sua instalação) e alterar a variável BIND de localhost para any para aceitar de qualquer dispositivo (neste caso, por motivos de segurança, é necessário especificar senha para acesso). Após executar ./j64-804/bin/jhs, temos um resultado como o que segue:

jhs1

Agora é só usar o seu navegador, abrir o endereço especificado e brincar. Para encerrar o servidor, digite exit”.

jhs2

jupyter

Mas não eram três? Sim, mas este não conta. Ainda está em desenvolvimento e está muito relacionado com python. Interessante por permitir gravar a sessão para visualização futura. Outras informações em jkernel.

Projeto Euler – Problema #11

O problema #11 do projeto Euler deseja saber o maior produto de quatro números adjacentes calculados em qualquer direção (direita, esquerda, diagonais, cima, baixo) em uma matriz dada..

 

Como de costume, vamos resolver em J . Vamos começar com uma matriz pequena para facilitar a visualização.

 

   A=. ?. 6 6 $ 10
Ok, criamos uma matriz 6×6 com elementos aleatórios entre 0 a 9 (como foi utilizado o ?. o resultado será sempre o mesmo).

 

   A
6 5 9 2 4 9
0 7 0 4 6 8
3 8 1 2 8 0
0 2 1 6 0 4
4 1 3 3 6 6
5 7 8 8 2 1
Para o agrupamento de quatro elementos de uma coluna podemos utilizar 4\ e termos:

 

   4<\A
┌───────────┬───────────┬───────────┐
│6 5 9 2 4 9│0 7 0 4 6 8│3 8 1 2 8 0│
│0 7 0 4 6 8│3 8 1 2 8 0│0 2 1 6 0 4│
│3 8 1 2 8 0│0 2 1 6 0 4│4 1 3 3 6 6│
│0 2 1 6 0 4│4 1 3 3 6 6│5 7 8 8 2 1│
└───────────┴───────────┴───────────┘
Como é possível ver, a primeira coluna da matriz A contendo 6 0 3 0 4 5 foi seccionada em três com quatro elementos cada: 6 0 3 0, 0 3 0 4 e 3 0 4 5. Todas as outras também. Como tanto faz de baixo para cima ou o contrário que o resultado será o mesmo.

 

   4*/\A
0 560  0  96 0 0
0 112  0 144 0 0
0 112 24 288 0 0
Para saber o maior produto obtido:

 

   >./, 4*/\A 560
A primeira etapa foi muito simples. Bastaram 9 caracteres para resolver o nosso problema. Mas é apenas a primeira etapa. Obtemos a maior soma de quatro número consecutivos de todas as colunas da nossa matriz. Como próxima etapa, podemos calcular a maior soma das linhas da nossa matriz. Para obter o resultado é um pouquinho mais complexo.

 

   >./,4*/\"1 A
2240
Da mesma forma que para as colunas, não é necessário efetuar o mesmo cálculo da esquerda para a direita. Agora entraremos na parte mais complexa. Trabalhar com as diagonais.

 

   A
6 5 9 2 4 9
0 7 0 4 6 8
3 8 1 2 8 0
0 2 1 6 0 4
4 1 3 3 6 6
5 7 8 8 2 1
Para obter as diagonais da matriz é só utilizar /.

 

   </.A
┌─┬───┬─────┬───────┬─────────┬───────────┬─────────┬───────┬─────┬───┬─┐
│6│5 0│9 7 3│2 0 8 0│4 4 1 2 4│9 6 2 1 1 5│8 8 6 3 7│0 0 3 8│4 6 8│6 2│1│
└─┴───┴─────┴───────┴─────────┴───────────┴─────────┴───────┴─────┴───┴─┘
É fácil associar as diagonais com a matriz original.

 

   >./,4*/\"1]/.A
1152
Na diagonal irá fazer diferença da direita para a esquerda e da esquerda para a direita. Então teremos que pegar a outra, que pode ser obtida por:

 

   </.|.A
┌─┬───┬─────┬───────┬─────────┬───────────┬─────────┬───────┬─────┬───┬─┐
│5│7 4│8 1 0│8 3 2 3│2 3 1 8 0│1 6 6 1 7 6│6 0 2 0 5│4 8 4 9│0 6 2│8 4│9│
└─┴───┴─────┴───────┴─────────┴───────────┴─────────┴───────┴─────┴───┴─┘
   >./,4*/\"1]/.|.A
1152
Juntando tudo temos o que poderíamos chamar de ‘one liners’. 😉

 

   (>./,4*/\"1]/.|.A) >. (>./,4*/\"1]/.A) >. (>./,4*/\"1 A) >. >./, 4*/\A
2240
Que nos dará o resultado do problema em uma etapa. É só substituir nossa matriz pela do exercício e o problema estará resolvido.

 

A=: ".;._2(0 : 0)
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
...
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48
)
E aplicar o nosso programa de uma linha. 😉

Projeto Euler – Problema #24

A resolução de problema #24 do Projeto Euler não tem muita graça em J. Conforme o enunciado, temos que as permutações possíveis de 0, 1 e 2 são: 012, 021, 102, 120, 201 e 210.

Inicialmente temos que 0, 1 e 2 pode ser traduzido para J como i.3. O número de permutações para três elementos seria dada pelo fatorial de 3 ou !3 em J que é 6. Para resolver as permutações e selecionar uma das sequências utilizamos A. (Anagram Index). Como no exemplo são três elementos e seis possíveis combinações, para obtermos todas as combinações podemos utilizar:

0 1 2 3 4 5 A. 0 1 2

0 1 2
0 2 1
1 0 2
1 2 0
2 0 1
2 1 0

Apesar do número de permutações aumentar rapidamente e não ser interessante visualizar todas, uma forma mais genéria poderia ser:

(i.!3) A. i.3

0 1 2
0 2 1
1 0 2
1 2 0
2 0 1
2 1 0

Então, para sabermos a quinta permutação, usamos diretamente 4 A. i.3 que retorna 2 0 1. Para saber a décima sexta permutação onde os elementos são os números inteiros de 0 a 9, podemos escrever:

15 A. i.10

0 1 2 3 4 5 8 7 9 6

Até aqui tudo bem, só que o problema deseja um número sem espaços. A solução mais complicada seria copiar a lista gerada e apagar manualmente os espaços. Outra forma é utilizar a #. (base) utilizando 10 como base. Como exemplo: 10#.2 3 4 => 234. A resposta para o problema ficaria como 10#.999999 A.i.10.

Como uma string é uma lista de caracteres (como pode ser visto no final do artigo sobre programas em uma linha), o problema também poderia ser resolvido usando uma string. No exemplo do problema ficaria:

(i.6) A. '012'

012
021
102
120
201
210

Facinho né?

=-=-=-=-=
Powered by Blogilo