So, I have .txt files with matrices in this form:
5 8
9 -1
0 2
file2:
9 2 -1
7 0 9
-1 7 0
and so on, the dimensions are not set in stone.
What I'm trying to do is to create a function that translates the text documents into matrices and later no is capable of doing basic math with said matrices, namely multiplication.
My code is already capable of opening the matrices and reading them to some extent like so:
Matrix = {}
file = open(filename, 'r')
for line in file:
width = len(line.split(" "))
height += 1
matrixname = input("enter matrix name")
for line in file:
Matrix[matrixname] = [[0 for x in range(height)] for y in range(width)]
but I'm not sure if I'm going into the right direction or what I'm able to do now.
Edit*
juanpa's suggested code piece
[[int(i) for i in line.split()] for line in tiedosto]
does the job of handling each index value one by one and I now have a function that will create a matrix of zeros that is the same dimension as the original matrix, now what I lack is a way to put each index value into their correspondent matrix index of the matrix of zeros.
Related
I'm trying to write a Sudoku solver, which is the fun part. The un-fun part is actually loading the puzzles into Julia from a text file. The text file consists of a series of puzzles comprising a label line followed by 9 lines of digits (0s being used to denote blank squares). The following is a simple example of the sort of text file I am using (sudokus.txt):
Easy 7
000009001
008405670
940000032
034061800
070050020
002940360
890000056
061502700
400700000
Medium 95
000300100
800016070
000009634
001070000
760000015
000020300
592400000
030860002
007002000
Hard 143
000003700
305061000
000200004
067002100
400000003
003900580
200008000
000490308
008100000
What I want to do is strip out the label lines and store the 9x9 grids in an array. File input operations are not my specialist subject, and I've tried various methods such as read(), readcsv(), readlines() and readline(). I don't know whether there is any advantage to storing the digits as characters rather than integers, but leading zeros have to be maintained (a problem I have encountered with some input methods and with abortive attempts to use parse()).
I've come up with a solution, but I suspect it's far from optimal:
function main()
open("Text Files\\sudokus.txt") do file
grids = Vector{Matrix{Int}}()
grid = Matrix{Int}(0,9)
row_no = 0
for line in eachline(file)
if !(all(i -> isnumber(i), line))
continue
else
row_no += 1
squares = split(line, "")
row = transpose([parse(Int, square) for square in squares])
grid = vcat(grid, row)
if row_no == 9
push!(grids, grid)
grid = Matrix{Int}(0,9)
row_no = 0
end
end
end
return grids
end
end
#time main()
I initially ran into #code_warntype problems from the closure, but I seem to have solved those by moving my grids, grid and row_no variables from the main() function to the open block.
Can anyone come up with a more efficient way to achieve my objective or improve my code? Is it possible, for example, to load 10 lines at a time from the text file? I am using Julia 0.6, but solutions using 0.7 or 1.0 will also be useful going forward.
I believe your file is well-structured, by that I mean each 1,11,21... contains difficulty information and the lines between them contains the sudoku rows. Therefore if we know the number of lines then we know the number of sudokus in the file. The code utilizes this information to pre-allocate an array of exactly the size needed.
If your file is too-big then you can play with eachline instead of readlines. readlines read all the lines of the file into the RAM while eachline creates an iterable to read lines one-by-one.
function readsudoku(file_name)
lines = readlines(file_name)
sudokus = Array{Int}(undef, 9, 9, div(length(lines),10)) # the last dimension is for each sudoku
for i in 1:length(lines)
if i % 10 != 1 # if i % 10 == 1 you have difficulty line
sudokus[(i - 1) % 10, : , div(i-1, 10) + 1] .= parse.(Int, collect(lines[i])) # collect is used to create an array of `Char`s
end
end
return sudokus
end
This should run on 1.0 and 0.7 but I do not know if it runs on 0.6. Probably, you should remove undef argument in Array allocation to make it run on 0.6.
Similar to Hckr's (faster) approach, my first idea is:
s = readlines("sudoku.txt")
smat = reshape(s, 10,3)
sudokus = Dict{String, Matrix{Int}}()
for k in 1:3
sudokus[smat[1,k]] = parse.(Int, permutedims(hcat(collect.(Char, smat[2:end, k])...), (2,1)))
end
which produces
julia> sudokus
Dict{String,Array{Int64,2}} with 3 entries:
"Hard 143" => [0 0 … 0 0; 3 0 … 0 0; … ; 0 0 … 0 8; 0 0 … 0 0]
"Medium 95" => [0 0 … 0 0; 8 0 … 7 0; … ; 0 3 … 0 2; 0 0 … 0 0]
"Easy 7" => [0 0 … 0 1; 0 0 … 7 0; … ; 0 6 … 0 0; 4 0 … 0 0]
I am trying to plot a figure using three matrices but somehow I couldn't understand. I have three matrices and an array. Suppose,
A =
1 2 3
4 5 4
7 8 9
B =
2 3 13
5 11 10
9 7 6
C =
1 2 3
2 3 13
5 11 10
and an array
Y= [0.001 0.0002 0.0004].
Now I want to plot it in such a way that array values should be on y axis while against 0.001, 0.002 and 0.0004 the matrices value should be arranged.
for examples, the y=0.001, A(1,1)=1, y=0.0002, B(1,1)=2 y=0.0004, C(1,1)=1 for a single line.
and similarly process goes for A(i,j),B(i,j) and c(i,j) points using loop to plot all lines on a single figure.
Thanks
So, the first plot is plot([1,2,1],Y), the next one is plot([2,3,2],Y) and so on?
If so, you could do it like that
X = cat(3,cat(3,A,B),C);
X = reshape(permute(X,[3,1,2]),3,9);
plot(X,Y,'--x');
which gives a plot like this:
Is this what you were looking for? If not, I didn't understand your question well and I'd like to ask you to rephrase it.
You can create a 3D array (tensor) and access it in a loop.
T(:,:,1) = A;
T(:,:,2) = B;
T(:,:,3) = C;
figure;
for idi = 1:size(A,1)
for idj = 1:size(A,2)
plot(squeeze(T(idi,idj,:)).',Y); hold on;
end
end
Accessing the third dimension is not fastest operation (as they are not store sequential in memory) and if the matrices are larger you might consider reshape.
I did not understand you wanted the vector Y to be on the x-axis or y-axis (and neither of those plots make sense to me) but I am sure you can modify the code from here for your needs.
I have recently started learning Haskell and I'm having a hard time figuring out how to interpret text files.
I have following .txt file:
ncols 5
nrows 5
xllcorner 809970
yllcorner 169790
cellsize 20
NODATA_value -9999
9 0 0 0 0
0 1 0 0 0
0 0 0 0 0
0 0 0 0 0
0 2 0 0 3
The first 6 lines just display some information I need when working with the file in a GIS software. The real deal starts when I try to work with the numbers below in Haskell.
I want to tell Haskell to look up where the numbers 9, 1, 2 and 3 are and print back the number of the row and column where those numbers actually are. In this case Haskell should print:
The value 9 is in row 1 and column 1
The value 1 is in row 2 and column 2
The value 2 is in row 5 and column 2
The value 3 is in row 5 and column 5
I tried finding the solution (or at least similar methods for interpreting files) in tutorials and other Haskell scripts without any success, so any help would be greatly appreciated.
Here is an example of a script to do what you want. Note that this will in its current form does not fail gracefully (but given this is a script, I doubt this is a concern). Make sure there is a trailing newline at the end of your file!
import Control.Monad (replicateM, when)
import Data.Traversable (for)
import System.Environment (getArgs)
main = do
-- numbers we are looking for
numbers <- getArgs
-- get the key-value metadata
metadata <- replicateM 6 $ do
[key,value] <- words <$> getLine
return (key,value)
let Just rows = read <$> lookup "nrows" metadata
Just cols = read <$> lookup "ncols" metadata
-- loop over all the entries
for [1..rows] $ \row ->do
rawRow <- words <$> getLine
for (zip [1..cols] rawRow) $ \(col,cell) ->
when (cell `elem` numbers)
(putStrLn ("The value " ++ cell ++ " is in row " ++ show row ++ " and column " ++ show col))
To use it, pass it as command line arguments the numbers you are looking for and then feed as input your data file.
$ ghc script.hs
$ ./script 9 1 2 3 < data.txt
Let me know if you have any questions!
I wasn't really sure if you wanted to look up just a fixed set of numbers, or any non-zero number. As your question asked for the former, that is what I did.
I have a 4 by 4 matrix:
A=[rand(1) 2 -1 rand(1);
rand(1) 3 rand(1) 0;
rand(1) -5 -2 5;
9 0 0 rand(1)];
Now I would like to form a vector b to be the first column of the matrix A. So the vector b is
b=[rand(1)
rand(1)
rand(1)
9 ];
I would like to write a for loop that compute b many times say 100 then store these vectors in matrix C ( which now has size of 4*100) and then compute the mean of all columns of C. So far I wrote:
for j=1:100
A=[rand(1) 2 -1 rand(1);...
rand(1) 3 rand(1) 0;...
rand(1) -5 -2 5;...
9 0 0 rand(1)];
b=A(:,1)
end
Every time the loop executed, it produces a vector, say b_1 then b_2,....,b_100. How to store them in matrix C=[b_1 b_2 ... b_100] and then compute the mean of matrix C over all columns so that the mean will be a vector of size 4 by 1 the same size as b.
I don't have Matlab on this laptop but the little script should be like this:
for jj=1:100
C(:,jj)=[rand(1) ;...
rand(1) ;...
rand(1) ;...
9 ];
end
The matrix C will contain all the column-vectors b. To access to any of them just use b(:,x) where x is the index-number or column that you want to use.
For the average you can do something like this:
b_average=[mean(C(1,:)); mean(C(2,:)); mean(C(3,:));mean(C(4,:))];
Of course the last mean upon a vector with only 9 values hasn't meaning: I leave the code as it is just for completeness.
Remember as well that the average of a vector with random numbers will be really close to the value zero if N is big enough (where N is the number of the sample in the vector of course).
Anyway, the for loop is not the best way to do this. Try to use something like this:
C=[rand(1,100);rand(1,100);rand(1,100);9*ones(1,100)];
or better (as it was point out by Adriaan)
C=[rand(3,100);9*ones(1,100)];
This line does the same of the for loop. Again: try to don't use the variable j and iin Matlab because they are reserved.
How to increase the size of a matrix. I have a matrix of size 36 rows and 3000 columns. I want to convert it to an array of size 200 rows and 3600 columns without affecting the information contained in the original matrix.
In any programming language you will need to create the new array and do copy of the previous elements in the new array.
If you are using java i would prefer to use Arraylist.
You can always create 2D array using arrayList in java.Something like this
ArrayList<ArrayList<Type>>
But in C/C++ you will need to do entire copy operation.
There is a way to do this using zero padding.
Assuming matrix A has p rows and q columns and you want to convert it to a matrix B having m rows and n columns (m>p and n>q). You can use
B = padarray(A,[m-p n-q],0,'post');
B will contain the matrix A and the rest of the matrix will be all zeros.
Example:
a=randi(10,[2 2]);
a =
10 10
2 9
b = padarray(a,[4-2 3-2],0,'post');
b =
10 10 0
2 9 0
0 0 0
0 0 0