Як працює математика у світі Анастасії?


44

Фон:

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

12 + 123 = 135

і

12 * 123 = 1476

Це не цікаво і нудно! Багато шкіл вже трактують це як практику, практику, практику офіційних алгоритмів. Це передбачає досить жорстку і нудну математичну дієту, і це не те, що призначено в цьому виклику. Будьте готові пограти весело на нашому улюбленому сайті.

Розглянемо процес додавання двох додатних цілих чисел, а потім знову додаємо всі цифри його результату. Повторюючи з додаванням, поки не вийде лише одна цифра. Наприклад:

  1. Результат 12 + 123- 135.
  2. Додаючи всі цифри 135, отримані нами 1 + 3 + 5 = 9.

Кількість кроків, необхідних для отримання одноцифрового значення 9 у цьому повторному додаванні, становить 2.

Як і в попередньому процесі додавання, множення двох додатних цілих чисел слідує за тим самим процесом. Помножте всі цифри його результату, а потім повторюйте цей процес, поки не залишиться лише одна цифра. Візьмемо наведений вище приклад:

  1. Результат 12 * 123- 1476 рік.
  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 Yup. це вірно. Оскільки у нього немає авторських прав, тому я копіюю його без вашого дозволу. Hehehe: D
Анастасія-Романова 秀

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

1
@ BradGilbertb2gills Так, звичайно. Це написано в дописі, до речі. Цитата: "Формат вводу - це довільний вибір програміста".
Анастасія-Романова 秀

Відповіді:


11

Діалог 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 ОП дозволяє будь-які вхідні позначення. Отже, якби мова могла підтримувати математику Анастасіяна за замовчуванням поза межами поля, багатогранний гліф (+)був би Анастасіян +. Dyalog APL підтримує математику Анастасіяна, але він використовує інший багатоядерний гліф, так само як *і сила, і вам потрібно ×для множення, тоді як /означає реплікацію і вам потрібно ÷для ділення.
Adám

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

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
@ Анастасія-Романова 秀 Так, вона може обробляти числа великими, як і ваша оперативна пам'ять, оскільки Integerтип Haskell без обмежень.
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). Чи може він обробляти велику кількість входів?
Анастасія-Романова 秀

@ Анастасія-Романова 秀 вона повинна мати можливість обробляти довільні числа
Блакитний

Я не можу перевірити ваш код, оскільки Інтернет заблокований, оскільки це порушує політику використання моїх батьків в Інтернеті. 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

Піта, 16

eJ.uvjhQ`N.vQ)lJ

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

Спробуйте тут або запустіть тестовий набір , але зауважте, що це покладається на 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)}

Безголівки:

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повернувся ! Ага!
Ні

Використання:

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

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

Дякую @plannapus за те, що виграли 24 байти!
-7 байт завдяки гарній ідеї від @Vlo !


Так, будь ласка, додайте пояснення, оскільки я люблю R! Це моя друга мова після VBA. (+1)
Анастасія-Романова 秀

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

@plannapus: Дуже приємно! Дуже дякую !
Фредерік

1
@ Frédéric приємного використання strtoi! Ще 4 байти - ти мене побив.
планнапус

1
Схоже, ви можете додатково перейти на байт, включивши в першу операцію визначення O в межах призначення x: x = (O = перемикач (S, сума, `*`)) (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

Досить прикро, що ти запізнився з цією відповіддю, але ти маєш мою позицію. Дякуємо, що створили це в Р.
Анастасія-Романова 秀

Чому прикро?
планнапус

Тому що якби ви прийшли першими, то у вас було б більше результатів
Анастасія-Романова 秀

@ Анастасія-Романова enough Досить справедливо :)
плануємо

Бонусні бали за те, що 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.

Третій аргумент - це масив Strings, який містить значення для додавання / множення.

Безумовно

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 Ahh. Це нудно .. Я зараз спробую це виправити.
Shaun Wild

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

Я мало використовую Java, але чи потрібен вам цей jвар в кінці? Вкладене (r+"")вдвічі схоже на те, що воно буде голити кілька байтів.
молоко

1
Чи не можемо ми в майбутньому не змінювати мої повідомлення? Якщо ви хочете запропонувати редагувати, зробіть це в коментарях.
Shaun Wild

3

Желе , 17 байт

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

Спробуйте в Інтернеті!

З огляду на такі аргументи x y 1, це обчислює суму Анастасії x (+) y.

З огляду на такі аргументи x y 0, це обчислює добуток Анастасії x (*) y.

Вихідні дані задаються як [number of steps, result].


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

3

Пітон, 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(з нормальними +та *знаками) і передбачає, що це єдині два оператори.

Він може працювати з введеннями чисел настільки великими, скільки дозволяє пам'ять комп'ютера.

Я майже впевнений, що це може бути і далі.

EDIT: 16 31 байт збережено завдяки @Copper.


Дякую за відповідь, (+1). Чи може він обробляти велику кількість входів?
Анастасія-Романова 秀

@ Анастасія-Романова 秀 Умммм ... я впевнена, що вони можуть. Чи можете ви надати мені приклади великих входів? Я спробую обчислити з них.
клісмік

Можливо: 3218753647208435810122106 * 29349566754?
Анастасія-Романова 秀

1
@ Анастасія-Романова 秀 Так, це спрацювало за 0,5 секунди, не встигнуло.
клісмік

Ви можете перейти "+" 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 для мене все ще є новим, тому це, мабуть, не найкраще рішення. Завдання було все-таки весело. Крім того, код працював з дуже великою кількістю без особливих труднощів.


Це дуже пізно, але ви можете зменшити більшість просторів там.
клісмік

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

Пояснення

На основі чудового рішення для Java @Sean Bean.

  • p: Закриття (функція, лямбда, що завгодно), що реалізує рішення
  • t: Поточну глибину виклику (кількість повторень) pзавжди слід викликатиt=1
  • m: Операція для виконання 0"додавання" 1для "множення"
  • d: Список операндів, кожен операнд є об'єктом String
  • e: Елементи dкожного, перетвореного на цілий ряд
  • r: Сума або добуток e, залежно від операціїm
  • Звіт про результат, починаючи з r > 9:
    • Якщо багатозначний ( 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 сьогодні сьогодні ...)

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ми покладаємось на те, що вхідний аргумент є функцією, а просто явно викликаємо його. (Так, для функцій, які є першокласними об'єктами!)
  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. Я думаю, що це мета-пост, на який ви посилаєтесь.
Джузеппе

@Giuseppe Ага так, ти маєш рацію в обох аспектах. Дякую!
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

Математика, 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 (для (*)).

Невикористаний і тестовий код:

Спробуйте тут.

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.