这是Loeschian号码吗?


33

正整数kLoeschian数,如果

  • k可以表示i*i + j*j + i*jij整数。

例如,第一正Loeschian号码为:1i=1j=0); 3i=j=1); 4i=2j=0); 7i=2j=1); 9i=-3j=3); ...注意ij对于给定k的不是唯一的。例如,9也可以与产生的i=3j=0

这些数字的其他等效特征是:

  • k可以表示i*i + j*j + i*jij非负整数。(对于每对整数ij都有一对给出相同值的非负整数k

  • 有一组k连续的六边形在六边形网格上形成网格化(请参见k = 4和的插图k = 7)。(由于这个属性,这些数字可在移动蜂窝通信网络中找到应用。)

  • 在序列的OEIS页面中查看更多特征。

挑战

给定一个正整数如果它是Loeschian数输出真实结果,否则,则输出虚假结果。

程序或函数应处理(例如不到一分钟)最多达1000或数据类型限制的输入。

代码高尔夫。最短的胜利。

测试用例

以下数字应输出真实结果:

1, 4, 7, 12, 13, 108, 109, 192, 516, 999

以下数字应输出虚假结果:

2, 5, 10, 42, 101, 102, 128, 150, 501, 1000

相关(如@PeterTaylor所述)
Luis

蛮力算法的注意事项:如果迭代到√k,则会将算法复杂度从O(n²)降低到O(n),但要花一些字节c;
Rod

i, j non-negative integers9 (i=-3, j=3)-是哪一个?
泰特斯

1
@Titus哦,现在我明白了。对于每对整数i,j,都有一个非负数对给出相同的k
Luis Mendo

Answers:


17

果冻11 9 字节

ÆF‘%3,2ḄȦ

在线尝试!验证所有测试用例

背景

二元二次形式a²+ ab +b²的基本结果中,作者证明了有关Löschian数的以下定理。

定理16. 任何非负整数的充分必要条件是在形式 A²+ AB +称b² 是,在它的质数分解,比其它所有素数 3 不在形式(6K + 1)具有连指数。

如相关OEIS页面上所述,由于所有整数都与 012的模3,数字3是唯一的素数是全等到0,和形式的所有数目(6K + 1)是一致的,以如图1所示,该定理可以替代地陈述如下。

当且仅当 2 3 一致 n的所有素均具有偶数指数时,非负整数 n 才是Löschian数

怎么运行的

ÆF‘%3,2ḄȦ  Main link. Argument: n (integer)

ÆF         Yield the prime factorization of n, as prime-exponent pairs.
  ‘        Increment all primes and exponents, turning primes of the form 3k - 2
           into multiples of 3 and odd exponents into multiples of 2.
   %3,2    Reduce all incremented primes/exponents modulo 3/2.
           n is Löschian if and only if this does not result in a [0, 0] pair.
           Due to Jelly's form of vectorization, this yields [3, 2] if n = 1.
       Ḅ   Unbinary; convert each pair from base 2 to integer.
           Note that [x, y] = [0, 0] if and only if 2x + y = 0.
        Ȧ  All; return 1 if the result contains no zeroes, 0 otherwise.

17

视网膜66 63 45 43 36字节

^()(\1(?<1>.\1))+(\1(.(?(4).\4)))*$

尽管标题为Retina,但这只是一个简单的.NET正则表达式,它接受Loeschian数字的一元表示形式。

输入999和1000占用的时间不到一秒钟。

在线尝试!(第一行启用了换行分隔的测试套件,为方便起见,后两行将转换为一元。)

说明

解决方案基于以下分类:输入可以写i*i + j*(i + j)为正数i和非负数j(因为我们不必处理输入0),而这n*n仅仅是前n奇数个整数的和。打高尔夫球是前瞻性参考中的一项有趣的练习。

“前向引用”是将后向引用放入其所引用的组中。当然,当第一次使用该组时,这是行不通的,因为还没有要进行反向引用的内容,但是如果将其置于循环中,则每次使用反向引用都会捕获先前的迭代。反过来,让我们在每次迭代中构建一个更大的捕获。这可以用来为三角形,正方形和斐波那契数之类的东西制作非常紧凑的图案。

例如,利用平方只是第一个n奇数整数的和的事实,我们可以匹配平方输入,如下所示:

(^.|..\1)+$

在第一次迭代中,..\1由于\1没有值,因此无法正常工作。因此,我们从^.捕获单个字符到组开始1。在后续迭代中,^.由于锚点而不再匹配,但是现在..\1有效。它比上一次迭代匹配两个更多的字符,并更新捕获。这样,我们匹配增加的奇数,在每次迭代后得到一个平方。

现在很遗憾,我们不能按原样使用此技术。匹配之后i*i,我们还需要得到i,以便我们可以将其乘以j。一种简单(但很长)的方法是利用匹配i*i需要i迭代的事实,这样我们就i可以在group中捕获事物1。现在,我们可以使用平衡组来提取它i,但是就像我说的那样,这很昂贵。

取而代之的是,我想出了另一种写此“连续奇数整数之和”的方法,该方法也i最终在捕获组中产生。当然,i奇数是2i-1。这为我们提供了一种在每次迭代中仅将前向引用增加1的方法。这就是这一部分:

^()(\1(?<1>.\1))+

()只是将空捕获推入组1(初始化i0)。这几乎等同于^.|上面的简单解决方案,但是|在这种情况下使用会有些棘手。

然后我们有了主循环(\1(?<1>.\1))\1匹配前面i(?<1>.\1)然后更新组1i+1。在new方面 i,我们已经匹配了2i-1字符。正是我们需要的。

完成后,我们匹配了一个正方形,i*i并且组1仍然包含i字符。

第二部分更接近我上面显示的简单平方匹配。让我们暂时忽略对它的反向引用1

(.(?(4).\1))*

这与基本上相同(^.|..\4)*,不同之处在于我们无法使用它,^因为我们不在字符串的开头。取而代之的是,我们使用条件,.\1仅在已经使用group时才匹配附加条件4。但是实际上这是完全一样的。这给了我们j*j

唯一缺少的是j*i术语。j*j通过利用j*j计算仍然需要j迭代的事实,我们将此与结合起来。因此,对于每次迭代,我们也向前移动光标i\1。我们只需要确保不要将其写入group 4,因为那样会使匹配的连续奇数混乱。这就是我们得出的结果:

(\1(.(?(4).\1)))*

2
我读的次数越多,我的理解就越少。我真的很想知道很多正则表达式
哈维尔·迪亚兹

@JavierDiaz 有一系列文章解释了基于Java regex的Stack Overflow的正向引用。那里的例子可能要简单一些。
Martin Ender

13

CJam(16 15字节)

{mF{~\3%2=&},!}

在线演示

这是一个块(“匿名函数”),它在堆栈上输入并离开01在堆栈上。它使用数字为Loeschian的特征,即它不具有等于2 mod 3且具有奇重数的素数。

感谢Dennis节省了一个字节。


哇,很好的表征!
Luis Mendo

6

Python 2,56个字节

lambda n:any(n==i*i%n+i/n*(i/n+i%n)for i in range(2*n*n))

6

Haskell,42个字节

f k=or[k==i*i+j*j+i*j|i<-[0..k],j<-[0..i]]

用法示例:f 501-> False

尝试的所有组合i,从0kj0i。如果相等性对于至少一种组合成立,则or返回。Truek==i*i+j*j+i*j

@flawr发现具有相同字节数的版本略有不同:

f k|v<-[0..k]=or[(i+j)^2==k+i*j|i<-v,j<-v]

我不知道or,冷=)也许你有一个想法如何高尔夫这种替代措辞:f k|v<-[0..k]=or[(i+j)^2==k+i*j|i<-v,j<-v]
瑕疵的

@flawr:不,不知道如何进一步打版。如果您不介意,我会将其添加到我的答案中作为替代版本。
nimi

5

Java 8,81字节

k->{for(int i=0,j;i<=k;i++)for(j=0;j<=k;)if(i*i+j*j+i*j++==k)return 1;return 0;};

简单,天真的实现。巧合的是与C#相同的代码,但使用->而不是=>


少三个字节,因为您可以省略花括号和结尾;。该死的!
TheLethalCoder

@TheLethalCoder我实际上不能,我犯了一个错误-与C#相同的字节数。
贾斯汀

无论如何让我感觉更好:)
TheLethalCoder '16

这似乎没有测试阴性ij
泰特斯


4

果冻15 14 13 12 字节

1英里感谢英里。

²S+P
‘ṗ2’Ç€i

在线尝试!

验证较小的测试用例

在测试大量(大于50)时要提一个建议:不要。

Truthy是一个正数。假为零。

说明

‘ṗ2’Ç€i   main chain, argument: z
‘ṗ2’      generate all pairs of numbers between 0 and z inclusive
    ǀ    apply the helper link to each pair
      i   find the index of z in the result

²S+P   helper link, argument: [x,y] (a pair of numbers)
²      compute [x*x, y*y]
 S     x*x+y*y
  +P   x*x+y*y+x*y

现在绑(...)... :-)
路易斯·门多

我们应该利用彼得的特征...吗?
路易斯·门多

@LuisMendo这似乎很有趣,但似乎会更长
Leaky Nun

我认为您不需要弄平它。您的帮助程序链接已经从元组映射到整数。
英里

@miles很聪明,谢谢。
Leaky Nun


3

玛特14 13字节

t:0hU&+HM&*+m

在线尝试!验证所有测试用例

输出10

说明

t:    % Implicitly input number k. Duplicate. Generate vector [1 2 ...k]
0h    % Concatenate a 0. Gives [1 2 ... k 0]
U     % Square, element-wise. Gives [1 4 ... k^2 0]
&+    % Sum of all pairs from this vector. Gives a (k+1)×(k+1) matrix
HM    % Push [1 2 ... k 0] again
&*    % Product of all pairs from this vector. Gives a (k+1)×(k+1) matrix
+     % Add the two matrices
m     % True if k is a member of the resulting matrix. Implicitly display

您刚出去高尔夫果冻吗?
Leaky Nun

@LeakyNun让我们看看它能持续多久。也许我会稍微延迟一下代码说明:-P
Luis Mendo

不。– – – – –
Leaky Nun

轮到您– – –
Leaky Nun

@LeakyNun Aw :-(现在我可以添加解释:-)
Luis

3

Python,49个字节

lambda n:0in[(n-3*i*i+0j)**.5%1for i in range(n)]

使用的OEIS上给出的等效二次形式n == 3*i*i+j*j。通过取平方根并检查它是否为整数(即​​等于0模1),来检查是否n-3*i*i为任意i平方的完美平方。请注意,Python会精确计算完美平方的平方根,而没有浮点错误。这+0j使得它成为一个复数,以避免负数的平方根出现错误。


3

C(gcc),71 69字节

i,j,r;f(n){for(r=i=n+1;i--;)for(j=n;j--;)r*=n!=i*i+j*j+i*j;return!r;}

69个字节:i,j,r;f(n){for(r=i=n+1;i--;)for(j=n;j--;)r*=n!=i*i+j*j+i*j;return!r;}
owacoder

这似乎没有测试阴性ij
泰特斯

@Titus该问题指示非负数ij
orlp

积极的k,但不ij。仔细看看这些例子。
泰特斯(Titus)

@Titus从挑战引述:k可以表示为i*i + j*j + i*ji, j 非负整数。” 仔细看看。
orlp

2

C#,84 82 81字节

k=>{for(int i=0,j;i<=k;++i)for(j=0;j<=k;)if(i*i+j*j+i*j++==k)return 1;return 0;};

天真的解决方案。1 =真,0 =假


2

VBA,68 67字节

Function L(N):For a=0To N:For b=0To a:L=L+(N=a^2+a*b+b^2):Next b,a

天真的搜索,在n = 1000时开始缓慢降低。Excel将零收益识别为虚假,将其他所有收益识别为真实。

请注意,由于给定i> j> = 0,因此无需研究负ij

(-i)2 +(-i)(-j)+(-j)2 = i 2 + ij + j 2

(与ij相同的结果)

(-i)2 +(-i)j + j 2 = i 2 -ij + j 2

i 2 + i(-j)+(-j)2 = i 2 -ij + j 2

(如果一个为负数,则无关紧要),然后

(IJ)2 +(IJ).J + J 2 =(I 2 - 2ij + J 2)+(IJ - J 2)+ J 2 = I 2ij + J 2

并且,由于(ij)j均为非负数,因此可以使用非负数实现任何生成负数的Loeschian数。


保存了一个字节,Next:Next-> Next b,a感谢泰勒·斯科特(Taylor Scott)。


这似乎没有测试阴性ij
泰特斯

请参见“其他等效特征”下的第一点。请注意,所有测试用例均正确显示。我会在答案中添加数学上的证明(如果可以的话)。
Joffan '17年

对不起,我的错。过度阅读那是没有必要的。
泰特斯

@乔芬你可以凝结 Next:NextNext b,a
泰勒斯科特

@Joffan再次查看您的解决方案,也许是因为缺少 :End Function解决方案结尾处
Taylor Scott

1

Javascript(使用外部库-可枚举)(63字节)

k=>_.Range(0,k+1).Any(i=>_.Range(0,k+1).Any(j=>i*i+j*j+i*j==k))

链接到图书馆:https : //github.com/mvegh1/Enumerable 代码说明:创建一个从0到k的整数范围(将此范围称为“ i”范围​​),并测试是否有任何“ i”满足某个谓词。该谓词创建一个从0到k的范围(称为“ j”范围),并测试是否有任何“ j”满足某个谓词。谓词是洛希式公式

enter image description here


1

Perl 6  52个51  50字节

->\k{?first ->(\i,\j){k==i*i+j*j+i*j},(0..k X 0..k)}
->\k{?grep ->(\i,\j){k==i*i+j*j+i*j},(0..k X 0..k)}

{?grep ->(\i,\j){$_==i*i+j*j+i*j},(0..$_ X 0..$_)}

说明:

{
  # Turn the following into a Bool
  # ( Technically not necessary as a list of 1 or more values is truthy )
  ?

  # find all where the code block returns a truthy value
  grep

  # pointy block that takes one value (list of 2 values)
  # and gives each of the values in it a name
  ->
    $ ( \i, \j )
  {
    # return true if the definition matches
    $_ == i*i + j*j + i*j
  },

  # a list of 2 element lists (possible i and j values)
  ( 0..$_ X 0..$_ )
}

测试:

use v6.c;
use Test;

my @true = 0, 1, 4, 7, 12, 13, 108, 109, 192, 516, 999;
my @false = 2, 5, 10, 42, 101, 102, 128, 150, 501, 1000;

plan (@true + @false) * 2;

my &is-loeschian = {?grep ->(\i,\j){$_==i*i+j*j+i*j},(0..$_ X 0..$_)}

for |(@true X True), |(@false X False) -> ( $input, $expected ) {
  my ($result,$seconds) = $input.&time-it;
  is $result, $expected, ~$input;
  cmp-ok $seconds, &[<], 60, "in $seconds seconds"
}

sub time-it ( $input ) {
  my $start = now;
  my $result = $input.&is-loeschian;
  my $finish = now;
  return ( $result, $finish - $start )
}
1..42
ok 1 - 0
ok 2 - in 0.00111763 seconds
ok 3 - 1
ok 4 - in 0.00076766 seconds
...
ok 19 - 516
ok 20 - in 0.19629727 seconds
ok 21 - 999
ok 22 - in 0.1126715 seconds
ok 23 - 2
ok 24 - in 0.0013301 seconds
ok 25 - 5
ok 26 - in 0.00186610 seconds
...
ok 37 - 150
ok 38 - in 0.83877554 seconds
ok 39 - 501
ok 40 - in 9.2968558 seconds
ok 41 - 1000
ok 42 - in 37.31434146 seconds

这似乎没有测试阴性ij
泰特斯

@Titus (0..$_ X 0..$_)如果$_小于0,则会生成一个空列表,因此无需检查是否为负ij因为它们永远不会为负。由于只能产生True正的Loeschian数,因此对于负数情况,我不需要做任何特殊的事情。
布拉德·吉尔伯特b2gills

9 = (3*3)+(-3*-3)+(3*-3)是一个积极的Loeschian与i=3, j=-3; 但是我太过理解每个Loeschian数都有非负数ij。因此,不必寻找负数。所以实际上我们可以删除这些评论。对不起,很烦;我的错。
泰特斯

@Titus修改代码以{grep ->(\i,\j){$_==i*i+j*j+i*j},(-$_..$_ X -$_..$_)}(9)产生((-3,0),(-3,3),(0,-3),(0,3),(3,-3),(3,0))。老实说,我可能只是从其他答案中改编了它。
布拉德·吉尔伯特b2gills

1

PowerShell v2 +,63 56 55字节

param($k)(0..$k|%{0..($i=$_)|%{$i*($i+$_)+$_*$_}})-eq$k

接受输入$k,向上循环两次(外循环$i = 0 to $k,内循环$j = 0 to $i),每次迭代生成i*i + j*j + i*j(缩短为i*(i+j) + j*j)。这些结果封装在parens中,并作为数组传递给-eq$k。这用作仅选择等于输入的元素的过滤器。为真输出非零(返回的数字),为假输出不输出(空)。1000在我的机器上处理大约15秒钟。

测试用例

PS C:\Tools\Scripts\golfing> (1,4,7,12,13,108,109,192,516,999|%{.\loeschian-numbers.ps1 $_})-join','
1,4,7,12,13,108,109,192,516,999

PS C:\Tools\Scripts\golfing> (2,5,10,42,101,102,128,150,501,1000|%{.\loeschian-numbers.ps1 $_})-join','

PS C:\Tools\Scripts\golfing>

1

Perl,54 + 1(-n标志)= 55个字节

for$i(0..$_){for$j(0..$_){$i*$i+$j*$j+$i*$j-$_?1:say}}

运行的需求-n-M5.010标志:

perl -nE 'for$i(0..$_){for$j(0..$_){$i*$i+$j*$j+$i*$j-$_?1:say}}'

如果数字是Loeschian数,则输出一些东西,否则输出其他东西。

这种实现很无聊,因此这是另一个实现,基于正则表达式,为87字节,仅供参考:

perl -pE '$_=(1 x$_)=~/^(.*)(??{$1x(-1+length$1)})(.*)(??{$2x(-1+length$2)})(??{$1x length$2})$/'

谨慎处理这一点,因为回溯将占用大量内存,因此请勿尝试测试太大的数字!(尤其是不是Loeschians的数字)


1

Dyalog APL,19 个字节

⊢∊(∘.(×-⍨2*⍨+)⍨0,⍳)

检查是否ķ ε( + Ĵ)² - IJ,对于任何0≤ Ĵķ

    k
是从ij的平方中减去所有i j
    ∘.
        × i乘以j的所有组合的成员,其中0 i都以整数1到k
        -⍨
        2*⍨
        +
    
    0,
    

1000在我的M540上花费3.3秒,而在TryAPL花费的时间更少


1

Matlab,53 52字节

n=input('');[a b]=ndgrid(0:n);find((a+b).^2-a.*b==n)

简单搜索所有可能性。
将空数组输出为falsy,将非空向量输出为true值。

将全零矩阵视为虚假,将非全零矩阵视为真,我们可以摆脱find产生47 46字节解决方案的函数:

n=input('');[a b]=ndgrid(0:n);(a+b).^2-a.*b==n

@flawr节省了一个字节


1
(a+b).^2-a.*b==n更短。
瑕疵的

1

C,66字节

致电f()以进行测试。该函数返回找到的解决方案的数量。

q,r;f(n){for(r=q=0;q++<n*n;r+=n==q%n*(q%n+q/n)+q/n*q/n);return r;}

在ideone上尝试一下


1

Mathematica,44个字节

MemberQ[(+##)^2-##&@@@0~Range~#~Tuples~2,#]&

未命名函数,将整数作为输入并返回TrueFalse。该命令0~Range~#~Tuples~20和之间创建所有有序的整数对#。该函数(+##)^2-##&计算其自变量总和的平方减去其自变量的乘积;当在两个参数i和上调用时j,这完全i^2+j^2+ij是所希望的。因此,将在所有元组上调用该函数,然后MemberQ[...,#]检查输入是否为结果值之一。


1

ASP,39 + 4 = 43字节

o:-k=I*I+J*J+I*J;I=1..k;J=1..k.:-not o.

输出:如果k是Loeschian,则问题可以满足。

答案集编程是一种逻辑语言,类似于序言。我在这里使用Potassco的实现老兄

输入来自参数(-ck=长度为4个字节)。通话示例:

clingo -ck=999

输出样本:

SATISFIABLE

尝试过1000次:

clingo -ck=1000

输出样本:

UNSATISFIABLE

您可以在浏览器中尝试它;不幸的是,此方法不处理调用标志,因此您需要添加行#const k=999以使其起作用。


取消说明的代码:

v(1..k).  % predicate v(X) holds for any X in [1..k]
o:- k=I*I+J*J+I*J ; v(I) ; v(J).  % o holds if k is Loeschian.
:- not o.  % discard models where o doesn't holds (make problem unsatisfiable)

1

PHP,70个字节

for(;$i++<$k=$argv[1];)for($j=$i+1;$j--;)$i*$i+$j*$j+$i*$j-$k?:die(1);

从命令行参数获取输入;用1Loeschian数退出,用0else 退出。
用运行-nr

分解

for(;$i++<$k=$argv[1];)     # loop $i from 1 to $k
    for($j=$i+1;$j--;)      # loop $j from $i to 0
        $i*$i+$j*$j+$i*$j-$k?   # if $i,$j,$k do not satisfy the equation, do nothing
        :die(1);                # else exit with return code 1
                            # implicit: exit with code 0
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.