2
\$\begingroup\$

Origins

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

Challenge

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)

Clarifications

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.

\$\endgroup\$

closed as unclear what you're asking by trichoplax, Leaky Nun, DJMcMayhem, NoOneIsHere, Blue Jul 31 '16 at 11:49

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\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\$ – trichoplax Jul 30 '16 at 23:48
  • \$\begingroup\$ @trichoplax i'd say falling gracefully is preferred, but hey, it's your code \$\endgroup\$ – InitializeSahib Jul 30 '16 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\$ – trichoplax Jul 30 '16 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 '16 at 0:07
  • 8
    \$\begingroup\$ Note to self: will put in sandbox first. \$\endgroup\$ – InitializeSahib Jul 31 '16 at 0:08
2
\$\begingroup\$

Batch, 105 bytes

@set/an=%1,n*=s=n^>^>31^|1
@set n=%n:~0,1%%n%
@cmd/cset/ad=n%%10,e=d-4,t=e^^^>^^^>31^^^|1,(n-d+e*t)*s*t

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
\$\endgroup\$
2
\$\begingroup\$

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

+(~/^-?\d+$/)
sub(/\d/){$&*2}
sub(/.$/){$&.to_i-4}
p sub(/(-)?(.+)-/){$1?$2:?-+$2}.to_i
\$\endgroup\$
  • \$\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 '16 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 '16 at 10:51
0
\$\begingroup\$

Pyth, 31 bytes

*i++hJja0QTPJa0K-eJ4T^_1x<K0<Q0

Naive implementation of the question.

Test suite.

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

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.

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

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:

f(char*n){
    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
    char*m;
    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
    else
        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 */
}
\$\endgroup\$

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