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\$
  • 17
    \$\begingroup\$ "For the purposes of this challenge, runs of length 1 are not counted." This seems completely arbitrary. \$\endgroup\$ – Fatalize Jul 11 '17 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 '17 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 '17 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\$ – Skidsdev Jul 11 '17 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\$ – Greg Martin Jul 11 '17 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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Your code fails on the test case f "1". Expected output is undefined \$\endgroup\$ – maple_shaft Jul 11 '17 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 '17 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\$ – Christian Sievers Jul 11 '17 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
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Does this multiply by 10 or something? \$\endgroup\$ – Erik the Outgolfer Jul 11 '17 at 12:15
  • \$\begingroup\$ Incorrect output for 1112333, outputs 73926 when it should output 36963 \$\endgroup\$ – Skidsdev Jul 11 '17 at 12:16
  • \$\begingroup\$ @Mayube: Fixed now. \$\endgroup\$ – Shaggy Jul 11 '17 at 12:25
  • \$\begingroup\$ @EriktheOutgolfer; I'd missed the rule about ignoring runs of length 1. \$\endgroup\$ – Shaggy Jul 11 '17 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\$ – ETHproductions Jul 11 '17 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!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Save a byte by using instead of žhS. \$\endgroup\$ – Erik the Outgolfer Jul 11 '17 at 12:22
  • \$\begingroup\$ @EriktheOutgolfer Ah! I knew there was a way to do it in 2 bytes. \$\endgroup\$ – Okx Jul 11 '17 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>

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ -9 bytes: s=>s.replace(/(.)\1+/g,m=>n*=m,n=1)&&n (I haven't tested it yet) \$\endgroup\$ – Herman L Jul 11 '17 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 '17 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 '17 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 '17 at 13:02
2
\$\begingroup\$

Jelly, 7 bytes

ŒgḊÐfḌP

Try it online!

-1 thanks to Leaky Nun.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ 7 bytes? \$\endgroup\$ – Leaky Nun Jul 11 '17 at 12:35
  • \$\begingroup\$ @LeakyNun Ooh clever trick... \$\endgroup\$ – Erik the Outgolfer Jul 11 '17 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.

| improve this answer | |
\$\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
      /
    )
}
| improve this answer | |
\$\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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ You can get this to 42 bytes by using the multiplication stage from Retinas wiki. \$\endgroup\$ – ovs Jul 11 '17 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!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Mathematica, 61 bytes

Times@@FromDigits/@Select[Split@IntegerDigits@#,Length@#>1&]&
| improve this answer | |
\$\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!

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ [1,int(l)][len(l)>1] is equivalent to int(l)**(len(l)>1) \$\endgroup\$ – Leaky Nun Jul 11 '17 at 12:41
  • \$\begingroup\$ Would l='' instead of l='0' work? \$\endgroup\$ – Leaky Nun Jul 11 '17 at 12:42
  • \$\begingroup\$ no, the int(l) would throw an error if the string was empty \$\endgroup\$ – Felipe Nardi Batista Jul 11 '17 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!

| improve this answer | |
\$\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!

| improve this answer | |
\$\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
| improve this answer | |
\$\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.

| improve this answer | |
\$\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...

| improve this answer | |
\$\endgroup\$

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.