Це число Лоешян?


33

Позитивне ціле число k- лескіанське число, якщо

  • kможе бути виражений як i*i + j*j + i*jдля i, jцілих чисел.

Наприклад, перші позитивні лескіанські числа: 1( i=1, j=0); 3( i=j=1); 4( i=2, j=0); 7( i=2, j=1); 9( i=-3, j=3); ... Зверніть увагу , що i, jдля даних kне є чимось унікальним. Наприклад, 9також можуть бути отримані з i=3, j=0.

Інші еквівалентні характеристики цих чисел:

  • kможе бути виражено як i*i + j*j + i*jдля i, jневід'ємних цілих чисел. (Для кожної пари цілих чисел i, jє пара невід'ємних цілих чисел , яке дає той же k)

  • Існує набір kсуміжних шестикутників, що утворює тесселяцію на шестикутній сітці (див. Ілюстрації для k = 4та для k = 7). (Через цю властивість ці номери знаходять застосування в мобільних мережах стільникового зв'язку .)

  • Дивіться інші характеристики на сторінці OEIS послідовності.

Змагання

Враховуючи додатне ціле число , виведіть простий результат, якщо це число Лесся або помилковий результат.

Програма або функція повинна обробляти (скажімо, менше ніж за хвилину) введеннями до 1000або до обмежень типу даних.

Код гольфу. Найкоротші виграші.

Тестові справи

Наступні цифри повинні виводити надійний результат:

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

Наступні цифри повинні вивести помилковий результат:

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

Пов'язані (як зазначає @PeterTaylor)
Луїс Мендо

зверніть увагу на алгоритм грубої сили: якщо ви повторите до √k, ви зменшите складність алгоритму з O (n²) до O (n) за рахунок деяких байт c;
Прут

i, j non-negative integersабо 9 (i=-3, j=3)- який це?
Тит

1
@Titus О тепер я бачу. Для кожної пари цілих чисел i, j існує невід’ємна пара, яка дає однаковий k
Луїс Мендо

Відповіді:


17

Желе , 11 9 байт

ÆF‘%3,2ḄȦ

Спробуйте в Інтернеті! або перевірити всі тестові випадки .

Фон

В Елементарних результатах по двійковій квадратичній формі a² + ab + b² автор доводить наступну теорему про лесківські числа.

Теорема 16. Необхідною і достатньою умовою будь-якого невід'ємного цілого числа бути у формі a² + ab + b² є те, що в його основній факторизації всі прайми, крім 3 , які не мають форми (6k + 1), мають навіть експоненти.

Як зазначається на відповідній сторінці OEIS , оскільки всі цілі числа збігаються з 0 , 1 або 2 за модулем 3 , число 3 є єдиним простим числом, яке відповідає контенту 0 , і всі числа форми (6k + 1) відповідають 1 , теорему можна викласти як варіант.

Невід'ємне ціле число n - це лешківське число тоді і тільки тоді, коли всі прості множники n, що відповідають 2 модулю 3, мають навіть показники.

Як це працює

Æ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-регулярний вираз, який приймає унарні подання лескіанських чисел.

Входи 999 і 1000 проходять за секунду.

Спробуйте в Інтернеті! (Перший рядок включає тестовий набір, відокремлений підведенням по каналах, а наступні два дбають про перетворення в одинарне для зручності.)

Пояснення

Рішення засноване на класифікації, що вхід може бути записаний як i*i + j*(i + j)позитивний, так iі негативний j(оскільки нам не потрібно обробляти введення 0), і n*nце лише сума перших nнепарних цілих чисел. Гольф це було цікавою вправою в прямому посиланні.

"Посилання в прямому напрямку" - це коли ви ставите зворотний зв'язок всередині групи, на яку він посилається. Звичайно, це не спрацьовує при використанні групи вперше, оскільки ще немає нічого, що має бути зворотним референдумом, але якщо ви помістите це в цикл, то backreference отримує попередню ітерацію щоразу. Це, в свою чергу, дозволить вам створити більшу кількість знімків з кожною ітерацією. Це можна використовувати для створення дуже компактних візерунків для таких речей, як трикутні числа, квадрати та числа Фібоначчі.

Як приклад, використовуючи той факт, що квадрати - це лише суми перших nнепарних цілих чисел, ми можемо зіставити такий квадратний вхід:

(^.|..\1)+$

На першій ітерації ..\1не можна працювати, оскільки \1ще не має значення. Отже, ми почнемо з того ^., що захоплює одного символу в групу 1. На наступних ітераціях ^.більше не збігається через якір, але тепер ..\1діє. Він відповідає двом символам, ніж попередня ітерація, і оновлює зйомку. Таким чином ми співставляємо збільшення непарних чисел, отримуючи квадрат після кожної ітерації.

На жаль, ми не можемо використовувати цю техніку як є. Після відповідності i*iнам також потрібно отримати i, щоб ми могли помножити його на j. Простий (але довгий) спосіб зробити це - скористатися тим фактом, що відповідність i*iбере iітерації, щоб ми захопили iречі в групі 1. Зараз ми могли використовувати балансуючі групи для отримання цього i, але, як я сказав, це дорого.

Натомість я придумав інший спосіб записати цю "суму послідовних непарних цілих чисел", яка також поступається iв групі захоплення наприкінці. Звичайно, iнепарне число просто 2i-1. Це дає нам можливість збільшити пряму посилання лише на 1 на кожну ітерацію. Ось ця частина:

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

Це ()просто підштовхує порожнє захоплення до групи 1(ініціалізація iдо 0). Це майже еквівалентно ^.|простому рішенню вище, але використання |в цьому випадку було б трохи складніше.

Тоді у нас є основна петля (\1(?<1>.\1)). \1відповідає попередньому i, а (?<1>.\1)потім оновлює групу 1з i+1. З точки зору нового i , ми щойно відповідали 2i-1персонажам. Саме те, що нам потрібно.

Коли ми закінчимо, ми зіставили деякий квадрат i*iі група 1все ще містить iсимволи.

Друга частина ближче до простого квадратного зіставлення, яке я показав вище. Давайте поки ігноруємо зворотну посилання на 1:

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

Це в основному те саме, що (^.|..\4)*, за винятком того, що ми не можемо скористатись ^тим, що ми не на початку рядка. Замість цього ми використовуємо умовне, щоб відповідати додатковому .\1лише тоді, коли ми вже використовували групу 4. Але насправді це точно так само. Це нам дає j*j.

Єдине, чого не вистачає - це j*iтермін. Ми поєднуємо це з тим j*j, що використовуємо той факт, що j*jобчислення все ще приймають jітерації. Тож для кожної ітерації ми також просуваємо курсор за iдопомогою \1. Нам просто потрібно переконатися, що не записувати це в групу 4, тому що це зіпсується із збігом послідовних непарних чисел. Ось як ми доходимо до:

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

2
Чим більше разів я це читаю, тим менше розумію. Мені дуже хочеться знати, що багато виразів
Хав'єр Діаз

@JavierDiaz Існує серія публікацій, що пояснюють прямі посилання на переповнення стека, засновані на Java-регулярному виразі. Приклади там, мабуть, трохи простіші.
Мартін Ендер

13

CJam ( 16 15 байт)

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

Демонстрація в Інтернеті

Це блок ("анонімна функція"), який приймає дані про стек і залишає 0або1 на стеці. Він використовує характеристику, що число є Loeschian iff, якщо він не має основного коефіцієнта, рівного 2 mod 3 з непарною кратністю.

Завдяки Деннісу за однобайтну економію.


Нічого, приємна характеристика!
Луїс Мендо

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

Хаскелл, 42 байти

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

Приклад використання: f 501-> False.

Перевірте всі комбінації iвід 0до kі jз 0до i. orповертається, Trueякщо рівність k==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

@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

Це , здається, це НЕ поширюється тест негативний iабо j.
Тит


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 Це розумно, дякую.
Лина монахиня


3

MATL , 14 13 байт

t:0hU&+HM&*+m

Try it online! Or verify all test cases.

Outputs 1 or 0.

Explanation

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

Did you just out-golf Jelly?
Leaky Nun

@LeakyNun Let's see how long it lasts. Maybe I'll delay the code explanation a bit :-P
Luis Mendo

Nope. – – – – –
Leaky Nun

Your turn – – –
Leaky Nun

@LeakyNun Aw :-( Now I can add the explanation :-)
Luis Mendo

3

Python, 49 bytes

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

Uses the equivalent quadratic form given on OEIS of n == 3*i*i+j*j. Check whether n-3*i*i is a perfect square for any i by taking its square root and checking if it's an integer, i.e. equals 0 modulo 1. Note that Python computes square roots of perfect squares exactly, without floating point error. The +0j makes it a complex number to avoid an error on the square root of a negative.


3

C (gcc), 71 69 bytes

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 bytes: 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

This doesn´t seem to test negative i or j.
Titus

@Titus The question dictates non-negative i and j.
orlp

positive k, but not i and j. Take a closer look at the examples.
Titus

@Titus Quoting from the challenge: "k can be expressed as i*i + j*j + i*j for i, j non-negative integers." You take a closer look.
orlp

2

C#, 84 82 81 bytes

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

A naïve solution. 1 = true, 0 = false


2

VBA, 68 67 bytes

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

Naive search, starting to slow down slightly for n=1000. Excel recognizes zero return as falsy, all other returns as truthy.

Note that investigation of negative i and j is not needed, since given i>j>=0 :

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

(the same result as for i and j)

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

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

(if one is negative, it doesn't matter which one), and then

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

And since both (i-j) and j are non-negative, any generation of Loeschian numbers involving a negative number can be achieved using non-negative numbers.


Saved a byte, Next:Next -> Next b,a thanks to Taylor Scott.


This doesn´t seem to test negative i or j.
Titus

See the first point under "Other equivalent characterizations". Note that all test cases come up correctly. I'll add the mathematical justification to my answer (if I can).
Joffan

Sorry, my fault. Overread that that´s not necessary.
Titus

@Joffan you can condense Next:Next to Next b,a
Taylor Scott

@Joffan looking at your solution again maybe that is because of a missing :End Functionat the end of your solution
Taylor Scott

1

Javascript (using external library - Enumerable) (63 bytes)

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

Link to library: https://github.com/mvegh1/Enumerable Code explanation: Create a range of integers from 0 to k (call this the "i" range), and test if any "i" satisfies a certain predicate. That predicate creates a range from 0 to k (call this the "j" range), and tests if any "j" satisfies a certain predicate. That predicate is the loeschian formula

enter image description here


1

Perl 6,  52 51  50 bytes

->\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..$_)}

Explanation:

{
  # 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..$_ )
}

Test:

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

This doesn´t seem to test negative i or j.
Titus

@Titus the (0..$_ X 0..$_) produces an empty list if $_ is less than 0, so there is no need to check for negative i and j because they will never be negative. Since it is only supposed to produce True for a positive Loeschian number, I don't have to do anything special for the negative case.
Brad Gilbert b2gills

9 = (3*3)+(-3*-3)+(3*-3) is a positive Loeschian with i=3, j=-3; BUT I overread that every Loeschian number has non-negative i and j. So looking for negative numbers is not necessary. So actually we could delete those comments. Sorry for bugging; my fault.
Titus

@Titus modifying the code to {grep ->(\i,\j){$_==i*i+j*j+i*j},(-$_..$_ X -$_..$_)}(9) results in ((-3,0),(-3,3),(0,-3),(0,3),(3,-3),(3,0)). Honestly I probably just adapted it from other answers.
Brad Gilbert b2gills

1

PowerShell v2+, 63 56 55 bytes

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

Takes input $k, loops upwards twice (outer loop $i = 0 to $k, inner loop $j = 0 to $i), each iteration generates the result of i*i + j*j + i*j (shortened to i*(i+j) + j*j). Those results are encapsulated in parens, and passed as an array to -eq$k. This acts as a filter to select only elements that equal the input. Outputs a nonzero (the number back) for truthy, or nothing (empty) for falsey. Processes 1000 in about 15 seconds on my machine.

Test Cases

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 flag) = 55 bytes

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

Needs -n and -M5.010 flags to run :

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

Outputs some stuffs if the number is a Loeschian number, and nothing otherwise.

This implementation is quite boring, so here is another one, for 87 bytes, regex-based, just for the eyes :

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

Carefull with this one, as the backtracking will use a lot of memory, so don't try to test numbers too big! (especially numbers that aren't Loeschians)


1

Dyalog APL, 19 bytes

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

Checks if k ∊ (i + j)² – ij, for any 0 ≤ i, jk.

     is k
a member of
    ∘. all combinations of
        × i times j
        -⍨ subtracted from
        2*⍨ the square of
        + i plus j
     for all i and j in
    0, zero prepended to
     the integers 1 through k

1000 takes 3.3 seconds on my M540 and even less on TryAPL.


1

Matlab, 53 52 bytes

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

Simple search over all possibilities.
Outputs empty array as falsy and a non-empty vector as truthy value.

Considering all-zeros matrix as falsy and not-all-zeros matrix as truthy we can get rid of the find function resulting in 47 46 bytes solution:

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

One byte saved thanks to @flawr


1
(a+b).^2-a.*b==n is shorter.
flawr

1

C, 66 bytes

Call f() with the number to test. The function returns the number of solutions it found.

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

Try it on ideone.


1

Mathematica, 44 bytes

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

Unnamed function taking an integer as input and returning True or False. The command 0~Range~#~Tuples~2 creates all ordered pairs of integers both between 0 and the input #. The function (+##)^2-##& computes the square of the sum of its arguments minus the product of its arguments; when called on two arguments i and j, this is exactly i^2+j^2+ij as desired. So that function is called on all the tuples, and then MemberQ[...,#] checks whether the input is one of the resulting values.


1

ASP, 39 + 4 = 43 bytes

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

Output: the problem is satisfiable iff k is Loeschian.

Answer Set Programming is a logical language, similar to prolog. I use here the Potassco implementation, clingo.

Input is taken from parameters (-ck= is 4 bytes long). Call example:

clingo -ck=999

Output sample:

SATISFIABLE

Tried with 1000:

clingo -ck=1000

Output sample:

UNSATISFIABLE

You can try it in your browser ; unfortunately, this method doesn't handle call flags, so you need to add the line #const k=999 in order to make it work.


Ungolfed & explained code:

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 bytes

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

takes input from command line argument; exits with 1 for Loeschian number, with 0 else.
Run with -nr.

breakdown

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.