I guess I'm not setting the array correctly or something, but this throws a "nullreferenceexception" when it gets to the line where it actually sets the new array value to the color_table array (should be the 7th and 12th lines of what you see below). How should I write this so that it works?
public int[] colors = new int[] { 0, 255, 0, 255, 0, 255 };
private int[][] color_table;
public void setcolors()
{
this.color_table[0] = new int[] { 0, 0, 0 };
for (int i = 1; i <= this.precision; i++) {
int r = (((this.colors[1] - this.colors[0]) * ((i - 1) / (this.precision - 1))) + this.colors[0]);
int g = (((this.colors[3] - this.colors[2]) * ((i - 1) / (this.precision - 1))) + this.colors[2]);
int b = (((this.colors[5] - this.colors[4]) * ((i - 1) / (this.precision - 1))) + this.colors[4]);
this.color_table[i] = new int[] { r, g, b };
}
}
I've heard something about that you MUST initialize an array with its length before using it, but a) I don't know how to do that and b) I'm not sure if it's problem. The issue there is that I don't know what the array length is going to be. I tried this to no avail:
private int[this.precision][3] color_table;
Thanks!
this.color_table has not been initialized. Hence you can't assign values to it.
Did you mean something like this:
public void setcolors()
{
color_table = new int[precision + 1][];
for (int i = 1; i <= this.precision; i++)
{
int r = (((this.colors[1] - this.colors[0]) * ((i - 1) / (this.precision - 1))) + this.colors[0]);
int g = (((this.colors[3] - this.colors[2]) * ((i - 1) / (this.precision - 1))) + this.colors[2]);
int b = (((this.colors[5] - this.colors[4]) * ((i - 1) / (this.precision - 1))) + this.colors[4]);
this.color_table[i] = new int[] { r, g, b };
}
}
try to use list if you don't know the length of your array
List<int[]> color_table = new List<int[]>();
...
color_table.Add(new int[] { r, g, b });
Related
I'm struggling with dynamic programming and desperately need help! I would very appreciate it. For hours I've been trying to transform a recursive method into a non-recursive one, but was unable to do that. My initial task was to write two algorithms for a recurrent equation. The first method being a recursive method, the other using a loop and storing the data.
There are two integers, n and w, and two integer arrays s[n] and p[n]. Need to find the return value of a recursive method G1(n, w) then create method G2(n, w) which would complete the same task, but it has to use loops instead of recursion.
private static int G1(int k, int r)
{
if (k == 0 || r == 0)
{
return 0;
}
if (s[k - 1] > r)
{
return G1(k - 1, r);
}
return Max(G1(k - 1, r), p[k - 1] + G1(k - 1, r - s[k - 1]));
}
I found a possible solution for C#, but I couldn't apply it for my equation:
A similar task (RECURSION)
A similar task (LOOP)
This is my code and initial data, but I can't get it to work:
n = 3;
w = 3;
s = new List<int>{ 2, 3, 8 };
p = new List<int> { 1, 3, 5 };
private static int G2(int k, int r)
{
List<Tuple<int, int, int>> data = new List<Tuple<int, int, int>>();
data.Add(new Tuple<int, int, int>(0, 0, 0));
do
{
if (data[0].Item1 == 0 || data[0].Item2 == 0)
{
data[0] = new Tuple<int, int, int>(data[0].Item1, data[0].Item2, 0);
}
else
{
if (s[data[0].Item1 - 1] > data[0].Item2)
{
data.Add(new Tuple<int, int, int>(data[0].Item1 - 1, data[0].Item2, data[0].Item3));
}
if (data[0].Item1 + 1 >= k)
{
data.Add(new Tuple<int, int, int>(data[0].Item1 - 1, data[0].Item2, data[0].Item3));
}
if (data[0].Item2 + 1 >= r)
{
data.Add(new Tuple<int, int, int>(data[0].Item1 - 1, data[0].Item2 - s[data[0].Item1 - 1], data[0].Item3 + p[data[0].Item1 - 1]));
}
}
Console.WriteLine($"DEBUG: current k: {data[0].Item1} current r: {data[0].Item2} current result: {data[0].Item3}");
data.RemoveAt(0);
} while (data.Count > 0 && data.Count(entry => entry.Item1 == k && entry.Item2 == r) <= 0);
return data.First(entry => entry.Item1 == k && entry.Item2 == r).Item3;
}
There is a common solution. You should create a 2D arry by the size of k x r. Then, loop on this array in diagonal zigzag order to fill the value (in bottom-up order, like the following image).
At the end of the filling the value of the 2d array, you will have the value of G2(k,r). You can find the implementation of G2(k,r) in the below.
int G2(int k, int r)
{
int[,] values = new int[k + 1,r + 1];
var maxDim = Max(k + 1,r + 1);
for( int h = 1 ; h < maxDim * 2 ; h++ ) {
for( int j = 0 ; j <= h ; j++ ) {
int i = h - j;
if( i <= k && j <= r && i > 0 && j > 0 ) {
if (s[i - 1] > j)
{
values[i,j] = values[i - 1, j];
}
else
{
values[i,j] = Max(values[i - 1, j], p[i - 1] + values[i - 1, j - s[i - 1]]);
}
}
}
}
return values[k , r];
}
I am halfway done with converting this function from c to c# but I am totally lost as to what the middle computational line does.
y -= m < 3;
C Version
int DayOfWeek(int d, int m, int y)
{
static int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
y -= m < 3;
return (y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7;
}
C# Version
int DayOfWeek(int d, int m, int y)
{
int[] t = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
y -= m < 3;
return (y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7;
}
1) I understand y -= m is equivalent to y = y - m but what does "<" do? Is it an expression?
2) How do I convert the rest of this to c#?
Thank you everyone, for clarification this is for a degree program.
y -= (m < 3) ? 1 : 0;
or more readibly
if (m < 3) y -= 1;
or even
if (m < 3) --y;
It's some C code using the fact that conditionals return 1 or 0 as a value. Fix as shown.
Edit: I now see the comments saying this code is obfuscated. I guess I'm such an old C hat I found it immediately obvious on reading it, not that I recommend writing it that way.
Or we can do this thing the really ovbious way:
int DayOfWeek(int d, int m, int y) => (new DateTime(y, m, d)).DayOfWeek;
I am unfamiliar with C# syntax, but in C
m < 3
evaluates to 0 or 1. The line
y -= m < 3;
is equivalent to
if(m < 3) { y--; }
int DayOfWeek(int d, int m, int y)
{
var dt = new DateTime(y,m,d);
return (int) dt.DayOfWeek;
}
For example, if the array is like
1 1 0 0
0 1 1 0
0 0 1 0
1 0 0 0
then the answer is 5.
I have a helper function
// Returns the size of the region of 1s containing the point (x0, y0).
// For example, if mat = 0 0 1
// 1 0 0
// 1 1 1
// then max_connected_region(0,0,mat) = 0,
// max_connected_region(2,0,mat) = 1,
// and max_connected_region(0,1,mat) = 4
static int max_connected_region(int x0, int y0, int[,] mat)
{
if(mat[x0,y0] == 0)
return 0;
var surroundings = (new int[][] {
new int[] { x0 - 1, y0 }, new int[] {x0 + 1, y0 },
new int[] { x0 - 1, y0 + 1}, new int[] { x0, y0 + 1 }, new int[] {x0 + 1, y0 + 1},
new int[] { x0 - 1, y0 - 1}, new int[] { x0, y0 - 1 }, new int[] {x0 + 1, y0 - 1} }
).Where(pair => pair[0] >= 0 && pair[0] < mat.GetLength(0) && pair[1] >= 0 && pair[1] < mat.GetLength(1));
int count = 1;
foreach(var pair in surroundings)
count += max_connected_region(pair[0], pair[1], mat);
mat[x0,y0] = 0;
return count;
}
and how I find the maximum connection in an n x m array (n rows, m columns) is using it like
int max_connections = 0;
for(int j = 0; j < n; ++j)
{
for(int i = 0; i < m; ++i)
{
if(matrix[i,j] == 0)
continue;
int connections = max_connected_region(i,j,matrix);
if(connections > max_connections)
max_connections = connections;
}
}
This procedure is giving me either a timeout or an out-of-bounds in the test cases and I can't figure out why.
As noted in the comments, your algorithm is revisiting array elements it's already checked, putting it in an endless loop.
You actually have a program statement that appears to be trying to avoid this, but you execute it after your recursive call. So it has no useful effect. If you simply move it before the loop that performs the recursive calls, your algorithm will work:
static int max_connected_region(int x0, int y0, int[,] mat)
{
if (mat[x0, y0] == 0)
return 0;
var surroundings = (new int[][] {
new int[] { x0 - 1, y0 }, new int[] {x0 + 1, y0 },
new int[] { x0 - 1, y0 + 1}, new int[] { x0, y0 + 1 }, new int[] {x0 + 1, y0 + 1},
new int[] { x0 - 1, y0 - 1}, new int[] { x0, y0 - 1 }, new int[] {x0 + 1, y0 - 1} }
).Where(pair => pair[0] >= 0 && pair[0] < mat.GetLength(0) && pair[1] >= 0 && pair[1] < mat.GetLength(1));
int count = 1;
mat[x0, y0] = 0;
foreach (var pair in surroundings)
count += max_connected_region(pair[0], pair[1], mat);
return count;
}
I note that your algorithm is destructive. That is, it modifies the array that's passed to it. This may be acceptable for your scenario — at worst, it means the caller needs to make sure that it passes a copy of its data. But if this were to be some sort of library method, you might consider making the copy yourself, or using an appropriately-sized bool[,] to track where the algorithm has already visited.
I also feel that allocating a whole new array for the surroundings with each iteration of the method is maybe not the best approach. If you intend to run this algorithm on much larger data sets, it might make more sense to have a static array containing the valid offsets, and then just have an explicit for loop iterating through that array for the recursive calls. This will minimize the extra memory allocation and garbage collection overhead as you visit each array element.
Making those changes, the method, and its supporting class members, would look more like this:
static int max_connected_region2(int x0, int y0, int[,] mat)
{
return max_connected_region2_impl(x0, y0, (int[,])mat.Clone());
}
static int max_connected_region2_impl(int x0, int y0, int[,] mat)
{
if (mat[x0, y0] == 0)
return 0;
int count = 1;
mat[x0, y0] = 0;
for (int i = 0; i < adjacentCells.Length; i++)
{
int[] pair = adjacentCells[i];
int x1 = pair[0] + x0, y1 = pair[1] + y0;
if (x1 >= 0 && x1 < mat.GetLength(0) && y1 >= 0 && y1 < mat.GetLength(1))
{
count += max_connected_region2_impl(x1, y1, mat);
}
}
return count;
}
private static readonly int[][] adjacentCells =
{
new [] { -1, 0 }, new [] { 1, 0 }, new [] { -1, 1 }, new [] {0, 1 },
new [] { 1, 1 }, new [] { -1, -1}, new [] { 0, -1 }, new [] { 1, -1 }
};
so I want to allow user to choose even number of grayscales for output image,
I found pseudocode on wikipedia and implemented it ( I think properly), it works fine if I use 2 grayscales (black &white), but it reduces quality if I choose 4 and more grayscales instead of actually improving it.
Orginal image
result after using 2 grayscales (black&white) which is good
will post 2 more pictures in comment (1.weird result after 4 grayscale dithering , 2. how proper result should look like with 4grayscales), because I dont have reputation to post more than 2 links...
here is my code:
public static byte Truncate(byte a, int b)
{
if (a + b < 0)
return 0;
else if (a + b > 255)
return (byte)255;
else
return (byte)(a + b);
}
public static Color FindNearestColor(Color color, Color[] palette)
{
int minDistanceSquared = 255 * 255 + 255 * 255 + 255 * 255 + 1;
int bestIndex = 0;
for (int i = 0; i < palette.Length; i++)
{
int Rdiff =(color.R) - (palette[i].R);
int Gdiff =(color.G) - (palette[i].G);
int Bdiff =(color.B) - (palette[i].B);
int distanceSquared = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff;
if (distanceSquared < minDistanceSquared)
{
minDistanceSquared = distanceSquared;
bestIndex = i;
}
}
return palette[bestIndex];
}
here is my dithering function
public static Bitmap Dither(Bitmap image,int grayshades)
{
Color[] palette = new Color[grayshades];
double start = 0;
for (int i = 0; i < palette.Length; i++)
{
double x = start;
Color a =Color.FromArgb(255,(int)x, (int)x, (int)x);
start += 255 / (grayshades - 1);
palette[i] = a;
}
Color b = Color.FromArgb(255, 255, 255, 255);
palette[palette.Length - 1] = b;
int height = image.Height;
int width = image.Width;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width;x++)
{
Color currentPixel = image.GetPixel(x, y);
Color bestColor = FindNearestColor(currentPixel, palette);
image.SetPixel(x, y, bestColor);
int errorR = (currentPixel.R) - (bestColor.R);
int errorG = (currentPixel.G) - (bestColor.G);
int errorB = (currentPixel.B) - (bestColor.B);
if (x + 1 < width)
{
image.SetPixel(x + 1, y + 0, Color.FromArgb(
Truncate(image.GetPixel(x + 1, y + 0).R, (errorR * 7) >> 4),
Truncate(image.GetPixel(x + 1, y + 0).G, (errorG * 7) >> 4),
Truncate(image.GetPixel(x + 1, y + 0).B, (errorB * 7) >> 4)
));
}
if (y + 1 < height)
{
if (x - 1 > 0)
{
image.SetPixel(x - 1, y + 1, Color.FromArgb(
Truncate(image.GetPixel(x - 1, y + 1).R, (errorR * 3) >> 4),
Truncate(image.GetPixel(x - 1, y + 1).G, (errorG * 3) >> 4),
Truncate(image.GetPixel(x - 1, y + 1).B, (errorB * 3) >> 4)
));
}
image.SetPixel(x , y + 1, Color.FromArgb(
Truncate(image.GetPixel(x , y + 1).R, (errorR * 5) >> 4),
Truncate(image.GetPixel(x , y + 1).G, (errorG * 5) >> 4),
Truncate(image.GetPixel(x , y + 1).B, (errorB * 5) >> 4)
));
if (x + 1 < width)
{
image.SetPixel(x + 1, y + 1, Color.FromArgb(
Truncate(image.GetPixel(x + 1, y + 1).R, (errorR * 1) >> 4),
Truncate(image.GetPixel(x + 1, y + 1).G, (errorG * 1) >> 4),
Truncate(image.GetPixel(x + 1, y + 1).B, (errorB * 1) >> 4)
));
}
}
}
}
return image;
}
I have looked over this code many times and have no idea why it yields not nice result for grayscales >=4 , would be grateful if you could help me find the problem, also please pardon me if I broke any rule, its my first post here.
Thank you in advance for your help and kindness.
I am writing my own midpoint displacement algorithm for learning purposes and I decided to implement it in my own way to see if I was 1) able to understand the algorithm and 2) see if i could modify it to my liking.
here is the code to generate the fractal:
public void Generate(Double rg, int size)
{
Random rand = new Random();
int min = -127;
int max = 128;
// Starting points of the rectangle
MDP_Point s1 = new MDP_Point(0, 0, rand.Next(min, max));
MDP_Point s2 = new MDP_Point(size, 0, rand.Next(min, max));
MDP_Point s3 = new MDP_Point(size, size, rand.Next(min, max));
MDP_Point s4 = new MDP_Point(0, size, rand.Next(min, max));
// Lists containing the rectangles
List<MDP_Rect> newRect = new List<MDP_Rect>(); // Newly created rectangles
List<MDP_Rect> oldRect = new List<MDP_Rect>(); // Rectangles being divided
// Starting rectangle is added to the list
oldRect.Add(new MDP_Rect(s1, s2, s3, s4));
// Distance between 2 points in a rectangle
int h = size;
while (h > 1)
{
foreach (MDP_Rect r in oldRect)
{
// Middle points of rectangle segments
MDP_Point m1 = new MDP_Point();
MDP_Point m2 = new MDP_Point();
MDP_Point m3 = new MDP_Point();
MDP_Point m4 = new MDP_Point();
// Middle point of rectangle
MDP_Point mm = new MDP_Point();
m1.x = (r.C1.x + r.C2.x) / 2;
m1.y = (r.C1.y + r.C2.y) / 2;
m1.z = ((r.C1.z + r.C2.z) / 2) +(rand.Next(min, max) * rg);
m2.x = (r.C2.x + r.C3.x) / 2;
m2.y = (r.C2.y + r.C3.y) / 2;
m2.z = ((r.C2.z + r.C3.z) / 2) +(rand.Next(min, max) * rg);
m3.x = (r.C3.x + r.C4.x) / 2;
m3.y = (r.C3.y + r.C4.y) / 2;
m3.z = ((r.C3.z + r.C4.z) / 2) +(rand.Next(min, max) * rg);
m4.x = (r.C1.x + r.C4.x) / 2;
m4.y = (r.C1.y + r.C4.y) / 2;
m4.z = ((r.C1.z + r.C4.z) / 2) + (rand.Next(min, max) * rg);
mm.x = (r.C1.x + r.C2.x + r.C3.x + r.C4.x) / 4;
mm.y = (r.C1.y + r.C2.y + r.C3.y + r.C4.y) / 4;
mm.z = ((r.C1.z + r.C2.z + r.C3.z + r.C4.z) / 4) + (rand.Next(min, max) * rg);
newRect.Add(new MDP_Rect(r.C1, m1, mm, m4));
newRect.Add(new MDP_Rect(m1, r.C2, m2, mm));
newRect.Add(new MDP_Rect(mm, m2, r.C3, m3));
newRect.Add(new MDP_Rect(m4, mm, m3, r.C4));
}
oldRect.Clear();
oldRect = new List<MDP_Rect>(newRect);
newRect.Clear();
h /= 2;
}
List<MDP_Rect> sorted = new List<MDP_Rect>();
sorted = oldRect.OrderBy(y => y.C1.y).ThenBy(x => x.C1.x).ToList();
List<MDP_Point> mapArray = new List<MDP_Point>();
mapArray.AddRange(CreateArray(sorted));
CreateImage(size, mapArray, rg);
}
MDP_Point only contains x, y and z values
MDP_Rectangle contains 4 points, creating a rectangle
The CreateArray() method only takes the ordered rectangle list and outputs and list of points in the correct order to create an image.
CreateArray():
private List<MDP_Point> CreateArray(List<MDP_Rect> lRect)
{
List<MDP_Point> p = new List<MDP_Point>();
int size = (int)Math.Sqrt(lRect.Count);
int i = 0;
foreach (MDP_Rect r in lRect)
{
p.Add(new MDP_Point((int)r.C1.x, (int)r.C1.y, (int)r.C1.z));
if (i > 0 && i % size == size - 1)
{
p.Add(new MDP_Point((int)r.C2.x, (int)r.C2.y, (int)r.C2.z));
}
i++;
}
for (int a = 0; a < size; a++)
{
p.Add(new MDP_Point((int)lRect[(size * size - size) + a].C4.x,
(int)lRect[(size * size - size) + a].C4.y,
(int)lRect[(size * size - size) + a].C4.z));
if (a > 0 && a % size == size - 1)
{
p.Add(new MDP_Point((int)lRect[(size * size - size) + a].C3.x,
(int)lRect[(size * size - size) + a].C3.y,
(int)lRect[(size * size - size) + a].C3.z));
}
}
return p;
}
This is the method to create the image:
private void CreateImage(int size, List<MDP_Point> arr, double roughness)
{
Bitmap map = new Bitmap(size, size);
int ver = 0;
for (int i = 0; i < map.Height; i++)
{
for (int n = 0; n < map.Width; n++ )
{
int h = (int)arr[ver].z + 127;
if (h < 0)
{
h = 0;
}
else if (h > 255)
{
h = 255 ;
}
Color c = Color.FromArgb(h, h, h);
//map.SetPixel(n, i, c);
map.SetPixel(i, n, c);
ver++;
}
}
Bitmap m = new Bitmap(map);
bool saved = true;
int num = 0;
while (saved)
{
if (File.Exists("map_S" + size + "_R" + roughness + "_" + num + ".png"))
{
num++;
}
else
{
m.Save("map_S" + size + "_R" + roughness + "_" + num + ".png", System.Drawing.Imaging.ImageFormat.Png);
saved = false;
}
}
map.Dispose();
m.Dispose();
}
The fact that any value below 0 is set to 0 and any value above 255 is set to 255 is probably a big issue.... not sure what to do about it.
Here's an image generated by the code:
Size: 1024
Roughness: 0.5
The most obvious issues are the diagonal "ridge lines" and the tiled look there is.
At this point, i'm not sure what to do to fix this to make it look more natural.
Any ideas?
Here, I think part of the problem is your hacking of the h variable with 255 and 0. I tried the code using:
int h = (int) arr[ver].z;
if (h < 0)
{
h = Math.Abs(h);
}
while(h > 255)
{
h -= 255;
}
On my PC the result was:
and when I used:
int h = (int) arr[ver].z + 127;
Note that I just had to create a testing MDP_Point class and MDP_Rect to test this...
To avoid these artifacts, you should use the two-stage method proposed by Peitgen et al. in "The Science of Fractal Images". They also suggest adding additional random displacements to all vertices after each subdivision step. I found a scanned excerpt here (page 45):
http://cs455.cs.byu.edu/lectureslides/FractalsPart2.pdf