Generating all the increasing digit numbers - c#

I came across the following question for an interview.
For a given number of digits, generate all the numbers such that the value of a higher order digit is less than a lower order digit.
145 // 1 < 4 < 5
Is there a better (efficient) way to do this than the one I have come up with:
public static void GenerateSpecialNumbers(int noDigits)
{
int prod = 1;
for(int i=0; i < noDigits; i++)
{
prod = prod * 10;
}
int minValue = prod/10;
int maxValue = prod - 1;
for(int i = minValue; i < maxValue; i++)
{
bool isValid = true;
int num = i;
int max = int.MaxValue;
while(num > 0)
{
int digit = num % 10;
if(digit >= max)
{
isValid = false;
break;
}
max = digit;
num = num/10;
}
if(isValid)
Console.WriteLine(i);
}
}
EDIT:
Output for 3 digits:
123
124
125
126
127
128
129
134
135
136
137
138
139
145
146
147
148
149
156
157
158
159
167
168
169
178
179
189
234
235
236
237
238
239
245
246
247
248
249
256
257
258
259
267
268
269
278
279
289
345
346
347
348
349
356
357
358
359
367
368
369
378
379
389
456
457
458
459
467
468
469
478
479
489
567
568
569
578
579
589
678
679
689
789

Nice puzzle! Here's my take:
static void Main()
{
WriteNumbers(3);
}
static void WriteNumbers(int digits, int number = 0)
{
int i = (number % 10) + 1;
number *= 10;
for (; i <= 9; i++)
{
if (digits == 1)
Console.WriteLine(number + i);
else
WriteNumbers(digits - 1, number + i);
}
}

Yes, this problem has a simple recursive description that constructs all the numbers without having to test and throw any away.
For example, the valid n digit numbers include "1".append(all valid n-1 digit numbers using only digits >1)
Each digit has a lower bound of one plus the digit immediately to its left. Can you find a simple upper bound?

Since I like table-based things, I would generate the table for n = 2 first (< 100 entries, obviously) and just hold it in an initialized array.
Then f(n) = the digits in the sequence N [1, 2, 3, 4, 5, 6, 7, 8, 9] composed with f(n-1) where f(n-1)[0] > N
i.e. for n = 3:
1, f(2) where f(2)[0] > 1: 123, 124, 125, ...
2, f(2) where f(2)[0] > 2: 234, 235, 236, ...
...

for (i1 from 1 to 9)
for (i2 from 1 to i1 - 1)
for (i3 from 1 to i2 - 1)
print(i1 * 1 + i2 * 10 + i3 * 100);
No recursion needed for fixed-length numbers. Easy to code and fail-safe.
Please note that the loop upper bounds are not fixed. This is what makes this work.

Here is my solution with help from #Hand-E-Food and #Ben Voigt's comment. I feel this is easier to understand:
static void WriteNumbers(int digits, int left=0,int number=0)
{
for(int i=left+1; i<10; i++)
{
if(digits==1)
{
Console.WriteLine(number*10+i);
}
else
{
WriteNumbers(digits - 1, i, number*10 + i);
}
}
}

Here's a hint: if there are N possible digit values, and you want to pick M of them, the number of possibilities is "N choose M".

Here's a solution (albeit kind of hack-ish) that will work for any number of digits:
private static void printSpecialNumbers(int noOfDigits){
int max = (int) Math.pow(10, noOfDigits);
int min = (int) Math.pow(10, noOfDigits-1);
for(int i = min; i < max; i++){
if(isSpecialNumber(i))
System.out.println(i);
}
}
private static boolean isSpecialNumber(int i){
String intString = String.valueOf(i);
String[] digits = intString.split("");
for(int k = 1; k < digits.length-1; k++){
if(Integer.valueOf(digits[k]) >= Integer.valueOf(digits[k+1]))
return false;
}
return true;
}

Related

Why numbers converted from char to int are different than before conversion?

so, as the title says, I can't convert numbers from char to integer. Am I doing something wrong?
Console.Clear();
int hourBin1 = 0, hourBin2 = 0, minuteBin1 = 0, minuteBin2 = 0, secondBin1 = 0, secondBin2 = 0;
int iteration=0;
void conversion(int variable){
int i=0;
int[] table = new int[6];
while(variable>0){
table[i]=variable%2;
Console.WriteLine($"{i} {variable} {table[i]}");
variable/=2;
i++;
}
int result = 0;
for(int j=i-1;j>=0;j--){
result*=10;
result+=table[j];
}
if(iteration==0){
hourBin1=result;
iteration++;
}else if(iteration==1){
hourBin2=result;
iteration++;
}else if(iteration==2){
minuteBin1=result;
iteration++;
}else if(iteration==3){
minuteBin2=result;
iteration++;
}else if (iteration==4){
secondBin1=result;
iteration++;
}else if (iteration==5){
secondBin2=result;
iteration++;
}
}
Console.Write("enter date in HH:MM:SS format to convert: ");
string numberString = Console.ReadLine()!.Trim();
char[] separation = numberString.ToCharArray();
foreach (var x in separation){
Console.Write($"{x} ");
}
int hour1 = Convert.ToInt16(separation[0]);
int hour2 = Convert.ToInt16(separation[1]);
int minute1 = Convert.ToInt16(separation[3]);
int minute2 = Convert.ToInt16(separation[4]);
int second1 = Convert.ToInt16(separation[6]);
int second2 = Convert.ToInt16(separation[7]);
Console.WriteLine("converting to binary system");
conversion(hour1);
conversion(hour2);
conversion(minute1);
conversion(minute2);
conversion(second1);
conversion(second2);
Console.WriteLine($"\n{hour1} {hour2} {minute1} {minute2} {second1} {second2}");
Console.WriteLine($"hourBin1}\n{hourBin2}\n{minuteBin1}\n{minuteBin2}\n{secondBin1}\n{secondBin2}");
for example:
console outputs for "12:23:34" looks like this:
1 2 : 2 3 : 3 4 49 50 50 51 51 52
I want it to look like this :
1 2 : 2 3 : 3 4 1 2 2 3 3 4
and final output looks like this:
49 50 50 51 51 52 110001 110010 110010 110011 110011 110100
I want it to look like this :
1 2 2 3 3 4 0001 0010 0010 0011 0011 0100
PS for some reason, table cant take value smallet than 6, any ideas why?
There are basically the equivalent ASCII values, all you can do is simply subtract 48 from each value then you will get the exact value. ASCII value of char 1 is 49.
int hour1 = Convert.ToInt16(separation[0]) - 48;

Finding all possible combinations of positive and negative numbers that equal a given sum

How would you go if you want to see in how many ways you can combine the numbers from 1 to N in such a way that by using addition or subtraction you will end up with combinations that equal a given target number.
In regards to this topic Finding all possible combinations of numbers to reach a given sum, I was unable to modify it in a way that I could achieve my result, so I decided to ask instead.
Example: (Lets say that N = 8. How would I approach to solve this if I create the following array from 1 to N. Don't use each number more than once.)
arr = [1, 2, 3, 4, 5, 6, 7, 8]
sum = 0;
Result:
+1 +2 +3 +4 -5 -6 -7 +8
+1 +2 +3 -4 +5 -6 +7 -8
+1 +2 -3 +4 +5 +6 -7 -8
+1 +2 -3 -4 -5 -6 +7 +8
+1 -2 +3 -4 -5 +6 -7 +8
+1 -2 -3 +4 +5 -6 -7 +8
+1 -2 -3 +4 -5 +6 +7 -8
-1 +2 +3 -4 +5 -6 -7 +8
-1 +2 +3 -4 -5 +6 +7 -8
-1 +2 -3 +4 +5 -6 +7 -8
-1 -2 +3 +4 +5 +6 -7 -8
-1 -2 +3 -4 -5 -6 +7 +8
-1 -2 -3 +4 -5 +6 -7 +8
-1 -2 -3 -4 +5 +6 +7 -8
Total Solutions: 14
Here a recursive function that will print all the combinations that worked, and the ones that did not work.
The code (test it here, or a simpler version here):
// This code can be improved a lot, but i wrote it in the way that i believe it is easier to read and understand what it does.
using System;
namespace algorithm_simple_csharp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Working on it!");
int[] allNumbers = new int[] {1,2,3,4};
int desiredSum = 0;
// We will create two trees, one with a positive first number, and the other one with a negative one
// Positive tree
int initIndex = 0;
OperationTreeNode firstPositiveNode = new OperationTreeNode
{
parentNode = null,
currentNumber = allNumbers[initIndex],
accumulativeSum = allNumbers[initIndex],
operation = "+"
};
int totalSolutionsPositiveFirst = ApplyNumber(firstPositiveNode, allNumbers, initIndex + 1, desiredSum);
// Negative tree
OperationTreeNode firstNegativeNode = new OperationTreeNode
{
parentNode = null,
currentNumber = -allNumbers[initIndex],
accumulativeSum = -allNumbers[initIndex],
operation = "-"
};
int totalSolutionsNegativeFirst = ApplyNumber(firstNegativeNode, allNumbers, initIndex + 1, desiredSum);
// Print all solutions found with both trees
Console.WriteLine("Total soltions: " + (totalSolutionsPositiveFirst + totalSolutionsNegativeFirst));
}
// This function will take care of the next number we should apply: allNumbers[index]
// If there are still numbers to apply, It will create two nodes, one for + allNumbers[index] and one for - allNumbers[index]
static int ApplyNumber(OperationTreeNode currentNode, int[] allNumbers, int index, int desiredSum)
{
// The base case, There are no more numbers to cover.
// In that case we evaluate if the last node is equal to desiredSum or not
if(index > allNumbers.GetUpperBound(0))
{
if(currentNode.accumulativeSum == desiredSum)
{
Console.WriteLine(currentNode.BranchToString() + " = " + currentNode.accumulativeSum + " <--- THIS ONE");
return 1;
}
Console.WriteLine(currentNode.BranchToString() + " = " + currentNode.accumulativeSum);
return 0;
}
// If it is not the last node, then we create two child nodes of the current node.
// First we evaluate what happens if we apply a + to the next number...
OperationTreeNode plusNode = new OperationTreeNode
{
parentNode = currentNode,
currentNumber = allNumbers[index],
accumulativeSum = currentNode.accumulativeSum + allNumbers[index],
operation = "+"
};
int totalSolutionsWithPlus = ApplyNumber(plusNode, allNumbers, index +1, desiredSum);
// Now we evaluate what happens if we apply a - to the next number...
OperationTreeNode minusNode = new OperationTreeNode
{
parentNode = currentNode,
currentNumber = allNumbers[index],
accumulativeSum = currentNode.accumulativeSum - allNumbers[index],
operation = "-"
};
int totalSolutionsWithMinus = ApplyNumber(minusNode, allNumbers, index +1, desiredSum);
// The total number of solutions we found is the sum of the solutions of both sub-trees
return totalSolutionsWithPlus + totalSolutionsWithMinus;
}
}
public class OperationTreeNode
{
public int accumulativeSum = 0;
public OperationTreeNode parentNode = null;
public int currentNumber = 0;
public string operation;
public string BranchToString()
{
if(parentNode == null)
{
return $"{this.currentNumber} ";
}
return $"{parentNode.BranchToString()} {this.operation} {this.currentNumber} ";
}
}
}
The output in the console
Working on it!
1 + 2 + 3 + 4 = 10
1 + 2 + 3 - 4 = 2
1 + 2 - 3 + 4 = 4
1 + 2 - 3 - 4 = -4
1 - 2 + 3 + 4 = 6
1 - 2 + 3 - 4 = -2
1 - 2 - 3 + 4 = 0 <--- THIS ONE
1 - 2 - 3 - 4 = -8
-1 + 2 + 3 + 4 = 8
-1 + 2 + 3 - 4 = 0 <--- THIS ONE
-1 + 2 - 3 + 4 = 2
-1 + 2 - 3 - 4 = -6
-1 - 2 + 3 + 4 = 4
-1 - 2 + 3 - 4 = -4
-1 - 2 - 3 + 4 = -2
-1 - 2 - 3 - 4 = -10
Total soltions: 2
How it works?
It creates a tree. Each node of the tree is an object of type OperationTreeNode that represents a number and its operation. for example: +1 and -1 are two OperationTreeNode
when you reached the last number, ApplyNumber will evaluate if the node is equal to desiredSum.
ApplyNumber returns how many solutions that subtree found
As far as i know, and if i've understood the question, you need a for loop since if you have a number n, there are infinite combinations of numbers that added or subtracted equals n, so you need a number that, if reached will stop the process.
If you need multiple number (e.g. 3+10+1=14) you need more loops.
This would be my way to go:
int l = 50;//my limit
int n = 14;//my number
for(int i = 0; i < l; i++)
{
for(int j = 0; j < l; j++)
{
if ( i + j == n )
{
//Do whatever you want
Console.WriteLine("{0} = {1} + {2}", n, i, j);
}
if ( i - j == n )
{
//Do whatever you want
Console.WriteLine("{0} = {1} - {2}", n, i, j);
}
}
}//Repeat for negative numbers
Hope this will help.
Iterative, how many ways to reach a target.
using System;
class Program
{
static void Main()
{
Console.WriteLine(C(0));
int[] a = { 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144 };
Console.Write(C(0, a)); Console.Read();
}
static int C(int t) // ±1 ± 2 ± 3 ± 4 == 0
{
int c = 0, s = 0;
for (int n = 0; n < 16; n++)
{
if ((n & 1) == 0) s -= 1; else s += 1;
if ((n & 2) == 0) s -= 2; else s += 2;
if ((n & 4) == 0) s -= 3; else s += 3;
if ((n & 8) == 0) s -= 4; else s += 4;
if (s == t) c++; s = 0;
} return c;
}
static int C(int t, int[] a)
{
int c = 0, s = 0, i, j = a.Length, n, m = 1 << j;
for (n = 0; n < m; n++)
{
for (i = 0; i < j; i++)
if ((n & 1 << i) == 0) s -= a[i]; else s += a[i];
if (s == t) c++; s = 0;
} return c;
}
}

array numbers which sum is dividing on 4

I want to print numbers on label from 1-to 100
The number's sum must be dividing on 4.
Example:
print 35. because 3+5 = 8 .
8 dividing on 4.
This is code
from loop printing numbers. but how choose those numbers?
print those numbers from 1 to 100 ;
for (int i = 1; i < 100; i++)
{
//select numbers wich sum is dividing on 4
label3.Text += Convert.ToString(i) + " | ";
}
Stolen from Greg Hewgill answer's, you can use his algorithm and use remainder operator (%) like;
int sum, temp;
for (int i = 1; i < 100; i++)
{
sum = 0;
temp = i;
while (temp != 0)
{
sum += temp % 10;
temp /= 10;
}
if (sum % 4 == 0)
{
Console.WriteLine(i);
}
}
Result will be;
4
8
13
17
22
26
31
35
39
40
44
48
53
57
62
66
71
75
79
80
84
88
93
97
Here a demonstration.
You should use a nested loop for that , and use the % operator (% means the rest of division):
for (int i = 1; i < 100; i++)
{
for (int j = i; j < 100; j++)
{
//select numbers wich sum is dividing on 4
if( (i+j)%4 == 0)
{
label3.Text += Convert.ToString(i) + Convert.ToString(j) " | ";
}
}
}

Converting single dimension array to a 2D array in C# for AES data matrix

I'm trying to make a 2D array from a single dimension array to make a data state in Rijndael or AES cryptographical process. I've been trying using this code here;
public byte[,] MakeAState(byte[] block){
byte[,] State;
foreach (byte i in block)
for (int row = 0; row < 4; row++)
for (int column = 0; column < 4; column++)
State[column, row] = i;
return State;
}
and I intend to make the result to be like this
//Original Sequence
[99 111 98 97 112 97 115 115 99 111 98 97 112 97 115 115]
//Desired Sequence
[99 112 99 112]
[111 97 111 97]
[98 115 98 115]
[97 115 97 115]
The results always comes out as if the elements of Block used as if the index of the State array, causing an 'out-of boundary' error message appearing. any idea on how to manage this?
This should be what you want, and it's working with division and modulo to determine column and row(just switch "i % 4" with "i / 4" if you want to turn the matrix):
class Program
{
static void Main(string[] args)
{
byte[] original = new byte[] { 99, 111, 98, 97, 112, 97, 115, 115, 99, 111, 98, 97, 112, 97, 115, 115 };
byte[,] result = MakeAState(original);
for (int row = 0; row < 4; row++)
{
for (int column = 0; column < 4; column++)
{
Console.Write(result[row,column] + " ");
}
Console.WriteLine();
}
}
public static byte[,] MakeAState(byte[] block)
{
if (block.Length < 16)
{
return null;
}
byte[,] state = new byte[4,4];
for (int i = 0; i < 16; i++)
{
state[i % 4, i / 4] = block[i];
}
return state;
}
}
}
Output:
99 112 99 112
111 97 111 97
98 115 98 115
97 115 97 115
You likely flipped row and column on State[column, row] = i; which might be what's causing your out of bounds exception. Can't tell without more information about your variables, though.
But that's not the only issue here. Assuming you just want the array to be split into groups of four. This is your current situation if you flip row/columnand get past your exception.
//Original sequence:
[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]
//Desired sequence:
[0 4 8 12]
[1 5 9 13]
[3 6 10 14]
[4 7 11 15]
//What you are currently getting:
[15 15 15 15]
[15 15 15 15]
[15 15 15 15] //<-- Last value of original sequence, everywhere.
What's happening in your code is every position in Block is placed in every position in the new array, which means that you'll end up with an array filled with the last value of Block when the algorithm is finished.
Changing it to something like this would return the result you want.
public static byte[,] State(byte[] Block)
{
if (Block.Length % 16 != 0)
throw new Exception("Byte array length must be divisible by 16.");
var rowCount = Block.Length / 4;
var State = new byte[rowCount, 4];
for (int column = 0, block = 0; column < 4; column++)
for (int row = 0; row < rowCount; row++, block++)
State[row, column] = Block[block];
return State;
}

How to 'normalize' a grayscale image?

My math is a bit rusty. I'm trying to equalize a histogram of a 2D array which represents grayscale values in the range 0-255 (values may not be whole numbers because of how they are computed).
I found this article on Wikipedia, but I don't quite understand the formulas they present.
ni, n and L I can compute, but I'm not quite sure how to implement this cdf function. Might this function be of use?
Here's what I've got so far:
static double[,] Normalize(double[,] mat)
{
int width = mat.GetLength(0);
int height = mat.GetLength(1);
int nPixels = width*height;
double sum = 0;
double max = double.MinValue;
double min = double.MaxValue;
var grayLevels = new Dictionary<double, int>();
foreach (var g in mat)
{
sum += g;
if (g > max) max = g;
if (g < min) min = g;
if (!grayLevels.ContainsKey(g)) grayLevels[g] = 0;
++grayLevels[g];
}
double avg = sum/nPixels;
double range = max - min;
var I = new double[width,height];
// how to normalize?
return I;
}
Found something that you might find useful
http://sonabstudios.blogspot.in/2011/01/histogram-equalization-algorithm.html
Hope that helps
Calculating the cumulative distribution function involves a couple of steps.
First you get the frequency distribution of your grayscale values.
So something like:
freqDist = new int[256];
for each (var g in mat)
{
int grayscaleInt = (int)g;
freqDist[grayscaleInt]++;
}
Then to get your CDF, something like:
cdf = new int[256];
int total = 0;
for (int i = 0; i < 256; i++)
{
total += freqDist[i];
cdf[i] = total;
}
I can help you to understand your link,
first, counting value which represent image, shows in that link,
Value Count Value Count Value Count Value Count Value Count
52 1 64 2 72 1 85 2 113 1
55 3 65 3 73 2 87 1 122 1
58 2 66 2 75 1 88 1 126 1
59 3 67 1 76 1 90 1 144 1
60 1 68 5 77 1 94 1 154 1
61 4 69 3 78 1 104 2
62 1 70 4 79 2 106 1
63 2 71 2 83 1 109 1
it is means, the image is created with values above, nothing else.
second, sums the value cumulatively from 52 to 154
Value cdf Value cdf Value cdf Value cdf Value cdf
52 1 64 19 72 40 85 51 113 60
55 4 65 22 73 42 87 52 122 61
58 6 66 24 75 43 88 53 126 62
59 9 67 25 76 44 90 54 144 63
60 10 68 30 77 45 94 55 154 64
61 14 69 33 78 46 104 57
62 15 70 37 79 48 106 58
63 17 71 39 83 49 109 59
it is means,
value 52 have 1 cdf cause it is initial value,
value 55 have 4 cdf cause it has 3 count in image plus 1 cdf from 52,
value 58 have 6 cdf cause it has 2 count in image plus 4 cdf from 55,
and so on.. till..
value 154 have 64 cdf cause it has 1 count in image plus 63 cdf from 144.
then, calculating histogram equalization formula for each image values based on the function
cdf(v) is represent current cdf value from current image value,
in this case, if h(v) = 61 so cdf(v) = 14
cdfmin is represent initial cdf value, in this case, 1 cdf from value 52
happy coding.. ^^
Here's my implementation:
private static byte[,] Normalize(byte[,] mat)
{
int width = mat.GetLength(0);
int height = mat.GetLength(1);
int nPixels = width*height;
var freqDist = new int[256];
foreach (var g in mat)
{
++freqDist[g];
}
var cdf = new int[256];
int total = 0;
for (int i = 0; i < 256; ++i)
{
total += freqDist[i];
cdf[i] = total;
}
int cdfmin = 0;
for (int i = 0; i < 256; ++i)
{
if (cdf[i] > 0)
{
cdfmin = cdf[i];
break;
}
}
var I = new byte[width,height];
double div = (nPixels - cdfmin) / 255d;
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
I[x, y] = (byte)Math.Round((cdf[mat[x, y]] - cdfmin) / div);
}
}
return I;
}
I changed it from using doubles to bytes to work better with the histogram (freqDist).
In addition to what John says, you will need to use the cdf array to compute the new value for every pixel. You do this by:
Adjust John's second iteration to get the first i that has a
freqDist > 0 and call that i imin
Going pixel by pixel i,j between 0 and width and 0 and height repectively and
evaluating round((cdf[pixel[i,j]]-cdf[imin])/(width*height-cdf[imin]))*255),
that is the normalized pixel value at that location.
You can use this function I just wrote:
public static Bitmap ContrastStretch(Bitmap srcImage, double blackPointPercent = 0.02, double whitePointPercent = 0.01)
{
BitmapData srcData = srcImage.LockBits(new Rectangle(0, 0, srcImage.Width, srcImage.Height), ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
Bitmap destImage = new Bitmap(srcImage.Width, srcImage.Height);
BitmapData destData = destImage.LockBits(new Rectangle(0, 0, destImage.Width, destImage.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
int stride = srcData.Stride;
IntPtr srcScan0 = srcData.Scan0;
IntPtr destScan0 = destData.Scan0;
var freq = new int[256];
unsafe
{
byte* src = (byte*) srcScan0;
for (int y = 0; y < srcImage.Height; ++y)
{
for (int x = 0; x < srcImage.Width; ++x)
{
++freq[src[y*stride + x*4]];
}
}
int numPixels = srcImage.Width*srcImage.Height;
int minI = 0;
var blackPixels = numPixels*blackPointPercent;
int accum = 0;
while (minI < 255)
{
accum += freq[minI];
if (accum > blackPixels) break;
++minI;
}
int maxI = 255;
var whitePixels = numPixels*whitePointPercent;
accum = 0;
while (maxI > 0)
{
accum += freq[maxI];
if (accum > whitePixels) break;
--maxI;
}
double spread = 255d/(maxI - minI);
byte* dst = (byte*) destScan0;
for (int y = 0; y < srcImage.Height; ++y)
{
for (int x = 0; x < srcImage.Width; ++x)
{
int i = y*stride + x*4;
byte val = (byte) Clamp(Math.Round((src[i] - minI)*spread), 0, 255);
dst[i] = val;
dst[i + 1] = val;
dst[i + 2] = val;
dst[i + 3] = 255;
}
}
}
srcImage.UnlockBits(srcData);
destImage.UnlockBits(destData);
return destImage;
}
static double Clamp(double val, double min, double max)
{
return Math.Min(Math.Max(val, min), max);
}
The defaults mean that the darkest 2% of pixels will become black, the lightest 1% will become white, and everything in between will be stretched to fill the color space. This is the same as the default for ImageMagick.
This algorithm has the fun side effect that if you use values above 50% then it will invert the image! Set to .5, .5 to get a black & white image (2 shades) or 1, 1 to get a perfect inversion.
Assumes your image is already grayscale.

Categories

Resources