26
\$\begingroup\$

What?

Many programming languages, both practical and esoteric, have functions, methods, etc to convert a given string to a decimal number. This is how the process might work:

  • For each character in the given string.
    • Take the character's ASCII value and subtract it by 48.
    • Multiply the output value by 10. (The output at the first iteration is 0)
    • Add the subtracted ASCII value to the output.

Let us do this process for the string "109":

  1. The ASCII value of 1 is 49. Subtract it by 48, and we get 1. We multiply the output by 10, we get 0. Finally, we add 1 to 0 and get one.

  2. Next, we subtract 0's ASCII value (48) by 48, we get 0. We multiply 1 by 10, we get 10. Nothing happens when we add 0.

  3. Then we subtract 9's ASCII value (57) by 48, we get 9. We multiply 10 by 10 and get 100. We add 9 to 100 and get 109.

There, we successfully converted "109" to 109! It is just as simple!

The problem is that most languages do not like it when the converting string has non-digital characters (characters with an ASCII value not in the range 48-57 inclusive). They would most likely throw some nasty errors or exceptions at us.

How 'bout we ignore that!

Task

Given a printable string from STDIN (you can assume that \$1 ≤ \text{Input Length} ≤ 10\$), implement a program or function to badly convert it to an integer according to the above steps, and output or return it back.

Strings can contain whitespace characters (Spaces, tabs and linefeeds).

For another example string "Hi!":

  1. The ASCII value of H is 72:
    72 - 48 = 24
    0 * 10 = 0
    0 + 24 = 24

  2. The ASCII value of i is 105:
    105 - 48 = 57
    24 * 10 = 240
    240 + 57 = 297.

  3. The ASCII value of ! is 33:
    33 - 48 = -15
    297 * 10 = 2970
    2970 + -15 = 2955

This means that "Hi!" converted to an integer is 2955!

Standard I/O rules apply.

Note: if your language does not support input, feel free to tell me in your answers (you can put the "input" strings in your source code)!

More test cases

STDIN                  Output
"123456789"         ->  123456789
"0123456789"        ->  123456789
"-12345"            -> -287655
"Lorem"             ->  350191
"Ipsum"             ->  321451
"AAAAAAAA"          ->  188888887
"        "          -> -177777776
"A"                 ->  17
" "                 -> -16
"
"                   -> -38

Standard rules apply!

\$\endgroup\$
18
  • 1
    \$\begingroup\$ What do you mean when you say "You can use Unicode values instead"? Unicode and ASCII code points line up, so there's no difference between Unicode and ASCII values \$\endgroup\$ Commented Oct 11, 2020 at 14:40
  • 3
    \$\begingroup\$ Yes, but unless we have to handle inputs with characters outside of the printable ASCII range, the two are one and the same \$\endgroup\$ Commented Oct 11, 2020 at 14:55
  • 3
    \$\begingroup\$ Just to confirm: "-12345" should convert to -287655? We don't want the conversion to be too perfect, correct? :-) \$\endgroup\$
    – ErikF
    Commented Oct 11, 2020 at 17:28
  • 1
    \$\begingroup\$ Wouldn't it make more sense to switch the first two steps and replace "multiply the output" by "multiply the previous output (if available)"? No special case anymore, a better flow and no 10*1=0. \$\endgroup\$ Commented Oct 12, 2020 at 1:17
  • 1
    \$\begingroup\$ @SunnyMoon: Sorry if I wasn't clear. I was just proposing an alternative way to explain the above process, because the current explanation is a bit confusing IMHO. "Multiply the output by 10 " seems to be referring to ASCII value - 48 even though it actually refers to the previous step. Just my 2c$, feel free to ignore it. \$\endgroup\$ Commented Oct 12, 2020 at 11:19

57 Answers 57

1
2
4
\$\begingroup\$

GolfScript, 13 12 bytes

{48-}%10base

Try it online!

{   }%         # For each byte in the input
 48-           # Subtract 48
      10base   # Convert to base 10
\$\endgroup\$
4
\$\begingroup\$

Japt, 8 bytes

Takes input as an array of characters.

£48nXcÃì

Try it (Header splits string input to array)

£48nXcÃì     :Implicit input of array
£            :Map each X
 48n         :  Subtract 48 from
    Xc       :  Charcode of X
      Ã      :End map
       ì     :Convert to integer from base-10 digit array
\$\endgroup\$
3
\$\begingroup\$

Husk, 9 7 bytes

Edit: -2 bytes thanks to Razetime

dmo-48c

Try it online!

How?

d           # interpret digits as base-10 number:
 m          # map function over each element of list (each character of string)
  o         # combine 2 functions into one
      c     # convert character to Utf8 value
   -48      # subtract 48
\$\endgroup\$
2
  • \$\begingroup\$ B10 becomes d \$\endgroup\$
    – Razetime
    Commented Oct 11, 2020 at 15:31
  • \$\begingroup\$ Duh! How did I miss that? Thanks a lot! \$\endgroup\$ Commented Oct 11, 2020 at 15:33
3
\$\begingroup\$

mlochbaum/BQN, 21 bytes

10{+⟜(𝕨⊸×)´⌽𝕩}'0'-˜¨

Try it!

The online BQN REPL does not have a method of taking input( in APL), so append the string to the end of the program.

\$\endgroup\$
3
\$\begingroup\$

Charcoal, 10 bytes

I↨ES⁻℅ι⁴⁸χ

Try it online! Link is to verbose version of code. Explanation:

   S        Input string
  E         Map over characters
      ι     Current character
     ℅      Ordinal
       ⁴⁸   Literal 48
    ⁻       Subtract
         χ  Literal 10
 ↨          Base conversion
I           Cast to string
            Implicitly print
\$\endgroup\$
3
\$\begingroup\$

Keg, -hr, 15 bytes

0&?⑷86*-⑸(
⑾⑼)⑻

Try it online!

Keg is very special. Like very special.

\$\endgroup\$
3
\$\begingroup\$

Gol><>, 10 bytes

iEh$a*+`0-

Try it online!

i           Read one char from the input
 Eh         If last char read was EOF halt and output current sum as number
   $a*      Else swap new input and current sum, then multiply sum by 10
      +     Add the new char value to current sum
       `0-  Subtract 48 (value of '0') and wrap around implicitly to loop
\$\endgroup\$
3
\$\begingroup\$

Elixir, 36 bytes

&List.foldl&1,0,fn x,y->y*10+x-48end

Try it online!

Anonymous function that performs a simple left fold over its argument (&1) using the specified accumulating function. Relies on the fact that Elixir charlists are the same thing as the lists of integer codepoints, so that the transformation can be applied directly without any conversions.

\$\endgroup\$
3
\$\begingroup\$

SNOBOL4 (CSNOBOL4), 84 bytes

	I =INPUT
N	I LEN(1) . C REM . I	:F(O)
	O =O * 10 + ORD(C) - 48	:(N)
O	OUTPUT =O
END

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Rust macro, 121 bytes

macro_rules!f{($a:expr;)=>{$a};($a:expr;$c:tt$(,$r:tt)*)=>{f!($a*10+$c as i64-48;$($r),*)};($($c:tt)*)=>{f!(0;$($c),*)};}

Try it online!

This is a macro that takes a sequence of characters and returns an expression like ((0 * 10 + '1' as i64 - 48) * 10 + '0' as i64 - 48) * 10 + '9' as i64 - 48. The expression $a is used as an accumulator: The macro expands to $a if all characters are consumed.

\$\endgroup\$
2
\$\begingroup\$

Lua, 55 bytes

i=0(...):gsub('.',load'i=i*10+(...):byte()-48')print(i)

Try it online!

Fairly simple: executes given algorithm for every character in given string, then prints the result. TIO includes test suite.

Note: input is taken as an argument. This doesn't conform to question as currently written, but is an input method allowed by default I/O rules.

\$\endgroup\$
2
\$\begingroup\$

Haskell, 23 bytes

foldl(\a x->10*a+x-48)0

Try it online!

A simple fold.

\$\endgroup\$
2
\$\begingroup\$

jq, 35 bytes

explode|reduce.[]as$x(0;.*10+$x-48)

Try it online!

This is pretty much a direct translation of the rules to jq syntax...

explode

Splits the input string into a list of codepoints.

reduce.[]as$x(0;.*10+$x-48)

Initializes the accumulator variable $x to 0, the for each codepoint computes 10 times the current accumulator value and adds the current codepoint value less 48. The result is a single number with is displayed to STDOUT by default.

\$\endgroup\$
2
\$\begingroup\$

Alice, 75 48 bytes

wi.hn$}'0-!]K@ O Q \{
      {;e(w]?. h n ${~a*+K

Try it online!

w .hn$      K                While there is characters left in the input
 i    '0-!]                  Read one char - 48 and put it on the tape
      }                      Otherwise go south
      {;e(                   Go east and rewind the tape
          w]?. h n $     K   While there is more to read on the tape
                     ~a*+    Multiply the current stack value by 10 and sum the tape value
                    {        Then go north
                   \{        Go west, switch to ordinal mode
             @ O Q           Convert the stack to string, print it, bye
\$\endgroup\$
2
\$\begingroup\$

Factor + project-euler.common, 31 bytes

Thanks to @chunes for pointing out that there actually is a function to convert a list of digits to a number, it's just hidden under an extension of the standard library.

[ >array 48 v-n digits>number ]
  • [ … ] Quotation (anonymous function) taking a string on the stack
  • >array Convert string to list of code points
  • 48 v-n Subtract 48 from each
  • digits>number Convert list of numbers to base-10 number

The >array is necessary because if you subtract a number greater than a character's codepoint from a character, it goes around to some really big number instead of being negative.

Screenshot of test cases passing


Without using extra vocabularies, the program is only 2 bytes longer:

Factor, 33 bytes

[ 0 [ 48 - swap 10 * + ] reduce ]

Try it online!

I feel like there’s probably a built in to convert a list of digits to a number, but if it exists I can’t find it. @chunes pointed out that such a function exists under an extension of the standard library, thus the above solution. I decided to keep this one since it's almost as short with a different approach and doesn't use any extra vocabularies.

Explanation

Code           Explanation Stack              
[ … ] Quotation (anonymous function) taking a string (equivalent to list of code points) "-12345"
0 [ … ] reduce Reduce body, taking previous then current, with 0 as initial 0 "-"
48 - Subtract 48 from char 0 -3
swap Swap so accumulator is on top of the stack -3 0
10 * Multiply by 10 -3 0
+ Add -3
This repeats until string ends -3 → -29 → -288 → -2877 → … -287655
\$\endgroup\$
1
  • \$\begingroup\$ "I feel like there’s probably a built in to convert a list of digits to a number, but if it exists I can’t find it." digits>number in project-euler.common. \$\endgroup\$
    – chunes
    Commented Jun 29, 2023 at 3:36
1
\$\begingroup\$

MMIX, 36 bytes (9 instrs)

00000000: e3010000 83ff0000 e7000001 42ff0005  ẉ¢¡¡³”¡¡ḃ¡¡¢B”¡¦
00000010: 2a010101 280101ff 21010130 f1fffffa  *¢¢¢(¢¢”!¢¢0ȯ””«
00000020: f8020000                             ẏ£¡¡

Disassembly:

atoi    SET   $1,0          // n = 0
0H      LDBU  $255,$0
        INCL  $0,1          // loop: v = *a++
        BZ    $255,0F       // if(!v) goto end
        4ADDU $1,$1,$1      // n = (n << 2) + n
        2ADDU $1,$1,$255    // n = (n << 1) + v
        SUBU  $1,$1,'0'     // n -= '0'
        JMP   0B            // goto loop
0H      POP   2,0           // end: return n

Note the one trick I used: 4ADDU x,x,x; 2ADDU x,x,y takes no more space than the obvious MULU x,x,10; ADDU x,x,y and executes faster (multiplication is much more expensive than addition or shifting).

\$\endgroup\$
1
\$\begingroup\$

BQN, 14 bytes

10⊸×⊸+˜´'0'-˜⌽

Anonymous tacit function that takes a string and returns a number. Try it at BQN online!

Explanation

10⊸×⊸+˜´'0'-˜⌽
              ⌽  Reverse the argument
         '0'-˜    Subtract character 0 from each character
        ´         Right fold on this function:
       ˜           Apply this function with arguments swapped:
     ⊸+            Add the right argument to
10⊸×               10 times the left argument

For example, with an argument of "109", '0'-˜⌽ gives ⟨9,0,1⟩. Then the fold proceeds as follows:

0 (10⊸×⊸+)˜ 1  →  1 (10⊸×⊸+) 0  →  10 + 0  →  10
9 (10⊸×⊸+)˜ 10  →  10 (10⊸×⊸+) 9  →  100 + 9  →  109
\$\endgroup\$
1
\$\begingroup\$

Julia

36 bytes

an evalpoly version:

!s=evalpoly(10,[reverse(s)...].-'0')

Attempt This Online!

and a fold based:

35 bytes

!s=foldl((x,c)->c-'0'+10x,s,init=0)

Attempt This Online!

and here are two more variants:

36 bytes

foreach:

!s=(x=0;foreach(c->x=c-'0'+10x,s);x)

34 bytes

!s=(x=0;[s...].|>c->x=c-'0'+10x;x)
\$\endgroup\$
1
\$\begingroup\$

Thunno, \$ 6 \log_{256}(96) \approx \$ 4.94 bytes

O48-ZD

Attempt This Online! or verify all test cases.

Port of caird coinheringaahing's Jelly answer.

Explanation

O48-ZD  # Implicit input
O       # Ordinals of input
 48-    # -48 to each
    ZD  # Convert to base-10
        # (from a list of digits)
        # Implicit output
\$\endgroup\$
1
\$\begingroup\$

Opcode (x64, Linux), 17 bytes

f:	xor eax, eax
f0:	imul rdx, rax, 10
	xor eax, eax
	lodsb
	lea rax, [rax+rdx-48]
	loop f0
	ret

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Pip, 14 bytes

FiaYy*t+Ai-48y

How?

FiaYy*t+Ai-48y  : One arg; String
Fia             : For each character in a
        Ai        : ASCII value for char
          -48     : Subtract 48
    y             : Previous result
     *t           : Multiply by ten
       +          : Add together
   Y              : Yank
             y  : Return result

Try It Online!

\$\endgroup\$
1
\$\begingroup\$

Nibbles, 4 bytes

`@~+-48

Attempt This Online!

`@~ Convert from base 10
+    add [vectorized]
-48   -48
      input
\$\endgroup\$
0
\$\begingroup\$

C#, 34 bytes

x=>x.Aggregate(0,(y,z)=>10*y+z-48)

Try it online!

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

C++ (gcc), 48 bytes

int f(char*s,int r=0){r=*s?f(s+1,r*10+*s-48):r;}

Try it online!

Edit #1: -4 bytes by removing return

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

Thunno 2 B, 5 bytes

48-Tḋ

Attempt This Online!

Explanation

48-Tḋ  # Implicit input
       # Cast to codepoints
48-    # Subtract 48 from each
    ḋ  # Convert from a list
   T   # of digits in base ten
       # Implicit output
\$\endgroup\$
0
\$\begingroup\$

Pip, 9 bytes

A*a-48FDt

Try It Online!

Explanation

A*a-48FDt
  a        ; Command-line argument
A*         ; ASCII code of each character
   -48     ; Minus 48
      FD   ; Convert to integer from list of digits in base...
        t  ; 10
\$\endgroup\$
0
\$\begingroup\$

JavaScript (Node.js), 41 bytes

f=s=>s[0]?Buffer(s.pop())[0]-48+f(s)*10:0

Try it online!

Takes input as an array of characters.

\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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