Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

You are developing some code to generate ID numbers. Policy requires that no ID numbers include the digit sequence 666.

Create a function (or your language's equivalent) which takes a positive integer parameter and returns the next integer that does not include 666 when that integer is expressed in decimal. (60606 is fine, 66600 is not.)

Your code must not use a loop that adds one until it finds a result that fits the rules.

f(1) returns 2.
f(665) returns 667.
f(665999999) returns 667000000 without having looped a million times.
(Following examples added since the question was first posed.)
f(666666666) also returns 667000000.
f(66600) returns 66700.
f(456667) returns 456670.

UPDATE:
Replacing 666 with 667 won't work if there's more than one 666 in the input.

share|improve this question
1  
What about something like 456667? Should that return 456670, or are we only worried about a leading 666? –  Kyle Kanos Apr 29 at 14:18
10  
I think this would be better as code-golf than popularity-contest since there are such straightforward solutions. –  Nate Eldredge Apr 29 at 16:08
10  
@nyuszika7h but the result should be 66700. –  Martin Büttner Apr 29 at 17:07
3  
as a real challenge, there should've also been a requirement to not have "666" anywhere in the code –  DLeh Apr 30 at 19:18
2  
Depending on your regex implementation, you could use '6{3}' to detect 666. –  celtschk May 1 at 19:33

34 Answers 34

Python, no string manipulation

def f(n):
    n += 1
    p = 1
    m = n
    while m:
        if m % 1000 == 666:
            n += p - n % p
        p *= 10
        m /= 10
    return n

Works by finding powers of 10, p, where 666 appears, and adding p - n % p to n which replaces 666xxxxx with 66700000.

share|improve this answer
6  
I like this in that if this was actually a real customer requirement, this implementation is non-hacky, sensible and efficient. –  romkyns Apr 29 at 14:32
    
Will this work with numbers that contain multiple instances of 666? –  supercat Apr 29 at 15:48
    
Yes. The leftmost 666 is the only one that actually matters, and this algorithm fixes that one last. –  cardboard_box Apr 29 at 16:20
19  
@romkyns Post an actual real customer requirement to codegolf to trick other people into doing their work for them? That's evil! (hides) –  billpg Apr 29 at 16:37
3  
For everyone who uses python 3: This code does not work on python 3+, to run this code on python 3 you have to change m /= 10 to m //= 10. If you don't then m will become a float and the condition m % 1000 == 666 will continously be false and other "666" in n are left unchanged. –  Sirac May 4 at 12:36

JavaScript (updated to work with all test cases)

The little-known truth is that there are actually four 6s, but one of the betrayed the others and polymorphed into code form to eradicate them from the world digits of the numbers. Here is that traitorous six:

    x=prompt(''+
  'Enter number');
 alert(      ( (~x[
'ind'+
'exOf']('666')))?(x 
.replace(/666(.*)$/,
function    (mat,g){
return       '667'+g
 ['re'+      'place'
 ](/./g,0)})):((+x+
    1+'').replace(
     666,667)));

Here is an explanation. First, beautify the code and remove useless stuff like ''+'string' and ((code)):

x = prompt('Enter number');
alert(
    ~x['indexOf']('666')
        ?
    x.replace(/666(.*)$/, function(mat,g) {
        return '667' + g['replace'](/./g,0)
    })
        :
    (+x+1+'').replace(666, 667)
);

Convert weird notations (like ~indexOf and ['replace']) into more common ones:

x = prompt('Enter number');
alert(
    x.indexOf('666') > -1
        ?
    x.replace(/666(.*)$/, function(mat, g) {
        return '667' + g.replace(/./g, 0)
    })
        :
    ((parseInt(x) + 1) + '').replace(666, 667)
);

And now simply understand that the algorithm goes like this:

  • If there is already a 666 in the input,

    • replace it with a 667.
    • replace every digit after that with a 0.
  • else,

    • add one to the number.
    • NOTE: we are now guaranteed to have either no 666, a 666 at the end of the string, or a 666 somewhere else that already has zeroes going to the end (think "carrying" when doing "manual" addition).
    • if there's a 666, replace it with a 667.

Old version (doesn't work for 666666666):

    s='Enter number';x
  =prompt(           ''+
 s);x=+x+
(-~![]);
x=(''+x).replace('666',
666+([][         +[]]+[])
[+[]]['l         ength'[
 'repla'+       'ce'](
  / /g,'')]);alert(x)

To understand this, let's first beautify it:

s = 'Enter number';
x = prompt('' + s);
x = +x + (-~![]);
x = ('' + x).replace('666',666+([][+[]]+[])[+[]]['l         ength'['repla'+'ce'](/ /g,'')]);
alert(x);

Now let's remove useless things like '' + string and 'str' + 'ing', remove the unnecessary s variable, and change weirdness like -~![] into 1:

x = prompt('Enter number');
x = +x + 1;
x = ('' + x).replace('666', 666+"undefined"[0]['l         ength'['replace'](/ /g,'')]);
alert(x);

'l ength'['replace'](/ /g,'') is simply "length":

x = prompt('Enter number');
x = +x + 1;
x = ('' + x).replace('666', 666+"undefined"[0].length);
alert(x);

And "undefined"[0] is "u", and "u".length is 1:

x = prompt('Enter number');
x = +x + 1;
x = ('' + x).replace('666', 666 + 1);
alert(x);

Now we're done! It should be pretty easy to understand now.

share|improve this answer
13  
I like your answer but it fails for 666666666 –  Michael Apr 29 at 13:18
3  
@Michael Added new version! Works for 666666666, and the font of the 6 is fancier ;) –  Doorknob Apr 29 at 21:14
1  
Huh - using ~1 for != -1 is pretty cool. –  WChargin Apr 30 at 2:02
    
@WChargin Too bad that doesn't work in LiveScript. I know this isn't code golf but I have a golfed version in my post for fun. –  nyuszika7h Apr 30 at 9:14
    
It does work in LiveScript :). ~a.indexOf('b') generates the correct JS, try it on livescript.net ! –  user1737909 May 3 at 20:51

Applescript

This site doesn't have enough Applescript answers. Lets banish some demons!

property demon : "666"
property trinity : 1

on exorcise above possessed
    set possessed to possessed as text
    set relic to AppleScript's text item delimiters
    set AppleScript's text item delimiters to demon
    set deliverance to possessed's first text item
    if possessed is deliverance then
        set deliverance to possessed + trinity
    else
        set AppleScript's text item delimiters to trinity
        set compellingPower to ¬
            (count of possessed's characters) - ¬
            (count of deliverance's characters) - ¬
            (count of demon's characters)
        set deliverance to ¬
            deliverance & ¬
            demon + trinity & ¬
            last text item of (((10 ^ compellingPower) as integer) as text)
    end if
    set AppleScript's text item delimiters to relic
    return deliverance
end exorcise

log (exorcise above 666)
log (exorcise above 66666666)
log (exorcise above 1266612)
log (exorcise above 1212)

Log output:

(*667*)
(*66700000*)
(*1266700*)
(*1213*)

I'd wanted to get some of the more powerful quotes from The Exorcist into this, but that would have made this posted decidedly NSFW. You can read the IMDB page instead.

share|improve this answer
    
How do you run this without having OS X? –  nyuszika7h Apr 30 at 9:44
    
I think Applescript is pretty much dependent on OSX stackoverflow.com/questions/7642299/… - I'm not aware of any ports to other platforms. OS 9 did have a version of Applescript, though no guarantees that this script would run there. –  DigitalTrauma Apr 30 at 14:23
2  
It would have made the post Not For Safe Work? Dammit, my job isn't dangerous –  Cruncher Apr 30 at 17:39
1  
@Cruncher oops ;-) –  DigitalTrauma Apr 30 at 17:43
1  
+1 for the choice of variable names (and because apple script is cool). –  Floris Apr 30 at 20:50

Perl

You said we must not increment in a loop. I'm not using any mathematical operators at all! Here is a pure regex-substitution approach (no guarantees it's safe for your sanity).

#!/usr/bin/perl

$_ = <>;

s/$/ ~0123456789/;
s/(?=\d)(?:([0-8])(?=.*\1(\d)\d*$)|(?=.*(1)))(?:(9+)(?=.*(~))|)(?!\d)/$2$3$4$5/g;
s/9(?=9*~)(?=.*(0))|~| ~0123456789$/$1/g;
s/(?!^)\G\d|(666)\d/${1}0/g;
s/666/667/g;

print($_)

The first three substitutions increment the number by one. I did solve that problem myself once, but it included a substitution that had to be looped until no more substitutions were made, so I used Andrew Cheong's approach instead.

The fourth substitution turns all digits following a 666 into zeros. The final substitution turns the remaining 666 into a 667.

As a bonus this will work with multiple integers in the input as long as they are separated by non-digit characters.

share|improve this answer

LiveScript

This is bending the rules. You see, you said I must not use a loop that adds one until it finds a correct result. So I subtract minus one instead!

nextId = (id) ->
  while (id + 1).toString!indexOf('666') != -1
    id -= -1
  id + 1

A golfed version in 53 48 45 bytes for fun:

n=(i)->(while~(i+1+'')indexOf(\666)=>i-=-1);i+1

Thanks to user1737909 for helping golf it further.

Tests

Requires Node.js with the LiveScript npm module or a compatible assert library.

assert = require \assert

assert.equal nextId(1), 2
assert.equal nextId(665), 667
assert.equal nextId(665999999), 667000000
assert.equal nextId(66600), 66700
assert.equal nextId(456667), 456670
share|improve this answer
5  
It is going to fail horribly when you get to 665999, as your stack will explode. –  TimWolla Apr 29 at 12:48
9  
Very clever. You should be writing RFCs to spot loopholes like that. –  billpg Apr 29 at 12:59
1  
@TimWolla That's interesting. How did you find that? –  nyuszika7h Apr 29 at 14:52
1  
@nyuszika7h: If you think about it, 666000 through 666999 will all fail... you'll be recursing at least 1000 times. –  Andrew Coonce Apr 29 at 14:58
1  
I don't have a particular reason, I guess. –  nyuszika7h Apr 29 at 16:28

Ruby

This is (I think) the first answer that works for 666666666. (Except the cheaty subtracting -1 answer. ;) )

x = gets.chomp.to_i + 1
p (x..x.to_s.gsub('666', '667').to_i).select{|i| !(i.to_s.index '666') }.min

I'm in a hurry now; explanation will be added later.

Update: much more efficient version (almost constant runtime I believe):

x = gets.chomp
if x.index '666'
    # replace ex. 6661234 with 6670000
    puts x.sub(/666(.*)/){ "667#{"0" * $1.length}" }
else
    # old algorithm (guaranteed to result in
    # 0 or 1 666s now)
    puts (x.to_i+1).to_s.sub(/666/, "667")
end
share|improve this answer
    
Actually, my answer works fine for 666666666. –  isaacg Apr 29 at 13:56
    
The second version throws TypeError: String can't be coerced into Fixnum for 666666666, 66600 and 456667. (Tested on Ruby 1.9.3-p194 (Debian 7.5) and Ruby 2.1.1-p76.) –  nyuszika7h Apr 30 at 9:37
    
@nyu Oops; typo. Fixed –  Doorknob Apr 30 at 11:49
    
Constant runtime is impossible. Even checking if a "666" exists is a linear problem. This is a strictly harder problem than that. –  Cruncher Apr 30 at 17:36

PowerShell

($args[0]+1 -replace '(?<=666.*).','0') -replace '666', '667'
share|improve this answer

J

Finally, a good use for E.!

(({.~ , '667' {.!.'0'~ #@[ - ]) '666'&E. i. 1:) @ ": @ >:

In essence, we find the first position in which the argument has a full 666, and we replace that substring and everything after with 66700000... until the end.

Explained in detail:

  • ":@>: - Increment by one and convert to string.
  • '666'&E. - Make a vector of booleans, true in each place that '666' begins in the string.
  • i.1: - Find the index of the first true in the vector, else return the length of the vector.
  • #@[-] - Length of the string (which is also the length of the vector) minus the result of i..
  • '667'{.!.'0'~ - Take a substring of '667' with a length of that result, padding on the right with '0' if necessary.
  • {.~ - Take a substring with the length of the original result from i..
  • , - Append the two together.

In use:

   f =: (({.~,'667'{.!.'0'~#@[-])'666'&E.i.1:)@":@>:
   f 1              NB. this leaves okay numbers untouched
2
   f 665999999      NB. properly handles multiple increments
667000000
   f 16266366646666 NB. only takes effect at sets of 3 sixes
16266366700000

And since this isn't a code golf, this doesn't have to get golfed to hell with crazy optimizations. Everybody wins!

share|improve this answer

C#

148 137 chars

Was able to shave off a few chars thanks to @recursive

public static int f(int b){b++;var z=new Regex("666\\d*");var q=z.Replace(b+"","667",1);return int.Parse(q.PadRight((b+"").Length,'0'));}

Ungolfed:

public static int f(int b)
{
    b++;
    var z = new Regex("666[\\d]*");
    var q = z.Replace(b+"", "667", 1);
    return Int32.Parse(q.PadRight((b+"").Length, '0')); 
}

Fiddle: http://dotnetfiddle.net/XB83bf

share|improve this answer
1  
The square brackets in your regex are unnecessary, and there are also a lot of syntactically unnecessary spaces. –  recursive Apr 29 at 16:00
    
Oh, and Int32 can be replaced with int. –  recursive Apr 29 at 16:01
    
@recursive You are correct, thanks! –  JakeP Apr 29 at 16:07
    
Note this is a popularity-contest and not code-golf. Having said that if you feel shaving off characters will make your answer more popular, then go for it! –  DigitalTrauma Apr 29 at 18:14
2  
First I have seen of dotnetfiddle.net =) AWESOME! –  CodeBlend Apr 30 at 15:48

Python

def next_id(id_num):
  id_num_p1=str(id_num+1)
  pieces=id_num_p1.split('666')
  if len(pieces)==1:
    return id_num+1
  next_id_str=pieces[0]+'667'+'0'*(len(id_num_p1)-len(pieces[0])-3)
  return int(next_id_str)
share|improve this answer

Perl

$_++;$_.=$/;s:666(.*):667 .'0'x($+[1]-$-[1]):e

Inline code which changes the content inside $_, a pretty standard ideology in perl. Can be used in conjunction with -p flag like this:

$ perl -p % <<< 66666
66700
share|improve this answer

J

No strings, loops or conditionals:

   next =: 3 :'<.(y+1)(+-|~)10^<:666 i:~666,1000|<.(y+1)%10^i.<.10^.>:y'

   next 1
2
   next 665
667
   next 665999999
667000000
   next 666666666
667000000
   next 66600
66700

Similarly to cardboard_box's solution, this separates the number into groups of three digits by dividing by powers of ten. It uses the index of the first occurrence of 666 to round the number up appropriately.

share|improve this answer

Haskell (70 characters)

Here is a simple implementation in Haskell.

import Data.List
import Data.Char

nextid :: Integer -> Integer
nextid = foldl' ((+).(*10)) 0 . purge . map digitToInt . show . (+1)
  where purge (6:6:6:xs) = 6 : 6 : 7 : map (const 0) xs
        purge (x:xs)     = fromIntegral x : purge xs
        purge []         = []
  • Firstly, it uses map digitToInt . show to convert a possibly evil ID to a list of digits.
  • Next, purge matches the evil pattern and replaces it with its good equivalent.
  • Finally, foldl' ((+).(*10)) 0 reduces the list of digits to one Integer.

Let's see if it works!

ghci> nextid 1
2
ghci> nextid 665
667
ghci> nextid 665999999
667000000
ghci> nextid 666666666
667000000
ghci> nextid 66600
66700
ghci> nextid 456667
456670
ghci> nextid 6660239486660239466
6670000000000000000

Looks good. And just for fun a golfed version.

f=read.w.show.(+1);w('6':'6':'6':t)="667"++(t>>"0");w(h:t)=h:w t;w t=t
share|improve this answer

Java

Isn't it enough to do this?

private static int nextId(int currentId) {
    String currentIdStr = String.valueOf(currentId);
    return currentIdStr.contains("666") ? Integer.parseInt(currentIdStr.replace("666", "667")) : ++currentId;
}
share|improve this answer
    
Close, but that should be String.valueOf(currentId + 1). –  nyuszika7h Apr 29 at 12:10
    
Oh right, I forgot that +1 thingy! :D –  Valentin Grégoire Apr 29 at 12:12
    
That conditional is useless; the original solution slightly modified per my suggestion will work too: return Integer.parseInt(String.valueOf(currentId + 1).replace("666", "667")); –  nyuszika7h Apr 29 at 12:23
1  
Not true... 66600 would be returned as 66701, which is 1 too high. –  Valentin Grégoire Apr 29 at 12:39

R

Replacing 666 with 667 works.

f <- function(x) {
  x <- as.integer(x + 1)
  if (grepl(666, x)) {
    k <- regexpr(666, x)
    cat(substring(x, 1, k + 1), 7, rep(0, nchar(x) - k - 2), sep = "")
  }
  else cat(x)
}

Results

> f(1)
2
> f(665)
667
> f(665999999)
667000000
> f(666666666)
667000000
> f(66600)
66700
> f(126660)
126670
> f(126661)
126670
> f(666666666)
667000000
share|improve this answer
awk '{i=index(++$0,"666")}
      i{a=substr($0,1,i-1)
       b=substr($0,i+3)
       gsub(/./,0,b)
       $0=a"667"b}
      1
' <<_INPUT_
1
665
665999999
666666666
66600
_INPUT_

gives

2
667
667000000
667000000
66700
share|improve this answer
1  
which doesn't seem to be correct answers. 665 should give 667, 66600 should give 66700 etc –  ace Apr 29 at 14:25
1  
Your results contain a lot of "666" substrings. –  Glenn Randers-Pehrson Apr 29 at 14:28
    
That's embarrassing. I fixed the 2(!) fence-post-errors I made because I forgot that awk indexes strings 1-based. –  sg-lecram Apr 29 at 15:56
    
@Cruncher As explicitly stated in the question, f(665) returns 667 as it is asking for "the next integer that does not include 666" –  ace Apr 30 at 17:48

3 Different JavaScript answers:

1. JavaScript (ECMAScript 6)

f=x=>(a=b=c=0,[c?'0':a+(a=b)+(b=i)==666?(c='7'):i for(i of ""+(x+1))].join('')*1)

Converts the number to a string then iterates over each character until it finds 666 then it changes that last 6 to a 7 and outputs 0 for all following characters.

2. JavaScript (ECMAScript 6 Draft)

Recursive function without string manipulation:

g=(x,y=x+1,p=1)=>y?g(y%1e3==666?y*p+p:y>x?y:x,y/10|0,p*10):x

Or more verbosely:

function g(x,y=x+1,p=1)
{
  if ( y == 0 )
    return x;
  else if ( y % 1000 == 666 )
    return g( y*p+p, Math.floor(y/10), p*10 );
  else
    return g( Math.max(y, x), Math.floor(y/10), p*10 );
}

Tests:

g(5) // 6
g(65) // 66
g(665) // 667
g(66599) // 66700
g(66666) // 66700
g(6656665665) // 6656670000

3. JavaScript

Using regular expressions:

function h(x)(""+(x+1)).replace( /^(.*?)(666)(.*)$/, function(a,b,c,d)(b+667+d.replace(/./g,0)) )*1

Or (the same but using ECMAScript 6)

h=x=>(""+(x+1)).replace(/^(.*?)(666)(.*)$/,(a,b,c,d)=>b+667+d.replace(/./g,0))*1
share|improve this answer
    
With your first version, if you enter 6 septillion, 666 sextillion you get a return value of 6.667 so technically it's still there. Don't think it can be helped though. –  Spedwards May 4 at 14:01
    
1e20 is about the largest order of magnitude that JavaScript (at least in FireFox) will print as an integer without resorting to scientific notation. –  MT0 May 4 at 16:24

Python:

def f(b):
    b = `b+1`
    while '666' in b: b = b.replace('666','667',1)
    return int(b)

Or:

 f=lambda b:int(`b+1`.replace('666','667'))
share|improve this answer
    
I don't see how that works. Wouldn't that turn 666666 into 667667 instead of 667000? –  Martin Büttner Apr 29 at 16:35
    
@m.buettner Good point, I think I already have an solution. –  ɐɔıʇǝɥʇuʎs Apr 29 at 16:56

Java

public static int f(int i) {
    i++;
    i += findAdjustment(i);
    return i;
}

private static int findAdjustment(int i) {
    if (i < 666) {
        return 0;
    }
    int adjustment = findAdjustment(i / 10);
    if (adjustment != 0) {
        // Leftmost 666 found, fix adjustment by current last digit
        return adjustment * 10 - i % 10;
    } else if (i % 1000 == 666) {
        return 1; // This is leftmost 666, need to be corrected by 1
    } else {
        return 0; // no adjustment needed
    }
}

Using recursive function to find leftmost 666 and calculation how much to adjust the number when popping the call stack again.

share|improve this answer
    
I don't think this code is correct. What result does it give for input 666666666? –  algorithmshark Apr 29 at 13:09
    
You are right, didn't realise that the input already could contain Evil numbers. So f(666666666) -> 667667667? –  Roger Lindsjö Apr 29 at 13:28
    
f(666666666) -> 667000000 –  djhurio Apr 29 at 13:34
    
@djhurio Seems I can not generate tests for edge cases today. Believe I have it fixed now, but the code is not so short any more. –  Roger Lindsjö Apr 29 at 14:01
1  
@RogerLindsjö This is a popularity-contest, not a code-golf. –  nyuszika7h Apr 29 at 18:39

Batch

Simple iterated string manipulation.

@echo off

setLocal enableDelayedExpansion
set /a inp=%1+1
for /f usebackq %%a in (`powershell "&{'%inp%'.length-1}"`) do (
    set a len=%%a-2
    set chars=%%a
)

for /l %%b in (0, 1, %len%) do (
    if "!inp:~%%b,3!"=="666" (
        set inp=!inp:~0,%%b!667
        set /a a=%%b+3
        for /l %%c in (!a!, 1, %chars%) do set inp=!inp!0
        goto :break
    )
)

:break

echo %inp%

It starts at the first three characters of the number (as a string), and works its way to the end until it finds 666, it then replaces that 666 with 667, and loops to the length of the string adding zeros.

The test cases all produce the correct results.

share|improve this answer

perl, 45 bytes

A single regex with the /e flag does all the work here:

$_=<>+1;s/666(.*)$/"667".0 x length$1/e;print
share|improve this answer

SQL

To be precise, SQL Server 2012 Transact-SQL.

create function dbo.GoodIntegers( @i bigint )
returns bigint
as begin
    declare @s varchar(20) = cast( @i+1 as varchar(20) ) ;
    declare @badindex int = charindex( '666', @s ) ;
    declare @rv bigint  = cast ( 
        iif( @badindex = 0 ,
            @s ,
            concat( left( @s, @badindex - 1 ), '667', replicate( '0', len( @s ) - @badindex - 2 ) )
        ) as bigint 
    ) ;
    return @rv ;
end ; -- function dbo.GoodIntegers
share|improve this answer

Python

import re
def exorcise(number):
    number = str(number+1)
    i = re.compile("^(\d*?)(666)(\d*)$")
    if re.match(i,number):
        n = re.match(i,number).groups()
        return int(n[0]+"667"+"".join(["0"*len(n[2])]))
    return int(number)
share|improve this answer

Julia

function f(x::Int)
    y = string(x+1)
    n = length(y)
    z = string(^("0",n))
    ~ismatch(r"6{3}", y) ?
    int(y) :
    while ismatch(r"6{3}",y)
        m = match(r"6{3}", y)
        y = string(y[1:m.offset+1], '7', z[m.offset+3:n])
    end
    int(y)
end

REPL results

julia> f(1)
2

julia> f(665)
667

julia> f(665999999)
667000000

julia> f(666666666)
667000000

julia> f(66600)
66700

julia> f(456667) 
456670
share|improve this answer

C#

Am I doing it right

static int F(int n)
{
    n++;

    int a = 666;
    int b = 1;

    while (n >= b)
    {
        if (((n - a) / b) % 1000 == 0)
        {
            n += b;
        }

        a *= 10;
        b *= 10;
    }

    return n;
}
share|improve this answer

vba

Function f(num As Long) As Long
Dim SixPos As Long
Dim s As String
s = CStr(num)
SixPos = InStr(s, "666")
If SixPos = 0 Then
    s = CStr(num + 1)
    SixPos = InStr(s, "666")
End If
If SixPos Then
    Mid(s, SixPos + 2, 1) = "7"
    If Len(s) > SixPos + 2 Then
        Mid(s, SixPos + 3, Len(s) - SixPos + 3) = String$(Len(s) - SixPos + 3, "0")
    End If
End If

f = CLng(s)

End Function

In action:

Sub demo()
Debug.Print f(1) 'returns 2.
Debug.Print f(665) 'returns 667.
Debug.Print f(665999999) 'returns 667000000 without having looped a million times.
'(Following examples added since the question was first posed.)
Debug.Print f(666666666) 'also returns 667000000.
Debug.Print f(66600) 'returns 66700.
Debug.Print f(456667) 'returns 456670.
End Sub

result:

2 
667 
667000000 
667000000 
66700 
456670 
share|improve this answer

C++

I know this isn't code-golf, but (a) some people have suggested that it is a good golf challenge, and (b) this is my first challenge/golf answer, I thought it would be fun, and if I do this here I don't get shown up in an actual golf challenge for being a terrible golfer. X)

Basically, replaced '666' with '667' works if you do it for the first instance in the number and then write out trailing 0s.

Golfed (175 155 chars):

#include<sstream>
int f(int x){std::stringstream s,o;s<<++x;x=0;for(char c=s.get();!s.eof();c=s.get())o<<((x+=c=='6')++==3?'7':--x>3?'0':c);o>>x;return x;}

Ungolfed:

#include<sstream>
int f(int x){
    std::stringstream s,o;
    s<<++x;    // Increment to next int.
    x=0;       // Reusing this to count 6s
    for(char c=s.get();!s.eof();c=s.get()){    // For each digit
        if (c=='6'){
           ++x;    // Count sixes...
        }
        if(x==3) {  // Devil's number!
            c='7'; // Output 7 here.
            ++x;   // Increment once more.
        } else if (x > 3) {
            c='0';    // Already replaced 666 with 667, so write out 0s
        }
        o<<c;   // Append digit
    }
    o>>x; // Get int
    return x;
}
share|improve this answer
    
I think you don't need x+=c=='6'?1:0, you can get away with x+=c=='6'. Haven't tried it, though. –  nyuszika7h May 1 at 15:29
    
Also, you left out the std:: before stringstream. It doesn't compile without that. –  nyuszika7h May 1 at 15:32
    
Added std::, thanks for that @nyuszika7h. I made the mistake of using an IDE that autogenerated 'using namespace std;' to test it in. -_- I will try the x+=c=='6' reduction, as well as looking at doing this with int digits rather than sstream chars... –  mike32 May 1 at 18:27

Ruby

n=(gets.chomp.to_i+1).to_s
i=n.index("666")
if i!=nil
    n=n[0..i+1]+"7"+"0"*(n.length-i-3)
end
puts n
share|improve this answer

perl, 36 just a sub, no bytes

A shorter version than my last solution, using a mix of arithmetic and regex ops.

sub{($_[0]+1)=~s/666(.*)/667$1/r-$1}
share|improve this answer
    
print+(<>+1)=~s/666(.*)/667$1/r-$1 (saved you a byte)(two more if you use say) - although the request was for a function so remove print+ and use sub{ ... } –  Altreus Apr 30 at 12:06

C

#include <stdlib.h>
#include <stdio.h>

int next(int a)
{
    for(int b=a+1,c=0,d=0; b>665 ;b/=10, c++)
        if(b%1000==666) {d=c; a=b;}

    a++;
    while(d --> 0) a*=10;

    return a;
}

void main(int a, char *v[])
{
    int c = a>1?atoi(v[1]):0;

    printf("%d\n",next(c));
}

OK - no bounds checking and far too much whitespace but it's not golf. Also a fun bit of formatting in "while (d --> 0)".

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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