Compile-time generated 2D array in D - multidimensional-array

In my program I need to generate array with powers' (from 0 to 5) sum of numbers from 1 to 100,000.
So I tried to compile this code:
const enum size_t MAX_ARRAY_SIZE = 100_000 + 1;
const enum size_t MAX_POWER_SIZE = 5 + 1;
const enum power_sum = calc_power_sum();
// some unimportant code here
pure ulong[MAX_POWER_SIZE][MAX_ARRAY_SIZE] calc_power_sum() {
ulong[MAX_POWER_SIZE][MAX_ARRAY_SIZE] power_sum;
power_sum[0][] = 1;
foreach (x, ref element; power_sum[1]) {
element = x;
}
foreach (n; 2 .. MAX_POWER_SIZE) {
foreach (x, ref element; power_sum[n]) {
element = power_sum[n - 1][x] * power_sum[1][x];
}
}
foreach (ref power; power_sum) {
foreach (x; 1 .. MAX_ARRAY_SIZE) {
power[x] += power[x - 1]; // error appears here
}
}
return power_sum;
}
But compiler says:
$ dmd problem.d
problem.d(130): Error: array index 6 is out of bounds [1LU, 2LU, 3LU, 4LU, 5LU, 6LU][0 .. 6]
problem.d(15): called from here: calc_power_sum()
What am I doing wrong?

At first glance looks like you have simply misunderstood array dimension order. You have
ulong[MAX_POWER_SIZE][MAX_ARRAY_SIZE]
and your code assumes directly opposite
ulong[MAX_ARRAY_SIZE][MAX_POWER_SIZE]
Also I am afraid 100 000 may be a bit too much, after above mentioned fix I get an internal compiler error. Works for smaller MAX_ARRAY_SIZE values though.

As Mihail said, you should reverse the order of dimensions.
However, you most likely won't be able to do what you plan for all sizes because the maximum size of static array is limited in D ( http://dlang.org/arrays.html ) :
The total size of a static array cannot exceed 16Mb.

Related

My GML shuffling array function is alway returning the same result

I'm trying to make a shuffling array function in GML. Here's what I tried, with argument0 being the array to shuffle and argument1 being the size of this array:
///Shuffling array function
//argument0: the array to shuffle
//argument1: the size of the array
var i;
var j;
show_debug_message("----------");
show_debug_message("Original array: ");
show_debug_message(argument0);
show_debug_message("Size: ");
show_debug_message(argument1);
for (i = 0; i < argument1; i++)
{
j = irandom_range(i, argument1 - 1);
if (i != j)
{
k = argument0[i];
argument0[i] = argument0[j];
argument0[j] = k;
}
}
show_debug_message("Result array: ");
show_debug_message(argument0);
show_debug_message("----------");
return argument0;
When I execute this function, I alway got the same result:
----------
Original array:
{ { 1,2,3,4,5 }, }
Size:
5
Result array:
{ { 5,3,1,4,2 }, }
----------
Have you used the function randomize() anywhere in your game? Randomize will set the seed to a random value each time your game is run — without it, random functions will always return the same result because they're always working with the same seed value.
NOTE: [Random functions] will return the same value every time the game is run afresh due to the fact that GameMaker: Studio generates the same initial random seed every time to make debugging code a far easier task. To avoid this behaviour use randomize at the start of your game.
Documentation on randomize(): https://docs.yoyogames.com/source/dadiospice/002_reference/maths/real%20valued%20functions/randomize.html

Combine multiple mono QImage into a color QImage

For a list of colors, I have a corresponding list of QImage, format mono. The mono images have been processed in such a way that a single pixel can be black from all images.
I would like to merge them into a color image.
I had 3 ideas.
1. Use image composition modes. I was unable to get it to work. (Editing to remove it, to clean up post...)
2. Use the mono images as masks for each of the colors when added to the destination.
I have no idea how to implement it.
3. Iterating through pixels - slow, the documentation says that pixel manipulation functions are slow...
This works:
// Creating destination image
// m_colors: list of (n+1) QCcolor (last one corresponding to background)
// m_images: list of n QImage, Format_Mono, all of the same size (as the destination)
// using indexed image for destination since I have a limited palette
QImage preview = QImage(rect.size().toSize(), QImage::Format_Indexed8);
int previewWidth = preview.size().width();
int previewHeight = preview.size().height();
int colorsSize = m_colors.size();
for(int k = 0; k < colorsSize; ++k)
{
preview.setColor(k, m_colors.at(k).rgb());
}
--colorsSize;
// combining images
for(int j = 0; j < previewHeight; ++j)
{
for(int i = 0; i < previewWidth; ++i)
{
// set background color
preview.setPixel(i, j, colorsSize);
for(int k = 0; k < colorsSize; ++k)
{
QImage im = m_images.at(k);
if(!im.isNull())
{
if(m_images.at(k).pixelIndex(i, j) == 0)
{
preview.setPixel(i, j, k);
}
}
}
}
}
I should at least improve this using scanLine(), but don't know how... I can only find examples that use scanLine() with 32 bit images, not 8 or 2.
Is it actually possible to use scanLine() with 8 or 2 bit images ?
I don't understand the documentation - does it mean that only 32 bit images can be read/written using scanLine() or that regardless of image type, the function will work the same way, and I only use one of the 4 bytes ?
Would be more effective to use 32 bit images instead of 8 or 2 bit ?
If I use 32 bit image for destination, and try to use scanLine() to write data, still how can I improve my reading of the mono images ?
Please help me improve my algorithm, either to improve the version that I get to work iterating through all pixels of images, or perhaps using some tools like combining images using composition.
Is it actually possible to use scanLine() with 8 or 2 bit images ?
Yes it is.
Would be more effective to use 32 bit images instead of 8 or 2 bit ?
You will have to measure, and it will depend on the specific code. I used 8 bit code here for simplicity and because your code did.
If I use 32 bit image for destination, and try to use scanLine() to write data, still how can I improve my reading of the mono images ?
It is probably not a good idea to copy the image in the inner loop
QImage im = m_images.at(k)
and to then not use that copy for the next access.
if(m_images.at(k).pixelIndex(i, j) == 0)
It should speed up your painting if your inner loop iterates over an image instead of iterating over the destination pixels in the inner loop.
If the image is monochrome, then the scan line will point to packed color information which will need to be unpacked. It is easier (and maybe faster) to let convertToFormat convert the image and then use scanLine to read the unpacked information. In the example below the images are all 8 bit.
#include<vector>
#include <QtGui/QImage>
#include <QtGui/QColor>
static char * img1[] = {
"5 5 2 1", "a c #000000", "b c #ffffff",
"aabba", "aabba", "aabba", "aabba", "aabba"
};
static char * img2[] = {
"5 5 2 1","a c #000000","b c #ffffff",
"aaaaa", "aaaaa", "bbbbb", "bbbbb", "aaaaa"
};
int main( int argc, char* arg[] )
{
auto images = std::vector<QImage>( 2 );
images[0] = QImage( img1 );
images[1] = QImage( img2 );
auto colors = std::vector<QColor>( 2 );
colors[0] = QColor( Qt::red );
colors[1] = QColor( Qt::green );
QImage combined = QImage( images[0].size(), QImage::Format_Indexed8 );
combined.setColor( 0, Qt::black );
combined.fill(0);
for( int k = 1, num = images.size(); k <= num; ++k )
{
combined.setColor( k, colors[k-1].rgb() );
QImage img= images[k-1];
for( int i = 0, height = img.height(); i < height ; ++i )
{
uchar* src = img.scanLine(i);
uchar* dst = combined.scanLine(i);
for( int j = 0, width = mono.width(); j < width; ++j )
{
if( src[j] != 0 )
dst[j] = k;
}
}
}

D lang appending to multidimensional dynamic array

I want to append a 2D array to my 3D array. I expect it should be same as int[] arr; arr ~= 3;
void readInput()
{
char[][][] candidate;
char[] buff;
size_t counter = 0;
while ( stdin.readln(buff) )
{
char[][] line = buff.chomp().split();
writeln(line);
candidate ~= line;
writeln(candidate);
if (++counter > 1 ) break;
}
}
And I send the inputs below
201212?4 64
20121235 93
I expect a output like
[["201212?4", "64"], ["20121235", "93"]]
But instead I see
[["20121235", "93"], ["20121235", "93"]]
=~ replaces all the elements in the array with the last added. Where am I doing wrong? How can I meet my expectation?
The problem here is that byLine is reusing buf (that's actually one reason why it asks for a mutable buffer and returns mutable - as a warning that it might change on you).
So when you ~= it, it is really appending the one array multiple times all with a pointer to the same data, so when it changes, that change is seen each time.
You can fix it by adding a .dup to the array you are appending.

pointers memory allocation using calloc example

when the size of pointer array is itself 4 and when i try to print 5th value it gives a random number.How? tell me how this random allocation happens. Thanks!
#include< stdio.h>
#include< stdlib.h>
int main()
{
int* p_array;
int i;
// call calloc to allocate that appropriate number of bytes for the array
p_array = (int *)calloc(4,sizeof(int)); // allocate 4 ints
for(i=0; i < 4; i++)
{
p_array[i] = 1;
}
for(i=0; i < 4; i++)
{
printf("%d\n",p_array[i]);
}
printf("%d\n",p_array[5]); // when the size of pointer array is itself 4 and when i try to print 5th value it gives a random number.How?
free(p_array);
return 0;
}
Arrays start at zero, so p_array[5] wasn't initialized in your code. It is printing out a piece of memory that is somewhere on your system.
Read this for a great description on why arrays are zero-based.
e.g.:
p_array[0] = 1;
p_array[1] = 1;
p_array[2] = 1;
p_array[3] = 1;
p_array[4] = 1;
p_array[5] = ?????;
The following has undefined behaviour since you're reading past the end of the array:
p_array[5]
printf("%d\n",p_array[5]);
is an attempt to print an uninitialized section of memory, because your array p_array has the strenght to store only 5 items p_array = (int *)calloc(4,sizeof(int)); starting from
p_array[0] through p_array[4] and hence p_array[5] gives you a garbage value.

how to binary to qpixmap

I find it difficult to translate binary into picture, I use a pixmap.
transfer into the binary is correct but when I show using this program actually does not work.
this is my code:
if (binaryNumber[0]==1)ui->led16->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led16->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[1]=1) ui->led15->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led15->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[2]==1)ui->led14->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led14->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[3]==1)ui->led13->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led13->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[4]==1)ui->led12->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led12->setPixmap(QPixmap("../../picture/ball-gray.png"));
bool ok2 = false;
QByteArray binaryNumber = QByteArray::number(DO.toLongLong(&ok2, 16), 2);
qDebug()<<binaryNumber<<binaryNumber[0]<<binaryNumber[1]<<binaryNumber[2 <<binaryNumber[3];
i.e
binaryNumber =1011
binaryNumber[0] = 1
binaryNumber[1] = 0
binaryNumber[2] = 1
binaryNumber[3] = 1
but when
binaryNumber =100
binaryNumber[0] = 1
binaryNumber[1] = 0
binaryNumber[2] = 0
so when i use a pixmap, then led the flame does not correspond to the binary number because array [0] is different when the size is different.
is there any simple code for me?
Your use of a QByteArray to store bits of a number is unnecessary. In C/C++, you can access the bits directly by doing a bitwise AND (&) with a mask.
template <typename T> static QPixmap setPixmap(T * p, int value, int bitNo)
{
const bool bit = value & (1<<bitNo);
p->setPixmap(bit ? QPixmap("../../picture/ball-yellow.png")
: QPixmap("../../picture/ball-gray.png"));
}
void Class::setDisplay(int val)
{
setPixmap(ui->led12, val, 0);
setPixmap(ui->led13, val, 1);
setPixmap(ui->led14, val, 2);
setPixmap(ui->led15, val, 3);
setPixmap(ui->led16, val, 4);
}
Note that QByteArray::number() returns alphanumeric characters ('0' = 48, '1' = 49 etc.), not characters with the numerical values 0, 1 etc. This is an important difference!
If you do binaryNumber = QByteArray::number(value, 2), this returns a byte array like for example "1010". Thus, binaryNumber[0] == '1', NOT binaryNumber[0] == 1:
if (binaryNumber[0]=='1')ui->led16->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led16->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[1]=='1')ui->led15->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led15->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[2]=='1')ui->led14->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led14->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[3]=='1')ui->led13->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led13->setPixmap(QPixmap("../../picture/ball-gray.png"));
if (binaryNumber[4]=='1')ui->led12->setPixmap(QPixmap("../../picture/ball-yellow.png"));
else ui->led12->setPixmap(QPixmap("../../picture/ball-gray.png"));
Note that your code is riddled with redundant code lines, resulting in bad quality software. You should try to write the code above in a loop or at least move out the pixmaps. Moving the pixmap initialisations in some static variables or in the constructor of the containing class results in some performance boost, too.
So your class could look similar to this: (I only included the relevant parts, of course, there also has to be the code for the UI stuff.)
class LEDNumberView
{
private:
// member variables:
QPixmap bitOn;
QPixmap bitOff;
// helper function
inline QPixmap getBitPixmap(bool bitVal)
{
return bitVal ? bitOn : bitOff;
}
public:
// constructor
LEDNumberView()
{
QString path = "../../picture/ball-%1.png";
bitOn = QPixmap(path.arg("yellow"));
bitOff = QPixmap(path.arg("gray"));
}
// call whenever you want to change the binary number displayed by the LEDs
void setBinaryNumber(int value)
{
QByteArray binaryNumber = QByteArray::number(value, 2);
ui->led16->setPixmap(getBitPixmap(binaryNumber[0] == '1'));
ui->led15->setPixmap(getBitPixmap(binaryNumber[1] == '1'));
ui->led14->setPixmap(getBitPixmap(binaryNumber[2] == '1'));
ui->led13->setPixmap(getBitPixmap(binaryNumber[3] == '1'));
ui->led12->setPixmap(getBitPixmap(binaryNumber[4] == '1'));
ui->led11->setPixmap(getBitPixmap(binaryNumber[5] == '1'));
}
};
To combine the answer of Kuba Ober with mine, write the setBinaryNumber function as he suggested. It's up to you which method of binary conversion you prefer - bit manipulation (use his method) or convert to and then work with bytes (yours).

Resources