17
\$\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\$
10
  • 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\$ Sep 21, 2014 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\$ Sep 21, 2014 at 11:23
  • 1
    \$\begingroup\$ What about carrying? What happens to 999? \$\endgroup\$
    – fluffy
    Sep 21, 2014 at 17:13
  • 3
    \$\begingroup\$ possible duplicate of Multiply all numbers in a string \$\endgroup\$ Sep 21, 2014 at 18:52
  • 8
    \$\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\$ Sep 21, 2014 at 20:45

33 Answers 33

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\$
1
13
\$\begingroup\$

Ruby, 30 24 bytes

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

Expects the input to be stored in s.

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

JavaScript (ES6) - 28

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

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

\$\endgroup\$
1
  • 2
    \$\begingroup\$ You can take out the H= and just have it be an anonymous function. \$\endgroup\$ Nov 10, 2016 at 14:29
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\$
1
  • \$\begingroup\$ I can't seem to make this work.... (I am using vim 7.0.237) \$\endgroup\$ Nov 11, 2016 at 2:24
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\$
0
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\$
11
  • 1
    \$\begingroup\$ I'm sure you can get rid of some of the includes and it will still compile fine with gcc. \$\endgroup\$ Sep 21, 2014 at 11:58
  • 1
    \$\begingroup\$ Will this work with a string containing e.g. 99? \$\endgroup\$
    – anatolyg
    Sep 21, 2014 at 16:32
  • \$\begingroup\$ @MartinBüttner: Yes but then it wouldn't be valid C, just something that happens to work on gcc. \$\endgroup\$ Sep 21, 2014 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\$ Sep 21, 2014 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\$ Sep 21, 2014 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\$
2
  • 1
    \$\begingroup\$ You can drop the trailing %% since this is no user code: flex.sourceforge.net/manual/… \$\endgroup\$
    – Josh
    Sep 24, 2014 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, 2014 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\$
0
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\$
9
  • \$\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\$ Sep 23, 2014 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, 2014 at 17:22
  • \$\begingroup\$ Oops :-) :-) :-) :-) \$\endgroup\$ Sep 23, 2014 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\$ Sep 23, 2014 at 17:51
  • \$\begingroup\$ btw sorry for sending you the C tips instead of the C# tips: codegolf.stackexchange.com/questions/173/… \$\endgroup\$ Sep 23, 2014 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
  • 1
    \$\begingroup\$ (it as int)+1it.next() \$\endgroup\$
    – manatwork
    Nov 11, 2016 at 12:28
1
\$\begingroup\$

AWK, 40 bytes

BEGIN{RS="[0-9]+";ORS=e}$0=$0(RT?RT+1:e)

Try it online!

Parses each substring of numbers as a record separator (default is a newline, "\n"). Adds one to the record text (RT), that is the number that previously matched to the regex. Except for the last RT, which is null. That's what the last condition is about. Otherwise, there would be a 1 appended to the end of the output.

\$\endgroup\$
1
\$\begingroup\$

Perl 6, 13 bytes

{S:g{\d+}+=1}

Try it online!

Very simple regex substitution that just increments each instance of a series of digits

\$\endgroup\$
1
\$\begingroup\$

Brachylog, 17 bytes

~c{ịᵐc+₁ṫ|ịˢĖ&}ᵐc

Try it online!

Explanation

~c{ịᵐc+₁ṫ|ịˢĖ&}ᵐc
~c                 Partition the input string such that
  {           }ᵐ   this predicate can be applied to each substring:
                    Either:
   ịᵐ                Convert each character to a number (i.e. they are all digits)
     c               Concatenate the digits into a single number
      +₁             Add 1
        ṫ            Convert back to a string
         |          Or:
          ịˢ         Find all characters that can be converted to a number
            Ė        Assert that that list is empty (i.e. none of them are digits)
             &       Return the substring unchanged
                c  Concatenate the results back into a single string
\$\endgroup\$
1
\$\begingroup\$

Vyxal s, 8 bytes

⁽±Ḋƛ±[⌊›

Try it Online!

Who needs regex amiright?

Explained

⁽±Ḋƛ±[⌊›
⁽±Ḋ      # Group the input by whether each item is numeric
   ƛ     # To each group:
    ±[   #   If it's numeric:
      ⌊› #     Cast to int and increment
# -s flag sums into a single string. 
\$\endgroup\$
1
  • \$\begingroup\$ How does it work though? \$\endgroup\$
    – DLosc
    Sep 3, 2022 at 4:27
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\$
1
  • \$\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\$ Sep 23, 2014 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\$
6
  • \$\begingroup\$ I tried this test string: 42;rm -rf / It worked the first time. \$\endgroup\$
    – Dennis
    Sep 26, 2014 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, 2014 at 14:34
  • \$\begingroup\$ Arbitrary code execution is a feature :-) \$\endgroup\$
    – mgjk
    Sep 26, 2014 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, 2014 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\$ Sep 26, 2014 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\$

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\$
3
  • 2
    \$\begingroup\$ Invalid, cannot expect input in a variable \$\endgroup\$
    – ASCII-only
    Jan 31, 2019 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, 2019 at 11:45
  • \$\begingroup\$ Oh wait :/ ew this question \$\endgroup\$
    – ASCII-only
    Jan 31, 2019 at 23:57
0
\$\begingroup\$

Stax, 9 bytes

ü╜≥NÇNX╪ÿ

Run and debug it

regex

\$\endgroup\$

Your Answer

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

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