Como a matemática funciona no mundo de Anastasiya?

44

Fundo:

As operações matemáticas padrão, como adição e multiplicação básicas no mundo real, funcionam da seguinte maneira:

12 + 123 = 135

e

12 * 123 = 1476

Isso não é interessante e chato! Muitas escolas já estão interpretando isso como prática, prática, prática de algoritmos formais. Isso implica uma dieta matemática bastante rígida e chata e não é o que se pretende neste desafio. Prepare-se para se divertir um pouco no nosso amado site.

Considere o processo de adicionar dois números inteiros positivos e, em seguida, adicionar novamente todos os dígitos do resultado. Repetindo com a adição até que apenas um dígito seja obtido. Por exemplo:

  1. O resultado de 12 + 123é 135.
  2. Adicionando todos os dígitos de 135, obtemos 1 + 3 + 5 = 9.

O número de etapas necessárias para obter um valor de um dígito 9 nesta adição repetida é 2.

Como no processo anterior da adição, a multiplicação de dois números inteiros positivos segue o mesmo processo. Multiplique todos os dígitos do resultado e, em seguida, repita esse processo até restar apenas um dígito. Veja o exemplo acima:

  1. O resultado 12 * 123é 1476.
  2. Multiplique todos os dígitos de 1476 que obtemos 1 * 4 * 7 * 6 = 168.
  3. Multiplique novamente todos os dígitos de 168 que obtemos 1 * 6 * 8 = 48.
  4. Multiplique novamente todos os dígitos de 48 que obtemos 4 * 8 = 32.
  5. Multiplique mais uma vez todos os dígitos de 32 que obtemos 3 * 2 = 6.

O número de etapas necessárias para obter um valor de um dígito 6 nessa multiplicação repetida é 5.

Para esse desafio e para evitar qualquer uso indevido de notações matemáticas, apresento essas duas notações falsas: (+)e (*), mas você pode usar qualquer notação que desejar , que funciona da seguinte maneira:

  1. A operação do processo de adição repetida para obter um único valor é 12 (+) 123 = 9.
  2. A operação do processo de multiplicação repetida para obter um único valor é 12 (*) 123 = 6.

Desafio:

O desafio é escrever um programa ou uma função que possa executar as duas operações, conforme explicado na seção em segundo plano: (+)e (*).

Entrada:

As entradas do programa ou da função são dois números inteiros positivos e uma operação é (+)e (*). O formato da entrada é uma escolha arbitrária do programador . Você pode formatar a entrada, por exemplo, a (+) bou F(a, (+), b)ou qualquer formato que desejar.

Resultado:

A saída do programa ou da função deve conter o resultado da operação e o número de etapas necessárias com o formato freestyle, conforme desejado.

Casos de teste (ignore o formato de entrada e saída):

    81 (+) 31       -->   (4 ; 2)
    351 (+) 14568   -->   (6 ; 3)
    21 (*) 111      -->   (8 ; 3)
    136 (*) 2356    -->   (0 ; 2)

Regras gerais:

  • Isso é , então a resposta mais curta em bytes vence o desafio.
    Não permita que a esolangs o desencoraje de postar uma resposta em idiomas comuns. Aproveite esse desafio, fornecendo uma resposta o mais curta possível com sua linguagem de programação. Se você postar uma resposta inteligente e uma explicação clara, sua resposta será apreciada (daí os votos positivos), independentemente da linguagem de programação usada.
  • As regras padrão se aplicam à sua resposta, para que você possa usar STDIN / STDOUT, funções / método com os parâmetros adequados, programas completos, etc. A escolha é sua.
  • Se possível, seu programa pode lidar adequadamente com grandes números. Caso contrário, tudo ficará bem.

Que comece o jogo!!

Anastasiya-Romanova 秀
fonte
A adição repetida parte ( raiz digitais ) é essencialmente uma duplicata de codegolf.stackexchange.com/q/1128/194
Peter Taylor
4
Ótima primeira pergunta! E reconheço o formato e as frases das regras gerais de minhas próprias perguntas. ;)
Kevin Cruijssen
4
@KevinCruijssen Yup. está certo. Como ele não possui direitos autorais, eu o duplico sem a sua permissão. Hehehe: D
Anastasiya-Romanova 秀
4
@ Anastasiya-Romanova 秀 "sem direitos autorais"? No século XXI? Não; tudo aqui é o CC-BY-SA 3.0. A permissão é concedida quando o conteúdo é enviado. Verifique o rodapé do site.
Mindwin
1
@ BradGilbertb2gills Sim, é claro. É declarado no post a propósito. Citação: "O formato da entrada é uma escolha arbitrária do programador".
Anastasiya-Romanova # 24/16

Respostas:

11

Dyalog APL , 33 32 30 29 bytes

Isso estende o APL para incluir a notação de prefixo +/A n₁ n₂e ×/A n₁ n₂. (De fato, você pode usar qualquer operação à esquerda do /A.) Retorna uma lista de {resultado, número de repetições}.

A←{(⊃,≢)⍺⍺{∪⍵,⍨⍺⍺⍎¨⍕⊃⍵}⍣≡⍺⍺⍵}

A←{definir uma função de ordem superior em termos de função da esquerda ⍺⍺e argumento da direita

(⊃,≢) o primeiro elemento de, seguido pela contagem de

⍺⍺{a função fornecida ( +/por soma ou ×/por produto) alimentada à função de ordem superior

os elementos únicos de

⍵,⍨ o argumento anexado a

⍺⍺ a função alimentada aplicada a

⍎¨ a avaliação de cada personagem de

a representação de caracteres de

⊃⍵ o primeiro elemento do argumento

}⍣≡ aplicado repetidamente até que o resultado seja idêntico ao argumento, começando com

⍺⍺⍵a função originalmente alimentada ( +/ou ×/) aplicada ao argumento original

} [fim da definição da função de ordem superior]

TryAPL online! ( foi copiado epor motivos de segurança.)

Agradecemos a @ngn por salvar um byte.


0 bytes (em tom de brincadeira)

O Dyalog APL, na verdade, já tem suporte total para a matemática Anastasiyan; em vez de (+)e (×), usa +{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}e ×{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}.

Tente 81 +{(⊃,≢)⍺⍺{∪⍵,⍨⍺⍺e¨⍕⊃⍵}⍣≡⍺⍺/⍺⍵} 31e 21 ×{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/e¨⍕⍵}⍣=⍵⍺⍺⍨⍺} 111.

Adão
fonte
Obrigado pela resposta, (+1). Ele pode lidar com entradas de grande número?
Anastasiya-Romanova 秀
1
Se definir ⎕FR←1287(ou seja, utilizar IEEE 754-2008 128 bits decimal M ponto-loating R ePresentation) e ⎕PP←34(isto é, utilização de 34 caracteres P rint P recision), pode utilizar inteiros abaixo 10³⁴.
Adám 24/08/16
Hmm, embora tenha total apoio, não são +{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}e ×{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}ainda muito poucos bytes? Estou confuso sobre como isso é 0 bytes ..: S
Kevin Cruijssen
3
@KevinCruijssen O OP permite qualquer notação de entrada. Portanto, se um idioma suportasse a matemática Anastasiyan de notação padrão pronta para uso, o glifo com vários caracteres (+)seria o Anastasiyan +. O Dyalog APL suporta matemática Anastasiyan, mas usa um glifo de vários caracteres diferente, assim como *significa poder e você precisa ×multiplicar, enquanto /significa replicação e ÷divisão.
Adám 24/08/16
1
@ Adám Ah, ok, isso faz sentido. É meio que dobrar as regras do OP, mas não quebrá-las. Ainda é bastante estranho que em vez de (+)você ter +{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}como entrada, mas como o OP realmente declarou que qualquer formato de entrada serve, você pode usar a função como parâmetro. Hmm, gostaria de saber se isso também é possível em outras linguagens de programação que suportam funções como entrada.
Kevin Cruijssen
8

Haskell, 108 bytes

f=map(read.pure).show
g h=(\x->(h.f$last x,length x+1)).takeWhile(>10).iterate(h.f)
(a#b)o=g(foldr1 o)$o a b

Define a função #que tem antes ae be então o operador o. Curiosidade: isso funciona com qualquer operador (na verdade, qualquer função) que você quiser!

ThreeFx
fonte
Obrigado pela resposta, (+1). Ele pode lidar com entradas de grande número?
Anastasiya-Romanova 秀
4
@ Anastasiya-Romanova 秀 Sim, ele pode lidar com números tão grandes quanto a sua RAM, pois o Integertipo de Haskell é ilimitado.
ThreeFx
8

Pyke, 16 bytes

RE`DltImbRoKr)oh

Experimente aqui!

RE               - evaluate the input as Pyke code
                 -  (`B` is product and `s` is sum, the second line is a tuple)
  `              - i = str(^)
    ltI      )   - if len(i) != 1:
       mb        -   map(i, int)
         R       -   get the `B` or `s` from input
          oK     -   o++
            r    -   goto_start()
              oh - o++ + 1

Toma multiplicar como Be adicionar como s. As duas entradas numéricas são separadas por vírgulas.

Azul
fonte
1
Agradável! Podemos obter uma explicação?
Emigna
Obrigado pela resposta, (+1). Ele pode lidar com entradas de grande número?
Anastasiya-Romanova #
@ Anastasiya-Romanova秀ele deve ser capaz de lidar com números arbitrários
Azul
Não consigo testar seu código porque a Web está bloqueada, pois viola a política de uso da Internet dos meus pais. T_T
Anastasiya-Romanova,
Algo assim: Página da Web bloqueada! Você tentou acessar uma página da Web que viola sua política de uso da Internet. URL: pyke.catbus.co.uk/?code=RE%60DltImbRoKr%29oh&input=B%0A21%2C+111&warnings=0 Categoria: Sem classificação
Anastasiya-Romanova 秀
8

JavaScript (ES6), 59

Função recursiva, o formato de entrada é adaptado para simplificar a chamada recursiva:

  • operador: '+' ou '*'
  • operandos: matriz de dois valores
f=(o,v,s=1,t=eval(v.join(o)))=>t>9?f(o,[...t+''],s+1):[t,s]

Teste

f=(o,v,s=1,t=eval(v.join(o)))=>t>9?f(o,[...t+''],s+1):[t,s]

;[
  [81,'+',31,     /* -> */ 4, 2]
, [351,'+',14568, /* -> */ 6, 3]
, [21,'*',111,    /* -> */ 8, 3]
, [136,'*',2356,  /* -> */ 0, 2]
].forEach(t=>{
  var [a,o,b,k1,k2] = t,
      [r,s]=f(o,[a,b]);
  console.log(k1==r && k2==s ? 'OK':'KO',a,o,b,'->',r,s)
})  
  

edc65
fonte
Obrigado pela resposta, (+1). Ele pode lidar com entradas de grande número?
Anastasiya-Romanova 秀
1
@ Anastasiya-Romanova秀até o limite de formato numérico javascript, 53 bits de precisão (17 dígitos decimais)
edc65
8

Python 2, 60 bytes

f=lambda s,c=0:s[1:]and f(min(s).join(`eval(s)`),c+1)or(s,c)

Input é uma string como 81+31, output é uma tupla de uma string singleton e um contador (por exemplo ('4', 2),.

Teste em Ideone .

Dennis
fonte
Se pegar a entrada como uma matriz de cordas e uma única corda é permitido, por exemplo, f(['81', '31'],'+'), mais um byte pode ser salvo, mas que se sente como esticar as regras um pouco longe demais ...
Dennis
... caso em que eu mesmo ir tão longe e considerar passando operator.addou operator.mulrespectivamente;)
Tobias KIENZLER
7

Pyth, 16

eJ.uvjhQ`N.vQ)lJ

Toma entrada como "+ 123 12"para adição e "* 123 12"multiplicação. Saídas como result<linefeed>steps.

Experimente aqui ou execute um Conjunto de Testes , mas observe que isso depende de avaliação, portanto, apenas a variante de adição funcionará no interpretador online. A multiplicação funciona corretamente com o intérprete offline.

Isso usa a função de redução cumulativa para criar uma lista de resultados intermediários, portanto "+ 351 14568", obtemos [14919, 24, 6]. Isso funciona porque os números de um dígito são um ponto fixo da adição e multiplicação de Anastasiya. Em seguida, obtemos apenas o último elemento da matriz, bem como o comprimento da matriz.

Isso funcionará para números arbitrariamente grandes, pelo menos até você ficar sem memória.

FryAmTheEggman
fonte
7

R, 175 167 164 140 134 127 126 119 bytes

function(G,S,D){i=1;O=switch(S,"+"=sum,prod);x=O(G,D);while(x>9){i=i+1;x=O(strtoi(strsplit(paste(x),"")[[1]]))};c(x,i)}

Ungolfed:

f=function(G,S,D) #The function takes : the left operand, the operation symbol (between quote marks)
                  #and then the right operand
i=1               #That's the counter

O=switch(S,"+"=sum,prod)     #`O` takes the value `sum` if `S` matches `+`, `prod` 
                             #(which is the next agument) if not. 

x=O(G,D)                     #Does the first operation

while(nchar(x)>1)                 #While the number of character of the result 
                                  #of the operation is not of length 1, i.e., an integer :

    i=i+1                                    #Increase the counter
    x=O(strtoi(strsplit(paste(x),"")[[1]]))  #Apply the operation `O` to the first operation and 
                                             #the eventual subsequent ones

c(x,i)                                 #Outputs the result and the counter

ifelseestá de volta ! Sim !
Nop

Uso:

Special addition
> f(31,"+",81)
[1] 4 2

Special multiplication
> f(136,"*",2356)
[1] 0 2

Muito obrigado a @plannapus por jogar fora 24 bytes!
-7 bytes graças a uma boa ideia do @Vlo !

Frédéric
fonte
Sim, adicione explicações, já que eu amo o R! Este é o meu segundo idioma após o VBA. (+1)
Anastasiya-Romanova ·
1
@ Anastasiya-Romanova D: Feito!
Frédéric
@ plannapus: Muito bom! Muito obrigado !
Frédéric
1
@ Frédéric bom uso de strtoi! Mais 4 bytes você me derrotou.
Plannapus 26/08/16
1
Parece que você pode obter ainda mais um byte incluindo a definição de O na atribuição de x na primeira operação: x = (O = alternar (S, soma, `*`)) (G, D) ;.
rturnbull
6

05AB1E , 20 15 bytes

[¼¹iOëP}Dg#S]¾‚

Explicação

[       Dg# ]    # loop until number is single digit
 ¼               # increase counter
  ¹iO            # if operation is addition, sum list
     ëP}         # else take product of list
           S     # split into a list of digits
             ¾‚  # pair final number with counter and output

Operador é 1 para adição, 0 para multiplicação.

Experimente online

Emigna
fonte
Obrigado pela resposta, (+1). Ele pode lidar com entradas de grande número?
Anastasiya-Romanova #
@ Anastasiya-Romanova 秀 Não vejo uma razão pela qual não. Você tem um exemplo?
Emigna
Seu programa foi testado para esse tipo de entradas, por isso aperfeiçoa :)
Anastasiya-Romanova秀
6

Geléia , 11 10 bytes

Dj⁹VµÐĿḊĖṪ

Entrada é um par de números e ou +ou ×.

Experimente online! ou verifique todos os casos de teste .

Como funciona

Dj⁹VµÐĿḊĖṪ  Main link. Left argument: [x, y] (integers). Right argument: + or ×

    µÐĿ     Repeatedly execute the chain to the left, initially with argument
            [x, y], then with the previous return value. Stop when the results are
            no longer unique, and return the array of all intermediate results.
D           Decimal; convert the integers [x, y] or the return value z to base 10.
 j⁹         Join, separating by the link's right argument, i.e., '+' or '×'.
   V        Evaluate the result. This casts the previous return value to string,
            so, e.g., [8, 1, '+', 3, 1] becomes "81+31" before evaluation.
       Ḋ    Dequeue; discard the first intermediate result, i.e., [x, y].
        Ė   Enumerate; prefix each integer in the array with its 1-based index.
         Ṫ  Tail; extract the last index-value pair.
Dennis
fonte
6

Código da máquina ARM, 48 bytes

Despejo hexagonal:

b570 2a00 bf0c 1840 4348 2101 230a e00c 3101 0015 fbb0 f6f3 fb06 0413 2a00 bf0c 192d 4365 0030 d1f5 0028 280a d2f0 bd70

Esta função não depende de nenhuma chamada do sistema ou função de biblioteca. Este é o código Thumb-2, que é uma codificação de instruções de comprimento variável (2 ou 4 bytes) para o ARM de 32 bits. Assim, o valor máximo que ele pode processar é 2 ^ 32-1. 2 bytes podem ser eliminados se não estiverem em conformidade com o AAPCS ( 46 bytes ), pois não teríamos que empilhar registros no início.

Montagem não destruída (sintaxe GNU):

.syntax unified
.text
.global anastasiya
.thumb_func
anastasiya:
    @Input:
    @r0 - First number
    @r1 - Second number
    @r2 - 0 for add, 1 for multiply
    @Output:
    @r0 - Resultant value
    @r1 - Number of steps
    push {r4,r5,r6,lr}
    cmp r2,#0
    ite eq @if r2==0
    addeq r0,r0,r1 @r0+=r1
    mulne r0,r0,r1 @else r0*=r1
    movs r1,#1 @r1 is the number of steps
    movs r3,#10
    b endloop
    loop:
        adds r1,r1,#1 @Increment number of steps
        movs r5,r2 @r5=1 if multiply, 0 if add
        parseDigits:
            udiv r6,r0,r3 @r6=r0/r3
            mls r4,r6,r3,r0 @r4=r0 - r6*r3
            @Last two operations were r4=r0%r3 (r3==10)
            cmp r2,#0
            ite eq @if r2==0
            addeq r5,r5,r4 @r5+=r4
            mulne r5,r5,r4 @else r5*=r4
            movs r0,r6 @r0=r6 (Set r0 to r0/10)
            bne parseDigits @while (r0!=0)
        @Now our new total is in r5
        movs r0,r5 @Put it in r0
    endloop:
        cmp r0,#10
        bhs loop @while (r0 >=10)
    pop {r4,r5,r6,pc} @Return

Teste de script em C:

#include <stdio.h>
unsigned long long anastasiya(unsigned,unsigned,unsigned);

int main(void) {
    unsigned x,y,op;
    printf("Enter first operand, second operand, and 0 for addition or 1 for multiplication.\n");
    scanf("%u%u%u",&x,&y,&op);
    unsigned long long res = anastasiya(x,y,op);
    printf("Result = %u, steps = %u\n",(unsigned)res ,(unsigned)(res >> 32));
}
Ian Chew
fonte
4

R, 130 124 caracteres

Uma abordagem um pouco diferente da @ Frédéric 's:

f=function(a,f,b){b=c(a,b);n=1;while((m<-nchar(d<-switch(f,'(+)'=sum,prod)(b)))>1){b=d%%10^(1:m)%/%10^(1:m-1);n=n+1};c(d,n)}

Recuado, com novas linhas:

f=function(a,f,b){
    b=c(a,b) # Take both numbers
    n=1 #Counter
    while((m<-nchar(d<-switch(f,'(+)'=sum,prod)(b)))>1){
#My own special digit splitter! (d is the result and m is the nb of char of d)
        b=d%%10^(1:m)%/%10^(1:m-1)
        n=n+1
    }
    c(d,n) #Print results
    }

A linha 4 provavelmente precisa de mais explicações:

switch(f,'(+)'=sum,prod) #pick which operator to use
switch(f,'(+)'=sum,prod)(b) # apply it to b
d<-switch(f,'(+)'=sum,prod)(b) #Saves the result in d
nchar(d<-switch(f,'(+)'=sum,prod)(b))#Measures the number of character of d
m<-nchar(d<-switch(f,'(+)'=sum,prod)(b)) #Saves it in m
(m<-nchar(d<-switch(f,'(+)'=sum,prod)(b)))>1 #Checks if it is more than 1

Casos de teste:

> f(12,"(+)",123)
[1] 9 2
> f(12,"(*)",123)
[1] 6 5
> f(351,"(+)",14568)
[1] 6 3
plannapus
fonte
Muito infeliz, você chegou atrasado com esta resposta, mas você tem o meu voto positivo. Obrigado por criar isso em R.
Anastasiya-Romanova 秀
Por que infeliz?
plannapus
Porque se você tivesse chegado primeiro, teria mais votos positivos
Anastasiya-Romanova 秀 25/08
@ Anastasiya-Romanova秀Fair suficiente :)
plannapus
Os pontos de bónus para ter fser tanto o nome da função e um dos seus argumentos :)
JDL
4

Oitava, 85 bytes MATLAB, 123, 114, 105, 94 bytes

Decidiu traduzir isso para a Octace, para aproveitar a indexação direta e aumentar os recursos. Pega a entrada no formulário:, f(a,operator)onde a = [number1, number2], e operator==1fornece o produto e operator==2fornece a soma.

function[x,i]=f(a,o)
g={@prod,@sum}{o};x=g(a);i=1;while(x=g(num2str(x)-48))>9;i++;end

Explicações:

g={@prod,@sum}{o} : Escolhe a função, produto ou soma apropriada e a atribui a g

x=g(a) toma a soma ou o produto das entradas

i=1; ... i++ : Incrementador para contar o número de etapas

while(x=g(num2str(x)-48))>9;
          num2str(x)-48)     % turns a number 123 into an array [1 2 3].
        g(num2str(x)-48))    % Takes the sum or product of the array
      x=g(num2str(x)-48))    % Assign that value to the variable x
      x=g(num2str(x)-48))>9  % Checks if x > 9, continue looping if yes

Removidas duas novas linhas, um espaço e colocadas os dois números de entrada em um vetor, em vez de argumentos separados. Isso economizou 9 bytes, graças ao pajonk! Removido k=@(x)...para salvar outros 11 bytes graças ao beaker =) Finalmente, traduzi tudo para o Octave para salvar outros 9 bytes ...

Stewie Griffin
fonte
4

Java, 164 159 146 bytes

int[]p(int t,int m,String[]d){int r=m;for(String i:d){int x=Integer.decode(i);r=m<1?r+x:r*x;}return r>9?p(++t,m,(r+"").split("")):new int[]{r,t};}

O primeiro argumento é apenas o contador, sempre 0

O segundo argumento é o método, 0 para ADD e 1 para MULTIPLY.

O terceiro argumento é uma matriz de Strings, que contém os valores a serem adicionados / multiplicados.

Ungolfed

public static int[] p(int t, int m, String[] d) {
    int r = m;
    for (String i : d) {
        int x = Integer.decode(i);
        r = m < 1 ? r + x : r * x;
    }
    return (r + "").length() > 1 ? p(++t, m, (r + "").split("")) : new int[]{r, t};
}

obrigado a @Kevin Cruijssen por cortar alguns bytes.

graças ao @milk por cortar 5 bytes.

Programa de teste

public static final int ADD = 0;
public static final int MULTIPLY = 1;

public static void main(String[] args) {
    System.out.println(Arrays.toString(p(0, ADD, new String[]{"12", "123"}))); //9
    System.out.println(Arrays.toString(p(0, MULTIPLY, new String[]{"12", "123"}))); //6
}

public static int[] p(int t, int m, String[] d) {
    int r = m;
    for (String i : d) {
        int x = Integer.decode(i);
        r = m < 1 ? r + x : r * x;
    }
    return (r + "").length() > 1 ? p(++t, m, (r + "").split("")) : new int[]{r, t};
}
Shaun Wild
fonte
Bom, mais curto que minha resposta em Java . No entanto, também é suposto para imprimir os passos, bem como a resposta que atualmente está faltando em sua resposta ..
Kevin Cruijssen
@KevinCruijssen Ahh. Isso é chato .. Vou tentar consertar isso agora.
Shaun Wild
Aliás, você pode jogar um pouco sua resposta atual. m==0pode ser m<1e Integer.parseIntpode ser Integer.decode.
Kevin Cruijssen
Eu não uso muito Java, mas você precisa dessa jvar no final? Inlining (r+"")duas vezes parece que ele rasparia alguns bytes.
milk
1
Não podemos alterar minhas postagens no futuro? Se você deseja sugerir uma edição, faça-o nos comentários.
Shaun Wild
3

Geléia , 17 bytes

+×⁵?µDSP⁵?$ÐĿµL;Ṫ

Experimente online!

Dados argumentos como x y 1esse, calcula a soma de Anastasiya x (+) y.

Dados argumentos como x y 0esse, calcula o produto Anastasiya x (*) y.

A saída é dada como [number of steps, result].

Lynn
fonte
Obrigado pela resposta, mas a saída do seu programa não contém o número de etapas necessárias? Estou faltando alguma coisa aqui?
Anastasiya-Romanova 秀
3

Python, 160 146 129 bytes

def r(s):
 n=str(eval(s));c=0
 while n[1:]:exec("n=str(reduce(lambda a,b:a%sb,map(int,list(n))))"%"*+"["+"in s]);c+=1
 return n,c

Postará uma explicação em breve.

A entrada está no formato 12+12ou 5*35(com normal +e *sinais) e assume que esses são os únicos dois operadores.

Ele pode lidar com entradas numéricas tão grandes quanto a memória do seu computador permitir.

Estou quase certamente confiante de que isso pode ser mais longe.

EDIT: 16 31 bytes salvos graças ao @Copper.

clismique
fonte
Obrigado pela resposta, (+1). Ele pode lidar com entradas de grande número?
Anastasiya-Romanova 秀
@ Anastasiya-Romanova 秀 Uhmmm ... eu tenho certeza que eles podem. Você pode me dar exemplos de grandes insumos? Vou tentar calcular com esses.
Clismique
Talvez: 3218753647208435810122106 * 29349566754?
Anastasiya-Romanova 秀
1
@ Anastasiya-Romanova 秀 Sim, funcionou em ~ 0,5 segundos, não foi o tempo certo.
Clismique
Você pode alterar "+" if "+" in s else "*"para "*+"["+"in s]e, em vez de atribuí-lo t, basta adicioná-lo em linha na execchamada.
Copper
3

R, 110 bytes

Usando o divisor do @plannapus.

function(A,F,B){r=Reduce;x=r(F,A,B);y=1;while(x>9){m=nchar(x);x=r(F,x%%10^(1:m)%/%10^(1:m-1));y=y+1};cat(x,y)}

f=function(A,F,B){
  r=Reduce                                  # Shortcut for Reduce
  x=r(F,A,B)                                # A operator B
  y=1                                       # Initiate counter
  while(x>9)                                # If number of digits > 2, or number > 9
  {m=nchar(x)                               # Count number of digits
    x=r(F,x%%10^(1:m)%/%10^(1:m-1))         # @plannapus's splitter, then feed into the A operator B operator C, etc while condition true
    y=y+1}                                  # Increment counter
  cat(x,y)}                                 # Print

Resultado

> f(136,"*",2356)
0 2
> f(31,"+",81)
4 2
> f(2,"+",3)
5 1
> (function(A,F,B){r=Reduce;x=r(F,A,B);y=1;while(x>9){m=nchar(x);x=r(F,x%%10^(1:m)%/%10^(1:m-1));y=y+1};cat(x,y)})(21,"*",111)
8 3

editar: eu não posso contar.

Vlo
fonte
R é fantástico porque nos permite encurtar sua função, algo que é valioso no golfe. (+1)
Anastasiya-Romanova,
3

Clojure 126 bytes

(defn f [o a b] (loop [n (o a b) c 1] (if (< n 10) [n c] (recur (reduce #(o %1 %2) (map #(- (int %) 48) (str n))) (inc c)))))

A função é chamada assim:

(f + 81 31)

Aqui está o código ungolfed:

(defn f [o a b]
  (loop [n (o a b) c 1]
    (if (< n 10)
      [n c]
      (recur (reduce #(o %1 %2)
                     (map #(- (int %) 48) (str n)))
             (inc c)))))

(def test-cases [[+ 81 31]
                 [+ 351 14568]
                 [* 21 111]
                 [* 136 2356]])

(map #(apply f %) test-cases)
;;=> ([4 2] [6 3] [8 3] [0 2])

Lembre-se de que Clojure ainda é novo para mim, portanto essa provavelmente não é a melhor solução. O desafio foi divertido do mesmo jeito. Além disso, o código foi executado com números muito grandes sem nenhuma dificuldade.

James B.
fonte
É muito tarde, mas você pode reduzir a maioria dos espaços lá.
Clismique
2

Perl 6 53 bytes

{$/=(&^b($^a,$^c),{[[&b]] .comb}...10>*);$/[*-1],+$/}

Como ( 12, &[+], 123 )é aceitável para a entrada, posso reduzi-lo para 53 bytes.
( &[+]é a abreviação de &infix:<+>uma "reverência" ao operador de adição de infixo numérico)

Se o segundo argumento tivesse que ser uma string (+), seria de 87 bytes

{my&b=::("&infix:<$^b.substr(1,1)>");$/=(b($^a,$^c),{[[&b]] .comb}...10>*);$/[*-1],+$/}

Explicação:

# bare block lambda with 3 parameters declared using placeholder syntax
{
  # store list into 「$/」
  # ( used 「$/」 so that I don't have to declare a variable )
  $/ = (

    # declare second placeholder parameter, and call it
    &^b(
      # with the first and third placeholder parameters
      $^a, $^c
    ),

    # bare block lambda with implicit parameter 「$_」
    {
      # list reduce using the second parameter from outer block
      [[&b]]

      # a list of the digits of 「$_」 (implicit method call)
      .comb
    }

    # keep doing that until
    ...

    # it produces something smaller than 10
    # ( Whatever lambda )
    10 > *
  );

  # returns

  # final result ( last value from list )
  $/[ * - 1 ],
  # and count of values in list
  +$/
}

Teste:

#! /usr/bin/env perl6
use v6.c;
use Test;

my &anastasiya-math = {$/=(&^b($^a,$^c),{[[&b]] .comb}...10>*);$/[*-1],+$/}

my @test = (
  (  81, &[+], 31    ) => (4, 2),
  ( 351, &[+], 14568 ) => (6, 3),
  (  21, &[*], 111   ) => (8, 3),
  ( 136, &[*], 2356  ) => (0, 2),
);

plan +@test;

for @test -> $_ ( :key(@input), :value(@expected) ) {
  cmp-ok anastasiya-math(|@input), &[»==«], @expected;
}

Uso normal:

# override built-in Bag operator 「(+)」 in current lexical scope
my &infix:<(+)> = &anastasiya-math.assuming: *, &[+], *;

# add a new operator
my &infix:<(*)> = &anastasiya-math.assuming: *, &[*], *;

say 12 (+) 123; # (9 2)
say 12 (*) 123; # (6 5)
Brad Gilbert b2gills
fonte
2

Python 2, 107 97 bytes

g=lambda x,o,i=1:x<10and[x,i]or g(eval(o.join(`x`)),o,i+1)
lambda a,o,b:g(eval('%s'*3%(a,o,b)),o)

Uma função anônima que recebe entrada via argumento de um primeiro operando a, um operador o( '+'ou '*') e um segundo operando be retorna uma lista do formulário [result, steps].

Como funciona

A função anônima cria uma string concatenando os operandos com o operador entre eles e, em seguida, avalia; este é o primeiro passo descrito na pergunta. Então, esse valor e o operador são passados ​​para a função recursiva g. Aqui, um contador i, que é incrementado para cada chamada recursiva, é usado. Se a entrada for menor que 10, um único dígito deve ter sido alcançado, portanto, isso ié retornado. Caso contrário, a entrada é convertida em uma string e cada caractere dessa string é associado ao operador, fornecendo o cálculo desejado, que é então avaliado e passado para a função recursivamente.

Experimente no Ideone

TheBikingViking
fonte
(+1) enquanto aguarda a explicação :)
Anastasiya-Romanova 秀 25/08
2

Groovy, 102 bytes

def p,e,r;p={t,m,d->e=d*.toInteger();r=m<1?e.sum():e.inject{a,b->a*b};r>9?p(++t,m,""+r as List):[r,t]}

Degolfed

def p,e,r
p = { t, m, d ->
    e = d*.toInteger()
    r = (
            m<1
                ? e.sum()
                : e.inject { a, b -> a * b }
        )
    r > 9
        ? p(++t, m, "" + r as List)
        : [r,t]
}

Explicação

Baseado na excelente solução do @Sean Bean para Java.

  • p: O fechamento (função, lambda, qualquer que seja) que implementa a solução
  • t: A profundidade da chamada atual (número de iterações) psempre deve ser chamada comt=1
  • m: A operação a ser executada, 0para "adicionar", 1para "multiplicar"
  • d: A lista de operandos, cada operando é um objeto String
  • e: Os elementos de d, cada um convertido em um número inteiro
  • r: A soma ou o produto de e, dependendo da operaçãom
  • declaração de resultado, começando com r > 9:
    • Se houver vários dígitos ( r > 9), reinicie, aumentando a profundidade te convertendo rem uma lista de cadeias de dígitos (e retornando o resultado).
    • Se um dígito, retorne re tcomo uma lista.

Programa de teste

final ADD = 0
final MULTIPLY = 1
println p(1, ADD, ["12", "123"]) //9, 2
println p(1, MULTIPLY, ["12", "123"]) //6, 5
println p(1, ADD, ["2", "3"]) //5, 1

Resultados

[9, 2]
[6, 5]
[5, 1]
Roger Glover
fonte
2

Haskell, 76 70 bytes

 (x#y)f=until(<[10])(\[s,i]->[foldr(f.read.pure)0$show s,i+1])[f x y,1]

Retorna uma lista de dois elementos com o resultado e o número de etapas. Funciona para grandes números arbitrários. Exemplo de uso: (351#14568)(+)-> [6,3].

Edit: Obrigado a @BlackCap por 6 bytes.

nimi
fonte
Você pode substituir (-48+).fromEnumporread.pure
BlackCap 14/16
2

R, 91 bytes

Usando o código do @ Vlo, que faz uso do divisor do @ plannapus, e algumas idéias que eu gerei ao jogar a resposta de @ Frédéric, essa é a resposta R mais curta de todos os tempos. (Um número extraordinariamente grande de respostas R está aqui hoje ...)

function(A,F,B){x=F(A,B);while(x>9){m=nchar(x);x=F(x%%10^(1:m)%/%10^(1:m-1));T=T+1};c(x,T)}

Fundamentalmente, isso requer que a entrada do operador seja sumpara (+) ou prodpara (*). Sob as regras do desafio, isso parece estar bem.

Com recuo:

function(A,F,B){
  x=F(A,B);
  while(x>9){
    m=nchar(x);
    x=F(x%%10^(1:m)%/%10^(1:m-1));
    T=T+1
  };
  c(x,T)
}

As principais diferenças da resposta da @ Vlo são:

  1. Em vez de usar Reduce, contamos com o argumento de entrada como uma função e apenas o chamamos explicitamente. (Sim, para funções que são objetos de primeira classe!)
  2. Em vez de inicializar uma nova variável como nosso contador, abusamos dos buildins e do uso de R T, o que é avaliado como TRUE(aka 1), mas como não é uma variável reservada, podemos modificá-la. Assim T+Té 2. Então, usamos isso como nosso contador.
  3. Em vez de catdigitar a saída, apenas retornamos como um vetor com c. Além de salvar dois bytes, o fato de a saída ser forçada em um vetor garante que isso Tseja de classe numeric. Se usarmos cate Tnão tivermos sido incrementados, obteremos resultados errados como 1 TRUE.
rturnbull
fonte
você pode reestruturar o whilecircuito a seguir, mudando Fpara ser outra coisa para conflitos de nome evitar: function(A,O,B){x=O(A,B);while({F=F+1;x>9})x=O(x%/%10^(1:nchar(x)-1)%%10;c(x,F)}}. É incrível como muitos R truques golfe nós viemos acima com nos últimos anos :)
Giuseppe
@Giuseppe Nice reestruturação! Não consigo encontrar o meta consenso no momento, mas estou razoavelmente confiante de que o uso do truque Tand Fcounter dentro de uma função é realmente inválido, pois significa que a função pode ser chamada apenas uma vez. Portanto, esta resposta (e várias das minhas outras!) São inválidas, a menos que haja uma explícita rm(T)no final. Vou continuar procurando essa meta post, para ter certeza de que não sonhei.
Rdb #
Eu acredito que o truque Te Fé perfeitamente válido desde que você não modifique Tou Fno ambiente global. por exemplo, f=function(){T=T+1;T}retorna consistentemente 2. Eu acho que este é o meta post ao qual você se refere.
Giuseppe
@ Giuseppe Ah, sim, você está certo em ambos os aspectos. Obrigado!
Rdb #
1

Ruby, 55 bytes

Chamada recursiva. Costumava ser muito diferente da resposta JavaScript do @ edc65, mas como eu o otimizei, eventualmente se tornou uma porta direta desenvolvida quase independentemente da resposta, menos uma otimização final envolvendo a verificação do resultado avaliado em vez do tamanho da lista de operandos passados ​​em , o que me permitiu superar a contagem de bytes.

Input é uma string que representa o operador e uma matriz que contém os operandos.

Experimente online.

f=->o,x,i=1{y=eval x*o;y>9?f[o,y.to_s.chars,i+1]:[y,i]}
Value Ink
fonte
O resultado está correto, mas o número de etapas necessárias para obter um valor de um dígito está incorreto. Você pode retificar seu código?
Anastasiya-Romanova # 25/16
@ Anastasiya-Romanova 秀 ah, você está certo. Minha lógica antiga exigia que ela iniciasse i=0e eu esqueci ao refatorar.
Value Ink
1

Perl, 38 bytes

Inclui +2 para -ap

Execute com a entrada STDIN e espaços ao redor do operador:

amath.pl <<< "12 + 123"
amath.pl <<< "12 * 123"

A saída é um dígito e as etapas são separadas por +A

amath.pl:

#!/usr/bin/perl -ap
1while++$\,$_=eval."+A",s/\B/$F[1]/g

Se a saída das etapas em unário estiver ok, esta versão de 35 bytes funcionará melhor:

#!/usr/bin/perl -lap
1while$\.=1,$_=eval,s/\B/$F[1]/g
Ton Hospel
fonte
1

Mathematica, 105 94 bytes

Código.

{x,y}=(c=0;f//.a_:>(c++;t=o@@IntegerDigits@a);{t,c})&/.{{f->#1+#2,o->Plus},{f->#1#2,o->Times}}

Uso.

x[81, 31]
(* {4, 2} *)

x[351, 14568]
(* {6, 3} *)

y[21, 111]
(* {8, 3} *)

y[136, 2356]
(* {0, 2} *)

Explicação.

As duas funções x(para (+)) e y(para (*)) são criadas ao mesmo tempo, substituindo os parâmetros fe oem

(c = 0;
 f //. a_ :> (c++; t = o@@ IntegerDigits@a);
 {t, c}
)&

com seus valores apropriados. Pois x, ftorna #1 + #2- ose e torna - se Plus; para y, eles respectivamente se tornar #1 #2e Times. Reescrevendo a função xpara a última parte da explicação:

x = (
  c = 0;
  #1 + #2 //. a_ :> (c++; t = Plus@@IntegerDigits@a); 
  {t, c}
) &;

(* The symbol //. stands for ReplaceRepeated. 
   The rule a_ :> (c++; t = Plus@@IntegerDigits@a) is applied until the result no longer 
changed. Specifically, the rule increments the counter of 1 at each step (this is c++), 
then takes the sum of the digits of the previous result (this is Plus@@IntegerDigits@a). 
The rule stops to apply when the variable t is less than 10. We return the final result and 
the number of steps with {t, c}. *)

fonte
1

Java 7, 203 195 192 bytes

int c=1;String c(long a,long b,int o){return p(((o<1?a+b:a*b)+"",o)+","+c;}long p(String n,int o){long x=o,q;for(String s:n.split("")){q=new Long(s);x=o<1?x+q:x*q}c++;return x<10?x:p(x+"",o);}

Ele usa long(valor máximo de 2 63 -1). Se fosse utilizado int(valor máximo de 2 31 -1), seria apenas 1 byte a menos ( 191 bytes ):

int c=1;String c(int a,int b,int o){return p(((o<1?a+b:a*b)+"",o)+","+c;}int p(String n,int o){int x=o,q;for(String s:n.split("")){q=new Integer(s);x=o<1?x+q:x*q}c++;return x<10?x:p(x+"",o);}

Provavelmente pode ser jogado um pouco mais. Porém, ter que imprimir as etapas, bem como a resposta para os dois operadores, leva alguns bytes.
Usa 0 (para (+)) e 1 (para (*)).

Ungolfed & código de teste:

Experimente aqui.

class Main{
  static int c = 1;
  static String c(long a, long b, int o){
    return p((o < 1 ? a+b : a*b) + "", o) + "," + c;
  }

  static long p(String n, int o){
    long x = o,
         q;
    for(String s : n.split("")){
      q = new Long(s);
      x = o < 1
           ? x + q
           : x * q;
    }
    c++;
    return x < 10
            ? x
            : p(x+"", o);
  }

  public static void main(String[] a){
    System.out.println(c(81, 31, true));
    c = 1;
    System.out.println(c(351, 14568, true));
    c = 1;
    System.out.println(c(21, 111, false));
    c = 1;
    System.out.println(c(136, 2356, false));
  }
}

Resultado:

4,2
6,3
8,3
0,2
Kevin Cruijssen
fonte