Mathematically navigating a large 2D Numeric grid in C# - c#

I am trying to find certain coordinates of interest within a very large virtual grid. This grid does not actually exist in memory since the dimensions are huge. For the sake of this question, let's assume those dimensions to be (Width x Height) = (Int32.MaxValue x Int32.MaxValue).
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
Known data about grid:
Dimensions of the grid = (Int32.MaxValue x Int32.MaxValue).
Value at any given (x, y) coordinate = Product of X and Y = (x * y).
Given the above large set of finite numbers, I need to calculate a set of coordinates whose value (x * y) is a power of e. Let's say e is 2 in this case.
Since looping through the grid is not an option, I thought about looping through:
int n = 0;
long r = 0;
List<long> powers = new List<long>();
while (r < (Int32.MaxValue * Int32.MaxValue))
{
r = Math.Pow(e, n++);
powers.Add(r);
}
This gives us a unique set of powers. I now need to find out at what coordinates each power exists. Let's take 2^3=8. As shown in the grid above, 8 exists in 4 coordinates: (8,1), (4,2), (2,4) & (1, 8).
Clearly the problem here is finding multiple factors of the number 8 but this would become impractical for larger numbers. Is there another way to achieve this and am I missing something?
Using sets won't work since the factors don't exist in memory.
Is there a creative way to factor knowing that the number in question will always be a power of e?

The best method is to factor e into it prime components. Lets say they are as follows: {a^m, b^p, c^q}. Then you build set for each power of e, for example if m=2, p=1, q=3,
e^1 = {a, a, b, c, c, c}
e^2 = (a, a, a, a, b, b, c, c, c, c, c, c}
etc. up to e^K > Int32.MaxValue * Int32.MaxValue
then for each set you need to iterate over each unique subset of these sets to form one coordinate. The other coordinate is what remains. You will need one nested loop for each of the unique primes in e. For example:
Lets say for e^2
M=m*m;
P=p*p;
Q=q*q;
c1 = 1 ;
for (i=0 ; i<=M ; i++)
{
t1 = c1 ;
for (j=0 ; j<=P ; j++)
{
t2 = c1 ;
for (k=0 ; k<=Q ; k++)
{
// c1 holds first coordinate
c2 = e*e/c1 ;
// store c1, c2
c1 *= c ;
}
c1 = t2*b ;
}
c1 = t1*a ;
}
There should be (M+1)(P+1)(Q+1) unique coordinates.

Another solution, not as sophisticated as the idea from Commodore63, but therefore maybe a little bit simpler (no need to do a prime factorization and calculating all proper subsets):
const int MaxX = 50;
const int MaxY = 50;
const int b = 6;
var maxExponent = (int)Math.Log((long)MaxX * MaxY, b);
var result = new List<Tuple<int, int>>[maxExponent + 1];
for (var i = 0; i < result.Length; ++i)
result[i] = new List<Tuple<int, int>>();
// Add the trivial case
result[0].Add(Tuple.Create(1, 1));
// Add all (x,y) with x*y = b
for (var factor = 1; factor <= (int)Math.Sqrt(b); ++factor)
if (b % factor == 0)
result[1].Add(Tuple.Create(factor, b / factor));
// Now handle the rest, meaning x > b, y <= x, x != 1, y != 1
for (var x = b; x <= MaxX; ++x) {
if (x % b != 0)
continue;
// Get the max exponent for b in x and the remaining factor
int exp = 1;
int lastFactor = x / b;
while (lastFactor >= b && lastFactor % b == 0) {
++exp;
lastFactor = lastFactor / b;
}
if (lastFactor > 1) {
// Find 1 < y < b with x*y yielding a power of b
for (var y = 2; y < b; ++y)
if (lastFactor * y == b)
result[exp + 1].Add(Tuple.Create(x, y));
} else {
// lastFactor == 1 meaning that x is a power of b
// that means that y has to be a power of b (with y <= x)
for (var k = 1; k <= exp; ++k)
result[exp + k].Add(Tuple.Create(x, (int)Math.Pow(b, k)));
}
}
// Output the result
for (var i = 0; i < result.Length; ++i) {
Console.WriteLine("Exponent {0} - Power {1}:", i, Math.Pow(b, i));
foreach (var pair in result[i]) {
Console.WriteLine(" {0}", pair);
//if (pair.Item1 != pair.Item2)
// Console.WriteLine(" ({0}, {1})", pair.Item2, pair.Item1);
}
}

Related

Find the largest Pair in an integer

I'm playing around with numbers, and I'm looking to write a small program that will return the largest double-digit of an integer that's passed in for example:
I pass in 2215487
it should return 87
I pass in 98765499
It should return 99
I've tried looking at Math.Max, but I don't believe that's what I'm looking for unless I have overlooked it
You can divide by 10 each time and then compare the remainder of dividing the remaining number by 100. For example:
int v = 98765499;
int m = 0;
v = Math.Abs(v); // negate negative numbers so that we can process these too
while (v >= 10) // if you want to accept single digit initial values for V change this to v > 0
{
m = Math.Max(m, v % 100);
v /= 10;
}
Console.WriteLine(m);
We use v >= 10 because we don't want to consider single-digit numbers (e.g. an initial value of v = 5).
v % 100 uses the remainder operator to give us the value left over when we divide by 100.
v /= 10 divides v by 10 and stores the result in v.
I've used Math.Abs( ) to make this work with negative numbers too, though you can take this line out if you only care about positive numbers.
At the end, m will either hold 0 (for single digit numbers or zero) or the highest two-digit value.
Example execution flow:
Initial V
V % 100
New V
98765499
99
9876549
9876549
49
987654
987654
54
98765
98765
65
9876
9876
76
987
987
87
98
98
98
9
Highest v % 100 is 99.
Try it online
A very simple solution would be as follows:
var thenumber = 987654990;
var s = thenumber.ToString();
var max = 0;
for (var i = 0; i < s.Length-1; i++) {
int d1 = (int)(s[i] - '0');
int d2 = (int)(s[i+1] - '0');
max = Math.Max(max, 10*d1+ d2);
}
Console.WriteLine(max);
Ie, just iterate over the number and calculate the "pair" at the current position (consisting of the current digit d1 and the next one d2) if the pair is greater than the current max, make it the new max ...

Binding Variable Nested List to GridView

I am trying to make a multiplication table appear on a page based on input from the user. This is my code:
<asp:GridView runat="server" ID="TableData"></asp:GridView>
List<List<int>> nestedList = new List<List<int>>();
protected void LoadTable(int val)
{
for (int y = 0; y <= val; y++)
{
List<int> list = new List<int>();
for (int x = 0; x <= val; x++)
list.Add(x * y);
nestedList.Add(list);
}
TableData.DataSource = nestedList;
TableData.DataBind();
}
But this displays as:
Capacity Count
16 14
16 14
16 14
16 14
16 14
16 14
16 14
16 14
16 14
16 14
16 14
16 14
16 14
16 14
What am I doing wrong?
For clarification, if the user enters 5, the output should be:
0 0 0 0 0 0
0 1 2 3 4 5
0 2 4 6 8 10
0 3 6 9 12 15
0 4 8 12 16 20
0 5 10 15 20 25
I am not worried about column or row headers at this time.
The problem is with your items Source.
a list< list < ?? > > is not a good choice (as i think).
For a Linear view you can use this approach
Code Snippet
var objList = new List<object>();
for (int i = 0; i < 5; i++)
{
var temp = new { operation = string.Format("{0} * {1}", i, i + 1), result = i * (i + 1) };
objList.Add(temp);
}
GridView does not support 2d list binding, consider using another methode.
For exemple, use a simple List , each string will represent a row, you can fill up each string by using a loop that goes like :
(first loop)
{
string s;
for(int x = 0; x < val; x ++)
{
s += (x * y).Tostring() + " ");
}
nestedList.Add(s);
}

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.

How do I determine if adding 2 numbers will involve regourping / carryover or subracting 2 numbers will involve borrowing?

I need to create a function that will generate 2 random numbers between x and y (e.g. x = 1, y = 20) which when added will not involve regrouping / carryover or which when subracted will not involve borrowing.
For example,
18 + 1 = good
14 + 5 = good
18-7 = good
29 - 8 = good
15 + 6 = bad
6 + 7 = bad
21 - 3 = bad
36 - 8 = bad etc.
I want to create a simple worksheet generator that will generate sample problems using the requirements above.
I guess I could always convert the number to string, get the right most digit for each of the 2 numbers, convert them back to integer, and test if one is greater than the other. Repeat for all the digit. Only thing is, that is so damn ugly (read inefficient). I am sure that there is a better way. Anyone have any suggestions? Thanks
Generate them one digit at a time. e.g
a1 = rand(9)
a2 = rand(9 - a1)
b1 = rand(9)
b2 = rand(9 - b1)
x = b1*10 + a1
y = b2*10 + a2
From the construction you know that x+y will not involve any carry, because a1+a2 <= 9 and b1 + b2 <= 9.
You can do similar for subtraction.
If you want to restrict the overall range to be [1..20] instead of [1..99], just adjust the range for the leftmost digit:
b1 = rand(1)
b2 = rand(1 - b1)
using System;
class Sample {
static void Main() {
var rnd = new Random();
var x = 1;
var y = 20;
var a = rnd.Next(x, y);
var b = rnd.Next(x, y);
var op = '+';
Console.WriteLine("{0} {2} {1} = {3}", a, b, op , isValid(a, b, op)? "good":"bad");
op = '-';
Console.WriteLine("{0} {2} {1} = {3}", a, b, op , isValid(a, b, op)? "good":"bad");
}
static bool isValid(int x, int y, char op){
int a = x % 10;
int b = y % 10;
switch (op){
case '+':
return a + b < 10;
case '-':
return x >= y && a - b >= 0;
default:
throw new Exception(String.Format("unknown operator '{0}'", op));
}
}
}
Breaking up the numbers into digits is indeed exactly what you need to do. It does not matter whether you do that by arithmetic manipulation (division and modulus by 10) or by converting the numbers into strings, but fundamentally your question is precisely about the individual digits of the numbers.
For the subtraction x − y, no borrows are required if and only if none of the digits in y are greater than the corresponding digit in x.
For the addition x + y, there will be no carries if and only if the sum of each pair of corresponding digits is less than 10.
Here's some pseudo-C# for checking these conditions:
bool CanSubtractWithoutBorrow (uint x, uint y) {
while (y > 0) {
if ((x % 10) < (y % 10)) return False;
x /= 10; y /= 10;
}
return True;
}
bool CanAddWithoutCarry (uint x, uint y) {
while (x > 0 && y > 0) {
if ((x % 10) + (y % 10) >= 10) return False;
x /= 10; y /= 10;
}
return True;
}
You need to look at each pair digit in turn, and see if adding or subtracting them involves carries.
You can get the rightmost digit by taking the value modulo 10, x%10, and you can erase the right most digit by dividing by 10.
No string conversions are necessary.

Generate multiplication table from a single for loop

Is it possible to generate a multiplication table (for example, from 1 to 9) with a single for loop?
Yes, using something like this... But why not using two nested loops?
for (int i = 0; i < 9 * 9; ++i)
{
int a = i / 9 + 1;
int b = i % 9 + 1;
Console.WriteLine("{0} * {1} = {2}", a, b, a * b);
}
To generate the multiplication table of 1-9 with a single for loop you could loop 81 time and use the division and modulo operator to get the two operands.
for (int i = 0; i < 9*9; ++i)
{
int a = i / 9 + 1;
int b = i % 9 + 1;
Console.WriteLine($"{a} * {b} = {a * b}");
//Console.WriteLine("{0} * {1} = {2}", a, b, a * b);
}
Note, there must be a better way to construct the output, but I'm not familiar with C#.
Here's a hint for one way to do it.
How can you extract all of the needed multipliers and multiplicands from a single integer from 0 to 81?
try:
Console.WriteLine(" 1 2 3 4 5 6 7 8 9");
for (int i = 1; i<10; i++)
Console.WriteLine(
string.Format("{0}: {1:#0} {2:#0} {3:#0} {4:#0} " +
"{5:#0} {6:#0} {7:#0} {8:#0} {9:#0}",
i, i, 2*i, 3*i, 4*i, 5*i, 6*i, 7*i, 8*i, 9*i));
here, the code for multiplication tables based on our criteria
suppose
Enter a value:2
Enter b value:10
then the output is like 2*1=2 to 2*10=20...
static void Main(string[] args)
{
int a, b, c, d;
Console.WriteLine("enter a value:");
a = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("enter b value:");
b = Convert.ToInt32(Console.ReadLine());
for (d = 1; d <=b; d++)
{
c = a * d;
Console.WriteLine("{0}*{1}={2}",a,d,c);
}
Console.ReadLine();
}
class Program
{
static void Main(string[] args)
{
Console.Write("Enter the value:");
int m = int.Parse(Console.ReadLine());
if (m == 0)
return;
for(int i=1;i<=10;i++)
Console.WriteLine("{0} * {1} ={2}",m,i,m*i);
Console.ReadLine();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication11
{
class Program
{
int a;
int b;
int c;
public void Accept()
{
Console.WriteLine("enter the no.:");
a = Convert.ToInt32(Console.ReadLine());
}
public void Process()
{
for (int c = 1; c <= 10; c++)
{
b = a * c;
Console.WriteLine("table: {0}", b);
}
Console.ReadLine();
}
public void Display()
{
//Console.WriteLine(a "X" + c +"="b);
}
static void Main(string[] args)
{
Program pr = new Program();
pr.Accept();
pr.Process();
Console.ReadKey();
}
}
}
It is C solution, but you may easily re-write it into whatever language you like.
#include <stdio.h>
void Mult_table(int n)
{
int i;
int a = 0;
int b = 0;
int count = 0;
for (i= 0; i< n*n; ++i)
{
a = i/n + 1;
b = i%n + 1;
printf("%4d ", a*b);
count++;
if(count %n == 0) /*new line*/
{
printf("\n");
}
}
}
Output (if n = 10, but will work with any n):
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100

Categories

Resources