数学在Anastasiya的世界中如何运作?


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 (+) bF(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
Peter Taylor

4
伟大的第一个问题!我从自己的问题中识别出一般规则格式和句子。;)
Kevin Cruijssen

4
@KevinCruijssen是的。那就对了。由于它没有版权,因此未经您的允许,我将其复制。Hehehe:D
Anastasiya-Romanova秀

4
@ Anastasiya-Romanova秀“没有版权”?在二十一世纪?不; 这里的一切都是CC-BY-SA 3.0。提交内容时授予权限。检查站点页脚。
Mindwin

1
@ BradGilbertb2gills是的,当然。顺便说一句在帖子中。Quote: “输入的格式是程序员的任意选择”。
Anastasiya-Romanova秀

Answers:


11

Dyalog APL33 32 30 29 字节

这将APL扩展为包括前缀符号+/A n₁ n₂×/A n₁ n₂。(实际上,您可以使用/A。左侧的任何操作。)返回{结果,重复计数}的列表。

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

A←{根据左手函数和右手参数定义一个高阶函数⍺⍺

(⊃,≢) 的第一个元素,然后是

⍺⍺{提供给高阶函数的函数(+/用于求和或×/乘积)

的独特元素

⍵,⍨ 附加的论点

⍺⍺ 美联储功能应用于

⍎¨ 每个角色的评价

的字符表示

⊃⍵ 参数的第一个元素

}⍣≡ 重复应用,直到结果与参数相同,从

⍺⍺⍵应用于原始参数的原始输入函数(+/×/

} [高阶函数定义的结尾]

在线尝试APL!(出于安全原因已被模拟e。)

感谢@ngn节省了一个字节。


0字节(开玩笑)

实际上,Dyalog APL已完全支持Anastasiyan数学。代替(+)(×),它使用+{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}×{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}

尝试81 +{(⊃,≢)⍺⍺{∪⍵,⍨⍺⍺e¨⍕⊃⍵}⍣≡⍺⍺/⍺⍵} 3121 ×{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/e¨⍕⍵}⍣=⍵⍺⍺⍨⍺} 111


感谢您的回答(+1)。它可以处理大量输入吗?
Anastasiya-Romanova秀

1
如果设置⎕FR←1287(即使用IEEE 754-2008 128位小数˚F loating点- [R epresentation)和⎕PP←34(即使用34个字符P RINT P recision),则可以使用下面10³⁴整数。
2013年

嗯,尽管它得到了全面的支持,但不是+{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}×{n←0⋄n,⍺⍺{n+←1⋄⍺⍺/⍎¨⍕⍵}⍣=⍵⍺⍺⍨⍺}仍然还有很多字节吗?我对这是0字节感到困惑。:S
Kevin Cruijssen

3
@KevinCruijssen OP允许任何输入符号。因此,如果一种语言开箱即用地支持默认符号Anastasiyan数学,则多字符字形(+)就是Anastasiyan +。Dyalog APL确实支持Anastasiyan数学,但它使用了不同的多字符字形,正如*表示能力和您需要×乘法,而/表示复制和您需要÷除法。
2013年

1
@Adám嗯,这很有道理。这有点违反了OP的规则,但并没有违反它们。代替(+)+{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

定义功能,#它首先需要ab再操作o。有趣的事实:这可以与您想要的任何运算符(实际上是任何函数)一起使用!


感谢您的回答(+1)。它可以处理大量输入吗?
Anastasiya-Romanova秀

4
@ Anastasiya-Romanova秀是的,因为Haskell的Integer类型不受限制,所以它可以处理与RAM一样大的数字。
ThreeFx

8

Pyke,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
真好!我们可以得到解释吗?
Emigna

感谢您的回答(+1)。它可以处理大量输入吗?
Anastasiya-Romanova秀

@阿纳斯塔西-诺娃秀它应该能够处理任意数字

我无法测试您的代码,因为网络被封锁,因为它违反了我父母的互联网使用政策。T_T
Anastasiya-Romanova秀

这样的事情:网页被阻止!您试图访问违反互联网使用政策的网页。网址:pyke.catbus.co.uk/?code=RE%60DltImbRoKr%29oh&input=B%0A21%2C+111&warnings=0类别:未分级
Anastasiya-Romanova秀

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)。它可以处理大量输入吗?
Anastasiya-Romanova秀

1
@ Anastasiya-Romanova秀达到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'],'+')可以再保存一个字节,但是这感觉像是在扩展规则太多了……
Dennis


...在这种情况下,我什至走得更远,分别考虑通过operator.addoperator.mul;)
Tobias Kienzler

7

珀斯,16岁

eJ.uvjhQ`N.vQ)lJ

接受类似"+ 123 12"加法和"* 123 12"乘法的输入。输出如result<linefeed>steps

在此处尝试运行,或运行Test Suite,但是请注意,这取决于eval,因此只有加法变体才能在在线解释器中使用。脱机解释器可以正确使用乘法。

这使用累积归约函数创建中间结果列表,因此"+ 351 14568"我们得到[14919, 24, 6]。这是有效的,因为一位数字是Anastasiya加法和乘法的固定点。然后,我们只获取数组的最后一个元素以及数组的长度。

这将适用于任意数量的数字,至少直到内存用完为止。


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回来了 !是的
p

用法:

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

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

非常感谢@plannapus打出24个字节!
-7个字节,这要归功于@Vlo的一个好主意!


是的,由于我喜欢R,请添加说明!这是我仅次于VBA的第二语言。(+1)
Anastasiya-Romanova秀

1
@ Anastasiya-Romanova秀:完成!
弗雷德里克·

@plannapus:真的很好!非常感谢 !
弗雷德里克·

1
@Frédéric很好用strtoi!还有4个字节让您遭到殴打。
plannapus

1
看起来您可以通过在第一个操作x的赋值中包含O的定义来进一步提高字节:x =(O = switch(S,sum,`*`))(G,D);。
rturnbull

6

05AB1E20 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)。它可以处理大量输入吗?
Anastasiya-Romanova秀

@ Anastasiya-Romanova秀我不明白为什么没有。你有例子吗?
Emigna '16

您的程序已经过此类输入的测试,因此很完美:)
Anastasiya-Romanova秀

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代码,它是32位ARM的可变长度指令编码(2或4字节)。因此,它可以处理的最大值为2 ^ 32-1。如果它不符合AAPCS(46个字节),则可以丢弃2个字节,因为我们不必在开始时堆叠寄存器。

非高尔夫装配(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的方法有些不同:

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

因为如果您是第一位的,那么您就会获得更多赞誉
Anastasiya-Romanova秀

@ Anastasiya-Romanova秀足够多了:)
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

删除了两个换行符(一个空格),并将两个输入数字都放在一个向量中,而不是单独的参数中。由于pajonk,这节省了9个字节!k=@(x)...多亏了烧杯,将其删除以节省另外11个字节=)最后,将整个内容转换为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

第二个参数是方法,对于ADD为0,对于MULTIPLY为1。

第三个参数是字符串数组,其中包含要相加/相乘的值。

不打高尔夫球

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回答要短。但是,你也应该打印步骤以及当前正在从你的答案缺少答案..
凯文Cruijssen

@KevinCruijssen啊。太无聊了。我现在尝试修复该问题。
肖恩·怀尔德

顺便说一句,你可以打高尔夫目前的答案。m==0可以m<1并且Integer.parseInt可以Integer.decode
凯文·克鲁伊森

我用的Java不太多,但j最后需要使用var吗?(r+"")两次内联看起来会节省一些字节。
牛奶

1
我们以后不能更改我的帖子吗?如果您想提出修改建议,请在注释中提出。
肖恩·维尔德(Shaun Wild)

3

果冻,17个字节

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

在线尝试!

给定类似参数x y 1,这将计算Anastasiya和x (+) y

给定类似参数x y 0,这将计算Anastasiya乘积x (*) y

输出为[number of steps, result]


感谢您的回答,但是您的程序输出中不包含所需的步骤数?我在这里想念什么吗?
Anastasiya-Romanova秀

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(带有普通+*符号),并假定它们是仅有的两个运算符。

它可以处理计算机内存允许的最大数字输入。

我几乎可以肯定,这可以进一步发展。

编辑: 由于@Copper,节省了16 31个字节。


感谢您的回答(+1)。它可以处理大量输入吗?
Anastasiya-Romanova秀

@ Anastasiya-Romanova秀Uhmmm ...我相当确定他们可以。能给我一些大投入的例子吗?我将尝试从中进行计算。
clismique

也许:3218753647208435810122106 * 29349566754?
Anastasiya-Romanova秀

1
@ Anastasiya-Romanova秀是的,它的工作时间约为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)
Anastasiya-Romanova秀

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 '16

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),等待说明:)
Anastasiya-Romanova秀

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

脱胶

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:实现解决方案的闭包(函数,lambda等)
  • t:当前调用深度(迭代次数)p应始终使用t=1
  • m:要执行的操作,0用于“加”,1“乘”
  • d:操作数列表,每个操作数是一个String对象
  • e:的元素d,每个都转换为Integer
  • r:的总和或乘积e,取决于运算m
  • 结果语句,以r > 9
    • 如果是多位数字(r > 9),请重新调用,增加深度t并转换r为数字字符串列表(并返回结果)。
    • 如果为一位数,则返回rt作为列表。

测试程序

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+).fromEnumread.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,我们依赖于输入参数是一个函数,而只是显式地调用它。(是的,函数是一流的对象!)
  2. 代替初始化新变量作为计数器,我们滥用R的内建函数并使用T,其结果为TRUE(aka 1),但由于它不是保留变量,因此我们可以对其进行修改。T+T就是这样2。因此,我们将其用作计数器。
  3. 而不是cat输出,我们只是将其作为向量返回c。除了节省两个字节之外,将输出强制为向量的事实还确保了该输出为Tclass 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

@Giuseppe尼斯重组!我目前无法找到元共识,但是我有足够的信心相信在函数中使用Tand F计数器技巧实际上是无效的,因为这意味着该函数只能被调用一次。因此,除非最后有明确说明,否则这个答案(以及我的其他几个答案)都是无效的rm(T)。我将继续寻找该元文章,因此我可以确定我不仅仅是在做梦。
rturnbull

我相信,只要您不进行修改或在全球环境中,Tand F技巧都是完全有效的。例如,始终返回。我认为是您所引用的meta帖子。TFf=function(){T=T+1;T}2
朱塞佩

@Giuseppe啊,是的,您在两个方面都对。谢谢!
rturnbull

1

Ruby,55个字节

递归调用。过去与@ edc65的JavaScript答案大不相同,但是当我对其进行优化时,它最终成为了一个直接独立于其答案而开发的直接端口,减去了最后一项优化,其中涉及检查评估结果而不是传入的操作数列表的长度,这使我超过了他们的字节数。

输入是代表运算符的字符串,以及包含操作数的数组。

在线尝试。

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

结果是正确的,但是获得一位数值所需的步数不正确。您可以更正您的代码吗?
Anastasiya-Romanova秀

@ Anastasiya-Romanova秀啊,你是对的。我以前的逻辑要求它从头开始,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(*))。fo

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

及其适当的值。因为xf成为#1 + #2o成为Plus; 因为y,他们分别成为#1 #2Timesx在解释的最后部分重写函数:

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.