12
\$\begingroup\$

Find the original challenge here

Challenge

Given an integer, Z in the range -2^31 < Z < 2^31, output the number of digits in that number (in base 10).

Rules

You must not use any string functions (in the case of overloading, you must not pass a string into functions which act as both string and integer functions). You are not allowed to store the number as a string.

All mathematical functions are allowed.

You may take input in any base, but the output must be the length of the number in base 10.

Do not count the minus sign for negative numbers. Number will never be a decimal.

Zero is effectively a leading zero, so it can have zero or one digit.

Examples

Input > Output

-45 > 2
1254 > 4
107638538 > 9
-20000 > 5
0 > 0 or 1
-18 > 2

Winning

Shortest code in bytes wins.

\$\endgroup\$
5
  • \$\begingroup\$ I assume no array functions either? \$\endgroup\$ – Cyoce May 19 '17 at 16:45
  • \$\begingroup\$ @Cyoce Yes, no array functions \$\endgroup\$ – Beta Decay May 19 '17 at 17:04
  • 1
    \$\begingroup\$ So if a language only accepts input as a string, it's invalid for this challenge, right? \$\endgroup\$ – Engineer Toast May 19 '17 at 19:24
  • \$\begingroup\$ @EngineerToast Yes, very much so \$\endgroup\$ – Beta Decay May 19 '17 at 19:33
  • 1
    \$\begingroup\$ I'm removing the restricted source tag because while this is a restriction it is not a real source restriction in that it is not computer tractable. \$\endgroup\$ – Wheat Wizard May 19 '17 at 21:50

41 Answers 41

1
2
0
\$\begingroup\$

Pari/GP, 13 bytes

n->#digits(n)

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Ruby, 27 bytes

f=->x{x==0?0:1+f[x.abs/10]}

As a test:

tests = [[-45 , 2],
         [1254 , 4],
         [107638538 , 9],
         [-20000 , 5],
         [0 , 0 ],
         [-18 , 2]]

tests.each do |i, o|
  p f.call(i) == o
end

It outputs:

true
true
true
true
true
true
\$\endgroup\$
0
\$\begingroup\$

@yBASIC, 53 bytes.

_#=@_>.@_
_%=_%/(_#*_#+!.)_=_+!.GOTO(@_)+"_"*!_%@__?_

Input should be stored in variable _%

\$\endgroup\$
0
\$\begingroup\$

Rust, 41 bytes

fn f(n:i32)->u8{n!=0&&return f(n/10)+1;0}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to PPCG. \$\endgroup\$ – Muhammad Salman Apr 22 '18 at 8:25
0
\$\begingroup\$

Pyth, 10 bytes

.xhs.l.aQT

Test suite

Explanation:
.xhs.l.aQT  # Code
.xhs.l.aQTQ # With implicit variables
            # Print (implicit):
    .l   T  #   the log base 10 of:
      .aQ   #    the absolute value of the input
   s        #   floored
  h         #   plus 1
.x        Q #  unless it throws an error, in which case the input
Python 3 translation:
import math
Q=eval(input())
try:
    print(int(math.log(abs(Q),10))+1)
except:
    print(Q)
\$\endgroup\$
0
\$\begingroup\$

Gol><>, 12 bytes

SA:z+aSLS(PB

Try it online!

Example full program & How it works

1AGIE;GN
SA:z+aSLS(PB

1AGIE;GN
1AG       Register row 1 as function G
   IE;    Take input as int, halt if EOF
      GN  Call G and print the result as int

SA:z+aSLS(PB
SA            Absolute value
  :z+         Add 1 if zero
     aSL      Take log 10
        S(    Floor
          PB  Increment and return

Many math functions are prefixed with S, which made the code longer.

Adding 0.9 unconditionally (9a,+) and using ceiling (S)) is also possible with same byte count. Zero input yields 0 in this case.

\$\endgroup\$
0
\$\begingroup\$

ARM Thumb-2 (no div instruction, no libgcc), 30 bytes

Raw machine code:

2800 d00b bfb8 4240 2201 2100 3101 380a
dafc 3201 0008 280a daf7 0010 4770     

Uncommented assembly:

        .syntax unified
        .globl count_digits
        .thumb
        .thumb_func
count_digits:
        cmp     r0, #0
        beq     .Lret
        it      lt
        neglt   r0, r0
        movs    r2, #1
.Lcountloop:
        movs    r1, #0
.Ldivloop:
        adds    r1, #1
        subs    r0, #10
        bge     .Ldivloop
.Ldivloop_end:
        adds    r2, #1
        movs    r0, r1
        cmp     r0, #10
        bge     .Lcountloop
.Lcountloop_end:
        movs    r0, r2
.Lret:
        bx      lr

Returns 0 if 0.

Explanation

C function signature:

int32_t count_digits(int32_t val);

First, we compare val to zero.

If it is zero, we return zero. If it is less than zero, we negate it.

count_digits:
        cmp     r0, #0
        beq     .Lret
        it      lt
        neglt   r0, r0

Set up our digit counter for the outer loop.

        movs    r2, #1

Now, a naïve subtraction based division loop

        movs    r1, #0
.Ldivloop:
        adds    r1, #1
        subs    r0, #10
        bge     .Ldivloop

Increment the digits counter, then loop to the outer loop if we are still more than 10.

.Ldivloop_end:
        adds    r2, #1
        movs    r0, r1
        cmp     r0, #10
        bge     .Lcountloop

Move the result into the return register and return.

.Lcountloop_end:
        movs    r0, r2
.Lret:
        bx      lr
\$\endgroup\$
0
\$\begingroup\$

Perl 5 -Minteger -p, 26 24 bytes

1while++$\*abs($_/=10)}{

Try it online!

\$\endgroup\$
0
\$\begingroup\$

AWK, 33 bytes

$1=int(log(($1?$1^2:1)^.5)/2.3)+1

Try it online!

Basically, this will print the integer part of the log base 10 of the input, plus one. 2.3 is a working approximation of natural log of 10. To deal with negative numbers, it takes the square root of the power of two. If input is zero, returns 1 instead, so the pattern is different from 0, which would return false and would not be printed. Too many necessary workarounds.

\$\endgroup\$
0
\$\begingroup\$

R, 38 bytes

f=function(x)`if`(x^2<100,1,1+f(x/10))

Try it online!

Unusually for R, a recursive function seems to be shorter here than the previous answer using built-in functions (although this is mostly gained simply because we can skip abs(x) by using x^2<100 as a condition instead)...

\$\endgroup\$
0
\$\begingroup\$

Julia, 7 bytes

ndigits

Try it online!

\$\endgroup\$
1
2

Not the answer you're looking for? Browse other questions tagged or ask your own question.