14
\$\begingroup\$

Take a string as an input, and perform addition/subtraction of all the digits in the string and output the sum of those operations as the result.

Rules

  • The digits in the string are read from left to right
  • If a digit (n) is odd, perform addition with the next digit (n + n1)
  • If a digit (n) is even, perform subtraction with the next digit (n - n1)
  • If you've reached the last digit in the string, perform the operation with the first digit in the string
  • Output will be the sum of all the resulting values
  • If there is only one digit in the string, perform the operation with itself (n+n or n-n)
  • If there are no digits in the string, output is 0

Example

Input: r5e6o9mm!/3708dvc    
Process: (5+6) + (6-9) + (9+3) + (3+7) + (7+0) + (0-8) + (8-5)
Output: 32

Notes

  • Either function or full program is accepted
  • Maximum input length would depend on your language's limit for a string input
  • No restrictions on character input, but only half-width digits count towards the output
  • Fewest bytes wins
\$\endgroup\$
7
  • 4
    \$\begingroup\$ A couple more examples would be good too \$\endgroup\$
    – dylnan
    Commented Jul 6, 2018 at 5:55
  • 2
    \$\begingroup\$ I'd recommend to add a test case ending with an odd digit. \$\endgroup\$
    – Arnauld
    Commented Jul 6, 2018 at 8:11
  • 3
    \$\begingroup\$ Suggested testcase: "", "0", "1" \$\endgroup\$
    – tsh
    Commented Jul 6, 2018 at 9:00
  • 1
    \$\begingroup\$ Can we take input as an array of characters instead of a string? (Julia makes a distinction between those two.) \$\endgroup\$
    – Sundar R
    Commented Jul 6, 2018 at 9:08
  • 4
    \$\begingroup\$ @sundar The current consensus is that a string is defined as a sequence of characters. My understanding is that arrays of characters are therefore allowed by default even if your language has a native string type. \$\endgroup\$
    – Arnauld
    Commented Jul 6, 2018 at 9:31

19 Answers 19

6
\$\begingroup\$

Jelly, 17 15 12 bytes

fØDV€ḂT‘ịƲSḤ

Try it online!

Try test cases.

The program keeps only the digits that follow an odd digit then computes twice the sum.

fØDV€ḂT‘ịƲSḤ   
f                   Remove anything that isn't...
 ØD                 a digit.
   V€               Cast each digit to an integer
         Ʋ          Monad:
     Ḃ              Parity of each digit.
      T             Indices of truthy elements (odd digits).
       ‘            Increment.
        ị           Index into list of digits.
                    Wraps to beginning and if there are no digits this returns 0.
          S         Sum.
           Ḥ        Double.
\$\endgroup\$
0
3
\$\begingroup\$

K (oK), 47 43 40 31 bytes

Solution:

{+/(1_x,*x)*2*2!x^:(x-:48)^!10}

Try it online!

Explanation:

Remove everything from string that isn't a number (whilst also converting), modulo 2, multiply by 2, multiply with x rotated by 1, and sum up.

{+/(1_x,*x)*2*2!x^:(x-:48)^!10} / solution
{                             } / lambda taking implicit x
                           !10  / range 0..10
                          ^     / except
                   (     )      / do this together
                    x-:48       / subtract 48 from x (type fudging char ascii value -> ints), save back into x
                x^:             / x except right, and save back to x
              2!                / modulo 2
            2*                  / multiply by 2
           *                    / multiply by
   (      )                     / do this together
        *x                      / first element of x
       ,                        / append to
      x                         / x
    1_                          / drop first (ie rotate everything by 1)
 +/                             / sum, add (+) over (/)

Naive solution:

Remove everything from string that isn't a number (whilst also converting), take 2-item sliding window, figure out whether they are odd or even, apply add/subtract as appropriate, then sum up.

{+/((-;+)2!x).'2':(1+#x)#x^:(x-:48)^!10}

Try it online!

Notes:

  • -4 bytes thanks to @ngn due to a smarter way of filtering the input
  • -3 bytes by using sliding window rather than reshape
  • -9 bytes porting ngn's solution (non-naive approach)
\$\endgroup\$
4
  • 1
    \$\begingroup\$ x:48!x@&x in,/$!10 -> x^:(x-:48)^!10 \$\endgroup\$
    – ngn
    Commented Jul 6, 2018 at 10:02
  • \$\begingroup\$ I wrote the solution in q/kdb+ then ported to oK... might be able to squeeze a few more bytes out of this yet! \$\endgroup\$
    – mkst
    Commented Jul 6, 2018 at 10:16
  • 1
    \$\begingroup\$ I posted a separate answer in ngn/k, feel free to bring in ideas from there. I think oK will end up being the shortest, as my parser is rubbish at the moment - it doesn't parse modified assignment properly. By the way, I wasn't aware of ': as "sliding window" - interesting. \$\endgroup\$
    – ngn
    Commented Jul 6, 2018 at 10:26
  • \$\begingroup\$ You seem to be well familiar with k. If you ever feel like discussing vector programming stuff with like-minded people or just watching the rest of us argue - we've got this chat room. Most of the banter is about APL, but k and J are on-topic too. \$\endgroup\$
    – ngn
    Commented Jul 6, 2018 at 17:04
3
\$\begingroup\$

Python 2, 86 bytes

k=[int(a)for a in input()if'/'<a<':']
print sum(a-(-1)**a*b for a,b in zip(k,k[1:]+k))

Try it online!

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

Perl 6, 41 bytes

{2*sum rotate($!=.comb(/\d/))Z*(@$! X%2)}

Try it online!

Uses the same logic as dylnan's Jelly answer. This sums only digits that follow an odd number and then multiplies by 2.

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

Powershell, 80 78 76 bytes

($d="$args"-split'\D*'-ne'')+$d[0]|?{$p-match'[13579]';$p=$_}|%{$s+=2*$_};$s

-2 bytes thanks Neil with Retina solution

-2 bytes thanks AdmBorkBork

Test script:

$f = {
($d="$args"-split'\D*'-ne'')+$d[0]|?{$p-match'[13579]';$p=$_}|%{$s+=2*$_};$s
}

&$f 'r5e6o9mm!/3708dvc'

Explanation

First of all: it sould add 2*n if previous digit is odd, and 0 if a previous digit is even.

($d="$args"-split'\D*'-ne'')+ # let $d is array contains digits only, each element is a digit
$d[0]|                        # apend first digit to the end of the array
?{                            # where for each digit
    $p-match'[13579]'         # predicate is 'previous digit is odd' (it is false on the first iteration because $p is null)
    $p=$_                     # let previous digit is current
}|
%{                            # for each digit matched to the predicate
    $s+=2*$_                  # add current digit multiply 2 to $s. 
}
$s                            # return sum

Extra, 99 bytes

Inspired by @Neil. Regex match digits with 'previous digit is odd' only. Matches is an automatic variable.

param($d)$d+($d-match'\d')+$Matches[0]|sls '(?<=[13579]\D*)\d'-a|%{$_.Matches.Value|%{$s+=2*$_}};$s
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Save a byte swapping |?{$_} for -ne''and another by moving $d="$args"-split'\D*'-ne'' into parens like ($d="$args"-split'\D*'-ne'')+$d[0]. \$\endgroup\$ Commented Jul 6, 2018 at 12:34
2
\$\begingroup\$

MATL, 18 17 bytes

t4Y2m)!Ut1YSof)sE

Try it online!

(-1 byte thanks to Luis Mendo/Giuseppe/both!)

Explanation:

     % Implicit input
 t   % duplicate input
     % stack: ['r5e6o9mm!/3708dvc' 'r5e6o9mm!/3708dvc']
 4Y2 % push inbuilt literal, characters '0':'9'
     % stack: ['r5e6o9mm!/3708dvc' 'r5e6o9mm!/3708dvc' '0123456789']
 m)  % extract only characters from input that belong to '0':'9'
     % stack: ['5693708']
 !U  % transpose and convert each value from string to number
     % stack: [5 6 9 3 7 0 8]
 t   % duplicate that
 1YS % circular shift by 1
     % stack: [[5 6 9 3 7 0 8] [8 5 6 9 3 7 0]]
 o   % parity check - 1 for odd, 0 for even
     % stack: [[5 6 9 3 7 0 8] [0 1 0 1 1 1 0]]
 f   % find non-zero value indices in last array
     % stack: [[5 6 9 3 7 0 8] [2 4 5 6]]
 )   % index at those places in the first array
 s   % sum
 E   % multiply by 2
     % (implicit) convert to string and display

The basic idea is that numbers that follow even numbers can be ignored, while those that follow odd numbers are doubled - and the final result is the sum of those doubled values.

I didn't think f after the parity check o would be necessary, but for some reason MATL doesn't see the array of 0's and 1's that result from the o as a logical array, instead takes them as numerical indices and indexes into positions 1 and end.

\$\endgroup\$
7
  • \$\begingroup\$ I think you can use !U instead of 48-. The transpose doesn't seem to do any harm here. o for double input is just mod(...,2), so the output is double. Nice NaN input trick! If that's meant to solve the extraneous output in STDOUT, Dennis had an idea and will probably fix that soon \$\endgroup\$
    – Luis Mendo
    Commented Jul 6, 2018 at 13:29
  • \$\begingroup\$ !U instead of 48- \$\endgroup\$
    – Giuseppe
    Commented Jul 6, 2018 at 13:29
  • \$\begingroup\$ @LuisMendo welp, you beat me to the punch! \$\endgroup\$
    – Giuseppe
    Commented Jul 6, 2018 at 13:29
  • \$\begingroup\$ @Giuseppe :-D :-D \$\endgroup\$
    – Luis Mendo
    Commented Jul 6, 2018 at 13:30
  • \$\begingroup\$ Thank you both, edited. @LuisMendo When does o give a logical array output then - or does it not? (I must confess I've never really looked into MATLAB's numeric type system.) And yeah, I thought NaN would make for a nice sentinel since it's unlikely to be actual input anywhere, but good to know it won't be needed for much longer! \$\endgroup\$
    – Sundar R
    Commented Jul 6, 2018 at 14:03
2
\$\begingroup\$

K (ngn/k), 33 bytes

{+/(1_x,*x)*2*2!x:-48+x^x^,/$!10}

Try it online!

{ } is a function with argument x

!10 is the list 0 1 ... 9

$ convert to strings

,/ concatenate

x^ means x without what's on the right

x^x^ means x intersected with what's on the right, i.e. keep only the digits from x

-48+ subtract 48, which is the ASCII code of "0"

x: assign to x

2! mod 2

2* multiplied by 2

1_x,*x is one drop of: x followed by the first of x; i.e. x rotated to the left by one step

+/ sum

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

Japt (v2.0a0), 25 19 bytes

-6 bytes thanks to Shaggy.

kè\D
íÈ°*2*Y°u}Ué)x

Try it here.

It works with no digits this time! Input is a list of characters.

\$\endgroup\$
6
  • \$\begingroup\$ 19 bytes, including switching to Japt v2. Not happy with the array in the xfunction, though. Ping me in chat if you've any questions. \$\endgroup\$
    – Shaggy
    Commented Jul 6, 2018 at 14:22
  • \$\begingroup\$ Wait, just noticed that this won't work at all if the input doesn't contain any digits. \$\endgroup\$
    – Shaggy
    Commented Jul 6, 2018 at 14:30
  • \$\begingroup\$ Also, where's the source for v2.0a0, @Shaggy? I can't find it in the repo. \$\endgroup\$ Commented Jul 6, 2018 at 14:32
  • \$\begingroup\$ This is v1 and this is v2. \$\endgroup\$
    – Shaggy
    Commented Jul 6, 2018 at 14:34
  • \$\begingroup\$ In case you missed it in chat, I got this down to 12 bytes for you. \$\endgroup\$
    – Shaggy
    Commented Jul 6, 2018 at 15:39
2
\$\begingroup\$

05AB1E, 12 9 bytes

Saves 1 byte over the naive method by utilizing dylnan's parity trick
Saved 3 bytes thanks to Mr. Xcoder

þDÁ€ÉÏSO·

Try it online!

Explanation

þ              # push only digits of input
 D             # duplicate
  Á            # rotate right
   ۃ          # get the parity of each
     Ï         # keep only true items
      SO       # calculate digit-sum
        ·      # double
\$\endgroup\$
2
  • \$\begingroup\$ Hmm, would þÀIþ€ÉÏSO·, þÀDÁ€ÉÏSO·, þÀ¹þ€ÉÏSO· or þÀsþ€ÉÏSO· pass all test cases for -2 bytes? \$\endgroup\$
    – Mr. Xcoder
    Commented Jul 6, 2018 at 19:04
  • \$\begingroup\$ @Mr.Xcoder: Ah, yes. Nice! We can even do þDÁ€ÉÏSO· for -3 :) \$\endgroup\$
    – Emigna
    Commented Jul 6, 2018 at 23:09
1
\$\begingroup\$

Retina, 37 bytes

(\d).*
$&$1
L$`(?<=[13579]\D*).
2**
_

Try it online! Explanation:

(\d).*
$&$1

Append a duplicate of the first digit.

L$`(?<=[13579]\D*).

Match anything whose first previous digit is odd.

2**

Convert all the matches to unary and double them. (Non-digits are treated as zero.)

_

Take the sum. If there were no matches, then this produces zero as required.

The best I could do in Retina 0.8.2 was 44 bytes:

[^\d]

(.).*
$&$1
(?<![13579]).

.
$*
.
..
.

Try it online! Explanation:

[^\d]

Delete non-digits.

(.).*
$&$1

Append a copy of the first digit.

(?<![13579]).

Delete digits that do not follow an odd digit.

.
$*

Convert to unary.

.
..

Double them.

.

Take the sum.

\$\endgroup\$
3
  • \$\begingroup\$ I'm afraid the result will be incorrect if the last digit is not odd \$\endgroup\$
    – mazzy
    Commented Jul 6, 2018 at 9:16
  • 1
    \$\begingroup\$ @mazzy When you say the last digit, do you mean before or after copying the first digit to the end? \$\endgroup\$
    – Neil
    Commented Jul 6, 2018 at 9:23
  • \$\begingroup\$ 'to the end'. the step 'Append a duplicate of the first digit' is copying to the end? ok. cool. Thanks \$\endgroup\$
    – mazzy
    Commented Jul 6, 2018 at 9:29
1
\$\begingroup\$

Jelly, 15 bytes

fØDV€1ịṭƊ+_Ḃ?ƝS

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ I hope you don't mind if I borrow 1ịṭƊ \$\endgroup\$
    – dylnan
    Commented Jul 6, 2018 at 17:30
1
\$\begingroup\$

JavaScript (ES6), 56 bytes

Takes input as an array of characters.

s=>s.map(c=>1/c?r+=p*(p=c*2&2,n=n||c,c):0,n=p=r=0)|r+p*n

Try it online!

Commented

s =>                     // given the input array s[]
  s.map(c =>             // for each character c in s[]:
    1 / c ?              //   if c is a digit:
      r +=               //     update r:
        p * (            //       p = either 0 or 2 (always 0 on the 1st iteration)
          p = c * 2 & 2, //       p = 0 if c is even, 2 if c is odd
          n = n || c,    //       if n is still equal to 0 (as an integer), set it to c
          c              //       compute p * c
        )                //     add the result to r
    :                    //   else:
      0,                 //     do nothing
    n = p = r = 0        //   n = first digit, p = previous digit, r = result
  )                      // end of map()
  | r + p * n            // compute the last operation with the 1st digit and add it to r
\$\endgroup\$
1
\$\begingroup\$

JavaScript (Node.js), 85 84 83 82 bytes

-1 bytes thanks to ovs

s=>(s.match(/\d/g)||[]).reduce((r,n,i,a)=>r+(+n)+a[a[++i]!=null?i:0]*-(1-n%2*2),0)

Try it online!

Takes the string input, finds the digits as an array of characters or returns empty array if none found, and then uses type coercion to ensure the values are added/subtracted correctly. The forward lookup preincrements the index and uses a null check for brevity, and then the final part checks whether number is odd or even to then force addition or subtraction ( + and - is -, etc)

\$\endgroup\$
2
  • \$\begingroup\$ n-0 can be +n \$\endgroup\$
    – ovs
    Commented Jul 6, 2018 at 11:35
  • \$\begingroup\$ Welcome to PPCG! \$\endgroup\$ Commented Jul 7, 2018 at 6:04
1
\$\begingroup\$

R, 58 bytes

function(x,y=strtoi(x[x%in%0:9]))sum(c(y[-1],y[1])*y%%2*2)

Try it online!

  • using dylnan's parity trick
  • -8 bytes accepting vector of characters instead of strings
  • -3 byte thanks to @Giuseppe
\$\endgroup\$
5
  • \$\begingroup\$ 67 bytes if you don't mind array output. \$\endgroup\$
    – Giuseppe
    Commented Jul 6, 2018 at 13:35
  • 1
    \$\begingroup\$ hmm actually you can't use the dot product because of the empty array in xxx so it's 68 bytes by using the change in indexing a to generate y. \$\endgroup\$
    – Giuseppe
    Commented Jul 6, 2018 at 13:36
  • \$\begingroup\$ @Giuseppe: modified, thanks :) \$\endgroup\$
    – digEmAll
    Commented Jul 6, 2018 at 15:02
  • \$\begingroup\$ @Giuseppe: I ask your opinion you since you're a wiser code-golfer... from comments it seems we can use a vector of characters, in this case 61 bytes are possible : Try it online! what do you think ? \$\endgroup\$
    – digEmAll
    Commented Jul 6, 2018 at 15:15
  • \$\begingroup\$ use strtoi instead of as.double, but yeah, that should be fine. \$\endgroup\$
    – Giuseppe
    Commented Jul 6, 2018 at 15:17
0
\$\begingroup\$

Perl 5, 48 bytes

$;=$;[++$-%@;],$\+=$_%2?$_+$;:$_-$;for@;=/\d/g}{

Try it online!

I quite like how cryptic this looks, but it's a pretty straightforward loop around all the numbers in the string.

\$\endgroup\$
0
\$\begingroup\$

Julia 0.6, 77 69 bytes

s->(s=s.-'0';s=s[0.<=s.<=9];endof(s)>0?sum(2(s%2).*[s[2:end];s[]]):0)

Try it online!

\$\endgroup\$
0
\$\begingroup\$

C Sharp 180 bytes

This isn't very good golfing, lol.

s=>{var q=new Queue<int>(s.Where(Char.IsNumber).Select(n=>n-48));q.Enqueue(q.First());int t,o=0;o=q.Dequeue();try{while(true){t+=o+(o%2==0?-1:1)*(o=q.Dequeue());}}catch{return t;}}

Ungolfed :

var q = new Queue<int>(s.Where(Char.IsNumber).Select(n=>n-48));
int t,o=0;

q.Enqueue(q.First());    
o=q.Dequeue();

try{
    while(true){
        t += o + (o%2==0?-1:1) * (o=q.Dequeue());
    }
}
catch {
    return t;
}
\$\endgroup\$
0
\$\begingroup\$

Stax, 14 bytes

ÿ←«4é■≥B▬ê→█T♥

Run and debug it

Unpacked, ungolfed, and commented, it looks like this.

Vd|&    filter out non-digits
c|(\    zip into pairs after rotating right
F       for each digit pair
  B2%s  first-of-pair % 2, then swap top two stack elements
  eH*   eval digit as integer, double, then multiply
  +     add to running total

Run this one

\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 52 bytes

s=>s.filter(t=>1/t&&~(a+=u*t,u=t%2),a=u=0)[0]*u+a<<1

Expects input as an array of characters. Caveat: Due to use of bit-shifting, the output has an upper bound of 2^31-1

Try it online!

Explanation

Essentially doubles the sum of the digits following odd values.

s => s.filter(             // filter to preserve the first digit
    t =>
        1/t &&             // short-circuits if NaN
        ~(                 // coerce to truthy value
            a += u * t,    // adds value only if previous digit is odd
            u = t%2        // store parity of current digit
        ),
    a = u = 0
)[0]                       // first digit
* u + a
<< 1                       // bit-shift to multiply by 2 (also coerces a NaN resulting from a string devoid of digits to 0)
\$\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.