0

As stated in problem 37 at Project Euler:

The number 3797 has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, and remain prime at each stage: 3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3.

I already solved this problem (answer ends with 7 :-), but a doubt remains: how efficiently left/right truncate a number, WITHOUT using strings? I built following code, but it seems ugly:

public static void Main()
{
    Console.WriteLine( // 3797, 379, 37, 3, 797, 97, 7
        String.Join(", ", 3797L.Truncate().ToArray()));
    Console.ReadLine();
}

static IEnumerable<long> Truncate(this long number)
{
    yield return number;

    long aux = number;
    while ((aux /= 10) > 0) // right to left
        yield return aux;

    // god forgive me, but it works
    while ((number = (number.Reverse() / 10).Reverse()) > 0) // left to right
    {
        yield return number;
    }
}

public static long Reverse(this long number)
{
    long reverse = number % 10;
    number = number / 10;
    while (number != 0)
    {
        reverse = (number % 10) + (10 * reverse);
        number = number / 10;
    }
    return reverse;
}

EDIT: I ended with this code:

static IEnumerable<long> Truncate(this long number)
{
    yield return number;

    int i = 10;
    while (number / i > 0)
    {
        yield return number / i;
        yield return number % i;
        i *= 10;
    }
}
Rubens Farias
  • 57,174
  • 8
  • 131
  • 162

3 Answers3

11

To truncate the rightmost digit, divide by 10 (your code already does that).

To truncate one digit on the left of a n-digit number, take the modulo of the number by 10^(n-1).

Example: 3797 % 1000 -> 797

EDIT: to clarify how I suggest to get the value for the modulo:

w <- n
d <- 1
while (w <> 0)
  test primality of w
  w <- w / 10
  d <- d * 10
end
w <- n
while (d <> 10)
  d <- d / 10
  w <- w % d
  test primality of w
end
Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • how to determine `n` without strings? – Rubens Farias Nov 25 '09 at 20:57
  • 2
    That's one plus the integral part of the base-10 logarithm of your number. If your language doesn't have log10 but only e-base logarithm, you can convert one into the other by dividing by the e-base logarithm of 10. – Pascal Cuoq Nov 25 '09 at 21:02
  • Note that computing a logarithm to determine the number of digits is a little overkill. You could get the number of digits by counting them with successive divisions by 10 and it may be more economical. Especially, you can count the digits at the same time you are removing digits from right to left in the first pass. – Pascal Cuoq Nov 25 '09 at 21:07
  • @Pascal, this answer made me cry, ty =) – Rubens Farias Nov 25 '09 at 21:22
2

Could you not divide by tens?

3797/10 = 379

379/10= 37

37/10=3

No strings needed.

To go the other way use %

JonH
  • 32,732
  • 12
  • 87
  • 145
1
var numbers = GetNumbers(3797);  

public static IEnumerable<int> GetNumbers(int val)
        {
            int ba = 1;
            int result = 1;

            while(result > 0)
            {

                ba *= 10;
                result = val / ba;
                if(result > 0)
                    yield return result;
            }

        }

will produce

379 37 3

Stan R.
  • 15,757
  • 4
  • 50
  • 58