10 J One Liners to Impress Your Friends

Pô, fizeram em Scala (acho que foi o primeiro) e, logo vieram versões em CoffeScript, Python, Clojure, F#, C#, Haskell e Ruby (já devem ter outras ou nem foi nessa ordem). É aquele negócio de: “Uau! Olha só do que a minha linguagem é capaz!”. E lá vem uma dúzia dizendo: “A minha também faz!”. Mas fiquei imaginando: “Quem ficaria impressionado com os exemplos?”. Apenas quem conhece só uma linguagem que não faz aquilo.

Vendo os primeiros exemplos, lembrei de Lisp e Scheme (todos conhecem o Apply do Lisp né?). Bem as duas linguagens trabalham normalmente com listas e muitas linguagens estão implementando algumas facilidades ali encontradas, o que é legal. Também justifica o programador conhecer mais de uma linguagem o que permite acoplar soluções mais inteligentes para os problemas.

Programas em uma linha são coisas antigas e, desde quando me conheço por gente, tenho visto. Até jogos completos feitos em uma linha de BASIC (acho que era do MSX). Recentemente (nem tanto assim) achei alguns programas em uma linha de REBOL bastante interessantes.

Por exemplo, a linha abaixo cria uma janela com um relógio digital (e que funciona)

view layout[origin 0 t: h1 red black (to string! now/time) rate 1 feel[engage: [t/text: now/time show t]]]

E a linha abaixo cria uma janela. Clicando na imagem é possível selecionar uma outra imagem do seu computador para ser visualizada e assim sucessivamente. Um visualizador de imagens em uma linha.

view l: layout[origin 0x0 b: box "Load" [error? try [b/image: i: load first request-file b/text: "" l/size: b/size: i/size show l]]]

Para ficar mais impressionante, funciona no Linux, Windows, Mac, etc. e basta baixar o REBOL/View que tem apenas 600KiB para testar. Mas é claro que os fãns das respectivas linguagens irão dizer: “Bah, não vou perder tempo baixando pois a minha linguagem é melhor. Prefiro preder o meu tempo mostrando que a minha linguagem faz a mesma coisa que as outras.”

Como? Refazer os 10 exemplos de uma linha em J para provar que a linguagem também é capaz só para alguém dizer: “E daí?”. Ou como no comentário de Ruby sobre o Crivo de Erastótenes que diz: “The Scala one liner is very clever, but entirely unreadable. …”. É claro santa. Se tu não conheces não entende. Em J, os 10 primeiros números primos são fornecidos pela frase: p: i.10 o que nem considero ‘one liner’.

Mas tem algumas coisinhas que eu achei legal em J e envolvem gráficos. Pode impressionar uns e não impressionar outros. Por exemplo:

'surface' plot sin */~ steps 0 3 50

viewmat |. j.~/~ i:2j16

Um poquinho de asciiart

3 6$<^:6]0 0$0

┌──────────┬──────────┬──────────┬──────────┬──────────┬──────────┐
│┌────────┐│┌────────┐│┌────────┐│┌────────┐│┌────────┐│┌────────┐│
││┌──────┐│││┌──────┐│││┌──────┐│││┌──────┐│││┌──────┐│││┌──────┐││
│││┌────┐│││││┌────┐│││││┌────┐│││││┌────┐│││││┌────┐│││││┌────┐│││
││││┌──┐│││││││┌──┐│││││││┌──┐│││││││┌──┐│││││││┌──┐│││││││┌──┐││││
│││││┌┐│││││││││┌┐│││││││││┌┐│││││││││┌┐│││││││││┌┐│││││││││┌┐│││││
│││││└┘│││││││││└┘│││││││││└┘│││││││││└┘│││││││││└┘│││││││││└┘│││││
││││└──┘│││││││└──┘│││││││└──┘│││││││└──┘│││││││└──┘│││││││└──┘││││
│││└────┘│││││└────┘│││││└────┘│││││└────┘│││││└────┘│││││└────┘│││
││└──────┘│││└──────┘│││└──────┘│││└──────┘│││└──────┘│││└──────┘││
│└────────┘│└────────┘│└────────┘│└────────┘│└────────┘│└────────┘│
├──────────┼──────────┼──────────┼──────────┼──────────┼──────────┤
│┌────────┐│┌────────┐│┌────────┐│┌────────┐│┌────────┐│┌────────┐│
││┌──────┐│││┌──────┐│││┌──────┐│││┌──────┐│││┌──────┐│││┌──────┐││
│││┌────┐│││││┌────┐│││││┌────┐│││││┌────┐│││││┌────┐│││││┌────┐│││
││││┌──┐│││││││┌──┐│││││││┌──┐│││││││┌──┐│││││││┌──┐│││││││┌──┐││││
│││││┌┐│││││││││┌┐│││││││││┌┐│││││││││┌┐│││││││││┌┐│││││││││┌┐│││││
│││││└┘│││││││││└┘│││││││││└┘│││││││││└┘│││││││││└┘│││││││││└┘│││││
││││└──┘│││││││└──┘│││││││└──┘│││││││└──┘│││││││└──┘│││││││└──┘││││
│││└────┘│││││└────┘│││││└────┘│││││└────┘│││││└────┘│││││└────┘│││
││└──────┘│││└──────┘│││└──────┘│││└──────┘│││└──────┘│││└──────┘││
│└────────┘│└────────┘│└────────┘│└────────┘│└────────┘│└────────┘│
├──────────┼──────────┼──────────┼──────────┼──────────┼──────────┤
│┌────────┐│┌────────┐│┌────────┐│┌────────┐│┌────────┐│┌────────┐│
││┌──────┐│││┌──────┐│││┌──────┐│││┌──────┐│││┌──────┐│││┌──────┐││
│││┌────┐│││││┌────┐│││││┌────┐│││││┌────┐│││││┌────┐│││││┌────┐│││
││││┌──┐│││││││┌──┐│││││││┌──┐│││││││┌──┐│││││││┌──┐│││││││┌──┐││││
│││││┌┐│││││││││┌┐│││││││││┌┐│││││││││┌┐│││││││││┌┐│││││││││┌┐│││││
│││││└┘│││││││││└┘│││││││││└┘│││││││││└┘│││││││││└┘│││││││││└┘│││││
││││└──┘│││││││└──┘│││││││└──┘│││││││└──┘│││││││└──┘│││││││└──┘││││
│││└────┘│││││└────┘│││││└────┘│││││└────┘│││││└────┘│││││└────┘│││
││└──────┘│││└──────┘│││└──────┘│││└──────┘│││└──────┘│││└──────┘││
│└────────┘│└────────┘│└────────┘│└────────┘│└────────┘│└────────┘│
└──────────┴──────────┴──────────┴──────────┴──────────┴──────────┘

color 2 rem int 7 7

Impressionado? Eu realmente não me importo.

(}.i.!4) A. 'CASA'

CAAS
CSAA
CSAA
CAAS
CASA
ACSA
ACAS
ASCA
ASAC
AACS
AASC
SCAA
SCAA
SACA
SAAC
SACA
SAAC
ACAS
ACSA
AACS
AASC
ASCA
ASAC

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

Utilizando J em imagens (parte 4 de n)

Brincamos um pouco com imagens no artigo anterior, mas achei que o preto e branco foi pouco explorado. Vou partir com a seguinte imagem para facilitar a visualização da simulação de filtros.

Para converter a imagem para preto e branco podemos utilizar <. 3 # "0 media "1 im , obtendo a seguinte imagem:

Como foi visto anteriormente, usando 1 0 0 * "1 im podemos extrair apenas o canal vermelho da imagem. Poderíamos utilizar apenas o valor do canal vermelho para gerar a nossa imagem e, em vez de calcular a média dos três canais, utilizamos o valor de um canal e colocamos nos outros dois. Os exemplos a seguir mostram como ficariam as imagens utilizando apenas um canal. Na sequencia R, G e B (coloquei a imagem colorida do canal para auxiliar na visualização).

Acho que a imagem evidenciou bastante a diferença no resultado do preto e branco. No primeiro caso, bastante comum na fotografia em filme, era utilizado um filtro avermelhado. Quanto mais vermelho, mais escuro ficava o céu, dando um bom contraste com as nuvens. O mesmo ocorreu na imagem, onde a parte azulada (ciano) da parede ficou bem escura, já que o filtro vermelho bloquearia a passagem da luz azul. Por outro lado, a parte vermelha da placa na porta ficou praticamente branca.

Oops. Quase esqueci de colocar a sentença para geração de uma imagem preto e branco baseada apenas em um canal. Para converter para preto e branco utilizando apenas o canal vermelho, usamos:

view_image 3# "0 ]0{"1 im

Nesse caso, nós montamos uma matriz com o valor do canal vermelho utilizando o verbo From que recebe como parâmetro os valores 0, 1 ou 2 (0{, 1{ ou 2{) dependendo do canal desejado (R, G ou B). Depois repetimos três vezes o valor para a visualização da imagem. Só para constar, é possível gravar as imagens em vez de apenas visualizá-las com view_image.

(3# "0 ]2{"1 im) write_image '/home/guara/temp/porta-bw-b.jpg'

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

Utilizando J em imagens (parte 3 de n)

Caso não saiba o que é J, é necessário ler o primeiro artigo da série. Se sabe mas não tem instalado ou não leu o segundo artigo, agora é a hora. Por último, existe a possibilidade de ler apenas este artigo e ignorar os outros.

Primeiramente vamos partir de uma imagem qualquer gravada em um diretório qualquer (aqui a imagem possui o nome de pipoca.jpg e está gravada na pasta /home/guara/).

load 'media/image3'

load 'media/image3/view_m'

im=.read_image '/home/guara/pipoca.jpg'

view_image im

Considerando que im é uma matriz com n linhas e m colunas (largura e altura da imagem) e p planos (para as cores r,g,b), podemos fazer alguns cálculo em cima de cada trio de cores primárias. Uma das coisas seria selecionar apenas uma das cores. Para tanto, multiplicamos por 1 a cor de desejamos manter e por 0 a cor que desejamos excluir. Se desejamos apenas o canal vermelho, usamos:

view_image 1 0 0 * "1 im

Com o mesmo processo poderíamos efetuar alguma correção de cor. Se desejamos retirar um pouco de vermelho e verde, podemos multiplicar as cores por 0,9 e 0.95, por exemplo.

view_image <. 0.9 0.95 1 * "1 im

Para uma imagem em tonalidades de cinza, devemos deixar os valores de r,g,b iguais. Um procedimento simples é obter a média de um ponto e deixar os três valores iguais. Por exemplo, se o ponto tiver R=145, G=103, B=80, deixamos R=G=B=(145+103+80)/3=109,33=109. A definição de média em J é dada pela expressão (mais informações na documentação):

media=. +/ % #

e utilizamos a expressão

view_image <. 3 # "0 media "1 im

para obter a imagem:

Pode-se ainda juntar tudo o que foi visto para simular a utilização de um filtro na conversão. Mesmo um filtro que não existiria normalmente. Se eu desejo apenas escurecer o vermelho, poderia utilizar:

view_image <. 3 # "0 media "1 (0.5 1 1 * "1 im)

para obter:

Sim, é claro que tudo o que foi mostrado poderia ter sido feito em qualquer linguagem. O difícil seria fazer sem utilizar um for…next ou qualquer outra estrutura de laço. Em J, as brincadeiras se resumiram a alguns caracteres em uma linha.

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

Utilizando J em imagens (parte 2 de n)

Duas coisinhas para começar: Não sei quantos artigos farei, só espero que este não seja o último. Quem não leu o anterior, acho que é melhor começar por lá.

Pressuponho que você já baixou e instalou o J no seu sistema operacional, deu uma olhadinha no Studio/Labs, executou os exemplos e leu um pouquinho da documentação. Se não fez nada disso, deverá instalar o J e poderá deixar o resto para depois. Já existe biblioteca pronta para trabalhar com imagens e diversas outras atividades portanto, é mais fácil utilizar algo pronto do que reinventar a roda. Como as bibliotecas adicionais não foram instaladas juntamente com o programa é necessário que você baixe e instale elas. É fácil instalar e manter as bibliotecas diretamente com alguns comandos mas, para não assustar, bastam alguns cliques que estará tudo feito. Acesse o menu Run e a opção Package Manager..

Deverá ser aberta uma janela pareceda com a que segue:

No meu caso, todos os pacotes já estão instalados e atualizados. Precisaremos do media/image3. Clicando nos pacotes, temos uma descrição do que ele possibilita. Marque os que você deseja instalar (ou todos) e instale. Após a instalação, outras seções estarão disponíveis no Studio/Labs, e você poderá estudar um pouco o funcionamento das bibliotecas.

Antes de continuar, um pequeno aviso. Você deverá copiar linha a linha do código e pressionar enter para que ela seja executada. Se você copiar um bloco de linhas e colar, o resultado não será o desejado. É claro que existe a opção de copiar e colar um programa inteiro e executá-lo, mas fica para a próxima.

A primeira coisa a fazer e carregar os pacotes desejados. Para tanto, digite as linhas abaixo no seu ambiente (ou copie, cole e execute pressionando enter cada uma delas)

load 'media/image3'
load 'media/image3/view_m'

Vamos criar uma matriz quadrada contendo as cores vermelho, verde, azul e amarelo em cada uma das quatro posições. Uma matriz 2x2x3. Uma linha como a que segue será o suficiente

im=.2 2 3 $ 255 0 0 0 255 0 0 0 255 255 255 0

Já poderíamos visualizar a imagem mas, como a imagem teria apenas 2×2 pixels, preciisamos aumentar um pouco para facilitar a visualização. Uma imagem de 80 pixels de cada lado ficará bem melhor. Vamos criar a imagem 2 com essas dimensões. Se a atribuição dos valores seria algo simples em diversas linguagens de programação, algo como im=[[[255, 0, 0], [0, 255, 0]], [[0, 0, 255], [255, 255, 0]]] (mais feio para uns e mais bonito para outros), você pode testar qual a complexidade de elevar de 2×2 para 80×80.

im2=.80 80 resize_image im

Ok, já poderemos visualizar a imagem. Para tanto, a linha abaixo é o suficiente.

view_image im2

O resultado deverá ser o seguinte:

Como é uma linguagem orientada a matrizes, nada mais normal do que facilitar o trabalho com elas. Para mostrar a imagem com cores inversas, devemos subtrair 255 de cada pixel. É uma operação trivial. uma linha como 2 + 1 2 3 4 resultará em 3 4 5 6. Para subtrair 255 da matrix, basta 255-matrix.

view_image 255-im2

Resultará em:

Apesar de não ser difícil, em outras linguagens de programação precisariamos de algo como:

for i=1 to 80: for j=1 to 80: for c=1 to 3: m[i,j,c]=255-m[i,j,c]

É possível rotacionar a matriz facilmente. Podemos rotacionar 12 posições para a esquerda (cada posição irá corresponder a um pixel) e 24 posições para cima, por exemplo. Se temos a matriz 1 2 3 4, rotacionar 1 posição para a esquerda (1|.) resultará em 2 3 4 1. Veja que o primeiro elemento foi para a última posição. Já pensou em utilizar a sua linguagem preferida para efetuar esta operação em uma matrix de 80x80x3? É bem provável que envolva um pouco a mais de trabalho. Então, vamos ver como fica:

view_image 24 12|.im2

e o resultado será:

Para finalizar o artigo, poderiamos efetuar a rotação e, em vez de de utilizar o valor do elemento que cai fora da matriz no seu final, poderemos preencher com outro valor. Você também pode testar para ver como ficaria o procedimento em outra linguagem.

view_image 24 _12|.!.0 im2

e temos:

Ok, ficamos por aqui. Não pretendo me prender muito nos verbos e advérbios utilizados pela linguagem. No help você encontrará uma farta documentação. Só para complementar, é possível ler diretamente uma imagem utilizando im=:read_image <caminho>, onde <caminho> é o caminho completo para a sua imagem. Teste algo como im=:read_image ‘/home/user/images/teste.png’ ou im=:read_image ‘c:\imagens\teste.jpg’ com os comandos deste artigo para ver se funcionam bem e a rapidez com que eles são executados (lembrando que J é uma linguagem interpretada). Veja o que view_image |.im faz.

T+

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