Трикутні залежності


25

Трикутне число є числом , яке є сумою nнатуральних чисел від 1 до n. Наприклад , 1 + 2 + 3 + 4 = 10так 10це трикутне число.

Давши позитивне ціле число ( 0 < n <= 10000) як вхідне (можна сприймати як ціле число або як рядок), поверніть найменше можливе трикутне число, яке можна додати до вводу для створення іншого трикутного числа.

Наприклад, дане введення 26, додавання 10результатів у 36, яке також є трикутним числом. Немає трикутних чисел, менших, ніж 10це можна додати для 26створення іншого трикутного числа, тому 10правильний результат у цьому випадку.

0 є трикутним числом, тому якщо вхід сам по собі є трикутним числом, вихід повинен бути 0

Тестові шафи

Справи наводяться у форматі input -> output (resulting triangular number)

0     -> 0   (0)
4     -> 6   (10)
5     -> 1   (6)
7     -> 3   (10)
8     -> 28  (36)
10    -> 0   (10)
24    -> 21  (45)
25    -> 3   (28)
26    -> 10  (36)
34    -> 21  (55)
10000 -> 153 (10153)

Оцінка балів

Це тому виграє найменше байтів на кожній мові !


Чи не так 26 -> 2?
Okx

@Okx Я зробив ту саму помилку, вам потрібно знайти трикутне число, яке слід додати до поточного, щоб зробити ще одне трикутне число.
Мартін Ендер

2
Пов'язані. (прикордонний дублікат)
Мартін Ендер

Відповіді:


21

Java 8, 58 57 байт

n->{int i=0,m=0;while(n!=0)n+=n<0?++i:--m;return-~i*i/2;}

Інтернет-тестовий набір

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


6
Тепер це Ява, гольф! :)
Олів'є Грегоар

4
@Computronium, порядок операцій гарантується специфікацією мови Java . Java навмисно уникає деяких слабких місць С.
Пітер Тейлор


2
return-~i*i/2;зберігає байт.
Денніс

1
@Okx Java - це прохідне значення для примітивних типів і пропускне посилання для об'єктів (включаючи масиви). Якщо ви хочете насправді виводити в ту саму змінну, вам слід опинитися в контексті проходження посилання (прямо вказано у вашому посиланні). Єдиний спосіб, яким я бачу переходити через посилання, який міг би працювати, - це передавати аргумент int[]замість intяк аргумент. Але це означає, що згодом мати справу з масивами. Це могло б працювати: x->{int i=0,m=0,n=x[0];while(n!=0)n+=n<0?++i:--m;x[0]=-~i*i/2;}але це 63 байти.
Олів'є Грегоар

7

MATL , 13 12 байт

1 байт видалено за допомогою ідеї (встановити перетин) з відповіді Еміньї 05AB1E

Q:qYstG-X&X<

Спробуйте в Інтернеті!

Пояснення

Нехай t(n) = 1 + 2 + ··· + nпозначають n-ве трикутне число.

Код використовує той факт, що, задано n, рішення є верхньою межею t(n-1). Щоб побачити це, зауважте, що t(n-1) + nдорівнює t(n)і тому це трикутне число.

Розглянемо вклад 8як приклад.

Q:q   % Input n implicitly. Push [0 1 2 ... n]
      % STACK: [0 1 2 3 4 5 6 7 8]
Ys    % Cumulative sum
      % STACK: [0 1 3 6 10 15 21 28 36]
t     % Duplicate
      % STACK: [0 1 3 6 10 15 21 28 36], [0 1 3 6 10 15 21 28 36]
G-    % Subtract input, element-wise
      % STACK: [0 1 3 6 10 15 21 28 36], [-8 -7 -5 -2  2  7 13 20 28]
X&    % Set intersection
      % STACK: 28
X<    % Minimum of array (in case there are several solutions). Implicit display
      % STACK: 28

Чи можете ви усунути провідні Qаргументи щодо обмеженості?
Джузеппе

@Giuseppe Ні, це не вдається для введення 8. Коли вихід дорівнює зв'язаному t(n-1), код отримує його як t(n)-n. Так t(n)треба. Дякую за ідею все одно!
Луїс Мендо

7

Java (OpenJDK 8) , 83 байти

n->{int m=0,a=n,b;for(;a-->0;)for(b=0;b<=n;)m=2*n+b*~b++==a*~a?a*a+a:m;return m/2;}

Спробуйте в Інтернеті!

Кредити


1
Гарна відповідь (як завжди ..). Я не помітив, що вже було відповіді на Java, коли я розмістив шахту . Моя спочатку була коротшою, але вже не здається. :)
Кевін Круїссен

Спасибі! Так, моя перша відповідь була справді зайвою. Я це виправив і зробив більш матовим, хоча й більш жадібним до процесорів. Я перевірю твою через секунду!
Олів'є Грегоар

Я досі не розумію, що тут відбувається. Чому це працює? Ви міняєте m щоразу, тож який сенс?
В. Куртуа

2
@ V.Courtois Питання задає найменшого m. Тож я йду aзнизу вниз 0. «Але ви привласнюєте може бути в 100 разів таке ж значення , a*a+aщоб mв b-loop», так, мені не потрібно робити це в 100 разів, але я набираю байти, не порушуючи b-loop раніше.
Олів'є Грегоар

Я бачу @ OlivierGrégoire. Тож це спеціально антиефективно: D
V. Courtois


4

Нейм , 12 9 байт

tS𝕊Λt𝕚)0𝕔

Для обчислення це забирає занадто багато часу (але працює з урахуванням нескінченного часу та пам’яті), тому в посиланні я генерую лише перші 143 трикутні числа - використовуючи £𝕖, що достатньо, щоб обробити вхід 10000, але недостатньо, щоб вичерпати час.

Попередження: це може не працювати в майбутніх версіях. Якщо так, замініть £ на 143

Пояснення:

t                 Infinite list of triangular numbers
 [ 𝕖]             Select the first  v  numbers
 [£ ]                              143
     S𝕊           Subtract the input from each element
       Λ  )       Only keep elements that are
        t𝕚          triangular
           0𝕔     Get the value closest to 0 - prioritising the higher number if tie

Спробуй це!


Як вистачає перших 143 трикутникових чисел для будь-якого введення між 0 і 10000? З введенням 9998очікуваний результат дорівнює 3118753143-му номеру трикутника (що становить `10296).
Олів'є Грегоар

@ OlivierGrégoire тому щоThis takes too long to compute (but works given infinite time and memory)
Стівен

Дякую @StepHen, але це не те, що я сказав. Що я мав на увазі, це те, що речення "перших 143 трикутних чисел [достатньо] для обробки введення 10000" є помилковим. Я не займався математикою, але я вважаю, що вам потрібно буде близько 10000 (дайте чи візьміть) трикутникові числа, щоб обробляти справи до 10000.
Олів'є Грегоар

@ OlivierGrégoire Я заявив, що достатньо обробляти вхід 10000, але не будь-яке число менше. Не соромтеся перейти £на більшу кількість, наприклад, 200.
Окс

@ Okx Добре, я цього не зрозумів, коли я вперше прочитав, дякую, що знайшли час для пояснення :)
Олів'є Грегоар

4

PHP , 45 байт

for(;!$$t;$t+=++$i)${$argn+$t}=~+$t;echo~$$t;

Спробуйте в Інтернеті!

Це коротший варіант for(;!$r[$t];$t+=++$i)$r[$argn+$t]=~+$t;echo~$r[$t];

Розширено

for(;!$$t;  # stop if a triangular number exists where input plus triangular number is a triangular number
$t+=++$i) # make the next triangular number
  ${$argn+$t}=~+$t; # build variable $4,$5,$7,$10,... for input 4 
echo~$$t; # Output result 

PHP , 53 байти

for(;$d=$t<=>$n+$argn;)~$d?$n+=++$k:$t+=++$i;echo+$n;

Спробуйте в Інтернеті!

Використовуйте новий оператор космічного корабля в PHP 7

Розширено

for(;$d=$t<=>$n+$argn;) # stop if triangular number is equal to input plus triangular number 
  ~$d
    ?$n+=++$k  # raise additional triangular number
    :$t+=++$i; # raise triangular number sum
echo+$n; # Output and cast variable to integer in case of zero

PHP , 55 байт

for(;fmod(sqrt(8*($t+$argn)+1),2)!=1;)$t+=++$i;echo+$t;

Спробуйте в Інтернеті!


4

Java 8, 110 102 100 93 92 байт

n->{int r=0;for(;t(r)<-t(n+r);r++);return r;}int t(int n){for(int j=0;n>0;n-=++j);return n;}

-2 байти завдяки @PeterTaylor .
-7 байт завдяки @JollyJoker .
-1 байт завдяки @ceilingcat .

Пояснення:

Спробуйте в Інтернеті.

n->{                  // Method with integer as parameter and return-type
  int r=0;            //  Result-integer (starting at 0)
  for(;t(r)<-t(n+r);  //  Loop as long as neither `r` nor `n+r` is a triangular number
    r++);             //   And increase `r` by 1 after every iteration
  return r;}          //  Return the result of the loop

int t(int n){         // Separate method with integer as parameter and return-type
                      // This method will return 0 if the input is a triangular number
  for(int i=0;n>0;)   //  Loop as long as the input `n` is larger than 0
    n-=++j;           //   Decrease `n` by `j` every iteration, after we've raised `j` by 1
  return n;}          //  Return `n`, which is now either 0 or below 0

1
Найпростіший для читання рішень Java :)
JollyJoker

@JollyJoker Можливо, тому це найдовше. ;) Або це через моє додаткове пояснення?
Кевін Кройсейсен

Ні, я думав про код. Я, мабуть, витратив 15 хвилин, щоб зрозуміти, як працює рішення Пітера Тейлора. Ваше зрозуміло навіть без коментарів.
JollyJoker


3

Python 2 , 59 байт

lambda n:min((r-2*n/r)**2/8for r in range(1,2*n,2)if n%r<1)

Спробуйте в Інтернеті!

Для цього використовується наступна характеристика трикутних чисел, tніж можна додати nдля отримання трикутного числа:

8*t+1 = (r-2*s)^2для пар дільниць (r,s)з r*s==nі rнепарними.

Код бере мінімум усіх таких трикутних чисел.


3

Желе , 8 байт

0r+\ðf_Ḣ

Спробуйте в Інтернеті!

Як це працює

0r+\ðf_Ḣ  Main link. Argument: n

0r        Build [0, ..., n].
  +\      Take the cumulative sum, generating A := [T(0), ..., T(n)].
    ð     Begin a dyadic chain with left argument A and right argument n.
      _   Compute A - n, i.e., subtract n from each number in A.
     f    Filter; keep only numbers of A that appear in A - n.
       Ḣ  Head; take the first result.

3

Japt , 24 23 16 15 байт

ò å+
m!nNg)æ!øU

Перевірте це

1 байт збережено завдяки ETH


Пояснення

    :Implicit input of integer U.
ò   :Create an array of integers from 0 to U, inclusive.
å+  :Cumulatively reduce by summing. Result is implicitly assigned to variable V.
m   :Map over U.
!n  :From the current element subtract...
Ng  :  The first element in the array of inputs (the original value of U).
æ   :Get the first element that returns true when...
!øU :  Checking if U contains it.
    :Implicit output of resulting integer.

Я думаю, ви можете зберегти байт за допомогою æ!øV. Крім цього, виглядає чудово :-)
ETHproductions



2

Математика, 62 байти

(s=Min@Abs[m/.Solve[2#==(n-m)(n+m+1),{n,m},Integers]])(s+1)/2&

Я не знаю Mathematica, але було Solve[2*#==m(m+1)-n(n+1)б коротше (якщо воно працює)?
Kritixi Lithos

так, я щойно опублікував свою відповідь і намагаюся зараз
переграти

2

Пітон 2 , 78 71 70 байт

Сім байтів збережено, ніж в порівнянні з ов і теспіноза

Ще один байт збережений в зв'язку з зауваженням Neil , x+9є suffisant і перевіряється для всіх натуральних чисел 0 <= n <= 10000. Крім того , було перевірено для x+1а x+9, вона також працює.

x=input()
I={n*-~n/2for n in range(x+1)}
print min(I&{i-x for i in I})

Спробуйте в Інтернеті!


2
Ви можете використовувати n*-~n/2замістьn*(n+1)/2
ovs

2
Чи спрацював би діапазон (x + 9)?
Ніл

2
Ви можете використовувати {n*(n+1)/2for n in range(999)}замість явного, setа також використовувати {}замість setтретього рядка
TheEspinosa

2

JavaScript (ES6), 43 42 байти

f=(n,a=s=0)=>n?f(n+=n>0?--s:++a,a):a*++a/2
<input type=number min=0 value=0 oninput=o.textContent=f(+this.value)><pre id=o>0

Редагувати: Збережено 1 байт завдяки @PeterTaylor.


Встановлення глобальної змінної - прикрий зловживання параметром за замовчуванням. +1. Але FWIW ви можете зберегти подальший байт, замінивши -++sна --s, як я це робив у своїй незалежно виведеній, але досить схожій версії Java. (Додаток: вам також потрібно змінити тест на n>0).
Пітер Тейлор

@PeterTaylor Гм, тож n>sчек був червоною оселедцем весь час!
Ніл

Працює не для 8192
Йорг Гюльсерманн

@ JörgHülsermann Якщо ви маєте на увазі фрагмент, розмір стека вашого браузера може бути недостатньо великим, або вам може знадобитися браузер з експериментальною оптимізацією хвостових викликів. Крім того, якщо ви використовуєте NodeJS для тестування, використовуйте node --stack_size=для збільшення розміру стека.
Ніл

2

Python 3 , 60 44 байти

f=lambda n,k=1:(8*n+1)**.5%1and f(n+k,k+1)+k

Дякуємо @xnor за пропозицію, яка зберегла 16 байт!

Спробуйте в Інтернеті!

Фон

Нехай n - невід'ємне ціле число. Якщо n - k- е трикутне число, маємо

стан

що означає, що буде природне рішення тоді і лише тоді, коли 1 + 8n - непарний, ідеальний квадрат. Зрозуміло, перевіряючи парність 1 + 8n не потрібно.

Як це працює

Рекурсивна функція n приймає єдине невід'ємне ціле число як аргумент. Коли викликається одним аргументом, k за замовчуванням до 1 .

По-перше, (8*n+1)**.5%1тести, якщо n - трикутне число: якщо (і тільки якщо воно є), (8*n+1)**.5вийде ціле число, тож залишок з ділення на 1 дасть 0 .

Якщо модуль дорівнює 0 , andумова вийде з ладу, через що f повернеться до 0 . Якщо це відбувається в початковому виклику до f , зауважте, що це правильний вихід з n вже трикутний.

Якщо модуль позитивний, andумова виконується і f(n+k,k+1)+kвиконується. Це викликає f знову, збільшуючи n на k і k на 1 , потім додає k до результату.

Коли f (n 0 , k 0 ) нарешті повертає 0 , ми повертаємося поза рекурсією. Першим аргументом у першому дзвінку було n , другому n + 1 , третьому n + 1 + 2 , поки нарешті n 0 = n + 1 +… k 0 -1 . Зауважимо, що n 0 - n - трикутне число.

Так само всі ці цілі числа будуть додані до найпотаємнішого зворотного значення ( 0 ), тому результат виклику вхідного сигналу f (n) дорівнює n 0 - n , як бажано.


Якщо ви збільшуєтесь і nв повторенні, ви можете писати, nа не писати (n+k).
xnor


Нічого собі, це набагато приємніше, ніж те, що я намагався.
xnor

2

C # (.NET Core) , 291 281 байт

class p{static int Main(string[]I){string d="0",s=I[0];int c=1,j,k;for(;;){j=k=0;string[]D=d.Split(' '),S=s.Split(' ');for(;j<D.Length;j++)for(;k<S.Length;k++)if(D[j]==S[k])return int.Parse(D[k]);j=int.Parse(D[0])+c++;d=d.Insert(0,$"{j} ");s=s.Insert(0,$"{j+int.Parse(I[0])} ");}}}

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

Збережено 10 байт завдяки Кевіну Крейсейну


1
Привіт, Ласкаво просимо до PPCG! Повна програма вам не потрібна, якщо в виклику не вказано інше. За замовчуванням - програма / функція, тому лямбда також дозволена в C #. Але якщо ви хочете скористатися програмою, ви можете class p{static int Main(string[]I){string d="0",s=I[0];int c=1,j,k;for(;;){j=k=0;string[]D=d.Split(' '),S=s.Split(' ');for(;j<D.Length;j++)for(;k<S.Length;k++)if(D[j]==S[k])return int.Parse(D[k]);j=int.Parse(D[0])+c++;d=d.Insert(0,$"{j} ");s=s.Insert(0,$"{j+int.Parse(I[0])} ");}}}
пограти

@KevinCruijssen Дякую за пораду! використання for(;;)для створення нескінченного циклу - це приємна помилка, і я обов’язково подумаю більш ретельно про те, чи використання var насправді більш ефективне, ніж використання явного типу, але комбінування оголошень, і, мабуть, буду більш ретельним у видаленні непотрібних дужок. Що стосується програми проти функції, я почав з лямбда, але не зміг її запустити в TIO. Я знаю, що посилання на TIO насправді не потрібне, але це те, що я люблю бачити у відповідях інших, тому мені хотілося хоча б чогось подібного.
Каміль Дракарі

Я також не дуже хороший в C # лямбдах tbh, я зазвичай кодовагольф на Java. Але я думаю, що це має бути правильним . ( 252 байти ). Крім того, якщо ви цього ще не бачили: Поради щодо гольфу на коді в C # та Поради щодо гольфу на <всіх мовах> можуть бути цікавими для прочитання. Знову вітаю, і +1 від мене. Приємна перша відповідь. Насолодитися перебуванням. :)
Кевін Кройсейсен

2

JavaScript (ES7), 46 44 байти

f=(n,x=r=0)=>(8*(n+x)+1)**.5%1?f(n,x+=++r):x

Спробуй це

o.innerText=(
f=(n,x=r=0)=>(8*(n+x)+1)**.5%1?f(n,x+=++r):x
)(i.value=8);oninput=_=>o.innerText=f(+i.value)
<input id=i type=number><pre id=o>


1
Було б r=x=0працювати?
Kritixi Lithos

На жаль, ні @KritixiLithos.
Кудлатий


1

Діалог APL, 19 байт

6 байт збережено завдяки @KritixiLithos

{⊃o/⍨o∊⍨⍵+o←0,+\⍳⍵}

Спробуйте в Інтернеті!

Як?

o←0,+\⍳⍵ - призначити o перші трикутні числа

o/⍨ - фільтр o по

o∊⍨⍵+o - трикутні числа, які підсумовуються с утворюють трикутники

- і візьми перше


+\⍳⍵має працювати замість того, що ви використовуєте для генерації трикутних чисел.
Kritixi Lithos

Я думаю, що замість цього працює⌊/
Kritixi Lithos



1

Додайте ++ , 68 байт

L,RBFEREsECAAx$pBcB_B]VARBFEREsB]GEi$pGBcB*A8*1+.5^1%!!@A!@*b]EZBF#@

Спробуйте в Інтернеті! або переглянути набір тестів !

Навіть Java мене б’є. Мені дійсно потрібно додати кілька заданих команд до Add ++

Як це працює

L,    - Create a lambda function
      - Example argument:  8
  R   - Range;     STACK = [[1 2 3 4 5 6 7 8]]
  BF  - Flatten;   STACK = [1 2 3 4 5 6 7 8]
  ER  - Range;     STACK = [[1] [1 2] ... [1 2 3 4 5 6 7 8]
  Es  - Sum;       STACK = [1 3 6 10 15 21 28 36]
  EC  - Collect;   STACK = [[1 3 6 10 15 21 28 36]]
  A   - Argument;  STACK = [[1 3 6 10 15 21 28 36] 8]
  A   - Argument;  STACK = [[1 3 6 10 15 21 28 36] 8 8]
  x   - Repeat;    STACK = [[1 3 6 10 15 21 28 36] 8 [8 8 8 8 8 8 8 8]]
  $p  - Remove;    STACK = [[1 3 6 10 15 21 28 36] [8 8 8 8 8 8 8 8]]
  Bc  - Zip;       STACK = [[1 8] [3 8] [6 8] [10 8] [15 8] [21 8] [28 8] [36 8]]
  B_  - Deltas;    STACK = [-7 -5 -2 2 7 13 20 28]
  B]  - Wrap;      STACK = [[-7 -5 -2 2 7 13 20 28]]
  V   - Save;      STACK = []
  A   - Argument;  STACK = [8]
  R   - Range;     STACK = [[1 2 3 4 5 6 7 8]]
  BF  - Flatten;   STACK = [1 2 3 4 5 6 7 8]
  ER  - Range;     STACK = [[1] [1 2] ... [1 2 3 4 5 6 7 8]]
  Es  - Sum;       STACK = [1 3 6 10 15 21 28 36]
  B]  - Wrap;      STACK = [[1 3 6 10 15 21 28 36]]
  G   - Retrieve;  STACK = [[1 3 6 10 15 21 28 36] [-7 -5 -2 2 7 13 20 28]]
  Ei  - Contains;  STACK = [[1 3 6 10 15 21 28 36] [0 0 0 0 0 0 0 1]]
  $p  - Remove;    STACK = [[0 0 0 0 0 0 0 1]]
  G   - Retrieve;  STACK = [[0 0 0 0 0 0 0 1] [-7 -5 -2 2 7 13 20 28]]
  Bc  - Zip;       STACK = [[0 -7] [0 -5] [0 -2] [0 2] [0 7] [0 13] [0 20] [1 28]]
  B*  - Products;  STACK = [0 0 0 0 0 0 0 28]
  A   - Argument;  STACK = [0 0 0 0 0 0 0 28 8]
  8*  - Times 8;   STACK = [0 0 0 0 0 0 0 28 64]
  1+  - Increment; STACK = [0 0 0 0 0 0 0 28 65]
  .5^ - Root;      STACK = [0 0 0 0 0 0 0 28 8.1]
  1%  - Frac part; STACK = [0 0 0 0 0 0 0 28 0.1]
  !!  - To bool;   STACK = [0 0 0 0 0 0 0 28 1]
  @   - Reverse;   STACK = [1 28 0 0 0 0 0 0 0]
  A   - Argument;  STACK = [1 28 0 0 0 0 0 0 0 8] 
  !   - Not;       STACK = [1 28 0 0 0 0 0 0 0 0]
  @   - Reverse;   STACK = [0 0 0 0 0 0 0 0 28 1]
  *   - Multiply;  STACK = [0 0 0 0 0 0 0 0 28]
  b]  - Wrap;      STACK = [0 0 0 0 0 0 0 0 [28]]
  EZ  - Unzero;    STACK = [[28]]
  BF  - Flatten;   STACK = [28]
  #   - Sort;      STACK = [28]
  @   - Reverse;   STACK = [28]

1

R , 46 44 43 41 байт

function(x,y=cumsum(0:x))y[(x+y)%in%y][1]

Спробуйте в Інтернеті!

Анонімна функція з одним обов’язковим аргументом x; обчислює перші x+1трикутні числа як необов'язковий аргумент, щоб виграти кілька фігурних дужок. Я використовував, chooseперш ніж побачив відповідь Октава Луїса Мендо .

Я поголив кілька байт відповіді Луїса Мендо, але забув використати ту саму ідею у своїй відповіді.





0

Clojure, 74 байти

#(nth(for[t[(reductions +(range))]i t :when((set(take 1e5 t))(+ i %))]i)0)
#(nth(for[R[reductions]i(R + %(range)):when((set(R - i(range 1e5)))0)]i)0)

Виберіть улюбленого :) Петлі можуть бути коротшими ...


0

Пітон 2 , 82 байти

f=lambda n,R=[1]:n-sum(R)and f(n,[R+[R[-1]+1],R[1:]][sum(R)>n])or sum(range(R[0]))

Спробуйте в Інтернеті

Це було створено, змінивши цю відповідь із пов'язаного питання.


працює не для 8192
Йорг Гюльсерманн

Це також не справляється з цим питанням через глибину рекурсії. Я не впевнений, що таке консенсус щодо цього.
mbomb007

Деякі інші відповіді мають таку ж проблему. Я даю лише інформацію
Jörg Hülsermann
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.