Avoid the evil integers!

53

10

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.

billpg

Posted 2014-04-29T11:36:44.393

Reputation: 1 995

Question was closed 2016-04-25T14:25:16.287

1What about something like 456667? Should that return 456670, or are we only worried about a leading 666? – Kyle Kanos – 2014-04-29T14:18:00.610

1@KyleKanos - Yes. The returned value can't contain 666 anywhere. I'll add a few more examples including yours. – billpg – 2014-04-29T15:50:58.370

11I think this would be better as [tag:code-golf] than [tag:popularity-contest] since there are such straightforward solutions. – Nate Eldredge – 2014-04-29T16:08:30.273

1Replacing 666 with 667 won't work if there's more than one 666 in the input. I don't see why not, as long as all instances are replaced left-to-right, e.g. 66666 -> 66766. – nyuszika7h – 2014-04-29T16:56:38.527

10@nyuszika7h but the result should be 66700. – Martin Ender – 2014-04-29T17:07:02.107

1@m.buettner Oh, right. – nyuszika7h – 2014-04-29T17:08:12.373

What should 6660666 evaluate to? 6670000? – Greenstone Walker – 2014-04-30T02:40:50.220

@GreenstoneWalker Yes, I think thats right. 6670000 is the lowest number greater than 6660666 that has no consecutive 666 digits – Digital Trauma – 2014-04-30T03:55:04.837

Actually you just add 1 once, then search first occurrence of "666", replace it with "667" and substitute all digits after that with 0-s; – Cthulhu – 2014-04-30T06:40:10.340

you can replace "666" with "667" and add zeros, which I did in the Julia example – Milktrader – 2014-04-30T13:04:43.790

3as a real challenge, there should've also been a requirement to not have "666" anywhere in the code – DLeh – 2014-04-30T19:18:46.757

1@DLeh 665 + 1 – Doorknob – 2014-05-01T00:13:36.717

1right, try using 665 + 1 in regex. – DLeh – 2014-05-01T10:52:17.250

@DLeh Highest voted answer doesn't use regex. But in any case "regexbefore" + "66" + "6" + "regexafter" still works. Or str(665+1) – Cruncher – 2014-05-01T14:41:25.260

2Depending on your regex implementation, you could use '6{3}' to detect 666. – celtschk – 2014-05-01T19:33:36.750

You want to make 'Your code must not use a loop that adds one until it finds a result that fits the rules' more bulletproof. I could simply add 3 (you never said the numbers had to be consecutive). I could add 2 and subtract 1. I could add 10 and count down, rejecting the first 8 numbers. etc. I could add 1.6 (float) and convert back to integer. This alone (workaround 'adding one') would make a lawyerly code-golf puzzle in itself... – smci – 2014-05-01T20:47:24.663

1As the evil integers should be avoided, shouldn't that also apply to source code + computer memory? That would make the challenge significantly harder. – Simon Forsberg – 2014-05-02T12:53:46.820

Your specification looks weird. I wouldn’t call something an ID unless it were unique. And uniqueness (possibly asking that ID are increasing wrt ales, and that they are always as small as possible) seems to me like a more interesting challenge. Not that I would compete. – Édouard – 2014-05-04T10:38:49.743

Answers

53

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.

cardboard_box

Posted 2014-04-29T11:36:44.393

Reputation: 5 150

6I like this in that if this was actually a real customer requirement, this implementation is non-hacky, sensible and efficient. – RomanSt – 2014-04-29T14:32:01.283

Will this work with numbers that contain multiple instances of 666? – supercat – 2014-04-29T15:48:24.223

Yes. The leftmost 666 is the only one that actually matters, and this algorithm fixes that one last. – cardboard_box – 2014-04-29T16:20:05.007

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 – 2014-04-29T16:37:09.440

3For 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 – 2014-05-04T12:36:33.660

50

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.

Doorknob

Posted 2014-04-29T11:36:44.393

Reputation: 68 138

13I like your answer but it fails for 666666666 – Michael M. – 2014-04-29T13:18:24.573

3@Michael Added new version! Works for 666666666, and the font of the 6 is fancier ;) – Doorknob – 2014-04-29T21:14:37.513

1Huh - using ~1 for != -1 is pretty cool. – wchargin – 2014-04-30T02:02:46.850

@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 – 2014-04-30T09:14:51.577

It does work in LiveScript :). ~a.indexOf('b') generates the correct JS, try it on livescript.net ! – Ven – 2014-05-03T20:51:13.510

20

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.

Digital Trauma

Posted 2014-04-29T11:36:44.393

Reputation: 64 644

How do you run this without having OS X? – nyuszika7h – 2014-04-30T09:44:28.277

I think Applescript is pretty much dependent on OSX http://stackoverflow.com/questions/7642299/what-are-the-alternatives-to-applescript-in-linux-how-are-they-different - 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.

– Digital Trauma – 2014-04-30T14:23:36.933

2It would have made the post Not For Safe Work? Dammit, my job isn't dangerous – Cruncher – 2014-04-30T17:39:43.540

1@Cruncher oops ;-) – Digital Trauma – 2014-04-30T17:43:50.993

1+1 for the choice of variable names (and because apple script is cool). – Floris – 2014-04-30T20:50:08.583

@DigitalTrauma — AppleScript existed way before Mac OS X. – Nicolas Barbulesco – 2014-05-07T22:32:07.367

@NicolasBarbulesco Yep. I think my previous comment alluded to that.

– Digital Trauma – 2014-05-08T16:28:17.357

15

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.

Martin Ender

Posted 2014-04-29T11:36:44.393

Reputation: 184 808

8

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

nyuszika7h

Posted 2014-04-29T11:36:44.393

Reputation: 1 624

I think this is invalid since the question says f(665999999) returns 667000000 without having looped a million times. – mbomb007 – 2015-05-04T16:48:52.373

5It is going to fail horribly when you get to 665999, as your stack will explode. – TimWolla – 2014-04-29T12:48:51.360

9Very clever. You should be writing RFCs to spot loopholes like that. – billpg – 2014-04-29T12:59:46.597

1@TimWolla That's interesting. How did you find that? – nyuszika7h – 2014-04-29T14:52:59.967

1@nyuszika7h: If you think about it, 666000 through 666999 will all fail... you'll be recursing at least 1000 times. – Andrew Coonce – 2014-04-29T14:58:51.717

Why would you use recursion instead of looping here? – ɐɔıʇǝɥʇuʎs – 2014-04-29T15:37:30.903

1I don't have a particular reason, I guess. – nyuszika7h – 2014-04-29T16:28:39.760

My thought when I read the restriction on looping was to do recursion instead. (The letter of the rules vs. the spirit of the rules.) – TecBrat – 2014-05-02T15:35:04.187

1you can use (a)b instead of (a).b and => instead of then – Ven – 2014-05-03T21:38:10.517

You can also use ~ instead of !=-1 – Ven – 2014-05-04T13:18:18.843

1@user1737909 That doesn't work in LiveScript, it compiles into while (bind$((i + 1 + '').indexOf('666'), 1)), which looks like an infinite loop to me; it hangs on n 1. – nyuszika7h – 2014-05-04T13:25:48.793

1Definitely works for LiveScript : while~(i+1+'')indexOf(\666)=> compiles to the correct javascript. I guess you LS was while(i+1+'')indexOf(\666)~1 which is indeed incorrect (infix ~ is bind operator) – Ven – 2014-05-04T14:04:29.580

6

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

Doorknob

Posted 2014-04-29T11:36:44.393

Reputation: 68 138

Actually, my answer works fine for 666666666. – isaacg – 2014-04-29T13:56:14.447

Constant runtime is impossible. Even checking if a "666" exists is a linear problem. This is a strictly harder problem than that. – Cruncher – 2014-04-30T17:36:33.243

4

PowerShell

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

Rynant

Posted 2014-04-29T11:36:44.393

Reputation: 2 353

4

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!

algorithmshark

Posted 2014-04-29T11:36:44.393

Reputation: 8 144

3

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

Trying

Posted 2014-04-29T11:36:44.393

Reputation: 269

1The square brackets in your regex are unnecessary, and there are also a lot of syntactically unnecessary spaces. – recursive – 2014-04-29T16:00:52.283

Oh, and Int32 can be replaced with int. – recursive – 2014-04-29T16:01:42.187

@recursive You are correct, thanks! – Trying – 2014-04-29T16:07:36.117

Note this is a [tag:popularity-contest] and not [tag:code-golf]. Having said that if you feel shaving off characters will make your answer more popular, then go for it! – Digital Trauma – 2014-04-29T18:14:24.630

2First I have seen of dotnetfiddle.net =) AWESOME! – Coops – 2014-04-30T15:48:41.770

I'm not sure you need the "public static " on the function. The question says that you need to make a function, not one that's publicly accessible. There exists a context in which the function works. – Cruncher – 2014-04-30T17:43:45.190

2

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)

isaacg

Posted 2014-04-29T11:36:44.393

Reputation: 39 268

2

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

mniip

Posted 2014-04-29T11:36:44.393

Reputation: 9 396

2

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.

grc

Posted 2014-04-29T11:36:44.393

Reputation: 18 565

2

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

Piotr Miś

Posted 2014-04-29T11:36:44.393

Reputation: 121

1

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;
}

Valentin Grégoire

Posted 2014-04-29T11:36:44.393

Reputation: 121

Close, but that should be String.valueOf(currentId + 1). – nyuszika7h – 2014-04-29T12:10:08.813

Oh right, I forgot that +1 thingy! :D – Valentin Grégoire – 2014-04-29T12:12:06.413

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 – 2014-04-29T12:23:16.513

1Not true... 66600 would be returned as 66701, which is 1 too high. – Valentin Grégoire – 2014-04-29T12:39:29.690

1

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

djhurio

Posted 2014-04-29T11:36:44.393

Reputation: 1 113

1

AWK

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

edit: 2nd solution

awk -F666 -vOFS=667 '{++$0;$1=$1}
    NF-1{for(gsub(/./,0,$2);NF>2;--NF){$2=$2 0 0 0
               for(i=length($NF);i;--i)$2=$2 0}}1
' <<_INPUT_
1
665
665999999
666666666
66600
1236661
_INPUT_

yields

2
667
667000000
667000000
66700
1236670

mschilli

Posted 2014-04-29T11:36:44.393

Reputation: 221

I added a 2nd way that is a) more awkish and b) minimizes the use of string functions. – mschilli – 2015-05-04T07:25:24.693

1which doesn't seem to be correct answers. 665 should give 667, 66600 should give 66700 etc – user12205 – 2014-04-29T14:25:50.097

1Your results contain a lot of "666" substrings. – Glenn Randers-Pehrson – 2014-04-29T14:28:43.337

That's embarrassing. I fixed the 2(!) fence-post-errors I made because I forgot that awk indexes strings 1-based. – mschilli – 2014-04-29T15:56:29.893

@Cruncher As explicitly stated in the question, f(665) returns 667 as it is asking for "the next integer that does not include 666" – user12205 – 2014-04-30T17:48:33.097

1

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

MT0

Posted 2014-04-29T11:36:44.393

Reputation: 3 373

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 – 2014-05-04T14:01:31.610

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 – 2014-05-04T16:24:35.013

0

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.

Roger Lindsjö

Posted 2014-04-29T11:36:44.393

Reputation: 101

I don't think this code is correct. What result does it give for input 666666666? – algorithmshark – 2014-04-29T13:09:36.327

You are right, didn't realise that the input already could contain Evil numbers. So f(666666666) -> 667667667? – Roger Lindsjö – 2014-04-29T13:28:42.773

f(666666666) -> 667000000 – djhurio – 2014-04-29T13:34:36.317

@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ö – 2014-04-29T14:01:38.810

1@RogerLindsjö This is a popularity-contest, not a code-golf. – nyuszika7h – 2014-04-29T18:39:27.027

0

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'))

ɐɔıʇǝɥʇuʎs

Posted 2014-04-29T11:36:44.393

Reputation: 4 449

I don't see how that works. Wouldn't that turn 666666 into 667667 instead of 667000? – Martin Ender – 2014-04-29T16:35:43.543

@m.buettner Good point, I think I already have an solution. – ɐɔıʇǝɥʇuʎs – 2014-04-29T16:56:13.877

0

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.

unclemeat

Posted 2014-04-29T11:36:44.393

Reputation: 2 302

0

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)

Οurous

Posted 2014-04-29T11:36:44.393

Reputation: 7 916

0

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

skibrianski

Posted 2014-04-29T11:36:44.393

Reputation: 1 197

0

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}

skibrianski

Posted 2014-04-29T11:36:44.393

Reputation: 1 197

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 – 2014-04-30T12:06:02.967

0

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

Greenstone Walker

Posted 2014-04-29T11:36:44.393

Reputation: 101

0

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

Milktrader

Posted 2014-04-29T11:36:44.393

Reputation: 101

0

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;
}

toplel32

Posted 2014-04-29T11:36:44.393

Reputation: 101

0

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 

SeanC

Posted 2014-04-29T11:36:44.393

Reputation: 1 117

0

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)".

Alchymist

Posted 2014-04-29T11:36:44.393

Reputation: 544

0

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;
}

mike32

Posted 2014-04-29T11:36:44.393

Reputation: 171

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 – 2014-05-01T15:29:06.420

Also, you left out the std:: before stringstream. It doesn't compile without that. – nyuszika7h – 2014-05-01T15:32:27.480

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 – 2014-05-01T18:27:50.337

0

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

yourface

Posted 2014-04-29T11:36:44.393

Reputation: 11

0

PHP, 115 characters

<?php
function n($n){$p=strpos(++$n,'666');return($p>=0?substr($n,0,$p). 667 .str_repeat(0,-strlen($n)+$p+3):$n);}
?>

ungolfed:

<?php    
function n($n)
{
    $p = strpos(++$n, '666');

    return($p >= 0
    ? 
        substr($n, 0, $p) . 667 . str_repeat(0, -strlen($n) + $p + 3)
    :
        $n
    );
}
?>

Leo Pflug

Posted 2014-04-29T11:36:44.393

Reputation: 185

0

Javascript (E6) 47 64

Even if it's not golf

Assuming positive 32 bit integers. NB +a is string concat, -a is numeric sub

F=x=>-(~x+'').replace(/666(.*)/,(s,a)=>667+a-a)

Usage

;[ F(6666), F(1), F(665), F(665999999), F(666666666), F(66600), F(456667) ]

[6670, 2, 667, 667000000, 667000000, 66700, 456670]

edc65

Posted 2014-04-29T11:36:44.393

Reputation: 31 086

-2

PHP

echo preg_match('/666/', $n+1)?preg_replace('/666/', '667', $n+1):$n+1;

kuldeep.kamboj

Posted 2014-04-29T11:36:44.393

Reputation: 625

5Given 123666123, won't this produce 123667123? It should produce 123667000 for that input. – RomanSt – 2014-04-29T14:35:06.880