Executando verificação de segurança...
2

Autohotkey versão 2 - Ordenação topológica (Array, Map, Função recursiva, Grafo)

É um artigo?

Sei que alguns aqui tem grandes ambições e anseiam por artigos.
Porém já aviso que isto não é um artigo.

O que é Autohotkey?

Autohotkey é uma linguagem de script poderosa usada para automatizar aplicativos desktops, mapear teclas ou criar scripts que auxiliam durante a jogatina de games, não é popular mas fornece alta produtividade para quem sabe usar, também se destaca em tarefas que em outras linguagens seria mais complicado além de ter que escrever muito mais código.

Motivação

Quero apenas compartilhar um código que tentei codificar do zero, porém falhei, demorei a encontrar e o tornei mais inteligível e enxuto.
Na empresa havia sempre o mesmo problema, scripts sql's que geravam arquivos .csv deviam ser chamados na ordem correta, era comum um depender do outro, havendo uma certa hierarquia, quando uma tabela não retornava dados era a dúvida de sempre, será que não está na ordem de execução correta, ou será alguma condição?
Segue uma possível solução:

#Requires AutoHotkey v2.0+
#SingleInstance

gestores := Map()
gestores["municipio"] 	:= ["estado", "governo"]
gestores["pai"] 		:= ["empresa"]
gestores["filho"] 		:= ["mae", "pai"]
gestores["estado"] 		:= ["governo"]
gestores["mae"] 		:= ["empresa"]
gestores["governo"] 	:= []
gestores["empresa"] 	:= ["municipio", "estado", "governo"]

try {
	resultado_array := ordena_topologicamente(gestores)
	MsgBox array_para_string(resultado_array, "`n"), "Ordenação topológica", "Iconi"
} catch Error as falha {
	MsgBox falha.message "`n Linha: " falha.Line, "Falha: " falha.What, "IconX"
} ; end try


ordena_topologicamente(gestores) {
    array_ordenado := [], rastro_map := Map(), ja_foi_ordenado_map := Map()

    for elemento in gestores
        if not ja_foi_ordenado_map.Has(elemento)
            ordene(elemento, gestores, array_ordenado, rastro_map, ja_foi_ordenado_map)

    return array_ordenado
} ; end function

ordene(elemento, gestores, array_ordenado, rastro_map , ja_foi_ordenado_map) {

    if rastro_map.Has(elemento)
		throw Error("Dependência cíclica, causando loop infinito!", "ordene()")

    if not ja_foi_ordenado_map.Has(elemento) {
        rastro_map[elemento] := true

        if not gestores.has(elemento)
            throw Error(" Elemento (" elemento ") do array `n não encontrado no Map() gestores!", "ordene()")

        for elemento in gestores[elemento]
            ordene(elemento, gestores, array_ordenado, rastro_map, ja_foi_ordenado_map)

        rastro_map.Delete(elemento)
        ja_foi_ordenado_map[elemento] := true
        array_ordenado.Push(elemento)
    } ; end if
} ; end function

array_para_string(array, separador := ", ") {
    resultado := ""
    for elemento in array
        resultado .= separador elemento

    return LTrim(resultado, separador)
} ; end function

Resultado

resultado

Ei, não está faltando coisa?

Muitos vão dizer, e com razão, que o código não lê .csv, etc.
Verdade, o código real é ainda mais complexo pois a estrutura com os dados é formada de forma dinâmica, etc. o que demonstro aqui é só a função principal, a parte mais complexa do código do todo.

Para quê esse código em uma linguagem que "ninguém" usa?

Realmente, como eu disse Autohotkey não é muito popular, no entanto, acredito que não será difícil adaptar para linguagem com funcionalidades semelhantes (map, array e função).

Carregando publicação patrocinada...
1
1

Eu comecei a programar com script similares com um software chamado AutoIt, na época tinha aqueles mini games em Flash que rodavam graças ao plugin Shockwave Player da Adobe e tinha um game chamado Bible Fight, então automatizei os golpes especiais de todos personagens.