5
\$\begingroup\$

We seem to quite like digit runs lately, so here's a fairly simple challenge.

Given a positive integer, split it into it's digit runs, and return the product.

For example:

11122333 would become 111, 22, 333, the product of which is 813186

Input may be taken as an integer, string, or list/array of digits/characters. Your entry must work for any number within it's representable range. I have tested this for 32-bit integers (2^32-1 max value) and the largest possible result I have found is 1099999989 from 1199999999, which is also within the 32-bit integer range. I have yet to find a number who's output is larger than the input.

For the purposes of this challenge, runs of length 1 are not counted.

If there is only 1 run, return the run. If there are no runs, do anything (undefined behaviour)

Standard I/O rules apply, output can be given as an integer or string.

Testcases

11122333 -> 813186
1112333 -> 36963
1122855098 -> 13310
98776543 -> 77
1000000 -> 0
123456789 -> undefined
1 -> undefined
99445662 -> 287496
1199999999 -> 1099999989
999999999 -> 999999999

Scoring

This is so fewest bytes in each language wins!

\$\endgroup\$
11
  • 17
    \$\begingroup\$ "For the purposes of this challenge, runs of length 1 are not counted." This seems completely arbitrary. \$\endgroup\$
    – Fatalize
    Jul 11, 2017 at 11:57
  • 12
    \$\begingroup\$ @Mayube Adding arbitrary constraints to make a trivial challenge barely less trivial does not seem like a desirable thing to do to me. \$\endgroup\$
    – Fatalize
    Jul 11, 2017 at 12:16
  • 2
    \$\begingroup\$ Why are no runs undefined? I'm not really complaining, I don't think it matters much, but the product of the empty set is 1 in pretty much any definition of product. \$\endgroup\$
    – Wheat Wizard
    Jul 11, 2017 at 13:20
  • 1
    \$\begingroup\$ @WheatWizard I prefer to leave "invalid" inputs as either undefined, or remove them completely, I like undefined behaviour for cases like this as it sometimes allows answers to have a lot more flexibility. (Although admittedly perhaps not so much in this particular case) \$\endgroup\$
    – Mayube
    Jul 11, 2017 at 13:23
  • 1
    \$\begingroup\$ Proof that the output never exceeds the input: it suffices to show that if two positive integers A and B are concatenated to form the integer C, then A*B<C. But if B has d digits, then B<10^d, and so C = A*10^d + B ≥ A*10^d > A*B. \$\endgroup\$ Jul 11, 2017 at 18:26

16 Answers 16

6
\$\begingroup\$

Haskell, 63 55 bytes

Since no one has done Haskell yet here's my take on it. Takes a string as input (of course).

import Data.List
f s=product[read x|x@(_:_:_)<-group s]

Try it online!

This code almost looks as if it is not golfed, but I cannot find anyway to make it shorter.

\$\endgroup\$
3
  • \$\begingroup\$ Your code fails on the test case f "1". Expected output is undefined \$\endgroup\$ Jul 11, 2017 at 13:38
  • 1
    \$\begingroup\$ @maple_shaft undefined does not mean they literally want undefined as the output, only that the behavior of the program is undefined. 1 is valid output for "1". \$\endgroup\$
    – Wheat Wizard
    Jul 11, 2017 at 13:39
  • 2
    \$\begingroup\$ You can check the length condition in the pattern match, like this: x@(_:_:_)<-, and the numeric type of product is enough for the defaulting rule to apply, so you don't need the type annotation. \$\endgroup\$ Jul 11, 2017 at 14:20
5
\$\begingroup\$

Japt, 10 8 bytes

Takes input as a string, outputs an integer or 1 for "undefined".

ò¦ fa_Ã×

Test it

  • 2 bytes saved thanks to ETH
\$\endgroup\$
8
  • \$\begingroup\$ Does this multiply by 10 or something? \$\endgroup\$ Jul 11, 2017 at 12:15
  • \$\begingroup\$ Incorrect output for 1112333, outputs 73926 when it should output 36963 \$\endgroup\$
    – Mayube
    Jul 11, 2017 at 12:16
  • \$\begingroup\$ @Mayube: Fixed now. \$\endgroup\$
    – Shaggy
    Jul 11, 2017 at 12:25
  • \$\begingroup\$ @EriktheOutgolfer; I'd missed the rule about ignoring runs of length 1. \$\endgroup\$
    – Shaggy
    Jul 11, 2017 at 12:26
  • \$\begingroup\$ I found a couple ways of dealing with that rule that only amount to 8 bytes: ò¦ fa_Ã× or ò¦ f>9 × \$\endgroup\$ Jul 11, 2017 at 12:45
4
\$\begingroup\$

05AB1E, 6 5 bytes

-1 byte thanks to Erik the Outgolfer

γ9ÝKP

Try it online!

If we don't need to ignore runs of length one, 2 bytes:

γP

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Save a byte by using instead of žhS. \$\endgroup\$ Jul 11, 2017 at 12:22
  • \$\begingroup\$ @EriktheOutgolfer Ah! I knew there was a way to do it in 2 bytes. \$\endgroup\$
    – Okx
    Jul 11, 2017 at 12:24
3
\$\begingroup\$

JavaScript (ES6), 46 45 38 35 bytes

Takes input as a string, outputs an integer or throws an error for "undefined".

s=>eval(s.match(/(.)\1+/g).join`*`)
  • 7 bytes saved thanks to Herman.
  • 3 bytes saved thanks to Craig.

Try it

o.innerText=(f=
s=>eval(s.match(/(.)\1+/g).join`*`)
)(i.value="11122333");oninput=_=>o.innerText=f(i.value)
<input id=i><pre id=o>

\$\endgroup\$
4
  • 1
    \$\begingroup\$ -9 bytes: s=>s.replace(/(.)\1+/g,m=>n*=m,n=1)&&n (I haven't tested it yet) \$\endgroup\$
    – Endenite
    Jul 11, 2017 at 12:44
  • \$\begingroup\$ Seems to do the job, thanks, @HermanLauenstein :) Was playing around to see if I could get it shorter using + instead of * but hadn't got there yet. \$\endgroup\$
    – Shaggy
    Jul 11, 2017 at 12:47
  • \$\begingroup\$ Could you use eval to save a few bytes? s=>eval(s.match(/(.)\1+/g).join`*`) - throws an error if no runs \$\endgroup\$
    – Craig Ayre
    Jul 11, 2017 at 12:57
  • \$\begingroup\$ Nice one, @CraigAyre. I was stupidly trying to see if I could save bytes by passing the replace through eval! Given the state of my golfing the past couple of days, it's a very good thing I have a holiday coming up tomorrow! \$\endgroup\$
    – Shaggy
    Jul 11, 2017 at 13:02
2
\$\begingroup\$

Jelly, 7 bytes

ŒgḊÐfḌP

Try it online!

-1 thanks to Leaky Nun.

\$\endgroup\$
2
  • \$\begingroup\$ 7 bytes? \$\endgroup\$
    – Leaky Nun
    Jul 11, 2017 at 12:35
  • \$\begingroup\$ @LeakyNun Ooh clever trick... \$\endgroup\$ Jul 11, 2017 at 12:38
2
\$\begingroup\$

Perl 5, 25 bytes

24 bytes + -p flag.

s/(.)\1+/$.*=$&/eg;$_=$.

Try it online!

Quite straight forward: (.)\1+ matches the runs of more than one digit, and $.*=$& uses $. as accumulator for the multiplications (because its initial value is 1 and not 0). Finally, $_ is set to $. and implicitly printed thanks to -p flag.

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

Perl 6, 21 bytes

{[*] .comb(/(.)$0+/)}

Test it

This returns 1 if there is no “digit runs” as that is the base case for multiplication.

The only change to allow one digit runs is to replace $0+ with $0* in the regular expression.

Expanded:

{            # bare block lambda with implicit parameter 「$_」

  [*]        # reduce the following using &infix:<*>

    .comb(   # pull out substrings that match the following
             # (implicit method call on 「$_」)

      /
        (.)  # any digit (character)
        $0+  # at least one more of that digit
      /
    )
}
\$\endgroup\$
1
\$\begingroup\$

Retina, 47 bytes

(.)\1+
$*_ 
T`d
{`(?<=^(_+) _*)_
$1
}`^_+ _
_
_

This is slow on the larger test cases.

Try it online!

Explanation

(.)\1+
$*_ 

First, replace each run of 2 or more of the same digit with that many _s, followed by a space for separation.

T`d

Then remove all remaining digits.

{`(?<=^(_+) _*)_
$1
}`^_+ _
_

Next, run these two stages in a loop. The first replaces every _ in the second run with the entire first run, effectively multiplying them. The second stage deletes the first run.

_

Finally, output the number _s.

\$\endgroup\$
1
  • \$\begingroup\$ You can get this to 42 bytes by using the multiplication stage from Retinas wiki. \$\endgroup\$
    – ovs
    Jul 11, 2017 at 17:15
1
\$\begingroup\$

C (gcc), 93 89 bytes

There must be some more golfing to be done here...

z,r;f(char*d){for(z=0;r=*d++;z=r/10?z?z*r:r:z)for(r-=48;r%10==*d-48;r=r*10+*d++-48);d=z;}

Try it online!

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

Mathematica, 61 bytes

Times@@FromDigits/@Select[Split@IntegerDigits@#,Length@#>1&]&
\$\endgroup\$
1
\$\begingroup\$

Python 2, 95 79 bytes

-2 thanks to @LeakyNum

l='0'
p=1
for c in input()+' ':a=c in l;p*=int(l)**(len(l)>1>a);l=l*a+c
print p

Try it online!

\$\endgroup\$
3
  • 1
    \$\begingroup\$ [1,int(l)][len(l)>1] is equivalent to int(l)**(len(l)>1) \$\endgroup\$
    – Leaky Nun
    Jul 11, 2017 at 12:41
  • \$\begingroup\$ Would l='' instead of l='0' work? \$\endgroup\$
    – Leaky Nun
    Jul 11, 2017 at 12:42
  • \$\begingroup\$ no, the int(l) would throw an error if the string was empty \$\endgroup\$ Jul 11, 2017 at 12:43
1
\$\begingroup\$

Python 2, 69 bytes

lambda n:eval('*'.join(zip(*re.findall(r'((.)\2+)',n))[0]))
import re

Try it online!

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

PHP, 62 bytes

prints 1 if no run is found

preg_match_all('#(.)\1+#',$argn,$t);echo array_product($t[0]);

Try it online!

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

CJam, 18 Bytes

qe`{0=1>},{:*i}%:*

Try it Online

q           e# read string - '1112333'
e`          e# convert string to RLE - [[3,'1'],[1,'2'],[3,'3']]
{0=1>},     e# filter out runs of length one - [[3,'1'],[3,'3']]
{:*i}%      e# convert sub-arrays to runs - [111,333]
:*          e# multiply array elements - 36963
\$\endgroup\$
0
\$\begingroup\$

Ruby, 41 bytes

p eval gets.scan(/(.)\1+/).map(&:join)*?*

Takes input from stdin, scans it for runs of length > 1, joins them on "*", evaluates and prints.

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

Factor, 151 bytes

[ { } { } ] dip
[ 48 - 2dup swap in? [ suffix ] [ [ suffix ] dip 1array ] if ] each
suffix rest [ 0 swap [ swap 10 * + ] each ] map product

Getting a better grip on this language! Still don't think I'm using enough combinators...

\$\endgroup\$

Your Answer

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

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