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);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With