11
\$\begingroup\$

Given a string containing decimal numbers:

teststring134this 123test string54 100

increment every number in this string by one to give the new string

teststring135this 124test string55 101.

The string can be provided as:

  • a command line argument
  • STDIN
  • a hard-coded variable or function argument

Cover all possible positions for a number:

  • as a prefix for a word; 123test124test
  • as a suffix for a word; test123test124
  • inside a word; te123stte124st
  • alone test 123 testtest 124 test

Here's a non-golfed solution in Python:

NUMBERS = '0123456789'

def increment(s):
    out = ''

    number = ''
    for c in s:
        if c in NUMBERS:
            number += c
        else:
            if number != '':
                out += str(int(number) + 1)
                number = ''
            out += c

    if number != '':
        out += str(int(number) + 1)
        number = ''

    return out


print "\"%s\"" % (increment('teststring134this 123test string54 100'))

This is a code-golf question, shortest code wins.

\$\endgroup\$
  • 5
    \$\begingroup\$ Fun fact: this can be done with 3 pure regex substitutions (no callbacks) stackoverflow.com/questions/12941362/… (that wouldn't be the golfiest way though) \$\endgroup\$ – Martin Ender Sep 21 '14 at 11:19
  • 4
    \$\begingroup\$ You specified input but not output. From your input spec I assume both STDOUT and and return value are fine. But can we also store the result in a hardcoded variable (just as we can take input from it)? \$\endgroup\$ – Martin Ender Sep 21 '14 at 11:23
  • 1
    \$\begingroup\$ What about carrying? What happens to 999? \$\endgroup\$ – fluffy Sep 21 '14 at 17:13
  • 3
    \$\begingroup\$ possible duplicate of Multiply all numbers in a string \$\endgroup\$ – Digital Trauma Sep 21 '14 at 18:52
  • 7
    \$\begingroup\$ What about negative numbers? What about numbers with a decimal point? What about numbers with a decimal point and nothing before it (except perhaps for a minus sign)? \$\endgroup\$ – Peter Taylor Sep 21 '14 at 20:45

26 Answers 26

23
\$\begingroup\$

Perl, 14 bytes

s/\d+/$&+1/ge

Requires the -p switch, which I have counted as one byte.

Example run

$ perl -p <(echo 's/\d+/$&+1/ge') <<< 'teststring134this 123test string54 100'
teststring135this 124test string55 101
\$\endgroup\$
12
\$\begingroup\$

Ruby, 30 24 bytes

$><<s.gsub(/\d+/,&:next)

Expects the input to be stored in s.

\$\endgroup\$
  • 3
    \$\begingroup\$ Couldn't $1.next be used in the block? \$\endgroup\$ – August Sep 21 '14 at 12:29
  • \$\begingroup\$ @August nice, thanks! I didn't know next was that sophisticated. \$\endgroup\$ – Martin Ender Sep 21 '14 at 12:34
11
\$\begingroup\$

Vim - 13 keystrokes

0qqqqq^Al@qq@q

Expects the input to be the current line.

Or for finitely many numbers (e.g. 999) in 8 + ceil(log(n)) keystrokes:

0qq^Alq999@q
\$\endgroup\$
  • \$\begingroup\$ I can't seem to make this work.... (I am using vim 7.0.237) \$\endgroup\$ – Jerry Jeremiah Nov 11 '16 at 2:24
10
\$\begingroup\$

JavaScript (ES6) - 28

H=k=>k.replace(/\d+/g,k=>++k)

Run by using H("test 123 234t").

\$\endgroup\$
  • 1
    \$\begingroup\$ You can take out the H= and just have it be an anonymous function. \$\endgroup\$ – Mama Fun Roll Nov 10 '16 at 14:29
8
\$\begingroup\$

Perl, 23

Assumes the input string is assigned to $_

s/\d+/@{[$&+1]}/g;print
\$\endgroup\$
8
\$\begingroup\$

Python 2 - 59

Supply the string as the variable n

import re;print re.sub('\d+',lambda x:`int(x.group())+1`,n)
\$\endgroup\$
6
\$\begingroup\$

C99 - 86 (GCC 4.9.0 and Visual C++ 2013)

Edit: Both GCC 4.9.0 (with -std=c99) and Visual C++ 2013 successfully build (with warnings) the same code without the includes. I didn't know you could do that! Thanks for the hint.

Edit: It didn't even occur to me that I should write it to the screen on the fly instead of creating the string and then printing it. That makes a huge difference. Thanks Dennis!

This is using a hard coded string but the contents of the string are not counted towards the total (the ="" is counted).

main(i){for(char*q,*s="test123test999test-1test";i=strtol(s,&q,0),*s;q>s?printf("%d",i+1,s=q):putchar(*s++));}

Basically it runs through the string one character at a time checking each to see if it is an integer. If it is then it increments the integer and writes it to the output otherwise it copies the current character to the output.

This leaks the hardcoded string because it increments s.

\$\endgroup\$
  • 1
    \$\begingroup\$ I'm sure you can get rid of some of the includes and it will still compile fine with gcc. \$\endgroup\$ – Martin Ender Sep 21 '14 at 11:58
  • 1
    \$\begingroup\$ Will this work with a string containing e.g. 99? \$\endgroup\$ – anatolyg Sep 21 '14 at 16:32
  • \$\begingroup\$ @MartinBüttner: Yes but then it wouldn't be valid C, just something that happens to work on gcc. \$\endgroup\$ – R.. Sep 21 '14 at 18:46
  • \$\begingroup\$ @R.. That's generally allowed on PPCG though. I've seen (and subsequently done) it quite often without anyone complaining. \$\endgroup\$ – Martin Ender Sep 21 '14 at 19:58
  • \$\begingroup\$ Yes, and it's a general peeve of mine. The language should be listed as "GCC" or "C on [particular arch/etc. the hacks happen to work on]" or similar, rather than C, if it's not actually valid C. :-) \$\endgroup\$ – R.. Sep 21 '14 at 20:01
5
\$\begingroup\$

J (20)

Expects the input to be stored in the variable a.

'\d+'>:&.".rxapply a

Test:

   a=:'teststring134this 123test string54 100'
   '\d+'>:&.".rxapply a
teststring135this 124test string55 101
\$\endgroup\$
5
\$\begingroup\$

(f?)lex (39)

File inc.l:

%%
[0-9]+ printf("%d",atoi(yytext)+1);

Compile:

$ flex inc.l
$ gcc lex.yy.c -o inc -lfl

Run:

$ echo 'teststring134this 123test string54 100' | ./inc
teststring135this 124test string55 101

$ i='(-: 2 empty bottles of beer :-)'
$ tty=$(tty)
$ for n in {2..5} ; do i=$(./inc<<<$i|tee $tty) ; done
(-: 3 empty bottles of beer :-)
(-: 4 empty bottles of beer :-)
(-: 5 empty bottles of beer :-)
(-: 6 empty bottles of beer :-)

I did not test this with the original lex. Comments are welcome.

\$\endgroup\$
  • 1
    \$\begingroup\$ You can drop the trailing %% since this is no user code: flex.sourceforge.net/manual/… \$\endgroup\$ – Josh Sep 24 '14 at 19:41
  • \$\begingroup\$ Hey... yes! I tried but without trailing newline and that failed... then I didn't try to add the final newline... ;-) ...stupid mistake! \$\endgroup\$ – user19214 Sep 24 '14 at 20:54
3
\$\begingroup\$

Emacs - 20 characters

C-M-% [0-9]+ RET \,(1+ \#0) RET !

Requires text to be processed to be present in the current buffer. I counted C-M-% as one character here since it can be entered with one keystroke when holding down three modifiers.

\$\endgroup\$
3
\$\begingroup\$

GNU sed, 304 (including 1 for -r flag)

I close-voted this question as a possible duplicate, but this is perhaps contrary to that because this answer can't be trivially changed to work there. By far the longest answer though.

Inspired by this example from the sed documentation, though it needed some work to handle multiple numbers in a string:

:d
s/9([^0-9]+|$)/_\1/g
td
s/8(_*)([^0-9]+|$)/9\1\2/g
s/7(_*)([^0-9]+|$)/8\1\2/g
s/6(_*)([^0-9]+|$)/7\1\2/g
s/5(_*)([^0-9]+|$)/6\1\2/g
s/4(_*)([^0-9]+|$)/5\1\2/g
s/3(_*)([^0-9]+|$)/4\1\2/g
s/2(_*)([^0-9]+|$)/3\1\2/g
s/1(_*)([^0-9]+|$)/2\1\2/g
s/0(_*)([^0-9]+|$)/1\1\2/g
s/(^|[^0-9_]+)(_+)/\11\2/g
y/_/0/

Output:

$ for s in "teststring134this 123test string54 100" "123test" "test123" "te123st" "test 123 test" ; do echo "$s" | sed -rf incr.sed ; done
teststring135this 124test string55 101
124test
test124
te124st
test 124 test
$ 

Note this temporarily inserts _ characters, so could lead to incorrect results if there are _ in the input stream. As a mitigation to this, we can replace the _ in the sed script with some non-printable character (e.g. ASCII 0x07 BEL), and assume the input stream contains only printable ASCII. This seems to work fine when I test it.

\$\endgroup\$
3
\$\begingroup\$

Racket 74

(define(f x)(regexp-replace* #px"\\d+"x(λ(m)(~a(+ 1(string->number m))))))
\$\endgroup\$
2
\$\begingroup\$

Lua - 68 characters

d='(%D-)'for k,i,j in s:gmatch(d..'(%d+)'..d)do io.write(k,i+1,j)end

Expects the input to be stored in s.

\$\endgroup\$
2
\$\begingroup\$

CJam, 67 58 53 48 31 characters

This question is like the worst question for CJam. No regex, no pattern matching, no exception catching. But here we go (#YOLO)

Sl+_A,sNerN%\[_A,s-Ner~]:)]zs1>

This one splits the string in group of just alphabets and just digits. The increments each digit and stitches back the two array taking one element of each at a time.


Previous solution:

L_l{:Ci57-zA<:RC*+:N\R!N*NNW?i):NL?+RLC?@R*}/NL?

Try it online here

How it works:

Basic idea is to keep storing the character separately in a string if it is a digit and dump the incremented value to the final string once we get a non digit character.

L_                                               "Push two empty strings to stack,"
                                                 "first representing the final string"
                                                 "and second, the current ongoing number";
  l{                                       }/    "Run this block for each character of input string";
    :Ci                                          "Store the character to C and convert to"
                                                 "its ASCII equivalent integer";
       57-zA<:R                                  "Subtract 57 from the integer and compare"
                                                 "its absolute value with 10. Numeric character"
                                                 "would result to true here. Store the result in R";
               C*+:N                             "Take either 0 or 1 characters from C based"
                                                 "on value of R, add it to the second string"
                                                 "from first step. Also store the value in N";
                    \                            "Switch the strings. Now the string containing"
                                                 "the final result string is at top of stack";
                     R!N*                        "If the character was not a digit and N contains a number in it";
                         NNW?i):NL?+             "Convert N to number and increment it."
                                                 "If N is blank, take 0 instead. Put the final"
                                                 "value back in N and add it to the final result string";
                                    RLC?         "If the character was not a digit, push it to stack";
                                        @R*      "Put the ongoing numeric string back to top of stack";
                                             NL? "This is to handle the case when the last number"
                                                 "is not followed by a string, so stack will"
                                                 "have a string at top. Push the value of N to stack in that case";
\$\endgroup\$
1
\$\begingroup\$

Cobra - 88

do(s='')=RegularExpressions.Regex.replace(s,'\d+',do(m as Match)='[int.parse("[m]")+1]')
\$\endgroup\$
1
\$\begingroup\$

C# - 178 169 157 characters

This assumes that numbers like 999 are allowed to overflow to 000 and that -+,.E are not part of a number.

class T{static void Main(){var a="".ToCharArray();for(int b=1,c,i=a.Length;i-->0;b=48>c|c>57?7:b>0?c>56?a[i]='0':++a[i]*0:b)c=a[i];System.Console.Write(a);}}

Better readable form:

class T
{
    static void Main()
    {
        var a="7teststring134this 123test string59 100".ToCharArray();

        for (int b=3, c, i=a.Length; i-->0;
            b=48>c|c>57
                ?7
                :b>2
                    ?c>56?a[i]='0':++a[i]*0
                    :b
        ) c=a[i];

        System.Console.Write(a);
        System.Console.ReadKey();
    }
}

I'm new here, never tried code golf before, just gave it a try :)

I wonder if anyone has ideas to get it even shorter...

To participate with C# it would be nice if we could omit all the necessary framework around the actual code - then this would only have 82 chars, and that without calling any powerful system functions.


The same with pointers (182 chars):

class T
{
    unsafe static void Main()
    {
        char[] a="7teststring134this 123test string59 100".ToCharArray();

        int b=3;
        fixed (char* s=&a[0])
            for (var p=s+a.Length; p-->s; )
                b=*p<48|*p>57
                    ?7
                    :b>2
                        ?*p>56?*p='0':++*p*0
                        :b;

        System.Console.Write(a);
        System.Console.ReadKey();
    }
}

Now without overflowing, this correctly handles the 999 case (223 chars):

class T
{
    static void Main()
    {
        var s=new System.Text.StringBuilder("9999teststring134this 123test string99 100");

        for (int b=3, c, i=s.Length; i-->0; )
        {
            c=s[i];
            b=48>c|c>57
                ?b>8?8:7
                :b>2
                    ?c>56?c-(s[i]='0'):++s[i]*0
                    :b;
            if (b>8&i<1|b==8) s.Insert(i+9-b, '1');
        }

        System.Console.Write(s);
        System.Console.ReadKey();
    }
}

Another different older one, it reads from standard input and uses recursion:

namespace System {
    using C=Console;
    class T {
        class t {
            byte b=1;
            string s="";
            void R() {
                var c=C.Read();
                if (c>31) {
                    R();
                    if (48>c|c>57) b=1;
                    else if (b==1) c=c==57?48:++c*b--;
                    s=(char)c+s;
                }
            }
            public t() {
                R();
                C.Write(s);
            }
        }
        static void Main() {
            new t();
            C.ReadKey();
        }
    }
}

Note: Console.ReadKey(); and the string itself should not be counted.

I improved this already multiple times, see comments. There is still room for more improvements, I would say :) And sorry for the length, but I think the different versions are interesting enough to keep them...

\$\endgroup\$
  • \$\begingroup\$ no, getting rid of the "environment" isn't allowed. i reckon in your second code after if(c==57) you could write c--; instead of c=48;, what about the ternary operator too. there is infact a lot of golfing tricks. maybe you should visit codegolf.stackexchange.com/questions/2203/tips-for-golfing-in-c \$\endgroup\$ – proud haskeller Sep 23 '14 at 17:18
  • \$\begingroup\$ Thanks, I know nothing about golf :) everything you see here was invented by me ;-) 57-1 isn't 48. So I don't understand. \$\endgroup\$ – maf-soft Sep 23 '14 at 17:22
  • \$\begingroup\$ Oops :-) :-) :-) :-) \$\endgroup\$ – proud haskeller Sep 23 '14 at 17:24
  • \$\begingroup\$ I don't really know C# well, but I guess you can use some operator to stick them together like ... ? ... : c++*b-- \$\endgroup\$ – proud haskeller Sep 23 '14 at 17:51
  • \$\begingroup\$ btw sorry for sending you the C tips instead of the C# tips: codegolf.stackexchange.com/questions/173/… \$\endgroup\$ – proud haskeller Sep 23 '14 at 17:53
1
\$\begingroup\$

Groovy, 38 bytes

{it.replaceAll(/\d+/,{(it as int)+1})}

Uggghhh... I absolutely hate the words replace and all, they ruin all regex golfs for me.

\$\endgroup\$
  • 1
    \$\begingroup\$ (it as int)+1it.next() \$\endgroup\$ – manatwork Nov 11 '16 at 12:28
0
\$\begingroup\$

PHP - 91 Bytes

<?$i=fgets(STDIN);for($n=0;$n<strlen($i);$n++)if(is_numeric($i[$n]))$i[$n]=$i[$n]+1;echo$i;

I don't wanted to use regular expressions. PHP isn't capable to directly increment a string offset, so, I needed to add some bytes on the increment step. This one line script remembers me a very dark age of the PHP scripting...

\$\endgroup\$
  • \$\begingroup\$ I have observed just now that the question asks you to increment the result number of a sequence of algarisms. This answer is incorrect. But I really feel that the op should add more details about what he wants. \$\endgroup\$ – Alexandre Teles Sep 23 '14 at 13:15
0
\$\begingroup\$

K, 56

{" "/:{,/$(`$a)^`$$1+"I"$a:_[;x]@&~~':x in .Q.n}'" "\:x}
\$\endgroup\$
0
\$\begingroup\$

sed and bash - 40 (including invocation and pipes)

$ cat << EOF |sed 's/[0-9]\+/$((\0+1))/g;s/^/echo /'|bash
teststring134this 123test string54 100
123test
test123
te123st
test 123 test
EOF

Outputs:

teststring135this 124test string55 101
124test
test124
te124st
test 124 test
\$\endgroup\$
  • \$\begingroup\$ I tried this test string: 42;rm -rf / It worked the first time. \$\endgroup\$ – Dennis Sep 26 '14 at 13:22
  • 2
    \$\begingroup\$ You can change \0 to & (-1 char), $((…)) to $[…] (-2 chars), s/^/echo / to iecho \\ (-2 chars) to shorten your current code. However better fix the bug mentioned by @Dennis first. (He wrote “It worked the first time” for fun and as hint about the issue. Actually your code fails on input containing ;, #, `…`, $(…) and maybe other special characters too.) \$\endgroup\$ – manatwork Sep 26 '14 at 14:34
  • \$\begingroup\$ Arbitrary code execution is a feature :-) \$\endgroup\$ – mgjk Sep 26 '14 at 14:37
  • \$\begingroup\$ There may be no way to go this route without some kind of input restrictions and keeping the code tiny. The nature of the solution is to translate the input and use an interpreter to do the math since sed can't do it. As soon as user input hits an interpreter, the escaping is nuts. Short of the previous sed example, sed can't do math. \$\endgroup\$ – mgjk Sep 26 '14 at 15:43
  • \$\begingroup\$ Somewhat shorter: eval echo `sed 's/[0-9]\+/$[&+1]/g'` - still has the code injection problem though, as per my answer to another similar question codegolf.stackexchange.com/a/37145/11259 \$\endgroup\$ – Digital Trauma Sep 26 '14 at 18:55
0
\$\begingroup\$

Java 7, 119 bytes

void c(String s){for(String x:s.split("(?=[^\\d]+)|(?<=[^\\d]+)"))System.out.print(x.matches("\\d+")?new Long(x)+1:x);}

If the requirement is a program instead of just a function, then it's 149 bytes:

class M{public static void main(String[]a){for(String x:a[0].split("(?=[^\\d]+)|(?<=[^\\d]+)"))System.out.print(x.matches("\\d+")?new Long(x)+1:x);}}

Ungolfed & test code:

Try it here.

class M{
  static void c(String s){
    for(String x : s.split("(?=[^\\d]+)|(?<=[^\\d]+)")){
      System.out.print(x.matches("\\d+")
                        ? new Long(x) + 1
                        : x);
    }
  }

  public static void main(String[] a){
    c("123test");
    System.out.println();
    c("test123");
    System.out.println();
    c("te123st");
    System.out.println();
    c("test 123 test");
    System.out.println();
    c("7teststring134this 123test string59 100");
  }
}

Output:

124test
test124
te124st
test 124 test
8teststring135this 124test string60 101
\$\endgroup\$
0
\$\begingroup\$

Gema, 14 characters

<D>=@add{$1;1}

Sample run:

bash-4.3$ gema '<D>=@add{$1;1}' <<< 'teststring134this 123test string54 100'
teststring135this 124test string55 101
\$\endgroup\$
0
\$\begingroup\$

DASH, 16 bytes (noncompeting)

rstr[R"\d+""g"+1

This returns a function/partial application.

Usage:

rstr[R"\d+""g"+1]"test 123 234t"

Explanation

rstr[          #. replace any parts of the input
  R "\d+" "g"  #. matching /\d+/g
  +1           #. with its incremented form
]
\$\endgroup\$
  • \$\begingroup\$ Is this answer non-competing? \$\endgroup\$ – Dennis Nov 10 '16 at 14:45
  • \$\begingroup\$ oh rip :( I somehow thought this was a catalog question. \$\endgroup\$ – Mama Fun Roll Nov 11 '16 at 1:29
0
\$\begingroup\$

CJam, 18 bytes

q_A,s-_:(:`ers~]:)

Try it here.

Explanation

q         e# Read input.
_A,s-     e# Duplicate and remove digits.
_         e# Duplicate.
:(:`      e# Decrement and get the string representation of each character.
er        e# Map the characters to the decremented string representation.
s~        e# Flatten to string and evaluate.
]:)       e# Wrap in an array and increment each element.
\$\endgroup\$
0
\$\begingroup\$

R, 83 bytes

Late to the party. Assumes input is stored in variable x. It's probably not needed to use regmatches to solve this but I couldn't figure out vectorized replacements without any external packages.

paste0(el(r(x,m<-gregexpr("\\d+",x),T)),c(as.numeric(el(r(x,m)))+1,""),collapse="")

Ungolfed and explained

r=regmatches                                        # Alias for regmatch
y=r(x<-scan(,""),m<-gregexpr("\\d+",x))             # return match digits
i=r(x,m,T)                                          # return inverted match (non-digits)
paste0(el(i),c(as.numeric(el(y))+1,""),collapse="") # join digits+1 and non-digits, element-wise

Example output

input: 
"teststring135this 124test string55 101"

output:
[1] "teststring136this 125test string56 102"
\$\endgroup\$
0
\$\begingroup\$

C# (Visual C# Interactive Compiler) with command-line option /u:System.Text.RegularExpressions.Regex;System.Int32, 40 bytes

Replace(n,"\\d+",m=>Parse(m.Value)+1+"")

Expects input to be in a variable named n.

Try it online!

\$\endgroup\$
  • 2
    \$\begingroup\$ Invalid, cannot expect input in a variable \$\endgroup\$ – ASCII-only Jan 31 at 9:10
  • \$\begingroup\$ @ascii-only This question seems to explicitly allow it' though personally, I would try to stick to today's input standards \$\endgroup\$ – Jo King Jan 31 at 11:45
  • \$\begingroup\$ Oh wait :/ ew this question \$\endgroup\$ – ASCII-only Jan 31 at 23:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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