CS50 Filter grayscale check50 - cs50

The grayscale code seems to run fine with programs having whole number as average. But gives error with complex averages, where the result is different from expected code by just 1.
// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
double avgcolor;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
avgcolor = (image[i][j].rgbtRed + image[i][j].rgbtBlue + image[i][j].rgbtGreen) / 3;
image[i][j].rgbtRed = image[i][j].rgbtBlue = image[i][j].rgbtGreen = round(avgcolor);
}
}
return;
}
Error Message
:( grayscale correctly filters single pixel without whole number average
Cause
expected "28 28 28\n", not "27 27 27\n"
Log
testing with pixel (27, 28, 28)
running ./testing 0 1...
checking for output "28 28 28\n"...
Expected Output:
28 28 28
Actual Output:
27 27 27
I get such errors in two other cases. It could be a minor issue with the round function. Ive gone through the code several times but still cant find the cause of error.

You are dividing two integers, so C will compute your average, which may not be a whole number, and then drop what comes after the decimal point. Because image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtRed will always be an integer, dividing this integer value by another integer, 3, will return yet another integer, regardless of any decimal point. In other words, if image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtRed/3 = 27.66 then avgcolor will equal 27. A solution to this would be to divide the color values by 3.0, a float, instead. An integer divided by a float can return a float, but not an integer divided by an integer.
Try this code, where you do an integer by float division with 3.0:
// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
double avgcolor;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
avgcolor = (image[i][j].rgbtRed + image[i][j].rgbtBlue + image[i][j].rgbtGreen) / 3.0;
image[i][j].rgbtRed = image[i][j].rgbtBlue = image[i][j].rgbtGreen = round(avgcolor);
}
}
return;
}

Related

CS50 Filter Blur

I don't know what I do wrong. Its work on images but when output calculate answer is wrong.
ERROR output calculate
:( blur correctly filters middle pixel
expected "127 140 149\n", not "145 160 169\n"
:( blur correctly filters pixel on edge
expected "80 95 105\n", not "90 106 116\n"
:) blur correctly filters pixel in corner
:( blur correctly filters 3x3 image
expected "70 85 95\n80 9...", not "70 85 95\n90 1..."
:( blur correctly filters 4x4 image
expected "70 85 95\n80 9...", not "70 85 95\n90 1..."
this is my code.
void blur(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
double red = 0,green = 0,blue = 0;
int count = 0;
for (int m = 0; m < 3; m++)
{
int h = i+m-1;
for (int n = 0; n < 3; n++)
{
int w = j+n-1;
if(h > -1 && w > -1 && h < height && w < width)
{
red += image[h][w].rgbtRed;
green += image[h][w].rgbtGreen;
blue += image[h][w].rgbtBlue;
count++;
}
}
}
red = 1.00*red/count;
green = 1.00*green/count;
blue = 1.00*blue/count;
image[i][j].rgbtRed = round(red);
image[i][j].rgbtGreen = round(green);
image[i][j].rgbtBlue = round(blue);
}
}
return;
}
May someone explain to me? I dont know why.

Why does my cs50 sepia filter not compute the right pixel values?

for some reason the math portion of my sepia code does not seem to work. I get errors when I run check50, and it shows all the pixel values as being too high. I triple check the values for the filter but all seems good.
void sepia(int height, int width, RGBTRIPLE image[height][width])
{
float org_red = 0;
float org_green = 0;
float org_blue = 0;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
org_red = image[i][j].rgbtRed;
org_green = image[i][j].rgbtBlue;
org_blue = image[i][j].rgbtGreen;
long sepiaRed = (.393 * org_red + .769 * org_green + .189 * org_blue);
long sepiaGreen = (.349 * org_red) + .686 * org_green + .168 * org_blue;
long sepiaBlue = (.272 * org_red + .534 * org_green + .131 * org_blue);
if (sepiaRed > 255)
{
sepiaRed = 255;
}
if (sepiaGreen > 255)
{
sepiaGreen = 255;
}
if (sepiaBlue > 255)
{
sepiaBlue = 255;
}
image[i][j].rgbtRed = round(sepiaRed);
image[i][j].rgbtGreen = round(sepiaGreen);
image[i][j].rgbtBlue = round(sepiaBlue);
}
}
return;
}
The error i get says
:( sepia correctly filters single pixel
expected "56 50 39\n", not "84 75 58\n"
:( sepia correctly filters simple 3x3 image
expected "100 89 69\n100...", not "100 88 69\n100..."
:( sepia correctly filters more complex 3x3 image
expected "25 22 17\n66 5...", not "30 27 21\n71 6..."
:( sepia correctly filters 4x4 image
expected "25 22 17\n66 5...", not "30 27 21\n71 6..."

Confused about a string hash function

As I was looking through some string hash fucntions, I came across this one (code below). The function processes the string four bytes at a time, and interprets each of the four-byte chunks as a single long integer value. The integer values for the four-byte chunks are added together. In the end, the resulting sum is converted to the range 0 to M-1 using the modulus operator.
The following is the function code :
// Use folding on a string, summed 4 bytes at a time
long sfold(String s, int M) {
int intLength = s.length() / 4;
long sum = 0;
for (int j = 0; j < intLength; j++) {
char c[] = s.substring(j * 4, (j * 4) + 4).toCharArray();
long mult = 1;
for (int k = 0; k < c.length; k++) {
sum += c[k] * mult;
mult *= 256;
}
}
char c[] = s.substring(intLength * 4).toCharArray();
long mult = 1;
for (int k = 0; k < c.length; k++) {
sum += c[k] * mult;
mult *= 256;
}
return(Math.abs(sum) % M);
}
The confusion for me is this chunk of code, especially the first line.
char c[] = s.substring(intLength * 4).toCharArray();
long mult = 1;
for (int k = 0; k < c.length; k++) {
sum += c[k] * mult;
mult *= 256;
To my knowledge, the substring function used in this line takes as argument : begin index inclusive, The substring will start from the specified beginIndex and it will extend to the end of the string.
For the sake of example, let's assume we want to hash the following string : aaaabbbb. In this case intLength is going to be 2 (second line of function code). Replacing the value of intlength in s.substring(intLength * 4).toCharArray() will give us s.substring(8).toCharArray() which means string index is out of bounds given the string to be hashed has 8 characters.
I don't quite understand what's going on !
This hash function is awful, but to answer your question:
There is no IndexOutOfBoundsException, because "aaaabbbb".substring(8) is ""
The purpose of that last loop is to deal with leftovers when the string length isn't a multiple of 4. When s is "aaaabbbbcc", for example, then intLength == 2, and s.substring(8) is "cc".

Getting timeout error for min_sub_array_sum?

I am getting this kind of weird error, I wrote a function to find the minimum sub array sum. But this doesn't work when the values of array start from 1 to size for value 1 2 3 4. I get timeout, but same code for 1 2 3 4 5 gives the correct answer. If I put a statement print statement above min_sub_array it gives the right answer for all values. It also works fine when the values start from 0 to size - 1
int min_sub_array_sum(int d[], int size)
{
for(int i = 1; i <= size; i++)
d[i] = -d[i];
int max_end_i = d[1], max_so_far = d[1];
for(int i = 2; i <= size; i++)
{
max_end_i += d[i];
if(max_so_far < max_end_i)
max_so_far = max_end_i;
if(max_end_i < 0)
max_end_i = 0;
}
return (-max_so_far);
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
int d[n];
for(int i = 1; i <= n; i++)
cin>>d[i];
cout<<min_sub_array_sum(d, n)<<'\n';
}
}
I should get the value of 1 for 1 2 3 4. But I am not getting.
You are accessing the nth index of array d[n] which does not exist.

Errors with repeated FFTW calls

I'm having a strange issue that I can't resolve. I made this as a simple example that demonstrates the problem. I have a sine wave defined between [0, 2*pi]. I take the Fourier transform using FFTW. Then I have a for loop where I repeatedly take the inverse Fourier transform. In each iteration, I take the average of my solution and print the results. I expect that the average stays the same with each iteration because there is no change to solution, y. However, when I pick N = 256 and other even values of N, I note that the average grows as if there are numerical errors. However, if I choose, say, N = 255 or N = 257, this is not the case and I get what is expect (avg = 0.0 for each iteration).
Code:
#include <stdio.h>
#include <stdlib.h>
#include <fftw3.h>
#include <math.h>
int main(void)
{
int N = 256;
double dx = 2.0 * M_PI / (double)N, dt = 1.0e-3;
double *x, *y;
x = (double *) malloc (sizeof (double) * N);
y = (double *) malloc (sizeof (double) * N);
// initial conditions
for (int i = 0; i < N; i++) {
x[i] = (double)i * dx;
y[i] = sin(x[i]);
}
fftw_complex yhat[N/2 + 1];
fftw_plan fftwplan, fftwplan2;
// forward plan
fftwplan = fftw_plan_dft_r2c_1d(N, y, yhat, FFTW_ESTIMATE);
fftw_execute(fftwplan);
// set N/2th mode to zero if N is even
if (N % 2 < 1.0e-13) {
yhat[N/2][0] = 0.0;
yhat[N/2][1] = 0.0;
}
// backward plan
fftwplan2 = fftw_plan_dft_c2r_1d(N, yhat, y, FFTW_ESTIMATE);
for (int i = 0; i < 50; i++) {
// yhat to y
fftw_execute(fftwplan2);
// rescale
for (int j = 0; j < N; j++) {
y[j] = y[j] / (double)N;
}
double avg = 0.0;
for (int j = 0; j < N; j++) {
avg += y[j];
}
printf("%.15f\n", avg/N);
}
fftw_destroy_plan(fftwplan);
fftw_destroy_plan(fftwplan2);
void fftw_cleanup(void);
free(x);
free(y);
return 0;
}
Output for N = 256:
0.000000000000000
0.000000000000000
0.000000000000000
-0.000000000000000
0.000000000000000
0.000000000000022
-0.000000000000007
-0.000000000000039
0.000000000000161
-0.000000000000314
0.000000000000369
0.000000000004775
-0.000000000007390
-0.000000000079126
-0.000000000009457
-0.000000000462023
0.000000000900855
-0.000000000196451
0.000000000931323
-0.000000009895302
0.000000039348379
0.000000133179128
0.000000260770321
-0.000003233551979
0.000008285045624
-0.000016331672668
0.000067450106144
-0.000166893005371
0.001059055328369
-0.002521514892578
0.005493164062500
-0.029907226562500
0.093383789062500
-0.339111328125000
1.208251953125000
-3.937500000000000
13.654296875000000
-43.812500000000000
161.109375000000000
-479.250000000000000
1785.500000000000000
-5369.000000000000000
19376.000000000000000
-66372.000000000000000
221104.000000000000000
-753792.000000000000000
2387712.000000000000000
-8603776.000000000000000
29706240.000000000000000
-96833536.000000000000000
Any ideas?
libfftw has the odious habit of modifying its inputs. Back up yhat if you want to do repeated inverse transforms.
OTOH, it's perverse, but why are you repeating the same operation if you don't expect it give different results? (Despite this being the case)
As indicated in comments: "if you want to keep the input data unchanged, use the FFTW_PRESERVE_INPUT flag. Per http://www.fftw.org/doc/Planner-Flags.html"
For example:
// backward plan
fftwplan2 = fftw_plan_dft_c2r_1d(N, yhat, y, FFTW_ESTIMATE | FFTW_PRESERVE_INPUT);

Resources