Треугольные зависимости


25

Треугольное число является числом , которое является суммой nнатуральных чисел от 1 до n. Например , 1 + 2 + 3 + 4 = 10так 10это треугольное число.

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

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

0 является треугольным числом, поэтому, если сам вход является треугольным числом, вывод должен быть 0

Testcases

Случаи приведены в формате 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
Теперь это Java, игра в гольф! :)
Оливье Грегуар

4
@Computronium, порядок операций гарантирован Спецификацией языка Java . Ява намеренно избегает некоторых слабостей С.
Питер Тейлор


2
return-~i*i/2;сохраняет байт.
Деннис

1
@Okx Java - передача по значению для примитивных типов и передача по ссылке для объектов (включая массивы). Если вы хотите на самом деле выводить в одной и той же переменной, вы должны находиться в контексте передачи по ссылке (явно указано в вашей ссылке). Единственный способ, с помощью которого я мог бы работать путем передачи по ссылке, - это передавать аргумент int[]вместо intas. Но это значит иметь дело с массивами позже. Это может сработать 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через 3-е 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 треугольных числа - использование £𝕖, которое достаточно для обработки ввода в 10 000, но недостаточно для тайм-аута.

Предупреждение: это может не работать в будущих версиях. Если это так, замените £ на 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ожидаемый результат будет 3118753намного выше 143-го номера треугольника (то есть `10296).
Оливье Грегуар

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

Спасибо @StepHen, но это не то, что я сказал. Я имел в виду, что предложение «первых 143 треугольных чисел [достаточно] для обработки ввода 10 000» неверно. Я не делал математику, но я считаю, что вам нужно около 10000 (дать или взять) треугольных чисел для обработки случаев до 10000.
Оливье Грегуар

@ OlivierGrégoire Я сказал, что этого достаточно для ввода 10000, но не меньше, чем это. Не стесняйтесь перейти £на большее число, например, 200.
Okx

@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

Брахилог , 17 15 байт

⟦{a₀+}ᶠ⊇Ċ-ṅ?∧Ċh

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

объяснение

⟦                  [0, …, Input]
 {   }ᶠ            Find all…
  a₀+                …Sums of prefixes (i.e. triangular numbers)
       ⊇Ċ          Take an ordered subset of two elements
         -ṅ?       Subtracting those elements results in -(Input)
            ∧Ċh    Output is the first element of that subset

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

Mathematica, 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)короче (если это работает)?
Критиси Литос

да, я только что опубликовал свой ответ и пытаюсь
J42161217

2

Python 2 , 78 71 70 байт

Семь байт сохранены, спасибо в овсе и theespinosa

Еще один байт, сохраненный благодаря примечанию neil , x+9является достаточным и проверяется на все натуральные числа 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
овса

2
Будет ли работать диапазон (х + 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 # lambdas 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работать?
Критиси Литос

К сожалению, нет, @KritixiLithos.
Лохматый


1

Дьялог АПЛ, 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#@

Попробуйте онлайн! или посмотрите набор тестов !

Даже Ява бьет меня. Мне действительно нужно добавить некоторые команды набора в 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

Python 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

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