perl array size is smaller than it should be - arrays

I want to initialize 4^9 (=262144) indices of #clump as 0. So I wrote this:
my $k=9;
my #clump=();
my $n=4**$k;
for(my $i=0;$i<$n;$i++){
push(#clump,0);
print "$i ";
}
But it keeps freezing at 261632! I then tried making $n=5^9 (=1953125) and my code stopped at 1952392. So its definitely not a memory issue. This should be simple enough but I can't figure out what's wrong with my code. Help a newbie?

Suffering from buffering?
When I add a sleep 1000 to the end of your program, stream the output to a file, and read the tail of the file, I also observe the last numbers to be printed are 261632 and 1952392. The remaining output is stuck in the output buffer, waiting for some event (the buffer filling up, the filehandle closing, the program exiting, or an explicit flush call) to flush the output.
The buffering can be changed by one of the following statements early in your program
$|= 1;
STDOUT->autoflush(1);

#!/usr/bin/env perl
use strict;
use warnings;
my $k = 9;
my $n = 4 ** $k;
my #clump = (0) x $n;
print join(' ', #clump), "\n";
printf "%d elements in \#clump\n", scalar #clump;
Or,
#!/usr/bin/env perl
use strict;
use warnings;
my $k = 9;
my $n = 4 ** $k;
my #clump;
$#clump = $n - 1;
$_ = 0 for #clump;
print join(' ', #clump), "\n";
printf "%d elements in \#clump\n", scalar #clump;
Output:
...
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
262144 elements in #clump
Also, note that initialization with 0 is almost never required in Perl. Why do you need this?

Related

How to use offset in arrays in bash?

Here is my code.
#! /bin/bash
array=(3 2 1 0 0 0 0 0 0 0)
for i in {0..10}
do
this=${array:$i:$((i+1))}
echo $this
done
I want to print each number of my number separately. I have used this line to get the array elements using an offset number.
this=${array:$i:$((i+1))}
However I am only getting 3 printed and rest all are new lines. I basically want to print 3, 2, 1 etc on separate lines. How do I correct this?
First, you need to use the whole array array[#], not array.
echo "${array[#]:3:2}"
Then, you may change the index to simple variable names:
this=${array[#]:i:i+1}
And then, you probably need to extract just one value of the list:
this=${array[#]:i:1}
Try this code:
array=(3 2 1 0 0 0 0 0 0 0)
for i in {0..10}
do
this=${array[#]:i:1}
echo "$this"
done
There is no reason to use an array slice here, just access the individual elements of the array. Try this:
#! /bin/bash
array=(3 2 1 0 0 0 0 0 0 0)
for i in {0..10}
do
this=${array[$((i+1))]}
echo $this
done
In general you can access a single element of an array like that: ${array[3]}.
Note that in this case, it would have been preferable to do this:
array=(3 2 1 0 0 0 0 0 0 0)
for this in "${array[#]}"
do
echo $this
done

Array block splitting in MATLAB

Say we have a vector containing zeros interspersed blocks of ones of varying length, such as:
0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0
I would like to transform this into a 2D array as follows. Each row contains zeros only and one of the blocks. I.e. the number of rows of the 2D array would be the number of blocks at the end. The above array would transform to:
0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0
I.e the first block ends up in the first row, the second block in the second row etc.
Question
This exercise is rather trivial using loops. My question is if there is a neat way using MATLAB matrix operations, MATLAB functions and array indexing to do this?
Off the top of my head you could use bwlabel (from the Image Processing Toolbox) to assign each cluster of 1's a unique value. You could then use bsxfun to check equality between the labeled version and the unique labels which will automatically expand it out into a matrix.
a = [0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0];
b = bwlabel(a);
out = bsxfun(#eq, (1:max(b))', b);
Without the image processing toolbox you could do effectively the same thing with:
C = cumsum(~a);
out = bsxfun(#eq, unique(C(logical(a))).', C);
I tried this one
N = 100; % set array size
A = randi(2,N,1)-1; % generate random array filled with 0 and 1
d = diff([0;A]); % if 1 : starting point of block
% if -1 : end point of block
ir = find(A); % Find A==1 which will be row index
ic = cumsum(d(ir)>0); % Set col index
% assemble array
% if you want output as full array
A_new = accumarray([ir,ic],ones(size(ir)),[length(A),ic(end)]);
% if you want output as sparse array
A_new = sparse(ir,ic,ones(size(ir)),length(A),ic(end),length(ir));
% display routine
figure;spy(A,'r');hold on;spy([zeros(size(A)),A_new]);
Turns out it is faster than #Suever 's solution (Compared tic toc time with size 10000, 1000 trial). Also, if you use sparse instead of accumarray, then it is much faster
Suever_time = 7~8 sec
Accumarray = 2~3 sec
Sparse = 0.2~0.3 sec
However, his one is much shorter and neat!

substituting some elements of a matrix with new values bash

I am trying to read in a file, change some parts of it and write it to a new file in bash. I know that I can substitute the parts with the "sed" command but I do not know how to it in my case which is a matrix in the beginning of my file. Here is how my file looks like
alpha
1 0 0
0 1 0
0 0 1
some text here
more numbers here
and I am trying to substitute the values of the matrix above in a for loop like
for i in 1 2 3 4
do
replace 1 0 0
0 1 0
0 0 1
by 1*(1+${i}) ${i}/2 0
${i}/2 1 0
0 0 1
and print the whole file with the substitution to newfile.${i}
done
I want to do this in bash. Any idea how to do this? And I only want to change this part and only this part!
Awk is more suitable for this:
for i in {1..4}; do awk -v i="$i" -f substitute.awk oldfile.txt > newfile.$i; done
using the following substitute.awk script:
{
if( NR == 3 ) { print 1 + i, i / 2, 0 }
else if( NR == 4 ) { print i / 2, 1, 0 }
else print $0
}
(assuming, as you wrote, that the matrix is always in lines 3 through 5; in your example it is in lines 2 through 4)

How do you initialize an array of ninety '0's' in matlab?

I'm trying to initialize an array in matlab of ninety zero's. However, I don't want to write 90 consecutive zeros after even = [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...... ] etc.
Use the zeros function.
E.g. x = zeros(1,90)

for-loop left after one iteration

I'm encountering this problem and I don't get why. I used the exact same loop before to test it (without inside code) and it worked. I'm not a programming newbie (though c newbie), but now I definitely feel like one. I replaced length with a hard coded number, doesn't change anything. jobStatus() also only uses a for-loop which works fine. Help is appreciated!
PS: Don't mind the if / else-if part. This was just a desperation move because I cant find the problem, I know that I don't need the last else if etc.
thanks in advance
#include <stdio.h>
#include <stdlib.h>
short jobs[] = {6,13,7,3,4,9,10,11};
short table[13][10];
short Q,i,j,k,diff;
short sum;
void jobStatus(short a){
printf("Jobstatus:");
for(i=0;i<a;i++){
printf(" %i",jobs[i]);
} printf("\n");
}
int main(){
// berechne Anzahl der Jobs
short length = sizeof(jobs)/2;
printf("Jobs: %i\n", length);
/* für alle Quanten Q
for(Q=0;Q<13;Q++){
// schreibe das jeweilige Quantum in die erste Spalte jeder Zeile
table[Q][0]=(Q+1);
gehe jeden Job durch*/
for(i=0;i<length;i++){
printf("Current Job: %i\n", i);
/* falls der aktuelle job i bereits erledigt ist überspringe ihn
if(jobs[i]==0){
i++;
}*/
diff=jobs[i]-(Q+1);
if(diff>0){
jobs[i]=diff;
jobStatus(length);
table[Q][i+1]=diff;
} else if(diff==0){
jobs[i]=0;
} else if(diff<0){
diff=diff*(-1);
jobs[i]=0;
table[Q][i+1]+=diff;
}
}
printf("# Q P1 P2 P3 P4 P5 P6 P7 P8 Avg.Time\n");
printf("#------------------------------------\n");
for(Q=0;Q<13;Q++){
for(i=0;i<8;i++){
printf(" %i", table[Q][i]);
}
printf("\n");
}
return 0;
}
This is the output:
Jobs: 8 // Indicates that length should be set to 8
Jobstatus: 5 13 7 3 4 9 10 11
Q P1 P2 P3 P4 P5 P6 P7 P8 Avg.Time
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
You have only a global variable i which is used in both for loops (inside jobstatus and in your main). Thus once you call jobstatus(length); within your main loop the content of the variable will be changed and afterwards the loop terminates (because i was then set to length).
You are using global variable i. It is changes inside jobStatus and for-loop in main.
Try to use local inside main()
I agree with Howard, but I think that sizeof(jobs) it's wrong. You should write something like (sizeof (jobs))/(sizeof (jobs[0])) or instead use count() function.

Resources