g | x | w | all
Bytes Lang Time Link
054Ruby p250510T043946ZValue In
042Juby221214T161113ZJordan
017Uiua SBCS240213T062402Zchunes
006Vyxal 3 g240212T222620Zpacman25
011MATL170712T012245ZSuever
023K ngn/k201106T192250Zcoltim
068Groovy201108T032812ZM. Justi
009Japt h201106T150428ZShaggy
069Haskell170712T104436Zbartavel
00505AB1E170711T223619ZAdnan
019Japt170712T170739ZOliver
013Japt170711T225654ZETHprodu
025Braingolf170712T103341ZMayube
022CJam170712T101130ZErik the
065JavaScript ES6170712T055716ZArnauld
096R170711T225105ZRudier
042Mathematica170711T223602ZZaMoC
008Husk170712T065741ZZgarb
008Brachylog170712T064300ZFatalize
050Perl 5170712T054031ZDada
009Jelly170711T230722ZAdalynn
113PHP170711T225124ZJör
096Python 3170711T223724Znotjagan
011Pyth170711T223410ZPurkkaKo
104R170711T222935ZGiuseppe

Ruby -p, 54 bytes

$_="#{eval gsub(/(.)\1*/){?++$&.chars*?*}}"while~/$/>1

Attempt This Online!

J-uby, 42 bytes

:!~&(:digits|:slice_when+:!=|:sum+(:/&:*))

Attempt This Online!

Explanation

:!~ & (:digits | :slice_when + :!= | :sum + (:/ & :*))

:!~ & (                                              )  # Apply the following function until F(x) == x
       :digits |                                        #   Get digits
                 :slice_when + :!= |                    #   Group like elements (slice between unequal)
                                     :sum + (:/ & :*)   #   Sum products

Uiua SBCS, 20 17 bytes

⍥(/+⊜/×+1.-@0°⋕)∞

Try it!

Vyxal 3 g, 6 bytes

ᵡλġᵛΠ∑

Try it Online!

MATL, 11 bytes

`!UY'^sVtnq

Try it at MATL Online

Explanation

        % Implicitly grab input as a string
`       % Do...while loop
  !U    % Convert the string to an array of numbers (the digits)
  Y'    % Perform run-length encoding
  ^     % Raise the digits to the power corresponding to the number of times they
        % occurred consecutively
  s     % Sum the result
  V     % Convert to a string
  tn    % Duplicate and determine the number of characters in the string
  q     % Subtract one, causes the loop to continue until it's a single digit
        % Implicit end of do...while loop and display

K (ngn/k), 17 23 bytes

+6 bytes from handling cases where the same digit is present in multiple chunks

{+/*/'(&~=':x)_x:10\x}/

Try it online!

Fails on inputs too large for 64-bit integers.

Groovy, 69 68 bytes

f={r->r>9?f((r=~/(.)\1*/)*.tap{}.sum{n->n[1]as int**n[0].size()}):r}

Requires Groovy 3.x.

Explanation

If the input is single digit, returns it, else recursively calls the function on the next pass of the algorithm.

f={r->r>9?f(...):r}     : Recursively call algorithm if input > 9, else return input
r=~/(.)\1*/)            : Regex capture of each run, e.g. [["444", "4"], ["2", "2"]]
*.tap{}                 : Convert Matcher to List<List<Integer>> so we can call sum()
.sum{...}               : Apply the closure to each List element and sum them
n[1]as int**n[0].size() : <digit>^<run length> from e.g. ["444", "4"]

Japt -h, 9 bytes

I/O as digit arrays

£=òÎx_×Ãì

Try it

£=òÎx_×Ãì     :Implicit input of digit array
£             :Map
 =            :  Reassign to U
  ò           :  Partition between elements where
   Î          :    The sign of their difference in truthy (not zero)
    x         :  Reduce by addition
     _        :  After passing each through this function
      ×       :    Reduce by multiplication
       Ã      :  End function
        ì     :  Split to digit array
              :  Implicit output of last element

Haskell, 103 70 69 bytes

import Data.List
until(<10)$sum.map product.group.map(read.pure).show

Try it online!

05AB1E, 7 6 5 bytes

Thanks to Emigna for saving a byte!

vSγPO

Uses the 05AB1E encoding. Try it online!

Japt, 19 bytes

=ò¦ m¬®×Ãx)<A?U:ßUs

Try it online!

Explanation:

=ò¦ m¬®×Ãx)<A?U:ßUs
=                    // Implicit U (input) =
 ò¦                  //   Split the input into an array of consecutive digit runs
    m¬               //   Split each inner array: ["1","22","333"] -> [["1"],["2","2"],["3","3","3"]]
      ®              //   Map; At each item:
       ×             //     Get the product of each run
        Ã            //   }
         x           //   Sum
           <A        // <10
             ?       // If true:
              U      //   return U
               :     // Else:
                ß    //   Run the program again; Pass:
                 Us  //     U, cast to a string

Japt, 17 15 13 bytes

e".+"_¬ò¦ x_×

Test it online! Takes input as a string.

Still not satisfied with this answer...

Explanation

e".+"_  ¬ ò¦  x_  ×
e".+"Z{Zq ò!= xZ{Zr*1}}

e".+"                     Repeatedly replace all matches of /.+/ (the entire string)
     Z{               }   Z with this function:
       Zq                   Split Z into chars.
          ò!=               Partition at inequality; that is, split into runs of equal items.
              xZ{    }      Take the sum of: for each item in Z:
                 Zr*1         the item reduced by multiplication (i.e. the product).
                          This procedure is repeated until the same result is yielded twice.
                          Implicit: output result of last expression

Braingolf, 25 bytes

!L1-Mv[RG(d&*)&+!L1-Mv>]R

Will add a TIO link once I get Dennis to pull the latest version, as using greedy operators inside (...) loops is currently broken on TIO

Explanation

!L1-Mv[RG(d&*)&+!L1-Mv>]R  Implicit input from commandline args
!L1-M                      Push length of input minus 1 to stack2
     v                     Switch to stack2
      [.........!L1-Mv>]   While length of input > 1..
       RG                  Split into digit runs
         (d&*)             Product of digits of each item in stack
              &+           Sum stack
                        R  Return to stack1
                           Implicit output from stack

CJam, 22 bytes

r_,{1/e`Wf%::i::#:+s}*

Try it online!

JavaScript (ES6), 77 73 67 65 bytes

Saved 2 bytes thanks to @CraigAyre

f=s=>s>9?f(''+eval(s.replace(/(.)\1*/g,s=>'+'+[...s].join`*`))):s

How?

The input s is transformed into an arithmetic expression with:

s.replace(/(.)\1*/g, s => '+' + [...s].join`*`)

For instance, 1234444999 becomes +1+2+3+4*4*4*4+9*9*9.

We evaluate this expression and do a recursive call with the result until it's boiled down to a single decimal digit.

Test cases

f=s=>s>9?f(''+eval(s.replace(/(.)\1*/g,s=>'+'+[...s].join`*`))):s

console.log(f("1234444999"                    )) // = 1
console.log(f("222222222222222"               )) // = 8
console.log(f("111222333444555666777888999000")) // = 9
console.log(f("11122233344455566677788899"    )) // = 8
console.log(f("1112223334445"                 )) // = 6
console.log(f("14536"                         )) // = 1
console.log(f("99"                            )) // = 9

R, 97 96 bytes

a=scan(,"");while(nchar(a)>1){a=paste(sum(strtoi((b<-rle(el(strsplit(a,""))))$v)^strtoi(b$l)))}a

Slightly different approach than the other answer using R.

This answer makes use of the rle function, which compute[s] the lengths and values of runs of equal values in a vector.

-1 bytes thanks to @Giuseppe !

Mathematica, 55 42 bytes

#//.i_:>Tr[Times@@@Split@IntegerDigits@i]&

-13 bytes from @JungHwan Min. Thanx!

in case someone wants to use this as a random-digit-generator,
here is the tally of the first 100.000 numbers

{{1, 17320}, {2, 4873}, {3, 10862}, {4, 11358}, {5, 10853}, {6, 9688}, {7, 11464}, {8, 10878}, {9, 12704}}
or if you gamble, don't put your money on 2!

Husk, 8 bytes

ωöṁΠgmis

Takes and returns an integer. Try it online!

Explanation

Having a built-in for base 10 digits would be nice...

ωöṁΠgmis
ω         Iterate until a fixed point is found
 ö        the composition of the following four functions:
       s   convert to string,
     mi    convert each digit to integer,
    g      group equal adjacent integers,
  ṁΠ       take product of each group and sum the results.

Brachylog, 8 bytes

Ḋ|ẹḅ×ᵐ+↰

Try it online!

Explanation

Ḋ          Input = Output = a digit
 |         Or
  ẹ        Split into a list of digits
   ḅ       Group consecutive equal elements together
    ×ᵐ     Map multiply
      +    Sum
       ↰   Recursive call

Perl 5, 50 bytes

49 bytes of code + -p flag.

s/(.)\1*/"+".$&=~s%.%$&*%gr.1/ge while($_=eval)>9

Try it online!

Jelly, 9 bytes

DŒgP€SµÐL

Try it online

Here's how it works:

D  - input as a list of digits
Œg - group runs of equal elements
P€ - the product of each element
S  - the sum of the list
µ  - syntax stuff to separate the left from the right
ÐL - repeat until we get a result twice, then return that result.

PHP, 113 bytes

for(;9<$a=&$argn;$a=$s){$s=0;preg_match_all('#(.)\1*#',$argn,$t);foreach($t[0]as$v)$s+=$v[0]**strlen($v);}echo$a;

Try it online!

Python 3, 96 bytes

from itertools import*
f=lambda n:n*(n<10)or f(sum(int(k)**len([*g])for k,g in groupby(str(n))))

Try it online!

Pyth, 11 bytes

us^M_MrjGT8

Try it online. Test suite.

R, 114 104 bytes

n=scan(,'');while(nchar(n)>1){n=el(strsplit(n,''));b=table(n);n=as.character(sum(strtoi(names(b))^b))};n

reads from stdin; returns the answer as a string.

Try it online!