Reduza um número pelo maior dígito

33

Tarefa:

Dado um número inteiro no sistema de números decimais, reduza-o para um único dígito decimal da seguinte maneira:

  1. Converta o número em uma lista de dígitos decimais.
  2. Encontre o maior dígito, D
  3. Remova D da lista. Se houver mais de uma ocorrência de D, escolha a primeira da esquerda (na posição mais significativa), todas as outras devem permanecer intactas.
  4. Converta a lista resultante em um número decimal e multiplique por D.
  5. Se o número for maior que 9 (tem mais de 1 dígito decimal), repita todo o procedimento, inserindo o resultado nele. Pare quando você obtiver um resultado de um dígito.
  6. Exibe o resultado.

Exemplo:

26364 -> 
1. 2 6 3 6 4 
2. The largest digit is 6, so D=6
3. There are two occurrences or 6: at positions 1 and 3 (0-based). We remove the left one,
    at position 1 and get the list 2 3 6 4 
4. we convert the list 2 3 6 4 to 2364 and multiply it by D:
   2364 * 6 = 14184
5. 14184 is greater than 9 so we repeat the procedure, feeding 14184 into it.

Continuamos repetindo o procedimento para 14184 e assim por diante e passamos pelos seguintes resultados intermediários, chegando finalmente a 8:

11312
3336
1998
1782
1376
952
468
368
288
224
88
64
24
8

Portanto, o resultado para 26364 é 8.

Entrada: um número inteiro / uma sequência que representa um número inteiro

Saída: um único dígito, o resultado da redução aplicada ao número.

Casos de teste:

9 -> 9
27 -> 4
757 -> 5
1234 -> 8
26364 -> 8
432969 -> 0
1234584 -> 8
91273716 -> 6

Isso é , então as respostas mais curtas em bytes em cada idioma vencem.

Galen Ivanov
fonte
3
Qual é Se o número for maior que 10 ou tiver mais de 1 dígito decimal . O número 10 tem mais de um dígito decimal, mas não é maior que dez.
Adám
@ Adám Ao codificar lógicas, deveria 10 -> 10?
19717 Ian H.
1
@ Adám Você está certo, eu deveria ter escrito "maior que 9". Vou editar a descrição. Obrigado!
Galen Ivanov #
Alguém examinou o histograma dessa função em busca de regiões suficientemente grandes? Parece ter muitos zeros; Eu também tenho muitos 8s enquanto componho os casos de teste.
Galen Ivanov
2
Além disso, um número divisível acaso por 4 tem 3/5 probabilidade do produto dos dois dígitos última sendo divisível por 8.
Ørjan Johansen

Respostas:

18

05AB1E , 6 bytes

Código:

[Dg#à*

Usa a codificação 05AB1E . Experimente online!

Explicação

[Dg#     # While the length of the number is not 1
    à    # Extract the largest element from the current number
     *   # Multiply it with the leftover number
Adnan
fonte
11

JavaScript (ES6), 49 bytes

f=n=>n>9?f(""+n.replace(m=Math.max(...n),"")*m):n

Recebe entrada como uma representação de seqüência de caracteres de um número inteiro, como f("26364").

Casos de teste

Justin Mariner
fonte
6

Pitão , 16 bytes

.WtH`*s.-ZKeSZsK

Recebe entrada como uma String. Experimente aqui! (Alternativa: .WtH`*s.-ZeSZseS)

Pitão , 18 bytes

.WgHT*s.-`ZKeS`ZsK

Recebe a entrada como um número inteiro. Experimente aqui!

Como funciona

16 byter

.WtH` * s.-ZKeSZsK ~ Programa completo.

.W ~ Tempo funcional. Enquanto A (valor) é verdadeiro, valor = B (valor).
                 ~ O valor final é retornado.
  tH ~ A, condição: O valor [1:] é verdadeiro? O comprimento é ≥ 2?
    `* s.-ZKeSZsK ~ B, levantador.
       .- ~ Subtração Bagwise, usada para remover o dígito mais alto, com ...
         Z ~ O valor atual Z e ...
          KeSZ ~ O dígito mais alto de Z (como uma String). Também atribui a uma variável K.
      s ~ Lançado para um número inteiro.
     * ~ Multiplicado por ...
              sK ~ O dígito mais alto.
    `~ Converta em uma String.

18 byter

.WgHT * s.-`ZKeS`ZsK ~ Programa completo.

.W ~ Tempo funcional. Enquanto A (valor) é verdadeiro, valor = B (valor).
                   ~ O valor final é retornado.
  gHT ~ A, condição: o valor (H) é ≥ 10?
     * s.-`ZKeS`ZsK ~ B, levantador.
       .- ~ Subtração bagwise (usada para remover a primeira ocorrência).
         `Z ~ A representação em cadeia de Z.
           KeS`Z ~ E o caractere mais alto (lexicograficamente) de Z (dígito mais alto).
                     Também o atribui a uma variável chamada K.
      s ~ Transmitir para inteiro.
     * ~ Multiplique por ...
                sK ~ K convertido para int.

Estar tão próximo de Jelly nesse tipo de desafio é muito bom para Pyth IMO :-)

Mr. Xcoder
fonte
6

Casca , 14 13 12 bytes

Obrigado Zgarb por economizar 1 byte.

Ω≤9oṠS*od-▲d

Experimente online!

Explicação:

Ω≤9            Repeat the following function until the result is ≤ 9
           d     Convert to a list of digits
         -▲      Remove the largest one
       od        Convert back to an integer
   oṠS*          Multiply by the maximum digit
H.PWiz
fonte
12 bytes com alguma reorganização.
Zgarb
@ Zgarb Obrigado, eu estava procurando por algo assim.
H.PWiz
6

R , 99 bytes 95

f=function(x)"if"(n<-nchar(x)-1,f(10^(n:1-1)%*%(d=x%/%10^(n:0)%%10)[-(M=which.max(d))]*d[M]),x)

Experimente online!

Uma função recursiva. A adição f(number)no rodapé pode ser usada para testar outros valores de number. Implementação direta, dé a lista de dígitos e 10^(n:2-2)%*%d[-M]calcula o número com o maior dígito removido.

Giuseppe
fonte
5

Python 2 , 72 bytes

f=lambda n:`n`*(n<=9)or f(int(`n`.replace(max(`n`),'',1))*int(max(`n`)))

Experimente online!

FlipTack
fonte
1
... Eu estava depurando um erro estúpido nisso . Droga, eu fui ninja.
totallyhuman
Estou recebendo um erro na entrada 9
RoryT 19/17/17
Isso parece falhar no caso de teste 432969. "ValueError: literal inválido para int () com base 10: ''"
James Webster
@JamesWebster deve ser corrigido agora.
FlipTack
1
@recursive Não, como se nfosse 0, n*(n<=9)ele ainda seria avaliado como um valor falso, 0, fazendo a recursão continuar e causando um erro, enquanto a string '0'é um valor verdadeiro e, portanto, a recursão é interrompida.
FlipTack 21/11
4

Ruby , 59 bytes

f=->n{m=n.digits.max;n>9?f[n.to_s.sub(m.to_s,"").to_i*m]:n}

Experimente online!

Função lambda recursiva chamada like f[26364].

Justin Mariner
fonte
4

Gelatina , 15 bytes

D×Ṁ$œṡṀ$FḌµ>9µ¿

Experimente online! ou veja a suíte de testes .

Quão?

D×Ṁ$œṡṀ$FḌµ>9µ¿ - Link: number, n
              ¿ - while:
             µ  - ...condition (monadic):
            9   -    literal 9
           >    -    loop value greater than (9)?
          µ     - ...do (monadic):               e.g. 432969
D               -    convert to a decimal list        [4,3,2,9,6,9]
   $            -    last two links as a monad:
  Ṁ             -      maximum                         9
 ×              -      multiply (vectorises)          [36,27,18,81,54,81]
       $        -    last two links as a monad:
      Ṁ         -      maximum                         81
    œṡ          -      split at first occurrence      [[36,27,18],[54,81]]
        F       -    flatten                          [36,27,18,54,81]
         Ḍ      -    convert from base 10              389421  (i.e. 360000 + 27000 + 1800 + 540 + 81)
Jonathan Allan
fonte
4

Haskell , 70 67 66 bytes

Guardado 3 4 bytes graças a nimi!

f x|x<10=x|(a,b:c)<-span=<<(>).maximum$show x=f$read[b]*read(a++c)

Experimente online!

H.PWiz
fonte
Uma recursão explícita é menor que until. Experimente online! .
N
mais um byte para salvar: ...span=<<(>).maximum....
N
Ooh ... Nice :) #
2120 H.PWiz
4

C # (.NET Core) , 126 bytes

int F(int n){var x=(n+"").ToList();var m=x.Max();x.RemoveAt(x.IndexOf(m));return n>9?F(int.Parse(string.Concat(x))*(m-48)):n;}

Experimente online!

Timmeh
fonte
Bem-vindo ao PPCG! Você pode remover um espaço .
Erik the Outgolfer
@EriktheOutgolfer Obrigado, perdi essa.
Timmeh
1
@totallyhuman Obrigado, até 137 depois de alguma refatoração.
precisa
Você pode alterar if(n<10)return n;...return F(...);a um único retorno com ternário-se, assim: int F(int n){var x=(n+"").ToList();var m=x.Max(d=>d);x.RemoveAt(x.IndexOf(m));return n<10?n:F(int.Parse(string.Concat(x))*(m-48));}( 131 bytes )
Kevin Cruijssen
Eu acho que você precisa incluir using System.Linq;(18 bytes) no bytecount.
Ian H.
4

APL (Dyalog) , 36 35 33 bytes

-1 devido a especificações de OP atualizadas. -2 graças a ngn.

Função de prefixo tácito anônimo. Leva inteiro como argumento.

{⍵>9:∇(⌈/×10⊥⊂⌷⍨¨⍳∘≢~⊢⍳⌈/)⍎¨⍕⍵⋄⍵}

Experimente online!

{}Uma função em que está o argumento:

⍵>9: se o argumento for maior que 9, então:

  ⍕⍵ formatar (stringify) o argumento

  ⍎¨ executar (avaliar) cada um (isso nos dá os dígitos como números)

  () Aplique a seguinte função tácita naqueles

   ⌈/ o maior dígito

   × vezes

   10⊥ a decodificação de base 10 de (coleta dígitos)

    todos os dígitos

   ⌷⍨¨ indexado por cada um

   ⍳∘≢ os i ndices do número de dígitos

    é diferente de

   ⊢⍳⌈/ o maior de dígitos i NDEX em toda a lista de dígitos

   recursar (ou seja, chamar a si próprio)

 outro

   retornar o argumento não modificado

Adão
fonte
Não deveria >10ser >9?
Erik the Outgolfer
@EriktheOutgolfer Provavelmente, mas o OP não é realmente claro (contraditório) sobre isso.
Adám 18/11/19
Isso é verdade, mas >9salvaria um byte.
Erik the Outgolfer
@EriktheOutgolfer Updated.
Adám 19/11/19
@ Adám ∇ em vez de ⍣ = para -1 byte: {⍵> 9: ∇ (⌈ / ... ⋄⍵})
ngn
3

Perl 6 ,  45  41 bytes

{($_,{$/=.comb.max;S/"$/"//*$/}...10>*).tail}

Teste-o

{($_,{S/"{.comb.max}"//*$/}...10>*).tail}

Teste-o

Expandido:

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

  (  # generate the sequence

      $_,                      # start the sequence with the input

      {                        # generate the rest of the values in the sequence

          S/                   # find and replace (not in-place)
            "{  .comb.max  }"  # find the max digit and match against it
          //                   # replace it with nothing
          *                    # multiply the result with
          $/                   # the digit that was removed
      }

      ...                      # keep generating values until

      10 > *                   # the value is less than 10

  ).tail                       # get the last value from the sequence
}
Brad Gilbert b2gills
fonte
3

Retina , 67 bytes

{1`(..+)?
1$&;$&
O`\G\d
.+((.);.*?)\2
$1
\d+
$*
1(?=.*;(1+))|.
$1
1

Experimente online! O link inclui os casos de teste com rapidez suficiente para não prejudicar o servidor de Dennis. Explicação:

{1`(..+)?
1$&;$&

Para números de dois dígitos, isso duplica o número com um ;separador, prefixando 1 para a duplicata. Para números de um dígito, esse prefixo 1;é o número.

O`\G\d

Classifique os dígitos da duplicata. (Para números de um dígito, isso não tem efeito.)

.+((.);.*?)\2
$1

Encontre a primeira ocorrência do dígito maior e exclua-o, e também os outros dígitos na duplicata e o 1 extra que foi adicionado anteriormente. (Para números de um dígito, a correspondência falha, então isso não faz nada.)

\d+
$*
1(?=.*;(1+))|.
$1
1

Multiplique o número pelo dígito. Para números de um dígito, isso resulta no número original e o loop termina. Caso contrário, o programa será repetido até que um único dígito seja alcançado.

Neil
fonte
3

C # (.NET Core) , 177 164 + 18 bytes

Guardado 13 bytes graças a @raznagul!

int f(int n){string s=n+"",m=s.Max(d=>d)+"";if(n<10)return n;var x=s.ToList();x.RemoveAt(s.IndexOf(m));int y=int.Parse(string.Join("",x))*int.Parse(m);return f(y);}

Experimente online!

Ian H.
fonte
Você pode mudar s.Length<2para n<10. Além disso, você pode remover o operador ternário e return f(y)no final, pois o caso é tratado ifna próxima etapa da recursão.
raznagul
3

Java 8, 126 104 bytes

n->{for(;n>9;n=new Long((n+"").replaceFirst((n=(n+"").chars().max().getAsInt()-48)+"",""))*n);return n;}

-22 bytes graças a @ OlivierGrégoire .

Explicação:

Experimente aqui.

n->{         // Method with long as both parameter and return-type
  for(;n>9;  //  Loop as long as the number contains more than 1 digit
    n=       //   Replace the current number with:
      new Long((n+"").replaceFirst((n=(n+"").chars().max().getAsInt()-48)+"",""))
             //    Remove the first largest digit from the number,
      *n     //    and multiply this new number with the removed digit
  );         //  End of loop
  return n;  //  Return the result
}            // End of method
Kevin Cruijssen
fonte
111 bytes
Olivier Grégoire
1
104 bytes (o mesmo que acima, mas iterativo em vez de recursivo, também: n>9e reverta as condições em vez de n<10).
Olivier Grégoire
2

Jq 1.5 , 86 bytes

until(.<10;"\(.)"|(./""|max)as$v|index($v)as$x|.[:$x]+.[1+$x:]|tonumber*($v|tonumber))

Expandido

until(
    .<10                    # until number is below 10
  ; "\(.)"                  # convert to string
  | (./""|max) as $v        # find largest digit, call it $v
  | index($v) as $x         # find index of digit
  | .[:$x]+.[1+$x:]         # remove digit
  | tonumber*($v|tonumber)  # convert back to number and multiply by $v
)

Experimente online!

jq170727
fonte
2

Perl 5 , 41 + 1 ( -p) = 42 bytes

$m=(sort/./g)[-1];s/$m//;($_*=$m)>9&&redo

Experimente online!

Xcali
fonte
Falha na entrada de 9. :( mas consertou um pouco e conseguiu obter 41 bytes com uma correção: Experimente online!
Dom Hastings
2

Lua, 137 108 bytes

function f(n)while n>9 do b="0"g=b.gsub g(n,".",function(m)b=math.max(m,b)end)n=b*g(n,b,"",1)end print(n)end

Agradecimentos a Jonathan S por jogar fora 29 bytes.

Experimente online!

MCAdventure10
fonte
1
108 bytes
Jonathan S.
Obrigado. Isso parece digno de uma resposta própria - será vinculado a uma postagem que você fizer, caso contrário, será editada e creditada.
MCAdventure10
Apenas edite-o. Ainda é o seu código, não o escrevi do zero.
Jonathan S.
2

D , 188 186 185 bytes

import std.conv,std.algorithm;T f(T,U=string)(T u){if(u<10)return u;T[]r;u.text.each!(n=>r~=n.to!T-48);T m=r.maxElement;U s;r.remove(r.maxIndex).each!(n=>s~=n.to!U);return f(m*s.to!T);}

Experimente online!

Eu odeio tanto a avaliação preguiçosa. Todas as dicas são bem-vindas!

Zacharý
fonte
2

Lua, 154 bytes

Eu deveria ter algumas maneiras de jogar isso, estou experimentando agora.

n=...z=table
while n+0>9 do
t={}T={}n=n..''n:gsub(".",function(c)t[#t+1]=c T[#T+1]=c
end)z.sort(t)x=t[#t]z.remove(T,n:find(x))n=z.concat(T)*x
end
print(n)

Experimente online!

Explicações

n=...                    -- define n as a shorthand for the argument
z=table                  -- define z as a pointer to the object table
while n+0>9              -- iterate as long as n is greater than 9
do                       -- n+0 ensure that we're using a number to do the comparison
  t={}                   -- intialise two tables, one is used to find the greatest digit
  T={}                   -- the other one is used to remove it from the string
  n=n..''                -- ensure that n is a string (mandatory after the first loop)
  n:gsub(".",function(c) -- apply an anonymous function to each character in n
               t[#t+1]=c -- fill our tables with the digits
               T[#T+1]=c
             end)        
  z.sort(t)              -- sort t to put the greatest digit in the last index
  x=t[#t]                -- intialise x to the value of the greatest digit
  z.remove(T,n:find(x))  -- remove the first occurence of x from the table T 
                         -- based on its position in the input string
  n=z.concat(T)*x        -- assign the new value to n
end                      -- if it still isn't a single digit, we're looping over again
print(n)                 -- output the answer
Katenkyo
fonte
2

PowerShell , 123 bytes

[Collections.ArrayList]$a=[char[]]"$args"
while(9-lt-join$a){$a.remove(($b=($a|sort)[-1]));$a=[char[]]"$(+"$b"*-join$a)"}$a

Experimente online!

Ooof. As matrizes do PowerShell são imutáveis; portanto, precisamos usar a [Collections.ArrayList]conversão longa aqui para podermos ligar .remove()mais tarde.

Recebe entrada $args, converte-a em uma string, depois em char-array e, em seguida, em um ArrayList. Armazena isso em $a. Em seguida, fazemos um whileloop até estarmos abaixo ou abaixo 9. A cada iteração, estamos chamando .removeo maior elemento de $a(feito sorte recebendo o último elemento [-1]), armazenando o maior elemento $bao mesmo tempo. Isso funciona porque os valores ASCII são classificados da mesma maneira que os dígitos literais.

Em seguida, recalculamos $a, novamente como uma charmatriz -e ( ArrayListimplicitamente), convertendo nossa $b(que atualmente é a char) para uma string, depois um int com +e multiplicando isso para $a -joined em uma string (implicitamente convertida em int). Isso satisfaz a parte "multiplicar por D" do desafio.

Finalmente, uma vez que estamos fora do circuito, colocamos $ano pipeline e a saída está implícita.

AdmBorkBork
fonte
2

Pip , 22 21 bytes

Wa>9a:aRAa@?YMXax*:ya

Recebe entrada como um argumento de linha de comando. Verifique todos os casos de teste: Experimente online!

Explicação

Ungolfed, com comentários:

                 a is 1st cmdline arg
W a>9 {          While a > 9:
  Y MXa           Yank max(a) into y
  a RA: a@?y ""   Find index of y in a; replace the character at that position with ""
  a *: y          Multiply a by y
}
a                Autoprint a

Na versão golfed, o corpo do loop é condensado em uma única expressão:

a:aRAa@?YMXax*:y
        YMXa      Yank max(a)
     a@?          Find its index in a
  aRA       x     Replace at that index with x (preinitialized to "")
             *:y  Multiply that result by y (using : meta-operator to lower the precedence)
a:                Assign back to a
DLosc
fonte
2

C 103 , 95 , 90 bytes

a,b;t,m;f(n){for(t=m=0,a=b=1e9;a/=10;)if((t=n/a%10)>m)m=t,b=a;n=n>9?f(m*=n/b/10*b+n%b):n;}

Experimente online!

PrincePolka
fonte
2

Java 8: 115 bytes


-10 bytes graças a Jo King

Infelizmente, você não pode chamar uma função lambda recursivamente, portanto, são necessários 11 bytes extras para o cabeçalho do método. Estou ciente de que há uma resposta Java mais curta que faz um loop, mas decidi criar isso sozinha.

long f(long n){int m=(n+"").chars().max().getAsInt()-48;return n>9?f(new Long((n+"").replaceFirst(""+m,""))*m):n;};

Experimente online

Benjamin Urquhart
fonte
Você pode mover o -48do mapa para o final da mdefinição. Experimente online! Você também tem um espaço em branco extra no seu link TIO
Jo King
@JoKing thanks.
Benjamin Urquhart
1

J, 40 bytes

((]*<^:3@i.{[)>./)&.(10&#.inv)^:(9&<)^:_

Experimente online!

explicação

(      iterate                   )^:(9&<)^:_    NB. keep iterating while the number is > 9
 (     stuff         )&.(10&#.inv)              NB. convert to digits, do stuff, convert back to number
 (           )>./)                              NB. stuff is a hook, with max digit >./  on the right
 (]*<^:3@i.{[)                                  NB. so that in this phrase, ] means "max" and [ means "all digits"
  ]                                             NB. the max digit...
   *                                            NB. times...        
    <^:3@                                       NB. triple box...
         i.                                     NB. the first index of the max in the list of all digits
           {                                    NB. "from" -- which because of the triple box means "take all indexes except..."
            [                                   NB. from all the digits of the number
Jonah
fonte
1
Hoje eu aprendi sobre a seleção da caixa tripla, obrigado!
Galen Ivanov
1

PowerShell , 230 bytes

$n="$args";do{$n=$n.ToString();$a=@();0..$n.Length|%{$a+=$n[$_]};$g=[convert]::ToInt32(($a|sort|select -last 1),10);[regex]$p=$g.ToString();[int]$s=$p.replace($n,'',1);if($n.Length-eq1){$n;exit}else{$r=$s*$g}$n=$r}until($r-lt10)$r

Experimente online!

Desperdiçou demais com todo o tipo de elenco.

raiz
fonte
1

PHP, 82 77 + 1 bytes

for($n=$argn;$n>9;)$n=join("",explode($d=max(str_split($n)),$n,2))*$d;echo$n;

Execute como pipe -nRou experimente online .

Titus
fonte
1

dc , 98 85 bytes

?dsj[0dsosclj[soIlc^sr0]sn[I~dlo!>nrlc1+scd0<i]dsixljdlr%rlrI*/lr*+lo*dsj9<T]sT9<Tljp

Muito obrigado a esta resposta pela idéia de utilizar~ na extração de dígitos de um número, resultando em dois bytes salvos sobre a versão original do código.

Este foi um pouco para concluir em dc com seus recursos inexistentes de manipulação de strings.

Experimente online!

R. Kap
fonte
1

Bash, 80 bytes

Usa os pacotes Utilitários Principais (para sorte tail) e grep.

while((n>9));do m=$(grep -o .<<<$n|sort|tail -n1);n=$((${n/$m/}*m));done;echo $n

Como funciona?

while (( n > 9 )); do  # C-style loop conditional
    grep -o .          # Separate the string into one char per line
              <<< $n   # Use the content of variable `n` as its stdin
    | sort             # Pipe to `sort`, which sorts strings by line
    | tail -n 1        # Take the last line

m=$(                 ) # Assign the output of the command chain to `m`
n=$((          ))      # Assign the result of the evaluation to n
     ${n/$m/}          # Replace the first occurrence of $m with empty
             *m        # ... and multiply it by the value of `m`
done; echo $n          # After loop, print the value of `n`
iBug
fonte