Coding Stuff
sexta-feira, 2 de maio de 2025
segunda-feira, 7 de abril de 2025
SELECÇÕES E FUNÇÕES
A propósito de uma piada pythoniana que apareceu aí numa rede (ver imagem), lembrei-me de uma solução engraçada, puramente aritmética, para a questão da selecção de 3 hipóteses a partir de 2 valores.
Os valores limite são dois, 18 e 96, pelo que uma função de primeiro grau (linear) resolve o problema.
96-18=78, portanto o zero deste inusitado sistema métrico seria -60 (18-78).
Basta então transpor -60, 18, 96 (+60) para 0, 78, 156 e a expressão:resolve o problema.
Ok! Não funciona para idosos com mais de 173 anos. Havia que fazer uma pequena adaptação:
😁
quinta-feira, 3 de abril de 2025
COBOL para quê?
O seu nome é aliás um acrónimo para a expressão Common Business Oriented Language, uma linguagem orientada portanto a negócios comuns.
Fora desse sentido, resolvi rever velhos tempos e implementar algo que mostra que poderá também ser usada para fins menos "cinzentos" e mais lúdicos.
Trata-se pois do conhecido jogo Torres de Hanoi sem grandes artifícios ou fancy UI mesmo à moda antiga quando CRT ainda era uma coisa.
O programa foi compilado em GnuCOBOL 3.2.0 mas a implementação foi feita sem idiomáticas modernas pelo que deve compilar em qualquer compilador.
O projecto está no GitHub e tem um vídeo a acompanhar.
Hope you like it.
segunda-feira, 24 de fevereiro de 2025
Programadores, essa raça de mal-humorados
Donald Knuth, alegadamente o GOAT dos programador de computadores, escreveu, em vários volumes, aquilo a que chamou "A arte da programação de computadores".
Pretendeu criar um repositório de algoritmos e técnicas de programação que pudesse servir de referência para profissionais e estudantes. É uma obra monumental, ainda em curso. Começou o trabalho na década de 1960 e já editou 4 dos 5 previstos volumes.Como se trata de uma obra sobre algoritmos e técnicas de programação, haveria que incluir, obviamente, trechos de código para exemplificar este ou aquele conceito ou procedimento.
(parêntesis) no final do terceiro volume, descontente com os processos e resultados da edição tipográfica da época, resolveu criar um novo sistema digital para edição e impressão de textos, e criou então o Tex e o
Metafont. (fecha parêntesis)
Colocava-se então a questão da escolha da linguagem a utilizar nos tais exemplos. À época, a escolha teria quase obrigatoriamente de recair sobre ALGOL ou Fortran e, não contente com a ideia por razões que explica mas que não vêm ao caso, resolveu então criar um novo computador (hipotético claro está) e uma linguagem-máquina para a sua programação.
Nasceu então o computador mítico MIX e a linguagem MIXAL que quem se aventurar na leitura da obra terá de, forçosamente, aprender.
Trinta anos passados, estamos em finais do século XX, e a evolução no meio quer em processadores quer em linguagens, remeteu MIX e MIXAL para o depósito dos fósseis, pelo que, para manter a total relevância da obra, havia que criar um novo computador e uma nova linguagem que acompanhasse essa a evolução. Nasce então o novo MMIX e a MMIXAL e novos suplementos e fascículos de atualização das centenas de rotinas MIX originais para o novo MMIX. Só de pensar dá suores.
A MMIXAL uma linguagem-máquina constituída por 256 operações diferentes; coisas como: ADD para somar, MUL para multiplicar, AND para conjugar, JMP para saltar, etc.
Acontece que foram necessárias apenas 255 pelo que faltava uma operação para perfazer o número redondo de 256.
Termina assim o manual da linguagem MMIXAL com a operação SWYM, nas palavras do próprio Knuth:
"SWYM X,Y,Z (Sympathize With Your Machinery) - The last of MMIX's 256 opcodes is, fortunately, the simplest off all. In fact, it is often called a no-op, because ir performs no operation. It does, however, keep the machine running smoothly, just as a real-world swimming helps to keep programmers healthy. Bytes X, Y, and Z are ignored."
segunda-feira, 25 de novembro de 2024
Ó IA, traduz isto ...
Neste artigo proponho-me relatar a experiência na utilização de uma ferramenta de IA, no caso o Copilot (via Bing), na tradução de um pedaço de código Python para Erlang.
Desde logo convém realçar o desafio, que não se trata apenas de uma tradução gramatical entre duas linguagens mas, mais do que isso, uma tradução semântica entre linguagens de paradigmas totalmente distintos, pelo menos na utilização que aqui lhes dou:
Introdução
Imutabilidade
O caso
- 1 cêntimo (1 maneira)
- 2 cêntimos (2 maneiras)
- 10 cêntimos (11)
- 2 euros (73682)
- 3 euros (471363)
- 5 euros (6295434) <- 5 segundos
- 6 euros (16960860) <- 11 segundos
A "funcionalização" do algoritmo
calc_loop para iterar sobre as combinações de moedas e ajustar a contagem total. Tente este código e veja se ele resolve o problema. Se precisar de mais alguma coisa, estou aqui para ajudar!"Conclusão
Posfácio
quinta-feira, 7 de novembro de 2024
Que língua é esta?
As frequências relativas de cada uma das letras no conjunto de palavras de uma língua constituem uma característica única dessa língua.
Sabemos, por exemplo que a letra a tem uma frequência relativa de 14.6% no português mas cerca de 6.0% no alemão.
Se conhecermos estas frequências relativas para várias línguas, um vector de percentagens para cada língua, basta-nos calcular o vector de frequências relativas das letras do texto que pretendemos analisar e tentar identificar de qual dos vectores de língua mais se aproxima.
É o que pretendo fazer, sem fazer uso de nenhum tipo de repositório lexical (dicionário).
O exercício será executado em linguagem R mas não tem nada de particular, aconselhado ou desaconselhado, que impeça a sua realização noutra linguagem qualquer.
Frequência de letras de idiomas
O repositório de dados que vai ser utilizado é algo reduzido mas suficiente para o conceito que se pretende demonstrar. Representa 15 idiomas (inglês, francês, alemão, espanhol, português, italiano, turco, sueco, polaco, neerlandês, dinamarquês, islandês, finlandês, checo e húngaro) e pode ser encontrado na Wikipedia no verbete Letter frequency.
A extração da tabela foi feita de forma manual, simples copy/paste
Os dados obtidos assim diretamente da página constituem linhas de valores separados por TAB, pelo que o ficheiro resultante é um ficheiro de texto.tsv (tab separated values).
Note-se que os valores são representados de maneira formatada para leitura, em pontos percentuais e incluindo o caractere %. Alguns valores incluem ainda outro tipo de caracteres não numéricos como '(', ')', '~' e '*', assim como a linha de título inclui algumas indicações de notas de rodapé [dd]; tudo isto será retirado no script de forma automatizada.
O processo
1) Ler o conteúdo do ficheiro
Para tal vai usar-se a package readr (Read Rectangular Text Data) que contém variadas funções de leitura de ficheiros de texto em vários formatos, nomeadamente o tsv.
library(readr)
df <- readr::read_tsv("data/letter_frequencies.tsv", col_names = TRUE)
O que resulta numa estrutura do tipo data-frame com o seguinte aspecto:
2) Limpeza e normalização de dados
Como já referido, há caracteres que devem ser retirados. Para tal vai usar-se a substituição por expressão regular gsub.
Primeiramente a linha de cabeçalho
colnames(df) <- gsub('([a-zA-Z]*)(.*)', '\\1', colnames(df))
De seguida uma função geral de retirada dos caracteres %, ~, ( e )
clean_values <- function(data) {
as.numeric(gsub('([0-9\\.]*)([%~\\*\\(\\)])', '\\1', data))
}
aplicada através da função sapply às colunas de valores df[2:ncol(df)]
df <- data.frame(df[1], sapply(df[2:ncol(df)], clean_values))
Após estas operações, o data-frame de frequências relativas por idioma fica com o seguinte aspecto:
3) Analisar o texto de que queremos identificar o idioma
O objectivo aqui é calcular um vector de frequências relativas das letras presentes no texto a analisar.
Começamos então por calcular as frequências absolutas:
letter_count <- (
text
%>% tolower
%>% strsplit(split="")
%>% unlist
%>% `[`(!. %in% c("", " ", ".", ","))
%>% table
%>& data.frame)
Precisamos de tornar este data-frame comparável com os vectores de frequências dos idiomas pelo que temos de incluir nele também as letras que não fazem parte do texto.
sum(letter_count$Frequency)
A coluna Percentage é directamente comparável com as colunas de idioma, já que tem o mesmo número de valores e dispostos pela mesma ordem (alfabética das letras respectivas), pelo que podemos calcular a distância entre cada uma destas e aquela e verificar então qual dos idiomas se encontra mais próximo.
4) Teste
Partimos então da frase em português "as armas e os baroes assinalados que da ocidental praia lusitana" a qual traduzimos com o google translator para cada um dos restantes 14 idiomas (sem preocupações poéticas):
phrase_pt <- "as armas e os baroes assinalados que da ocidental praia lusitana"
phrase_en <- "the weapons and barons marked from the western Lusitanian beach"
phrase_tk <- "Batı Lusitanya sahilinden işaretlenmiş silahlar ve baronlar"
phrase_fr <- "les armes et les barons marquaient celui de la plage ouest de la Lusitanienne"
phrase_de <- "Die Waffen und Barone markierten das vom westlichen lusitanischen Strand aus"
phrase_es <- "las armas y los barones marcaron eso desde la playa lusitana occidental"
phrase_it <- "le armi e i baroni lo segnavano dalla spiaggia lusitana occidentale"
phrase_se <- "vapnen och baronerna markerade det från den västra lusitanska stranden"
phrase_pl <- "broń i baronowie oznaczali to z zachodniej plaży Lusitanii"
phrase_nl <- "de wapens en baronnen markeerden dat vanaf het westelijke Lusitaanse strand"
phrase_dk <- "våbnene og baronerne påpegede, at der fra den vestlige lusitanske"
phrase_is <- "vopnin og barónarnir merktu það frá vesturhluta Lusitanian ströndinni"
phrase_fi <- "aseet ja paronit merkitsivät sen Länsi-Lusitanian rannalta"
phrase_ck <- "Zbraně a baroni označili,To ze západní pláže Lusitana"
phrase_hu <- "A fegyverek és a bárók megjelölték, A nyugati Lusitana strandé"
agrupadas numa estrutura apropriada:
test_df <- data.frame(
rbind(
c("English", phrase_en),
c("French", phrase_fr),
c("German", phrase_de),
c("Spanish", phrase_es),
c("Portuguese", phrase_pt),
c("Italian", phrase_it),
c("Turkish", phrase_tk),
c("Swedish", phrase_se),
c("Polish", phrase_pl),
c("Dutch", phrase_nl),
c("Danish", phrase_dk),
c("Icelandic", phrase_is),
c("Finnish", phrase_fi),
c("Czech", phrase_ck),
c("Hungarian", phrase_hu)))
colnames(test_df) <- c("Idiom", "SampleText")
e encapsulamos numa função as operações referidas acima:
idiom_inference <- function(text, frequency_df, distance_fn) {
# getting a data frame of the absolute frequencies of individual letters
# present on `text`
letter_count <- (
text
%>% tolower
%>% strsplit(split="")
%>% unlist
%>% `[`(!. %in% c("", " ", ".", ","))
%>% table
%>% data.frame)
# giving the letters data frame a proper nice structure
colnames(letter_count) = c("Letter", "Frequency")
# and merging it with the original all-letters columns
# in order to get a complete vector
letter_count <- merge(x = frequency_df[1], y = letter_count, by = c("Letter"), all.x = TRUE)
# letter missing in `text` get a NA value so we transform that in 0
letter_count[is.na(letter_count)] <- 0
# and calculate the relative frequency
letter_count$Percentage <- 100 * letter_count$Frequency / sum(letter_count$Frequency)
# finally we apply the distance function between out text relative frequency vector
# to each of the idioms relative frequency
distances <- t(data.frame(lapply(frequency_df[2:ncol(frequency_df)], distance_fn, letter_count$Percentage)))
# and return then rowname, which is the idiom name, of the lesser
rownames(distances)[which(distances == min(distances), arr.ind=TRUE)[,1]]
}
ontem os seguintes resultados:
5) Conclusões
A eficiência não é total já que falhou dois idiomas, "confundindo" dinamarquês com holandês e checo com italiano.
Para tal poderá ter contribuído a relativamente reduzida dimensão do texto bem como a não consideração de caracteres acentuados ou específicos em alguns idiomas, como é precisamente o caso do dinamarquês e do checo embora não se tenha confundido no húngaro em que tal também se verifica.
Não sabemos também como se comportará com outro tipo de textos, mais longos ou mais curtos, pelo que há espaço para evolução.
Espero que tenham gostado do exercício e parece que já estou a ouvir: "em Python faz-se em 3 linhas".
Venham elas.
6) Código fonte
O projecto encontra-se no GitHub.
quinta-feira, 31 de outubro de 2024
Mais um blogue?
Pois é.
Sou programador de computadores, gosto desta descrição, há mais tempo do que tempo ainda terei de vida.
Nunca fiz outra coisa.
Profissionalmente, terei já contactado com todas as principais linguagens de programação e, como passatempo, por outras tantas ou mais.
Sempre pensei partilhar um pouco da minha paixão pela programação, portanto, vai ser agora.
As publicações terão sempre algo a ver com programação de computadores mas não serão sempre código: breves notas biográficas, histórias e estórias mas, claro, principalmente código.
E nos casos de publicações com código, não pretendo mostrar genialidade ou sequer novidade; serão apenas exercícios sem nenhum outro objectivo que não a partilha de pequenos (ou grandes) prazeres e alguns deslumbramentos.
Em alguns casos serão certamente "invenções da roda"; não tenho, à partida, nenhum objectivo utilitarista, de eficiência ou desempenho, só prazer. E bem sabemos como o prazer pode ser ingénuo.
O primeiro fica já prometido: um script em R para identificar o idioma de um texto.
Liguem as antenas e digam coisas.
NOTA: sim, existem já, lá está, packages em R (e noutras linguagens talvez mais "apropriadas") com esse objectivo.
-
Toda a gente sabe que a COBOL foi inventada para programar sistemas de "negócio": ficheiros, relatórios, facturas e clientes. O se...
-
A propósito de uma piada pythoniana que apareceu aí numa rede (ver imagem), lembrei-me de uma solução engraçada, puramente aritmética, para...




_-_Google_Art_Project_-_edited.jpg)

