Ryan Palo
Posted on May 17, 2019
This is a neat trick that took me a little while to figure out. A lot of the Advent of Code challenges start by reading in a text file that is a 2D grid of characters. I wanted to figure out how to do that in Julia. There's a couple of cases I want to show.
First Case: Delimited
This case is much simpler and more satisfying. Let's say you have a text file called data.txt that looks like this:
A B C A
D B A C
C C C B
D A B B
How do we read this into a 2D array (matrix) in Julia to capitalize on the parallel processing power of Julia's syntax?
As it turns out, there's a function for that in the standard library: the DelimitedFiles
package.
using DelimitedFiles
grid = readdlm("data.txt", Char)
@show grid
readdlm
is a cool function that takes a bunch of optional arguments for types, delimiters, eol chars, and more. Here's the output of running the script:
~/temp
▶ julia delim.jl
grid = ['A' 'B' 'C' 'A'; 'D' 'B' 'A' 'C'; 'C' 'C' 'C' 'B'; 'D' 'A' 'B' 'B']
See how easy it makes it? Handles line-endings and more!
Second Case: Smooshed Chars
Now, what happens if the characters are not delimited and are all smooshed together? Things get a little harder and we actually have to do some processing. I'll show you the final solution and then discuss each of the key pieces.
Here's smooshed_data.txt
:
ABCA
DBAC
CCCB
DABB
And here's what we need to do to process it:
lines = map(collect, readlines("smooshed_data.txt"))
grid = permutedims(hcat(lines...))
@show grid
And running it:
~/temp
▶ julia smooshed.jl
grid = ['A' 'B' 'C' 'A'; 'D' 'B' 'A' 'C'; 'C' 'C' 'C' 'B'; 'D' 'A' 'B' 'B']
A little more complicated, but still only 3 relatively short lines. Let's talk about how it's working:
We use
readlines
to read all of the text from the text file into an array. This is a handy shortcut for opening the file and reading one line at a time. One nice feature of this is that it handles removing the newline characters for us--less to clean!We
map
over that array of lines,collecting
each of them.collect
takes it's argument and iterates over it, collecting the individual pieces into an array. In our case, since each line is a string, we get a bunch of characters when we iterate over it. So, in full, this line converts our array of strings representing each line of the file and converts it to an array of arrays of characters.Unfortunately, 1-D arrays are held as columns, not rows, meaning Julia considers them N x 1 rather than 1 x N in shape. For this reason, it's actually easier to combine the arrays of characters column by column next to each other, which we do using
hcat
.hcat
concatenates arrays side-by-side, and it takes an arbitrary number of arrays as its arguments. For this reason, we need to spread thelines
array intohcat
using the...
syntax.Same line. Because we now have the lines of characters in our data file, concatenated side by side, the current representation is this:
A D C D
B B C A
C A C B
A C B B
The first column matches the first row of our text file, etc. This is "sideways-ish" from what we want. We use permutedims
to flip the rows and columns. In other languages, you might consider this a "transpose." For reasons that are understandable but frustrating, in Julia, the actual transpose
function is recursive and for linear algebra, so transpose(matrix)
only seems to work on numbers.
It's important to note that we could have also permutedims(line)
for each line in order to convert from N x 1 to 1 x N before using a vcat
call to concatenate them in rows. This is more intuitive, but I'm not sure about the performance implications. It seems like it should be a little slower.
In any case, we finally end up with what we were hoping for, a 2D array of characters ready for processing. And hopefully a better understanding of some practical Julia basics!
Looking for Help
I'm learning Julia and I'm to the point where I know a few ways to do the things I want to do, but I don't really know what's idiomatic or the best way to go. If anybody has some helpful Julia resources beyond the official docs (great) or beginner "Intro to Julia" type resources, let me know what they are!
Posted on May 17, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.