Как работает математика в мире Анастасии?


44

Задний план:

Стандартные математические операции, такие как базовое сложение и умножение в реальном мире, работают так:

12 + 123 = 135

а также

12 * 123 = 1476

Это не интересно и скучно! Многие школы уже интерпретируют это как практику, практику, практику формальных алгоритмов. Это подразумевает довольно жесткую и скучную математическую диету и не является тем, что предназначено для этой задачи. Приготовьтесь поиграть на нашем любимом сайте.

Рассмотрим процесс сложения двух положительных целых чисел, а затем повторного добавления всех цифр его результата. Повторять с добавлением, пока не будет получена только одна цифра. Например:

  1. Результат 12 + 123135.
  2. Сложив все цифры 135 мы получим 1 + 3 + 5 = 9.

Количество шагов, необходимых для получения однозначного значения 9 в этом повторном сложении, равно 2.

Как и в предыдущем процессе сложения, умножение двух положительных целых чисел следует тому же процессу. Умножьте все цифры результата и повторяйте этот процесс, пока не останется только одна цифра. Возьмите приведенный выше пример:

  1. Результат 12 * 1231476.
  2. Умножьте все цифры 1476, которые мы получим 1 * 4 * 7 * 6 = 168.
  3. Умножьте снова все цифры 168, которые мы получим 1 * 6 * 8 = 48.
  4. Умножьте снова все цифры 48, которые мы получим 4 * 8 = 32.
  5. Умножим еще раз все цифры 32, которые мы получим 3 * 2 = 6.

Количество шагов, необходимых для получения однозначного значения 6 при этом повторном умножении, составляет 5.

Для этой задачи и во избежание любого неправильного использования математических обозначений я ввожу эти два фиктивных обозначения: (+)и (*), но вы можете использовать любые обозначения , которые вам нравятся , которые работают следующим образом:

  1. Операция повторного сложения процесса для получения единственного значения 12 (+) 123 = 9.
  2. Операция повторного процесса умножения для получения одного значения 12 (*) 123 = 6.

Вызов:

Задача состоит в том, чтобы написать либо программу, либо функцию, которая может выполнять обе операции, как описано в разделе фона: (+)и (*).

Входные данные:

Входы программы или функции являются два положительных целых чисел и одну операцию либо (+)и (*). Формат ввода - произвольный выбор программиста . Вы можете форматировать ввод, например, a (+) bили , F(a, (+), b)или любой формат , который вы хотите.

Выход:

Выходные данные программы или функции должны содержать результат операции и количество шагов, требуемых для формата вольного стиля, как вы хотите.

Тестовые случаи (игнорируйте формат ввода и вывода):

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

Основные правила:

  • Это , так что кратчайший ответ в байтах побеждает.
    Не позволяйте esolangs отговаривать вас от публикации ответов на обычных языках. Получите удовольствие от этой задачи, предоставив максимально короткий ответ на своем языке программирования. Если вы разместите умный ответ и четкое объяснение, ваш ответ будет оценен (следовательно, положительные отзывы) независимо от используемого вами языка программирования.
  • К вашему ответу применяются стандартные правила , поэтому вы можете использовать STDIN / STDOUT, функции / метод с соответствующими параметрами, полные программы и т. Д. Выбор за вами.
  • Если возможно, ваша программа может правильно обрабатывать большие числа. Если нет, то все будет хорошо.

Пусть начнется игра!!


Часть повторного добавления ( цифровой корень ) по сути является дубликатом codegolf.stackexchange.com/q/1128/194
Питер Тейлор,

4
Отличный первый вопрос! И я узнаю общие правила формата и предложения из моих собственных Вопросов. ;)
Кевин Круйссен

4
@KevinCruijssen Да. это верно. Поскольку он не имеет авторских прав, поэтому я копирую его без вашего разрешения. Хехехе: D
Анастасия-Романова

4
@ Анастасия-Романова 秀 "нет авторских прав"? В XXI веке? Нет; все здесь CC-BY-SA 3.0. Разрешение предоставляется при отправке контента. Проверьте нижний колонтитул сайта.
Миндвин

1
@ BradGilbertb2gills Да, конечно. Об этом говорится в сообщении, кстати. Цитата: «Формат ввода - произвольный выбор программиста».
Анастасия-Романова

Ответы:


11

Dyalog APL , 33 32 30 29 байт

Это расширяет APL для включения префиксной нотации +/A n₁ n₂и ×/A n₁ n₂. (На самом деле, вы можете использовать любую операцию слева от /A.) Возвращает список {результат, количество повторений}.

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

A←{определить функцию высшего порядка в терминах левой функции ⍺⍺и правого аргумента

(⊃,≢) первый элемент, за которым следует число

⍺⍺{предоставленная функция ( +/для суммы или ×/для продукта), переданная в функцию высшего порядка

уникальные элементы

⍵,⍨ аргумент приложен к

⍺⍺ функция подачи применяется к

⍎¨ оценка каждого персонажа

символьное представление

⊃⍵ первый элемент аргумента

}⍣≡ применяется несколько раз, пока результат не будет идентичен аргументу, начиная с

⍺⍺⍵исходная функция ( +/или ×/), примененная к исходному аргументу

} [конец определения функции высшего порядка]

Попробуй APL онлайн! ( был эмулирован в eцелях безопасности.)

Спасибо @ngn за сохранение байта.


0 байт (в шутку)

Dyalog APL на самом деле уже полностью поддерживает математику Анастасияна; вместо (+)и (×)он использует +{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}и ×{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}.

Попробуйте 81 +{(⊃,≢)⍺⍺{∪⍵,⍨⍺⍺e¨⍕⊃⍵}⍣≡⍺⍺/⍺⍵} 31и 21 ×{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/e¨⍕⍵}⍣=⍵⍺⍺⍨⍺} 111.


Спасибо за ответ, (+1). Может ли он обрабатывать большое количество входов?
Анастасия-Романова

1
Если установить ⎕FR←1287(т.е. использовать IEEE 754-2008 128-разрядное десятичное F loating точкой R epresentation) и ⎕PP←34(т.е. использовать 34 символов P Ринт P recision), вы можете использовать целые числа ниже 10³⁴.
Адам

Хм, даже если он имеет полную поддержку, не +{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}и ×{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}еще довольно много байт? Я запутался в том, что это 0 байтов ..: S
Кевин Круйссен

3
@KevinCruijssen OP позволяет вводить любые записи. Таким образом, если бы язык, как оказалось, поддерживал стандартную нотацию Анастасияна по умолчанию «из коробки», глиф с несколькими символами (+)был бы Анастасияном. Dyalog APL поддерживает математику Анастасияна, но использует другой многозначный глиф, так же, как *означает мощность и вам нужно ×для умножения, а /означает репликацию и вам нужно ÷для деления.
Адам

1
@ Adám Ладно, в этом есть смысл. Это своего рода нарушение правил ОП, но не нарушение их. Все еще довольно странно, что вместо (+)вас есть +{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}входные данные, но поскольку OP действительно заявил, что подойдет любой формат ввода, вы можете использовать функцию в качестве параметра. Хм, интересно, возможно ли это и в других языках программирования, которые поддерживают функции ввода.
Кевин Круйссен

8

Haskell, 108 байт

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

Определяет функцию , #которая принимает первый aи bзатем оператор o. Интересный факт: это работает с любым оператором (фактически, с любой функцией), который вы хотите!


Спасибо за ответ, (+1). Может ли он обрабатывать большое количество входов?
Анастасия-Романова

4
@ Анастасия-Романова 秀 Да, он может обрабатывать такие же большие числа, как и ваша RAM, поскольку Integerтип Хаскелла неограничен.
ThreeFx

8

Пайк, 16 байт

RE`DltImbRoKr)oh

Попробуй это здесь!

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

Принимает умножить как Bи добавить как s. Два числовых ввода разделены запятыми.


1
Ницца! Можем ли мы получить объяснение?
Эмигна

Спасибо за ответ, (+1). Может ли он обрабатывать большое количество входов?
Анастасия-Романова

@ Анастасия-Романова 秀 она должна уметь обрабатывать произвольные числа
Blue

Я не могу проверить ваш код, потому что сеть заблокирована, так как это нарушает политику использования моих родителей в Интернете. T_T
Анастасия-Романова

Примерно так: веб-страница заблокирована! Вы пытались получить доступ к веб-странице, которая нарушает вашу политику использования Интернета. URL: pyke.catbus.co.uk/?code=RE%60DltImbRoKr%29oh&input=B%0A21%2C+111&warnings=0 Категория: Без классификации
Анастасия-Романова

8

JavaScript (ES6), 59

Рекурсивная функция, формат ввода адаптирован для упрощения рекурсивного вызова:

  • оператор: '+' или '*'
  • операнды: массив из двух значений
f=(o,v,s=1,t=eval(v.join(o)))=>t>9?f(o,[...t+''],s+1):[t,s]

Тест

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)
})  
  


Спасибо за ответ, (+1). Может ли он обрабатывать большое количество входов?
Анастасия-Романова

1
@ Анастасия-Романова 秀 до предела числового формата javascript, 53 бита точности (17 десятичных цифр)
edc65

8

Python 2, 60 байт

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

Ввод представляет собой строку , как 81+31, выход кортеж из строки одноплодной и счетчик (например, ('4', 2).

Проверьте это на Ideone .


Если принимать входные данные в виде массива строк, и допускается, например, одна строка, f(['81', '31'],'+')можно сохранить еще один байт, но кажется, что это слишком растянуло правила ...
Деннис


... в этом случае я бы даже operator.addoperator.mul
зашел

7

Pyth, 16

eJ.uvjhQ`N.vQ)lJ

Принимает ввод как "+ 123 12"для сложения, так и "* 123 12"для умножения. Выходы вроде result<linefeed>steps.

Попробуйте здесь или запустите Test Suite , но учтите, что это зависит от eval, поэтому в онлайн-интерпретаторе будет работать только вариант дополнения. Умножение работает правильно с автономным переводчиком.

Здесь используется функция кумулятивного сокращения, чтобы создать список промежуточных результатов, так что "+ 351 14568"мы получаем [14919, 24, 6]. Это работает, потому что однозначные числа являются фиксированной точкой сложения и умножения Анастасии. Тогда мы просто получаем последний элемент массива, а также длину массива.

Это будет работать для произвольно больших чисел, по крайней мере, до тех пор, пока у вас не закончится память.


7

R 175 167 164 140 134 127 126 119 байт

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

ifelseвернулся! Да !
Nop

Использование :

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

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

Большое спасибо @plannapus за игру в 24 байта!
-7 байт благодаря хорошей идее от @Vlo !


Да, пожалуйста, добавьте объяснения, так как я люблю R! Это мой второй язык после VBA. (+1)
Анастасия-Романова

1
@ Анастасия-Романова Done: Готово!
Фредерик

@plannapus: Действительно приятно! Большое спасибо !
Фредерик

1
@ Frédéric приятно использовать strtoi! Еще 4 байта, вы меня избили.
plannapus

1
Похоже, вы можете еще больше отыграть байт, включив определение O в присваивание x в первой операции: x = (O = switch (S, sum, `*`)) (G, D) ;.
rturnbull

6

05AB1E , 20 15 байт

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

объяснение

[       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

Оператор равен 1 для сложения, 0 для умножения.

Попробуйте онлайн


Спасибо за ответ, (+1). Может ли он обрабатывать большое количество входов?
Анастасия-Романова

@ Анастасия-Романова 秀 Я не вижу причин, почему нет. У вас есть пример?
Эминья

Ваша программа была проверена на такие входные данные, поэтому она идеально подходит :)
Анастасия-Романова

6

Желе , 11 10 байт

Dj⁹VµÐĿḊĖṪ

Ввод представляет собой пару чисел и либо +или ×.

Попробуйте онлайн! или проверьте все контрольные примеры .

Как это работает

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.

6

Машинный код ARM, 48 байт

Шестнадцатеричный дамп:

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

Эта функция не зависит от системных вызовов или библиотечных функций. Это код Thumb-2, представляющий собой кодирование команды переменной длины (2 или 4 байта) для 32-разрядного ARM. Таким образом, максимальное значение, которое он может обработать, составляет 2 ^ 32-1. 2 байта можно было бы отбросить, если бы они не соответствовали AAPCS ( 46 байтов ), поскольку в начале нам не пришлось бы составлять регистры.

Неуправляемая сборка (синтаксис 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

Скрипт тестирования в 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));
}

4

R 130 124 символа

Несколько иной подход от @ 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)}

С отступом, с новыми строками:

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
    }

Строка 4, вероятно, нуждается в дополнительных пояснениях:

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

Тестовые случаи:

> f(12,"(+)",123)
[1] 9 2
> f(12,"(*)",123)
[1] 6 5
> f(351,"(+)",14568)
[1] 6 3

Весьма прискорбно, что вы опоздали с этим ответом, но у вас есть мой голос. Спасибо за создание этого в R.
Анастасия-Романова

Почему неудачный?
plannapus

Потому что, если бы ты пришел первым, то получил бы больше голосов
Анастасия-Романова 秀

@ Анастасия-Романова 秀 Достаточно справедливо :)
plannapus

Бонусные баллы за то, что они fявляются как именем функции, так и одним из ее аргументов :)
JDL

4

Октава, 85 байт MATLAB, 123, 114, 105, 94 байта

Решил перевести это на Octace, чтобы воспользоваться преимуществами прямой индексации и наращивания возможностей. Принимает данные в форме:, f(a,operator)где a = [number1, number2], и operator==1дает продукт, и operator==2дает сумму.

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

Пояснения:

g={@prod,@sum}{o} : Выбирает подходящую функцию, продукт или сумму и назначает ее g

x=g(a) берет сумму или произведение входов

i=1; ... i++ : Инкремент для подсчета количества шагов

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

Удалил две новые строки, пробел и поместил оба входных числа в вектор вместо отдельных аргументов. Это спасло 9 байтов, благодаря Pajonk! Удалено, k=@(x)...чтобы сохранить еще 11 байтов, благодаря beaker =) Наконец, все переведено в Octave, чтобы сохранить еще 9 байтов ...


4

Java, 164 159 146 байт

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};}

Первый аргумент - просто счетчик, всегда 0

Вторым аргументом является метод, 0 для ADD и 1 для MULTIPLY.

Третий аргумент - это массив строк, который содержит значения для добавления / умножения.

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};
}

спасибо @Kevin Cruijssen за сокращение нескольких байтов.

спасибо @milk за бритье 5 байт.

Тестовая программа

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};
}

Хорошо, короче, чем мой ответ на Java . Тем не менее, вы также должны напечатать шаги, а также ответ, который в настоящее время отсутствует в вашем ответе.
Кевин Круйссен

@KevinCruijssen Ааа. Это скучно .. Я попробую исправить это сейчас.
Шон Уайлд,

Кстати, вы можете немного поиграть в свой текущий ответ. m==0может быть m<1и Integer.parseIntможет быть Integer.decode.
Кевин Круйссен

Я не очень много использую Java, но нужен ли вам этот jvar в конце? Двойное встраивание (r+"")выглядит так, как будто оно побрило бы несколько байтов.
молоко

1
Разве мы не можем изменить мои сообщения в будущем? Если вы хотите предложить редактирование, сделайте это в комментариях.
Шон Уайлд,

3

Желе , 17 байт

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

Попробуйте онлайн!

Принимая во внимание такие аргументы, как x y 1, это вычисляет сумму Анастасии x (+) y.

Учитывая аргументы, такие как x y 0, это вычисляет продукт Анастасии x (*) y.

Выход дан как [number of steps, result].


Спасибо за ответ, но ваша программа не содержит количество шагов, необходимых для части? Я что-то здесь упускаю?
Анастасия-Романова

3

Python, 160 146 129 байт

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

Скоро выложу объяснение.

Ввод осуществляется в форме 12+12или 5*35(с нормой +и *знаками) и предполагает, что это только два оператора.

Он может обрабатывать числовые значения настолько большие, насколько позволяет память вашего компьютера.

Я почти наверняка уверен, что это может быть дальше.

РЕДАКТИРОВАТЬ: 16 31 байт сохранены благодаря @Copper.


Спасибо за ответ, (+1). Может ли он обрабатывать большое количество входов?
Анастасия-Романова

@ Анастасия-Романова 秀 Ммм ... Я вполне уверена, что они могут. Можете ли вы дать мне примеры больших входов? Я постараюсь рассчитать из тех.
clismique

Может быть: 3218753647208435810122106 * 29349566754?
Анастасия-Романова

1
@ Анастасия-Романова 秀 Да, это сработало в течение ~ 0.5 секунд, неправильно рассчитало время.
clismique

Вы можете изменить "+" if "+" in s else "*"его "*+"["+"in s], а затем вместо того, чтобы назначить его t, просто добавить его в execвызове.
Медь

3

R, 110 байт

Использование сплиттера @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

Выход

> 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

редактировать: я не могу сосчитать


R фантастичен, потому что позволяет нам сократить его функции, что ценно в гольфе. (+1)
Анастасия-Романова 秀

3

Clojure 126 байтов

(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)))))

Функция называется так:

(f + 81 31)

Вот код без ключа:

(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])

Имейте в виду, что Clojure все еще является новым для меня, так что это, вероятно, не лучшее решение. Задача все равно была веселой. Кроме того, код работал с очень большими числами без каких-либо затруднений.


Это очень поздно, но вы можете уменьшить большую часть пространства там.
clismique

2

Perl 6 53 байта

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

Поскольку ( 12, &[+], 123 )это приемлемо для ввода, я могу уменьшить его до 53 байт.
( &[+]сокращение от &infix:<+>которого является «почтением» к оператору сложения числового инфикса)

Если бы второй аргумент должен был быть строкой, (+)это было бы 87 байтов

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

Объяснение:

# 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
  +$/
}

Тест:

#! /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;
}

Нормальное использование:

# 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)

2

Python 2, 107 97 байт

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)

Анонимная функция, которая принимает входные данные через аргумент первого операнда a, оператора o( '+'или '*') и второго операнда bи возвращает список формы [result, steps].

Как это работает

Анонимная функция создает строку, объединяя операнды с оператором между ними, а затем оценивает ее; это первый шаг, описанный в вопросе. Затем это значение и оператор передаются рекурсивной функции g. Здесь используется счетчик i, который увеличивается для каждого рекурсивного вызова. Если ввод меньше, чем 10, должна быть достигнута одна цифра, так что это и iвозвращается. Если нет, входные данные преобразуются в строку, и каждый символ в этой строке соединяется с оператором, давая желаемое вычисление, которое затем оценивается и передается функции рекурсивно.

Попробуйте это на Ideone


(+1) в ожидании объяснения :)
Анастасия-Романова

2

Groovy, 102 байта

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]
}

объяснение

На основе превосходного решения @Sean Bean для Java.

  • p: Замыкание (функция, лямбда, что угодно), которое реализует решение
  • t: Текущая глубина вызова (количество итераций) pвсегда должна вызываться сt=1
  • m: Операция, которую нужно выполнить, 0для «сложения», 1для «умножения»
  • d: Список операндов, каждый операнд является объектом String
  • e: Элементы dкаждого преобразуются в целое число
  • r: Сумма или произведение e, в зависимости от операцииm
  • утверждение результата, начиная с r > 9:
    • Если multi-digit ( r > 9), повторно вызвать, увеличить глубину tи преобразовать rв список строк из цифр (и вернуть результат).
    • Если однозначный, вернуть rи tв виде списка.

Тестовая программа

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

Полученные результаты

[9, 2]
[6, 5]
[5, 1]

2

Haskell, 76 70 байт

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

Возвращает двухэлементный список с результатом и количеством шагов. Работает для произвольных больших чисел. Пример использования: (351#14568)(+)-> [6,3].

Изменить: Благодаря @BlackCap за 6 байтов.


Вы можете заменить (-48+).fromEnumнаread.pure
BlackCap

2

R, 91 байт

Используя код @ Vlo, который использует сплиттер @ plannapus, и некоторые идеи, которые я сгенерировал, играя в гольф в ответе @ Frédéric, это самый короткий R ответ. (Необычно большое количество ответов R здесь сегодня ...)

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)}

Важно, что это требует, чтобы вход для оператора был либо sumдля (+), либо prodдля (*). По правилам испытания, это, кажется, все в порядке.

С отступом:

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)
}

Основные отличия от ответа @ Vlo:

  1. Вместо использования Reduceмы полагаемся на то, что входной аргумент является функцией, и просто вызываем его явно. (Yay для функций, являющихся первоклассными объектами!)
  2. Вместо того, чтобы инициализировать новую переменную в качестве нашего счетчика, мы злоупотребляем встроенными функциями R и используем его T, который оценивается как TRUE(aka 1), но, поскольку это не зарезервированная переменная, мы можем изменить ее. Таким образом, T+Tесть 2. Таким образом, мы используем это как наш счетчик.
  3. Вместо catвывода мы просто возвращаем его как вектор с c. Помимо сохранения двух байтов, тот факт, что выходные данные принудительно передаются в вектор, гарантирует его Tпринадлежность к классу numeric. Если мы используем cat, и Tне был увеличен, то мы получаем ошибочный вывод, например 1 TRUE.

Вы можете реструктурировать whileпетлю следующим образом , изменения , Fчтобы быть еще что - то конфликты имен избегать: 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)}}. Удивительно, сколько трюков с R-гольфом мы придумали за последние несколько лет :)
Джузеппе

@Giuseppe Хорошая реструктуризация! Я не могу найти мета-консенсус в данный момент, но я достаточно уверен, что использование трюка Tи Fсчетчика внутри функции фактически недопустимо, так как это означает, что функция может быть вызвана только один раз. Так что этот ответ (и некоторые другие мои!) Являются недействительными, если rm(T)в конце нет явного . Я буду продолжать искать этот пост, чтобы быть уверенным, что я не просто придумал его.
rturnbull

Я считаю , что Tи Fтрюк отлично действует до тех пор , пока вы не измените Tили Fв глобальной среде. например, f=function(){T=T+1;T}последовательно возвращается 2. Я думаю, что это мета-пост, на который вы ссылаетесь.
Джузеппе

@ Джузеппе Ах, да, вы правы в обоих случаях. Благодарность!
rturnbull

1

Рубин, 55 байт

Рекурсивный вызов. Раньше он сильно отличался от ответа JavaScript @ edc65, но, по мере того как я его оптимизировал, он в конечном итоге стал прямым портом, разработанным практически независимо от их ответа, за исключением одной финальной оптимизации, включающей проверку результата eval'ed вместо длины списка операндов, передаваемых в , что позволило мне превзойти их количество байтов.

Ввод - это строка, представляющая оператор, и массив, содержащий операнды.

Попробуйте онлайн.

f=->o,x,i=1{y=eval x*o;y>9?f[o,y.to_s.chars,i+1]:[y,i]}

Результат правильный, но количество шагов, необходимых для получения однозначного значения, неверно. Не могли бы вы исправить свой код?
Анастасия-Романова

@ Анастасия-Романова 秀 ах, ты прав. Моя старая логика требовала, чтобы это началось, i=0и я как бы забыл при рефакторинге.
Стоимость чернил

1

Perl, 38 байт

Включает +2 для -ap

Запустите с вводом по STDIN и пробелами вокруг оператора:

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

Вывод цифра и шаги разделены +A

amath.pl:

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

Если вывод шагов в унарном порядке, то эта 35-байтовая версия работает лучше:

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

1

Mathematica, 105 94 байта

Код.

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

Использование.

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

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

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

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

Объяснение.

Эти две функции x(для (+)) и y(для (*)) созданы в то же время, заменив параметры fи oв

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

с их соответствующими значениями. Для получения x, fстановится #1 + #2и oстановится Plus; ибо yони соответственно становятся #1 #2и Times. Переписываем функцию xдля последней части объяснения:

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}. *)

1

Java 7, 203 195 192 байта

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);}

Используется long(максимальное значение 2 63 с -1). Если бы он использовал intвместо этого (максимальное значение 2 31 -1), он был бы только на 1 байт меньше ( 191 байт ):

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);}

Скорее всего, можно играть в гольф немного больше. Необходимость печати шагов, а также ответа для обоих операторов занимает несколько байтов, хотя ..
Использует 0 (для (+)) и 1 (для (*)).

Ungolfed & тестовый код:

Попробуй это здесь.

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));
  }
}

Выход:

4,2
6,3
8,3
0,2
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.