tl;dw (too lazy, didn't write): thought of it right before I fell asleep


Breaking a number is defined as the following steps:

  • Take a number or a parseable data type as input in any allowed way.
  • Duplicate the first digit (64 -> 664)
  • Subtract 4 from the last digit (664 -> 660)
  • If the subtraction gets a negative last digit, move the negative sign (-) to the front of the number (73 -> 773 -> -771)
  • If the original number was negative, and the last digit becomes negative, remove all negative signs entirely. (-44441 -> 444443)
  • Output the number in any allowed way.

Here are a few test cases:

64 -> 660
73 -> -771
thisisnotanumber -> (handle the situation)
432188 -> 4432184
-83213 -> 883211 (two negative signs turn into a positive)
0 -> -4 (0 -> 00 -> 0-4 -> -04 -> -4)


Standard loopholes are disallowed.

By "parseable data type", I mean any data type (String, Float, etc) that can be converted into the number type your program/function uses (Integer, Number, etc).

Your answer can be a function or a program. In both cases, provide an explanation of the code.

If it is a function, give a usage of it.

Test cases (or online interpreter) would be a nice plus to your answer.

Preceding 0s (-04) aren't allowed.

Behavior should be exactly replicated from the test cases above.

  • \$\begingroup\$ Since it wasn't specified, I've assumed this is code golf and added the tag. If you intended a different winning criterion please edit to whatever you prefer. \$\endgroup\$ Jul 30, 2016 at 23:48
  • \$\begingroup\$ @trichoplax i'd say falling gracefully is preferred, but hey, it's your code \$\endgroup\$ Jul 30, 2016 at 23:52
  • 3
    \$\begingroup\$ The trouble with "preferred" is that it isn't defined in the scoring, so no one will do it if it is not required, as it will adversely affect their score. \$\endgroup\$ Jul 30, 2016 at 23:53
  • 5
    \$\begingroup\$ It's still unclear to me. Also, I don't think that required behavior for invalid inputs really adds something to the challenge. \$\endgroup\$
    – Dennis
    Jul 31, 2016 at 0:07
  • 8
    \$\begingroup\$ Note to self: will put in sandbox first. \$\endgroup\$ Jul 31, 2016 at 0:08

5 Answers 5


Batch, 105 bytes

@set n=%n:~0,1%%n%

Alternatively the first line can be @set/as=%1^>^>31^|1,n=%1*s, also for 105 bytes. Explanation (without quoting metacharacters):

set /a n = %1               Get parameter
set /a s = n >> 31 | 1      Get sign of parameter
set /a n *= s               Get absolute value of parameter
set n=%n:~0,1%%n%           Duplicate the first digit
cmd /c                      Cause the final result to be printed
set /a d = n % 10           Get last digit
set /a e = d - 4            Calculate new last digit
set /a t = e >> 31 | 1      Get sign of new last digit
set /a e *= t               Get absolute value of new last digit
set /a (n - d + e) * s * t  Replace last digit and correct sign of result

Ruby, 88 87 + 3 (-n flag) = 90 bytes

Regex approach that reads lines from STDIN. Probably better solved with Perl if it's just regex like this?

Returns a nonsense NoMethodError if the input is not a number, which costs 14 bytes. If there's no need to worry about invalid inputs like that (the spec implied it needed handling) then the first line of the code can be removed.

-2 bytes from @Dada

p sub(/(-)?(.+)-/){$1?$2:?-+$2}.to_i
  • \$\begingroup\$ Nicely done. Your regex to check if the input is a number isn't quite right though, as it allows - anywhere, as well as inputs like ---. You'll probably want to use something like /^-?\d+$/ (which happens to be shorter by the way). \$\endgroup\$
    – Dada
    Jul 31, 2016 at 10:27
  • \$\begingroup\$ And indeed, the Perl solution is slightly shorter (66 bytes) : perl -pe '!/^-?\d+$/&¨s/\d/$&$&/;s/.$/$&-4/e;s/(-?)(.+)-/$1?$2:"-$2"/e;'. (which I won't post as it's your solution). \$\endgroup\$
    – Dada
    Jul 31, 2016 at 10:51

Pyth, 31 bytes


Naive implementation of the question.

Test suite.


Python, 79 78 Bytes

lambda x:"+-"[(int(x)<0)!=(int(x[-1])-4<0)]+x[1]+x[1:-1]+str(int(x[-1])-4)[-1]

anonymous lambda function, does all of the four parts, then adds them together. Expects input as a string with explicit sign e.g. "+64", output is of the same form. Throws ValueError if the string cannot be converted to an int.


C, 191 bytes

f(char*n){if(!isdigit(*n)&!isdigit(n[1]))return 0;char*m;strcpy(m+1,n);*m=m[1];if(*n==45)m[1]=m[2];int a=strlen(n);if(m[a]<52)m[a]=100-m[a],m--,*m=45;else m[a]-=4;return atoi(m[1]^45?m:m+2);}

Ungolfed with explanations:

    if(!isdigit(*n)&!isdigit(n[1])) /* if first two chars aren't digits
                                     * if it was only the first one, negative numbers wouldn't pass
                                     * if it was only the second one, 0 wouldn't pass */
        return 0;        // handling
    strcpy(m+1,n);        // copy leaving space for doubling the number
    *m=m[1];              // double the first digit or the minus sign
    if(*n==45)            // if negative
        m[1]=m[2];        // double the first digit
    int a=strlen(n);      /* length of the nunber
                           * it doesn't let me save 2 bytes, i dunno why. */
    if(m[a]<52)           // if the last digit is less than 4
        m[a]=100-m[a],    // subtract 4
        m--,              // leave space for minus sign
        *m=45;            // put minus sign
        m[a]-=4;          // subtract 4 from the last digit
    return atoi(m[1]^45?m:m+2); /* if there are two minus signs, skip them,
                                 * turn the string into an integer, and return */

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