分而治之


22

有时,当我懒散地尝试考虑出现在我面前的数字时,过了一会儿,我意识到这比我想象的要容易。就拿2156例如:它最终发生,我认为这两个2156是的倍数7,所以肯定2156 = 21 x 100 + 56也是一个倍数7

您的任务是编写一些代码,以标识由于此类巧合而更易于分解的数字。

更确切地说:

编写一个程序或函数,将正整数n作为输入,如果存在一个除数d(大于1),n可以将其切成两个以产生两个正整数,每个整数都是的倍数d;然后返回一个真值。否则返回假值。

  • “切成两半”表示您的想法:通常的以10为底的表示形式n在某个点划分为前半部分和后半部分,以产生另外两个以10为底的整数。如果第二个整数的前导零是可以的(但请注意,它必须是一个正整数,所以拆分12301230无效)。
  • 真实值和虚假值可以取决于输入。例如,如果在您选择的语言中有任何非零整数是真实的,那么欢迎您返回除数d或“ 的除数”之一n(或n就此而言)。
  • 例如,集合中至少有两位数字的任何偶数{2, 4, 6, 8}都会产生真实值:只需在第一个偶数之后将其分割即可。同样,例如,任何质数n都会产生伪造的值,任何一位数字也会产生伪造的值。
  • 注意,考虑素数除数就足够了d
  • 您可以假定输入有效(即正整数)。

这是,因此以字节为单位的最短代码获胜。但是欢迎使用所有语言的解决方案,因此我们可以争取使用每种语言的最短代码,而不仅仅是整体上最短的代码。

测试用例

(您只需要输出一个真实值或虚假值;下面的注释仅是为了说明。)产生真实值的一些输入是:

39  (3 divides both 3 and 9)
64  (2 divides both 6 and 4)
497  (7 divides both 49 and 7)
990  (splitting into 99 and 0 is invalid; but 9 divides both 9 and 90)
2233  (11 divides both 22 and 33)
9156  (3 divides both 9 and 156; or, 7 divides both 91 and 56)
11791  (13 divides both 117 and 91)
91015  (5 divides both 910 and 15)
1912496621  (23 divides both 1912496 and 621; some splittings are multiples of 7 as well)
9372679892  (2473 divides both 937267 and 9892; some splittings are multiples of 2 as well)

产生虚假值的一些输入是:

52
61
130  (note that 13 and 0 is not a valid splitting)
691
899
2397
9029
26315
77300  (neither 7730 and 0 nor 773 and 00 are valid splittings)
2242593803

¹是,我确实做到了

Answers:


7

视网膜31 29字节


,$';$`
\d+
$*
;(11+)\1*,\1+;

在线尝试!

输出有效输入为正整数,无效输入为零。

我不建议等待更大的测试用例...

说明


,$';$`

在输入的每个位置插入一个逗号,然后在该位置之前插入所有内容,然后在该位置之后插入一个分号,然后再插入所有内容。那是做什么的?它为我们提供了一个数字的所有可能分割(由,,分隔由;),然后在最后再次输入。所以输入123变成

,123;1,23;12,3;123,;123
     ^     ^     ^

我已在其中标记了原始输入字符(未标记的内容是我们插入的内容)。请注意,这将创建不是实际拆分的无效拆分,并且它也不在乎尾随分量是否全为零,但是我们将避免稍后再接受它们。创建无效拆分的好处是,我们知道每个有效拆分的;前后都有一个,因此我们可以在字边界上节省两个字节。

\d+
$*

将每个数字转换为一元。

;(11+)\1*,\1+;

通过将两个半部分匹配为至少2的倍数来匹配拆分。


关于视网膜的快速问题:领先的换行符是做什么的?
HyperNeutrino

@HyperNeutrino好吧,第一行是我们匹配的第一个正则表达式,我们想匹配空的正则表达式,以便将替换插入到字符之间的每个单个位置。
马丁·恩德

哦好的。谢谢!我可能应该多看看Retina;因为它似乎主要是基于正则表达式的,所以它可能对kolmogorov复杂性问题有好处
HyperNeutrino

最后一行可能是;(11+)+,\1+;
莱利(Riley)

@Riley不能保证第一段是同一因子的倍数。
马丁·恩德

6

Brachylog(2),8个字节

~c₂ḋᵐ∋ᵐ=

在线尝试!

说明

~c₂ḋᵐ∋ᵐ=
~c₂       Split the input into two pieces
    ᵐ ᵐ   On each of those pieces:
   ḋ ∋      Choose a prime factor
       =  such that both the chosen factors are equal

显然,如果相同的数字(大于1)将两部分相除,则相同的数将对这两部分相除。整洁地要求该因子为素数不允许1作为因子。它还防止将文字0选择为数字的一部分(因为0没有素数分解,并且会导致失败)。

无需检查匹配的内部零。如果分裂x0y有效,x0并且y将工作一样好(和走另一条路,如果x0y作品,然后我们有一个可行的解决方案,无论是否x0y将工作或没有)。

像这样的Brachylog完整程序返回一个布尔值;true.如果false.所有路径都导致失败,则有某种方法可以使它无故障运行(即做出选择,以使没有错误发生)。这正是我们想要的。


4

果冻14 12 11 10字节

ŒṖḌo1g/€P>

感谢@JonathanAllan打高尔夫球1个字节!

在线尝试!

怎么运行的

ŒṖḌo1g/€P>  Main link. Argument: n

ŒṖ          Compute all partitions of n's decimal digits.
  Ḍ         Undecimal; convert each array in each partition back to integer.
   o1       OR 1; replace disallowed zeroes with ones.
     g/€    Reduce (/) each (€) partition by GCD (g).
            The last GCD corresponds to the singleton partition and will always be
            equal to n. For a falsy input, all other GCDs will be 1.
        P   Take the product of all GCDs.
         >  Compare the product with n.

我认为您可以删除D,因为make_digits实际上是ŒṖ
乔纳森·艾伦

由于某种原因,我认为这会创建一个范围...谢谢!
丹尼斯,

3

Mathematica,63 62字节

(感谢格雷格·马丁(Greg Martin)1个字节)

1<Max@@GCD@@@Table[1~Max~#&/@Floor@{Mod[#,t=10^n],#/t},{n,#}]&

该函数需要一个整数作为输入并返回TrueFalse。如果要大量测试,请在等待时携带一本书阅读。

说明:

  • Floor@{Mod[#,t=10^n],#/t}算术上将输入分为最后n几位和其余m-n位数(其中m为位数)。
  • Table[1~Max~#&/@...,{n,#}]n最多对输入数字执行此操作。(这太大了。我们只需要达到输入的位数即可,但是这样可以节省字节并仍然给出正确的结果。)该1~Max~#&/@位摆脱了零,因此像这样的数字130 -> {13,0}不计入作为True
  • 1<Max@@GCD@@@... 找到这些对中每个对的最大公约数,并检查这些除数中的任何一个是否大于1。

1
好答案!您可以使用{#~Mod~10^n,#/10^n}或来保存一个字节{Mod[#,t=10^n],#/t}
格雷格·马丁

我尝试了#~Mod~10^n,但是好像被包围了Mod[#,10]^n而不是Mod[#,10^n]。不过,我没有想到您的第二个建议!
不是一棵树

公平的点Mod[#,10]^n
格雷格·马丁


2

C,145个 142 139 138 135字节

i,a,b;f(){char s[99];scanf("%s",s);for(char*p=s;*p++;)for(b=atoi(p),i=*p,*p=0,a=atoi(s),*p=i,i=1;i++<b;)*s=a%i-b%i|b%i?*s:0;return!*s;}

2

JavaScript(ES6),74 71 70字节

f=(s,t='',u)=>u?s%t?f(t,s%t,1):t:s&&f(t+=s[0],s=s.slice(1),1)>1|f(s,t)
<input oninput=o.textContent=f(this.value)><span id=o>

将输入作为字符串,对于代码段来说非常方便。编辑:由于@ user81655,节省了3个字节。


保存两个字节:(c,i)- > ci+1- > ++it=''- > i=t='',这一招非常有用,你需要使用基于1指数和有地方初始化任何时候i0
user81655

我也相信t=''可能是t=0,因为c无论如何都将其添加到字符串中。
user81655

@ user81655发生这种情况是因为我最初从and切片i,所以我不需要基于1的索引,但是随后我将第一个切片打到t+=c
尼尔

喔好吧。另外最后一两件事,我想这也可能是一个递归函数短:f=(x,y,z)=>z?x%y?g(y,x%y):y:x?f(x,y,1)>1||f(x.slice(1),~~y+x[0]):0。我也结合了您的GCD功能f。可能会打得更远。最后的建议,我保证!:P
user81655

@ user81655遗憾的是,当我的gcd功能过于简化时x=0,我的功能过于简化了,而要解决这个问题,您的错字把我带到了72个字节,所以很幸运,我之后又能打高尔夫球2个字节。
尼尔

2

Python 3中,133个 118 117字节

i,j=int,input()
from fractions import*
print(any(i(j[k:])*i(j[:k])*~-gcd(i(j[k:]),i(j[:k]))for k in range(1,len(j))))

当然不是最短的,可能会缩短一点。在工作O(n)时间。 由于Dead Possum -15个字节,感谢ovs -1个字节,感谢This Guy ,以默认的Python布尔值-3个字节的\d+形式获取输入,并以格式给出输出,格式(True|False)为默认Python布尔值
-3个字节


from fractions import*将节省3个字节
死貂

对于900,它返回True。我想这是错误的。MB你应该改变内anyall?在这种情况下,您可以将所有部分更改i(j[k:])and i(j[:k])为125字节。这里是修复程序
Dead Possum

您可以通过乘法替换and和all:any(i(j[k:])*i(j[:k])*~-gcd(i(j[k:]),i(j[:k]))for k in range(1,len(j)))
ovs

@DeadPossum哦,对了,我应该做的。是的,我目前的方法中包含很多可打高尔夫球的部件,但我将遵循ovs的建议。感谢您指出了这一点!(真的应该
亲自

您可以通过删除)) for
Caird coinheringaahing

1

QBIC91 90字节

;_LA|[a-1|B=left$(A,b)┘C=right$(A,a-b)┘x=!B!┘y=!C![2,x|~(x>1)*(y>1)*(x%c=0)*(y%c=0)|_Xq}?0

说明:

;               Get A$ from the command prompt
_LA|            Get the length of A$ and place it in a% (num var)
[a-1|           for b%=1; b% <= a%-1; b%++
B=left$(A,b)    break A$ in two components on index b%
C=right$(A,a-b)
x=!B!┘y=!C!     Convert both parts from string to num, assign to x% and y%
[2,x|           FOR c% = 2; c% <= x%; c%++

This next IF (~ in QBIC) is a bit ... iffy. It consists of a set of comparators.
Each comparator yields a -1 or a 0. We take the product of these. At any failed
comparison this will yield 0. When successful, it yields 1, which is seen as true by QBasic.

~(x>1)*(y>1)        IF X>1 and Y>1 --> this stops '00' and '1' splits.
*(x%c=0)*(y%c=0)    Trial divide the splits on loop counter c%.

|_Xq            Success? THEN END, and PRINT q (which is set to 1 in QBIC)
}               Close all language constructs (2 FOR loops and an IF)
?0              We didn't quit on match, so print 0


1

Perl 5,46个字节

代码的43个字节+ -p标志的3个字节。

s~~$\|=grep!($`%$_|$'%$_),2..$`if$`*$'~ge}{

在线尝试!或尝试使用允许多个输入的修改版本
您可能不想在最大的输入上尝试此操作,因为这可能需要一段时间(非常长)。

说明:
我们使用循环遍历单词中的每个位置s~~~g,其中$`包含前数字和$'后数字。如果$`*$'为true(表示没有一个为空,则没有一个为0),则我们检查数字是否介于2 $`并将两者均除(用grep!(...),2..$`)。如果是这样,$\|=..将设置$\为一个非零值,该值在末尾隐式打印,这要归功于-pflag。


2
如果有人知道如何渲染$<backquote>SE降价促销,请告诉我。
达达

1
您可以通过使用显式<code></code>(而不是``)来实现,然后将反引号转义为\`。另外,此注释的编写很痛苦,因为必须对其进行两次转义(并且两组转义规则不同!)。

@ ais523太好了,非常感谢!:)
Dada

0

Python 2,69个字节

f=lambda n,d=10,k=2:k<d<n and(n/d%k+n%d%k<1<n%d)|f(n,d,k+1)|f(n,10*d)

使用递归而不是GCD内置。

在线尝试!

怎么运行的

˚F调用与一到三个参数(d默认为10ķ2),它首先检查表达式的值k<d<n。如果不等式k <dd <n都成立,则and执行以下表达式并返回其值;否则,f将仅返回False

在前一种情况下,我们从评估表达式开始n/d%k+n%d%k<1<n%d

d永远是10的幂,所以n/dn%d有效的十进制数字拆分ň成两片。当且仅当求值为0时,这两个切片都可被k整除,这是通过将结果与1进行比较来测试的。n/d%k+n%d%k

由于部分要求是两个切片都必须表示正整数,因此n%d还将的值与1进行比较。请注意,1没有素数除数,因此不需要与0进行更昂贵的比较。另外,请注意,d <n已经确保n/d将计算为正整数。

最后,将所有结果递归f(n,d,k+1)(尝试下一个潜在的公因数)和f(n,10*d)(尝试拆分),并返回所有三个结果的逻辑或。这意味着,当(且仅当)kn / dn%d的公因数时,f才返回True;对于k的较大值和/或更高的10 d的幂,则f为真

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.