Convert a Map[Int, Array[(Int, Int)]] to Map[Int, Map[Int, Int]] in Scala - arrays

I have a data structure like this:
Map(
0 -> Array((1,1), (2,1)),
1 -> Array((2,1), (3,1), (0,1)),
2 -> Array((4,1), (0,1), (1,1)),
3 -> Array((1,1)),
4 -> Array((5,1), (2,1)),
5 -> Array((4,1))
)
and the result I need should look like this:
Map(
0 -> Map(1 -> 1, 2 -> 1),
1 -> Map(2 -> 1, 3 -> 1, 0 -> 1),
2 -> Map(4 -> 1, 0 -> 1, 1 -> 1),
3 -> Map(1 -> 1),
4 -> Map(5 -> 1, 2 -> 1),
5 -> Map(4 -> 1)
)

It is really simple: yourMap.mapValues(_.toMap)
scala> :paste
// Entering paste mode (ctrl-D to finish)
Map(
0 -> Array((1,1), (2,1)),
1 -> Array((2,1), (3,1), (0,1)),
2 -> Array((4,1), (0,1), (1,1)),
3 -> Array((1,1)),
4 -> Array((5,1), (2,1)),
5 -> Array((4,1))
)
// Exiting paste mode, now interpreting.
res0: scala.collection.immutable.Map[Int,Array[(Int, Int)]] = Map(0 -> Array((1,1), (2,1)), 5 -> Array((4,1)), 1 -> Array((2,1), (3,1), (0,1)), 2 -> Array((4,1), (0,1), (1,1)), 3 -> Array((1,1)), 4 -> Array((5,1), (2,1)))
scala> res0.mapValues(_.toMap)
res1: scala.collection.immutable.Map[Int,scala.collection.immutable.Map[Int,Int]] = Map(0 -> Map(1 -> 1, 2 -> 1), 5 -> Map(4 -> 1), 1 -> Map(2 -> 1, 3 -> 1, 0 -> 1), 2 -> Map(4 -> 1, 0 -> 1, 1 -> 1), 3 -> Map(1 -> 1), 4 -> Map(5 -> 1, 2 -> 1))

Related

Shuffle array several times without repeating pairs

I have a list of names, for example:
"Alice", "Bob", "Steve", "Kate", "Jane", "John", "Vic", "Dan", "Robert"
They call each other in a circle chain:
"Alice" -> "Bob" -> "Steve" -> "Kate" -> "Jane" -> "John" -> "Vic" -> "Dan" -> "Robert" -> "Alice"
I need an algorithm which will print several chains where in the result every person should have a call with all other persons without repeats. So if Vic called Dan and John called Vic yestarday all of them should have another persons in today call.
Your task can be achieved by the following MiniZinc model:
include "circuit.mzn";
int: n = 9; % number of participants
int: rounds = 4;
set of int: N = 1..n;
set of int: Rounds = 1..rounds;
% decision variables
array[N, Rounds] of var N: x;
predicate is_chain(array[N] of var N: c) =
circuit(c);
predicate is_talking_to(N: p1, N: p2, Rounds: r) =
(x[p1, r] == p2) \/
(x[p2, r] == p1);
constraint forall(r in Rounds) (circuit([x[p, r] | p in N]));
constraint forall(r1 in Rounds, r2 in r1+1..rounds, p1 in N, p2 in p1+1..n)
(is_talking_to(p1, p2, r1) -> not is_talking_to(p1, p2, r2));
function string: show_chain(array[N] of var N: c) =
join(" -> ", [ "\(c[p])" | p in N ]) ++ " -> \(c[1])\n";
output [ show_chain([fix(x[p, r]) | p in N]) | r in Rounds ];
Example output:
7 -> 5 -> 2 -> 9 -> 8 -> 4 -> 3 -> 6 -> 1 -> 7
4 -> 8 -> 9 -> 7 -> 1 -> 5 -> 2 -> 3 -> 6 -> 4
6 -> 9 -> 1 -> 3 -> 7 -> 2 -> 8 -> 4 -> 5 -> 6
2 -> 4 -> 6 -> 5 -> 3 -> 7 -> 9 -> 1 -> 8 -> 2
For more than four rounds, no solution was found.
The model interpretes to "have a call" as symmetric "speaking to eachother". It does not matter, who is initiating a call.

Longest Path: Recursive Backtracking with Constraints in C

I was recently assigned a problem, which boils down to finding the longest path in a given matrix, where two cells are adjacent iff the neighboring value is less than the present cell. I've been tearing my hair out trying to figure it out, so I would be extremely grateful for any help. However, as I said, this is a homework assignment, so suggestions and hints are very welcome (but try not to make it too easy for me).
Here's the latest version of my code:
#include <stdio.h>
int isValid(int i, int j, int rows, int cols) {
if (i < 0 || i >= rows || j < 0 || j >= cols)
return 0;
return 1;
}
void printpath(int path[1000][2]) {
int i = 0;
while (path[i][0] != -1) {
printf("(%d, %d) ", path[i][0], path[i][1]);
i++;
}
}
void print_array_path(int path[1000][2], int array[100][100]) {
int i = 0;
while (path[i][0] != -1) {
printf("%d -> ", array[path[i][0]][path[i][1]]);
i++;
}
}
int path_length(int path[1000][2]) {
int i = 0, s = 0;
while ( path[i][0] != -1) {
s++;
i++;
}
return s-1;
}
void add_path(int path[1000][2], int u, int v) {
int i = 0;
while (path[i][0] != -1) {
i++;
}
path[i][0] = u; // row
path[i][1] = v; // column
}
int last_i(int path[1000][2], int s) {
int v;
v = path[s][0];
//path[i-2][0] = -1;
return v;
}
int last_j(int path[1000][2], int s) {
int u;
u = path[s][1];
//path[i-2][1] = -1;
return u;
}
int c1[4] = {1, 0, -1, 0};
int c2[4] = {0, 1, 0, -1};
int dfs(int visited[100][100], int array[100][100], int i, int j, int rows, int cols, int path[1000][2], int length) {
// 1. Take the current visited, along with the previous vertex, to create a unique
// list of visited vertices.
// 2. For every direction, check if it is valid. If valid, do dfs(visited, current, choice)
// 3. If all four directions are checked, with no valid choice, report the solution.
int s;
for (s=0; s<4; s++) {
if ( isValid(i+c1[s], j+c2[s], rows, cols) && !(visited[i+c1[s]][j+c2[s]]) && (array[i][j] < array[i+c1[s]][j+c2[s]]) ) {
// TODO visited.add(current)
visited[i][j] = 1;
add_path(path, i+c1[s], j+c2[s]);
//printf("%d -> ", array[i+c1[s]][j+c2[s]]);
//printpath(path);
length += 1;
dfs( visited, array, i+c1[s], j+c2[s], rows, cols, path, length);
} else if (s==3) {
//visited[i+c1[s]][j+c2[s]] = 0;
//printf("end at %d, %d\n", i, j);
if ( (last_i(path, i) == i) && (last_i(path, j) == j) ){
printf("%d ", length);
print_array_path(path, array);
printf("\n");
continue;
}
length -= 1;
dfs(visited, array, last_i(path, i-1), last_j(path, i-1), rows, cols, path, length);
return path[i][0];
}
}
}
int main() {
int array[100][100];
int rows, columns;
scanf("%d", &rows);
scanf("%d", &columns);
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < columns; j++) {
scanf("%d", &array[i][j]);
}
}
for (i = 0; i < rows; i++) {
for (j = 0; j < columns; j++) {
printf("%d ", array[i][j]);
}
printf("\n");
}
int visited[100][100];
for (i=0; i<rows; i++) {
for (j=0; j<columns; j++) {
visited[i][j] = 0;
}
}
int path[1000][2];
for (i=0; i<1000; i++) {
for (j=0; j<2; j++) {
path[i][j] = -1;
}
}
path[0][1] = 0;
path[0][0] = 0;
int length = 0;
dfs(visited, array, 0, 0, rows, columns, path, length);
}
Basically, it first collects an inputted matrix, and starts at the first cell (once I get the whole thing working, it would move through every cell), calls a search function, checks to see if a neighboring cell is valid, then calls the search again. If all four directions have been checked, it backtracks. The current path is tracking in a list path. My problem seems to mostly be in the backtracking part. However, I'm not sure how to move forward. This code barely compiles at the moment, as I've been trying so many different things. At this point, I'd like to catch my breath and really understand what I'm trying to do.
Earlier on, I tried generating an adjacency list, and constructing paths from that, but the backtracking option seemed more promising. A typical input looks like this:
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
To express a 5x5 matrix. The expected output would be 25 (25->24-> ... 2->1). Please let me know if any other info would be helpful. Any advice / tips would be greatly appreciated! Thanks.
EDIT: The original problem was reversed (i.e two cells are adj iff the neighbor has a strictly lower value. The two problems are equivalent, right?)
EDIT 2: I made some changes to the code, and I think I'm a bit closer. It now gives this output:
3 1 -> 16 -> 17 -> 24 -> 25 ->
3 1 -> 16 -> 17 -> 24 -> 25 ->
4 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 ->
9 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 ->
10 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 ->
8 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 ->
17 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 ->
20 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 ->
21 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 ->
21 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 ->
19 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
19 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
13 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
12 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
11 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
9 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
8 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
7 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
8 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
7 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
5 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
4 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
2 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
1 1 -> 16 -> 17 -> 24 -> 25 -> 18 -> 25 -> 19 -> 20 -> 21 -> 22 -> 25 -> 23 -> 25 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 23 -> 13 -> 14 -> 23 -> 15 -> 25 ->
I replaced the above code to reflect those changes. It seems very close, but not quite the right answer, namely, the path seems to be found but the lengths are not correct.
The main problem of the current code is trackback.
It is necessary to return the environment after executing the function.
Specific modification example:
#include <stdio.h>
#include <stdbool.h>
#define MAX_LEN 1000
#define SIZE 100
#define EOP -1 //End Of Path
typedef struct pos {
int r, c;//rows, columns
} Pos;
Pos EPOS = { EOP, EOP};
bool isValidPos(Pos pos, int rows, int cols) {
return 0 <= pos.r && pos.r < rows && 0 <= pos.c && pos.c < cols;
}
bool isVisited(Pos pos, bool visited[SIZE][SIZE]){
return visited[pos.r][pos.c];
}
/* unused
void printPos(Pos pos){
printf("(%d, %d)", pos.r, pos.c);
}
void printpath(Pos path[]){
while(path->r != EOP)
printPos(*path++);
}
int path_length(Pos path[]) {
int i = 0;
while((path++)->r != EOP)
++i;
return i;
}
void add_path(Pos path[], Pos pos) {
while (path->r != EOP)
++path;
*path = pos;
path[1] = EPOS;
}
*/
int valueOf(Pos pos, int array[SIZE][SIZE]){
return array[pos.r][pos.c];
}
void print_path(Pos path[], int array[SIZE][SIZE]){
while(path->r != EOP)
printf("%d -> ", valueOf(*path++, array));
}
const Pos rpos[] = {{1,0},{0,1},{-1,0},{0,-1}};//relative position
void dfs(bool visited[SIZE][SIZE], int array[SIZE][SIZE], Pos pos, int rows, int cols, Pos path[], int length){
visited[pos.r][pos.c] = true;
int value = valueOf(pos, array);
bool CantAddPath = true;
for (int s = 0; s < sizeof(rpos)/sizeof(*rpos); s++){
Pos movePos = { .r = pos.r + rpos[s].r, .c = pos.c + rpos[s].c};
if(!isValidPos(movePos, rows, cols) || isVisited(movePos, visited) || value >= valueOf(movePos, array))
continue;
CantAddPath = false;
path[length++] = pos;//add_path(path, pos);length++;
dfs(visited, array, movePos, rows, cols, path, length);
path[--length] = EPOS;
}
if(CantAddPath){
printf("%d ", length+1);//+1: current (last) postion
print_path(path, array);
printf("%d\n", value);//value of current (last) position
}
visited[pos.r][pos.c] = false;
}
int main(void) {
int array[SIZE][SIZE];
int rows, columns;
scanf("%d", &rows);
scanf("%d", &columns);
int i, j;
for(i = 0; i < rows; i++)
for(j = 0; j < columns; j++)
scanf("%d", &array[i][j]);
for(i = 0; i < rows; i++){
for(j = 0; j < columns; j++)
printf("%2d ", array[i][j]);
printf("\n");
}
bool visited[SIZE][SIZE] = {{ false }};
Pos path[MAX_LEN];
for (i = 0; i < MAX_LEN; i++){
path[i] = EPOS;
}
Pos start = { 0, 0 };
//path[0] = start;//Mismatch with `int length = 0;`
int length = 0;
dfs(visited, array, start, rows, columns, path, length);
}

Loop text to match character count between two linked list in C

I have this text that I want to loop to match the count of my elements in a linked list.
char myBaseArray[] = "close your eyes ";
I have this linked list made of int (0 and 1) like this :
linkedListOne = 1 -> 0 -> 0 -> 0 -> 1 -> 1 -> 1 -> 1 -> 1 -> 1 -> 1 -> 0 -> 0 -> 0
I want to make a second linked list with the same number of 0's and 1's and loop through my base array for text. In other words, 1's and 0's are letters but I want to keep the blanks with my base array.
Example 1 :
linkedListOne = 1 -> 0 (2 elements in my list)
linkedListTwo = c -> l (2 letters)
Example 2 :
linkedListOne = 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 -> 1 -> 0 (20 elements in my list)
linkedListTwo = c -> l -> o -> s -> e ->(blank)-> y -> o -> u -> r ->(blank)-> e -> y -> e -> s ->(blank)->c -> l -> o -> s -> e->(blank)->y -> o(20 letters)
As you can see blank does not count as a 0 or 1.
The example 2 is more complex because I have to add blank spaces in my linked list so when I print it, it will output :
close your eyes close yo
Another output with a very long list could be :
close your eyes close your eyes close your eyes close your eyes close your eyes
My linked list are working just fine and I have implemented a count function so I know the numbers of 1's and 0's. I am not sure on how to loop through my base array to match that count.
I ended doing this :
int i=0;
int j=0;
while(i != LETTER_COUNT)
{
char c = myBaseArray[j % myBaseArray_LENGTH];
if(c == ' '){
linkedListTwo = add(linkedListTwo, c);
j++;
}
else{
linkedListTwo= add(linkedListTwo, c);
j++;
i++;
}
}

storing value against variable name "QW1I5K20" in an array element Q[1,5,20] using R

I have an excel file (.csv) with a sorted column of variable names such as "QW1I1K5" and numerical values against them.
this list goes on for
W from 1 to 15
I from 1 to 4
K from 1 to 30
total elements = 15*4*30 = 1800
I want to store the numerical values against these variables in an array whose indices are derived from the variable name .
for example QW1I1K5 has a value 11 . this must be stored in an array element Q[1,1,5] = 11 ( index set of [1,1,5] corresponds to W1 , I1 , K5)
May be this helps
Q <- array(dat$Col2, dim=c(15,4,30))
dat$Col2[dat$Col1=='QW1I1K5']
#[1] 34
Q[1,1,5]
#[1] 34
dat$Col2[dat$Col1=='QW4I3K8']
#[1] 38
Q[4,3,8]
#[1] 38
If you want the index along with the values
library(reshape2)
d1 <- melt(Q)
head(d1,3)
# Var1 Var2 Var3 value
#1 1 1 1 12
#2 2 1 1 9
#3 3 1 1 29
Q[1,1,1]
#[1] 12
Q[3,1,1]
#[1] 29
Update
Suppose, your data is in the order as you described in the comments, which will be dat1
indx <- read.table(text=gsub('[^0-9]+', ' ', dat1$Col1), header=FALSE)
dat2 <- dat1[do.call(order, indx[,3:1]),]
Q1 <- array(dat2$Col2,dim=c(15,4,30))
Q1[1,1,2]
#[1] 20
dat2$Col2[dat2$Col1=='QW1I1K2']
#[1] 20
data
Col1 <- do.call(paste,c(expand.grid('QW', 1:15, 'I', 1:4, 'K',1:30),
list(sep='')))
set.seed(24)
dat <- data.frame(Col1, Col2=sample(1:40, 1800,replace=TRUE))
dat1 <- dat[order(as.numeric(gsub('[^0-9]+', '', dat$Col1))),]
row.names(dat1) <- NULL
I would suggest looking at using "data.table" and setting your key to the split columns. You can use cSplit from my "splitstackshape" function to easily split the column.
Sample Data:
df <- data.frame(
V1 = c("QW1I1K1", "QW1I1K2", "QW1I1K3",
"QW1I1K4", "QW2I1K5", "QW2I3K2"),
V2 = c(15, 20, 5, 6, 7, 9))
df
# V1 V2
# 1 QW1I1K1 15
# 2 QW1I1K2 20
# 3 QW1I1K3 5
# 4 QW1I1K4 6
# 5 QW2I1K5 7
# 6 QW2I3K2 9
Splitting the column:
library(splitstackshape)
out <- cSplit(df, "V1", "[A-Z]+", fixed = FALSE)
setnames(out, c("V2", "W", "I", "K"))
setcolorder(out, c("W", "I", "K", "V2"))
setkey(out, W, I, K)
out
# W I K V2
# 1: 1 1 1 15
# 2: 1 1 2 20
# 3: 1 1 3 5
# 4: 1 1 4 6
# 5: 2 1 5 7
# 6: 2 3 2 9
Extracting rows:
out[J(1, 1, 4)]
# W I K V2
# 1: 1 1 4 6
out[J(2, 3, 2)]
# W I K V2
# 1: 2 3 2 9

Printing a 2d array in haskell

I'm messing around with printing a random 2d array of Ints, in this simple image format (PPM)
0 1 0 0 1
1 0 0 1 0
0 1 1 0 0
0 1 1 1 0
0 0 0 1 0
Below is my code, which works, but seems like way too much code for such a simple operation. Is there a better way to do this?
import System.Random
import Data.Array.IArray
main = do
g <- newStdGen
let img = listArray ((0,0),(5,5)) ( myRands g ) :: Array (Int,Int) Int
putStrLn $ printArray img
myRands :: RandomGen g => g -> [Int]
myRands g = randomRs (0,1) g
make2dRange :: Int -> Int -> Int -> Int -> [(Int,Int)]
make2dRange x1 y1 x2 y2 = range ((x1,y1),(x2,y2))
printArray :: ( Array (Int,Int) Int ) -> String
printArray arr = unlines rows
where rows = map (unwords . map (show . (!) arr)) rowIndices
rowIndices = map ( \y -> make2dRange 0 y 5 y ) [0..5]
Other than the obvious, of course (array dimensions are hardcoded, for example)
I would use list comprehensions to manipulate the indices.
printArray arr =
unlines [unwords [show (arr ! (x, y)) | x <- [0..5]] | y <- [0..5]]
per: http://lambda.haskell.org/platform/doc/current/packages/split-0.2.2/doc/html/Data-List-Split.html#v%3achunksOf
chunksOf :: Int -> [e] -> [[e]]
chunksOf n splits a list into length-n pieces. The last piece will be shorter if n does not evenly divide the length of the list. If n <= 0, chunksOf n l returns an infinite list of empty lists.
using chunksOf my implementation would be..
printArray arr = mapM_ (putStrLn . unwords) $ map (map show) $ chunksOf 5 arr
usage:
Prelude System.Random Data.List Data.List.Split> printArray [0..25]
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
25

Resources