| Bytes | Lang | Time | Link |
|---|---|---|---|
| 026 | Julia 0.6 | 160215T001211Z | Alex A. |
| nan | JavaScript Node.js | 240727T211830Z | Andrew B |
| 027 | Ruby | 240727T144345Z | int 21h |
| 030 | GCC | 240427T223541Z | l3akwire |
| 082 | Go | 240422T042848Z | bigyihsu |
| 051 | PowerShell Core | 240421T213709Z | Julian |
| 016 | Uiua | 240421T155750Z | Joao-3 |
| nan | C | 160219T115106Z | Toby Spe |
| 084 | Google Sheets | 240421T124405Z | Patric |
| 013 | Husk | 201031T045006Z | Razetime |
| 050 | PHP | 161102T111200Z | Titus |
| 360 | BrainFlak | 160805T135849Z | Wheat Wi |
| 104 | C# | 160805T152418Z | TheLetha |
| 133 | Java | 160805T130131Z | Justin |
| 043 | R | 160219T104801Z | slamball |
| 015 | GNU dc | 160215T123329Z | Toby Spe |
| nan | Haskell | 160215T144821Z | sourtin |
| 022 | Golfscript | 160214T220130Z | Dica |
| 142 | JavaScript ES6 | 160215T042525Z | Patrick |
| 108 | ES6 | 160215T135346Z | Neil |
| 116 | Oracle SQL 11.2 | 160215T124520Z | Jeto |
| 019 | CJam | 160215T100554Z | CJ Denni |
| 046 | Perl 5 | 160215T082858Z | Sake |
| 017 | Pyth | 160214T205722Z | Denker |
| 011 | Jelly | 160215T024242Z | Dennis |
| 044 | Mathematica | 160215T015515Z | LegionMa |
| 033 | Mathematica | 160215T023752Z | njpipeor |
| 035 | Haskell | 160214T231812Z | nimi |
| 013 | Pyth | 160214T213200Z | Jakube |
| 038 | Python 2 | 160214T201120Z | Denker |
| 038 | JavaScript ES6 | 160214T201650Z | Andreas |
Julia 0.6, 27 26 bytes
f(x)=x>9?f(x÷10-x%10*2):x
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!
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.
GCC, x86, No optimization, 30 bytes
f(i){i=i<70?i:f(i/10-i%10*2);}
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.
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}
PowerShell Core, 51 bytes
param($a)for(;$a-gt9){$a=($a-($r=$a%10))/10-$r*2}$a
There is a chance it can claim the bonuses but I'm not entirely sure of how these work so I'll keep my 52 bytes score.
Uiua, 16 bytes
⍢(⌊-×2⊃◿÷10|>70)
Explanation
⍢( | ) While
>70 greater than 70:
⊃◿÷10 separate last digit
-×2 multiply by 2 and subtract
⌊ floor because ÷ returns decimals
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:
- Subtract 7 if necessary, and again if still necessary
- 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.
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!)
Husk, 13 bytes
Ω≤70§-ȯD→d÷10
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
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;
Brain-Flak, 368 360 bytes
([([({})]<(())>)](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>){{}(({}))(<((()()()()()){}<>)>)<>{({}[()])<>(({}()[({})])){{}(<({}({}))>)}{}<>}{}<>([([([(({}<{}><>)<([{}]{})(<((()()()()()){}(<>))>)<>{({}[()])<>(({}()[({}<({}())>)])){{}(<({}({}<({}[()])>))>)}{}<>}{}<>{}{}({}<>)>){}]{})]<(())>)(<>)]){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}({}<>)}{}
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:
([(({})<([{}]{})(<((()()()()()){}(<>))>)<>{({}[()])<>(({}()[({}<({}())>)])){{}(<({}({}<({}[()])>))>)}{}<>}{}<>{}{}({}<>)>){}]{})
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);}
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);
}
}
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
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
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.
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 !
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>`))
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 2²⁵⁷ and 1000000000000000000001, but could use further golfing.
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;
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
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
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)
Pyth, 17 bytes
L?<b70by-/bT*%bT2
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
Jelly, 11 bytes
d⁵Uḅ-2µ>9$¿
How it works
d⁵Uḅ-2µ>9$¿ Main link. Input: n
d⁵ 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.
Mathematica, 47 44 bytes
If[#>70,#0[{1,-2}.{⌊#/10⌋,#~Mod~10}],#]&
Simple recursive approach. Could probably be golfed further.
Mathematica, 33 bytes
#//.a_/;a>70:>⌊a/10⌋-2a~Mod~10&
Test case
%[9999]
(* -3 *)
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.
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)
Python 2, 38 bytes
f=lambda x:f(x/10-x%10*2)if x>70else x
Simple recursive approach. Prints x if its < 70 otherwise applies the divisibility rule and calls itself with the result.
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>
