2

Question: Print all the number who has unique digits only. Input : n =15 output: 1 2 3 4 5 6 7 8 9 10 12 13 14 15

Here 11 is not included because it has 1 two times, same way 123, 456 .. are also valid but 121 1344 are not valid because there is same digit more than once.

I am running loop from 1- n and checking each number. I am using Hash-map to determine the uniqueness of number.

Is there any better solution of above problem.

Pavan Tiwari
  • 3,077
  • 3
  • 31
  • 71

8 Answers8

3

i'm not sure , but something like that..

 List<int> numbers = new List<int>(){};
 numbers =numbers.Where(p=>validCheck(p)==true).ToList();

static bool validCheck(int n)
{
 return (n.ToString().Length==n.ToString().Disctinct().Count());
}
A_Sk
  • 4,532
  • 3
  • 27
  • 51
2

You could use LINQ, convert the number into a string and check if the length of the string is equal to the number of distinct charchters.

for (int i = 1; i < n; i++){
  if (i.ToString().Length == i.ToString().Distinct().Count())
    Console.Out.Write(i + " ");
} 
Bojan B
  • 2,091
  • 4
  • 18
  • 26
1

as a semi useful library function where you seed it with a start and how many you want.

public static IEnumerable<int> UniqueDigits(int start, int count)
{
    for (var i = start; i < (start + count); i++)
    {
        var s = i.ToString();
        if (s.Distinct().Count() == s.Length)
        {
            yield return i;
        }
    }
}

then

UniqueDigits(0,15).ToList().ForEach(Console.WriteLine);   

or

foreach (var digit in UniqueDigits(100,50))
{
    Console.WriteLine(digit);
}
Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156
0

This is how I eliminate the numbers that have a duplicate characters.

    Console.Write("Input:");
    int number = int.Parse(Console.ReadLine());

    List<int> numbers = new List<int>();
    List<int> acceptedNumbers = new List<int>();

    for (int i = 1; i <= number; i++)
    {
        numbers.Add(i);
    }

    foreach (var num in numbers)
    {
        bool rejected = false;
        char[] numChars = num.ToString().ToCharArray();
        foreach (var numChar in numChars)
        {
            if (numChars.Where(n => n == numChar).Count() > 1)
            {
                rejected = true;
            }
        }

        if (!rejected)
        {
            acceptedNumbers.Add(num);
        }
    }

    acceptedNumbers.ForEach(n => Console.Write($"{n} "));
    Console.Read();
Onel Sarmiento
  • 1,608
  • 3
  • 20
  • 46
0

My thoughts:

  1. Run the Loop from 0 to n
  2. For each batch of 10 ( like from 0 to 9 , 10 to 19, 230 to 239..), pick the digits apart from the last one. These digits map to the counter which tends to be skipped. Rest all are to be emitted. For eg : for batch 12x , pick 1 & 2 , now we know that we have to skip numbers at position 1 and 2 , and rest all are acceptable so no need to do any processing for them.
  3. Keep the above digits in sorted manner in an arrayList and keep a pointer at index 0. Lets call it 'ptr'. While running through that batch, check if count ( which moves from 0 to 9 ) for each batch is equal to the array[ptr]. If no, emit the number out. Else, skip it and do ptr++.
  4. When you are doing step 2, check if any digits are duplicate. If yes, skip the entire batch of 10.

There are no string operations happening, so it should bring in the efficiency

Preeti Khurana
  • 369
  • 1
  • 11
0

A string is an IEnumerable - so you can use a LINQ statement to solve your problem:

Numbers.Where(N => N.ToString().Distinct().Count() == N.ToString().Length);

The query is checking how many characters of the string of your number distinct and comares this number with the number of total characters.

Here is the whole code printing out all distinct numbers until 20:

List<int> Numbers = new List<int>();

for (int i = 1; i <= 20; i++)
{
    Numbers.Add(i);
}

IEnumerable<int> AcceptedNumbers = Numbers.Where(N => N.ToString().Distinct().Count() == N.ToString().Length);

foreach (int AcceptedNumber in AcceptedNumbers)
{
    Console.WriteLine(AcceptedNumber);
}
Fruchtzwerg
  • 10,999
  • 12
  • 40
  • 49
0

Another solution is using integer division and modulo (no number to string conversion). You can verify the uniqueness of a number with the following method (assume digits is int array having 10 elements).

public static bool IsUnique(int num) {
    int[] digits = new int[10];
    num = Math.Abs(num);
    while (num > 0) {
        int r = num % 10;
        num /= 10;

        digits[r] ++;
        if (digits[r] > 1) {
            return false;
        }
    }
    return true;
}

Working example http://ideone.com/9emEoz

putu
  • 6,218
  • 1
  • 21
  • 30
  • ... why pass in `digits`? Why not just declare it as a local variable? Also, what happens if `num` is negative? – Clockwork-Muse Sep 22 '16 at 06:14
  • `digits` is passed to prevent allocating memory every time function is called. I've update the method to deal with negative number (take the `absolute` before `while` loop) – putu Sep 22 '16 at 06:23
  • 1
    No, I mean I figured that's what you were trying to avoid, I just wasn't sure whether the "setup" costs were worth it in the general case. Now I'm curious as to whether the JIT can recognize the situation and re-use a local array anyways... – Clockwork-Muse Sep 22 '16 at 07:07
  • You're alright. It's better and cleaner with local variable. I made a simple benchmark http://ideone.com/9emEoz . It shows that method using local variable is the fastest. I'll edit the answer. – putu Sep 22 '16 at 07:46
0

There are only 9 * 9! / (10 - n)! unique-digit numbers with n digits. For larger n, you might want a next lexicographic algorithm to avoid unnecessary iterations. (For example, there are only 544,320 7-unique-digit numbers, yet your program would need to iterate through almost 10 million numbers to produce them!)

Here's my attempt at a next lexicographic procedure for a set of n-unique-digit numbers (where n > 1):

(1) From left to right, start with the digits 10, then ascend from 2.
    For example, the first 4-digit number would be 1023.

(2) Increment the right-most digit that can be incremented to the next available 
    higher digit unused by digits to its left. Ascend to the right of the
    incremented digit with the rest of the available digits, starting with lowest.

Examples: 1023 -> 1024 (4 is unused by the digits left of 3)
             ^

          9786 -> 9801 (8 is unused be the digits left of 7)
           ^

          9658 -> 9670 (7 is unused by the digits left of 5)
            ^
גלעד ברקן
  • 23,602
  • 3
  • 25
  • 61