Anagram finder in Julia

This is the Julia implementation of the anagram program. The problem and the solution is described in the main anagram article. Do read that article first.

Also, you may find the C++ article helpful, since it describes member data and functions in some detail, not repeated here. This article describes only the differences between the C++ implementation and this implementation.

The Julia implementation is similar, almost identical, to the most other implementations; the differences are mostly syntactical.

The source code

using Printf;

MINIMUM     = 3;
comparisons = 0;

#------------------------------------------------------------------------ Word
mutable struct Word
    offset  :: Int;
    value   :: String
    unified :: String
end

function print(this :: Word)
    @printf("%4d %s %s\n", this.offset, this.value, this.unified);
end

function get_unified(s :: String)
    tmp = Vector{Char}(s);
    sort!(tmp);
    return String(tmp);
end

function isless(a :: Word, b :: Word) :: Bool
#   comparisons = comparisons + 1;
    if (a.unified < b.unified)
       return true;
    elseif (a.unified > b.unified)
       return false;
    else
       return a.offset < b.offset;
    end
end

#------------------------------------------------------------------------ AnagramFinder
mutable struct AnagramFinder
    len        :: Int;
    words      :: Array{Word, 1};
    accepted   :: Array{Word, 1};
    low_offset :: Int;

    function AnagramFinder(text :: String, len :: Int) #--- Constructor
        this = new(len, Word[], Word[], 0);
        last :: Int = length(text) - len + 1;
        for n = 1:last
           w :: String = text[n:(n+len-1)];
           push!(this.words, Word(n-1, w, get_unified(w)));
        end
        return this;
    end
end

function print_one_result(this :: AnagramFinder)
    @printf("%3u:", length(this.accepted));
    for it in this.accepted
        @printf(" %4d:%s", it.offset, it.value);
    end
    @printf("\n");
end

function add_candidate(this :: AnagramFinder, cand :: Word)
    if (cand.offset < this.low_offset)
        return;
    end
    for it in this.accepted
        if (it.value == cand.value)
            return;
        end
    end
    push!(this.accepted, cand);
    this.low_offset = cand.offset + this.len;
end

function add_range(this :: AnagramFinder, first :: Int, last :: Int)
    if (last-first+1 >= MINIMUM)
        this.accepted = Array{Char, 1}();
        this.low_offset = 0;
        for n = first:last
            add_candidate(this, this.words[n]);
        end
        if (length(this.accepted) >= MINIMUM)
            print_one_result(this);
        end
    end
end

function find_all(this :: AnagramFinder)
    sort!(this.words, lt = isless);
    first :: Int = 1;
    for n = 2:length(this.words)
        if (this.words[n].unified != this.words[first].unified)
            add_range(this, first, n-1);
            first = n;
        end
    end
    add_range(this, first, length(this.words));
end

function read_text() :: String
   tmp :: Array{Char, 1} = [];
   sizehint!(tmp, 500*512);
   while (! eof(stdin))
       ch :: Char = uppercase(read(stdin, Char));
       if (isletter(ch))
           push!(tmp, ch);
       end
   end
   return String(tmp);
end

#------------------------------------------------------------------------ main
function main(argc :: Int, argv :: Array{String, 1})
    from :: Int = (argc > 0) ? parse(Int, argv[1]) : 6;
    to   :: Int = (argc > 1) ? parse(Int, argv[2]) : from;

    text :: String = read_text();

    for len = from:to
        finder :: AnagramFinder = AnagramFinder(text, len);
        @printf("%slen = %d\n", (len > from) ? "\n" : "", len);
        find_all(finder);
    end
    @printf("string length = %5d, comparisons = %s\n",
            length(text), comparisons > 0 ? comparisons : "****");
end

main(length(ARGS), ARGS);

You can reach me by email at “lars dash 7 dot sdu dot se” or by telephone +46 705 189090

View source for the content of this page.