32
\$\begingroup\$

To check whether a decimal number is divisible by 7:

Erase the last digit. Multiply it by 2 and subtract from what is left. If the result is divisible by 7, the original number is divisible by 7.

(also described e.g. here)

This rule is good for manual divisibility check. For example:

Is 2016 divisible by 7?

Subtract 6*2 from 201; we get 189. Is this divisible by 7? To check it, let's apply the rule again.

Subtract 9*2 from 18; we get 0. Therefore, 2016 is divisible by 7.

In this challenge, you should apply this rule until the divisibility status is obvious, that is, the number is not greater than 70 (however, see below for details). Make a function or a full program.

Input: a positive integer; your code should support inputs up to 32767 (supporting arbitrary-precision integers is a bonus; see below).

Output: an integer (possibly negative), not greater than 70, that is a result of applying the divisibility-by-7 rule zero or more times.

Test cases:

Input Output Alternative output
1 1
10 10 1
100 10 1
13 13 -5
42 42 0
2016 0
9 9
99 -9
9999 -3
12345 3
32767 28 -14
---------- Values below are only relevant for the bonus
700168844221 70 7
36893488147419103232 32 -1
231584178474632390847141970017375815706539969331281128078915168015826259279872 8

Where two possible outputs are specified, either result is correct: the second one corresponds to applying the rule one more time. It's forbidden to apply the rule on a single-digit number: if you erase the digit, nothing (not 0) is left.


Bonus: If your algorithm

where n is the number of decimal digits:

Subtract 50% from your code's byte count.

Real bonus:

In addition, if your algorithm reads the input in normal direction, starting from the most significant digit, subtract 50% once again - your score is 25% of your byte count (it seems possible, but I'm not absolutely sure).

asked Feb 14, 2016 at 19:58
\$\endgroup\$
19
  • 1
    \$\begingroup\$ @DenkerAffe Returning the input as-is is acceptable. I updated the test-case of input=10 to reflect this; that was the idea from the beginning. \$\endgroup\$ Commented Feb 14, 2016 at 20:40
  • 4
    \$\begingroup\$ I wouldn't want to use that rule on 1000000000000000000001. \$\endgroup\$ Commented Feb 14, 2016 at 20:55
  • 1
    \$\begingroup\$ But what if your language has long longs or some equivalent type built in? \$\endgroup\$ Commented Feb 14, 2016 at 22:00
  • 1
    \$\begingroup\$ What I was saying was that, in some implementations, it's a 128-bit integer, which is more than big enough for that last test case. \$\endgroup\$ Commented Feb 14, 2016 at 22:18
  • 7
    \$\begingroup\$ -1. Not all languages support arbitrary precision. \$\endgroup\$ Commented Feb 15, 2016 at 3:54

31 Answers 31

1
2
23
\$\begingroup\$

Golfscript, (削除) 27 (削除ここまで) 22 bytes

{.9>{.10/10円%2*-f}*}:f

You can use it this way:

1000f

Explanation

{.9>{.10/10円%2*-f}*}:f
{ }:f # Define block 'f' (similar to a function)
 . # Duplicate the first value of the stack
 9>{ }* # If the value on top of the stack is greater than 9 then the block is executed
 .10/10円%2*- # Same as nb/10 - (nb%10 * 2) with some stack manipulations '.' to duplicate the top of the stack and '\' to swap the the first and second element of the stack
 f # Execute block 'f'

5 bytes saved thanks to Dennis !

answered Feb 14, 2016 at 22:01
\$\endgroup\$
7
  • 1
    \$\begingroup\$ Welcome to Programming Puzzles and Code Golf. This is a good answer, however you could improve it by adding a code breakdown and explanation, like the questions above. To reply to this comment, type @wizzwizz4 (@ then my username) at the beginning of (or anywhere in) a comment. \$\endgroup\$ Commented Feb 14, 2016 at 22:05
  • 1
    \$\begingroup\$ @wizzwizz4 Better ? I'm not sure that I understand what you mean by 'code breakdown' (not native speaker sorry) \$\endgroup\$ Commented Feb 14, 2016 at 22:34
  • 8
    \$\begingroup\$ I believe by "code breakdown" he meant an explanation, which you've added. This is a very nice first answer indeed. Welcome to the site! \$\endgroup\$ Commented Feb 14, 2016 at 22:55
  • 1
    \$\begingroup\$ You can rewrite the {...}{}if part as {...}*, which will just apply the code block zero of one times, depending on the value pushed by >. Also, we're allowed to perform one more iteration (so replacing 70 with 9 saves a byte), and I don't think you need to pop the block with ;. \$\endgroup\$ Commented Feb 15, 2016 at 3:12
  • 3
    \$\begingroup\$ @Dica, this is a first answer good enough to get 12+ upvotes on a question with only 624 views, and to get praise from two moderators. If you keep this up, you'll soon overtake Dennis! \$\endgroup\$ Commented Feb 15, 2016 at 8:52
13
\$\begingroup\$

Haskell, 35 bytes

until(<71)(\n->div n 10-2*mod n 10)

Usage example: until(<71)(\n->div n 10-2*mod n 10) 36893488147419103232 -> 32.

Nothing much to explain, it's a direct implementation of the algorithm.

answered Feb 14, 2016 at 23:18
\$\endgroup\$
0
9
\$\begingroup\$

Jelly, 11 bytes

d5Uḅ-2μ>9$¿

Try it online!

How it works

d5Uḅ-2μ>9$¿ Main link. Input: n
d5 Divmod; return [n : 10, n % 10].
 U Upend; yield [n % 10, n : 10].
 ḅ-2 Convert from base -2 to integer, i.e., yield -2 ×ばつ (n % 10) + (n : 10).
 μ Push the previous chain as a link and begin a new, monadic chain.
 ¿ Apply the previous chain while...
 >9$ its return value is greater than 9.
answered Feb 15, 2016 at 2:42
\$\endgroup\$
1
  • \$\begingroup\$ And as always, Jelly wins. Dennis, how much bytes would it take to implement a jelly interpreter in Jelly? \$\endgroup\$ Commented Feb 22, 2016 at 12:47
8
\$\begingroup\$

Julia 0.6, (削除) 27 (削除ここまで) 26 bytes

f(x)=x>9?f(x÷10-x%10*2):x

Try it online!

This is a recursive function that accepts an integer and returns a BigInt. If the input is a large number like in the last example, Julia parses it as a BigInt, so no manual conversion is necessary.

The approach is just a straightforward implementation of the algorithm. It will produce the alternate outputs. Taking the modulus when dividing by 10 yields the last digit and the quotient from integer division by 10 yields everything but the last digit.

Saved a byte thanks to Dennis!

MarcMush
6,84515 silver badges18 bronze badges
answered Feb 15, 2016 at 0:12
\$\endgroup\$
2
  • \$\begingroup\$ We're allowed to perform one more iteration, so replacing 70 with 9 saves a byte. \$\endgroup\$ Commented Feb 15, 2016 at 3:06
  • \$\begingroup\$ 23B replacing f(a) with !a \$\endgroup\$ Commented Sep 20, 2024 at 10:55
7
\$\begingroup\$

Python 2, 38 bytes

f=lambda x:f(x/10-x%10*2)if x>70else x

Try it here!

Simple recursive approach. Prints x if its < 70 otherwise applies the divisibility rule and calls itself with the result.

answered Feb 14, 2016 at 20:11
\$\endgroup\$
6
  • \$\begingroup\$ you don't need the space after the ) \$\endgroup\$ Commented Feb 14, 2016 at 20:12
  • \$\begingroup\$ @Maltysen True. Copy pasted the wrong one, thanks for the hint! \$\endgroup\$ Commented Feb 14, 2016 at 20:14
  • 2
    \$\begingroup\$ The if is too verbose. f=lambda x:x*(x<70)or f(x/10-x%10*2) \$\endgroup\$ Commented Feb 14, 2016 at 20:25
  • 1
    \$\begingroup\$ @Seeq Nice trick, thanks! This should work in theory, but it reaches the maximum recursion depth with 2016 as input while my version does not. Any idea why? \$\endgroup\$ Commented Feb 14, 2016 at 20:41
  • \$\begingroup\$ Ah, right, didn't consider that. This trick considers x*(x<70) != 0 to be the end condition. If x gets to 0 - like it does with 2016 - the end condition never happens. \$\endgroup\$ Commented Feb 14, 2016 at 20:44
6
\$\begingroup\$

Pyth, 13 bytes

.W>H9-/ZTyeZQ

Try it online: Demonstration or Test Suite

This will print all the alternative answers.

Explanation:

.W>H9-/ZTyeZQ 
 Q read a number from input
.W while
 >H9 the number is greater than 9
 do the following with the number:
 /ZT divide it by 10
 - and subtract
 yeZ 2*(number%10)
answered Feb 14, 2016 at 21:32
\$\endgroup\$
5
\$\begingroup\$

GNU dc, (削除) 20 (削除ここまで) 15 bytes

[10~2*-d70<F]sF

This defines my first (ever) dc function, F. It takes input on the top of stack, and leaves its output at top of stack. Example usage:

36893488147419103232
lFxp
32
answered Feb 15, 2016 at 12:33
\$\endgroup\$
4
\$\begingroup\$

Pyth, 17 bytes

L?<b70by-/bT*%bT2

Try it here!

Same recursive approach as in my python answer. Defines a lambda y which is called like this: y12345.
The byte counter in the online interpreter shows 19 bytes because I added the lambda call to it, so you can just try it by hitting the run-button.

Explanation

L?<b70by-/bT*%bT2
L # Defines the lambda y with the parameter b
 ?<b70 # if b < 70:
 b # return b, else:
 -/bT*%bT2 # calculate b/10 - b%10*2 and return it
answered Feb 14, 2016 at 20:57
\$\endgroup\$
1
  • \$\begingroup\$ You have a typo in your explanation, 17 should be 70 :P \$\endgroup\$ Commented Feb 15, 2016 at 2:01
4
\$\begingroup\$

CJam - 19 bytes

Do-while version:

r~A*{`)]:~~Y*-_9>}g

Try it online or While version #1:

r~{_9>}{`)]:~~Y*-}w

Try it online or While version #2:

r~{_9>}{_A/\A%Y*-}w

Try it online.

r~ | Read and convert input
 A* | Multiply by 10 to get around "if" rule
 ` | Stringify
 ) | Split last character off
 ] | Convert stack to array
 :~ | Foreach in array convert to value
 ~ | Dump array
 Y* | Multiply by 2
 - | Subtract
 _ | Duplicate
 9> | Greater than 9?
 { }g | do-while
answered Feb 15, 2016 at 10:05
\$\endgroup\$
4
\$\begingroup\$

Oracle SQL 11.2, 116 bytes

WITH v(i)AS(SELECT:1 FROM DUAL UNION ALL SELECT TRUNC(i/10)-(i-TRUNC(i,-1))*2 FROM v WHERE i>70)SELECT MIN(i)FROM v;

Un-golfed

WITH v(i) AS
(
 SELECT :1 FROM DUAL
 UNION ALL
 SELECT TRUNC(i/10)-(i-TRUNC(i,-1))*2 FROM v WHERE i>70
)
SELECT MIN(i) FROM v;
answered Feb 15, 2016 at 12:45
\$\endgroup\$
4
\$\begingroup\$

Haskell, (削除) 157 (削除ここまで) (削除) 192 (削除ここまで) (削除) 184 (削除ここまで) (削除) 167 (削除ここまで) (削除) 159 (削除ここまで) (削除) 147 (削除ここまで) 138+5 bytes - 50% = 71.5 bytes

O(1) space, O(n) time, single-pass!

h d=d%mod d 10
d%r=(quot(r-d)10,r)
p![d]=d-p*10
p![d,e]=d#(e-p)
p!(d:e:f)|(b,a)<-quotRem(2*d)10,(q,r)<-h$e-a-p=(b+q)!(r:f)
m#0=m
m#n=n-2*m
(0!)

Use as 0![6,1,0,2] to apply the rule to 2016, i.e. pass it a number in stream form with least significant figure first. In this way, it will pass over the number digit by digit, applying the rule with O(1) space complexity.

The ungolfed code is here:

import Data.Char
{- sub a b = sub2 0 a b
 where
 sub2 borrow (a:as) (b:bs) = res : sub2 borrow2 as bs
 where
 (borrow2, res) = subDig borrow a b
 sub2 borrow (a:as) [] = sub2 borrow (a:as) (0:[])
 sub2 _ [] _ = [] -}
--subDig :: Int -> Int -> Int -> (Int, Int)
subDig borrow a b = subDig2 (a - b - borrow)
 where
 subDig2 d = subDig3 d (d `mod` 10)
 subDig3 d r = ((r-d) `quot` 10, r)
seven ds = seven2 0 ds
seven2 borrow (d:e:f:gs) = seven2 (b + borrow2) (res:f:gs)
 where
 (a, b) = double d
 (borrow2, res) = subDig borrow e a
seven2 borrow (d:e:[]) = finalApp d (e-borrow)
seven2 borrow (d:[]) = d - borrow*10
double d = ((2*d) `mod` 10, (2*d) `quot` 10)
finalApp m 0 = m
finalApp m n = n - 2*m
num2stream :: Int -> [Int]
num2stream = reverse . map digitToInt . show
sev = seven . num2stream

The gist of how this works is that it implements a digit-by-digit subtraction algorithm, but takes advantage of the fact that each number to be subtracted is at most 2-digits, and so we can subtract an arbitrary amount of these 1-or-2 digit numbers from the main one (as well as eating the least significant digits).

The subtraction algorithm is O(1) and only stores the current 'borrow' value. I altered this to add in the extra digit (either 0 or 1), and we note that this borrow value is bounded (within the range [-2,2] so we need only 3 bits to store this).

The other values stored in memory are temporary variables representing the current 2-digit number to add, a single look-ahead in the stream, and to apply one step of the subtraction algorithm (i.e. it takes two digits and a borrow value, and returns one digit and a new borrow value).

Finally at the end it processes the last two digits in the stream at once to return a single-digit number rather than a list of digits.

N.B. The sev function in the ungolfed version will work on an Integer, converting it into the reversed stream form.

answered Feb 15, 2016 at 14:48
\$\endgroup\$
6
  • \$\begingroup\$ I intended the bonus to be for the normal order of digits. But I never said it, so it's fair to get the bonus for the reversed order, even though it's less fun. Anyway, even the reversed order is harder than I thought, so it's fun enough! \$\endgroup\$ Commented Feb 15, 2016 at 18:24
  • \$\begingroup\$ @anatolyg: Thanks! I'm not sure if it's possible to do a single pass O(1) implementation of the normal order... the rule depends on the least significant figures, so in theory direct application of the rule is impossible except in reversed order. The only other thing I can think of is by finding a mathematically equivalent form - for example Mod[18 - Quotient[n, 10] - 2*n, 21] - 18 + Quotient[n, 10] works empirically for n between 10 and 99, but gets more complicated the more digits n has... \$\endgroup\$ Commented Feb 15, 2016 at 20:59
  • \$\begingroup\$ Hmm I thought about it and it seemed there might be a way by keeping the front 2 digits and applying each subsequent digit, but multiplying by (-2)^n to take account of it 'filtering through'... as far as I can tell though there's no way to make this work without keeping all the digits in memory and sacrificing the O(1)'ness or even o(n)'ness... I think the normal order is definitely impossible :( \$\endgroup\$ Commented Feb 15, 2016 at 21:41
  • 1
    \$\begingroup\$ I'm afraid you have to count the bytes of the initial 0 when calling !, too, e.g. as a section (0!) (+ a newline), i.e. +5 bytes. On the other side you can shorten the first to pattern matches of ! to p![d]= and p![d,e]=. Also, use pattern guards instead of the let: p!(d:e:f)|(b,a)<-quotRem(2*d)10,(q,r)<-h$e-a-p=(b+q)!(r:f). \$\endgroup\$ Commented Feb 16, 2016 at 16:55
  • 1
    \$\begingroup\$ @nitrous: Oh I ment (0!) on a line of it's own. (0!) is the function you give as your answer. The 0 is required, but has nothing to do with the input, so you cannot outsource it to the caller. Of course you could also use f x=0!x, but this is longer. \$\endgroup\$ Commented Feb 16, 2016 at 21:32
4
\$\begingroup\$

GCC, x86, No optimization, 30 bytes

f(i){i=i<70?i:f(i/10-i%10*2);}

Try it online!

Written to Read

apply_seven_division(int i){
 if(i < 70) return i; 
 return apply_seven_division( (i / 10) - (2 * (i % 10)) );
}

I know using the first parameter as a return is a total hack and is undefined behavior but so is assuming NULL is 0. This is also why I specified GCC, x86, No optimization.

answered Apr 27, 2024 at 22:35
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Welcome to Code Golf, and nice first answer! Be sure to check out our Tips for golfing in C page for ways you can golf your program! You might want to include a Try it online! link so others can test your code. Also, you can put ```c at the start of the first code block to turn on syntax highlighting. \$\endgroup\$ Commented Apr 28, 2024 at 7:05
  • \$\begingroup\$ Thank you for the help! \$\endgroup\$ Commented Apr 29, 2024 at 13:49
3
\$\begingroup\$

Mathematica, (削除) 47 (削除ここまで) 44 bytes

If[#>70,#0[{1,-2}.{⌊#/10⌋,#~Mod~10}],#]&

Simple recursive approach. Could probably be golfed further.

answered Feb 15, 2016 at 1:55
\$\endgroup\$
1
  • \$\begingroup\$ #0[{1,-2}.QuotientRemainder[#,10]] saves a byte. \$\endgroup\$ Commented Feb 15, 2016 at 2:42
3
\$\begingroup\$

PHP, 50 bytes

for($n=$argv[1];$n>9;)$n=$n/10|0-2*($n%10);echo$n;

uses alternative output; works up to PHP_INT_MAX


string version, works for any (positive) number (64 bytes):

for($n=$argv[1];$n>9;)$n=substr($n,0,-1)-2*substr($n,-1);echo$n;
answered Nov 2, 2016 at 11:12
\$\endgroup\$
1
  • \$\begingroup\$ "works for any number" ... funny nobody has noticed so far. Of course it does not. $n becomes a number after the first iteration; so we´re still somewhat limited by PHP precision. But still, it can handle at least one digit more than the numeric version. \$\endgroup\$ Commented May 22, 2024 at 10:05
3
\$\begingroup\$

C, 56 bytes - 75% = 14

Although this doesn't give the exact same numbers as the test cases, it satisfies the spirit of the question (and arguably more). It correctly identifies exact multiples of 7, and gives the exact remainder for other numbers (since it doesn't ever use negative numbers).

n;f(char*c){for(n=0;*c;)n-=n>6?7:'0'-n-n-*c++;return n;}

There is no multiplication or division in the algorithm, only addition and subtraction, and digits are processed in a single pass from left to right. It works as follows, starting with 0 in the accumulator:

  1. Subtract 7 if necessary, and again if still necessary
  2. Multiply the running total by three, and add the next digit

The "multiply by three" step is written as n-=-n-n to save a byte and to avoid the multiply operator.

When we hit the end, we don't subtract sevens, so the result will be in the range 0-24; if you want a strict modulus (0-6), substitute *c with *c||n>6 in the for loop condition.

It qualifies for the enhanced bonus, because it

  • supports arbitrary-precision integers
  • performs only one pass on the input, in left-to-right order
  • has space complexity O(1)
  • has time complexity O(n).

Test program and results

#include <stdio.h>
int main(int argc, char **argv) {
 while (*++argv)
 printf("%s -> %d\n", *argv, f(*argv));
 return 0;
}
540 -> 15
541 -> 16
542 -> 17
543 -> 18
544 -> 19
545 -> 20
546 -> 21
547 -> 22
548 -> 23
549 -> 24
550 -> 18
99 -> 15
999 -> 12
12345 -> 11
32767 -> 7
700168844221 -> 7
36893488147419103232 -> 11
231584178474632390847141970017375815706539969331281128078915168015826259279872 -> 11

Alternative version

Here's one that recurses (you'll want to enable compiler optimizations to do tail-call transformation or you may overflow your stack; I used gcc -std=c89 -O3):

f(c,n)char*c;{return n>6?f(c,n-7):*c?f(c+1,n+n+n+*c-'0'):n;}

Call it with 0 as the second argument.

Both versions calculate the remainder-modulo-seven of a 60,000 digit number in under 50 milliseconds on my machine.

answered Feb 19, 2016 at 11:51
\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the bonus - it makes a real change for C to end up so competitive! Currently beaten only by Jelly (11) and Pyth (13). :-) \$\endgroup\$ Commented Aug 5, 2016 at 14:23
2
\$\begingroup\$

ES6, 108 bytes

f=(s,n=0)=>s>1e9?f(s.slice(0,-1),((1+s.slice(-1)-n%10)%10*21+n-s.slice(-1))/10):s>9?f(((s-=n)-s%10*21)/10):s

Works for 2257 and 1000000000000000000001, but could use further golfing.

answered Feb 15, 2016 at 13:53
\$\endgroup\$
1
  • \$\begingroup\$ @PatrickRoberts Oops, oversight when reformatting for the submission. \$\endgroup\$ Commented Feb 15, 2016 at 16:25
2
\$\begingroup\$

R, 43 bytes

x=scan();while(x>70)x=floor(x/10)-x%%10*2;x

Explanation:

x=scan() # Takes input as a double
 ; # Next line
 while(x>70) # While-loop that runs as long x > 70
 floor(x/10) # Divide x by 10 and round that down
 -x%%10*2 # Substract twice the last integer
 x= # Update x
 ; # Next line once x <= 70
 x # Print x

Sample runs:

> x=scan();while(x>70)x=floor(x/10)-x%%10*2;x
1: 9999
2: 
Read 1 item
[1] -3
> x=scan();while(x>70)x=floor(x/10)-x%%10*2;x
1: 32767
2: 
Read 1 item
[1] 28
answered Feb 19, 2016 at 10:48
\$\endgroup\$
2
\$\begingroup\$

C#, (削除) 111 (削除ここまで) 104 bytes

int d(int n){var s=""+n;return n<71?n:d(int.Parse(s.Remove(s.Length-1))-int.Parse(""+s[s.Length-1])*2);}
answered Aug 5, 2016 at 15:24
\$\endgroup\$
1
  • \$\begingroup\$ 42 bytes? \$\endgroup\$ Commented Apr 21, 2024 at 22:18
2
\$\begingroup\$

Google Sheets, 84 bytes

=LET(n,A1,f,LAMBDA(self,n,IF(n<71,n,self(self,INT(n/10)-(n-INT(n/10)*10)*2))),f(f,n)

This implements the division-by-7-rule recursively until the output is 70 or less.

Instructions: paste the input values into A-column and the formula into B-column

thanks to @doubleunary for the nice SO post on recursion in Google Sheets

A shorter 77-bytes version =LET(n,A1,f,LAMBDA(self,n,IF(n<71,n,self(self,INT(n/10)-mod(n,10)*2))),f(f,n) works for all values except the two last ones:

Error Parameters in MOD caused an out of range error. Namely, the error occurs when the following is true: (divisor * 1125900000000) is less than or equal to dividend.

The result:

(Interestingly, the three largest values are smoothly treated in Google Sheets the same way as the smaller ones!)

enter image description here

answered Apr 21, 2024 at 12:44
\$\endgroup\$
2
\$\begingroup\$

Uiua, 16 bytes

⍢(×ばつ2⊃◿÷10|>70)

Try it in the pad!

Explanation

⍢( | ) While
 >70 greater than 70:
 ⊃◿÷10 separate last digit
 ×ばつ2 multiply by 2 and subtract
 ⌊ floor because ÷ returns decimals
answered Apr 21, 2024 at 15:57
\$\endgroup\$
2
\$\begingroup\$

Go, 82 bytes

func f(n int)int{if n<71{return n}
c:=n/10-n%10*2
if c>70||c%7>0{c=f(c)}
return c}

Attempt This Online!

answered Apr 22, 2024 at 4:28
\$\endgroup\$
1
\$\begingroup\$

(削除) JavaScript ES6, 38 bytes (削除ここまで)

a=i=>i>70?a(Math.floor(i/10)-i%10*2):i

Fails with 36893488147419103232 and using ~~(1/10) will also fail for 700168844221

Test:

a=i=>i>70?a(Math.floor(i/10)-i%10*2):i
O.textContent = O.textContent.replace(/(-?\d+) +(-?\d+)/g, (_,i,o) =>
 _+": "+(a(+i)==o?"OK":"Fail")
);
<pre id=O>1 1
10 10
100 10
13 13
42 42
2016 0
9 9
99 -9
9999 -3
12345 3
700168844221 70
36893488147419103232 32</pre>

answered Feb 14, 2016 at 20:16
\$\endgroup\$
5
  • \$\begingroup\$ I get two Fails... 70 and 32 \$\endgroup\$ Commented Feb 14, 2016 at 20:29
  • \$\begingroup\$ @CᴏɴᴏʀO'Bʀɪᴇɴ Yea me to, I'm still wondering why... \$\endgroup\$ Commented Feb 14, 2016 at 20:31
  • \$\begingroup\$ Because JavaScript's number type doesn't handle the last case, at least. \$\endgroup\$ Commented Feb 14, 2016 at 20:31
  • 1
    \$\begingroup\$ f=n=>n>70?f((n-n%10*21)/10):n is a shorter version but still only works for up to 2**56. \$\endgroup\$ Commented Feb 14, 2016 at 20:37
  • \$\begingroup\$ @Neil see my answer for arbitrary precision, and please feel free to golf, greatly appreciated. \$\endgroup\$ Commented Feb 15, 2016 at 5:19
1
\$\begingroup\$

Mathematica, 33 bytes

#//.a_/;a>70:>⌊a/10⌋-2a~Mod~10&

Test case

%[9999]
(* -3 *)
answered Feb 15, 2016 at 2:37
\$\endgroup\$
1
\$\begingroup\$

Perl 5, (削除) 47 (削除ここまで) 46 bytes

Had to use bigintfor the last test case. (It returns 20 without)

use bigint;$_=<>;while($_>9){$_-=2*chop;}print

Not really sure it's a candidate for the bonus, so I didn't take it into account. (I think it does, but I'm not really accustomed to the concepts)

Try it here!

answered Feb 15, 2016 at 8:28
\$\endgroup\$
1
\$\begingroup\$

JavaScript ES6, (削除) 140 (削除ここまで) 142 bytes

f=s=>s>9?eval("t=s.replace(/.$/,'-$&*2');for(i=-1;0>(n=eval(u=t[c='slice'](i-4)))&&u!=t;i--);n<0?n:f(t[c](0,i-4)+('0'.repeat(-i)+n)[c](i))"):s

This is true arbitrary-precision math, even works on the largest test-case.

This function recursively removes the last digit from the string, then subtracts 2 * the last digit from the remaining numerical string by iteratively incrementing the amount of digits to apply to the minuend until the difference is positive. Then it appends that difference to the end of the string with appropriately padded 0s and calls itself recursively until its numerical value is less than or equal to 9.

  • Golfed 7 bytes thanks to @Neil (yes I know I gained 2 bytes but I fixed a few bugs that caused the function to freeze or return wrong output for some cases).

f=s=>s>9?eval("t=s.replace(/.$/,'-$&*2');for(i=-1;0>(n=eval(u=t[c='slice'](i-4)))&&u!=t;i--);n<0?n:f(t[c](0,i-4)+('0'.repeat(-i)+n)[c](i))"):s;[['1',1],['10',1],['100',1],['13',-5],['42',0],['2016',0],['9',9],['99',-9],['9999',-3],['12345',3],['700168844221',7],['36893488147419103232',-1],['231584178474632390847141970017375815706539969331281128078915168015826259279872',8]].map(a=>document.write(`<pre>${f(a[0])==a[1]?'PASS':'FAIL'} ${a[0]}=>${a[1]}</pre>`))

answered Feb 15, 2016 at 4:25
\$\endgroup\$
2
  • \$\begingroup\$ Nice, but it might not work on 1000000000000000000001. \$\endgroup\$ Commented Feb 15, 2016 at 9:29
  • 1
    \$\begingroup\$ Try s.replace(/.$/,'-$&*2'). I don't have any obvious ideas for the rest though sorry. \$\endgroup\$ Commented Feb 15, 2016 at 13:21
1
\$\begingroup\$

Java, 133 bytes

int d(int n){String s=""+n;return n<71?n:d(Integer.parseInt(s.replaceFirst(".$",""))-Integer.parseInt(""+s.charAt(s.length()-1))*2);}

I hate how verbose Integer.parseInt is. Ungolfed:

static int div(int n) {
 if (n <= 70) {
 return n;
 } else {
 String num = ("" + n);
 int last = Integer.parseInt("" + num.charAt(num.length() - 1));
 int k = Integer.parseInt(num.replaceFirst(".$", "")) - last * 2;
 return div(k);
 }
}
answered Aug 5, 2016 at 13:01
\$\endgroup\$
1
\$\begingroup\$

Brain-Flak, (削除) 368 (削除ここまで) 360 bytes

Try it Online!

([([({})]<(())>)](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>){{}(({}))(<((()()()()()){}<>)>)<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>([([([(({}<{}><>)<([{}]{})(<((()()()()()){}(<>))>)<>{({}[()])<>(({}()[({}<({}())>)])){{}(<({}({}<({}[()])>))>)}{}<>}{}<>{}{}({}<>)>){}]{})]<(())>)(<>)]){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>)}{}

Explanation

To start off all of the code is in a loop that runs until the top of the stack is less than zero:

([([({})]<(())>)](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>)
{{}
 ...
 ([([({})]<(())>)](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>)
}{}

Inside of the loop we run the divisible by seven algorithm:

Duplicate the top of the stack

(({}))

Take the mod 10 of the top of the stack (last digit)

(<((()()()()()){}<>)>)<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>({}<{}><>)

This is a bit of a mess but it does the rest of the algorithm I might explain it later but I don't entirely remember how it works:

([(({})<([{}]{})(<((()()()()()){}(<>))>)<>{({}[()])<>(({}()[({}<({}())>)])){{}(<({}({}<({}[()])>))>)}{}<>}{}<>{}{}({}<>)>){}]{})
answered Aug 5, 2016 at 13:58
\$\endgroup\$
1
\$\begingroup\$

Husk, 13 bytes

Ω≤70§-ȯD→d÷10

Try it online!

Tied with Pyth, using a modified method.

Explanation

Ω≤70§-ȯD→d÷10
Ω≤70 until the number is ≤ 70,
 §- subtract
 →d the last digit
 ȯD doubled
 ÷10 from the number floor divided by 10
answered Oct 31, 2020 at 4:50
\$\endgroup\$
1
\$\begingroup\$

Ruby, 27 bytes

f=->x{x>9?f[x/10-x%10*2]:x}

Attempt This Online!

Translated from the julia language (answer).

answered Jul 27, 2024 at 14:43
\$\endgroup\$
1
\$\begingroup\$

JavaScript (Node.js), 91 - 50% = 46 bytes

n=BigInt(process.argv[2])
f=x=>(x/10n|0n)-2n*(x%10n)
while(n>70n){n=f(n)}
console.log(n+'')

Ran the code in VS Code with command line input, and tested all the provided test cases. Added support for long integers, so claiming 50% bonus.

answered Jul 27, 2024 at 21:18
\$\endgroup\$
2
  • \$\begingroup\$ You don't have to define f as a function of x, you can just do those operations directly to n. Also, any while loop can be reduced to a for loop which is a little shorter. for(n=BigInt(process.argv[2]);n>70n;n=(n/10n|0n)-x%10n*2n);console.log(n) \$\endgroup\$ Commented Jul 28, 2024 at 0:29
  • \$\begingroup\$ If you want you could instead write this as a function taking n as input and returning it: f=n=>n>70n?f(n/10n-n%10n*2n):n \$\endgroup\$ Commented Jul 28, 2024 at 0:32
1
2

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.