Конгруэнтные числа


21

Определения:

  • Треугольник считается прямоугольным, если один из внутренних углов точно равен 90 градусам.
  • Число считается рациональным, если оно может быть представлено соотношением целых чисел, т. Е. p/qГде оба pи qявляются целыми числами.
  • Число nявляется конгруэнтным числом, если существует прямоугольный треугольник области, nгде все три стороны рациональны.
  • Это OEIS A003273 .

Вызов

Это . Учитывая введенное число, xвыведите отличное и непротиворечивое значение, если xэто не конгруэнтное число, и отдельное отличное и непротиворечивое значение, если xэто не конгруэнтное число. Выходные значения не обязательно должны быть правдивыми / ложными на вашем языке.

Специальное правило

Для целей этой задачи вы можете предположить, что гипотеза Берча и Суиннертона-Дайера верна. В качестве альтернативы, если вы можете доказать гипотезу Берча и Суиннертона-Дайера, иди и получите свой приз в размере 1 000 000 долларов. ;-)

Примеры

(Использование Trueдля конгруэнтных чисел и др. False).

5 True
6 True
108 False

Правила и разъяснения

  • Вход и выход могут быть заданы любым удобным способом .
  • Вы можете распечатать результат в STDOUT или вернуть его как результат функции. Пожалуйста, укажите в своем представлении, какие значения могут принимать результаты.
  • Либо полная программа или функция приемлемы.
  • Стандартные лазейки запрещены.
  • Это поэтому применяются все обычные правила игры в гольф, и выигрывает самый короткий код (в байтах).

3
Является ли вход положительным целым числом?
Линн

Мой первоначальный подход состоял в том, чтобы умножить входное значение на произвольное квадратное число, пока оно не станет половиной произведения ветвей в пифагорейской тройке, но затем я понял, что на самом деле может быть немного сложно завершить для неконгруэнтного ввода.
Несвязанная строка

@ Сиань Хорошо, но проблемы должны быть самодостаточными.
Линн

@Lynn Да, входное значение будет положительным целым числом.
AdmBorkBork

Ответы:


8

R 179 173 142 141 137 135 134 байта

Используя те же аргументы, основанные на теореме Туннелла , возвращает 0if, если nоно не конгруэнтно, и 1иначе. (Мне потребовалось много времени, чтобы определить ограничение на условие, применимое только к целым числам без квадратов .)

function(n){b=(-n:n)^2
for(i in b^!!b)n=n/i^(!n%%i)
P=1+n%%2
o=outer
!sum(!o(y<-o(8/P*b,2*b,"+")/P-n,z<-16/P*b,"+"),-2*!o(y,4*z,"+"))}

Попробуйте онлайн

Улучшения, внесенные Арно и Джузеппе (окончательный код, в основном, Гизеппа!), С -3 благодаря Робину

Синтаксический анализ:

for(i in b[b>0])n=n/i^(!n%%i) #eliminates all square divisors of n
P=2^(n%%2)                    #n odd (2) or even (1)
o=outer                       #saves 3 bytes 
o(8/P*b,2*b,"+")/P-n          #all sums of (8/P)x^2+(2/P)*y^2-n
o(...,16/P*b,"+")             #all sums of above and (16/P)*z^2
o(...,4*z,"+"))               #all sums of above and (64/P)*z^2
!o(...,4*z,"+"))              #all sums of above equal to zero
!sum(!...,2*!...)             #are zeroes twice one another (Tunnell)

с теоремой Туннелла, утверждающей, что n конгруэнтно тогда и только тогда, когда число целочисленных решений для 2x² + y² + 8z² = n вдвое больше, чем число целочисленных решений для 2x² + y² + 32z² = n, если n нечетно, и число число целочисленных решений для 8x² + y² + 16z² = n в два раза больше, чем число целочисленных решений для 8x² + y² + 64z² = n, если n четное.


1
Добро пожаловать в PPCG! Цель состоит в том, чтобы сделать код максимально коротким. Возможно, вы могли бы взглянуть на эти советы по игре в гольф или эти специальные советы .
Джузеппе

1
Там много пробелов, а также я бы рекомендовал включить ссылку на Try It Online! чтобы помочь проверить ваш код :-)
Джузеппе

1
Не стесняйтесь обращаться в чат R golfer тоже, если хотите; Вы можете уведомить, используя @[username]... Я предполагаю, что Робин Райдер втянул вас в кодовый гольф?
Джузеппе

1
142 байта - анонимные функции в порядке, и я сделал еще несколько гольфов, которые я с удовольствием объясню
Джузеппе

1
Ницца! Есть ли причина, которую вы используете -n:n? Я не читал теорему Туннеля, но мне кажется, что она n:0будет работать так же хорошо для -1 байта ... Кроме того, профессиональный совет, если вы нажмете кнопку "ссылка" в верхней части TIO, вы получите хороший форматы для копирования и вставки в PPCG :-) РЕДАКТИРОВАТЬ: я вижу, есть некоторые случаи, когда n:0не работает.
Джузеппе

3

Ржавчина - 282 байта

fn is(mut n:i64)->bool{let(mut v,p)=(vec![0;4],n as usize%2);while let Some(l)=(2..n).filter(|i|n%(i*i)==0).nth(0){n/=l*l;}for x in -n..=n{for y in -n..=n{for z in -n..=n{for i in 0..2{if n-6*x*x*(n+1)%2==2*x*x+(2-n%2)*(y*y+(24*i as i64+8)*z*z){v[2*p+i]+=1};}}}}v[2*p]==2*v[2*p+1]}
  • Используйте теорему Джерролда Б. Туннелла , которую я на самом деле не понимаю, но, похоже, все равно работает.
  • разделите n на все его квадратные множители, чтобы сделать его «свободным от квадратов», поскольку в статьях ниже теорема Туннелла описана только для свободных квадратов.
    • Я считаю, что это может сработать, потому что каждое конгруэнтное число, умноженное на квадрат, создает большее конгруэнтное число, и наоборот. таким образом, проверяя меньшее число, мы можем проверить большее, которое в нашем случае равно n. (все удаленные квадраты можно умножить, чтобы получился один большой квадрат).
  • если n нечетно, проверить, если n = 2Икс2+Y2+32Z2 и / или 2Икс2+Y2+8Z2
    если n четное, проверить, если n = 8Икс2+2Y2+64Z2 и / или 8Икс2+2Y2+16Z2
    • в самом коде четыре уравнения были объединены в одно, внутри цикла, используя модуль по четному / нечетному
  • вести подсчет, какие уравнения соответствуют n
  • после цикла проверьте соотношение подсчетов (по Tunnell)

Смотрите также:

исправлено четное / нечетное, спасибо @Level River St


1
о, хорошо, в то время, когда я получил эту работу, я видел только ответ на С ++, который был неправильным ...
Дон

спасибо Level River St
Дон Яркий

3

C ++ (gcc) , 251 234 байта

Спасибо @arnauld за указание на глупую опечатку с моей стороны.

-17 байт благодаря @ceilingcat.

#import<cmath>
int a(int n){int s=sqrt(n),c,x=-s,y,z,i=1,X;for(;++i<n;)for(;n%(i*i)<1;n/=i*i);for(;x++<s;)for(y=-s;y++<s;)for(z=-s;z++<s;c+=n&1?2*(n==X+24*z*z)-(n==X):2*(n==4*x*x+2*X+48*z*z)-(n/2==2*x*x+X))X=2*x*x+y*y+8*z*z;return!c;}

Попробуйте онлайн!

Возвращает 1, если nсовпадает, 0 в противном случае.

Qs2Q также конгруэнтно (алгоритм, кажется, разбивает некоторые квадратные числа.


1
@Arnauld: ах, это была опечатка с моей стороны. фиксированный.
Нил А.

1

JavaScript (ES7), 165 байт

Как и ответ @ NeilA. , Это основано на теореме Туннелла и поэтому предполагает, что гипотеза Берча и Суиннертона-Дайера верна.

Возвращает логическое значение.

n=>(r=(g=i=>i<n?g(i+!(n%i**2?0:n/=i*i)):n**.5|0)(s=2),g=(C,k=r)=>k+r&&g(C,k-1,C(k*k)))(x=>g(y=>g(z=>s+=2*(n==(X=(n&1?2:8)*x+(o=2-n%2)*y)+o*32*z)-(n==X+o*8*z))))|s==2

Попробуйте онлайн!

Как?

NN'рзнак равноN's2

r = (                // we will eventually save isqrt(n) into r
  g = i =>           // g = recursive function taking an integer i
    i < n ?          //   if i is less than n:
      g(i + !(       //     do a recursive call with either i or i + 1
        n % i**2 ?   //     if n is not divisible by i²:
          0          //       yield 0 and therefore increment i
        :            //     else:
          n /= i * i //       divide n by i² and leave i unchanged
      ))             //     end of recursive call
    :                //   else:
      n ** .5 | 0    //     stop recursion and return isqrt(n)
  )(s = 2)           // initial call to g with i = s = 2

граммСК2-р<Кр

  g = (C, k = r) =>  // C = callback function, k = counter initialized to r
    k + r &&         //   if k is not equal to -r:
    g(               //     do a recursive call:
      C,             //       pass the callback function unchanged
      k - 1,         //       decrement k
      C(k * k)       //       invoke the callback function with k²
    )                //     end of recursive call

грамм(Икс,Y,Z)[-р+1,р]3s2ANзнак равноВNN2СNзнак равноDNN

ANзнак равно#{(Икс,Y,Z)[-р+1,р]3|Nзнак равно2Икс2+Y2+32Z2}ВNзнак равно#{(Икс,Y,Z)[-р+1,р]3|Nзнак равно2Икс2+Y2+8Z2}СNзнак равно#{(Икс,Y,Z)[-р+1,р]3|Nзнак равно8Икс2+2Y2+64Z2}DNзнак равно#{(Икс,Y,Z)[-р+1,р]3|Nзнак равно8Икс2+2Y2+16Z2}

g(x =>                            // for each x:      \    NB:
  g(y =>                          //   for each y:     >-- all these values are
    g(z =>                        //     for each z:  /    already squared by g
      s +=                        //       add to s:
        2 * (                     //         +2 if:
          n == (                  //           n is equal to either
            X =                   //           An if n is odd (o = 1)
            (n & 1 ? 2 : 8) * x + //           or Cn if n is even (o = 2)
            (o = 2 - n % 2) * y   //
          ) + o * 32 * z          //
        ) - (                     //         -1 if:
          n == X + o * 8 * z      //           n is equal to either
        )                         //           Bn if n is odd
    )                             //           or Dn if n is even
  )                               //
)                                 // if s in unchanged, then n is (assumed to be) congruent

1

Рубин , 126 байт

->n{[8,32].product(*[(-n..-t=1).map{|i|i*=i;n%i<1&&n/=i;i}*2+[0]]*3).map{|j|d=2-n%2
k,x,y,z=j
2*d*x+y+k*z==n/d&&t+=k-16}
t==1}

Попробуйте онлайн!

нашел место для инициализации t=1и расширил список квадратов в триплет вместо того, qчтобы делать дополнительные копии.

Рубин , 129 байт

->n{t=0
[8,32].product(q=(-n..-1).map{|i|i*=i;n%i<1&&n/=i;i}*2+[0],q,q).map{|j|d=2-n%2
k,x,y,z=j
2*d*x+y+k*z==n/d&&t+=k-16}
t==0}

Попробуйте онлайн!

Использует теорему Туннелла, как и другие ответы. Я использую одно уравнение следующим образом.

2*d*x^2 + y^2 + k*z^2 == n/d  where d=2 for even n and d=1 for odd n

Мы проверяем случаи k=8и k=32проверяем, есть ли вдвое больше решений, k=8чем чем k=32. Это делается путем добавления k-16к tкаждому разу, когда мы находим решение. Это +16 в случае k=32или -8 в случае k=8. В целом число является конгруэнтным, если tоно совпадает с его начальным значением в конце функции.

Необходимо найти все решения тестового уравнения. Я вижу множество ответов между +/- sqrt n. Совершенно нормально тестировать и за этими пределами, если это делает код короче, но решения не будут найдены, потому что левая часть уравнения будет превышать n. В начале я упустил то, что негатив и позитив x,y,zрассматриваются отдельно. Таким образом, -3,0,3получается три квадрата, 9,0,9и все решения должны учитываться отдельно (0 должно учитываться один раз и 9должно учитываться дважды).

Код без правил

->n{t=0                              #counter for solutions

  q=(-n..-1).map{|i|i*=i;n%i<1&&n/=i #make n square free by dividing by -n^2 to -1^2 as necessary 
  i}*2+[0]                           #return an array of squares, duplicate for 1^2 to n^2, and add the case 0 

  [8,32].product(q,q,q).map{|j|      #make a cartesian product of all possible values for k,x,y,z and iterate
    d=2-n%2                          #d=1 for odd n, 2 for even n
    k,x,y,z=j                        #unpack j. k=8,32. x,y,z are the squared values from q.
    2*d*x+y+k*z==n/d&&t+=k-16}       #test if the current values of k,x,y,z are a valid solution. If so, adjust t by k-16 as explained above.
t==0}                                #return true if t is the same as its initial value. otherwise false.

о положительных и отрицательных решениях, то же самое здесь, я потратил много времени, упустив этот момент!
Сиань
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.